Create a content page resolution filter class
A content page resolution filter is used to customize the behavior of the content page resolution filter chain. This can enable you to tailor the response to a web content request in several ways, including overriding the content item displayed or the portal page used to display a content item in the web content viewer.
The content page resolution filter chain is composed of filters that are based on the Intercepting Filter design pattern, which provides a mechanism for intercepting a request and manipulating the request and its response. When used with requests for web content, the content page resolution filter chain has default filters that process any URL parameters contained in the web content request and then determine which portal page has a matching web content association. The default filters occur at the end of the filter chain.
We can customize the content page resolution filter chain by creating custom filters that are registered with the portal through the Eclipse plug-in framework with the extension ID com.ibm.workplace.wcm.api.ContentPageResolutionFilter. The sequence of filters in the filter chain is specified by a weight value associated with each filter. To insert custom filters into the filter chain before the default filters, we can use the weight attribute in the plugin.xml file. If the weight attribute is not present, filter sequence is determined by the getFilterChainWeight method of each custom filter.
Custom filters can perform various actions:
- Modify parameters before calling the default filters.
- Modify the result of the default filters.
- Handle exceptions generated by the default filters.
- Determine whether the default filters should be invoked at all.
- Modify the content path used as input for the default filters.
- Explicitly set a target page for displaying content.
- Determine which web content page should be used, if the default filters find more than one matching web content page for the request.
- Modify the presentation template selection.
- Set HTTP response status codes.
- Send redirects to external web resources.
To use a content page resolution filter, create a content page resolution filter class and then register the filter by deploying it on the server.
- Create a java class that implements the interface com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionFilter. This class must implement the following methods:
- public int getFilterChainWeight() {}
- This method returns the weight applied to the content page resolution filter elements in the filter chain. The lower the weight, the earlier the filter is inserted into the chain. If the weight parameter is defined in the plugin.xml file, that value overrides the value returned by this method.
- public void resolve(ContentPageResolutionRequest request, ContentPageResolutionResponse response, ContentPageResolutionFilterChain chain) {}
- This method is invoked during ContentPageResolution processing. The response parameter enables you to modify the content item displayed, the portal page where the content is displayed, and the presentation template used to render the content item. The request extends the resolver interface with an additional method that gets the content item that has been addressed. The filter chain contains the subsequent filters that can be invoked if needed.
See the Javadoc documentation for further information.
- A plugin.xml file is needed whether the deployment is done using a WAR or EAR, or using a loose jar. If deploying with an application in a WAR or EAR, include the plugin.xml file in the application's "WEB-INF" folder. When using a jar, include the plugin.xml in the root of the jar.
<?xml version="1.0" encoding="UTF-8"?> <plugin id="com.example" name="Sample Content Page Resolution Filter" version="1.0.0" provider-name="IBM"> <extension point="com.ibm.workplace.wcm.api.ContentPageResolutionFilter" id="SampleContentPageResolutionFilter"> <provider class="com.example.SampleContentPageResolutionFilter" weight="1"/> </extension> </plugin>When creating plug-ins, note the following:
- Each plug-in is represented by a single <extension> tag.
- The value of the extension point attribute must be com.ibm.workplace.wcm.api.ContentPageResolutionFilter.
- Provide an ID value of the choice.
- Specify the filter class for the plug-in.
- The weight parameter overrides the value of the getFilterChainWeight method
Naming conventions:
If you create a new plug-in application with the same names and IDs as an existing plug-in, the new plug-in may override the first. When creating plug-in applications ensure that the following are unique across the system:
- The plug-in ID, plug-in name and extension ID of the plugin.xml file.
- The fully qualified class name and path of all classes within the application.
- The file path of any files within the application.
Examples
The LocaleDependantSelectionFilter example performs the default page resolution and selects a target page from the candidate pages, according to the user's locale.
package com.ibm.workplace.wcm.extension.resolution; import java.util.List; import java.util.Locale; import javax.naming.InitialContext; import javax.naming.NamingException; import com.ibm.portal.ObjectID; import com.ibm.portal.model.CorLocalizedContextHome; import com.ibm.portal.model.LocalizedContext; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionFilter; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionFilterChain; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionRequest; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionResponse; import com.ibm.workplace.wcm.api.extensions.resolution.exceptions.ContentPageResolutionException; public class LocaleDependantSelectionFilter implements ContentPageResolutionFilter { CorLocalizedContextHome localizedContextHome; public LocaleDependantSelectionFilter() { try { InitialContext ctx = new InitialContext(); localizedContextHome = (CorLocalizedContextHome) ctx.lookup(CorLocalizedContextHome.JNDI_NAME); } catch(NamingException e) { e.printStackTrace(); } } public int getFilterChainWeight() { return 2; } public void resolve(ContentPageResolutionRequest request, ContentPageResolutionResponse response, ContentPageResolutionFilterChain chain) throws ContentPageResolutionException { // do standard resolution first chain.resolve(request, response); // check if more than one candidate pages List<ObjectID> candidates = response.getCandidatePageIds(); if (candidates.size() > 1) { LocalizedContext context = localizedContextHome.getLocalizedContext(request.getContext()); Locale locale = context.getPreferredSupportedLocale(); String lang = locale.getLanguage(); // find page with matching unique name for (ObjectID pageId : candidates) { if (pageId.getUniqueName().endsWith("." + lang)) { response.setPageID(pageId); break; } } } } }
- The ChangeContentPathFilter example changes the content path and performs the default resolution the new content path.
package com.ibm.workplace.wcm.extension.resolution; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionFilter; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionFilterChain; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionRequest; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionResponse; import com.ibm.workplace.wcm.api.extensions.resolution.exceptions.ContentPageResolutionException; public class ChangeContentPathFilter implements ContentPageResolutionFilter { public int getFilterChainWeight() { return 3; } public void resolve(ContentPageResolutionRequest request, ContentPageResolutionResponse response, ContentPageResolutionFilterChain chain) throws ContentPageResolutionException { // instead of england render UK if ("/countries/world/europe/england".equals(response.getContentPath())) { response.setContentPath("/countries/world/europe/uk"); } chain.resolve(request, response); } }
- The ResolveToSpecificPageFilter example resolves to a specific page. No default resolution is performed in this case.
package com.ibm.workplace.wcm.extension.resolution; import java.util.Arrays; import javax.naming.InitialContext; import javax.naming.NamingException; import com.ibm.portal.ObjectID; import com.ibm.portal.identification.Identification; import com.ibm.portal.serialize.SerializationException; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionFilter; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionFilterChain; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionRequest; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionResponse; import com.ibm.workplace.wcm.api.extensions.resolution.exceptions.ContentPageResolutionException; public class ResolveToSpecificPageFilter implements ContentPageResolutionFilter { private Identification identification; public ResolveToSpecificPageFilter() { try { InitialContext ctx = new InitialContext(); identification = (Identification) ctx.lookup("portal:service/Identification"); } catch (NamingException nx) { nx.printStackTrace(); } } public int getFilterChainWeight() { return 4; } public void resolve(ContentPageResolutionRequest request, ContentPageResolutionResponse response, ContentPageResolutionFilterChain chain) throws ContentPageResolutionException { try { // always resolve to page with unique name my.default.page ObjectID pageId = identification.deserialize("my.default.page"); response.setPageID(pageId); response.setCandidatePageIds(Arrays.asList(new ObjectID[]{pageId})); } catch (SerializationException e) { throw new ContentPageResolutionException(e); } } }
- The SetResponseCodePageResolutionFilter example checks for the requested web content item. If it does not exist, the code throws an exception that results in sending a 404 (Not found) HTTP response status code. If the content exists, resolution is delegated to other filters in the chain.
package com.ibm.workplace.wcm.extension.resolution; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.Locale; import java.util.Set; import javax.servlet.http.HttpServletResponse; import com.ibm.portal.ListModel; import com.ibm.portal.LocalizedStatus; import com.ibm.portal.ModelException; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionFilter; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionFilterChain; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionRequest; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionResponse; import com.ibm.workplace.wcm.api.extensions.resolution.ResolvedItem; import com.ibm.workplace.wcm.api.extensions.resolution.exceptions.ContentPageResolutionException; public class SetResponseCodePageResolutionFilter implements ContentPageResolutionFilter { public void resolve(ContentPageResolutionRequest request, ContentPageResolutionResponse response, ContentPageResolutionFilterChain chain) throws ContentPageResolutionException { if (!itemExists(request.getItem())) { // send 404 throw new ContentPageResolutionException(new ContentNotFoundException()); } else { // forward to the chain if the web content exists chain.resolve(request, response); } } private boolean itemExists(ResolvedItem item) { return (item.getItemID() != null) && (item.getItemPath() != null); } public int getFilterChainWeight() { return 1; } private static class ContentNotFoundException extends Exception implements LocalizedStatus { private static final long serialVersionUID = 70L; private static final Set<Locale> SUPPORTED_LOCALES = new HashSet<Locale>(Arrays.asList(new Locale[] { Locale.ENGLISH })); private static final String MESSAGE = "The requested web content does not exist"; public ContentNotFoundException() { super(MESSAGE); } public int getStatus() { return HttpServletResponse.SC_NOT_FOUND; } public String getTitle(Locale locale) { return MESSAGE; } public String getDescription(Locale locale) { return MESSAGE; } public ListModel<Locale> getLocales() { return new ListModel<Locale>() { public Iterator<Locale> iterator() throws ModelException { return SUPPORTED_LOCALES.iterator(); } }; } } }
- The SendRedirectPageResolutionFilter example checks for the requested web content item. If the content does not exist, the code sends a redirect to http://www.ibm.com. If the content exists, the resolution is delegated to other filters in the chain.
package com.ibm.workplace.wcm.extension.resolution; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; import com.ibm.portal.resolver.exceptions.ResolutionException; import com.ibm.portal.resolver.helper.CORResolutionService; import com.ibm.portal.state.exceptions.StateException; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionFilter; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionFilterChain; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionRequest; import com.ibm.workplace.wcm.api.extensions.resolution.ContentPageResolutionResponse; import com.ibm.workplace.wcm.api.extensions.resolution.ResolvedItem; import com.ibm.workplace.wcm.api.extensions.resolution.exceptions.ContentPageResolutionException; public class SendRedirectPageResolutionFilter implements ContentPageResolutionFilter { // the URL to redirect to private static final String URL = "http://www.ibm.com"; public void resolve(ContentPageResolutionRequest request, ContentPageResolutionResponse response, ContentPageResolutionFilterChain chain) throws ContentPageResolutionException { if (!itemExists(request.getItem())) { try { // encode to URL, this is important to prevent that the ':' // character appears in the path String encodedURL = URLEncoder.encode(URL, "UTF-8"); final URI redirectURI = new URI(com.ibm.portal.resolver.Constants.SCHEME_REDIRECT, encodedURL, null); CORResolutionService.SINGLETON.resolve(request.getResolved(), redirectURI, request.getVerb(), request.getResolutionParameters(), request.getAcceptedBindings(),request.getContext()); } catch (UnsupportedEncodingException uenc) { // should never happens as long as UTF-8 is supported throw new ContentPageResolutionException(uenc); } catch (URISyntaxException e) { throw new ContentPageResolutionException(e); } catch (StateException e) { throw new ContentPageResolutionException(e); } catch (ResolutionException e) { // do not catch the resolution exception // as this is used internally to trigger the redirect throw new ContentPageResolutionException(e); } } else { chain.resolve(request, response); } } private boolean itemExists(ResolvedItem item) { return (item.getItemID() != null) && (item.getItemPath() != null); } public int getFilterChainWeight() { return 1; } }
- The following example provides the plugin.xml file that registers the previous sample filters.
Registering all of these filters in one system is not recommended. The filters perform overlapping operations and are also exclusive in some cases. To use one of the filters in your system, remove the other unused filters in the plugin.xml file before deploying the file.
<?xml version="1.0" encoding="UTF-8"?> <?eclipse version="3.0"?> <plugin id="com.ibm.workplace.wcm.extension.resolution" name="Content Page Resolution Filter" version="1.0.0" provider-name="IBM"> <extension point="com.ibm.workplace.wcm.api.ContentPageResolutionFilter" id="SendRedirectPageResolutionFilter"> <provider class="com.ibm.workplace.wcm.extension.resolution.SendRedirectPageResolutionFilter" weight="1"/> </extension> <extension point="com.ibm.workplace.wcm.api.ContentPageResolutionFilter" id="SetResponseCodePageResolutionFilter"> <provider class="com.ibm.workplace.wcm.extension.resolution.SetResponseCodePageResolutionFilter" weight="1"/> </extension> <extension point="com.ibm.workplace.wcm.api.ContentPageResolutionFilter" id="LocaleDependantSelectionFilter"> <provider class="com.ibm.workplace.wcm.extension.resolution.LocaleDependantSelectionFilter" weight="2"/> </extension> <extension point="com.ibm.workplace.wcm.api.ContentPageResolutionFilter" id="ChangeContentPathFilter"> <provider class="com.ibm.workplace.wcm.extension.resolution.ChangeContentPathFilter" weight="3"/> </extension> <extension point="com.ibm.workplace.wcm.api.ContentPageResolutionFilter" id="ResolveToSpecificPageFilter"> <provider class="com.ibm.workplace.wcm.extension.resolution.ResolveToSpecificPageFilter" weight="4"/> </extension> </plugin>
Parent: Create custom plug-insRelated: