You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wink.apache.org by jr...@apache.org on 2009/12/17 19:14:58 UTC

svn commit: r891814 [1/2] - in /incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/wink/ src/main/java/org/apache/wink/providers/ src/...

Author: jramos
Date: Thu Dec 17 18:14:57 2009
New Revision: 891814

URL: http://svn.apache.org/viewvc?rev=891814&view=rev
Log:
[#Wink-239] Check in wink-jaxbcollection-provider source

Added:
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/pom.xml
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/json/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/json/JAXBArrayJSONProvider.java
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/AbstractJAXBCollectionProvider.java
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/JAXBArrayXmlProvider.java
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/JAXBCollectionXmlProvider.java
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/resources/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/resources/META-INF/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/resources/META-INF/wink-application
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/providers/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/providers/internal/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/providers/internal/JAXBCollectionJSONTest.java
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/providers/internal/JAXBCollectionXMLProviderTest.java
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/providers/internal/jaxb/
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/providers/internal/jaxb/ObjectFactory.java
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/providers/internal/jaxb/Person.java
Modified:
    incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/   (props changed)

Propchange: incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Dec 17 18:14:57 2009
@@ -0,0 +1,4 @@
+.settings
+target
+.classpath
+.project

Added: incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/pom.xml
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/pom.xml?rev=891814&view=auto
==============================================================================
--- incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/pom.xml (added)
+++ incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/pom.xml Thu Dec 17 18:14:57 2009
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+    <!--
+        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.
+    -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>wink-providers</artifactId>
+        <groupId>org.apache.wink</groupId>
+        <version>1.1-incubating-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>wink-jaxbcollection-provider</artifactId>
+    <name>Apache Wink Providers :: JAXB Collection Provider</name>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.wink</groupId>
+            <artifactId>wink-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.wink</groupId>
+            <artifactId>wink-component-test-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-j2ee_1.4_spec</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.wink</groupId>
+            <artifactId>wink-server</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.woodstox</groupId>
+            <artifactId>wstx-asl</artifactId>
+            <version>3.2.1</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.wink</groupId>
+            <artifactId>wink-json-provider</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.wink</groupId>
+            <artifactId>wink-jackson-provider</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file

Added: incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/json/JAXBArrayJSONProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/json/JAXBArrayJSONProvider.java?rev=891814&view=auto
==============================================================================
--- incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/json/JAXBArrayJSONProvider.java (added)
+++ incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/json/JAXBArrayJSONProvider.java Thu Dec 17 18:14:57 2009
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * 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.providers.json;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+
+import org.apache.wink.providers.xml.AbstractJAXBCollectionProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Provider
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+public class JAXBArrayJSONProvider extends AbstractJAXBCollectionProvider implements
+    MessageBodyReader<Object[]>, MessageBodyWriter<Object[]> {
+
+    protected volatile MessageBodyReader<Object> readerProvider = null;
+    protected volatile MessageBodyWriter<Object> writerProvider = null;
+    
+    private static final Logger logger = LoggerFactory.getLogger(JAXBArrayJSONProvider.class);
+
+    @Context
+    Providers                           injectedProviders;
+
+    public boolean isReadable(Class<?> type,
+                              Type genericType,
+                              Annotation[] annotations,
+                              MediaType mediaType) {
+        Class<?> theType = getParameterizedTypeClass(type, genericType, false);
+        if (theType != null)
+            return (type.isArray() && isJAXBObject(theType, genericType) && !isJAXBElement(theType,
+                                                                                           genericType));
+        return false;
+    }
+
+    public long getSize(Object[] t,
+                        Class<?> type,
+                        Type genericType,
+                        Annotation[] annotations,
+                        MediaType mediaType) {
+        return -1;
+    }
+
+    @SuppressWarnings("unchecked")
+    public Object[] readFrom(Class<Object[]> type,
+                             Type genericType,
+                             Annotation[] annotations,
+                             MediaType mediaType,
+                             MultivaluedMap<String, String> httpHeaders,
+                             InputStream entityStream) throws IOException, WebApplicationException {
+        Class<?> theType = getParameterizedTypeClass(type, genericType, false);
+        if (this.readerProvider == null) {
+            this.readerProvider =
+                injectedProviders.getMessageBodyReader((Class<Object>)theType,
+                                                       theType,
+                                                       annotations,
+                                                       mediaType);
+            logger.debug("readerProvider was {} of type {}", System.identityHashCode(readerProvider), readerProvider.getClass().getName());
+        }
+        Queue<String> queue = new LinkedList<String>();
+        List<Object> collection = new ArrayList<Object>();
+        Pattern p = Pattern.compile("\\S");
+        Matcher m = null;
+        int next = entityStream.read();
+        while (next != -1) {
+            m = p.matcher("" + (char)next);
+            if (m.matches() && (char)next != '[')
+                throw new WebApplicationException(500);
+            else if (!m.matches())
+                next = (char)entityStream.read();
+            else {
+                // we found the first non-whitespace character is '['. Read the
+                // next character and begin parsing
+                next = entityStream.read();
+                break;
+            }
+        }
+
+        // parse the content and deserialize the JSON Object one by one
+        String objectString = "";
+        while (next != -1) {
+            if (((char)next != ',') || ((char)next == ',' && !queue.isEmpty()))
+                objectString += (char)next;
+            if ((char)next == '{')
+                queue.offer("" + (char)next);
+            else if ((char)next == '}') {
+                queue.poll();
+                if (queue.isEmpty()) {
+                    collection.add(this.readerProvider
+                        .readFrom((Class<Object>)theType,
+                                  theType,
+                                  annotations,
+                                  mediaType,
+                                  httpHeaders,
+                                  new ByteArrayInputStream(objectString.getBytes())));
+                    objectString = "";
+                }
+            }
+            next = entityStream.read();
+        }
+        return (Object[])getArray(theType, collection);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected static <T> Object getArray(Class<T> type, List<?> collection) {
+        T[] ret = (T[])Array.newInstance(type, collection.size());
+        int i = 0;
+        for (Object o : collection) {
+            ret[i++] = (T)o;
+        }
+        return ret;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void writeTo(Object[] t,
+                        Class<?> type,
+                        Type genericType,
+                        Annotation[] annotations,
+                        MediaType mediaType,
+                        MultivaluedMap<String, Object> httpHeaders,
+                        OutputStream entityStream) throws IOException, WebApplicationException {
+        Class<?> theType = getParameterizedTypeClass(type, genericType, false);
+        if (this.writerProvider == null) {
+            this.writerProvider =
+                injectedProviders.getMessageBodyWriter((Class<Object>)theType,
+                                                       theType,
+                                                       annotations,
+                                                       mediaType);
+            logger.debug("writerProvider was {} of type {}", System.identityHashCode(writerProvider), writerProvider.getClass().getName());
+        }
+        entityStream.write("[".getBytes());
+        int i = 0;
+        for (Object o : t) {
+            this.writerProvider.writeTo(o,
+                                        theType,
+                                        theType,
+                                        annotations,
+                                        mediaType,
+                                        httpHeaders,
+                                        entityStream);
+            if ((++i) != t.length)
+                entityStream.write(",".getBytes());
+        }
+        entityStream.write("]".getBytes());
+    }
+
+    public boolean isWriteable(Class<?> type,
+                               Type genericType,
+                               Annotation[] annotations,
+                               MediaType mediaType) {
+        Class<?> theType = getParameterizedTypeClass(type, genericType, false);
+
+        if (theType != null)
+            return (isJAXBObject(theType, genericType) && !isJAXBElement(theType, genericType));
+        return false;
+    }
+
+}

Added: incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/AbstractJAXBCollectionProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/AbstractJAXBCollectionProvider.java?rev=891814&view=auto
==============================================================================
--- incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/AbstractJAXBCollectionProvider.java (added)
+++ incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/AbstractJAXBCollectionProvider.java Thu Dec 17 18:14:57 2009
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * 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.providers.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.wink.common.internal.i18n.Messages;
+import org.apache.wink.common.internal.providers.entity.xml.AbstractJAXBProvider;
+import org.apache.wink.common.internal.utils.GenericsUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractJAXBCollectionProvider extends AbstractJAXBProvider {
+    private static final String JAXB_DEFAULT_NAMESPACE = "##default";
+    private static final String JAXB_DEFAULT_NAME      = "##default";
+    private static final Logger logger                 =
+                                                           LoggerFactory
+                                                               .getLogger(AbstractJAXBCollectionProvider.class);
+
+    public Object read(Class<?> type,
+                       Type genericType,
+                       Annotation[] annotations,
+                       MediaType mediaType,
+                       MultivaluedMap<String, String> httpHeaders,
+                       InputStream entityStream) throws IOException, WebApplicationException {
+        try {
+            XMLInputFactory xmif = XMLInputFactory.newInstance();
+            XMLStreamReader xsr = xmif.createXMLStreamReader(entityStream);
+            Class<?> theType = getParameterizedTypeClass(type, genericType, true);
+            JAXBContext context = getContext(theType, mediaType);
+            Unmarshaller unmarshaller = getJAXBUnmarshaller(context);
+
+            int nextEvent = xsr.next();
+            while (nextEvent != XMLStreamReader.START_ELEMENT)
+                nextEvent = xsr.next();
+
+            List<Object> elementList = new ArrayList<Object>();
+            nextEvent = xsr.next();
+            while (nextEvent != XMLStreamReader.END_DOCUMENT) {
+                switch (nextEvent) {
+                    case XMLStreamReader.START_ELEMENT:
+                        if (getParameterizedTypeClass(type, genericType, false) == JAXBElement.class) {
+                            elementList.add(unmarshaller.unmarshal(xsr, theType));
+                        } else if (theType.isAnnotationPresent(XmlRootElement.class)) {
+                            elementList.add(unmarshaller.unmarshal(xsr));
+                        } else {
+                            elementList.add(unmarshaller.unmarshal(xsr, theType).getValue());
+                        }
+                        nextEvent = xsr.getEventType();
+                        break;
+                    default:
+                        nextEvent = xsr.next();
+                }
+            }
+
+            Object ret = null;
+            if (type.isArray())
+                ret = convertListToArray(theType, elementList);
+            else if (type == Set.class)
+                ret = new HashSet<Object>(elementList);
+            else
+                ret = elementList;
+
+            releaseJAXBUnmarshaller(context, unmarshaller);
+            return ret;
+        } catch (XMLStreamException e) {
+            logger.error(Messages.getMessage("jaxbFailToUnmarshal"), type.getName()); // TODO
+            // change
+            // message
+            throw new WebApplicationException(e, Response.Status.BAD_REQUEST);
+        } catch (JAXBException e) {
+            logger.error(Messages.getMessage("jaxbFailToUnmarshal"), type.getName());
+            throw new WebApplicationException(e, Response.Status.BAD_REQUEST);
+        }
+    }
+
+    public void write(Object t,
+                      Class<?> type,
+                      Type genericType,
+                      Annotation[] annotations,
+                      MediaType mediaType,
+                      MultivaluedMap<String, Object> httpHeaders,
+                      OutputStream entityStream) throws IOException, WebApplicationException {
+        try {
+            Class<?> theType = getParameterizedTypeClass(type, genericType, false);
+            Object[] elementArray = type.isArray() ? (Object[])t : ((Collection<?>)t).toArray();
+            QName qname = null;
+            boolean isJAXBElement = false;
+            if (elementArray.length > 0 && elementArray[0] instanceof JAXBElement<?>) {
+                JAXBElement<?> jaxbElement = (JAXBElement<?>)elementArray[0];
+                qname = jaxbElement.getName();
+                isJAXBElement = true;
+            } else {
+                qname = getJaxbQName(theType);
+            }
+
+            if (qname != null) {
+                writeStartTag(qname, entityStream, mediaType);
+            }
+
+            for (Object o : elementArray) {
+                Class<?> oType =
+                    isJAXBElement ? ((JAXBElement<?>)o).getDeclaredType() : o.getClass();
+                JAXBContext context = getContext(oType, mediaType);
+                Marshaller marshaller = getJAXBMarshaller(oType, context, mediaType);
+                marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
+                Object entityToMarshal = getEntityToMarshal(o, theType);
+                if (qname == null) {
+                    if (entityToMarshal instanceof JAXBElement<?>)
+                        qname = ((JAXBElement<?>)entityToMarshal).getName();
+                    else
+                        qname =
+                            new QName(entityToMarshal.getClass().getPackage().getName(),
+                                      entityToMarshal.getClass().getSimpleName());
+                    writeStartTag(qname, entityStream, mediaType);
+                }
+                Charset charSet = getCharSet(mediaType);
+                marshaller.setProperty(Marshaller.JAXB_ENCODING, charSet.name());
+                marshaller.marshal(entityToMarshal, entityStream);
+                releaseJAXBMarshaller(context, marshaller);
+            }
+
+            writeEndTag(qname, entityStream);
+        } catch (JAXBException e) {
+            logger.error(Messages.getMessage("jaxbFailToMarshal"), type.getName());
+            throw new WebApplicationException(e);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    protected static <T> Object convertListToArray(Class<T> type, List<Object> elementList) {
+        T[] ret = (T[])Array.newInstance(type, elementList.size());
+        for (int i = 0; i < elementList.size(); ++i)
+            ret[i] = (T)elementList.get(i);
+        return ret;
+    }
+
+    protected static void writeStartTag(QName qname, OutputStream entityStream, MediaType m)
+        throws IOException {
+        String startTag = null;
+        Charset charSet = getCharSet(m);
+        startTag = "<?xml version=\"1.0\" encoding=\"" + charSet.name() + "\" standalone=\"yes\"?>";
+        entityStream.write(startTag.getBytes());
+        // if (qname.getNamespaceURI().length() > 0)
+        // startTag = "<" + qname.getLocalPart() + "s xmlns=\"" +
+        // qname.getNamespaceURI() + "\">";
+        // else
+        startTag = "<" + qname.getLocalPart() + "s>";
+        entityStream.write(startTag.getBytes());
+    }
+
+    protected static Charset getCharSet(MediaType m) {
+        String charSetString = m.getParameters().get("charset");
+        Charset charSet =
+            charSetString == null ? Charset.forName("UTF-8") : Charset.forName(charSetString);
+        return charSet;
+    }
+
+    protected static void writeEndTag(QName qname, OutputStream entityStream) throws IOException {
+        String endTag = null;
+        if (qname.getNamespaceURI().length() > 0)
+            endTag = "</" + qname.getLocalPart() + "s>";
+        else
+            endTag = "</" + qname.getLocalPart() + "s>";
+        entityStream.write(endTag.getBytes());
+    }
+
+    public static Class<?> getParameterizedTypeClass(Class<?> type,
+                                                        Type genericType,
+                                                        boolean recurse) {
+        if (Collection.class.isAssignableFrom(type)) {
+            if (genericType instanceof ParameterizedType) {
+                ParameterizedType parameterizedType = (ParameterizedType)genericType;
+                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+                if (!(actualTypeArguments[0] instanceof ParameterizedType)) {
+                    return (Class<?>)actualTypeArguments[0];
+                } else {
+                    parameterizedType = (ParameterizedType)actualTypeArguments[0];
+                    if (recurse)
+                        return getParameterizedTypeClass(type, parameterizedType, recurse);
+                    else
+                        return (Class<?>)parameterizedType.getRawType();
+                }
+            } else {
+                return GenericsUtils.getGenericParamType(genericType);
+            }
+        } else if (type.isArray()) {
+            return type.getComponentType();
+        }
+        return null;
+    }
+
+    protected static QName getJaxbQName(Class<?> cls) {
+        XmlRootElement root = cls.getAnnotation(XmlRootElement.class);
+        if (root != null) {
+            String namespace = getNamespace(root.namespace());
+            String name = getLocalName(root.name(), cls.getSimpleName());
+            return new QName(namespace, name);
+        }
+        return null;
+    }
+
+    protected static String getLocalName(String name, String clsName) {
+        if (JAXB_DEFAULT_NAME.equals(name)) {
+            name = clsName;
+            if (name.length() > 1) {
+                name = name.substring(0, 1).toLowerCase() + name.substring(1);
+            } else {
+                name = name.toLowerCase();
+            }
+        }
+        return name;
+    }
+
+    protected static String getNamespace(String namespace) {
+        if (JAXB_DEFAULT_NAMESPACE.equals(namespace)) {
+            return "";
+        }
+        return namespace;
+    }
+}

Added: incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/JAXBArrayXmlProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/JAXBArrayXmlProvider.java?rev=891814&view=auto
==============================================================================
--- incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/JAXBArrayXmlProvider.java (added)
+++ incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/JAXBArrayXmlProvider.java Thu Dec 17 18:14:57 2009
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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.providers.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+@Provider
+@Consumes( {MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.WILDCARD})
+@Produces( {MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.WILDCARD})
+public class JAXBArrayXmlProvider extends AbstractJAXBCollectionProvider implements
+    MessageBodyReader<Object[]>, MessageBodyWriter<Object[]> {
+
+    public boolean isReadable(Class<?> type,
+                              Type genericType,
+                              Annotation[] annotations,
+                              MediaType mediaType) {
+        Class<?> theType = getParameterizedTypeClass(type, genericType, false);
+        if (theType != null)
+            return (isSupportedMediaType(mediaType) && isJAXBObject(theType, genericType) && !isJAXBElement(theType,
+                                                                                                            genericType));
+        return false;
+    }
+
+    public Object[] readFrom(Class<Object[]> type,
+                             Type genericType,
+                             Annotation[] annotations,
+                             MediaType mediaType,
+                             MultivaluedMap<String, String> httpHeaders,
+                             InputStream entityStream) throws IOException, WebApplicationException {
+        return (Object[])super.read(type,
+                                    genericType,
+                                    annotations,
+                                    mediaType,
+                                    httpHeaders,
+                                    entityStream);
+    }
+
+    public long getSize(Object[] t,
+                        Class<?> type,
+                        Type genericType,
+                        Annotation[] annotations,
+                        MediaType mediaType) {
+        return -1;
+    }
+
+    public boolean isWriteable(Class<?> type,
+                               Type genericType,
+                               Annotation[] annotations,
+                               MediaType mediaType) {
+        Class<?> theType = getParameterizedTypeClass(type, genericType, false);
+        if (theType != null)
+            return (isSupportedMediaType(mediaType) && isJAXBObject(theType, genericType) && !isJAXBElement(theType,
+                                                                                                            genericType));
+        return false;
+    }
+
+    public void writeTo(Object[] t,
+                        Class<?> type,
+                        Type genericType,
+                        Annotation[] annotations,
+                        MediaType mediaType,
+                        MultivaluedMap<String, Object> httpHeaders,
+                        OutputStream entityStream) throws IOException, WebApplicationException {
+        super.write(t, type, genericType, annotations, mediaType, httpHeaders, entityStream);
+    }
+
+}

Added: incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/JAXBCollectionXmlProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/JAXBCollectionXmlProvider.java?rev=891814&view=auto
==============================================================================
--- incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/JAXBCollectionXmlProvider.java (added)
+++ incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/java/org/apache/wink/providers/xml/JAXBCollectionXmlProvider.java Thu Dec 17 18:14:57 2009
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.providers.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+@Provider
+@Consumes( {MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.WILDCARD})
+@Produces( {MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.WILDCARD})
+public class JAXBCollectionXmlProvider extends AbstractJAXBCollectionProvider implements
+    MessageBodyReader<Object>, MessageBodyWriter<Object> {
+
+    public boolean isReadable(Class<?> type,
+                              Type genericType,
+                              Annotation[] annotations,
+                              MediaType mediaType) {
+        Class<?> theType = getParameterizedTypeClass(type, genericType, false);
+        if (theType != null)
+            return (Collection.class.isAssignableFrom(type) && isSupportedMediaType(mediaType) && (isJAXBObject(theType, genericType) || (isJAXBElement(theType,
+                                                                                                             genericType))));
+        return false;
+    }
+
+    public Object readFrom(Class<Object> type,
+                           Type genericType,
+                           Annotation[] annotations,
+                           MediaType mediaType,
+                           MultivaluedMap<String, String> httpHeaders,
+                           InputStream entityStream) throws IOException, WebApplicationException {
+        return super.read(type, genericType, annotations, mediaType, httpHeaders, entityStream);
+    }
+
+    public long getSize(Object t,
+                        Class<?> type,
+                        Type genericType,
+                        Annotation[] annotations,
+                        MediaType mediaType) {
+        return -1;
+    }
+
+    public boolean isWriteable(Class<?> type,
+                               Type genericType,
+                               Annotation[] annotations,
+                               MediaType mediaType) {
+        Class<?> theType = getParameterizedTypeClass(type, genericType, false);
+        if (theType != null)
+            return (Collection.class.isAssignableFrom(type) && isSupportedMediaType(mediaType) && (isJAXBObject(theType, genericType) || (isJAXBElement(theType,
+                                                                                                             genericType))));
+        return false;
+    }
+
+    public void writeTo(Object t,
+                        Class<?> type,
+                        Type genericType,
+                        Annotation[] annotations,
+                        MediaType mediaType,
+                        MultivaluedMap<String, Object> httpHeaders,
+                        OutputStream entityStream) throws IOException, WebApplicationException {
+        super.write(t, type, genericType, annotations, mediaType, httpHeaders, entityStream);
+    }
+}

Added: incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/resources/META-INF/wink-application
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/resources/META-INF/wink-application?rev=891814&view=auto
==============================================================================
--- incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/resources/META-INF/wink-application (added)
+++ incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/main/resources/META-INF/wink-application Thu Dec 17 18:14:57 2009
@@ -0,0 +1,22 @@
+##
+## 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.
+##
+
+org.apache.wink.providers.xml.JAXBCollectionXmlProvider
+org.apache.wink.providers.xml.JAXBArrayXmlProvider
+org.apache.wink.providers.json.JAXBArrayJSONProvider
\ No newline at end of file

Added: incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/providers/internal/JAXBCollectionJSONTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/providers/internal/JAXBCollectionJSONTest.java?rev=891814&view=auto
==============================================================================
--- incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/providers/internal/JAXBCollectionJSONTest.java (added)
+++ incubator/wink/trunk/wink-providers/wink-jaxbcollection-provider/src/test/java/org/apache/wink/providers/internal/JAXBCollectionJSONTest.java Thu Dec 17 18:14:57 2009
@@ -0,0 +1,358 @@
+/*******************************************************************************
+ * 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.providers.internal;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.xml.bind.JAXBElement;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.namespace.QName;
+
+import org.apache.wink.common.model.atom.AtomEntry;
+import org.apache.wink.providers.internal.jaxb.Person;
+import org.apache.wink.providers.json.JSONUtils;
+import org.apache.wink.server.internal.servlet.MockServletInvocationTest;
+import org.apache.wink.test.mock.MockRequestConstructor;
+import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig.Feature;
+import org.codehaus.jackson.xc.JaxbAnnotationIntrospector;
+import org.json.JSONArray;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+public class JAXBCollectionJSONTest extends MockServletInvocationTest {
+
+    private static final String ENTRY_STR_1         =
+                                                        "<entry xml:base=\"http://b216:8080/reporting/reports\" xmlns=\"http://www.w3.org/2005/Atom\">\n" + "    <id>toptenvalidators</id>\n"
+                                                            + "    <updated>2009-08-31T18:30:02Z</updated>\n"
+                                                            + "    <title type=\"text\" xml:lang=\"en\">top ten validators 1</title>\n"
+                                                            + "    <published>2009-08-31T18:30:02Z</published>\n"
+                                                            + "    <link href=\"http://b216:8080/reporting/reports/toptenvalidators?alt=application/json\" type=\"application/json\" rel=\"alternate\"/>\n"
+                                                            + "    <author>\n"
+                                                            + "        <name>admin 1</name>\n"
+                                                            + "    </author>\n"
+                                                            + "    <category label=\"report definition\" scheme=\"urn:com:systinet:reporting:kind\" term=\"urn:com:systinet:reporting:kind:definition\"/>\n"
+                                                            + "</entry>";
+    private static final String ENTRY_STR_2         =
+                                                        "<entry xml:base=\"http://b216:8080/reporting/reports\" xmlns=\"http://www.w3.org/2005/Atom\">\n" + "    <id>toptenvalidators</id>\n"
+                                                            + "    <updated>2009-08-31T18:30:02Z</updated>\n"
+                                                            + "    <title type=\"text\" xml:lang=\"en\">top ten validators 2</title>\n"
+                                                            + "    <published>2009-08-31T18:30:02Z</published>\n"
+                                                            + "    <link href=\"http://b216:8080/reporting/reports/toptenvalidators?alt=application/json\" type=\"application/json\" rel=\"alternate\"/>\n"
+                                                            + "    <author>\n"
+                                                            + "        <name>admin 2</name>\n"
+                                                            + "    </author>\n"
+                                                            + "    <category label=\"report definition\" scheme=\"urn:com:systinet:reporting:kind\" term=\"urn:com:systinet:reporting:kind:definition\"/>\n"
+                                                            + "</entry>";
+
+    private static final String ENTRY_STR_JSON_1    =
+                                                        "{\"base\":\"http://b216:8080/reporting/reports\"," + "\"otherAttributes\":{},"
+                                                            + "\"id\":\"toptenvalidators\","
+                                                            + "\"updated\":{\"year\":2009,\"month\":8,\"day\":31,\"timezone\":0,\"hour\":18,\"minute\":30,\"second\":2,\"millisecond\":-2147483648},"
+                                                            + "\"title\":{\"lang\":\"en\",\"otherAttributes\":{},\"type\":\"text\"},"
+                                                            + "\"published\":{\"year\":2009,\"month\":8,\"day\":31,\"timezone\":0,\"hour\":18,\"minute\":30,\"second\":2,\"millisecond\":-2147483648},"
+                                                            + "\"link\":[{\"otherAttributes\":{},\"rel\":\"alternate\",\"type\":\"application/json\",\"href\":\"http://b216:8080/reporting/reports/toptenvalidators?alt=application/json\"}],"
+                                                            + "\"author\":[{\"name\":\"admin 1\"}],"
+                                                            + "\"category\":[{\"otherAttributes\":{},\"term\":\"urn:com:systinet:reporting:kind:definition\",\"scheme\":\"urn:com:systinet:reporting:kind\",\"label\":\"report definition\"}]"
+                                                            + "}";
+    private static final String ENTRY_STR_JSON_2    =
+                                                        "{\"base\":\"http://b216:8080/reporting/reports\"," + "\"otherAttributes\":{},"
+                                                            + "\"id\":\"toptenvalidators\","
+                                                            + "\"updated\":{\"year\":2009,\"month\":8,\"day\":31,\"timezone\":0,\"hour\":18,\"minute\":30,\"second\":2,\"millisecond\":-2147483648},"
+                                                            + "\"title\":{\"lang\":\"en\",\"otherAttributes\":{},\"type\":\"text\"},"
+                                                            + "\"published\":{\"year\":2009,\"month\":8,\"day\":31,\"timezone\":0,\"hour\":18,\"minute\":30,\"second\":2,\"millisecond\":-2147483648},"
+                                                            + "\"link\":[{\"otherAttributes\":{},\"rel\":\"alternate\",\"type\":\"application/json\",\"href\":\"http://b216:8080/reporting/reports/toptenvalidators?alt=application/json\"}],"
+                                                            + "\"author\":[{\"name\":\"admin 2\"}],"
+                                                            + "\"category\":[{\"otherAttributes\":{},\"term\":\"urn:com:systinet:reporting:kind:definition\",\"scheme\":\"urn:com:systinet:reporting:kind\",\"label\":\"report definition\"}]"
+                                                            + "}";
+
+    private static final String ENTRY_STR_JSON_GET  =
+                                                        "[{\"name\":{\"namespaceURI\":\"http://www.w3.org/2005/Atom\",\"localPart\":\"entry\",\"prefix\":\"\"}," + "\"declaredType\":\"org.apache.wink.common.model.atom.AtomEntry\","
+                                                            + "\"scope\":\"javax.xml.bind.JAXBElement$GlobalScope\","
+                                                            + "\"value\":"
+                                                            + ENTRY_STR_JSON_1
+                                                            + ",\"nil\":false},"
+                                                            + "{\"name\":{\"namespaceURI\":\"http://www.w3.org/2005/Atom\",\"localPart\":\"entry\",\"prefix\":\"\"},"
+                                                            + "\"declaredType\":\"org.apache.wink.common.model.atom.AtomEntry\","
+                                                            + "\"scope\":\"javax.xml.bind.JAXBElement$GlobalScope\","
+                                                            + "\"value\":"
+                                                            + ENTRY_STR_JSON_2
+                                                            + ",\"nil\":false}]";
+
+    private static final String ENTRY_JSON_1;
+    private static final String ENTRY_JSON_2;
+
+    static {
+
+        GregorianCalendar gCal = new GregorianCalendar();
+        XMLGregorianCalendar xmlGCal = null;
+        try {
+            xmlGCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(gCal);
+        } catch (DatatypeConfigurationException e) {
+            fail("could not construct XMLGregorianCalendar: " + e.getMessage());
+            e.printStackTrace();
+        }
+        String jsonTimeStr1 = "{";
+        jsonTimeStr1 += "\"eon\":" + xmlGCal.getEon() + ",";
+        jsonTimeStr1 += "\"year\":" + xmlGCal.getYear() + ",";
+        jsonTimeStr1 += "\"day\":" + xmlGCal.getDay() + ",";
+        jsonTimeStr1 += "\"timezone\":" + xmlGCal.getTimezone() + ",";
+        jsonTimeStr1 += "\"hour\":" + xmlGCal.getHour() + ",";
+        jsonTimeStr1 += "\"minute\":" + xmlGCal.getMinute() + ",";
+        jsonTimeStr1 += "\"second\":" + xmlGCal.getSecond() + ",";
+        jsonTimeStr1 += "\"millisecond\":" + xmlGCal.getMillisecond();
+        jsonTimeStr1 += "}";
+        try {
+            Thread.sleep(2000);
+        } catch (InterruptedException e) {
+        }
+        String jsonTimeStr2 = "{";
+        jsonTimeStr2 += "\"eon\":" + xmlGCal.getEon() + ",";
+        jsonTimeStr2 += "\"year\":" + xmlGCal.getYear() + ",";
+        jsonTimeStr2 += "\"day\":" + xmlGCal.getDay() + ",";
+        jsonTimeStr2 += "\"timezone\":" + xmlGCal.getTimezone() + ",";
+        jsonTimeStr2 += "\"hour\":" + xmlGCal.getHour() + ",";
+        jsonTimeStr2 += "\"minute\":" + xmlGCal.getMinute() + ",";
+        jsonTimeStr2 += "\"second\":" + xmlGCal.getSecond() + ",";
+        jsonTimeStr2 += "\"millisecond\":" + xmlGCal.getMillisecond();
+        jsonTimeStr2 += "}";
+
+        ENTRY_JSON_1 = ENTRY_STR_JSON_1.replaceAll("@TIME_JSON@", jsonTimeStr1);
+        ENTRY_JSON_2 = ENTRY_STR_JSON_2.replaceAll("@TIME_JSON@", jsonTimeStr2);
+    }
+
+    @Override
+    protected Class<?>[] getClasses() {
+        return new Class<?>[] {TestResource.class, PersonResource.class};
+    }
+
+    @Override
+    protected Object[] getSingletons() {
+        ObjectMapper mapper = new ObjectMapper();
+        JaxbAnnotationIntrospector jaxbIntrospector = new JaxbAnnotationIntrospector();
+        mapper.getSerializationConfig().setAnnotationIntrospector(jaxbIntrospector);
+        mapper.getSerializationConfig().set(Feature.WRITE_DATES_AS_TIMESTAMPS, true);
+        mapper.getDeserializationConfig().setAnnotationIntrospector(jaxbIntrospector);
+        JacksonJsonProvider jacksonProvider = new JacksonJsonProvider(mapper);
+        return new Object[] {jacksonProvider};
+    }
+
+    @Path("/test/person")
+    public static class PersonResource {
+
+        @GET
+        @Path("collection")
+        public List<Person> getPeopleCollection() throws IOException {
+            List<Person> people = new ArrayList<Person>();
+            Person p = new Person();
+            p.setName("My Name");
+            p.setDesc("My desc");
+            people.add(p);
+            p = new Person();
+            p.setName("My Name 2");
+            p.setDesc("My desc 2");
+            people.add(p);
+            return people;
+        }
+
+        @GET
+        @Path("array")
+        public Person[] getPeopleArray() throws IOException {
+            return getPeopleCollection().toArray(new Person[] {});
+        }
+
+        @GET
+        @Path("jaxbelement")
+        public List<JAXBElement<Person>> getPeopleJAXBElementCollection() throws IOException {
+            List<Person> people = getPeopleCollection();
+            List<JAXBElement<Person>> ret = new ArrayList<JAXBElement<Person>>();
+            JAXBElement<Person> element = null;
+            for (Person p : people) {
+                element = new JAXBElement<Person>(new QName("", "person"), Person.class, p);
+                ret.add(element);
+            }
+            return ret;
+        }
+
+        @POST
+        @Path("collection")
+        public List<Person> postPeopleCollection(List<Person> p) {
+            return p;
+        }
+
+        @POST
+        @Path("array")
+        public Person[] postPeopleArray(Person[] p) {
+            return p;
+        }
+
+    }
+
+    @Path("test")
+    public static class TestResource {
+
+        @GET
+        @Path("atomentries/collection")
+        @Produces("application/json")
+        public List<AtomEntry> getAtomEntriesCollection() throws IOException {
+            List<AtomEntry> entries = new ArrayList<AtomEntry>();
+            AtomEntry entry1 = AtomEntry.unmarshal(new StringReader(ENTRY_STR_1));
+            AtomEntry entry2 = AtomEntry.unmarshal(new StringReader(ENTRY_STR_2));
+            entries.add(entry1);
+            entries.add(entry2);
+            return entries;
+        }
+
+        @GET
+        @Path("atomentries/array")
+        @Produces("application/json")
+        public AtomEntry[] getAtomEntriesArray() throws IOException {
+            return getAtomEntriesCollection().toArray(new AtomEntry[] {});
+        }
+
+        @GET
+        @Path("atomentryelements/collection")
+        @Produces("application/json")
+        public List<JAXBElement<AtomEntry>> getAtomEntryElementCollection() throws IOException {
+            List<JAXBElement<AtomEntry>> entries = new ArrayList<JAXBElement<AtomEntry>>();
+            AtomEntry entry1 = AtomEntry.unmarshal(new StringReader(ENTRY_STR_1));
+            AtomEntry entry2 = AtomEntry.unmarshal(new StringReader(ENTRY_STR_2));
+            org.apache.wink.common.model.atom.ObjectFactory of =
+                new org.apache.wink.common.model.atom.ObjectFactory();
+            entries.add(of.createEntry(entry1));
+            entries.add(of.createEntry(entry2));
+            return entries;
+        }
+    }
+
+    public void testGetPeople() throws Exception {
+        MockHttpServletRequest request =
+            MockRequestConstructor.constructMockRequest("GET",
+                                                        "/test/person/collection",
+                                                        "application/json");
+        MockHttpServletResponse response = invoke(request);
+        assertEquals(200, response.getStatus());
+
+        assertTrue(JSONUtils
+            .equals(new JSONArray(
+                                  "[{\"desc\":\"My desc\",\"name\":\"My Name\"},{\"desc\":\"My desc 2\",\"name\":\"My Name 2\"}]"),
+                    new JSONArray(response.getContentAsString())));
+
+        request =
+            MockRequestConstructor.constructMockRequest("GET",
+                                                        "/test/person/array",
+                                                        "application/json");
+        response = invoke(request);
+        assertEquals(200, response.getStatus());
+
+        assertTrue(JSONUtils
+            .equals(new JSONArray(
+                                  "[{\"desc\":\"My desc\",\"name\":\"My Name\"},{\"desc\":\"My desc 2\",\"name\":\"My Name 2\"}]"),
+                    new JSONArray(response.getContentAsString())));
+
+        request =
+            MockRequestConstructor.constructMockRequest("GET",
+                                                        "/test/person/jaxbelement",
+                                                        "application/json");
+        response = invoke(request);
+        assertEquals(200, response.getStatus());
+
+        assertTrue(JSONUtils
+            .equals(new JSONArray(
+                                  "[{\"name\":{\"namespaceURI\":\"\",\"localPart\":\"person\",\"prefix\":\"\"},\"declaredType\":\"org.apache.wink.providers.internal.jaxb.Person\",\"scope\":\"javax.xml.bind.JAXBElement$GlobalScope\",\"value\":{\"name\":\"My Name\",\"desc\":\"My desc\"},\"nil\":false},{\"name\":{\"namespaceURI\":\"\",\"localPart\":\"person\",\"prefix\":\"\"},\"declaredType\":\"org.apache.wink.providers.internal.jaxb.Person\",\"scope\":\"javax.xml.bind.JAXBElement$GlobalScope\",\"value\":{\"name\":\"My Name 2\",\"desc\":\"My desc 2\"},\"nil\":false}]"),
+                    new JSONArray(response.getContentAsString())));
+    }
+
+    public void testPostPeople() throws Exception {
+        MockHttpServletRequest request =
+            MockRequestConstructor.constructMockRequest("POST",
+                                                        "/test/person/collection",
+                                                        "application/json");
+        request.setContentType("application/json");
+        request
+            .setContent("[{\"desc\":\"My desc 1\",\"name\":\"My Name 1\"},{\"desc\":\"My desc 2\",\"name\":\"My Name 2\"}]"
+                .getBytes());
+        MockHttpServletResponse response = invoke(request);
+        assertEquals(200, response.getStatus());
+        assertTrue(JSONUtils
+            .equals(new JSONArray(
+                                  "[{\"desc\":\"My desc 1\",\"name\":\"My Name 1\"},{\"desc\":\"My desc 2\",\"name\":\"My Name 2\"}]"),
+                    new JSONArray(response.getContentAsString())));
+
+        request =
+            MockRequestConstructor.constructMockRequest("POST",
+                                                        "/test/person/array",
+                                                        "application/json");
+        request.setContentType("application/json");
+        request
+            .setContent("[{\"desc\":\"My desc 1\",\"name\":\"My Name 1\"},{\"desc\":\"My desc 2\",\"name\":\"My Name 2\"}]"
+                .getBytes());
+        response = invoke(request);
+        assertEquals(200, response.getStatus());
+        assertTrue(JSONUtils
+            .equals(new JSONArray(
+                                  "[{\"desc\":\"My desc 1\",\"name\":\"My Name 1\"},{\"desc\":\"My desc 2\",\"name\":\"My Name 2\"}]"),
+                    new JSONArray(response.getContentAsString())));
+
+    }
+
+    public void testGetAtomEntries() throws Exception {
+        MockHttpServletRequest request =
+            MockRequestConstructor.constructMockRequest("GET",
+                                                        "/test/atomentries/collection",
+                                                        "application/json");
+        MockHttpServletResponse response = invoke(request);
+        assertEquals(200, response.getStatus());
+        assertTrue(JSONUtils.equals(new JSONArray("[" + ENTRY_JSON_1 + "," + ENTRY_JSON_2 + "]"),
+                                    new JSONArray(response.getContentAsString())));
+
+        request =
+            MockRequestConstructor.constructMockRequest("GET",
+                                                        "/test/atomentries/array",
+                                                        "application/json");
+        response = invoke(request);
+        assertEquals(200, response.getStatus());
+        assertTrue(JSONUtils.equals(new JSONArray("[" + ENTRY_JSON_1 + "," + ENTRY_JSON_2 + "]"),
+                                    new JSONArray(response.getContentAsString())));
+    }
+
+    public void testGetAtomEntryElements() throws Exception {
+        MockHttpServletRequest request =
+            MockRequestConstructor.constructMockRequest("GET",
+                                                        "/test/atomentryelements/collection",
+                                                        "application/json");
+        MockHttpServletResponse response = invoke(request);
+        assertEquals(200, response.getStatus());
+        assertTrue(JSONUtils.equals(new JSONArray(ENTRY_STR_JSON_GET), new JSONArray(response
+            .getContentAsString())));
+    }
+}