You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2009/07/16 16:04:24 UTC
svn commit: r794680 - in /cxf/trunk:
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/
rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/
rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/
systests/src/test/java/or...
Author: sergeyb
Date: Thu Jul 16 14:04:24 2009
New Revision: 794680
URL: http://svn.apache.org/viewvc?rev=794680&view=rev
Log:
JAXRS : initial support for writing and reading explicit lists and arrays
Added:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/CollectionsResource.java (with props)
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/Messages.properties
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JAXBElementProviderTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JSONProviderTest.java
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java?rev=794680&r1=794679&r2=794680&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java Thu Jul 16 14:04:24 2009
@@ -21,10 +21,14 @@
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
+import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Logger;
@@ -41,14 +45,20 @@
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import javax.xml.namespace.QName;
import javax.xml.validation.Schema;
import org.apache.cxf.common.i18n.BundleUtils;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.PackageUtils;
+import org.apache.cxf.common.util.ReflectionInvokationHandler;
+import org.apache.cxf.jaxb.JAXBBeanInfo;
+import org.apache.cxf.jaxb.JAXBContextProxy;
+import org.apache.cxf.jaxb.JAXBUtils;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.utils.AnnotationUtils;
import org.apache.cxf.jaxrs.utils.InjectionUtils;
@@ -60,22 +70,140 @@
protected static final ResourceBundle BUNDLE = BundleUtils.getBundle(AbstractJAXBProvider.class);
private static final Logger LOG = LogUtils.getL7dLogger(AbstractJAXBProvider.class);
+
+ private static final String JAXB_DEFAULT_NAMESPACE = "##default";
+ private static final String JAXB_DEFAULT_NAME = "##default";
private static final String CHARSET_PARAMETER = "charset";
private static Map<String, JAXBContext> packageContexts = new WeakHashMap<String, JAXBContext>();
private static Map<Class<?>, JAXBContext> classContexts = new WeakHashMap<Class<?>, JAXBContext>();
+ private static Set<Class<?>> collectionContextClasses = new HashSet<Class<?>>();
+ private static JAXBContext collectionContext;
+
private MessageContext mc;
private Schema schema;
+ private String collectionWrapperName;
+ private Map<String, String> collectionWrapperMap;
+
+ public void setCollectionWrapperName(String wName) {
+ collectionWrapperName = wName;
+ }
+
+ public void setCollectionWrapperMap(Map<String, String> map) {
+ collectionWrapperMap = map;
+ }
protected void setContext(MessageContext context) {
mc = context;
}
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] anns, MediaType mt) {
+
+ if (InjectionUtils.isSupportedCollectionOrArray(type)) {
+ type = InjectionUtils.getActualType(genericType);
+ if (type == null) {
+ return false;
+ }
+ }
+
return isSupported(type, genericType, anns);
}
+ protected JAXBContext getCollectionContext(Class<?> type) throws JAXBException {
+ synchronized (collectionContextClasses) {
+ if (!collectionContextClasses.contains(type)) {
+ collectionContextClasses.add(CollectionWrapper.class);
+ collectionContextClasses.add(type);
+ }
+ collectionContext = JAXBContext.newInstance(collectionContextClasses.toArray(new Class[]{}));
+ return collectionContext;
+ }
+ }
+
+ protected QName getCollectionWrapperQName(Class<?> cls, Type type, Object object, boolean pluralName)
+ throws Exception {
+ String name = getCollectionWrapperName(cls);
+ if (name == null) {
+ return getJaxbQName(cls, type, object, pluralName);
+ }
+
+ int ind1 = name.indexOf('{');
+ if (ind1 != 0) {
+ return new QName(name);
+ }
+
+ int ind2 = name.indexOf('}');
+ if (ind2 <= ind1 + 1 || ind2 >= name.length() - 1) {
+ return null;
+ }
+ String ns = name.substring(ind1 + 1, ind2);
+ String localName = name.substring(ind2 + 1);
+ return new QName(ns, localName);
+ }
+
+ private String getCollectionWrapperName(Class<?> cls) {
+ if (collectionWrapperName != null) {
+ return collectionWrapperName;
+ }
+ if (collectionWrapperMap != null) {
+ return collectionWrapperMap.get(cls.getName());
+ }
+
+ return null;
+ }
+
+ protected QName getJaxbQName(Class<?> cls, Type type, Object object, boolean pluralName)
+ throws Exception {
+ //try the easy way first
+ XmlRootElement root = cls.getAnnotation(XmlRootElement.class);
+ QName qname = null;
+ if (root != null) {
+ String namespace = getNamespace(root.namespace());
+ String name = getLocalName(root.name(), cls.getSimpleName(), pluralName);
+ return new QName(namespace, name);
+ } else {
+ JAXBContext context = getJAXBContext(cls, type);
+ JAXBContextProxy proxy = ReflectionInvokationHandler.createProxyWrapper(context,
+ JAXBContextProxy.class);
+ JAXBBeanInfo info = JAXBUtils.getBeanInfo(proxy, cls);
+ if (info != null) {
+ try {
+ Object instance = object == null ? cls.newInstance() : object;
+ String name = getLocalName(info.getElementLocalName(instance), cls.getSimpleName(),
+ pluralName);
+ String namespace = getNamespace(info.getElementNamespaceURI(instance));
+ return new QName(namespace, name);
+ } catch (Exception ex) {
+ // ignore
+ }
+ }
+ }
+ return qname;
+ }
+
+ private String getLocalName(String name, String clsName, boolean pluralName) {
+ 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();
+ }
+ }
+ if (pluralName) {
+ name += 's';
+ }
+ return name;
+ }
+
+ private String getNamespace(String namespace) {
+ if (JAXB_DEFAULT_NAMESPACE.equals(namespace)) {
+ return "";
+ }
+ return namespace;
+ }
+
public boolean isReadable(Class<?> type, Type genericType, Annotation[] anns, MediaType mt) {
return isSupported(type, genericType, anns);
}
@@ -124,7 +252,6 @@
return context != null ? context : getClassContext(type);
}
- // TODO : move this method to a dedicated JAXBContextRegistry class
public JAXBContext getClassContext(Class<?> type) throws JAXBException {
synchronized (classContexts) {
JAXBContext context = classContexts.get(type);
@@ -136,7 +263,6 @@
}
}
- // TODO : move this method to a dedicated JAXBContextRegistry class
public JAXBContext getPackageContext(Class<?> type) {
if (type == null) {
return null;
@@ -159,12 +285,6 @@
}
protected boolean isSupported(Class<?> type, Type genericType, Annotation[] anns) {
- // TODO : Shall we just return true and let readFrom/writeTo
- // fail if JAXB can't handle a given type ?
-
- // TODO: still not checked :
- // - XmlJavaTypeAdapter at package level
- // - anything else ?
return type.getAnnotation(XmlRootElement.class) != null
|| JAXBElement.class.isAssignableFrom(type)
|| objectFactoryForClass(type)
@@ -193,7 +313,13 @@
protected Unmarshaller createUnmarshaller(Class<?> cls, Type genericType)
throws JAXBException {
- JAXBContext context = getJAXBContext(cls, genericType);
+ return createUnmarshaller(cls, genericType, false);
+ }
+
+ protected Unmarshaller createUnmarshaller(Class<?> cls, Type genericType, boolean isCollection)
+ throws JAXBException {
+ JAXBContext context = isCollection ? getCollectionContext(cls)
+ : getJAXBContext(cls, genericType);
Unmarshaller unmarshaller = context.createUnmarshaller();
if (schema != null) {
unmarshaller.setSchema(schema);
@@ -201,12 +327,15 @@
return unmarshaller;
}
- protected Marshaller createMarshaller(Object obj, Class<?> cls, Type genericType, String enc)
+ protected Marshaller createMarshaller(Object obj, Class<?> cls, Type genericType, String enc,
+ boolean isCollection)
throws JAXBException {
Class<?> objClazz = JAXBElement.class.isAssignableFrom(cls)
? ((JAXBElement)obj).getDeclaredType() : cls;
- JAXBContext context = getJAXBContext(objClazz, genericType);
+
+ JAXBContext context = isCollection ? getCollectionContext(objClazz)
+ : getJAXBContext(objClazz, genericType);
Marshaller marshaller = context.createMarshaller();
if (enc != null) {
marshaller.setProperty(Marshaller.JAXB_ENCODING, enc);
@@ -214,6 +343,12 @@
return marshaller;
}
+ protected Marshaller createMarshaller(Object obj, Class<?> cls, Type genericType, String enc)
+ throws JAXBException {
+
+ return createMarshaller(obj, cls, genericType, enc, false);
+ }
+
protected String getEncoding(MediaType mt, MultivaluedMap<String, Object> headers) {
String enc = mt.getParameters().get(CHARSET_PARAMETER);
if (enc == null) {
@@ -296,13 +431,56 @@
}
protected static void handleJAXBException(JAXBException e) {
+ StringBuilder sb = new StringBuilder();
+ if (e.getMessage() != null) {
+ sb.append(e.getMessage()).append(". ");
+ }
+ if (e.getCause() != null && e.getCause().getMessage() != null) {
+ sb.append(e.getCause().getMessage()).append(". ");
+ }
+ if (e.getLinkedException() != null && e.getLinkedException().getMessage() != null) {
+ sb.append(e.getLinkedException().getMessage()).append(". ");
+ }
Throwable t = e.getLinkedException() != null
? e.getLinkedException() : e.getCause() != null ? e.getCause() : e;
String message = new org.apache.cxf.common.i18n.Message("JAXB_EXCEPTION",
- BUNDLE, t.getMessage()).toString();
+ BUNDLE, sb.toString()).toString();
LOG.warning(message);
Response r = Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.type(MediaType.TEXT_PLAIN).entity(message).build();
throw new WebApplicationException(t, r);
}
+
+ @XmlRootElement
+ protected static class CollectionWrapper {
+
+ @XmlAnyElement(lax = true)
+ private List<?> l;
+
+ public void setList(List<?> list) {
+ l = list;
+ }
+
+ public List<?> getList() {
+ if (l == null) {
+ l = new ArrayList<Object>();
+ }
+ return l;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> Object getCollectionOrArray(Class<T> type, boolean isArray) {
+ List<?> theList = getList();
+ if (isArray) {
+ T[] values = (T[])Array.newInstance(type, theList.size());
+ for (int i = 0; i < theList.size(); i++) {
+ values[i] = (T)theList.get(i);
+ }
+ return values;
+ } else {
+ return theList;
+ }
+ }
+
+ }
}
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java?rev=794680&r1=794679&r2=794680&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java Thu Jul 16 14:04:24 2009
@@ -25,6 +25,8 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -35,18 +37,24 @@
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
+import javax.xml.bind.PropertyException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationEventHandler;
+import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.stream.StreamSource;
+import org.apache.cxf.jaxb.NamespaceMapper;
import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
import org.apache.cxf.jaxrs.utils.schemas.SchemaHandler;
+import org.apache.cxf.staxutils.DepthXMLStreamReader;
import org.apache.cxf.staxutils.StaxUtils;
@Produces({"application/xml", "application/*+xml", "text/xml" })
@@ -65,6 +73,19 @@
private boolean enableStreaming;
private ValidationEventHandler eventHandler;
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType, Annotation[] anns, MediaType mt) {
+
+ if (InjectionUtils.isSupportedCollectionOrArray(type)) {
+ type = InjectionUtils.getActualType(genericType);
+ if (type == null) {
+ return false;
+ }
+ }
+
+ return isSupported(type, genericType, anns);
+ }
+
@Context
public void setMessageContext(MessageContext mc) {
super.setContext(mc);
@@ -114,8 +135,11 @@
MultivaluedMap<String, String> headers, InputStream is)
throws IOException {
try {
- Class<?> theType = getActualType(type, genericType, anns);
- Unmarshaller unmarshaller = createUnmarshaller(theType, genericType);
+ boolean isCollection = InjectionUtils.isSupportedCollectionOrArray(type);
+ Class<?> theType = isCollection ? InjectionUtils.getActualType(genericType) : type;
+ theType = getActualType(theType, genericType, anns);
+
+ Unmarshaller unmarshaller = createUnmarshaller(theType, genericType, isCollection);
if (eventHandler != null) {
unmarshaller.setEventHandler(eventHandler);
}
@@ -123,8 +147,12 @@
if (JAXBElement.class.isAssignableFrom(type)) {
response = unmarshaller.unmarshal(new StreamSource(is), theType);
} else {
- response = doUnmarshal(unmarshaller, is, mt);
+ response = doUnmarshal(unmarshaller, type, is, mt);
}
+ if (isCollection) {
+ response = ((CollectionWrapper)response).getCollectionOrArray(theType, type.isArray());
+ }
+
response = checkAdapter(response, anns, false);
return response;
@@ -139,18 +167,25 @@
return null;
}
- protected Object doUnmarshal(Unmarshaller unmarshaller, InputStream is, MediaType mt)
+ protected Object doUnmarshal(Unmarshaller unmarshaller, Class<?> type, InputStream is, MediaType mt)
throws JAXBException {
- XMLStreamReader reader = getStreamReader(is, mt);
+ XMLStreamReader reader = getStreamReader(is, type, mt);
if (reader != null) {
return unmarshalFromReader(unmarshaller, reader, mt);
}
return unmarshalFromInputStream(unmarshaller, is, mt);
}
- protected XMLStreamReader getStreamReader(InputStream is, MediaType mt) {
+ protected XMLStreamReader getStreamReader(InputStream is, Class<?> type, MediaType mt) {
MessageContext mc = getContext();
- return mc != null ? mc.getContent(XMLStreamReader.class) : null;
+ XMLStreamReader reader = mc != null ? mc.getContent(XMLStreamReader.class) : null;
+ if (InjectionUtils.isSupportedCollectionOrArray(type)) {
+ reader = reader == null ? StaxUtils.createXMLStreamReader(is) : reader;
+ return new JAXBCollectionWrapperReader(reader);
+ } else {
+ return reader;
+ }
+
}
protected Object unmarshalFromInputStream(Unmarshaller unmarshaller, InputStream is, MediaType mt)
@@ -169,11 +204,13 @@
try {
Object actualObject = checkAdapter(obj, anns, true);
Class<?> actualClass = actualObject.getClass();
- if (cls == genericType) {
- genericType = actualClass;
- }
String encoding = getEncoding(m, headers);
- marshal(actualObject, actualClass, genericType, encoding, os, m);
+ if (InjectionUtils.isSupportedCollectionOrArray(actualClass)) {
+ actualClass = InjectionUtils.getActualType(genericType);
+ marshalCollection(cls, actualObject, actualClass, genericType, encoding, os, m);
+ } else {
+ marshal(actualObject, actualClass, genericType, encoding, os, m);
+ }
} catch (JAXBException e) {
handleJAXBException(e);
} catch (WebApplicationException e) {
@@ -183,15 +220,66 @@
}
}
- protected void marshal(Object obj, Class<?> cls, Type genericType,
- String enc, OutputStream os, MediaType mt)
+ protected void marshalCollection(Class<?> originalCls, Object actualObject, Class<?> actualClass,
+ Type genericType, String encoding, OutputStream os, MediaType m)
throws Exception {
+ QName qname = getCollectionWrapperQName(actualClass, genericType, actualObject, true);
+ if (qname == null) {
+ String message = new org.apache.cxf.common.i18n.Message("NO_COLLECTION_ROOT",
+ BUNDLE).toString();
+ throw new WebApplicationException(Response.serverError()
+ .entity(message).build());
+ }
+
+ String startTag = null;
+ String endTag = null;
+ if (qname.getNamespaceURI().length() > 0) {
+ startTag = "<ns1:" + qname.getLocalPart() + " xmlns:ns1=\"" + qname.getNamespaceURI()
+ + "\">";
+ endTag = "</ns1:" + qname.getLocalPart() + ">";
+ } else {
+ startTag = "<" + qname.getLocalPart() + ">";
+ endTag = "</" + qname.getLocalPart() + ">";
+ }
+ os.write(startTag.getBytes());
+ Object[] arr = originalCls.isArray() ? (Object[])actualObject : ((Collection)actualObject).toArray();
+ for (Object o : arr) {
+ marshalCollectionMember(o, actualClass, genericType, encoding, os, m,
+ qname.getNamespaceURI());
+ }
+ os.write(endTag.getBytes());
+ }
+
+ protected void marshalCollectionMember(Object obj, Class<?> cls, Type genericType,
+ String enc, OutputStream os, MediaType mt, String ns) throws Exception {
Marshaller ms = createMarshaller(obj, cls, genericType, enc);
+ ms.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
+ if (ns.length() > 0) {
+ Map<String, String> map = Collections.singletonMap(ns, "ns1");
+ NamespaceMapper nsMapper = new NamespaceMapper(map);
+ try {
+ ms.setProperty("com.sun.xml.bind.namespacePrefixMapper", nsMapper);
+ } catch (PropertyException ex) {
+ ms.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", nsMapper);
+ }
+ }
+ marshal(obj, cls, genericType, enc, os, mt, ms);
+ }
+
+ protected void marshal(Object obj, Class<?> cls, Type genericType,
+ String enc, OutputStream os, MediaType mt) throws Exception {
+ Marshaller ms = createMarshaller(obj, cls, genericType, enc);
+ marshal(obj, cls, genericType, enc, os, mt, ms);
+ }
+
+ protected void marshal(Object obj, Class<?> cls, Type genericType,
+ String enc, OutputStream os, MediaType mt, Marshaller ms)
+ throws Exception {
+
for (Map.Entry<String, Object> entry : mProperties.entrySet()) {
ms.setProperty(entry.getKey(), entry.getValue());
}
-
MessageContext mc = getContext();
if (mc != null) {
// check Marshaller properties which might've been set earlier on,
@@ -236,4 +324,35 @@
throws Exception {
ms.marshal(obj, writer);
}
+
+
+ protected static class JAXBCollectionWrapperReader extends DepthXMLStreamReader {
+
+ private boolean firstName;
+ private boolean firstNs;
+
+ public JAXBCollectionWrapperReader(XMLStreamReader reader) {
+ super(reader);
+ }
+
+ @Override
+ public String getNamespaceURI() {
+ if (!firstNs) {
+ firstNs = true;
+ return "";
+ }
+ return super.getNamespaceURI();
+ }
+
+ @Override
+ public String getLocalName() {
+ if (!firstName) {
+ firstName = true;
+ return "collectionWrapper";
+ }
+
+ return super.getLocalName();
+ }
+
+ }
}
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java?rev=794680&r1=794679&r2=794680&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java Thu Jul 16 14:04:24 2009
@@ -28,6 +28,7 @@
import java.io.SequenceInputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
+import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
@@ -39,23 +40,21 @@
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
-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.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
-import org.apache.cxf.common.util.ReflectionInvokationHandler;
-import org.apache.cxf.jaxb.JAXBBeanInfo;
-import org.apache.cxf.jaxb.JAXBContextProxy;
-import org.apache.cxf.jaxb.JAXBUtils;
import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
import org.apache.cxf.jaxrs.utils.schemas.SchemaHandler;
+import org.apache.cxf.staxutils.DelegatingXMLStreamWriter;
import org.codehaus.jettison.AbstractXMLStreamWriter;
import org.codehaus.jettison.mapped.Configuration;
import org.codehaus.jettison.mapped.MappedNamespaceConvention;
@@ -67,9 +66,6 @@
@Provider
public class JSONProvider extends AbstractJAXBProvider {
- private static final String JAXB_DEFAULT_NAMESPACE = "##default";
- private static final String JAXB_DEFAULT_NAME = "##default";
-
private Map<String, String> namespaceMap = new HashMap<String, String>();
private boolean serializeAsArray;
private List<String> arrayKeys;
@@ -132,12 +128,10 @@
try {
Class<?> theType = getActualType(type, genericType, anns);
-
Unmarshaller unmarshaller = createUnmarshaller(theType, genericType);
InputStream realStream = getInputStream(type, genericType, is);
- MappedXMLInputFactory factory = new MappedXMLInputFactory(namespaceMap);
- XMLStreamReader xsw = factory.createXMLStreamReader(realStream);
+ XMLStreamReader xsw = getStreamReader(type, realStream);
Object response = null;
if (JAXBElement.class.isAssignableFrom(type)) {
@@ -161,11 +155,18 @@
return null;
}
+ protected XMLStreamReader getStreamReader(Class<?> type, InputStream is)
+ throws Exception {
+ MappedXMLInputFactory factory = new MappedXMLInputFactory(namespaceMap);
+ return factory.createXMLStreamReader(is);
+ }
+
protected InputStream getInputStream(Class<Object> cls, Type type, InputStream is) throws Exception {
if (unwrapped) {
String rootName = getRootName(cls, type);
InputStream isBefore = new ByteArrayInputStream(rootName.getBytes());
- InputStream isAfter = new ByteArrayInputStream("}".getBytes());
+ String after = "}";
+ InputStream isAfter = new ByteArrayInputStream(after.getBytes());
final InputStream[] streams = new InputStream[]{isBefore, is, isAfter};
Enumeration<InputStream> list = new Enumeration<InputStream>() {
@@ -225,27 +226,12 @@
if (encoding == null) {
encoding = "UTF-8";
}
- Marshaller ms = createMarshaller(actualObject, actualClass, genericType, encoding);
-
- QName qname = getQName(actualClass, genericType, actualObject, true);
- Configuration c = new Configuration(namespaceMap);
- MappedNamespaceConvention convention = new MappedNamespaceConvention(c);
- AbstractXMLStreamWriter xsw = new MappedXMLStreamWriter(
- convention,
- new OutputStreamWriter(os, encoding));
- if (serializeAsArray) {
- if (arrayKeys != null) {
- for (String key : arrayKeys) {
- xsw.seriliazeAsArray(key);
- }
- } else {
- String key = getKey(convention, qname);
- xsw.seriliazeAsArray(key);
- }
+ if (InjectionUtils.isSupportedCollectionOrArray(actualClass)) {
+ actualClass = InjectionUtils.getActualType(genericType);
+ marshalCollection(cls, actualObject, actualClass, genericType, encoding, os, m);
+ } else {
+ marshal(actualObject, actualClass, genericType, encoding, os);
}
-
- ms.marshal(actualObject, xsw);
- xsw.close();
} catch (JAXBException e) {
handleJAXBException(e);
@@ -256,61 +242,85 @@
}
}
- private String getKey(MappedNamespaceConvention convention, QName qname) throws Exception {
- return convention.createKey(qname.getPrefix(),
- qname.getNamespaceURI(),
- qname.getLocalPart());
-
-
- }
-
- private QName getQName(Class<?> cls, Type type, Object object, boolean allocatePrefix)
+ protected void marshalCollection(Class<?> originalCls, Object actualObject, Class<?> actualClass,
+ Type genericType, String encoding, OutputStream os, MediaType m)
throws Exception {
- //try the easy way first
- XmlRootElement root = cls.getAnnotation(XmlRootElement.class);
- QName qname = null;
- if (root != null) {
- String namespace = getNamespace(root.namespace());
- String name = getLocalName(root.name(), cls.getSimpleName());
- String prefix = getPrefix(namespace, allocatePrefix);
- qname = new QName(namespace, name, prefix);
+
+ QName qname = getCollectionWrapperQName(actualClass, genericType, actualObject, false);
+ if (qname == null) {
+ String message = new org.apache.cxf.common.i18n.Message("NO_COLLECTION_ROOT",
+ BUNDLE).toString();
+ throw new WebApplicationException(Response.serverError()
+ .entity(message).build());
+ }
+ String startTag = null;
+ String endTag = null;
+ if (qname.getNamespaceURI().length() > 0) {
+ startTag = "{\"ns1." + qname.getLocalPart() + "\":[";
} else {
- JAXBContext context = getJAXBContext(cls, type);
- JAXBContextProxy proxy = ReflectionInvokationHandler.createProxyWrapper(context,
- JAXBContextProxy.class);
- JAXBBeanInfo info = JAXBUtils.getBeanInfo(proxy, cls);
- if (info != null) {
- try {
- Object instance = object == null ? cls.newInstance() : object;
- String name = getLocalName(info.getElementLocalName(instance), cls.getSimpleName());
- String namespace = getNamespace(info.getElementNamespaceURI(instance));
- String prefix = getPrefix(namespace, allocatePrefix);
- qname = new QName(namespace, name, prefix);
- } catch (Exception ex) {
- // ignore
- }
+ startTag = "{\"" + qname.getLocalPart() + "\":[";
+ }
+ endTag = "]}";
+ os.write(startTag.getBytes());
+ Object[] arr = originalCls.isArray() ? (Object[])actualObject : ((Collection)actualObject).toArray();
+ for (int i = 0; i < arr.length; i++) {
+ Marshaller ms = createMarshaller(actualObject, actualClass, genericType, encoding);
+ marshal(ms, arr[i], actualClass, genericType, encoding, os, true);
+ if (i + 1 < arr.length) {
+ os.write(",".getBytes());
}
}
- return qname;
+ os.write(endTag.getBytes());
}
- private 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);
+ protected void marshal(Marshaller ms, Object actualObject, Class<?> actualClass,
+ Type genericType, String enc, OutputStream os, boolean isCollection) throws Exception {
+ QName qname = getQName(actualClass, genericType, actualObject, true);
+ Configuration c = new Configuration(namespaceMap);
+ MappedNamespaceConvention convention = new MappedNamespaceConvention(c);
+ AbstractXMLStreamWriter xsw = new MappedXMLStreamWriter(
+ convention,
+ new OutputStreamWriter(os, enc));
+ if (serializeAsArray) {
+ if (arrayKeys != null) {
+ for (String key : arrayKeys) {
+ xsw.seriliazeAsArray(key);
+ }
} else {
- name = name.toLowerCase();
+ String key = getKey(convention, qname);
+ xsw.seriliazeAsArray(key);
}
}
- return name;
+
+ XMLStreamWriter writer = isCollection ? new JSONCollectionWriter(xsw, qname) : xsw;
+ ms.marshal(actualObject, writer);
+ xsw.close();
}
- private String getNamespace(String namespace) {
- if (JAXB_DEFAULT_NAMESPACE.equals(namespace)) {
- return "";
+
+
+ protected void marshal(Object actualObject, Class<?> actualClass,
+ Type genericType, String enc, OutputStream os) throws Exception {
+ Marshaller ms = createMarshaller(actualObject, actualClass, genericType, enc);
+ marshal(ms, actualObject, actualClass, genericType, enc, os, false);
+ }
+
+ private String getKey(MappedNamespaceConvention convention, QName qname) throws Exception {
+ return convention.createKey(qname.getPrefix(),
+ qname.getNamespaceURI(),
+ qname.getLocalPart());
+
+
+ }
+
+ private QName getQName(Class<?> cls, Type type, Object object, boolean allocatePrefix)
+ throws Exception {
+ QName qname = getJaxbQName(cls, type, object, false);
+ if (qname != null) {
+ String prefix = getPrefix(qname.getNamespaceURI(), allocatePrefix);
+ return new QName(qname.getNamespaceURI(), qname.getLocalPart(), prefix);
}
- return namespace;
+ return null;
}
private String getPrefix(String namespace, boolean allocatePrefix) {
@@ -325,4 +335,23 @@
}
return prefix;
}
+
+ protected static class JSONCollectionWriter extends DelegatingXMLStreamWriter {
+ private QName ignoredQName;
+ public JSONCollectionWriter(XMLStreamWriter writer, QName qname) {
+ super(writer);
+ ignoredQName = qname;
+ }
+
+ @Override
+ public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException {
+ if (ignoredQName.getLocalPart().equals(local)
+ && ignoredQName.getNamespaceURI().equals(uri)) {
+ return;
+ }
+ super.writeStartElement(prefix, local, uri);
+ }
+ }
+
+
}
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/Messages.properties
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/Messages.properties?rev=794680&r1=794679&r2=794680&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/Messages.properties (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/Messages.properties Thu Jul 16 14:04:24 2009
@@ -19,5 +19,6 @@
#
#
JAXB_EXCEPTION=JAXBException occurred : {0}
-UNSUPPORTED_ENCODING=Unsupported encoding : {0}, defaulting to UTF-8
+UNSUPPORTED_ENCODING=Unsupported encoding : {0}, defaulting to UTF-8
+NO_COLLECTION_ROOT=No collection name is provided
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JAXBElementProviderTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JAXBElementProviderTest.java?rev=794680&r1=794679&r2=794680&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JAXBElementProviderTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JAXBElementProviderTest.java Thu Jul 16 14:04:24 2009
@@ -19,11 +19,13 @@
package org.apache.cxf.jaxrs.provider;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.io.Writer;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
@@ -48,6 +50,9 @@
import org.xml.sax.ContentHandler;
import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.jaxrs.resources.Book;
+import org.apache.cxf.jaxrs.resources.CollectionsResource;
+import org.apache.cxf.jaxrs.resources.TagVO2;
import org.junit.Assert;
import org.junit.Test;
@@ -55,6 +60,135 @@
public class JAXBElementProviderTest extends Assert {
@Test
+ public void testIsWriteableCollection() throws Exception {
+ JAXBElementProvider provider = new JAXBElementProvider();
+ provider.setCollectionWrapperName("foo");
+ Method m = CollectionsResource.class.getMethod("getBooks", new Class[0]);
+ assertTrue(provider.isWriteable(m.getReturnType(), m.getGenericReturnType(),
+ new Annotation[0], MediaType.TEXT_XML_TYPE));
+ }
+
+ @Test
+ public void testWriteCollection() throws Exception {
+ doWriteUnqualifiedCollection(true, false);
+ }
+
+ @Test
+ public void testWriteCollectionJaxbName() throws Exception {
+ doWriteUnqualifiedCollection(false, false);
+ }
+
+ @Test
+ public void testWriteArray() throws Exception {
+ doWriteUnqualifiedCollection(true, true);
+ }
+
+ public void doWriteUnqualifiedCollection(boolean setName, boolean isArray) throws Exception {
+ JAXBElementProvider provider = new JAXBElementProvider();
+ if (setName) {
+ provider.setCollectionWrapperName("Books");
+ }
+ List<Book> books = new ArrayList<Book>();
+ books.add(new Book("CXF in Action", 123L));
+ books.add(new Book("CXF Rocks", 124L));
+ String mName = isArray ? "getBooksArray" : "getBooks";
+ Method m = CollectionsResource.class.getMethod(mName, new Class[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ provider.writeTo(isArray ? books.toArray() : books, m.getReturnType(), m.getGenericReturnType(),
+ new Annotation[0], MediaType.TEXT_XML_TYPE, new MetadataMap<String, Object>(), bos);
+ doReadUnqualifiedCollection(bos.toString());
+ }
+
+ @Test
+ public void testWriteQualifiedCollection() throws Exception {
+ JAXBElementProvider provider = new JAXBElementProvider();
+ provider.setCollectionWrapperName("{http://tags}tags");
+ List<TagVO2> tags = new ArrayList<TagVO2>();
+ tags.add(new TagVO2("A", "B"));
+ tags.add(new TagVO2("C", "D"));
+ Method m = CollectionsResource.class.getMethod("getTags", new Class[0]);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ provider.writeTo(tags, m.getReturnType(), m.getGenericReturnType(),
+ new Annotation[0], MediaType.TEXT_XML_TYPE, new MetadataMap<String, Object>(), bos);
+ doReadQualifiedCollection(bos.toString(), false);
+ }
+
+ @Test
+ public void testReadUnqualifiedCollection() throws Exception {
+ String data = "<Books><Book><id>123</id><name>CXF in Action</name>"
+ + "</Book><Book><id>124</id><name>CXF Rocks</name></Book></Books>";
+ doReadUnqualifiedCollection(data);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void doReadUnqualifiedCollection(String data) throws Exception {
+ JAXBElementProvider provider = new JAXBElementProvider();
+ Method m = CollectionsResource.class.getMethod("setBooks",
+ new Class[]{List.class});
+ ByteArrayInputStream is = new ByteArrayInputStream(data.getBytes());
+ List<Book> books = (List<Book>)provider.readFrom(
+ (Class)m.getParameterTypes()[0], m.getGenericParameterTypes()[0],
+ new Annotation[0], MediaType.TEXT_XML_TYPE, new MetadataMap<String, String>(), is);
+ assertNotNull(books);
+ assertEquals(2, books.size());
+ Book b1 = books.get(0);
+ assertEquals(123, b1.getId());
+ assertEquals("CXF in Action", b1.getName());
+
+ Book b2 = books.get(1);
+ assertEquals(124, b2.getId());
+ assertEquals("CXF Rocks", b2.getName());
+ }
+
+
+ @Test
+ public void testReadQualifiedCollection() throws Exception {
+ String data = "<ns1:tags xmlns:ns1=\"http://tags\"><ns1:thetag><group>B</group><name>A</name>"
+ + "</ns1:thetag><ns1:thetag><group>D</group><name>C</name></ns1:thetag></ns1:tags>";
+ doReadQualifiedCollection(data, false);
+ }
+
+ @Test
+ public void testReadQualifiedArray() throws Exception {
+ String data = "<ns1:tags xmlns:ns1=\"http://tags\"><ns1:thetag><group>B</group><name>A</name>"
+ + "</ns1:thetag><ns1:thetag><group>D</group><name>C</name></ns1:thetag></ns1:tags>";
+ doReadQualifiedCollection(data, true);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void doReadQualifiedCollection(String data, boolean isArray) throws Exception {
+ JAXBElementProvider provider = new JAXBElementProvider();
+ Method m = null;
+ if (!isArray) {
+ m = CollectionsResource.class.getMethod("setTags", new Class[]{List.class});
+ } else {
+ m = CollectionsResource.class.getMethod("setTagsArray", new Class[]{TagVO2[].class});
+ }
+
+ ByteArrayInputStream is = new ByteArrayInputStream(data.getBytes());
+ Object o = provider.readFrom(
+ (Class)m.getParameterTypes()[0], m.getGenericParameterTypes()[0],
+ new Annotation[0], MediaType.TEXT_XML_TYPE, new MetadataMap<String, String>(), is);
+ assertNotNull(o);
+ TagVO2 t1 = null;
+ TagVO2 t2 = null;
+ if (!isArray) {
+ assertEquals(2, ((List)o).size());
+ t1 = (TagVO2)((List)o).get(0);
+ t2 = (TagVO2)((List)o).get(1);
+ } else {
+ assertEquals(2, ((Object[])o).length);
+ t1 = (TagVO2)((Object[])o)[0];
+ t2 = (TagVO2)((Object[])o)[1];
+ }
+ assertEquals("A", t1.getName());
+ assertEquals("B", t1.getGroup());
+
+ assertEquals("C", t2.getName());
+ assertEquals("D", t2.getGroup());
+ }
+
+ @Test
public void testSetSchemasFromClasspath() {
JAXBElementProvider provider = new JAXBElementProvider();
List<String> locations = new ArrayList<String>();
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JSONProviderTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JSONProviderTest.java?rev=794680&r1=794679&r2=794680&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JSONProviderTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JSONProviderTest.java Thu Jul 16 14:04:24 2009
@@ -21,6 +21,9 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -30,12 +33,14 @@
import javax.ws.rs.ext.MessageBodyReader;
import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.jaxrs.resources.CollectionsResource;
import org.apache.cxf.jaxrs.resources.ManyTags;
import org.apache.cxf.jaxrs.resources.TagVO;
import org.apache.cxf.jaxrs.resources.TagVO2;
import org.apache.cxf.jaxrs.resources.Tags;
import org.junit.Assert;
+import org.junit.Ignore;
import org.junit.Test;
public class JSONProviderTest extends Assert {
@@ -161,6 +166,83 @@
}
@Test
+ public void testWriteQualifiedCollection() throws Exception {
+ JSONProvider p = new JSONProvider();
+ p.setCollectionWrapperName("{http://tags}tag");
+ Map<String, String> namespaceMap = new HashMap<String, String>();
+ namespaceMap.put("http://tags", "ns1");
+ p.setNamespaceMap(namespaceMap);
+ List<TagVO2> tags = new ArrayList<TagVO2>();
+ tags.add(createTag2("a", "b"));
+ tags.add(createTag2("c", "d"));
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ Method m = CollectionsResource.class.getMethod("getTags", new Class[0]);
+ p.writeTo(tags, m.getReturnType(), m.getGenericReturnType(), new Annotation[0],
+ MediaType.APPLICATION_JSON_TYPE, new MetadataMap<String, Object>(), os);
+
+ String s = os.toString();
+ String data = "{\"ns1.tag\":[{\"group\":\"b\",\"name\":\"a\"}"
+ + ",{\"group\":\"d\",\"name\":\"c\"}]}";
+ assertEquals(s, data);
+ }
+
+ @Test
+ @Ignore
+ public void testReadQualifiedCollection() throws Exception {
+ String data = "{\"ns1.tag\":[{\"group\":\"b\",\"name\":\"a\"}"
+ + ",{\"group\":\"d\",\"name\":\"c\"}]}";
+ doReadQualifiedCollection(data, false);
+ }
+
+ @Test
+ @Ignore
+ public void testReadQualifiedArray() throws Exception {
+ String data = "{\"ns1.tag\":[{\"group\":\"b\",\"name\":\"a\"}"
+ + ",{\"group\":\"d\",\"name\":\"c\"}]}";
+ doReadQualifiedCollection(data, true);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void doReadQualifiedCollection(String data, boolean isArray) throws Exception {
+
+ JSONProvider provider = new JSONProvider();
+ provider.setCollectionWrapperName("{http://tags}tag");
+ Map<String, String> namespaceMap = new HashMap<String, String>();
+ namespaceMap.put("http://tags", "ns1");
+ provider.setNamespaceMap(namespaceMap);
+
+ Method m = null;
+ if (!isArray) {
+ m = CollectionsResource.class.getMethod("setTags", new Class[]{List.class});
+ } else {
+ m = CollectionsResource.class.getMethod("setTagsArray", new Class[]{TagVO2[].class});
+ }
+
+ ByteArrayInputStream is = new ByteArrayInputStream(data.getBytes());
+ Object o = provider.readFrom(
+ (Class)m.getParameterTypes()[0], m.getGenericParameterTypes()[0],
+ new Annotation[0], MediaType.APPLICATION_JSON_TYPE,
+ new MetadataMap<String, String>(), is);
+ assertNotNull(o);
+ TagVO2 t1 = null;
+ TagVO2 t2 = null;
+ if (!isArray) {
+ assertEquals(2, ((List)o).size());
+ t1 = (TagVO2)((List)o).get(0);
+ t2 = (TagVO2)((List)o).get(1);
+ } else {
+ assertEquals(2, ((Object[])o).length);
+ t1 = (TagVO2)((Object[])o)[0];
+ t2 = (TagVO2)((Object[])o)[1];
+ }
+ assertEquals("A", t1.getName());
+ assertEquals("B", t1.getGroup());
+
+ assertEquals("C", t2.getName());
+ assertEquals("D", t2.getGroup());
+ }
+
+ @Test
public void testWriteToSingleQualifiedTag2() throws Exception {
JSONProvider p = new JSONProvider();
TagVO2 tag = createTag2("a", "b");
@@ -229,6 +311,7 @@
MediaType.APPLICATION_JSON_TYPE, new MetadataMap<String, Object>(), os);
String s = os.toString();
+ System.out.println(s);
assertEquals(
"{\"ManyTags\":{\"tags\":{\"list\":[{\"group\":\"b\",\"name\":\"a\"}]}}}",
s);
Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/CollectionsResource.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/CollectionsResource.java?rev=794680&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/CollectionsResource.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/CollectionsResource.java Thu Jul 16 14:04:24 2009
@@ -0,0 +1,54 @@
+/**
+ * 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.cxf.jaxrs.resources;
+
+import java.util.List;
+
+import javax.ws.rs.GET;
+
+import javax.ws.rs.POST;
+
+public class CollectionsResource {
+ @GET
+ public List<Book> getBooks() {
+ return null;
+ }
+
+ @GET
+ public List<TagVO2> getTags() {
+ return null;
+ }
+
+ @GET
+ public Book[] getBooksArray() {
+ return null;
+ }
+
+ @POST
+ public void setBooks(List<Book> books) {
+ }
+
+ @POST
+ public void setTags(List<TagVO2> tags) {
+ }
+
+ @POST
+ public void setTagsArray(TagVO2[] tags) {
+ }
+}
Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/CollectionsResource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/CollectionsResource.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java?rev=794680&r1=794679&r2=794680&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java Thu Jul 16 14:04:24 2009
@@ -137,6 +137,28 @@
return doGetBook(url2.substring(index + 1));
}
+ @POST
+ @Path("/collections")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public List<Book> getBookCollection(List<Book> bs) throws Exception {
+ if (bs == null || bs.size() != 2) {
+ throw new RuntimeException();
+ }
+ return bs;
+ }
+
+ @POST
+ @Path("/array")
+ @Produces("application/xml")
+ @Consumes("application/xml")
+ public Book[] getBookArray(Book[] bs) throws Exception {
+ if (bs == null || bs.length != 2) {
+ throw new RuntimeException();
+ }
+ return bs;
+ }
+
@GET
@Path("/segment/{pathsegment}/")
public Book getBookBySegment(@PathParam("pathsegment") PathSegment segment) throws Exception {
Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java?rev=794680&r1=794679&r2=794680&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java Thu Jul 16 14:04:24 2009
@@ -23,6 +23,7 @@
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -85,6 +86,46 @@
assertEquals("CXF rocks", source.getValue("Book/name"));
}
+ @Test
+ public void testGetBookCollection() throws Exception {
+ BookStore store = JAXRSClientFactory.create("http://localhost:9080", BookStore.class);
+ Book b1 = new Book("CXF in Action", 123L);
+ Book b2 = new Book("CXF Rocks", 124L);
+ List<Book> books = new ArrayList<Book>();
+ books.add(b1);
+ books.add(b2);
+ List<Book> books2 = store.getBookCollection(books);
+ assertNotNull(books2);
+ assertNotSame(books, books2);
+ assertEquals(2, books2.size());
+ Book b11 = books.get(0);
+ assertEquals(123L, b11.getId());
+ assertEquals("CXF in Action", b11.getName());
+ Book b22 = books.get(1);
+ assertEquals(124L, b22.getId());
+ assertEquals("CXF Rocks", b22.getName());
+ }
+
+ @Test
+ public void testGetBookArray() throws Exception {
+ BookStore store = JAXRSClientFactory.create("http://localhost:9080", BookStore.class);
+ Book b1 = new Book("CXF in Action", 123L);
+ Book b2 = new Book("CXF Rocks", 124L);
+ Book[] books = new Book[2];
+ books[0] = b1;
+ books[1] = b2;
+ Book[] books2 = store.getBookArray(books);
+ assertNotNull(books2);
+ assertNotSame(books, books2);
+ assertEquals(2, books2.length);
+ Book b11 = books2[0];
+ assertEquals(123L, b11.getId());
+ assertEquals("CXF in Action", b11.getName());
+ Book b22 = books2[1];
+ assertEquals(124L, b22.getId());
+ assertEquals("CXF Rocks", b22.getName());
+ }
+
@Test
public void testGetBookByURL() throws Exception {
getAndCompareAsStrings("http://localhost:9080/bookstore/bookurl/http%3A%2F%2Ftest.com%2Frss%2F123",