Attachment 'OmitNsTransformer.java'

Download

   1 /*
   2  ============================================================================
   3                    The Apache Software License, Version 1.1
   4  ============================================================================
   5 
   6  Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
   7 
   8  Redistribution and use in source and binary forms, with or without modifica-
   9  tion, are permitted provided that the following conditions are met:
  10 
  11  1. Redistributions of  source code must  retain the above copyright  notice,
  12     this list of conditions and the following disclaimer.
  13 
  14  2. Redistributions in binary form must reproduce the above copyright notice,
  15     this list of conditions and the following disclaimer in the documentation
  16     and/or other materials provided with the distribution.
  17 
  18  3. The end-user documentation included with the redistribution, if any, must
  19     include  the following  acknowledgment:  "This product includes  software
  20     developed  by the  Apache Software Foundation  (http://www.apache.org/)."
  21     Alternately, this  acknowledgment may  appear in the software itself,  if
  22     and wherever such third-party acknowledgments normally appear.
  23 
  24  4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
  25     used to  endorse or promote  products derived from  this software without
  26     prior written permission. For written permission, please contact
  27     apache@apache.org.
  28 
  29  5. Products  derived from this software may not  be called "Apache", nor may
  30     "Apache" appear  in their name,  without prior written permission  of the
  31     Apache Software Foundation.
  32 
  33  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  34  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  35  FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
  36  APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
  37  INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
  38  DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
  39  OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
  40  ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
  41  (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
  42  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  43 
  44  This software  consists of voluntary contributions made  by many individuals
  45  on  behalf of the Apache Software  Foundation and was  originally created by
  46  Stefano Mazzocchi  <stefano@apache.org>. For more  information on the Apache
  47  Software Foundation, please see <http://www.apache.org/>.
  48  
  49  * OmitNsTransformer.java
  50  * (C)2004 Gitus, s.r.o., http://www.gitus.com
  51  * Henryk Paluch, hpaluch@gitus.cz
  52  */
  53 package com.gitus.cocoon.transform;
  54 
  55 import java.io.IOException;
  56 import java.util.HashSet;
  57 import java.util.Iterator;
  58 import java.util.Map;
  59 import java.util.Set;
  60 import java.util.StringTokenizer;
  61 
  62 import org.apache.avalon.excalibur.pool.Recyclable;
  63 import org.apache.avalon.framework.parameters.Parameters;
  64 import org.apache.cocoon.ProcessingException;
  65 import org.apache.cocoon.environment.SourceResolver;
  66 import org.apache.cocoon.transformation.AbstractTransformer;
  67 import org.xml.sax.helpers.AttributesImpl;
  68 import org.xml.sax.Attributes;
  69 import org.xml.sax.SAXException;
  70 
  71 /**
  72  * This transformer is supposed to omit selected or all namespace declaration.
  73  * <h2>Usage</h2>
  74  * Declare this transformer in <code>map:transformers</code> section:
  75  * <pre>
  76  *  &lt;map:components&gt;
  77  *    ...
  78  *  &lt;map:transformes&gt;
  79  *    ...
  80  *  &lt;map:transformer
  81  *      logger="sitemap.transformer.omitns"
  82  *      name="omitns"
  83  *	    pool-grow="2" pool-max="16" pool-min="2"
  84  *	    src="com.gitus.cocoon.transform.OmitNsTransformer"/&gt;
  85  *   &lt;/map:transformer&gt;
  86  *   ...
  87  * </pre>
  88  * 
  89  * Insert <code>omitns</code> transformer with <code>omit-namespaces</code>
  90  * into your pipeline. For example, to omit common logicsheet tags from xsp use something like:
  91  * 
  92  * <pre>
  93  * &lt;map:match pattern="*_xsp"&gt;
  94  *  &lt;map:generate type="serverpages" src="xsp/{1}.xsp"/&gt;
  95  *  &lt;map:transform type="omitns" label="xml"&gt;
  96  *   &lt;map:parameter name="omit-namespaces" value="xsp jpath xspdoc esql xsp-request"/&gt;
  97  *  &lt;/map:transform&gt;
  98  *  &lt;map:serialize type="xml"/&gt;
  99  * &lt;/map:match&gt;                            
 100  * </pre>
 101  *
 102  * <p>If you want to omit all ns declaration - then leave <code>omit-namespaces</code> empty.</p>
 103  * <p>If you want to omit plain <code>xmlns=http://....</code> attribute (usefull for HTMLSerializer) then specify</p>
 104  * <pre>
 105  *   &lt;map:parameter name="omit-plain-xmlns" value="true"/&gt;
 106  * </pre>
 107  * @author <a href="mailto:hpaluch@gitus.cz">Henryk Paluch</a>
 108  * @version CVS $Id:$ 2004-01-16
 109  * 
 110  * 
 111  */
 112 public class OmitNsTransformer extends AbstractTransformer
 113  implements Recyclable
 114   {
 115   	/**
 116   	 * Parameter - specifies whitespace or comma separated list of namespaces
 117   	 * to omit (remove) from output.
 118   	 */
 119 	public static final String OMITNS_OMIT_NAMESPACES="omit-namespaces";
 120 
 121 	/**
 122 	 * Parameter - specifies whether to omit main <code>xmlns=http://...</code>
 123 	 * declaration.
 124 	 * Allowed values are "true" or "false". Default is false;
 125 	 */
 126 	public static final String OMITNS_OMIT_PLAIN_XMLNS="omit-plain-xmlns";
 127 
 128 
 129 	/**
 130 	 * Set of Strings containing namespace prefixes to omit from output.
 131 	 */
 132 	protected Set omittedNs = null;
 133 
 134 	/**
 135 	 * We need to make runtime set of URIs to omit too...
 136 	 */
 137 	protected Set omittedUris = null;
 138 
 139 	
 140 	/**
 141 	 * Whether to omit plain <code>xmlns=http://abcde</code>.
 142 	 * It is usefull when you like to specify <code>xmlns</code> for html
 143 	 * (it is accurate for XHTML or XML Serialization),
 144 	 * but it should be filtered out for HTML serialization
 145 	 */
 146 	protected boolean omitPlainXmlns = false;
 147 
 148 	/** 
 149 	 * Setup - prepare transformer.
 150 	 * setup list of omitted namespaces
 151 	 * @see org.apache.cocoon.sitemap.SitemapModelComponent#setup(org.apache.cocoon.environment.SourceResolver, java.util.Map, java.lang.String, org.apache.avalon.framework.parameters.Parameters)
 152 	 */
 153 	public void setup(
 154 		SourceResolver resolver,
 155 		Map objectModel,
 156 		String src,
 157 		Parameters parameters)
 158 		throws ProcessingException, SAXException, IOException {
 159 			omitPlainXmlns = parameters.getParameterAsBoolean(OMITNS_OMIT_PLAIN_XMLNS,false);			
 160 			omittedNs = new HashSet();
 161 			omittedUris = new HashSet();
 162 			myAddOmittedNamespaces(parameters);
 163 			if ( getLogger().isDebugEnabled()){
 164 				getLogger().debug("setup: List of ns prefixes to omit: "+showSet(omittedNs));
 165 				getLogger().debug("setup: omitPlainXmlns="+omitPlainXmlns);
 166 			}
 167 			
 168 	}
 169 	
 170 	/**
 171 	 * Release Set on recycle event.
 172 	 */
 173 	public void recycle() {
 174 		super.recycle();
 175 		omittedNs = null;
 176 		omittedUris = null;
 177 	}
 178 
 179 	/**
 180 	 * Hook for startPrefixMapping - if prefix is found in our omittedNs set - then ignore.
 181 	 */
 182 	public void startPrefixMapping(String prefix, String uri)
 183 		throws SAXException {
 184 
 185 		if ( ( omitPlainXmlns && prefix.length()==0) 
 186 		      || shouldOmitNs(prefix)){
 187 			if ( getLogger().isDebugEnabled()){
 188 				getLogger().debug("startPrefixMapping: omiting prefix="+prefix+", uri="+uri);
 189 			}
 190 			// add uri to omit list
 191 			omittedUris.add(uri);
 192 		} else {
 193 			super.startPrefixMapping(prefix, uri);
 194 		}
 195 	}
 196 
 197 	/**
 198 	 * Hook for endPrefixMapping - if prefix is found in our omittedNs set - then ignore.
 199 	 */
 200 
 201 	public void endPrefixMapping(String prefix) throws SAXException {
 202 		if (  ( omitPlainXmlns && prefix.length()==0) 
 203 		      || shouldOmitNs(prefix)){
 204 			if ( getLogger().isDebugEnabled()){
 205 				getLogger().debug("endPrefixMapping: omiting prefix="+prefix);
 206 			}
 207 		} else {
 208 			super.endPrefixMapping(prefix);
 209 		}
 210 	}
 211 
 212 	/**
 213 	 * Catch and filter out namespace in attributes.
 214 	 * It is supposed to filter out unwanted <code>xmlns:xyz</code>
 215 	 * This attribute is "inverted" (it is in <code>xmlns</code> but no <code>xyz</code>space
 216 	 * - therefore special catch needed...)
 217 	 * attribute.
 218 	 * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
 219 	 */
 220 	public void startElement(
 221 		String uri,
 222 		String name,
 223 		String raw,
 224 		Attributes attr)
 225 		throws SAXException {
 226 		
 227 		Attributes realAttr = attr; // by default pass unmodified attribute list	
 228 		if ( attr.getLength()>0){			
 229 			AttributesImpl myAttr = new AttributesImpl(attr);
 230 			// walk attributes backward to
 231 			// avoid unnecessary index change
 232 			for(int i=myAttr.getLength()-1;i>=0;i--){
 233 				String local = myAttr.getLocalName(i);
 234 				String qName = myAttr.getQName(i);
 235 				// handle omit-plain-xmlns
 236 				if ( omitPlainXmlns && qName.equals("xmlns")){
 237 					if ( getLogger().isDebugEnabled()){
 238 						getLogger().debug("startElement: omitting main xmlns attribute: "
 239 							   +",qname="+qName+",value="+myAttr.getValue(i));
 240 					}
 241 					myAttr.removeAttribute(i);
 242 					continue;
 243 				}
 244 				// handle omit-namespaces				
 245 				if ( qName.startsWith("xmlns:") && local.length()>0
 246 					 && shouldOmitNs(local) ){
 247 						if ( getLogger().isDebugEnabled()){
 248 							getLogger().debug("startElement: omitting xmlns attribute: local="+local
 249 								   +",qname="+qName+",value="+myAttr.getValue(i));
 250 						}
 251 						myAttr.removeAttribute(i);
 252 				}
 253 			}
 254 			realAttr = myAttr;
 255 		}			
 256 		if ( omittedUris.contains(uri)){
 257 			uri = ""; // clear uri
 258 		}
 259 		super.startElement(uri, name, raw, realAttr);
 260 	}
 261 
 262 	/**
 263 	 * Omit uris if needed.
 264 	 * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
 265 	 */
 266 	public void endElement(String uri, String loc, String qname)
 267 		throws SAXException {
 268 			
 269 		if ( omittedUris.contains(uri)){
 270 				uri = ""; // clear uri
 271 		}		
 272 		super.endElement(uri, loc, qname);
 273 	}
 274 
 275 
 276 	/**
 277 	 * Returns true if we should omit all namespace prefixes.
 278 	 * @return
 279 	 */
 280 	private boolean shouldOmitNs(String nsName)
 281 	{
 282 		return omittedNs.isEmpty() || omittedNs.contains(nsName);
 283 	}
 284 
 285 	/**
 286 	 * Parses list of namespace names in form of <code>ns1 ns2 ns3</code>
 287 	 * and adds them to <code>omitNsStr</code>.
 288 	 * @param parameters
 289 	 */
 290 	private void myAddOmittedNamespaces(Parameters parameters) {
 291 		String omitNsStr = parameters.getParameter(OMITNS_OMIT_NAMESPACES,null);
 292 		if ( omitNsStr != null){
 293 			StringTokenizer t = new StringTokenizer(omitNsStr," \t\r\n\f,:");
 294 			while ( t.hasMoreTokens()){
 295 				String ns = t.nextToken();
 296 				ns = ns.trim();
 297 				if ( ns.length() > 0){
 298 					omittedNs.add(ns); 
 299 				}
 300 			}
 301 		}		
 302 	}
 303 	
 304 	/**
 305 	 * Returns String of set items (using their toString() method).
 306 	 * Used for debug purposes.
 307 	 * @param s
 308 	 * @return
 309 	 */
 310 	private String showSet(Set s)
 311 	{
 312 		StringBuffer b = new StringBuffer();
 313 		Iterator i = s.iterator();
 314 		while (i.hasNext()){
 315 			String str = (String)i.next();
 316 			if ( b.length()>0){
 317 				b.append(",");
 318 			}
 319 			b.append(str);
 320 		}
 321 		return b.toString();		
 322 	}
 323 
 324 
 325 
 326 }

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.