[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wink-commits
Subject:    svn commit: r927462 - in /incubator/wink/trunk: ./
From:       rott () apache ! org
Date:       2010-03-25 15:58:08
Message-ID: 20100325155809.16DE72388A36 () eris ! apache ! org
[Download RAW message or body]

Author: rott
Date: Thu Mar 25 15:58:08 2010
New Revision: 927462

URL: http://svn.apache.org/viewvc?rev=927462&view=rev
Log:
WINK-219: best-effort to support JAXB inherited types

Added:
    incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBProviderInheritanceTest.java
 Modified:
    incubator/wink/trunk/   (props changed)
    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/JAXBXmlProvider.java
  incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBCollectionXMLProviderTest.java


Propchange: incubator/wink/trunk/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Thu Mar 25 15:58:08 2010
@@ -3,3 +3,4 @@ target
 dir_conflicts.prej
 .settings
 .classpath
+.metadata

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/a \
pache/wink/common/internal/providers/entity/xml/AbstractJAXBProvider.java?rev=927462&r1=927461&r2=927462&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 \
Thu Mar 25 15:58:08 2010 @@ -277,6 +277,15 @@ public abstract class \
AbstractJAXBProvid  }
 
     public static boolean isJAXBObject(Class<?> type, Type genericType) {
+        if (isJAXBObject(type)) {
+            return true;
+        } else if (genericType instanceof Class<?>) {
+            return isJAXBObject((Class<?>)genericType);
+        }
+        return false;
+    }
+
+    public static boolean isJAXBObject(Class<?> type) {
         return isXMLRootElement(type) || isXMLType(type);
     }
 
@@ -309,6 +318,10 @@ public abstract class AbstractJAXBProvid
     }
 
     protected JAXBContext getContext(Class<?> type, MediaType mediaType) throws \
JAXBException { +        return getContext(type, type, mediaType);
+    }
+
+    protected JAXBContext getContext(Class<?> type, Type genericType, MediaType \
mediaType) throws JAXBException {  
         ContextResolver<JAXBContext> contextResolver =
             providers.getContextResolver(JAXBContext.class, mediaType);
@@ -330,7 +343,7 @@ public abstract class AbstractJAXBProvid
         }
 
         if (context == null) {
-            context = getDefaultContext(type);
+            context = getDefaultContext(type, genericType);
         }
         
         if (contextCacheOn) {
@@ -340,10 +353,20 @@ public abstract class AbstractJAXBProvid
         return context;
     }
 
-    private JAXBContext getDefaultContext(Class<?> type) throws JAXBException {
+    private JAXBContext getDefaultContext(Class<?> type, Type genericType) throws \
JAXBException {  JAXBContext context = jaxbDefaultContexts.get(type);
         if (context == null) {
-            context = JAXBContext.newInstance(type);
+            
+            // 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 +                context = \
JAXBContext.newInstance((Class<?>)genericType); +            } else {
+                context = JAXBContext.newInstance(type);
+            }
+
             jaxbDefaultContexts.put(type, context);
         }
         return context;

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/a \
pache/wink/common/internal/providers/entity/xml/JAXBXmlProvider.java?rev=927462&r1=927461&r2=927462&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 \
Thu Mar 25 15:58:08 2010 @@ -119,14 +119,26 @@ public class JAXBXmlProvider extends \
Abs  MultivaluedMap<String, Object> httpHeaders,
                         OutputStream entityStream) throws IOException, \
