huber 02/02/06 13:18:49 Added: src/scratchpad/src/org/apache/cocoon/transformation EncodeURLTransformer.java Log: rewrite URLs, matching specified patterns using response.encodeURL() Revision Changes Path 1.1 xml-cocoon2/src/scratchpad/src/org/apache/cocoon/transformation/EncodeURLTransformer.java Index: EncodeURLTransformer.java =================================================================== package org.apache.cocoon.transformation; import java.io.IOException; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.avalon.excalibur.pool.Poolable; import org.apache.avalon.excalibur.pool.Recyclable; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.ProcessingException; import org.apache.cocoon.environment.SourceResolver; import org.apache.cocoon.environment.http.HttpEnvironment; import org.apache.cocoon.transformation.AbstractTransformer; import org.apache.regexp.RE; import org.apache.regexp.RESyntaxException; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; /** * The encodeURL transformer emits encoded URLs. * <p> * This transformer applies encodeURL method to URLs. * You may want to use this transform to avoid doing the manually * encodeURL() call. * </p> * <p> * Usually this transformer is appended as last transformer before * the serialization process. In this case it is possible to encode * URLs introduced in the generator, and xslt transformer phase. * </p> * <p> * You can specify which attributes hold URL values in order to restrict * URL rewriting to specific attributes only. * </p> * <p> * Usage in a sitemap: * </p> * <pre><tt> * <map:composition> * ... * <map:transformers> * ... * <map:transformer type="encodeURL" * src="org.apache.cocoon.optional.transformation.EncodeURLTransformer"> * <exclude-name>img/@src</exclude-name> * <include-name>.&asterik;/@href|.&asterik;/@src|.&asterik;/@action</include-name> * </map:transformer> * ... * <map:pipelines> * <map:pipeline> * ... * <map:transform type="encodeURL"/> * ... * </pre></tt> * * @author <a href="mailto:[EMAIL PROTECTED]">Bernhard Huber</a> * @version CVS $Id: EncodeURLTransformer.java,v 1.1 2002/02/06 21:18:49 huber Exp $ * * @cocoon:name encodeURL * @cocoon:status scratchpad * @cocoon:parameter name="exclude-name" * default-value="img/@src" * description="RE pattern for excluding attributes from encode URL rewriting" * @cocoon:parameter name="include-name" * default-value=".&asterik;/@href|.&asterik;/@src|.&asterik;/@action" * description="RE pattern for including attributes from encode URL rewriting" * */ public class EncodeURLTransformer extends AbstractTransformer implements Configurable, Recyclable { /** * Configuration name for specifying excluding patterns, * ie exclude-name. * * @since */ public final static String EXCLUDE_NAME = "exclude-name"; /** * Configuration name for specifying including patterns, * ie include-name. * * @since */ public final static String INCLUDE_NAME = "include-name"; /** * Configuration default exclude pattern, * ie img/@src * * @since */ public final static String EXCLUDE_NAME_DEFAULT = "img/@src"; /** * Configuration default exclude pattern, * ie .*\/@href|.*\/@action|frame/@src * * @since */ public final static String INCLUDE_NAME_DEFAULT = ".*/@href|.*/@action|frame/@src"; private String includeNameConfigure = INCLUDE_NAME_DEFAULT; private String excludeNameConfigure = EXCLUDE_NAME_DEFAULT; private String includeName; private String excludeName; private ElementAttributeMatching elementAttributeMatching; private HttpServletResponse response; private HttpServletRequest request; /** * Setup the transformer. * <p> * Setup include, and exclude patterns from the parameters * </p> * * @param resolver source resolver * @param objectModel sitemap objects * @param parameters request parameters * */ public void setup(SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws ProcessingException, SAXException, IOException { includeName = parameters.getParameter(EncodeURLTransformer.INCLUDE_NAME, this.includeNameConfigure); excludeName = parameters.getParameter(EncodeURLTransformer.EXCLUDE_NAME, this.excludeNameConfigure); try { elementAttributeMatching = new ElementAttributeMatching(includeName, excludeName); } catch (RESyntaxException reex) { String message = "Cannot parse include-name: " + includeName + " " + "or exclude-name: " + excludeName + "!"; throw new ProcessingException(message, reex); } response = (HttpServletResponse) objectModel.get(HttpEnvironment.HTTP_RESPONSE_OBJECT); request = (HttpServletRequest) objectModel.get(HttpEnvironment.HTTP_REQUEST_OBJECT); } /** * BEGIN SitemapComponent methods * * @param configuration Description of Parameter * @exception ConfigurationException Description of Exception * @since */ public void configure(Configuration configuration) throws ConfigurationException { if (configuration != null) { Configuration child; child = configuration.getChild(EncodeURLTransformer.INCLUDE_NAME); this.includeNameConfigure = child.getValue(INCLUDE_NAME_DEFAULT); child = configuration.getChild(EncodeURLTransformer.EXCLUDE_NAME); this.excludeNameConfigure = child.getValue(EXCLUDE_NAME_DEFAULT); } if (this.includeNameConfigure == null) { String message = "Configure " + INCLUDE_NAME + "!"; throw new ConfigurationException(message); } if (this.excludeNameConfigure == null) { String message = "Configure " + EXCLUDE_NAME + "!"; throw new ConfigurationException(message); } } /** *Description of the Method * * @since */ public void recycle() { response = null; request = null; elementAttributeMatching = null; } /** * Start parsing an element * * @param uri of the element * @param name of the element * @param raw name of the element * @param attributes list * @exception SAXException Description of Exception * @since */ public void startElement(String uri, String name, String raw, Attributes attributes) throws SAXException { String lname = name; if (response != null && elementAttributeMatching != null) { if (attributes != null && attributes.getLength() > 0) { AttributesImpl new_attributes = new AttributesImpl(attributes); for (int i = 0; i < new_attributes.getLength(); i++) { String attr_lname = new_attributes.getLocalName(i); String value = new_attributes.getValue(i); if (elementAttributeMatching.matchesElementAttribute(lname, attr_lname)) { String new_value = encodeURL(value, request, response); if (getLogger().isDebugEnabled()) { this.getLogger().debug("element/@attribute matches: " + name + "/@" + attr_lname); this.getLogger().debug("encodeURL: " + value + " -> " + new_value); } new_attributes.setValue(i, new_value); } } // parent handles element using encoded attribute values super.contentHandler.startElement(uri, name, raw, new_attributes); return; } } // no match, parent handles element as-is super.contentHandler.startElement(uri, name, raw, attributes); } /** * Encode a URL. * <p> * This method calculates from a given url the encoded url * </p> * * @param url the URL probably without sessionid. * @param request the http request * @param response the http response * @return String the original url inclusive the sessionid * @since */ private String encodeURL(String url, HttpServletRequest request, HttpServletResponse response) { String encoded_url; if (response != null) { // As some servlet-engine does not check if url has been already rewritten HttpSession session = request.getSession(false); if (session != null && url.indexOf(session.getId()) > -1) { encoded_url = url; } else { encoded_url = response.encodeURL(url); } } else { encoded_url = url; } return encoded_url; } /** * A helper class for matching element names, and attribute names. * * <p> * For given include-name, exclude-name decide if element-attribute pair * matches. This class defines the precedence and matching algorithm. * </p> * * @author <a href="mailto:[EMAIL PROTECTED]">Bernhard Huber</a> * @version CVS $Id: EncodeURLTransformer.java,v 1.1 2002/02/06 21:18:49 huber Exp $ */ public class ElementAttributeMatching { /** * Regular expression of including patterns * * @since */ protected RE includeNameRE; /** * Regular expression of excluding patterns * * @since */ protected RE excludeNameRE; /** *Constructor for the ElementAttributeMatching object * * @param includeName Description of Parameter * @param excludeName Description of Parameter * @exception RESyntaxException Description of Exception * @since */ public ElementAttributeMatching(String includeName, String excludeName) throws RESyntaxException { includeNameRE = new RE(includeName, RE.MATCH_CASEINDEPENDENT); excludeNameRE = new RE(excludeName, RE.MATCH_CASEINDEPENDENT); } /** * Return true iff element_name attr_name pair is not matched by exclude-name, * but is matched by include-name * * @param element_name * @param attr_name * @return boolean true iff value of attribute_name should get rewritten, else * false. * @since */ public boolean matchesElementAttribute(String element_name, String attr_name) { String element_attr_name = canonicalizeElementAttribute(element_name, attr_name); if (excludeNameRE != null && includeNameRE != null) { return !matchesExcludesElementAttribute(element_attr_name) && matchesIncludesElementAttribute(element_attr_name); } else { return false; } } /** * Build from elementname, and attribute name a single string. * <p> * String concatenated <code>element name + "/@" + attribute name</code> * is matched against the include and excluding patterns. * </p> * * @param element_name Description of Parameter * @param attr_name Description of Parameter * @return Description of the Returned Value * @since */ String canonicalizeElementAttribute(String element_name, String attr_name) { StringBuffer element_attr_name = new StringBuffer(); element_attr_name.append(element_name); element_attr_name.append("/@"); element_attr_name.append(attr_name); return element_attr_name.toString(); } /** * Return true iff element_name attr_name pair is matched by exclude-name. * * @param element_attr_name * @return boolean true iff exclude-name matches element_name, attr_name, else * false. * @since */ private boolean matchesExcludesElementAttribute(String element_attr_name) { boolean match = excludeNameRE.match(element_attr_name); return match; } /** * Return true iff element_name attr_name pair is matched by include-name. * * @param element_attr_name * @return boolean true iff include-name matches element_name, attr_name, else * false. * @since */ private boolean matchesIncludesElementAttribute(String element_attr_name) { boolean match = includeNameRE.match(element_attr_name); return match; } } }
---------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]