Attachment 'BetwixtTransformer.java'

Download

   1 /*
   2  ============================================================================
   3                    The Apache Software License, Version 1.1
   4  ============================================================================
   5  Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
   6  Redistribution and use in source and binary forms, with or without modifica-
   7  tion, are permitted provided that the following conditions are met:
   8  1. Redistributions of  source code must  retain the above copyright  notice,
   9     this list of conditions and the following disclaimer.
  10  2. Redistributions in binary form must reproduce the above copyright notice,
  11     this list of conditions and the following disclaimer in the documentation
  12     and/or other materials provided with the distribution.
  13  3. The end-user documentation included with the redistribution, if any, must
  14     include  the following  acknowledgment:  "This product includes  software
  15     developed  by the  Apache Software Foundation  (http://www.apache.org/)."
  16     Alternately, this  acknowledgment may  appear in the software itself,  if
  17     and wherever such third-party acknowledgments normally appear.
  18  4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
  19     used to  endorse or promote  products derived from  this software without
  20     prior written permission. For written permission, please contact
  21     apache@apache.org.
  22  5. Products  derived from this software may not  be called "Apache", nor may
  23     "Apache" appear  in their name,  without prior written permission  of the
  24     Apache Software Foundation.
  25  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  26  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  27  FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
  28  APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
  29  INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
  30  DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
  31  OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
  32  ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
  33  (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
  34  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35  This software  consists of voluntary contributions made  by many individuals
  36  on  behalf of the Apache Software  Foundation and was  originally created by
  37  Stefano Mazzocchi  <stefano@apache.org>. For more  information on the Apache
  38  Software Foundation, please see <http://www.apache.org/>.
  39  */
  40 
  41 package org.apache.cocoon.transformation;
  42 
  43 import java.lang.reflect.Proxy;
  44 import java.util.Collection;
  45 import java.util.Iterator;
  46 import java.util.Map;
  47 
  48 import org.apache.avalon.framework.configuration.Configurable;
  49 import org.apache.avalon.framework.configuration.Configuration;
  50 import org.apache.avalon.framework.configuration.ConfigurationException;
  51 import org.apache.avalon.framework.parameters.Parameters;
  52 import org.apache.cocoon.environment.Context;
  53 import org.apache.cocoon.environment.ObjectModelHelper;
  54 import org.apache.cocoon.environment.Request;
  55 import org.apache.cocoon.environment.Session;
  56 import org.apache.cocoon.environment.SourceResolver;
  57 import org.apache.commons.betwixt.XMLIntrospector;
  58 import org.apache.commons.betwixt.io.SAXBeanWriter;
  59 import org.apache.commons.betwixt.strategy.ClassNormalizer;
  60 import org.apache.commons.logging.impl.LogKitLogger;
  61 import org.xml.sax.Attributes;
  62 import org.xml.sax.SAXException;
  63 
  64 /**
  65  * Betwixt transformer marshals a object from the Sitemap, Session, Request or
  66  * the Conext into a series of SAX events.
  67  *
  68  * Configuation: The betwixt transformer can be configured to not output element
  69  * reference ids. The default setting is to output reference IDs.
  70  * <pre>
  71  *   &lt;map:transformer name="betwixt" src="org.apache.cocoon.transformation.BetwixtTransformer"
  72  *     &lt;ref-ids&gt;true&lt;/ref-ids&gt;
  73  *   &lt;/map:transformer&gt;
  74  * </pre>
  75  *
  76  * A sample for the use:
  77  * <pre>
  78  *   &lt;root xmlns:betwixt="http://apache.org/cocoon/betwixt-transfomer"&gt;
  79  *	   &lt;betwixt:include name="invoice" /&gt;
  80  *	   &lt;betwixt:include name="product" scope="sitemap" /&gt;
  81  *	   &lt;betwixt:include name="product2" element="other-product" /&gt;
  82  *   &lt;/root&gt;
  83  * </pre>
  84  * The <code>BetwixtTransfomer</code> support only one Element <code>betwixt:include</code>.
  85  * This element is replaced with the marshalled object. The Object given through the
  86  * attribute <code>name</code> will be searched in the <code>request</code>, <code>session</code>,
  87  * <code>context</code> and at least in <code>sitemap</code>.
  88  * If the scope is explicitly given, the object will ge located only there.
  89  * The attribute <code>element</code> can be given to specify an alternativ
  90  * root element for the object. Collections are marshalled by marshalling
  91  * each object it contains.
  92  *
  93  * @see <a href="http://jakarta.apache.org/commons/betwixt/">Betwixt Projekt Homepage</a>
  94  * @author <a href="mailto:cgaffga@triplemind.com">Christoph Gaffga</a>
  95  */
  96 public class BetwixtTransformer extends AbstractTransformer implements Configurable {
  97   private static final String BETWIXT_NSURI = "http://apache.org/cocoon/betwixt-transfomer";
  98 
  99   private final static String CMD_INCLUDE = "include";
 100   private final static String ATTR_NAME = "name";
 101   private final static String ATTR_SCOPE = "scope";
 102   private final static String SCOPE_SITEMAP = "sitemap";
 103   private final static String SCOPE_SESSION = "session";
 104   private final static String SCOPE_REQUEST = "request";
 105   private final static String SCOPE_CONTEXT = "context";
 106   private final static String ATTR_ELEMENT = "element";
 107   private final static String CONF_REFIDS = "ref-ids";
 108 
 109   // Introspector to share XMLBeanInfo cache
 110   private static XMLIntrospector introspector;
 111 
 112   private boolean refIds = true;
 113 
 114   private Map objectModel = null;
 115   private boolean inBetwixtElement = false;
 116   private SAXBeanWriter beanWriter = null;
 117 
 118   public void configure(Configuration conf) throws ConfigurationException {
 119     final String refIds = conf.getChild(CONF_REFIDS).getValue("true");
 120     this.refIds = "false".equals(refIds) || "no".equals(refIds);
 121   }
 122 
 123   public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) {
 124     this.objectModel = objectModel;
 125   }
 126 
 127   public void recycle() {
 128     this.objectModel = null;
 129     this.inBetwixtElement = false;
 130   }
 131 
 132   public void endElement(String uri, String name, String raw) throws SAXException {
 133     if (BETWIXT_NSURI.equals(uri)) {
 134       this.inBetwixtElement = false;
 135     } else {
 136       super.endElement(uri, name, raw);
 137     }
 138   }
 139 
 140   public void startElement(String uri, String name, String raw, Attributes attr) throws
 141       SAXException {
 142     if (BETWIXT_NSURI.equals(uri)) {
 143       this.inBetwixtElement = true;
 144       process(name, attr);
 145     } else {
 146       super.startElement(uri, name, raw, attr);
 147     }
 148   }
 149 
 150   public void characters(char[] ch, int start, int len) throws SAXException {
 151     if (!this.inBetwixtElement) {
 152       super.characters(ch, start, len);
 153     }
 154   }
 155 
 156   private void process(String command, Attributes attr) throws SAXException {
 157     if (CMD_INCLUDE.equals(command)) {
 158       final String scope = attr.getValue(ATTR_SCOPE);
 159       final String name = attr.getValue(ATTR_NAME);
 160       if (name == null) {
 161         throw new SAXException("Required attribute name is missing on element " + CMD_INCLUDE);
 162       }
 163 
 164       final String element = attr.getValue(ATTR_ELEMENT);
 165       if (element == null) {
 166         throw new SAXException("Attribute " + ATTR_ELEMENT + " can not be empty");
 167       }
 168 
 169       Object bean = null;
 170       if (scope == null || SCOPE_REQUEST.equals(scope)) {
 171         final Request request = ObjectModelHelper.getRequest(objectModel);
 172         bean = request.getAttribute(name);
 173       }
 174       if ( (scope == null && bean == null) || SCOPE_SESSION.equals(scope)) {
 175         final Session session = ObjectModelHelper.getRequest(objectModel).getSession(false);
 176         if (session != null) {
 177           bean = session.getAttribute(name);
 178         }
 179       }
 180       if ( (scope == null && bean == null) || SCOPE_CONTEXT.equals(scope)) {
 181         final Context context = ObjectModelHelper.getContext(objectModel);
 182         if (context != null) {
 183           bean = context.getAttribute(name);
 184         }
 185       }
 186       if ( (scope == null && bean == null) || SCOPE_SITEMAP.equals(scope)) {
 187         bean = objectModel.get(name);
 188       }
 189 
 190       if (bean != null) {
 191         includeBean(name, bean, element);
 192       } else {
 193         getLogger().warn("Bean " + name + " could not be found");
 194       }
 195     } else {
 196       throw new SAXException("Unknown command: " + command);
 197     }
 198   }
 199 
 200   private void includeBean(String name, Object bean, String element) {
 201     try {
 202       if (this.beanWriter == null) {
 203         this.beanWriter = new SAXBeanWriter(this.contentHandler);
 204         synchronized (this.introspector) {
 205           if (this.introspector == null) {
 206             this.introspector = this.beanWriter.getXMLIntrospector();
 207             this.introspector.setLog(new LogKitLogger("betwixt"));
 208             /* The following is needed for EJB */
 209             this.introspector.setClassNormalizer(new ClassNormalizer() {
 210               public Class normalize(Class clazz) {
 211                 if (Proxy.isProxyClass(clazz) && clazz.getInterfaces().length > 0) {
 212                   return clazz.getInterfaces()[0];
 213                 }
 214                 return super.normalize(clazz);
 215               }
 216             });
 217 
 218           } else {
 219             this.beanWriter.setXMLIntrospector(this.introspector);
 220           }
 221         }
 222         beanWriter.getBindingConfiguration().setMapIDs(this.refIds);
 223       }
 224 
 225       if (bean instanceof Collection) {
 226         Iterator i = ( (Collection) bean).iterator();
 227         while (i.hasNext()) {
 228           if (element == null) {
 229             beanWriter.write(bean);
 230           } else {
 231             beanWriter.write(element, bean);
 232           }
 233         }
 234       } else {
 235         if (element == null) {
 236           beanWriter.write(bean);
 237         } else {
 238           beanWriter.write(element, bean);
 239         }
 240       }
 241     } catch (Exception e) {
 242       getLogger().warn("Failed to marshal bean " + name, e);
 243     }
 244   }
 245 
 246 }

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.