cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From simonetrip...@apache.org
Subject svn commit: r957445 - in /cocoon/cocoon3/trunk/cocoon-optional/src: main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/ test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/
Date Thu, 24 Jun 2010 07:59:22 GMT
Author: simonetripodi
Date: Thu Jun 24 07:59:21 2010
New Revision: 957445

URL: http://svn.apache.org/viewvc?rev=957445&view=rev
Log:
started adding array/list support + array test case
extracted ObjectCacheKey inner class

Added:
    cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/ObjectCacheKey.java
  (with props)
Modified:
    cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/InMemoryLRUMarshallerCache.java
    cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGenerator.java
    cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/Animal.java
    cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGeneratorTestCase.java

Modified: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/InMemoryLRUMarshallerCache.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/InMemoryLRUMarshallerCache.java?rev=957445&r1=957444&r2=957445&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/InMemoryLRUMarshallerCache.java
(original)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/InMemoryLRUMarshallerCache.java
Thu Jun 24 07:59:21 2010
@@ -49,6 +49,19 @@ final class InMemoryLRUMarshallerCache i
      */
     private static final int CACHE_CAPACITY = (int) Math.ceil(CACHE_SIZE / LOAD_FACTOR) +
1;
 
+    private static final InMemoryLRUMarshallerCache INSTANCE = new InMemoryLRUMarshallerCache();
+
+    public static InMemoryLRUMarshallerCache getInstance() {
+        return INSTANCE;
+    }
+
+    /**
+     * This class can't be instantiated.
+     */
+    private InMemoryLRUMarshallerCache() {
+        // do nothing
+    }
+
     /**
      * The map that implements the LRU cache.
      */

Modified: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGenerator.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGenerator.java?rev=957445&r1=957444&r2=957445&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGenerator.java
(original)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGenerator.java
Thu Jun 24 07:59:21 2010
@@ -18,25 +18,36 @@
  */
 package org.apache.cocoon.optional.pipeline.components.sax.jaxb;
 
-import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
 
 import org.apache.cocoon.pipeline.ProcessingException;
-import org.apache.cocoon.pipeline.caching.AbstractCacheKey;
 import org.apache.cocoon.pipeline.caching.CacheKey;
 import org.apache.cocoon.pipeline.component.CachingPipelineComponent;
 import org.apache.cocoon.pipeline.util.StringRepresentation;
 import org.apache.cocoon.sax.AbstractSAXGenerator;
+import org.xml.sax.helpers.AttributesImpl;
 
 /**
  * SAX generator that produces SAX events from Object using the JAXB marshaller.
  */
 public final class JAXBGenerator extends AbstractSAXGenerator implements CachingPipelineComponent
{
 
-    private static final InMemoryLRUMarshallerCache MARSHALLER_CACHE = new InMemoryLRUMarshallerCache();
+    private static final String DEFAULT = "##default";
+
+    private static final String UTF_8 = "UTF-8";
+
+    private static final String EMPTY = "";
+
+    private final InMemoryLRUMarshallerCache marshallerCache = InMemoryLRUMarshallerCache.getInstance();
 
