Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 18129 invoked from network); 6 Oct 2003 16:27:36 -0000 Received: from daedalus.apache.org (HELO mail.apache.org) (208.185.179.12) by minotaur-2.apache.org with SMTP; 6 Oct 2003 16:27:36 -0000 Received: (qmail 29823 invoked by uid 500); 6 Oct 2003 16:27:28 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 29739 invoked by uid 500); 6 Oct 2003 16:27:27 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 29688 invoked by uid 500); 6 Oct 2003 16:27:27 -0000 Delivered-To: apmail-cocoon-2.1-cvs@apache.org Received: (qmail 29672 invoked from network); 6 Oct 2003 16:27:27 -0000 Received: from unknown (HELO minotaur.apache.org) (209.237.227.194) by daedalus.apache.org with SMTP; 6 Oct 2003 16:27:27 -0000 Received: (qmail 17998 invoked by uid 1509); 6 Oct 2003 16:27:33 -0000 Date: 6 Oct 2003 16:27:33 -0000 Message-ID: <20031006162733.17997.qmail@minotaur.apache.org> From: stephan@apache.org To: cocoon-2.1-cvs@apache.org Subject: cvs commit: cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/transformation CastorTransformer.java X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N 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: *
  - *   <root xmlns:castor="http://castor.exolab.org/cocoontransfomer">
  - *	<castor:InsertBean name="invoice"/>
  - *	<castor:InsertBean name="product" scope="sitemap" mapping="castor/specicalmapping.xml"/>
  + *   <root xmlns:castor="http://apache.org/cocoon/castor/1.0">
  + *         <castor:marshall name="invoice"/>
  + *         <castor:unmarshall name="product" scope="sitemap" mapping="castor/specicalmapping.xml"/>
    *  </root>
    * 
- * The CastorTransfomer support only one Element castor:InsertBean. This - * element is replaced with the marshalled object. The Object given through the - * attrbute name will be searched in the sitemap, request, - * session and at least in application - * If the scope is explicitly given, e.g , the object will ge located only here - * The Attribut mapping specifys the mapping to be used. If not given - * the default mapping is used - *
  + * The CastorTransfomer supports two elements
  + * castor:unmarshal and castor:marshal.
  + *
  + * The marshal element is replaced with the marshalled object.
  + * The Object given through the attrbute name
  + * will be searched in the sitemap, request, session and at
  + * least in application If the scope is explicitly given, e.g ,
  + * the object will ge located only here. The Attribute mapping
  + * specifys the mapping to be used. The attribute command 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 command attribute specifies the class that implements CastorUnmarshalCommand
  + * and will be called before and after unmarshalling.
    *
    * @author Thorsten Mauch
    * @author Vadim Gritsenko
  + * @author Michael Homeijer
    * @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);
           }
       }