WebApplicationException {  try {
-            JAXBContext context = getContext(type, mediaType);
-            Marshaller marshaller = getJAXBMarshaller(type, context, mediaType);
-            Object entityToMarshal = getEntityToMarshal(t, type);
+            if (isJAXBObject(type)) {
+                JAXBContext context = getContext(type, genericType, mediaType);
+                Marshaller marshaller = getJAXBMarshaller(type, context, mediaType);
+                Object entityToMarshal = getEntityToMarshal(t, type);
 
             // Use an OutputStream directly instead of a Writer for performance.
-            marshaller.marshal(entityToMarshal, entityStream);
+                marshaller.marshal(entityToMarshal, entityStream);
 
-            releaseJAXBMarshaller(context, marshaller);
+                releaseJAXBMarshaller(context, marshaller);
+            } else if (genericType instanceof Class<?>) {
+                JAXBContext context = getContext((Class<?>)genericType, genericType, \
mediaType); +                Marshaller marshaller = \
getJAXBMarshaller((Class<?>)genericType, context, mediaType); +                Object \
entityToMarshal = getEntityToMarshal(t, (Class<?>)genericType); +
+                // Use an OutputStream directly instead of a Writer for
+                // performance.
+                marshaller.marshal(entityToMarshal, entityStream);
+
+                releaseJAXBMarshaller(context, marshaller);
+            }
         } catch (JAXBException e) {
             logger.error(Messages.getMessage("jaxbFailToMarshal", type.getName()), \
e); //$NON-NLS-1$  throw new WebApplicationException(e);

Modified: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBCollectionXMLProviderTest.java
                
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/test/java/org/a \
pache/wink/server/internal/providers/entity/JAXBCollectionXMLProviderTest.java?rev=927462&r1=927461&r2=927462&view=diff
 ==============================================================================
--- incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBCollectionXMLProviderTest.java \
                (original)
+++ incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBCollectionXMLProviderTest.java \
Thu Mar 25 15:58:08 2010 @@ -23,6 +23,9 @@ package org.apache.wink.server.internal.
 import java.io.ByteArrayInputStream;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
@@ -532,15 +535,23 @@ public class JAXBCollectionXMLProviderTe
                                                         SOURCE_REQUEST_BYTES);
         MockHttpServletResponse invoke = invoke(request);
         assertEquals(200, invoke.getStatus());
-
+        
+        // nested elements may or may not have a namespace prefix, so...
+        String xml = invoke.getContentAsString();
+        Pattern myPattern = Pattern.compile("feeds><\\w*?:?feed");
+        Matcher matcher = myPattern.matcher(xml);
+        matcher.find();
+        // +6 to skip the "feeds>"
+        String feedString = xml.substring(matcher.start() + 6, matcher.end());
+        
         String[] elements =
-            getElementsFromList("<feeds>", "</feeds>", "<feed", \
invoke.getContentAsString()); +            getElementsFromList("<feeds>", "</feeds>", \
feedString, invoke.getContentAsString());  assertEquals(4, elements.length);
 
         AtomFeed feed = null;
         for (int i = 1; i < elements.length; ++i) {
             feed =
-                (AtomFeed)((JAXBElement<?>)unmarshallElement(AtomFeed.class, "<feed" \
+ elements[i])) +                \
(AtomFeed)((JAXBElement<?>)unmarshallElement(AtomFeed.class, feedString + \
                elements[i]))
                     .getValue();
             assertEquals("" + (i - 1) + "10", feed.getId());
         }
@@ -556,15 +567,23 @@ public class JAXBCollectionXMLProviderTe
                                       SOURCE_REQUEST_BYTES);
         MockHttpServletResponse invoke = invoke(request);
         assertEquals(200, invoke.getStatus());
+        
+        // nested elements may or may not have a namespace prefix, so...
+        String xml = invoke.getContentAsString();
+        Pattern myPattern = Pattern.compile("feeds><\\w*?:?feed");
+        Matcher matcher = myPattern.matcher(xml);
+        matcher.find();
+        // +6 to skip the "feeds>"
+        String feedString = xml.substring(matcher.start() + 6, matcher.end());
 
         String[] elements =
-            getElementsFromList("<feeds>", "</feeds>", "<feed", \
invoke.getContentAsString()); +            getElementsFromList("<feeds>", "</feeds>", \
feedString, invoke.getContentAsString());  assertEquals(4, elements.length);
 
         AtomFeed feed = null;
         for (int i = 1; i < elements.length; ++i) {
             feed =
-                (AtomFeed)((JAXBElement<?>)unmarshallElement(AtomFeed.class, "<feed" \
+ elements[i])) +                \
(AtomFeed)((JAXBElement<?>)unmarshallElement(AtomFeed.class, feedString + \
                elements[i]))
                     .getValue();
             assertEquals("" + (i - 1) + "10", feed.getId());
         }
