wink-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b...@apache.org
Subject svn commit: r935346 - in /incubator/wink/trunk: wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/ wink-common/src/main/java/org/apache/wink/common/internal/utils/ wink-common/src/main/java/org/apache/wink/common/model/ win...
Date Sun, 18 Apr 2010 14:44:52 GMT
Author: bluk
Date: Sun Apr 18 14:44:52 2010
New Revision: 935346

URL: http://svn.apache.org/viewvc?rev=935346&view=rev
Log:
Add JAXBUnmarshalOption to set properties

This is a mirror of XmlFormattingOptions
except for JAXB unmarshallers.

See [WINK-224].

Thanks to Ajiyos Yohannan for the
suggestion.

Added:
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/model/JAXBUnmarshalOptions.java
  (with props)
    incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalNoOptionsTest.java
  (with props)
    incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalOptionsTest.java
  (with props)
Modified:
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBCollectionProvider.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBProvider.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/JAXBElementXmlProvider.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/JAXBXmlProvider.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/JAXBUtils.java
    incubator/wink/trunk/wink-providers/wink-jettison-provider/src/main/java/org/apache/wink/providers/jettison/JettisonJAXBElementProvider.java
    incubator/wink/trunk/wink-providers/wink-jettison-provider/src/main/java/org/apache/wink/providers/jettison/JettisonJAXBProvider.java

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBCollectionProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBCollectionProvider.java?rev=935346&r1=935345&r2=935346&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBCollectionProvider.java
(original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBCollectionProvider.java
Sun Apr 18 14:44:52 2010
@@ -30,14 +30,11 @@ import java.lang.reflect.Type;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
@@ -59,8 +56,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public abstract class AbstractJAXBCollectionProvider extends AbstractJAXBProvider {
-    private static final String JAXB_DEFAULT_NAMESPACE = "##default"; //$NON-NLS-1$
-    private static final String JAXB_DEFAULT_NAME      = "##default"; //$NON-NLS-1$
+    private static final String JAXB_DEFAULT_NAMESPACE = "##default";                   
                       //$NON-NLS-1$
+    private static final String JAXB_DEFAULT_NAME      = "##default";                   
                       //$NON-NLS-1$
     private static final Logger logger                 =
                                                            LoggerFactory
                                                                .getLogger(AbstractJAXBCollectionProvider.class);
@@ -76,7 +73,7 @@ public abstract class AbstractJAXBCollec
             XMLStreamReader xsr = xmif.createXMLStreamReader(entityStream);
             Class<?> theType = getParameterizedTypeClass(type, genericType, true);
             JAXBContext context = getContext(theType, mediaType);
-            Unmarshaller unmarshaller = getJAXBUnmarshaller(context);
+            Unmarshaller unmarshaller = getJAXBUnmarshaller(type, context, mediaType);
 
             int nextEvent = xsr.next();
             while (nextEvent != XMLStreamReader.START_ELEMENT)
@@ -152,14 +149,14 @@ public abstract class AbstractJAXBCollec
             Marshaller marshaller = null;
             JAXBContext context = null;
             for (Object o : elementArray) {
-                if(marshaller == null) {
+                if (marshaller == null) {
                     Class<?> oType =
                         isJAXBElement ? ((JAXBElement<?>)o).getDeclaredType() : o.getClass();
-                        context = getContext(oType, mediaType);
-                        marshaller = getJAXBMarshaller(oType, context, mediaType);
-                        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
-                        Charset charSet = getCharSet(mediaType);
-                        marshaller.setProperty(Marshaller.JAXB_ENCODING, charSet.name());
+                    context = getContext(oType, mediaType);
+                    marshaller = getJAXBMarshaller(oType, context, mediaType);
+                    marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
+                    Charset charSet = getCharSet(mediaType);
+                    marshaller.setProperty(Marshaller.JAXB_ENCODING, charSet.name());
                 }
                 Object entityToMarshal = getEntityToMarshal(o, theType);
                 if (qname == null) {
@@ -221,8 +218,8 @@ public abstract class AbstractJAXBCollec
     }
 
     public static Class<?> getParameterizedTypeClass(Class<?> type,
-                                                        Type genericType,
-                                                        boolean recurse) {
+                                                     Type genericType,
+                                                     boolean recurse) {
         if (Collection.class.isAssignableFrom(type)) {
             if (genericType instanceof ParameterizedType) {
                 ParameterizedType parameterizedType = (ParameterizedType)genericType;

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBProvider.java?rev=935346&r1=935345&r2=935346&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBProvider.java
(original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBProvider.java
Sun Apr 18 14:44:52 2010
@@ -49,6 +49,7 @@ import org.apache.wink.common.internal.i
 import org.apache.wink.common.internal.utils.JAXBUtils;
 import org.apache.wink.common.internal.utils.MediaTypeUtils;
 import org.apache.wink.common.internal.utils.SoftConcurrentMap;
+import org.apache.wink.common.model.JAXBUnmarshalOptions;
 import org.apache.wink.common.model.XmlFormattingOptions;
 import org.apache.wink.common.utils.ProviderUtils;
 import org.slf4j.Logger;
@@ -74,30 +75,35 @@ public abstract class AbstractJAXBProvid
     // the Pool code for the pooling of unmarshallers is from Axis2 Java
     // http://svn.apache.org/repos/asf/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java
     //
-    // These pools should *not* be static in Wink, however, because the (un)marshallers are
unique per JAXBContext instance, each
-    // of which is unique per class object being (un)marshalled.  In Axis2, the JAXBContext
instances cover the entire application space, thus
+    // These pools should *not* be static in Wink, however, because the
+    // (un)marshallers are unique per JAXBContext instance, each
+    // of which is unique per class object being (un)marshalled. In Axis2, the
+    // JAXBContext instances cover the entire application space, thus
     // it was safe to cache them in a static field.
-    private Pool<JAXBContext, Marshaller>                  mpool                  
  =
+    private Pool<JAXBContext, Marshaller>                         mpool           
         =
                                                                                         
       new Pool<JAXBContext, Marshaller>();
-    private Pool<JAXBContext, Unmarshaller>                upool                  
  =
+    private Pool<JAXBContext, Unmarshaller>                       upool           
         =
                                                                                         
       new Pool<JAXBContext, Unmarshaller>();
 
     /**
-     * This class is the key to the JAXBContext cache.  It must be based on the ContextResolver
instance who created
-     * the JAXBContext and the type passed to it.  The only way this cache becomes invalid
is if the ContextResolver does
-     * something crazy like create JAXBContexts based on time -- it only creates contexts
between noon and 5:00pm.  So, uhhh,
-     * don't do that.
+     * This class is the key to the JAXBContext cache. It must be based on the
+     * ContextResolver instance who created the JAXBContext and the type passed
+     * to it. The only way this cache becomes invalid is if the ContextResolver
+     * does something crazy like create JAXBContexts based on time -- it only
+     * creates contexts between noon and 5:00pm. So, uhhh, don't do that.
      */
     private static class JAXBContextResolverKey {
         protected ContextResolver<JAXBContext> _resolver;
-        protected Type _type;
-        private int hashCode = -1;
+        protected Type                         _type;
+        private int                            hashCode = -1;
+
         public JAXBContextResolverKey(ContextResolver<JAXBContext> resolver, Type type)
{
-            // resolver may be null, which is ok; we'll protect against NPEs in equals and
hashCode overrides
+            // resolver may be null, which is ok; we'll protect against NPEs in
+            // equals and hashCode overrides
             _resolver = resolver;
             _type = type;
         }
-        
+
         @Override
         public boolean equals(Object o) {
             if ((o == null) || (!(o instanceof JAXBContextResolverKey))) {
@@ -105,7 +111,8 @@ public abstract class AbstractJAXBProvid
             }
             JAXBContextResolverKey obj = (JAXBContextResolverKey)o;
             // check for both null or both NOT null
-            boolean result = ((obj._resolver == null) && (_resolver == null)) ||
((obj._resolver != null) && (_resolver != null));
+            boolean result =
+                ((obj._resolver == null) && (_resolver == null)) || ((obj._resolver
!= null) && (_resolver != null));
             // we can use hashCode() to compare _resolver
             return result && (obj.hashCode() == hashCode()) && (obj._type.equals(_type));
         }
@@ -116,14 +123,21 @@ public abstract class AbstractJAXBProvid
                 return hashCode;
             }
             if (_resolver == null) {
-                // allow the key to be based entirely on the _type object equality from equals
method.  Only YOU can prevent NPEs.
-                hashCode = 0;  // don't use _type's hashCode, as the instances may differ
between JAXBContextResolverKey instances
+                // allow the key to be based entirely on the _type object
+                // equality from equals method. Only YOU can prevent NPEs.
+                hashCode = 0; // don't use _type's hashCode, as the instances
+                // may differ between JAXBContextResolverKey
+                // instances
                 return hashCode;
             }
-            // Resolver instances may be unique due to the way we proxy the call to get the
instances in the ProvidersRegistry.
-            // Therefore, we'll get better performance if we calculate the hashCode from
the package.classname of the ContextResolver.
-            // However, this means we need to make sure the map that uses this key is non-static,
so it remains scoped at the
-            // transaction level, rather than at the application, or worse, JVM level.
+            // Resolver instances may be unique due to the way we proxy the call
+            // to get the instances in the ProvidersRegistry.
+            // Therefore, we'll get better performance if we calculate the
+            // hashCode from the package.classname of the ContextResolver.
+            // However, this means we need to make sure the map that uses this
+            // key is non-static, so it remains scoped at the
+            // transaction level, rather than at the application, or worse, JVM
+            // level.
             String resolverName = _resolver.getClass().getName();
             byte[] bytes = resolverName.getBytes();
             for (int i = 0; i < bytes.length; i++) {
@@ -131,25 +145,33 @@ public abstract class AbstractJAXBProvid
             }
             return hashCode;
         }
-        
+
     }
-    
+
     /*
-     * TODO: in my small, uncontrolled test, the JVM (garbage collector?) was cleaning about
10% of the time.  It may be worth
-     * considering the use of LRU cache or something more directly under our control to gain
more of that.
-     * 
-     * To observe this behavior, set the "loop" int in JAXBCustomContextResolverCacheTest.testCustomResolverCacheOn
to a high
-     * number, and see the System.out for cacheMisses.  In my checking, it was about 10%
of "loop".
+     * TODO: in my small, uncontrolled test, the JVM (garbage collector?) was
+     * cleaning about 10% of the time. It may be worth considering the use of
+     * LRU cache or something more directly under our control to gain more of
+     * that. To observe this behavior, set the "loop" int in
+     * JAXBCustomContextResolverCacheTest.testCustomResolverCacheOn to a high
+     * number, and see the System.out for cacheMisses. In my checking, it was
+     * about 10% of "loop".
      */
-    // do not make static, as the key is based on the classname of the ContextResolver
-    private final SoftConcurrentMap<JAXBContextResolverKey, JAXBContext> jaxbContextCache
= new SoftConcurrentMap<JAXBContextResolverKey, JAXBContext>();
-    
+    // do not make static, as the key is based on the classname of the
+    // ContextResolver
+    private final SoftConcurrentMap<JAXBContextResolverKey, JAXBContext> jaxbContextCache
=
+                                                                                        
     new SoftConcurrentMap<JAXBContextResolverKey, JAXBContext>();
+
     // JAXBContext cache can be turned off through system property
-    static private final String propVal = System.getProperty("org.apache.wink.jaxbcontextcache");
+    static private final String                                          propVal        
 =
+                                                                                        
     System
+                                                                                        
         .getProperty("org.apache.wink.jaxbcontextcache");
     // non-final, protected only to make it unittestable
-    static protected boolean contextCacheOn = !((propVal != null) && (propVal.equalsIgnoreCase("off")));
-    
-    /**
+    static protected boolean                                             contextCacheOn 
 =
+                                                                                        
     !((propVal != null) && (propVal
+                                                                                        
         .equalsIgnoreCase("off")));
+
+/**
      * Get the unmarshaller. You must call {@link #releaseJAXBUnmarshaller(JAXBContext, Unmarshaller)
to put it back
      * into the pool.
      * 
@@ -157,7 +179,9 @@ public abstract class AbstractJAXBProvid
      * @return Unmarshaller an unmarshaller for the context
      * @throws JAXBException
      */
-    protected final Unmarshaller getJAXBUnmarshaller(JAXBContext context) throws JAXBException
{
+    protected final Unmarshaller getJAXBUnmarshaller(Class<?> type,
+                                                     JAXBContext context,
+                                                     MediaType mediaType) throws JAXBException
{
         Unmarshaller unm = upool.get(context);
         if (unm == null) {
             if (logger.isDebugEnabled()) {
@@ -169,6 +193,19 @@ public abstract class AbstractJAXBProvid
                 logger.debug("Unmarshaller obtained [from  pool]"); //$NON-NLS-1$
             }
         }
+
+        if (providers != null) {
+            ContextResolver<JAXBUnmarshalOptions> contextResolver =
+                providers.getContextResolver(JAXBUnmarshalOptions.class, mediaType);
+            JAXBUnmarshalOptions options = null;
+            if (contextResolver != null) {
+                options = contextResolver.getContext(type);
+            }
+            if (options != null) {
+                JAXBUtils.setJAXBUnmarshalOptions(unm, options);
+            }
+        }
+
         return unm;
     }
 
@@ -321,23 +358,25 @@ public abstract class AbstractJAXBProvid
         return getContext(type, type, mediaType);
     }
 
-    protected JAXBContext getContext(Class<?> type, Type genericType, MediaType mediaType)
throws JAXBException {
-        
+    protected JAXBContext getContext(Class<?> type, Type genericType, MediaType mediaType)
+        throws JAXBException {
+
         ContextResolver<JAXBContext> contextResolver =
             providers.getContextResolver(JAXBContext.class, mediaType);
-        
+
         JAXBContext context = null;
-        
+
         JAXBContextResolverKey key = null;
         if (contextCacheOn) {
-            // it's ok and safe for contextResolver to be null at this point.  JAXBContextResolverKey
can handle it
+            // it's ok and safe for contextResolver to be null at this point.
+            // JAXBContextResolverKey can handle it
             key = new JAXBContextResolverKey(contextResolver, type);
             context = jaxbContextCache.get(key);
             if (context != null) {
                 return context;
             }
         }
-        
+
         if (contextResolver != null) {
             context = contextResolver.getContext(type);
         }
@@ -345,23 +384,29 @@ public abstract class AbstractJAXBProvid
         if (context == null) {
             context = getDefaultContext(type, genericType);
         }
-        
+
         if (contextCacheOn) {
             jaxbContextCache.put(key, context);
         }
-        
+
         return context;
     }
 
     private JAXBContext getDefaultContext(Class<?> type, Type genericType) throws JAXBException
{
         JAXBContext context = jaxbDefaultContexts.get(type);
         if (context == null) {
-            
-            // CAUTION: be careful with this.  Adding a second or more classes to the JAXBContext
has the side
-            // effect of putting a namespace prefix and the namespace decl on the subelements
of the 
+
+            // CAUTION: be careful with this. Adding a second or more classes to
+            // the JAXBContext has the side
+            // effect of putting a namespace prefix and the namespace decl on
+            // the subelements of the
             // desired type, thus degrading performance.
-            
-            if(!isXMLRootElement(type) && !isXMLType(type)) {  // use genericType.
If that fails, we'll know soon enough
+
+            if (!isXMLRootElement(type) && !isXMLType(type)) { // use
+                // genericType.
+                // If that fails,
+                // we'll know
+                // soon enough
                 context = JAXBContext.newInstance((Class<?>)genericType);
             } else {
                 context = JAXBContext.newInstance(type);
@@ -474,8 +519,7 @@ public abstract class AbstractJAXBProvid
         /**
          * Maximum number of JAXBContexts to store
          */
-        private static int                                            MAX_LOAD_FACTOR   
       = 32;
-
+        private static int                                        MAX_LOAD_FACTOR = 32;
 
         /** The maps are freed up when a LOAD FACTOR is hit */
         private static int                                        MAX_LIST_FACTOR = 50;

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/JAXBElementXmlProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/JAXBElementXmlProvider.java?rev=935346&r1=935345&r2=935346&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/JAXBElementXmlProvider.java
(original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/JAXBElementXmlProvider.java
Sun Apr 18 14:44:52 2010
@@ -27,13 +27,10 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.nio.charset.Charset;
-import java.util.HashMap;
-import java.util.Map;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.Produces;
 import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
@@ -82,7 +79,7 @@ public class JAXBElementXmlProvider exte
 
         try {
             JAXBContext context = getContext(classToFill, mediaType);
-            unmarshaller = getJAXBUnmarshaller(context);
+            unmarshaller = getJAXBUnmarshaller(type, context, mediaType);
             String charset = ProviderUtils.getCharsetOrNull(mediaType);
             if (charset == null) {
                 // use default

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/JAXBXmlProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/JAXBXmlProvider.java?rev=935346&r1=935345&r2=935346&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/JAXBXmlProvider.java
(original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/JAXBXmlProvider.java
Sun Apr 18 14:44:52 2010
@@ -24,13 +24,10 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.Produces;
 import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
@@ -75,7 +72,7 @@ public class JAXBXmlProvider extends Abs
         Object unmarshaledResource = null;
         try {
             JAXBContext context = getContext(type, mediaType);
-            unmarshaller = getJAXBUnmarshaller(context);
+            unmarshaller = getJAXBUnmarshaller(type, context, mediaType);
             if (type.isAnnotationPresent(XmlRootElement.class)) {
                 unmarshaledResource = unmarshaller.unmarshal(entityStream);
                 if (unmarshaledResource instanceof JAXBElement) {

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/JAXBUtils.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/JAXBUtils.java?rev=935346&r1=935345&r2=935346&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/JAXBUtils.java
(original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/JAXBUtils.java
Sun Apr 18 14:44:52 2010
@@ -27,6 +27,7 @@ import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
 
+import org.apache.wink.common.model.JAXBUnmarshalOptions;
 import org.apache.wink.common.model.XmlFormattingOptions;
 
 public class JAXBUtils {
@@ -71,4 +72,18 @@ public class JAXBUtils {
         }
     }
 
+    public static void setJAXBUnmarshalOptions(Unmarshaller unmarshaller,
+                                               JAXBUnmarshalOptions options) {
+        if (options == null) {
+            return;
+        }
+        try {
+            Map<String, Object> properties = options.getProperties();
+            for (String key : properties.keySet()) {
+                unmarshaller.setProperty(key, properties.get(key));
+            }
+        } catch (Exception e) {
+            throw new WebApplicationException(e);
+        }
+    }
 }

Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/model/JAXBUnmarshalOptions.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/model/JAXBUnmarshalOptions.java?rev=935346&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/model/JAXBUnmarshalOptions.java
(added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/model/JAXBUnmarshalOptions.java
Sun Apr 18 14:44:52 2010
@@ -0,0 +1,35 @@
+/*
+ * 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.wink.common.model;
+
+import java.util.Map;
+
+public class JAXBUnmarshalOptions {
+
+    private final Map<String, Object> properties;
+
+    public JAXBUnmarshalOptions(Map<String, Object> properties) {
+        this.properties = properties;
+    }
+
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+}

Propchange: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/model/JAXBUnmarshalOptions.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/wink/trunk/wink-providers/wink-jettison-provider/src/main/java/org/apache/wink/providers/jettison/JettisonJAXBElementProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-providers/wink-jettison-provider/src/main/java/org/apache/wink/providers/jettison/JettisonJAXBElementProvider.java?rev=935346&r1=935345&r2=935346&view=diff
==============================================================================
--- incubator/wink/trunk/wink-providers/wink-jettison-provider/src/main/java/org/apache/wink/providers/jettison/JettisonJAXBElementProvider.java
(original)
+++ incubator/wink/trunk/wink-providers/wink-jettison-provider/src/main/java/org/apache/wink/providers/jettison/JettisonJAXBElementProvider.java
Sun Apr 18 14:44:52 2010
@@ -135,7 +135,7 @@ public class JettisonJAXBElementProvider
 
         try {
             JAXBContext context = getContext(classToFill, mediaType);
-            unmarshaller = getJAXBUnmarshaller(context);
+            unmarshaller = getJAXBUnmarshaller(type, context, mediaType);
 
             XMLStreamReader xsr = null;
             if (isBadgerFishConventionUsed) {

Modified: incubator/wink/trunk/wink-providers/wink-jettison-provider/src/main/java/org/apache/wink/providers/jettison/JettisonJAXBProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-providers/wink-jettison-provider/src/main/java/org/apache/wink/providers/jettison/JettisonJAXBProvider.java?rev=935346&r1=935345&r2=935346&view=diff
==============================================================================
--- incubator/wink/trunk/wink-providers/wink-jettison-provider/src/main/java/org/apache/wink/providers/jettison/JettisonJAXBProvider.java
(original)
+++ incubator/wink/trunk/wink-providers/wink-jettison-provider/src/main/java/org/apache/wink/providers/jettison/JettisonJAXBProvider.java
Sun Apr 18 14:44:52 2010
@@ -100,7 +100,8 @@ public class JettisonJAXBProvider extend
             this.outputConfiguration = new Configuration(new HashMap<String, String>());
         }
 
-        // see http://jira.codehaus.org/browse/JETTISON-74 . reading disabled for now
+        // see http://jira.codehaus.org/browse/JETTISON-74 . reading disabled
+        // for now
         isReadable = false;
         isWritable = true;
     }
@@ -130,7 +131,7 @@ public class JettisonJAXBProvider extend
         Object unmarshaledResource = null;
         try {
             JAXBContext context = getContext(type, mediaType);
-            unmarshaller = getJAXBUnmarshaller(context);
+            unmarshaller = getJAXBUnmarshaller(type, context, mediaType);
 
             XMLStreamReader xsr = null;
 
@@ -139,17 +140,22 @@ public class JettisonJAXBProvider extend
             } else {
                 xsr =
                     new MappedXMLInputFactory(inputConfiguration)
-                .createXMLStreamReader(entityStream);
+                        .createXMLStreamReader(entityStream);
             }
 
             if (type.isAnnotationPresent(XmlRootElement.class)) {
                 unmarshaledResource = unmarshaller.unmarshal(xsr);
                 if (unmarshaledResource instanceof JAXBElement) {
-                    // this can happen if the JAXBContext object used to create the unmarshaller
-                    // was created using the package name string instead of a class object
and the
-                    // ObjectFactory has a creator method for the desired object that returns
-                    // JAXBElement.  But we know better; the 'type' param passed in here
had the
-                    // XmlRootElement on it, so we know the desired return object type is
NOT
+                    // this can happen if the JAXBContext object used to create
+                    // the unmarshaller
+                    // was created using the package name string instead of a
+                    // class object and the
+                    // ObjectFactory has a creator method for the desired object
+                    // that returns
+                    // JAXBElement. But we know better; the 'type' param passed
+                    // in here had the
+                    // XmlRootElement on it, so we know the desired return
+                    // object type is NOT
                     // JAXBElement, thus:
                     unmarshaledResource = ((JAXBElement)unmarshaledResource).getValue();
                 }

Added: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalNoOptionsTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalNoOptionsTest.java?rev=935346&view=auto
==============================================================================
--- incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalNoOptionsTest.java
(added)
+++ incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalNoOptionsTest.java
Sun Apr 18 14:44:52 2010
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * 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.wink.server.internal.providers.entity;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlID;
+import javax.xml.bind.annotation.XmlIDREF;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.wink.common.model.JAXBUnmarshalOptions;
+import org.apache.wink.server.internal.servlet.MockServletInvocationTest;
+import org.apache.wink.test.mock.MockRequestConstructor;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.xml.sax.SAXException;
+
+import com.sun.xml.bind.IDResolver;
+
+/**
+ * Adding a JAXBUnmarshalOptions allows JAXB unmarshallers to have properties
+ * set on them.
+ */
+public class JAXBUnmarshalNoOptionsTest extends MockServletInvocationTest {
+    public static class Book {
+        @XmlID
+        @XmlAttribute
+        public String id;
+    }
+
+    public static class BookLink {
+        @XmlIDREF
+        @XmlAttribute
+        public Book idref;
+    }
+
+    public static class Author {
+        @XmlID
+        @XmlAttribute
+        public String id;
+    }
+
+    public static class AuthorLink {
+        @XmlIDREF
+        @XmlAttribute
+        public Author idref;
+    }
+
+    @XmlRootElement
+    public static class Bookstore {
+        @XmlElements( {@XmlElement(name = "book", type = Book.class),
+            @XmlElement(name = "author", type = Author.class),
+            @XmlElement(name = "bookLink", type = BookLink.class),
+            @XmlElement(name = "authorLink", type = AuthorLink.class)})
+        public List<Object> items;
+    }
+
+    @Provider
+    public static class BooksContextResolver implements ContextResolver<JAXBContext>
{
+
+        public JAXBContext getContext(Class<?> arg0) {
+            if (Bookstore.class.equals(arg0)) {
+                try {
+                    return JAXBContext.newInstance(Bookstore.class,
+                                                   Author.class,
+                                                   AuthorLink.class,
+                                                   Book.class,
+                                                   BookLink.class);
+
+                } catch (JAXBException e) {
+                    throw new WebApplicationException(e);
+                }
+            }
+            return null;
+        }
+
+    }
+
+    @Override
+    protected Class<?>[] getClasses() {
+        return new Class<?>[] {RootResource.class, BooksContextResolver.class};
+    }
+
+    @Path("/root")
+    public static class RootResource {
+
+        @POST
+        @Produces("application/xml")
+        public String post(Bookstore b) {
+            assertTrue(b != null);
+            assertTrue(b.items != null);
+            assertEquals(6, b.items.size());
+
+            Book book = (Book)b.items.get(2);
+            assertEquals("abcd", book.id);
+            BookLink bookLink = (BookLink)b.items.get(0);
+            /*
+             * note the difference here between having a unmarshal option and
+             * not is the idref here
+             */
+            assertNull(bookLink.idref);
+
+            Author author = (Author)b.items.get(3);
+            assertEquals("abcd", author.id);
+            AuthorLink authorLink = (AuthorLink)b.items.get(1);
+            assertSame(author, authorLink.idref);
+
+            Book book2 = (Book)b.items.get(4);
+            assertEquals("lmnop", book2.id);
+            BookLink bookLink2 = (BookLink)b.items.get(5);
+            assertSame(book2, bookLink2.idref);
+
+            return "hello";
+        }
+
+    }
+
+    public void testGenericEntityAnnotatedJAXB() throws Exception {
+        MockHttpServletRequest request =
+            MockRequestConstructor
+                .constructMockRequest("POST",
+                                      "/root",
+                                      MediaType.APPLICATION_XML,
+                                      MediaType.APPLICATION_XML,
+                                      /*
+                                       * note order of elements matter for test
+                                       */
+                                      ("<bookstore>" + "<bookLink idref=\"abcd\"/>"
+                                          + "<authorLink idref=\"abcd\"/>"
+
+                                          + "<book id=\"abcd\"/>"
+                                          + "<author id=\"abcd\"/>"
+
+                                          + "<book id=\"lmnop\"/>"
+                                          + "<bookLink idref=\"lmnop\"/>"
+
+                                          + "</bookstore>").getBytes());
+        MockHttpServletResponse response = invoke(request);
+        assertEquals(200, response.getStatus());
+        assertEquals("hello", response.getContentAsString());
+    }
+
+}

Propchange: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalNoOptionsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalOptionsTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalOptionsTest.java?rev=935346&view=auto
==============================================================================
--- incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalOptionsTest.java
(added)
+++ incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalOptionsTest.java
Sun Apr 18 14:44:52 2010
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * 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.wink.server.internal.providers.entity;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlID;
+import javax.xml.bind.annotation.XmlIDREF;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.wink.common.model.JAXBUnmarshalOptions;
+import org.apache.wink.server.internal.servlet.MockServletInvocationTest;
+import org.apache.wink.test.mock.MockRequestConstructor;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.xml.sax.SAXException;
+
+import com.sun.xml.bind.IDResolver;
+
+/**
+ * Adding a JAXBUnmarshalOptions allows JAXB unmarshallers to have properties
+ * set on them.
+ */
+public class JAXBUnmarshalOptionsTest extends MockServletInvocationTest {
+    public static class Book {
+        @XmlID
+        @XmlAttribute
+        public String id;
+    }
+
+    public static class BookLink {
+        @XmlIDREF
+        @XmlAttribute
+        public Book idref;
+    }
+
+    public static class Author {
+        @XmlID
+        @XmlAttribute
+        public String id;
+    }
+
+    public static class AuthorLink {
+        @XmlIDREF
+        @XmlAttribute
+        public Author idref;
+    }
+
+    @XmlRootElement
+    public static class Bookstore {
+        @XmlElements( {@XmlElement(name = "book", type = Book.class),
+            @XmlElement(name = "author", type = Author.class),
+            @XmlElement(name = "bookLink", type = BookLink.class),
+            @XmlElement(name = "authorLink", type = AuthorLink.class)})
+        public List<Object> items;
+    }
+
+    @Provider
+    public static class BooksContextResolver implements ContextResolver<JAXBContext>
{
+
+        public JAXBContext getContext(Class<?> arg0) {
+            if (Bookstore.class.equals(arg0)) {
+                try {
+                    return JAXBContext.newInstance(Bookstore.class,
+                                                   Author.class,
+                                                   AuthorLink.class,
+                                                   Book.class,
+                                                   BookLink.class);
+
+                } catch (JAXBException e) {
+                    throw new WebApplicationException(e);
+                }
+            }
+            return null;
+        }
+    }
+
+    public static class MyIDResolver extends IDResolver {
+
+        private Map<String, Book>   books   = new HashMap<String, Book>();
+        private Map<String, Author> authors = new HashMap<String, Author>();
+
+        @Override
+        public void bind(String arg0, Object arg1) throws SAXException {
+            if (arg1 instanceof Book) {
+                books.put(arg0, (Book)arg1);
+            } else if (arg1 instanceof Author) {
+                authors.put(arg0, (Author)arg1);
+            }
+        }
+
+        @Override
+        public Callable<?> resolve(final String arg0, final Class arg1) throws SAXException
{
+            return new Callable<Object>() {
+                public Object call() {
+                    if (arg1.equals(Book.class)) {
+                        return books.get(arg0);
+                    } else if (arg1.equals(Author.class)) {
+                        return authors.get(arg0);
+                    }
+                    return null;
+                }
+            };
+        }
+
+    }
+
+    @Provider
+    public static class MyIDResolverContextResolver implements
+        ContextResolver<JAXBUnmarshalOptions> {
+
+        public JAXBUnmarshalOptions getContext(Class<?> arg0) {
+            if (Bookstore.class.equals(arg0)) {
+                Map<String, Object> properties = new HashMap<String, Object>();
+                properties.put(IDResolver.class.getName(), new MyIDResolver());
+                return new JAXBUnmarshalOptions(properties);
+            }
+            return null;
+        }
+
+    }
+
+    @Override
+    protected Class<?>[] getClasses() {
+        return new Class<?>[] {RootResource.class, BooksContextResolver.class,
+            MyIDResolverContextResolver.class};
+    }
+
+    @Path("/root")
+    public static class RootResource {
+
+        @POST
+        @Produces("application/xml")
+        public String post(Bookstore b) {
+            assertTrue(b != null);
+            assertTrue(b.items != null);
+            assertEquals(6, b.items.size());
+
+            Book book = (Book)b.items.get(2);
+            assertEquals("abcd", book.id);
+            BookLink bookLink = (BookLink)b.items.get(0);
+            /*
+             * note the difference here between having a unmarshal option and
+             * not is the idref here
+             */
+            assertSame(book, bookLink.idref);
+
+            Author author = (Author)b.items.get(3);
+            assertEquals("abcd", author.id);
+            AuthorLink authorLink = (AuthorLink)b.items.get(1);
+            assertSame(author, authorLink.idref);
+
+            Book book2 = (Book)b.items.get(4);
+            assertEquals("lmnop", book2.id);
+            BookLink bookLink2 = (BookLink)b.items.get(5);
+            assertSame(book2, bookLink2.idref);
+
+            return "hello";
+        }
+
+    }
+
+    public void testGenericEntityAnnotatedJAXB() throws Exception {
+        MockHttpServletRequest request =
+            MockRequestConstructor
+                .constructMockRequest("POST",
+                                      "/root",
+                                      MediaType.APPLICATION_XML,
+                                      MediaType.APPLICATION_XML,
+                                      /*
+                                       * note order of elements matter for test
+                                       */
+                                      ("<bookstore>" + "<bookLink idref=\"abcd\"/>"
+                                          + "<authorLink idref=\"abcd\"/>"
+
+                                          + "<book id=\"abcd\"/>"
+                                          + "<author id=\"abcd\"/>"
+
+                                          + "<book id=\"lmnop\"/>"
+                                          + "<bookLink idref=\"lmnop\"/>"
+
+                                          + "</bookstore>").getBytes());
+        MockHttpServletResponse response = invoke(request);
+        assertEquals(200, response.getStatus());
+        assertEquals("hello", response.getContentAsString());
+    }
+
+}

Propchange: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBUnmarshalOptionsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message