     private final Object toBeMarshalled;
 
+    private String charset = UTF_8;
+
+    private boolean formattedOutput = false;
+
     public JAXBGenerator(Object toBeMarshalled) {
         if (toBeMarshalled == null) {
             throw new IllegalArgumentException("Argument 'toBeMarshalled' must not be null");
@@ -44,71 +55,120 @@ public final class JAXBGenerator extends
         this.toBeMarshalled = toBeMarshalled;
     }
 
-    public void execute() {
-        try {
-            Marshaller xmlMarshaller = MARSHALLER_CACHE.getMarshaller(this.toBeMarshalled.getClass());
-            xmlMarshaller.marshal(this.toBeMarshalled, this.getSAXConsumer());
-        } catch (JAXBException e) {
-            throw new ProcessingException("Impossible to marshal object of type "
-                    + this.toBeMarshalled.getClass()
-                    + " to XML", e);
-        }
+    public String getCharset() {
+        return this.charset;
     }
 
-    @Override
-    public String toString() {
-        return StringRepresentation.buildString(this, "toBeMarshalled=" + this.toBeMarshalled);
+    public void setCharset(String charset) {
+        this.charset = charset;
     }
 
-    public CacheKey constructCacheKey() {
-        return new ObjectCacheKey(this.toBeMarshalled);
+    public boolean isFormattedOutput() {
+        return this.formattedOutput;
     }
 
-    private final class ObjectCacheKey extends AbstractCacheKey {
+    public void setFormattedOutput(boolean formattedOutput) {
+        this.formattedOutput = formattedOutput;
+    }
 
-        private static final long serialVersionUID = 1L;
+    public void execute() {
+        // retrieve the right type has to be marshaled
+        String xmlRootElementName = null;
+        String xmlRootElementNameSpace = null;
+        boolean pluralize = false;
+        Class<?> type = this.toBeMarshalled.getClass();
+
+        // analyze generics for collections
+        if (Iterable.class.isAssignableFrom(type)) {
+            pluralize = true;
+            // TODO extract the generic type!!!
+        } else if (type.isArray()) { // else get array type
+            pluralize = true;
+            type = type.getComponentType();
+        }
+        // otherwise is the passed argument type
+
+        // validate the type can be marshaled using JAXB
+        if (!type.isAnnotationPresent(XmlRootElement.class)
+                && !type.isAnnotationPresent(XmlType.class)) {
+            throw new IllegalArgumentException("Object of type "
+                    + type.getName()
+                    + " can't be marshalled since neither of "
+                    + XmlRootElement.class.getName()
+                    + " or "
+                    + XmlType.class.getName()
+                    + " are present");
+        }
+
+        // get the root element name if needed
+        if (pluralize) {
+            String name = null;
+            if (type.isAnnotationPresent(XmlRootElement.class)) {
+                XmlRootElement xmlRootElement = type.getAnnotation(XmlRootElement.class);
+                name = xmlRootElement.name();
+                xmlRootElementNameSpace = xmlRootElement.namespace();
+            } else if (type.isAnnotationPresent(XmlType.class)) {
+                XmlType xmlType = type.getAnnotation(XmlType.class);
+                name = xmlType.name();
+                xmlRootElementNameSpace = xmlType.namespace();
+            }
 
-        private final Object obj;
+            if (name != null && !DEFAULT.equals(name)) {
+                xmlRootElementName = name;
+            } else {
+                xmlRootElementName = type.getSimpleName();
+            }
 
-        public ObjectCacheKey(Object obj) {
-            this.obj = obj;
-        }
+            if (DEFAULT.equals(xmlRootElementNameSpace)) {
+                xmlRootElementNameSpace = EMPTY;
+            }
 
-        public Object getObj() {
-            return this.obj;
+            // pluralize
+            // TODO has to be improved, see PluralStemmers reference impl
+            xmlRootElementName += 's';
         }
 
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof ObjectCacheKey)) {
-                return false;
+        try {
+            Marshaller xmlMarshaller = marshallerCache.getMarshaller(type);
+            if (this.charset != null) {
+                xmlMarshaller.setProperty(Marshaller.JAXB_ENCODING, this.charset);
             }
+            xmlMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, this.formattedOutput);
 
-            ObjectCacheKey otherCacheKey = (ObjectCacheKey) other;
-            return this.obj.equals(otherCacheKey.getObj());
-        }
-
-        @Override
-        public int hashCode() {
-            return this.obj.hashCode();
+            // setup the Marshaler if a collection has to be marshaled
+            if (pluralize) {
+                xmlMarshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
+                this.getSAXConsumer().startDocument();
+                this.getSAXConsumer().startElement(xmlRootElementNameSpace, xmlRootElementName,
xmlRootElementName, new AttributesImpl());
+
+                if (Iterable.class.isAssignableFrom(this.toBeMarshalled.getClass())) {
+                    for (Object object : (Iterable<Object>) this.toBeMarshalled) {
+                        xmlMarshaller.marshal(object, this.getSAXConsumer());
+                    }
+                } else if (this.toBeMarshalled.getClass().isArray()) {
+                    for (Object object : (Object[]) this.toBeMarshalled) {
+                        xmlMarshaller.marshal(object, this.getSAXConsumer());
+                    }
+                }
+
+                this.getSAXConsumer().endElement(xmlRootElementNameSpace, xmlRootElementName,
xmlRootElementName);
+                this.getSAXConsumer().endDocument();
+            } else {
+                xmlMarshaller.marshal(this.toBeMarshalled, this.getSAXConsumer());
+            }
+        } catch (Exception e) {
+            throw new ProcessingException("Impossible to marshal object of type "
+                    + this.toBeMarshalled.getClass()
+                    + " to XML", e);
         }
+    }
 
-        /**
-         * {@inheritDoc}
-         *
-         * @see org.apache.cocoon.pipeline.caching.CacheKey#isValid(org.apache.cocoon.pipeline.caching.CacheKey)
-         */
-        public long getLastModified() {
-            return -1;
-        }
+    public CacheKey constructCacheKey() {
+        return new ObjectCacheKey(this.toBeMarshalled);
+    }
 
-        /**
-         * {@inheritDoc}
-         *
-         * @see org.apache.cocoon.pipeline.caching.CacheKey#isValid(org.apache.cocoon.pipeline.caching.CacheKey)
-         */
-        public boolean isValid(CacheKey other) {
-            return this.equals(other);
-        }
+    @Override
+    public String toString() {
+        return StringRepresentation.buildString(this, "toBeMarshalled=" + this.toBeMarshalled);
     }
 }

Added: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/ObjectCacheKey.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/ObjectCacheKey.java?rev=957445&view=auto
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/ObjectCacheKey.java
(added)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/ObjectCacheKey.java
Thu Jun 24 07:59:21 2010
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cocoon.optional.pipeline.components.sax.jaxb;
+
+import org.apache.cocoon.pipeline.caching.AbstractCacheKey;
+import org.apache.cocoon.pipeline.caching.CacheKey;
+
+/**
+ * @version $Id$
+ */
+final class ObjectCacheKey extends AbstractCacheKey {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Object obj;
+
+    public ObjectCacheKey(Object obj) {
+        this.obj = obj;
+    }
+
+    public Object getObj() {
+        return this.obj;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof ObjectCacheKey)) {
+            return false;
+        }
+
+        ObjectCacheKey otherCacheKey = (ObjectCacheKey) other;
+        return this.obj.equals(otherCacheKey.getObj());
+    }
+
+    @Override
+    public int hashCode() {
+        return this.obj.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @see org.apache.cocoon.pipeline.caching.CacheKey#isValid(org.apache.cocoon.pipeline.caching.CacheKey)
+     */
+    public long getLastModified() {
+        return -1;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @see org.apache.cocoon.pipeline.caching.CacheKey#isValid(org.apache.cocoon.pipeline.caching.CacheKey)
+     */
+    public boolean isValid(CacheKey other) {
+        return this.equals(other);
+    }
+}

Propchange: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/ObjectCacheKey.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/ObjectCacheKey.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: cocoon/cocoon3/trunk/cocoon-optional/src/main/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/ObjectCacheKey.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/Animal.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/Animal.java?rev=957445&r1=957444&r2=957445&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/Animal.java
(original)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/Animal.java
Thu Jun 24 07:59:21 2010
@@ -22,7 +22,7 @@ import javax.xml.bind.annotation.XmlAttr
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
-@XmlRootElement
+@XmlRootElement(name = "animal")
 @XmlAccessorType(XmlAccessType.FIELD)
 final class Animal {
 

Modified: cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGeneratorTestCase.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGeneratorTestCase.java?rev=957445&r1=957444&r2=957445&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGeneratorTestCase.java
(original)
+++ cocoon/cocoon3/trunk/cocoon-optional/src/test/java/org/apache/cocoon/optional/pipeline/components/sax/jaxb/JAXBGeneratorTestCase.java
Thu Jun 24 07:59:21 2010
@@ -31,8 +31,20 @@ import org.junit.Test;
 
 public final class JAXBGeneratorTestCase {
 
+    // @Test
+    public void testPipelineWithBean() throws Exception {
+        Animal animal = new Animal();
+        animal.setAge(5);
+        animal.setCall("Dook");
+        animal.setColour("albino");
+        animal.setLatinName("Mustela putoris furo");
+        animal.setName("Lector");
+
+        this.internalAssert(animal, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><animal><call>Dook</call><colour>albino</colour><latinName>Mustela
putoris furo</latinName><name>Lector</name><age>5</age></animal>");
+    }
+
     @Test
-    public void testPipelineWithBeanGenerator() throws Exception {
+    public void testPipelineWithBeanArray() throws Exception {
         Animal animal = new Animal();
         animal.setAge(5);
         animal.setCall("Dook");
@@ -40,17 +52,20 @@ public final class JAXBGeneratorTestCase
         animal.setLatinName("Mustela putoris furo");
         animal.setName("Lector");
 
+        this.internalAssert(new Animal[]{ animal, animal },
+                "<?xml version=\"1.0\" encoding=\"UTF-8\"?><animals><animal><call>Dook</call><colour>albino</colour><latinName>Mustela
putoris furo</latinName><name>Lector</name><age>5</age></animal><animal><call>Dook</call><colour>albino</colour><latinName>Mustela
putoris furo</latinName><name>Lector</name><age>5</age></animal></animals>");
+    }
+
+    private void internalAssert(Object toBeMarshalled, String expected) throws Exception
{
         Pipeline<SAXPipelineComponent> pipeline = new NonCachingPipeline<SAXPipelineComponent>();
-        pipeline.addComponent(new JAXBGenerator(animal));
+        pipeline.addComponent(new JAXBGenerator(toBeMarshalled));
         pipeline.addComponent(new XMLSerializer());
 
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         pipeline.setup(baos);
         pipeline.execute();
 
-        Diff diff = new Diff(
-                "<?xml version=\"1.0\" encoding=\"UTF-8\"?><animal><call>Dook</call><colour>albino</colour><latinName>Mustela
putoris furo</latinName><name>Lector</name><age>5</age></animal>",
-                new String(baos.toByteArray()));
+        Diff diff = new Diff(expected, new String(baos.toByteArray()));
         assertTrue("Bean generation didn't work as expected " + diff, diff.identical());
     }
 



Mime
View raw message