sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1497446 - in /sis/branches/JDK7/core: sis-metadata/src/test/java/org/apache/sis/internal/jaxb/gml/ sis-utility/src/main/java/org/apache/sis/internal/jaxb/ sis-utility/src/main/java/org/apache/sis/xml/ sis-utility/src/test/java/org/apache/s...
Date Thu, 27 Jun 2013 17:03:34 GMT
Author: desruisseaux
Date: Thu Jun 27 17:03:33 2013
New Revision: 1497446

URL: http://svn.apache.org/r1497446
Log:
Refactoring of the test infrastructure in order to fix XML prefix, test Locale and test TimeZone
more easily.
For this purpose, we modified MarshallerPool in order to allow the constructor to parse all
properties given
in argument, build a template for them and use the template for all (un)marshaller creations.
This is likely
to be useful not only for tests, but also in production environment.

Added:
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java
  (with props)
Removed:
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/test/XMLTransformationTest.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/XMLTransformation.java
Modified:
    sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/gml/TimePeriodTest.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/XmlUtilities.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/Pooled.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledMarshaller.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledUnmarshaller.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/XMLComparator.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/XMLTestCase.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/iso/NameMarshallingTest.java

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/gml/TimePeriodTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/gml/TimePeriodTest.java?rev=1497446&r1=1497445&r2=1497446&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/gml/TimePeriodTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/gml/TimePeriodTest.java
[UTF-8] Thu Jun 27 17:03:33 2013
@@ -16,6 +16,8 @@
  */
 package org.apache.sis.internal.jaxb.gml;
 
+import java.util.Map;
+import java.util.HashMap;
 import java.util.Locale;
 import java.io.StringReader;
 import java.io.StringWriter;
@@ -24,8 +26,9 @@ import javax.xml.bind.Unmarshaller;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.datatype.DatatypeConfigurationException;
+import org.apache.sis.xml.XML;
+import org.apache.sis.xml.MarshallerPool;
 import org.apache.sis.internal.jaxb.XmlUtilities;
-import org.apache.sis.test.XMLTransformation;
 import org.apache.sis.test.XMLTestCase;
 import org.junit.BeforeClass;
 import org.junit.AfterClass;
@@ -47,47 +50,55 @@ import static org.apache.sis.test.TestUt
  */
 public final strictfp class TimePeriodTest extends XMLTestCase {
     /**
-     * The XML marshaller.
+     * A poll of configured {@link Marshaller} and {@link Unmarshaller}, created when first
needed.
      */
-    private static Marshaller marshaller;
+    private static MarshallerPool pool;
 
     /**
-     * The XML unmarshaller.
+     * A buffer where to marshal.
      */
-    private static Unmarshaller unmarshaller;
+    private final StringWriter buffer = new StringWriter();
 
     /**
-     * A buffer where to marshal.
+     * Set the marshalling context to a fixed locale and timezone before to create the
+     * JAXB wrappers for temporal objects. Callers shall invoke {@link #clearContext()}
+     * after this method.
      */
-    private final StringWriter buffer = new StringWriter();
+    private void createContext() {
+        createContext(true, Locale.FRANCE, "CET");
+    }
 
     /**
-     * Creates the XML marshaller to be shared by all test methods.
+     * Creates the XML (un)marshaller pool to be shared by all test methods.
+     * The (un)marshallers locale and timezone will be set to fixed values.
      *
-     * @throws JAXBException If an error occurred while creating the marshaller.
+     * @throws JAXBException If an error occurred while creating the pool.
      */
     @BeforeClass
     public static void createMarshallers() throws JAXBException {
-        final JAXBContext context = JAXBContext.newInstance(TimeInstant.class, TimePeriod.class);
-        marshaller   = context.createMarshaller();
-        unmarshaller = context.createUnmarshaller();
+        final Map<String,Object> properties = new HashMap<>(4);
+        assertNull(properties.put(XML.LOCALE, Locale.FRANCE));
+        assertNull(properties.put(XML.TIMEZONE, "CET"));
+        pool = new MarshallerPool(JAXBContext.newInstance(TimeInstant.class, TimePeriod.class),
properties);
     }
 
     /**
-     * Allows the garbage collector to collect the marshaller and unmarshallers.
+     * Invoked by JUnit after the execution of every tests in order to dispose
+     * the {@link MarshallerPool} instance used internally by this class.
      */
     @AfterClass
-    public static void disposeMarshallers() {
-        marshaller   = null;
-        unmarshaller = null;
+    public static void disposeMarshallerPool() {
+        pool = null;
     }
 
     /**
      * Creates a new time instant for the given date.
      */
-    private static TimeInstant createTimeInstant(final String date) throws DatatypeConfigurationException
{
+    private TimeInstant createTimeInstant(final String date) throws DatatypeConfigurationException
{
         final TimeInstant instant = new TimeInstant();
-        instant.timePosition = XmlUtilities.toXML(null, date(date));
+        createContext();
+        instant.timePosition = XmlUtilities.toXML(context, date(date));
+        clearContext();
         return instant;
     }
 
@@ -99,18 +110,22 @@ public final strictfp class TimePeriodTe
      */
     @Test
     public void testTimeInstant() throws JAXBException, DatatypeConfigurationException {
-        createContext(false, Locale.FRANCE, "CET");
-        String expected =
-            "<gml:TimeInstant>\n" +
-            "  <gml:timePosition>1992-01-01T01:00:00.000+01:00</gml:timePosition>\n"
+
-            "</gml:TimeInstant>\n";
+        final Marshaller   marshaller   = pool.acquireMarshaller();
+        final Unmarshaller unmarshaller = pool.acquireUnmarshaller();
+
         final TimeInstant instant = createTimeInstant("1992-01-01 00:00:00");
         marshaller.marshal(instant, buffer);
         final String actual = buffer.toString();
-        expected = XMLTransformation.GML.optionallyRemovePrefix(expected, actual);
-        assertXmlEquals(expected, actual, "xmlns:*", "xsi:schemaLocation");
+        assertXmlEquals(
+                "<gml:TimeInstant>\n" +
+                "  <gml:timePosition>1992-01-01T01:00:00.000+01:00</gml:timePosition>\n"
+
+                "</gml:TimeInstant>\n", actual, "xmlns:*", "xsi:schemaLocation");
+
         final TimeInstant test = (TimeInstant) unmarshaller.unmarshal(new StringReader(actual));
         assertEquals("1992-01-01 00:00:00", format(XmlUtilities.toDate(test.timePosition)));
+
+        pool.recycle(marshaller);
+        pool.recycle(unmarshaller);
     }
 
     /**
@@ -121,9 +136,11 @@ public final strictfp class TimePeriodTe
      */
     @Test
     public void testPeriodGML2() throws JAXBException {
-        createContext(false, Locale.FRANCE, "CET");
-        testPeriod(new TimePeriodBound.GML2(new DummyInstant(date("1992-01-01 00:00:00"))),
-                   new TimePeriodBound.GML2(new DummyInstant(date("2007-12-31 00:00:00"))),
+        createContext();
+        final TimePeriodBound begin = new TimePeriodBound.GML2(new DummyInstant(date("1992-01-01
00:00:00")));
+        final TimePeriodBound end   = new TimePeriodBound.GML2(new DummyInstant(date("2007-12-31
00:00:00")));
+        clearContext();
+        testPeriod(begin, end,
             "<gml:TimePeriod>\n" +
             "  <gml:begin>\n" +
             "    <gml:TimeInstant>\n" +
@@ -146,21 +163,23 @@ public final strictfp class TimePeriodTe
      * @param expected The expected string.
      */
     private void testPeriod(final TimePeriodBound begin, final TimePeriodBound end,
-            String expected, final boolean verifyValues) throws JAXBException
+            final String expected, final boolean verifyValues) throws JAXBException
     {
-        createContext(false, Locale.FRANCE, "CET");
+        final Marshaller   marshaller   = pool.acquireMarshaller();
+        final Unmarshaller unmarshaller = pool.acquireUnmarshaller();
         final TimePeriod period = new TimePeriod();
         period.begin = begin;
         period.end   = end;
         marshaller.marshal(period, buffer);
         final String actual = buffer.toString();
-        expected = XMLTransformation.GML.optionallyRemovePrefix(expected, actual);
         assertXmlEquals(expected, actual, "xmlns:*", "xsi:schemaLocation");
         final TimePeriod test = (TimePeriod) unmarshaller.unmarshal(new StringReader(actual));
         if (verifyValues) {
             assertEquals("1992-01-01 00:00:00", format(XmlUtilities.toDate(test.begin.calendar())));
             assertEquals("2007-12-31 00:00:00", format(XmlUtilities.toDate(test.end  .calendar())));
         }
+        pool.recycle(marshaller);
+        pool.recycle(unmarshaller);
     }
 
     /**
@@ -171,9 +190,11 @@ public final strictfp class TimePeriodTe
      */
     @Test
     public void testPeriodGML3() throws JAXBException {
-        createContext(false, Locale.FRANCE, "CET");
-        testPeriod(new TimePeriodBound.GML3(new DummyInstant(date("1992-01-01 00:00:00")),
"before"),
-                   new TimePeriodBound.GML3(new DummyInstant(date("2007-12-31 00:00:00")),
"after"),
+        createContext();
+        final TimePeriodBound begin = new TimePeriodBound.GML3(new DummyInstant(date("1992-01-01
00:00:00")), "before");
+        final TimePeriodBound end   = new TimePeriodBound.GML3(new DummyInstant(date("2007-12-31
00:00:00")), "after");
+        clearContext();
+        testPeriod(begin, end,
             "<gml:TimePeriod>\n" +
             "  <gml:beginPosition>1992-01-01T01:00:00+01:00</gml:beginPosition>\n"
+
             "  <gml:endPosition>2007-12-31T01:00:00+01:00</gml:endPosition>\n"
+
@@ -188,9 +209,11 @@ public final strictfp class TimePeriodTe
      */
     @Test
     public void testSimplifiedPeriodGML3() throws JAXBException {
-        createContext(false, Locale.FRANCE, "CET");
-        testPeriod(new TimePeriodBound.GML3(new DummyInstant(date("1992-01-01 23:00:00")),
"before"),
-                   new TimePeriodBound.GML3(new DummyInstant(date("2007-12-30 23:00:00")),
"after"),
+        createContext();
+        final TimePeriodBound begin = new TimePeriodBound.GML3(new DummyInstant(date("1992-01-01
23:00:00")), "before");
+        final TimePeriodBound end   = new TimePeriodBound.GML3(new DummyInstant(date("2007-12-30
23:00:00")), "after");
+        clearContext();
+        testPeriod(begin, end,
             "<gml:TimePeriod>\n" +
             "  <gml:beginPosition>1992-01-02</gml:beginPosition>\n" +
             "  <gml:endPosition>2007-12-31</gml:endPosition>\n" +
@@ -205,9 +228,11 @@ public final strictfp class TimePeriodTe
      */
     @Test
     public void testBeforePeriodGML3() throws JAXBException {
-        createContext(false, Locale.FRANCE, "CET");
-        testPeriod(new TimePeriodBound.GML3(null, "before"),
-                   new TimePeriodBound.GML3(new DummyInstant(date("2007-12-30 23:00:00")),
"after"),
+        createContext();
+        final TimePeriodBound begin = new TimePeriodBound.GML3(null, "before");
+        final TimePeriodBound end   = new TimePeriodBound.GML3(new DummyInstant(date("2007-12-30
23:00:00")), "after");
+        clearContext();
+        testPeriod(begin, end,
             "<gml:TimePeriod>\n" +
             "  <gml:beginPosition indeterminatePosition=\"before\"/>\n" +
             "  <gml:endPosition>2007-12-31</gml:endPosition>\n" +
@@ -222,9 +247,11 @@ public final strictfp class TimePeriodTe
      */
     @Test
     public void testAfterPeriodGML3() throws JAXBException {
-        createContext(false, Locale.FRANCE, "CET");
-        testPeriod(new TimePeriodBound.GML3(new DummyInstant(date("1992-01-01 23:00:00")),
"before"),
-                   new TimePeriodBound.GML3(null, "after"),
+        createContext();
+        final TimePeriodBound begin = new TimePeriodBound.GML3(new DummyInstant(date("1992-01-01
23:00:00")), "before");
+        final TimePeriodBound end   = new TimePeriodBound.GML3(null, "after");
+        clearContext();
+        testPeriod(begin, end,
             "<gml:TimePeriod>\n" +
             "  <gml:beginPosition>1992-01-02</gml:beginPosition>\n" +
             "  <gml:endPosition indeterminatePosition=\"after\"/>\n" +

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/XmlUtilities.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/XmlUtilities.java?rev=1497446&r1=1497445&r2=1497446&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/XmlUtilities.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/XmlUtilities.java
[UTF-8] Thu Jun 27 17:03:33 2013
@@ -141,7 +141,7 @@ public final class XmlUtilities extends 
      */
     public static XMLGregorianCalendar toXML(final Context context, final Date date) throws
DatatypeConfigurationException {
         if (date != null) {
-            final GregorianCalendar calendar = createGregorianCalendar();
+            final GregorianCalendar calendar = createGregorianCalendar(context);
             calendar.setTime(date);
             return getDatatypeFactory().newXMLGregorianCalendar(calendar);
         }
@@ -155,11 +155,10 @@ public final class XmlUtilities extends 
      *
      * @return A Gregorian calendar initialized with the current timezone and locale.
      */
-    private static GregorianCalendar createGregorianCalendar() {
-        final Context current = Context.current();
-        if (current != null) {
-            final Locale locale = current.getLocale();
-            final TimeZone timezone = current.getTimeZone();
+    private static GregorianCalendar createGregorianCalendar(final Context context) {
+        if (context != null) {
+            final Locale locale = context.getLocale();
+            final TimeZone timezone = context.getTimeZone();
             /*
              * Use the appropriate contructor rather than setting ourself the null values
to
              * the default locale or timezone, because the JDK constructors perform a better

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java?rev=1497446&r1=1497445&r2=1497446&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java
[UTF-8] Thu Jun 27 17:03:33 2013
@@ -60,6 +60,11 @@ import org.apache.sis.util.ArgumentCheck
 @ThreadSafe
 public class MarshallerPool {
     /**
+     * The indentation string, fixed to 2 spaces instead of 4 because ISO/OGC XML are very
verbose.
+     */
+    private static final String INDENTATION = "  ";
+
+    /**
      * Amount of nanoseconds to wait before to remove unused (un)marshallers.
      * This is a very approximative value: actual timeout will not be shorter,
      * but may be twice longer.
@@ -89,6 +94,11 @@ public class MarshallerPool {
     private final Object mapper;
 
     /**
+     * The {@link PooledTemplate} to use for initializing recycled (un)marshaller.
+     */
+    private final PooledTemplate template;
+
+    /**
      * The pool of marshaller. This pool is initially empty and will be filled with elements
as needed.
      * Marshallers (if any) shall be fetched using the {@link Deque#poll()} method and, after
use,
      * given back to the pool using the {@link Deque#push(Object)} method.
@@ -124,42 +134,39 @@ public class MarshallerPool {
 
     /**
      * Creates a new factory using the SIS default {@code JAXBContext} instance.
-     * The keys in the {@code properties} map can be one or many of following constants:
-     *
-     * <ul>
-     *   <li>{@link XML#DEFAULT_NAMESPACE} for specifying the default namespace of
the XML document to write.</li>
-     * </ul>
+     * The {@code properties} map is optional. If non-null, then the keys can be {@link XML}
constants or the
+     * names of any other properties recognized by <em>both</em> {@code Marshaller}
and {@code Unmarshaller}
+     * implementations.
+     *
+     * <p><b>Tip:</b> if the properties for the {@code Marshaller} differ
from the properties
+     * for the {@code Unmarshaller}, then consider overriding the {@link #createMarshaller()}
+     * or {@link #createUnmarshaller()} methods instead.</p>
      *
-     * @param  properties    The set of properties to be given to the pool, or {@code null}
if none.
+     * @param  properties The set of properties to be given to the (un)marshaller, or {@code
null} if none.
      * @throws JAXBException If the JAXB context can not be created.
      */
-    public MarshallerPool(final Map<String,String> properties) throws JAXBException
{
+    public MarshallerPool(final Map<String,?> properties) throws JAXBException {
         this(TypeRegistration.getSharedContext(), properties);
     }
 
     /**
      * Creates a new factory using the given JAXB context.
-     * The keys in the {@code properties} map can be one or many of following constants:
-     *
-     * <ul>
-     *   <li>{@link XML#DEFAULT_NAMESPACE} for specifying the default namespace of
the XML document to write.</li>
-     * </ul>
+     * The {@code properties} map is optional. If non-null, then the keys can be {@link XML}
constants or the
+     * names of any other properties recognized by <em>both</em> {@code Marshaller}
and {@code Unmarshaller}
+     * implementations.
+     *
+     * <p><b>Tip:</b> if the properties for the {@code Marshaller} differ
from the properties
+     * for the {@code Unmarshaller}, then consider overriding the {@link #createMarshaller()}
+     * or {@link #createUnmarshaller()} methods instead.</p>
      *
-     * @param  context       The JAXB context.
-     * @param  properties    The set of properties to be given to the pool, or {@code null}
if none.
+     * @param  context The JAXB context.
+     * @param  properties The set of properties to be given to the (un)marshaller, or {@code
null} if none.
      * @throws JAXBException If the marshaller pool can not be created.
      */
     @SuppressWarnings({"unchecked", "rawtypes"}) // Generic array creation
-    public MarshallerPool(final JAXBContext context, final Map<String,String> properties)
throws JAXBException {
+    public MarshallerPool(final JAXBContext context, final Map<String,?> properties)
throws JAXBException {
         ArgumentChecks.ensureNonNull("context", context);
         this.context = context;
-        String rootNamespace = "";
-        if (properties != null) {
-            rootNamespace = properties.get(XML.DEFAULT_NAMESPACE);
-            if (rootNamespace == null) {
-                rootNamespace = "";
-            }
-        }
         /*
          * Detects if we are using the endorsed JAXB implementation (i.e. the one provided
in
          * separated JAR files) or the one bundled in JDK 6. We use the JAXB context package
@@ -180,6 +187,12 @@ public class MarshallerPool {
             implementation = OTHER;
         }
         /*
+         * Prepares a copy of the property map (if any), then removes the
+         * properties which are handled especially by this constructor.
+         */
+        template = new PooledTemplate(properties, implementation == INTERNAL);
+        final Object rootNamespace = template.remove(XML.DEFAULT_NAMESPACE, "");
+        /*
          * Instantiates the OGCNamespacePrefixMapper appropriate for the implementation
          * we just detected. Note that we may get NoClassDefFoundError instead than the
          * usual ClassNotFoundException if the class was found but its parent class has
@@ -202,14 +215,14 @@ public class MarshallerPool {
      * This method:
      *
      * <ul>
-     *   <li>{@link Pooled#reset() Resets} the (un)marshaller to its initial state.</li>
+     *   <li>{@link Pooled#reset(Pooled) Resets} the (un)marshaller to its initial
state.</li>
      *   <li>{@linkplain Deque#push(Object) Pushes} the (un)marshaller in the given
queue.</li>
      *   <li>Registers a delayed task for disposing expired (un)marshallers after the
timeout.</li>
      * </ul>
      */
     private <T> void recycle(final Deque<T> queue, final T marshaller) {
         try {
-            ((Pooled) marshaller).reset();
+            ((Pooled) marshaller).reset(template);
         } catch (JAXBException exception) {
             // Not expected to happen because we are supposed
             // to reset the properties to their initial values.
@@ -307,7 +320,7 @@ public class MarshallerPool {
     public Marshaller acquireMarshaller() throws JAXBException {
         Marshaller marshaller = marshallers.poll();
         if (marshaller == null) {
-            marshaller = new PooledMarshaller(createMarshaller(), implementation == INTERNAL);
+            marshaller = new PooledMarshaller(createMarshaller(), template);
         }
         return marshaller;
     }
@@ -333,7 +346,7 @@ public class MarshallerPool {
     public Unmarshaller acquireUnmarshaller() throws JAXBException {
         Unmarshaller unmarshaller = unmarshallers.poll();
         if (unmarshaller == null) {
-            unmarshaller = new PooledUnmarshaller(createUnmarshaller(), implementation ==
INTERNAL);
+            unmarshaller = new PooledUnmarshaller(createUnmarshaller(), template);
         }
         return unmarshaller;
     }
@@ -401,10 +414,12 @@ public class MarshallerPool {
         switch (implementation) {
             case INTERNAL: {
                 marshaller.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper",
mapper);
+                marshaller.setProperty("com.sun.xml.internal.bind.indentString", INDENTATION);
                 break;
             }
             case ENDORSED: {
                 marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper);
+                marshaller.setProperty("com.sun.xml.bind.indentString", INDENTATION);
                 break;
             }
             // Do nothing for the OTHER case.

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/Pooled.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/Pooled.java?rev=1497446&r1=1497445&r2=1497446&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/Pooled.java [UTF-8]
(original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/Pooled.java [UTF-8]
Thu Jun 27 17:03:33 2013
@@ -28,6 +28,7 @@ import javax.xml.bind.JAXBException;
 import javax.xml.bind.PropertyException;
 import javax.xml.bind.ValidationEventHandler;
 import javax.xml.bind.annotation.adapters.XmlAdapter;
+import org.apache.sis.util.Locales;
 import org.apache.sis.util.Version;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.CharSequences;
@@ -85,8 +86,10 @@ abstract class Pooled {
      *   <li>For each entry having a key of type {@link String}, the value is the argument
      *       to be given to the {@code marshaller.setProperty(key, value)} method.</li>
      * </ul>
+     *
+     * This map is never {@code null}.
      */
-    private final Map<Object,Object> initialProperties;
+    final Map<Object,Object> initialProperties;
 
     /**
      * Bit masks for various boolean attributes. This include whatever the language codes
@@ -138,14 +141,14 @@ abstract class Pooled {
     private WarningListener<?> warningListener;
 
     /**
-     * The {@link System#nanoTime()} value of the last call to {@link #reset()}.
+     * The {@link System#nanoTime()} value of the last call to {@link #reset(Pooled)}.
      * This is used for disposing (un)marshallers that have not been used for a while,
      * since {@code reset()} is invoked just before to push a (un)marshaller in the pool.
      */
     volatile long resetTime;
 
     /**
-     * Default constructor.
+     * Creates a {@link PooledTemplate}.
      *
      * @param internal {@code true} if the JAXB implementation is the one bundled in JDK
6,
      *        or {@code false} if this is the external implementation provided as a JAR file
@@ -154,7 +157,32 @@ abstract class Pooled {
     Pooled(final boolean internal) {
         this.internal = internal;
         initialProperties = new LinkedHashMap<>();
-        bitMasks = initialBitMasks();
+    }
+
+    /**
+     * Creates a {@link PooledMarshaller} or {@link PooledUnmarshaller}. The {@link #initialize(Pooled)}
+     * method must be invoked after this constructor for completing the initialization.
+     *
+     * @param template The {@link PooledTemplate} from which to get the initial values.
+     */
+    Pooled(final Pooled template) {
+        initialProperties = new LinkedHashMap<>();
+        internal = template.internal;
+    }
+
+    /**
+     * Completes the creation of a {@link PooledMarshaller} or {@link PooledUnmarshaller}.
+     * This method is not invoked in the {@link #Pooled(Pooled)} constructor in order to
+     * give to subclasses a chance to complete their construction first.
+     *
+     * @param  template The {@link PooledTemplate} from which to get the initial values.
+     * @throws JAXBException If an error occurred while setting a property.
+     */
+    final void initialize(final Pooled template) throws JAXBException {
+        reset(template); // Set the SIS properties first. JAXB properties are set below.
+        for (final Map.Entry<Object,Object> entry : template.initialProperties.entrySet())
{
+            setStandardProperty((String) entry.getKey(), entry.getValue());
+        }
     }
 
     /**
@@ -170,27 +198,28 @@ abstract class Pooled {
      * This method is invoked by {@link MarshallerPool} just before to push a
      * (un)marshaller in the pool after its usage.
      *
+     * @param  template The {@link PooledTemplate} from which to get the initial values.
      * @throws JAXBException If an error occurred while restoring a property.
      */
-    public final void reset() throws JAXBException {
+    public final void reset(final Pooled template) throws JAXBException {
         for (final Map.Entry<Object,Object> entry : initialProperties.entrySet()) {
             reset(entry.getKey(), entry.getValue());
         }
         initialProperties.clear();
         bitMasks        = initialBitMasks();
-        locale          = null;
-        timezone        = null;
-        schemas         = null;
-        gmlVersion      = null;
-        resolver        = null;
-        converter       = null;
-        warningListener = null;
+        locale          = template.locale;
+        timezone        = template.timezone;
+        schemas         = template.schemas;
+        gmlVersion      = template.gmlVersion;
+        resolver        = template.resolver;
+        converter       = template.converter;
+        warningListener = template.warningListener;
         resetTime       = System.nanoTime();
     }
 
     /**
      * Resets the given marshaller property to its initial state. This method is invoked
-     * automatically by the {@link #reset()} method. The key is either a {@link String}
+     * automatically by the {@link #reset(Pooled)} method. The key is either a {@link String}
      * or a {@link Class}. If this is a string, then the value shall be given to the
      * {@code setProperty(key, value)} method. Otherwise the value shall be given to
      * {@code setFoo(value)} method where {@code "Foo"} is determined from the key.
@@ -211,8 +240,8 @@ abstract class Pooled {
 
     /**
      * Saves the current value of a property. This method is invoked before a value is
-     * modified for the first time, in order to allow {@link #reset()} to restore the
-     * (un)marshaller to its initial state.
+     * modified for the first time, in order to allow {@link #reset(Pooled)} to restore
+     * the (un)marshaller to its initial state.
      *
      * @param type  The property to save.
      * @param value The current value of the property.
@@ -250,11 +279,11 @@ abstract class Pooled {
         try {
             switch (name) {
                 case XML.LOCALE: {
-                    locale = (Locale) value;
+                    locale = (value instanceof CharSequence) ? Locales.parse(value.toString())
: (Locale) value;
                     return;
                 }
                 case XML.TIMEZONE: {
-                    timezone = (TimeZone) value;
+                    timezone = (value instanceof CharSequence) ? TimeZone.getTimeZone(value.toString())
: (TimeZone) value;
                     return;
                 }
                 case XML.SCHEMAS: {
@@ -308,10 +337,14 @@ abstract class Pooled {
                     return;
                 }
             }
-        } catch (ClassCastException e) {
+        } catch (ClassCastException | IllegalArgumentException e) {
             throw new PropertyException(Errors.format(
                     Errors.Keys.IllegalPropertyClass_2, name, value.getClass()), e);
         }
+        /*
+         * If we reach this point, the given name is not a SIS property. Try to handle
+         * it as a (un)marshaller-specific property, after saving the previous value.
+         */
         name = convertPropertyKey(name);
         if (!initialProperties.containsKey(name)) {
             if (initialProperties.put(name, getStandardProperty(name)) != null) {

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledMarshaller.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledMarshaller.java?rev=1497446&r1=1497445&r2=1497446&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledMarshaller.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledMarshaller.java
[UTF-8] Thu Jun 27 17:03:33 2013
@@ -60,20 +60,21 @@ final class PooledMarshaller extends Poo
 
     /**
      * Creates a pooled marshaller wrapping the given one.
+     * Callers shall invoke {@link #reset(Pooled)} after construction for completing the
initialization.
      *
-     * @param marshaller The marshaller to use for the actual work.
-     * @param internal {@code true} if the JAXB implementation is the one bundled in JDK
6,
-     *        or {@code false} if this is the external implementation provided as a JAR file
-     *        in the endorsed directory.
+     * @param  marshaller The marshaller to use for the actual work.
+     * @param  template The {@link PooledTemplate} from which to get the initial values.
+     * @throws JAXBException If an error occurred while setting a property.
      */
-    PooledMarshaller(final Marshaller marshaller, final boolean internal) {
-        super(internal);
+    PooledMarshaller(final Marshaller marshaller, final Pooled template) throws JAXBException
{
+        super(template);
         this.marshaller = marshaller;
+        initialize(template);
     }
 
     /**
      * Resets the given marshaller property to its initial state.
-     * This method is invoked automatically by {@link #reset()}.
+     * This method is invoked automatically by {@link #reset(Pooled)}.
      *
      * @param  key   The property to reset.
      * @param  value The saved initial value to give to the property.
@@ -238,7 +239,7 @@ final class PooledMarshaller extends Poo
 
     /**
      * Delegates to the wrapped marshaller. The initial state will be saved
-     * if it was not already done, for future restoration by {@link #reset()}.
+     * if it was not already done, for future restoration by {@link #reset(Pooled)}.
      */
     @Override
     @SuppressWarnings("rawtypes")
@@ -258,7 +259,7 @@ final class PooledMarshaller extends Poo
 
     /**
      * Delegates to the wrapped marshaller. The initial state will be saved
-     * if it was not already done, for future restoration by {@link #reset()}.
+     * if it was not already done, for future restoration by {@link #reset(Pooled)}.
      */
     @Override
     public void setSchema(final Schema schema) {
@@ -276,7 +277,7 @@ final class PooledMarshaller extends Poo
 
     /**
      * Delegates to the wrapped marshaller. The initial state will be saved
-     * if it was not already done, for future restoration by {@link #reset()}.
+     * if it was not already done, for future restoration by {@link #reset(Pooled)}.
      */
     @Override
     public void setEventHandler(final ValidationEventHandler handler) throws JAXBException
{
@@ -294,7 +295,7 @@ final class PooledMarshaller extends Poo
 
     /**
      * Delegates to the wrapped marshaller. The initial state will be saved
-     * if it was not already done, for future restoration by {@link #reset()}.
+     * if it was not already done, for future restoration by {@link #reset(Pooled)}.
      */
     @Override
     public void setAttachmentMarshaller(final AttachmentMarshaller am) {
@@ -314,7 +315,7 @@ final class PooledMarshaller extends Poo
 
     /**
      * Delegates to the wrapped marshaller. The initial state will be saved
-     * if it was not already done, for future restoration by {@link #reset()}.
+     * if it was not already done, for future restoration by {@link #reset(Pooled)}.
      */
     @Override
     public void setListener(final Listener listener) {

Added: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java?rev=1497446&view=auto
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java
(added)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java
[UTF-8] Thu Jun 27 17:03:33 2013
@@ -0,0 +1,134 @@
+/*
+ * 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.sis.xml;
+
+import java.util.Map;
+import javax.xml.validation.Schema;
+import javax.xml.bind.PropertyException;
+import javax.xml.bind.ValidationEventHandler;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * The template to use for {@link PooledMarshaller} and {@link PooledUnmarshaller} initialization.
+ * We use this class for parsing {@link XML} property values from the map given by the user
right
+ * at {@link MarshallerPool} construction time. This allow both to catch errors sooner, and
avoid
+ * redoing the conversion every time a new (un)marshaller is requested.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3
+ * @version 0.3
+ * @module
+ */
+final class PooledTemplate extends Pooled {
+    /**
+     * Creates a new template.
+     *
+     * @param properties The properties to be given to JAXB (un)marshallers, or {@code null}
if none.
+     * @param internal {@code true} if the JAXB implementation is the one bundled in JDK
6,
+     *        or {@code false} if this is the external implementation provided as a JAR file
+     *        in the endorsed directory.
+     */
+    PooledTemplate(final Map<String,?> properties, final boolean internal) throws PropertyException
{
+        super(internal);
+        if (properties != null) {
+            for (final Map.Entry<String,?> entry : properties.entrySet()) {
+                setProperty(entry.getKey(), entry.getValue());
+            }
+        }
+    }
+
+    /**
+     * Indirectly invoked by the constructor (through the {@link #setProperty(String, Object)}
method) for storing
+     * a property which is not one of the properties defined in the {@link XML} class. This
method overwrites the
+     * values stored by the super-class, which are only {@code null} because {@link #getStandardProperty(String)}
+     * is implemented that way.
+     */
+    @Override
+    void setStandardProperty(final String name, final Object value) {
+        if (initialProperties.put(name, value) != null) {
+            throw new AssertionError(name); // If non-null, some code has done unexpected
changes in the map.
+        }
+    }
+
+    /**
+     * Indirectly invoked by the constructor as a side-effect of {@link #setProperty(String,
Object)} implementation
+     * in the super-class This method is not of interest to {@code PooledTemplate}. However
as a safety, the above
+     * {@link #setStandardProperty(String, Object)} method will check that the map contains
the value returned here.
+     */
+    @Override
+    Object getStandardProperty(String name) {
+        return null;
+    }
+
+    /**
+     * Remove the given value from the {@link #initialProperties} map.
+     * This method is used for values that are handled especially by the {@link MarshallerPool}
constructor.
+     *
+     * <p>Current implementation expects values of type {@code String}, but this may
be generalized
+     * in a future SIS version if there is a need for that.</p>
+     *
+     * @param  name The name of the property to remove.
+     * @param  defaultValue The default value to return if the given property is not defined
in the map.
+     * @return The old value of that property, or {@code defaultValue} if the given property
was not defined.
+     * @throws PropertyException If the given property is not of the expected type.
+     */
+    String remove(final String name, final String defaultValue) throws PropertyException
{
+        final Object value = initialProperties.remove(name);
+        if (value instanceof String) {
+            return (String) value;
+        }
+        if (value == null) {
+            return defaultValue;
+        }
+        throw new PropertyException(Errors.format(Errors.Keys.IllegalPropertyClass_2, name,
value.getClass()));
+    }
+
+    /**
+     * Should never be invoked on {@code PooledTemplate} instances.
+     */
+    @Override
+    protected void reset(final Object key, final Object value) {
+        throw new AssertionError();
+    }
+
+    /**
+     * Should never be invoked on {@code PooledTemplate} instances.
+     */
+    @Override
+    @SuppressWarnings("rawtypes")
+    public <A extends XmlAdapter> A getAdapter(final Class<A> type) {
+        throw new AssertionError();
+    }
+
+    /**
+     * Should never be invoked on {@code PooledTemplate} instances.
+     */
+    @Override
+    public Schema getSchema() {
+        throw new AssertionError();
+    }
+
+    /**
+     * Should never be invoked on {@code PooledTemplate} instances.
+     */
+    @Override
+    public ValidationEventHandler getEventHandler() {
+        throw new AssertionError();
+    }
+}

Propchange: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledUnmarshaller.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledUnmarshaller.java?rev=1497446&r1=1497445&r2=1497446&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledUnmarshaller.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/PooledUnmarshaller.java
[UTF-8] Thu Jun 27 17:03:33 2013
@@ -63,20 +63,21 @@ final class PooledUnmarshaller extends P
 
     /**
      * Creates a pooled unmarshaller wrapping the given one.
+     * Callers shall invoke {@link #reset(Pooled)} after construction for completing the
initialization.
      *
-     * @param unmarshaller The unmarshaller to use for the actual work.
-     * @param internal {@code true} if the JAXB implementation is the one bundled in JDK
6,
-     *        or {@code false} if this is the external implementation provided as a JAR file
-     *        in the endorsed directory.
+     * @param  unmarshaller The unmarshaller to use for the actual work.
+     * @param  template The {@link PooledTemplate} from which to get the initial values.
+     * @throws JAXBException If an error occurred while setting a property.
      */
-    PooledUnmarshaller(final Unmarshaller unmarshaller, final boolean internal) {
-        super(internal);
+    PooledUnmarshaller(final Unmarshaller unmarshaller, final Pooled template) throws JAXBException
{
+        super(template);
         this.unmarshaller = unmarshaller;
+        initialize(template);
     }
 
     /**
      * Resets the given unmarshaller property to its initial state.
-     * This method is invoked automatically by {@link #reset()}.
+     * This method is invoked automatically by {@link #reset(Pooled)}.
      *
      * @param  key   The property to reset.
      * @param  value The saved initial value to give to the property.
@@ -299,7 +300,7 @@ final class PooledUnmarshaller extends P
 
     /**
      * Delegates to the wrapped unmarshaller. The initial state will be saved
-     * if it was not already done, for future restoration by {@link #reset()}.
+     * if it was not already done, for future restoration by {@link #reset(Pooled)}.
      */
     @Override
     @SuppressWarnings("rawtypes")
@@ -319,7 +320,7 @@ final class PooledUnmarshaller extends P
 
     /**
      * Delegates to the wrapped unmarshaller. The initial state will be saved
-     * if it was not already done, for future restoration by {@link #reset()}.
+     * if it was not already done, for future restoration by {@link #reset(Pooled)}.
      *
      * @deprecated Replaced by {@link #setSchema(javax.xml.validation.Schema)} in JAXB 2.0.
      */
@@ -345,7 +346,7 @@ final class PooledUnmarshaller extends P
 
     /**
      * Delegates to the wrapped unmarshaller. The initial state will be saved
-     * if it was not already done, for future restoration by {@link #reset()}.
+     * if it was not already done, for future restoration by {@link #reset(Pooled)}.
      */
     @Override
     public void setSchema(final Schema schema) {
@@ -363,7 +364,7 @@ final class PooledUnmarshaller extends P
 
     /**
      * Delegates to the wrapped unmarshaller. The initial state will be saved
-     * if it was not already done, for future restoration by {@link #reset()}.
+     * if it was not already done, for future restoration by {@link #reset(Pooled)}.
      */
     @Override
     public void setEventHandler(final ValidationEventHandler handler) throws JAXBException
{
@@ -381,7 +382,7 @@ final class PooledUnmarshaller extends P
 
     /**
      * Delegates to the wrapped unmarshaller. The initial state will be saved
-     * if it was not already done, for future restoration by {@link #reset()}.
+     * if it was not already done, for future restoration by {@link #reset(Pooled)}.
      */
     @Override
     public void setAttachmentUnmarshaller(final AttachmentUnmarshaller au) {
@@ -401,7 +402,7 @@ final class PooledUnmarshaller extends P
 
     /**
      * Delegates to the wrapped marshaller. The initial state will be saved
-     * if it was not already done, for future restoration by {@link #reset()}.
+     * if it was not already done, for future restoration by {@link #reset(Pooled)}.
      */
     @Override
     public void setListener(final Listener listener) {

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/XMLComparator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/XMLComparator.java?rev=1497446&r1=1497445&r2=1497446&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/XMLComparator.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/XMLComparator.java
[UTF-8] Thu Jun 27 17:03:33 2013
@@ -72,7 +72,6 @@ import static org.apache.sis.util.CharSe
  * @module
  *
  * @see XMLTestCase
- * @see XMLTransformation
  * @see Assert#assertXmlEquals(Object, Object, String[])
  */
 public strictfp class XMLComparator {

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/XMLTestCase.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/XMLTestCase.java?rev=1497446&r1=1497445&r2=1497446&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/XMLTestCase.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/test/XMLTestCase.java
[UTF-8] Thu Jun 27 17:03:33 2013
@@ -39,7 +39,6 @@ import static org.junit.Assert.*;
  * @module
  *
  * @see XMLComparator
- * @see XMLTransformation
  */
 public abstract strictfp class XMLTestCase extends TestCase {
     /**

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/iso/NameMarshallingTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/iso/NameMarshallingTest.java?rev=1497446&r1=1497445&r2=1497446&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/iso/NameMarshallingTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/iso/NameMarshallingTest.java
[UTF-8] Thu Jun 27 17:03:33 2013
@@ -49,7 +49,9 @@ import static org.apache.sis.test.Assert
 @DependsOn(DefaultNameFactoryTest.class)
 public final strictfp class NameMarshallingTest extends XMLTestCase {
     /**
-     * The JAXB context, created when first needed.
+     * A poll of configured {@link Marshaller} and {@link Unmarshaller}, created when first
needed.
+     *
+     * @see #disposeMarshallerPool()
      */
     private static MarshallerPool pool;
 



Mime
View raw message