You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by st...@apache.org on 2003/10/06 18:27:33 UTC

cvs commit: cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/transformation CastorTransformer.java

stephan     2003/10/06 09:27:33

  Modified:    src/blocks/scratchpad/java/org/apache/cocoon/transformation
                        CastorTransformer.java
  Log:
  Add unmarshalling capabilities, thanks to Michael Homeijer(see
  BUG 12993).
  
  Revision  Changes    Path
  1.3       +187 -65   cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/transformation/CastorTransformer.java
  
  Index: CastorTransformer.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/transformation/CastorTransformer.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- CastorTransformer.java	5 Sep 2003 07:04:34 -0000	1.2
  +++ CastorTransformer.java	6 Oct 2003 16:27:33 -0000	1.3
  @@ -67,7 +67,10 @@
   import org.exolab.castor.mapping.Mapping;
   import org.exolab.castor.mapping.MappingException;
   import org.exolab.castor.xml.Marshaller;
  +import org.exolab.castor.xml.UnmarshalHandler;
  +import org.exolab.castor.xml.Unmarshaller;
   import org.xml.sax.Attributes;
  +import org.xml.sax.ContentHandler;
   import org.xml.sax.SAXException;
   import org.xml.sax.InputSource;
   
  @@ -93,28 +96,37 @@
    *
    * A sample for the use:
    * <pre>
  - *   &ltroot xmlns:castor="http://castor.exolab.org/cocoontransfomer"&gt
  - *	&ltcastor:InsertBean name="invoice"/&gt
  - *	&ltcastor:InsertBean name="product" scope="sitemap" mapping="castor/specicalmapping.xml"/&gt
  + *   &ltroot xmlns:castor="http://apache.org/cocoon/castor/1.0"&gt
  + *         &ltcastor:marshall name="invoice"/&gt
  + *         &ltcastor:unmarshall name="product" scope="sitemap" mapping="castor/specicalmapping.xml"/&gt
    *  &lt/root&gt
    * </pre>
  - * The CastorTransfomer support only one Element <code>castor:InsertBean</code>. This
  - * element is replaced with the marshalled object. The Object given through the
  - * attrbute <code>name</code> will be searched in the <code>sitemap, request,
  - * session</code> and at least in <code>application</code>
  - * If the scope is explicitly given, e.g , the object will ge located only here
  - * The Attribut <code>mapping</code> specifys the mapping to be used. If not given
  - * the default mapping is used
  - * <pre/>
  + * The CastorTransfomer supports two elements
  + * <code>castor:unmarshal</code> and <code>castor:marshal</code>.
  + *
  + * The marshal element is replaced with the marshalled object.
  + * The Object given through the attrbute <code>name</code>
  + * will be searched in the <code>sitemap, request, session</code> and at
  + * least in <code>application</code> If the scope is explicitly given, e.g ,
  + * the object will ge located only here. The Attribute <code>mapping</code>
  + * specifys the mapping to be used. The attribute <code>command</code> specifies a class that
  + * implements CastorMarshalCommand and will be called before and after marshalling.
  + *
  + * The elements within the unmarshal element will be sent to the castor unmarshaller
  + * the resulting java object with be placed in the object specified by name and scope (see also marshall element).
  + * The <code>command</code> attribute specifies the class that implements CastorUnmarshalCommand
  + * and will be called before and after unmarshalling.
    *
    * @author <a href="mailto:mauch@imkenberg.de">Thorsten Mauch</a>
    * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
  + * @author <a href="mailto:michael.homeijer@ordina.nl">Michael Homeijer</a>
    * @version CVS $Id$
    */
   public class CastorTransformer extends AbstractTransformer implements Configurable {
  -    private static final String CASTOR_URI = "http://castor.exolab.org/cocoontransfomer";
  +    private static final String CASTOR_URI = "http://apache.org/cocoon/castor/1.0";
   
  -    private final static String CMD_INSERT_BEAN = "InsertBean";
  +    private static final String CMD_UNMARSHAL = "unmarshal";
  +    private static final String CMD_MARSHAL = "marshal";
       private final static String ATTRIB_NAME = "name";
       private final static String ATTRIB_SCOPE = "scope";
       private final static String SCOPE_SITEMAP = "sitemap";
  @@ -126,6 +138,17 @@
       // Stores all used mappings in the static cache
       private static HashMap mappings;
   
  +    /** The map of namespace prefixes. */
  +    private Map prefixMap = new HashMap();
  +                                                                                                                                                               
  +    private boolean in_castor_marshal = false;
  +                                                                                                                                                               
  +    private Unmarshaller unmarshaller;
  +    private UnmarshalHandler unmarshalHandler;
  +    private ContentHandler unmarshalContentHandler;
  +    private String beanName;
  +    private String beanScope;
  +
       private Map objectModel;
       private SourceResolver resolver;
   
  @@ -156,6 +179,29 @@
       public void endElement(String uri, String name, String raw) throws SAXException {
           if (CASTOR_URI.equals(uri)) {
               in_castor_element = false;
  +        } else if (unmarshalContentHandler != null) {
  +            // check if this marks the end of the unmarshalling
  +            if ((CASTOR_URI.equals(uri)) && (CMD_UNMARSHAL.equals(name))) {
  +                                                                                                                                                               
  +                // End marshalling, remove prefixes
  +                Iterator itt = prefixMap.entrySet().iterator();
  +                while ( itt.hasNext() ) {
  +                   Map.Entry entry = (Map.Entry) itt.next();
  +                   unmarshalContentHandler.endPrefixMapping((String)entry.getKey());
  +                }
  +                                                                                                                                                               
  +                // end document
  +                unmarshalContentHandler.endDocument();
  +                unmarshalContentHandler = null;
  +                                                                                                                                                               
  +                // store the result of the unmarshaller
  +                Object root = unmarshalHandler.getObject();
  +                this.storeBean(objectModel, beanName, beanScope, root);
  +            } else {
  +                unmarshalContentHandler.endElement(uri, name, raw);
  +            }
  +        } else if (CASTOR_URI.equals(uri)) {
  +            in_castor_marshal = false;
           } else {
               super.endElement(uri,  name,  raw);
           }
  @@ -177,76 +223,106 @@
       }
   
       private void process (String command, Attributes attr) throws SAXException {
  -        if (CMD_INSERT_BEAN.equals(command)) {
  -            final String scope = attr.getValue(ATTRIB_SCOPE);
  -            final String name = attr.getValue(ATTRIB_NAME);
  -            final String mapping = attr.getValue(ATTRIB_MAPPING);
  -            if (name == null){
  -                throw new SAXException("Required attribute name is missing on element " + CMD_INSERT_BEAN);
  -            }
  -
  -            Request request = ObjectModelHelper.getRequest(objectModel);
  -
  -            Object bean = null;
  -            if (scope == null) {
  -                // Search for bean in (1) objectModel, (2) request, (3) session, and (4) context.
  -                bean = request.getAttribute(name);
  -                if (bean == null) {
  -                    Session session = request.getSession(false);
  -                    if (session != null) {
  -                        bean = session.getAttribute(name);
  -                    }
  -                }
  -                if (bean == null) {
  -                    Context context = ObjectModelHelper.getContext(objectModel);
  -                    if (context != null) {
  -                        bean = context.getAttribute(name);
  -                    }
  -                }
  -                if (bean == null) {
  -                    bean = objectModel.get(name);
  -                }
  -            } else if (SCOPE_SITEMAP.equals(scope)) {
  -                bean = objectModel.get(name);
  -            } else if (SCOPE_REQUEST.equals(scope)) {
  -                bean = request.getAttribute(name);
  -            } if (SCOPE_SESSION.equals(scope)) {
  -                Session session = request.getSession(false);
  -                if (session != null) {
  -                    bean = session.getAttribute(name);
  -                }
  -            } if (SCOPE_CONTEXT.equals(scope)) {
  -                Context context = ObjectModelHelper.getContext(objectModel);
  -                if(context != null){
  -                    bean=context.getAttribute(name);
  +        if (command.equals(CMD_MARSHAL)) {
  +            in_castor_marshal = true;
  +                                                                                                                                                               
  +            String scope = attr.getValue(ATTRIB_SCOPE);
  +            String name = attr.getValue(ATTRIB_NAME);
  +            String mapping = attr.getValue(ATTRIB_MAPPING);
  +                                                                                                                                                               
  +            if (name == null) {
  +                getLogger().error("Attribute to insert not set");
  +            } else {
  +                marshal(objectModel, name, scope, mapping);
  +            }
  +        } else if (command.equals(CMD_UNMARSHAL)) {
  +            beanScope = attr.getValue(ATTRIB_SCOPE);
  +            beanName = attr.getValue(ATTRIB_NAME);
  +                                                                                                                                                               
  +            if (beanScope == null) {
  +              getLogger().error("Destination for unmarshalled bean not set");
  +              return;
  +            }
  +                                                                                                                                                               
  +            if (beanName == null) {
  +              getLogger().error("Name of unmarshalled bean not set");
  +              return;
  +            }
  +            String mappingpath = attr.getValue(ATTRIB_MAPPING);
  +                                                                                                                                                               
  +                                                                                                                                                               
  +            // Create the unmarshaller
  +            unmarshaller = new Unmarshaller((Class) null);
  +            // Only set a mapping if one is specified
  +            if (mappingpath != null) {
  +                Mapping mapping;
  +                                                                                                                                                               
  +                try {
  +                    mapping = loadMapping(mappingpath);
  +                    unmarshaller.setMapping(mapping);
  +                } catch (MappingException e) {
  +                    getLogger().error("Could not load mapping file " + mappingpath, e);
  +                } catch (IOException e) {
  +                    getLogger().error("Could not load mapping file " + mappingpath, e);
                   }
               }
  -
  -            if (bean != null) {
  -                insertBean(name, bean, mapping);
  -            } else {
  -                getLogger().warn("Bean " +name + " could not be found");
  +                                                                                                                                                               
  +//            unmarshalCommand = null;
  +/*            if (commandclass != null) {
  +    try {
  +      unmarshalCommand = (CastorUnmarshalCommand)Class.forName(commandclass).newInstance();
  +      unmarshalCommand.enableLogging(this.getLogger());
  +                                                                                                                                                               
  +      unmarshalCommand.pre(unmarshaller, xmlConsumer, objectModel, params);
  +    } catch (InstantiationException e) {
  +      getLogger().error("Could not instantiate class " + commandclass ,e);
  +    } catch (IllegalAccessException e) {
  +      getLogger().error("Could not access class " + commandclass ,e);
  +    } catch (ClassNotFoundException e) {
  +      getLogger().error("Could not instantiate class " + commandclass ,e);
  +    }
  +    }*/
  +                                                                                                                                                               
  +            // Create the unmarshalhandler and wrap it with a SAX2 contentHandler
  +            unmarshalHandler = unmarshaller.createHandler();
  +                                                                                                                                                               
  +            try {
  +                unmarshalContentHandler = unmarshaller.getContentHandler(
  +                                                  unmarshalHandler);
  +                                                                                                                                                               
  +                unmarshalContentHandler.startDocument();
  +                                                                                                                                                               
  +                Iterator itt = prefixMap.entrySet().iterator();
  +                while ( itt.hasNext() ) {
  +                   Map.Entry entry = (Map.Entry)itt.next();
  +                   unmarshalContentHandler.startPrefixMapping((String)entry.getKey(), (String)entry.getValue());
  +                }
  +                                                                                                                                                               
  +            } catch (SAXException e) {
  +                getLogger().error("Could not get contenthandler from unmarshaller", e);
               }
           } else {
               throw new SAXException("Unknown command: " + command);
           }
       }
   
  -    private void insertBean (String name, Object bean, String map) {
  +    private void marshal(Map objectModel, String name, String scope, String mappingpath) {
           try {
               Marshaller marshaller = new Marshaller(new IncludeXMLConsumer(super.contentHandler));
               try {
                   Mapping mapping = null;
  -                if (map != null) {
  -                    mapping = loadMapping(map);
  +                if (mappingpath != null) {
  +                    mapping = loadMapping(mappingpath);
                   } else {
                       mapping = defaultMapping;
                   }
                   marshaller.setMapping(mapping);
               } catch (Exception e) {
  -                getLogger().warn("Unable to load mapping " + map, e);
  +                getLogger().warn("Unable to load mapping " + mappingpath, e);
               }
   
  +            Object bean = this.searchBean(objectModel, name, scope);
  +
               if (bean instanceof Collection) {
                   Iterator i = ((Collection)bean).iterator();
                   while (i.hasNext()) {
  @@ -257,6 +333,52 @@
               }
           } catch (Exception e) {
               getLogger().warn("Failed to marshal bean " + name, e);
  +        }
  +    }
  +
  +    /**
  +     * Find the bean that should be marshalled by the transformer
  +     *
  +     * @param objectModel The Cocoon objectmodel
  +     * @param name The name of the bean
  +     * @param scope The source specification of the bean REQUEST/SESSION etc.
  +     * @return The bean that was found
  +     */
  +    private Object searchBean(Map objectModel, String name, String scope) {
  +        Request request = ObjectModelHelper.getRequest(objectModel);
  +        Object bean;
  +                                                                                                                                                               
  +        //  search all maps for the given bean
  +        if ((scope == null) || SCOPE_SITEMAP.equals(scope)) {
  +            return objectModel.get(name);
  +        }
  +                                                                                                                                                               
  +        if ((scope == null) || SCOPE_REQUEST.equals(scope)) {
  +            return request.getAttribute(name);
  +        }
  +                                                                                                                                                               
  +        if ((scope == null) || SCOPE_SESSION.equals(scope)) {
  +            Session session = request.getSession(false);
  +                                                                                                                                                               
  +            if (session != null) {
  +                return session.getAttribute(name);
  +            }
  +        }
  +                                                                                                                                                               
  +        return null;
  +    }
  +
  +    private void storeBean(Map objectModel, String name, String scope, Object bean) {
  +        Request request = ObjectModelHelper.getRequest(objectModel);
  +                                                                                                                                                               
  +        if (SCOPE_SITEMAP.equals(scope)) {
  +            objectModel.put(name, bean);
  +        } else if (SCOPE_REQUEST.equals(scope)) {
  +            request.setAttribute(name, bean);
  +        } else if (SCOPE_SESSION.equals(scope)) {
  +            Session session = request.getSession(true);
  +                                                                                                                                                               
  +            session.setAttribute(name, bean);
           }
       }