@@ -580,14 +599,22 @@ public class JAXBCollectionXMLProviderTe
         MockHttpServletResponse invoke = invoke(request);
         assertEquals(200, invoke.getStatus());
 
+        // nested elements may or may not have a namespace prefix, so...
+        String xml = invoke.getContentAsString();
+        Pattern myPattern = Pattern.compile("feeds><\\w*?:?feed");
+        Matcher matcher = myPattern.matcher(xml);
+        matcher.find();
+        // +6 to skip the "feeds>"
+        String feedString = xml.substring(matcher.start() + 6, matcher.end());
+        
         String[] elements =
-            getElementsFromList("<feeds>", "</feeds>", "<feed", \
invoke.getContentAsString()); +            getElementsFromList("<feeds>", "</feeds>", \
feedString, invoke.getContentAsString());  assertEquals(4, elements.length);
 
         AtomFeed feed = null;
         for (int i = 1; i < elements.length; ++i) {
             feed =
-                (AtomFeed)((JAXBElement<?>)unmarshallElement(AtomFeed.class, "<feed" \
+ elements[i])) +                \
(AtomFeed)((JAXBElement<?>)unmarshallElement(AtomFeed.class, feedString + \
                elements[i]))
                     .getValue();
             assertEquals("" + (i - 1) + "10", feed.getId());
         }

Added: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBProviderInheritanceTest.java
                
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/test/java/org/a \
pache/wink/server/internal/providers/entity/JAXBProviderInheritanceTest.java?rev=927462&view=auto
 ==============================================================================
--- incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBProviderInheritanceTest.java \
                (added)
+++ incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/providers/entity/JAXBProviderInheritanceTest.java \
Thu Mar 25 15:58:08 2010 @@ -0,0 +1,213 @@
+/*******************************************************************************
+ * 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.io.ByteArrayInputStream;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+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;
+
+/**
+ * Intent of this class is to exercise the JAXBContext cache in the \
ProvidersRegistry. + */
+public class JAXBProviderInheritanceTest extends MockServletInvocationTest {
+
+    @XmlAccessorType(XmlAccessType.FIELD)
+    @XmlType(name = "", propOrder = {
+        "arg0",
+        "arg1"
+    })
+    @XmlRootElement(name = "addNumbers")
+    public static class AddNumbers {
+
+        protected int arg0;
+        protected int arg1;
+
+        /**
+         * Gets the value of the arg0 property.
+         * 
+         */
+        public int getArg0() {
+            return arg0;
+        }
+
+        /**
+         * Sets the value of the arg0 property.
+         * 
+         */
+        public void setArg0(int value) {
+            this.arg0 = value;
+        }
+
+        /**
+         * Gets the value of the arg1 property.
+         * 
+         */
+        public int getArg1() {
+            return arg1;
+        }
+
+        /**
+         * Sets the value of the arg1 property.
+         * 
+         */
+        public void setArg1(int value) {
+            this.arg1 = value;
+        }
+
+    }
+    
+    @XmlRootElement
+    public static class AddIntsAnnotated extends AddNumbers {}
+    
+    public static class AddIntsNotAnnotated extends AddNumbers {}
+    
+    
+    @Override
+    protected Class<?>[] getClasses() {
+        return new Class<?>[] {Resource.class, ResourceInherited.class};
+    }
+
+    @Path("jaxbresource")
+    public static class Resource {
+
+        @POST
+        @Path("jaxbelement")
+        public String add(AddNumbers addNumbers) {
+            return String.valueOf(addNumbers.getArg0() + addNumbers.getArg1());
+        }
+    }
+    
+    @Path("jaxbresourceinherited")
+    public static class ResourceInherited {
+
+        @POST
+        @Path("jaxbelement")
+        public String add(AddIntsAnnotated addInts) {
+            return String.valueOf(addInts.getArg0() + addInts.getArg1());
+        }
+        
+        @GET
+        @Path("getannotated")
+        public Response getAnnotated() {
+            AddIntsAnnotated addInts = new AddIntsAnnotated();
+            addInts.setArg0(11);
+            addInts.setArg1(12);
+           return Response.ok(new GenericEntity<AddNumbers>(addInts) {}).build();
+        }
+        
+        @GET
+        @Path("getnotannotated")
+        public Response getNotAnnotated() {
+            AddIntsNotAnnotated addInts = new AddIntsNotAnnotated();
+            addInts.setArg0(15);
+            addInts.setArg1(16);
+           return Response.ok(new GenericEntity<AddNumbers>(addInts) {}).build();
+        }
+    }
+    
+
+    public void testNormal() throws Exception {
+        AddNumbers addNumbers = new AddNumbers();
+        addNumbers.setArg0(2);
+        addNumbers.setArg1(3);
+
+        JAXBContext context = JAXBContext.newInstance(AddNumbers.class);
+        Marshaller marshaller = context.createMarshaller();
+        Writer writer = new StringWriter();
+        marshaller.marshal(addNumbers, writer);
+
+        MockHttpServletRequest request = MockRequestConstructor
+        .constructMockRequest("POST", "/jaxbresource/jaxbelement",
+                MediaType.TEXT_PLAIN, MediaType.APPLICATION_XML,
+                writer.toString().getBytes());
+        MockHttpServletResponse response = invoke(request);
+        assertEquals(200, response.getStatus());
+        assertEquals("5", response.getContentAsString());
+    }
+    
+    public void testInheritance() throws Exception {
+        AddIntsAnnotated addInts = new AddIntsAnnotated();
+        addInts.setArg0(2);
+        addInts.setArg1(3);
+
+        // JAXBContext can handle inherited types
+        JAXBContext context = JAXBContext.newInstance(AddIntsAnnotated.class);
+        Marshaller marshaller = context.createMarshaller();
+        Writer writer = new StringWriter();
+        marshaller.marshal(addInts, writer);
+
+        MockHttpServletRequest request = MockRequestConstructor
+        .constructMockRequest("POST", "/jaxbresourceinherited/jaxbelement",
+                MediaType.TEXT_PLAIN, MediaType.APPLICATION_XML,
+                writer.toString().getBytes());
+        MockHttpServletResponse response = invoke(request);
+        assertEquals(200, response.getStatus());
+        assertEquals("5", response.getContentAsString());
+    }
+    
+    public void testGenericEntityAnnotatedJAXB() throws Exception {
+        MockHttpServletRequest request = \
MockRequestConstructor.constructMockRequest("GET", \
"/jaxbresourceinherited/getannotated", MediaType.APPLICATION_XML); +        \
MockHttpServletResponse response = invoke(request); +        assertEquals(200, \
response.getStatus()); +        ByteArrayInputStream bais = new \
ByteArrayInputStream(response.getContentAsByteArray()); +        
+        JAXBContext context = JAXBContext.newInstance(AddIntsAnnotated.class);
+        Unmarshaller unmarshaller = context.createUnmarshaller();
+        AddIntsAnnotated addInts = (AddIntsAnnotated)unmarshaller.unmarshal(bais);
+        
+        assertEquals(11, addInts.getArg0());
+        assertEquals(12, addInts.getArg1());
+    }
+    
+    public void testGenericEntityNotAnnotatedJAXB() throws Exception {
+        MockHttpServletRequest request = \
MockRequestConstructor.constructMockRequest("GET", \
"/jaxbresourceinherited/getnotannotated", MediaType.APPLICATION_XML); +        \
MockHttpServletResponse response = invoke(request); +        assertEquals(200, \
response.getStatus()); +        ByteArrayInputStream bais = new \
ByteArrayInputStream(response.getContentAsByteArray()); +        
+        JAXBContext context = JAXBContext.newInstance(new \
Class[]{AddIntsAnnotated.class, AddNumbers.class}); +        Unmarshaller \
unmarshaller = context.createUnmarshaller(); +        // JAXB cannot unmarshal to \
AddIntsNotAnnotated because there is no @XmlRootElement annotation on it, so... +     \
AddNumbers addNumbers = (AddNumbers)unmarshaller.unmarshal(bais); +        
+        assertEquals(15, addNumbers.getArg0());
+        assertEquals(16, addNumbers.getArg1());
+    }
+    
+}


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic