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 2010/02/08 17:41:12 UTC
svn commit: r907718 [1/2] - in /cxf/trunk:
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/
rt/frontend/jaxrs/src/...
Author: sergeyb
Date: Mon Feb 8 16:41:11 2010
New Revision: 907718
URL: http://svn.apache.org/viewvc?rev=907718&view=rev
Log:
JAXRS : WADLgen enhancements, case-insensitive query lookups plus few minor fixes
Added:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLName.java (with props)
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/ElementQNameResolver.java (with props)
cxf/trunk/rt/frontend/jaxrs/src/test/resources/book1.xsd (with props)
cxf/trunk/rt/frontend/jaxrs/src/test/resources/book2.xsd (with props)
cxf/trunk/rt/frontend/jaxrs/src/test/resources/books.xsd (with props)
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLSource.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java
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/XSLTJaxbProvider.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/schemas/SchemaHandler.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/xml/XMLSourceTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookStore.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/jaxb/Book.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/jaxb/Chapter.java
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/utils/JAXRSUtilsTest.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLName.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLName.java?rev=907718&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLName.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLName.java Mon Feb 8 16:41:11 2010
@@ -0,0 +1,43 @@
+/**
+ * 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.ext.xml;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Can be used to assign qualified XML names to arbitrary classes
+ * for the purpose of matching them with external schema definitions
+ *
+ */
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface XMLName {
+ /**
+ * Qualified name, example {http://books}book
+ */
+ String value() default "";
+ /**
+ * Optional prefix
+ **/
+ String prefix() default "";
+}
Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLName.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLName.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLSource.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLSource.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLSource.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLSource.java Mon Feb 8 16:41:11 2010
@@ -18,9 +18,12 @@
*/
package org.apache.cxf.jaxrs.ext.xml;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
+import java.lang.reflect.Method;
import java.net.URI;
import java.util.Collections;
import java.util.Iterator;
@@ -32,6 +35,7 @@
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.xpath.XPath;
@@ -46,9 +50,12 @@
import org.apache.cxf.common.i18n.BundleUtils;
import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.PrimitiveUtils;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.helpers.XMLUtils;
import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
/**
* Utility class for manipulating XML response using XPath and XSLT
@@ -62,6 +69,7 @@
private InputStream stream;
private boolean buffering;
+ private boolean markFailed;
public XMLSource(InputStream is) {
stream = is;
@@ -83,17 +91,14 @@
}
public <T> T getNode(String expression, Map<String, String> namespaces, Class<T> cls) {
- XPath xpath = XPathFactory.newInstance().newXPath();
- xpath.setNamespaceContext(new NamespaceContextImpl(namespaces));
- try {
- Node node = (Node)xpath.evaluate(expression, getSource(), XPathConstants.NODE);
- if (node == null) {
- return null;
- }
- DOMSource ds = new DOMSource(node);
- return readFromSource(ds, cls);
- } catch (XPathExpressionException ex) {
- throw new IllegalArgumentException("Illegal XPath expression '" + expression + "'", ex);
+ Node node = (Node)evaluate(expression, namespaces, XPathConstants.NODE);
+ if (node == null) {
+ return null;
+ }
+ if (cls.isPrimitive() || cls == String.class) {
+ return readPrimitiveValue(node, cls);
+ } else {
+ return readFromSource(new DOMSource(node), cls);
}
}
@@ -103,25 +108,21 @@
@SuppressWarnings("unchecked")
public <T> T[] getNodes(String expression, Map<String, String> namespaces, Class<T> cls) {
- XPath xpath = XPathFactory.newInstance().newXPath();
- xpath.setNamespaceContext(new NamespaceContextImpl(namespaces));
- try {
- NodeList nodes = (NodeList)xpath.evaluate(expression, getSource(), XPathConstants.NODESET);
- if (nodes == null || nodes.getLength() == 0) {
- return null;
+
+ NodeList nodes = (NodeList)evaluate(expression, namespaces, XPathConstants.NODESET);
+ if (nodes == null || nodes.getLength() == 0) {
+ return null;
+ }
+ T[] values = (T[])Array.newInstance(cls, nodes.getLength());
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+ if (InjectionUtils.isPrimitive(cls)) {
+ values[i] = readPrimitiveValue(node, cls);
+ } else {
+ values[i] = readFromSource(new DOMSource(node), cls);
}
- T[] values = (T[])Array.newInstance(cls, nodes.getLength());
-
- for (int i = 0; i < nodes.getLength(); i++) {
- DOMSource ds = new DOMSource(nodes.item(i));
- values[i] = readFromSource(ds, cls);
- }
-
- return values;
-
- } catch (XPathExpressionException ex) {
- throw new IllegalArgumentException("Illegal XPath expression '" + expression + "'", ex);
}
+ return values;
}
public URI getLink(String expression) {
@@ -144,15 +145,34 @@
}
public String getValue(String expression, Map<String, String> namespaces) {
+ return getValue(expression, namespaces, String.class);
+ }
+
+ public <T> T getValue(String expression, Map<String, String> namespaces, Class<T> cls) {
+ Object result = evaluate(expression, namespaces, XPathConstants.STRING);
+ return result == null ? null : convertStringToPrimitive(result.toString(), cls);
+ }
+
+
+ private Object evaluate(String expression, Map<String, String> namespaces, QName type) {
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContextImpl(namespaces));
try {
- return (String)xpath.evaluate(expression, getSource(), XPathConstants.STRING);
+ return xpath.evaluate(expression, getSource(), type);
} catch (XPathExpressionException ex) {
throw new IllegalArgumentException("Illegal XPath expression '" + expression + "'", ex);
}
}
+
+ public String[] getValues(String expression) {
+ return getValues(expression, CastUtils.cast(Collections.emptyMap(), String.class, String.class));
+ }
+
+ public String[] getValues(String expression, Map<String, String> namespaces) {
+ return getNodes(expression, namespaces, String.class);
+ }
+
private static class NamespaceContextImpl implements NamespaceContext {
private Map<String, String> namespaces;
@@ -183,6 +203,41 @@
}
}
+ private <T> T readPrimitiveValue(Node node, Class<T> cls) {
+ if (String.class == cls) {
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ XMLUtils.writeTo(new DOMSource(node), bos, 0, "", "yes");
+ try {
+ return cls.cast(bos.toString("UTF-8"));
+ } catch (UnsupportedEncodingException ex) {
+ // won't happen
+ }
+ } else {
+ return cls.cast(node.getNodeValue());
+ }
+ }
+
+ return convertStringToPrimitive(node.getNodeValue(), cls);
+ }
+
+ private <T> T convertStringToPrimitive(String value, Class<T> cls) {
+ if (String.class == cls) {
+ return cls.cast(value);
+ }
+ if (cls.isPrimitive()) {
+ return cls.cast(PrimitiveUtils.read(value, cls));
+ } else {
+ try {
+ Method m = cls.getMethod("valueOf", new Class[]{String.class});
+ return cls.cast(m.invoke(null, value));
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+
private <T> T readFromSource(Source s, Class<T> cls) {
try {
JAXBElementProvider provider = new JAXBElementProvider();
@@ -199,9 +254,15 @@
private InputSource getSource() {
try {
- if (buffering) {
- stream.reset();
- stream.mark(stream.available());
+ if (!markFailed && buffering) {
+ try {
+ stream.reset();
+ stream.mark(stream.available());
+ } catch (IOException ex) {
+ markFailed = true;
+ LOG.warning(new org.apache.cxf.common.i18n.Message("NO_SOURCE_MARK", BUNDLE).toString());
+ stream = IOUtils.loadIntoBAIS(stream);
+ }
}
} catch (IOException ex) {
LOG.warning(new org.apache.cxf.common.i18n.Message("NO_SOURCE_MARK", BUNDLE).toString());
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java Mon Feb 8 16:41:11 2010
@@ -43,18 +43,16 @@
public class UriInfoImpl implements UriInfo {
private static final Logger LOG = LogUtils.getL7dLogger(UriInfoImpl.class);
+ private static final String CASE_INSENSITIVE_QUERIES = "org.apache.cxf.http.case_insensitive_queries";
private MultivaluedMap<String, String> templateParams;
private Message message;
private OperationResourceInfoStack stack;
+ private boolean caseInsensitiveQueries;
@SuppressWarnings("unchecked")
public UriInfoImpl(Message m) {
- this.message = m;
- this.templateParams = (MultivaluedMap<String, String>)m.get(URITemplate.TEMPLATE_PARAMETERS);
- if (m != null) {
- this.stack = m.get(OperationResourceInfoStack.class);
- }
+ this(m, (MultivaluedMap<String, String>)m.get(URITemplate.TEMPLATE_PARAMETERS));
}
public UriInfoImpl(Message m, MultivaluedMap<String, String> templateParams) {
@@ -62,6 +60,8 @@
this.templateParams = templateParams;
if (m != null) {
this.stack = m.get(OperationResourceInfoStack.class);
+ this.caseInsensitiveQueries =
+ MessageUtils.isTrue(m.getContextualProperty(CASE_INSENSITIVE_QUERIES));
}
}
@@ -109,7 +109,15 @@
}
public MultivaluedMap<String, String> getQueryParameters(boolean decode) {
- return JAXRSUtils.getStructuredParams((String)message.get(Message.QUERY_STRING), "&", decode);
+
+ if (!caseInsensitiveQueries) {
+ return JAXRSUtils.getStructuredParams((String)message.get(Message.QUERY_STRING), "&", decode);
+ }
+
+ MultivaluedMap<String, String> queries = new MetadataMap<String, String>(false, true);
+ JAXRSUtils.getStructuredParams(queries, (String)message.get(Message.QUERY_STRING), "&", decode);
+ return queries;
+
}
public URI getRequestUri() {
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java Mon Feb 8 16:41:11 2010
@@ -336,12 +336,15 @@
Response excResponse = JAXRSUtils.convertFaultToResponse(ex, message);
if (excResponse != null) {
serializeMessage(message, excResponse, ori, false);
+ return;
+ } else {
+ ex.printStackTrace();
}
- } else {
- message.put(Message.RESPONSE_CODE, 500);
- writeResponseErrorMessage(out, "SERIALIZE_ERROR",
- responseObj.getClass().getSimpleName());
- }
+ }
+ message.put(Message.RESPONSE_CODE, 500);
+ writeResponseErrorMessage(out, "SERIALIZE_ERROR",
+ responseObj.getClass().getSimpleName());
+
}
Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/ElementQNameResolver.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/ElementQNameResolver.java?rev=907718&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/ElementQNameResolver.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/ElementQNameResolver.java Mon Feb 8 16:41:11 2010
@@ -0,0 +1,28 @@
+/**
+ * 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.model.wadl;
+
+import java.lang.annotation.Annotation;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+public interface ElementQNameResolver {
+ QName resolve(Class<?> type, Annotation[] annotations, Map<Class<?>, QName> clsMap);
+}
Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/ElementQNameResolver.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/ElementQNameResolver.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java Mon Feb 8 16:41:11 2010
@@ -18,10 +18,16 @@
*/
package org.apache.cxf.jaxrs.model.wadl;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.StringReader;
import java.io.StringWriter;
import java.lang.annotation.Annotation;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -45,8 +51,10 @@
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -68,6 +76,8 @@
import org.apache.cxf.jaxrs.JAXRSServiceImpl;
import org.apache.cxf.jaxrs.ext.Description;
import org.apache.cxf.jaxrs.ext.RequestHandler;
+import org.apache.cxf.jaxrs.ext.xml.XMLName;
+import org.apache.cxf.jaxrs.ext.xml.XMLSource;
import org.apache.cxf.jaxrs.impl.HttpHeadersImpl;
import org.apache.cxf.jaxrs.impl.UriInfoImpl;
import org.apache.cxf.jaxrs.model.ClassResourceInfo;
@@ -75,12 +85,14 @@
import org.apache.cxf.jaxrs.model.Parameter;
import org.apache.cxf.jaxrs.model.ParameterType;
import org.apache.cxf.jaxrs.model.URITemplate;
+import org.apache.cxf.jaxrs.utils.AnnotationUtils;
import org.apache.cxf.jaxrs.utils.InjectionUtils;
import org.apache.cxf.jaxrs.utils.JAXRSUtils;
import org.apache.cxf.jaxrs.utils.ResourceUtils;
import org.apache.cxf.jaxrs.utils.schemas.SchemaHandler;
import org.apache.cxf.message.Message;
import org.apache.cxf.service.Service;
+import org.apache.cxf.staxutils.DelegatingXMLStreamWriter;
import org.apache.cxf.staxutils.StaxUtils;
import org.apache.ws.commons.schema.XmlSchema;
@@ -98,7 +110,14 @@
private String wadlNamespace;
private boolean ignoreMessageWriters = true;
private boolean singleResourceMultipleMethods = true;
- private boolean useSingleSlashResource = true;
+ private boolean useSingleSlashResource;
+
+ private boolean useJaxbContextForQnames = true;
+
+ private List<String> externalSchemasCache;
+ private List<URI> externalSchemaLinks;
+ private Map<String, List<String>> externalQnamesMap;
+ private ElementQNameResolver resolver;
public Response handleRequest(Message m, ClassResourceInfo resource) {
@@ -122,25 +141,26 @@
List<ClassResourceInfo> cris = getResourcesList(m, resource);
- Set<Class<?>> jaxbTypes = ResourceUtils.getAllRequestResponseTypes(cris, true).keySet();
- JAXBContext context = createJaxbContext(jaxbTypes);
- SchemaCollection coll = getSchemaCollection(context);
- JAXBContextProxy proxy = null;
- if (coll != null) {
- proxy = ReflectionInvokationHandler.createProxyWrapper(context, JAXBContextProxy.class);
- }
+ Set<Class<?>> allTypes =
+ ResourceUtils.getAllRequestResponseTypes(cris, useJaxbContextForQnames).keySet();
+
+ JAXBContext context = createJaxbContext(allTypes);
+ SchemaWriter schemaWriter = createSchemaWriter(context, ui);
+ ElementQNameResolver qnameResolver =
+ schemaWriter == null ? null : createElementQNameResolver(context);
+
Map<Class<?>, QName> clsMap = new IdentityHashMap<Class<?>, QName>();
Set<ClassResourceInfo> visitedResources = new HashSet<ClassResourceInfo>();
for (ClassResourceInfo cri : cris) {
String path = cri.getURITemplate().getValue();
sbResources.append("<resource path=\"").append(path).append("\">");
handleDocs(cri.getServiceClass().getAnnotations(), sbResources);
- handleResource(sbResources, jaxbTypes, proxy, clsMap, cri, visitedResources);
+ handleResource(sbResources, allTypes, qnameResolver, clsMap, cri, visitedResources);
sbResources.append("</resource>");
}
sbResources.append("</resources>");
- handleGrammars(sbMain, sbGrammars, coll, clsMap);
+ handleGrammars(sbMain, sbGrammars, schemaWriter, clsMap);
sbGrammars.append("</grammars>");
sbMain.append(">");
@@ -157,7 +177,11 @@
}
private void handleGrammars(StringBuilder sbApp, StringBuilder sbGrammars,
- SchemaCollection coll, Map<Class<?>, QName> clsMap) {
+ SchemaWriter writer, Map<Class<?>, QName> clsMap) {
+ if (writer == null) {
+ return;
+ }
+
Map<String, String> map = new HashMap<String, String>();
for (QName qname : clsMap.values()) {
map.put(qname.getPrefix(), qname.getNamespaceURI());
@@ -167,25 +191,12 @@
.append(entry.getValue()).append("\"");
}
-
- writeSchemas(sbGrammars, coll);
+ writer.write(sbGrammars);
}
- private void writeSchemas(StringBuilder sb, SchemaCollection coll) {
- if (coll == null) {
- return;
- }
- for (XmlSchema xs : coll.getXmlSchemas()) {
- if (xs.getItems().getCount() == 0) {
- continue;
- }
- StringWriter writer = new StringWriter();
- xs.write(writer);
- sb.append(writer.toString());
- }
- }
- private void handleResource(StringBuilder sb, Set<Class<?>> jaxbTypes, JAXBContextProxy jaxbProxy,
+ private void handleResource(StringBuilder sb, Set<Class<?>> jaxbTypes,
+ ElementQNameResolver qnameResolver,
Map<Class<?>, QName> clsMap, ClassResourceInfo cri,
Set<ClassResourceInfo> visitedResources) {
visitedResources.add(cri);
@@ -204,23 +215,23 @@
sb.append("<resource path=\"").append(path).append("\">");
handleDocs(subcri.getServiceClass().getAnnotations(), sb);
handlePathAndMatrixParams(sb, ori);
- handleResource(sb, jaxbTypes, jaxbProxy, clsMap, subcri,
+ handleResource(sb, jaxbTypes, qnameResolver, clsMap, subcri,
visitedResources);
sb.append("</resource>");
} else {
- handleDynamicSubresource(sb, jaxbTypes, jaxbProxy, clsMap, ori, subcri);
+ handleDynamicSubresource(sb, jaxbTypes, qnameResolver, clsMap, ori, subcri);
}
continue;
}
OperationResourceInfo nextOp = i + 1 < sortedOps.size() ? sortedOps.get(i + 1) : null;
- resourceTagOpened = handleOperation(sb, jaxbTypes, jaxbProxy, clsMap, ori, nextOp,
+ resourceTagOpened = handleOperation(sb, jaxbTypes, qnameResolver, clsMap, ori, nextOp,
resourceTagOpened, i);
}
}
//CHECKSTYLE:OFF
private boolean handleOperation(StringBuilder sb, Set<Class<?>> jaxbTypes,
- JAXBContextProxy jaxbProxy,
+ ElementQNameResolver qnameResolver,
Map<Class<?>, QName> clsMap,
OperationResourceInfo ori,
OperationResourceInfo nextOp,
@@ -250,10 +261,10 @@
if (ori.getMethodToInvoke().getParameterTypes().length != 0) {
sb.append("<request>");
if (isFormRequest(ori)) {
- handleRepresentation(sb, jaxbTypes, jaxbProxy, clsMap, ori, null, false);
+ handleRepresentation(sb, jaxbTypes, qnameResolver, clsMap, ori, null, false);
} else {
for (Parameter p : ori.getParameters()) {
- handleParameter(sb, jaxbTypes, jaxbProxy, clsMap, ori, p);
+ handleParameter(sb, jaxbTypes, qnameResolver, clsMap, ori, p);
}
}
sb.append("</request>");
@@ -265,7 +276,7 @@
}
sb.append(">");
if (void.class != ori.getMethodToInvoke().getReturnType()) {
- handleRepresentation(sb, jaxbTypes, jaxbProxy, clsMap, ori,
+ handleRepresentation(sb, jaxbTypes, qnameResolver, clsMap, ori,
ori.getMethodToInvoke().getReturnType(), false);
}
sb.append("</response>");
@@ -315,7 +326,7 @@
}
protected void handleDynamicSubresource(StringBuilder sb, Set<Class<?>> jaxbTypes,
- JAXBContextProxy jaxbProxy, Map<Class<?>, QName> clsMap, OperationResourceInfo ori,
+ ElementQNameResolver qnameResolver, Map<Class<?>, QName> clsMap, OperationResourceInfo ori,
ClassResourceInfo subcri) {
if (subcri != null) {
@@ -334,11 +345,12 @@
}
- private void handleParameter(StringBuilder sb, Set<Class<?>> jaxbTypes, JAXBContextProxy jaxbProxy,
+ private void handleParameter(StringBuilder sb, Set<Class<?>> jaxbTypes,
+ ElementQNameResolver qnameResolver,
Map<Class<?>, QName> clsMap, OperationResourceInfo ori, Parameter pm) {
Class<?> cls = ori.getMethodToInvoke().getParameterTypes()[pm.getIndex()];
if (pm.getType() == ParameterType.REQUEST_BODY) {
- handleRepresentation(sb, jaxbTypes, jaxbProxy, clsMap, ori, cls, true);
+ handleRepresentation(sb, jaxbTypes, qnameResolver, clsMap, ori, cls, true);
return;
}
if (pm.getType() == ParameterType.PATH || pm.getType() == ParameterType.MATRIX) {
@@ -358,6 +370,19 @@
}
}
+ private Annotation[] getBodyAnnotations(OperationResourceInfo ori, boolean inbound) {
+ if (inbound) {
+ for (Parameter pm : ori.getParameters()) {
+ if (pm.getType() == ParameterType.REQUEST_BODY) {
+ return ori.getAnnotatedMethod().getParameterAnnotations()[pm.getIndex()];
+ }
+ }
+ return new Annotation[]{};
+ } else {
+ return ori.getAnnotatedMethod().getDeclaredAnnotations();
+ }
+ }
+
private void writeParam(StringBuilder sb, Parameter pm, OperationResourceInfo ori) {
Class<?> type = ori.getMethodToInvoke().getParameterTypes()[pm.getIndex()];
if (!"".equals(pm.getName())) {
@@ -383,7 +408,9 @@
}
protected void doWriteParam(StringBuilder sb, Parameter pm, Class<?> type, String paramName) {
-
+ if (ParameterType.REQUEST_BODY == pm.getType()) {
+ return;
+ }
sb.append("<param name=\"").append(paramName).append("\" ");
String style = ParameterType.PATH == pm.getType() ? "template"
: ParameterType.FORM == pm.getType() ? "query"
@@ -399,7 +426,8 @@
sb.append("/>");
}
- private void handleRepresentation(StringBuilder sb, Set<Class<?>> jaxbTypes, JAXBContextProxy jaxbProxy,
+ private void handleRepresentation(StringBuilder sb, Set<Class<?>> jaxbTypes,
+ ElementQNameResolver qnameResolver,
Map<Class<?>, QName> clsMap, OperationResourceInfo ori,
Class<?> type, boolean inbound) {
List<MediaType> types = inbound ? ori.getConsumeTypes() : ori.getProduceTypes();
@@ -416,8 +444,9 @@
}
sb.append("<representation");
sb.append(" mediaType=\"").append(mt.toString()).append("\"");
- if (jaxbProxy != null && mt.getSubtype().contains("xml") && jaxbTypes.contains(type)) {
- generateQName(sb, jaxbProxy, clsMap, type);
+ if (qnameResolver != null && mt.getSubtype().contains("xml") && jaxbTypes.contains(type)) {
+ generateQName(sb, qnameResolver, clsMap, type,
+ getBodyAnnotations(ori, inbound));
}
sb.append("/>");
}
@@ -463,9 +492,10 @@
private void generateQName(StringBuilder sb,
- JAXBContextProxy jaxbProxy,
+ ElementQNameResolver qnameResolver,
Map<Class<?>, QName> clsMap,
- Class<?> type) {
+ Class<?> type,
+ Annotation[] annotations) {
QName typeQName = clsMap.get(type);
if (typeQName != null) {
@@ -473,7 +503,8 @@
return;
}
- QName qname = getQName(jaxbProxy, type, clsMap);
+ QName qname = qnameResolver.resolve(type, annotations,
+ Collections.unmodifiableMap(clsMap));
if (qname != null) {
writeQName(sb, qname);
@@ -513,7 +544,7 @@
return xmlSchemaCollection;
}
- private QName getQName(JAXBContextProxy jaxbProxy, Class<?> type, Map<Class<?>, QName> clsMap) {
+ private QName getJaxbQName(JAXBContextProxy jaxbProxy, Class<?> type, Map<Class<?>, QName> clsMap) {
XmlRootElement root = type.getAnnotation(XmlRootElement.class);
if (root != null) {
@@ -530,7 +561,7 @@
}
try {
- JAXBBeanInfo jaxbInfo = JAXBUtils.getBeanInfo(jaxbProxy, type);
+ JAXBBeanInfo jaxbInfo = jaxbProxy == null ? null : JAXBUtils.getBeanInfo(jaxbProxy, type);
if (jaxbInfo == null) {
return null;
}
@@ -560,7 +591,7 @@
}
private JAXBContext createJaxbContext(Set<Class<?>> classes) {
- if (classes.isEmpty()) {
+ if (!useJaxbContextForQnames || classes.isEmpty()) {
return null;
}
Set<Class<?>> classesToBeBound = new HashSet<Class<?>>(classes);
@@ -734,4 +765,309 @@
this.useSingleSlashResource = useSingleSlashResource;
}
+ public void setSchemaLocations(List<String> locations) {
+
+ externalQnamesMap = new HashMap<String, List<String>>();
+ externalSchemasCache = new ArrayList<String>(locations.size());
+ for (int i = 0; i < locations.size(); i++) {
+ String loc = locations.get(i);
+ try {
+ InputStream is = ResourceUtils.getResourceStream(loc, BusFactory.getDefaultBus());
+ if (is == null) {
+ return;
+ }
+ ByteArrayInputStream bis = IOUtils.loadIntoBAIS(is);
+ XMLSource source = new XMLSource(bis);
+ source.setBuffering(true);
+ String targetNs = source.getValue("/*/@targetNamespace");
+
+ Map<String, String> nsMap =
+ Collections.singletonMap("xs", XmlSchemaConstants.XSD_NAMESPACE_URI);
+ String[] elementNames = source.getValues("/*/xs:element/@name", nsMap);
+ externalQnamesMap.put(targetNs, Arrays.asList(elementNames));
+ String schemaValue = source.getNode("/xs:schema", nsMap, String.class);
+ externalSchemasCache.add(schemaValue);
+ } catch (Exception ex) {
+ LOG.warning("No schema resource " + loc + " can be loaded : " + ex.getMessage());
+ externalSchemasCache = null;
+ externalQnamesMap = null;
+ return;
+ }
+ }
+
+ }
+
+ public void setUseJaxbContextForQnames(boolean checkJaxbOnly) {
+ this.useJaxbContextForQnames = checkJaxbOnly;
+ }
+
+ protected ElementQNameResolver createElementQNameResolver(JAXBContext context) {
+ if (resolver != null) {
+ return resolver;
+ }
+ if (useJaxbContextForQnames) {
+ if (context != null) {
+ JAXBContextProxy proxy =
+ ReflectionInvokationHandler.createProxyWrapper(context, JAXBContextProxy.class);
+ return new JaxbContextQNameResolver(proxy);
+ } else {
+ return null;
+ }
+ } else if (externalQnamesMap != null) {
+ return new SchemaQNameResolver(externalQnamesMap);
+ } else {
+ return new XMLNameQNameResolver();
+ }
+ }
+
+ protected SchemaWriter createSchemaWriter(JAXBContext context, UriInfo ui) {
+ // if neither externalSchemaLinks nor externalSchemasCache is set
+ // then JAXBContext will be used to generate the schema
+ if (externalSchemaLinks != null && externalSchemasCache == null) {
+ return new ExternalSchemaWriter(externalSchemaLinks, ui);
+ } else if (externalSchemasCache != null) {
+ return new StringSchemaWriter(externalSchemasCache, externalSchemaLinks, ui);
+ } else if (context != null) {
+ SchemaCollection coll = getSchemaCollection(context);
+ if (coll != null) {
+ return new SchemaCollectionWriter(coll);
+ }
+ }
+ return null;
+ }
+
+ public void setExternalLinks(List<String> externalLinks) {
+ externalSchemaLinks = new LinkedList<URI>();
+ for (String s : externalLinks) {
+ try {
+ externalSchemaLinks.add(URI.create(s));
+ } catch (Exception ex) {
+ LOG.warning("Not a valid URI : " + s);
+ externalSchemaLinks = null;
+ break;
+ }
+ }
+ }
+
+ private static interface SchemaWriter {
+ void write(StringBuilder sb);
+ }
+
+ private class StringSchemaWriter implements SchemaWriter {
+
+ private List<String> theSchemas;
+
+ public StringSchemaWriter(List<String> schemas, List<URI> links, UriInfo ui) {
+
+ this.theSchemas = new LinkedList<String>();
+ // we'll need to do the proper schema caching eventually
+ for (String s : schemas) {
+ XMLSource source = new XMLSource(new ByteArrayInputStream(s.getBytes()));
+ source.setBuffering(true);
+ Map<String, String> locs = getLocationsMap(source, "import", links, ui);
+ String actualSchema = !locs.isEmpty() ? transformSchema(s, locs) : s;
+ theSchemas.add(actualSchema);
+ }
+ }
+
+ private Map<String, String> getLocationsMap(XMLSource source, String elementName,
+ List<URI> links, UriInfo ui) {
+ Map<String, String> nsMap =
+ Collections.singletonMap("xs", XmlSchemaConstants.XSD_NAMESPACE_URI);
+ String[] locations = source.getValues("/*/xs:" + elementName + "/@schemaLocation", nsMap);
+ if (locations == null) {
+ return Collections.emptyMap();
+ }
+
+ Map<String, String> locs = new HashMap<String, String>();
+ for (String loc : locations) {
+ try {
+ URI uri = URI.create(loc);
+ if (!uri.isAbsolute()) {
+ if (links != null) {
+ for (URI overwriteURI : links) {
+ if (overwriteURI.toString().endsWith(loc)) {
+ if (overwriteURI.isAbsolute()) {
+ locs.put(loc, overwriteURI.toString());
+ } else {
+ locs.put(loc, ui.getBaseUriBuilder().path(
+ overwriteURI.toString()).build().toString());
+ }
+ break;
+ }
+ }
+ }
+ if (!locs.containsKey(loc)) {
+ locs.put(loc, ui.getBaseUriBuilder().path(
+ loc.toString()).build().toString());
+ }
+ }
+ } catch (Exception ex) {
+ // continue
+ }
+ }
+ return locs;
+ }
+
+ private String transformSchema(String schema, Map<String, String> locs) {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ SchemaConverter sc = new SchemaConverter(StaxUtils.createXMLStreamWriter(bos), locs);
+ try {
+ StaxUtils.copy(new StreamSource(new StringReader(schema)), sc);
+ sc.flush();
+ sc.close();
+ return bos.toString();
+ } catch (Exception ex) {
+ return schema;
+ }
+
+ }
+
+ public void write(StringBuilder sb) {
+ for (String s : theSchemas) {
+ sb.append(s);
+ }
+ }
+ }
+
+ private class SchemaCollectionWriter implements SchemaWriter {
+
+ private SchemaCollection coll;
+
+ public SchemaCollectionWriter(SchemaCollection coll) {
+ this.coll = coll;
+ }
+
+ public void write(StringBuilder sb) {
+ for (XmlSchema xs : coll.getXmlSchemas()) {
+ if (xs.getItems().getCount() == 0) {
+ continue;
+ }
+ StringWriter writer = new StringWriter();
+ xs.write(writer);
+ sb.append(writer.toString());
+ }
+ }
+ }
+
+ private class ExternalSchemaWriter implements SchemaWriter {
+
+ private List<URI> links;
+ private UriInfo uriInfo;
+
+ public ExternalSchemaWriter(List<URI> links, UriInfo ui) {
+ this.links = links;
+ this.uriInfo = ui;
+ }
+
+ public void write(StringBuilder sb) {
+ for (URI link : links) {
+ try {
+ URI value = link.isAbsolute() ? link
+ : uriInfo.getBaseUriBuilder().path(link.toString()).build();
+ sb.append("<include href=\"").append(value.toString()).append("\"/>");
+ } catch (Exception ex) {
+ LOG.warning("WADL grammar section will be incomplete, this link is not a valid URI : "
+ + link.toString());
+ }
+ }
+ }
+ }
+
+ private class JaxbContextQNameResolver implements ElementQNameResolver {
+
+ private JAXBContextProxy proxy;
+
+ public JaxbContextQNameResolver(JAXBContextProxy proxy) {
+ this.proxy = proxy;
+ }
+
+ public QName resolve(Class<?> type, Annotation[] annotations, Map<Class<?>, QName> clsMap) {
+ return getJaxbQName(proxy, type, clsMap);
+ }
+
+ }
+
+ private class XMLNameQNameResolver implements ElementQNameResolver {
+
+ public QName resolve(Class<?> type, Annotation[] annotations, Map<Class<?>, QName> clsMap) {
+ XMLName name = AnnotationUtils.getAnnotation(annotations, XMLName.class);
+ if (name == null) {
+ name = type.getAnnotation(XMLName.class);
+ }
+ if (name != null) {
+ QName qname = convertStringToQName(name.value(), name.prefix());
+ if (qname.getPrefix().length() > 0) {
+ return qname;
+ } else {
+ return getQNameFromParts(qname.getLocalPart(),
+ qname.getNamespaceURI(), clsMap);
+ }
+ }
+ return null;
+ }
+
+ }
+
+ private class SchemaQNameResolver implements ElementQNameResolver {
+
+ private Map<String, List<String>> map;
+
+ public SchemaQNameResolver(Map<String, List<String>> map) {
+ this.map = map;
+ }
+
+ public QName resolve(Class<?> type, Annotation[] annotations, Map<Class<?>, QName> clsMap) {
+ String name = type.getSimpleName();
+ for (Map.Entry<String, List<String>> entry : map.entrySet()) {
+ String elementName = null;
+ if (entry.getValue().contains(name)) {
+ elementName = name;
+ } else if (entry.getValue().contains(name.toLowerCase())) {
+ elementName = name.toLowerCase();
+ }
+ if (elementName != null) {
+ return getQNameFromParts(elementName, entry.getKey(), clsMap);
+ }
+ }
+ return null;
+ }
+
+ }
+
+ private QName convertStringToQName(String name, String prefix) {
+ int ind1 = name.indexOf('{');
+ if (ind1 != 0) {
+ return null;
+ }
+
+ 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, prefix);
+ }
+
+ public void setResolver(ElementQNameResolver resolver) {
+ this.resolver = resolver;
+ }
+
+ private static class SchemaConverter extends DelegatingXMLStreamWriter {
+ private static final String SCHEMA_LOCATION = "schemaLocation";
+ private Map<String, String> locsMap;
+ public SchemaConverter(XMLStreamWriter writer, Map<String, String> locsMap) {
+ super(writer);
+ this.locsMap = locsMap;
+ }
+
+ public void writeAttribute(String local, String value) throws XMLStreamException {
+ if (SCHEMA_LOCATION.equals(local) && locsMap.containsKey(value)) {
+ value = locsMap.get(value);
+ }
+ super.writeAttribute(local, value);
+ }
+ }
+
}
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=907718&r1=907717&r2=907718&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 Mon Feb 8 16:41:11 2010
@@ -629,9 +629,9 @@
return writer == null ? StaxUtils.createXMLStreamWriter(os) : writer;
}
- protected static void convertToMapOfQNames(Map<String, String> map,
- Map<QName, QName> elementsMap,
- Map<String, String> nsMap) {
+ protected static void convertToQNamesMap(Map<String, String> map,
+ QNamesMap elementsMap,
+ Map<String, String> nsMap) {
if (map != null) {
for (Map.Entry<String, String> entry : map.entrySet()) {
QName lname = convertStringToQName(entry.getKey());
@@ -644,6 +644,17 @@
}
}
+ protected static void convertToMapOfQNames(Map<String, String> map,
+ Map<QName, QName> elementsMap) {
+ if (map != null) {
+ for (Map.Entry<String, String> entry : map.entrySet()) {
+ QName lname = convertStringToQName(entry.getKey());
+ QName rname = convertStringToQName(entry.getValue());
+ elementsMap.put(lname, rname);
+ }
+ }
+ }
+
public void setAttributesToElements(boolean value) {
this.attributesToElements = value;
@@ -703,7 +714,7 @@
}
protected static class OutTransformWriter extends DelegatingXMLStreamWriter {
- private Map<QName, QName> elementsMap = new HashMap<QName, QName>(5);
+ private QNamesMap elementsMap;
private Map<QName, QName> appendMap = new HashMap<QName, QName>(5);
private Map<String, String> nsMap = new HashMap<String, String>(5);
private Set<String> prefixes = new HashSet<String>(2);
@@ -722,8 +733,9 @@
List<String> dropEls,
boolean attributesToElements) {
super(writer);
- convertToMapOfQNames(outMap, elementsMap, nsMap);
- convertToMapOfQNames(append, appendMap, null);
+ elementsMap = new QNamesMap(outMap == null ? 0 : outMap.size());
+ convertToQNamesMap(outMap, elementsMap, nsMap);
+ convertToMapOfQNames(append, appendMap);
dropElements = convertToSetOfQNames(dropEls);
this.attributesToElements = attributesToElements;
}
@@ -869,12 +881,44 @@
}
}
+ private static class QNamesMap {
+ private QName[] keys;
+ private QName[] values;
+ private int index;
+
+ public QNamesMap(int size) {
+ keys = new QName[size];
+ values = new QName[size];
+ }
+
+ public void put(QName key, QName value) {
+ keys[index] = key;
+ values[index] = value;
+ index++;
+ }
+
+ public QName get(QName key) {
+ for (int i = 0; i < keys.length; i++) {
+ if (keys[i].getNamespaceURI().equals(key.getNamespaceURI())) {
+ if (keys[i].getLocalPart().equals(key.getLocalPart())) {
+ return values[i];
+ } else if ("*".equals(keys[i].getLocalPart())) {
+ // assume it is something like {somens}* : *
+ return "*".equals(values[i]) ? new QName(key.getLocalPart())
+ : new QName(values[i].getNamespaceURI(), key.getLocalPart());
+ }
+ }
+ }
+ return null;
+ }
+ }
+
protected static class InTransformReader extends DepthXMLStreamReader {
private static final String INTERN_NAMES = "org.codehaus.stax2.internNames";
private static final String INTERN_NS = "org.codehaus.stax2.internNsUris";
- private Map<QName, QName> inElementsMap = new HashMap<QName, QName>(5);
+ private QNamesMap inElementsMap;
private Map<QName, QName> inAppendMap = new HashMap<QName, QName>(5);
private Map<String, String> nsMap = new HashMap<String, String>(5);
private QName currentQName;
@@ -885,8 +929,9 @@
Map<String, String> inMap,
Map<String, String> appendMap) {
super(reader);
- convertToMapOfQNames(inMap, inElementsMap, nsMap);
- convertToMapOfQNames(appendMap, inAppendMap, null);
+ inElementsMap = new QNamesMap(inMap == null ? 0 : inMap.size());
+ convertToQNamesMap(inMap, inElementsMap, nsMap);
+ convertToMapOfQNames(appendMap, inAppendMap);
}
public int next() throws XMLStreamException {
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/XSLTJaxbProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/XSLTJaxbProvider.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/XSLTJaxbProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/XSLTJaxbProvider.java Mon Feb 8 16:41:11 2010
@@ -19,8 +19,6 @@
package org.apache.cxf.jaxrs.provider;
import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
@@ -270,18 +268,8 @@
protected Templates createTemplates(String loc) {
try {
- InputStream is = null;
- if (loc.startsWith("classpath:")) {
- String path = loc.substring("classpath:".length());
- is = ResourceUtils.getClasspathResourceStream(path, this.getClass(), this.getBus());
- } else {
- File f = new File(loc);
- if (f.exists()) {
- is = new FileInputStream(f);
- }
- }
+ InputStream is = ResourceUtils.getResourceStream(loc, this.getBus());
if (is == null) {
- LOG.warning("No template is available at : " + loc);
return null;
}
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java Mon Feb 8 16:41:11 2010
@@ -872,21 +872,18 @@
Message m,
String defaultValue,
boolean decode) {
+
+ MultivaluedMap<String, String> queryMap = new UriInfoImpl(m, null).getQueryParameters(decode);
+
if ("".equals(queryName)) {
- return InjectionUtils.handleBean(paramType, new UriInfoImpl(m, null).getQueryParameters(),
- ParameterType.QUERY, m, decode);
+ return InjectionUtils.handleBean(paramType, queryMap, ParameterType.QUERY, m, false);
} else {
- List<String> results = getStructuredParams((String)m.get(Message.QUERY_STRING),
- "&",
- decode).get(queryName);
-
- return InjectionUtils.createParameterObject(results,
+ return InjectionUtils.createParameterObject(queryMap.get(queryName),
paramType,
genericType,
defaultValue,
false,
ParameterType.QUERY, m);
-
}
}
@@ -900,9 +897,18 @@
public static MultivaluedMap<String, String> getStructuredParams(String query,
String sep,
boolean decode) {
- MultivaluedMap<String, String> queries =
+ MultivaluedMap<String, String> map =
new MetadataMap<String, String>(new LinkedHashMap<String, List<String>>());
+ getStructuredParams(map, query, sep, decode);
+
+ return map;
+ }
+
+ public static void getStructuredParams(MultivaluedMap<String, String> queries,
+ String query,
+ String sep,
+ boolean decode) {
if (!StringUtils.isEmpty(query)) {
List<String> parts = Arrays.asList(query.split(sep));
for (String part : parts) {
@@ -919,7 +925,6 @@
queries.add(HttpUtils.urlDecode(values[0]), value);
}
}
- return queries;
}
@SuppressWarnings("unchecked")
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java Mon Feb 8 16:41:11 2010
@@ -78,7 +78,7 @@
private static final Logger LOG = LogUtils.getL7dLogger(ResourceUtils.class);
private static final ResourceBundle BUNDLE = BundleUtils.getBundle(ResourceUtils.class);
-
+ private static final String CLASSPATH_PREFIX = "classpath:";
private ResourceUtils() {
@@ -354,18 +354,8 @@
public static List<UserResource> getUserResources(String loc, Bus bus) {
try {
- InputStream is = null;
- if (loc.startsWith("classpath:")) {
- String path = loc.substring("classpath:".length());
- is = getClasspathResourceStream(path, ResourceUtils.class, bus);
- } else {
- File f = new File(loc);
- if (f.exists()) {
- is = new FileInputStream(f);
- }
- }
+ InputStream is = ResourceUtils.getResourceStream(loc, bus);
if (is == null) {
- LOG.warning("No user model is available at " + loc);
return null;
}
return getUserResources(is);
@@ -376,6 +366,26 @@
return null;
}
+ public static InputStream getResourceStream(String loc, Bus bus) throws Exception {
+ InputStream is = null;
+ if (loc.startsWith(CLASSPATH_PREFIX)) {
+ String path = loc.substring(CLASSPATH_PREFIX.length());
+ is = ResourceUtils.getClasspathResourceStream(path, ResourceUtils.class, bus);
+ if (is == null) {
+ LOG.warning("No classpath resource " + loc + " is available on classpath");
+ return null;
+ }
+ } else {
+ File f = new File(loc);
+ if (!f.exists()) {
+ LOG.warning("No file resource " + loc + " is available on local disk");
+ return null;
+ }
+ is = new FileInputStream(f);
+ }
+ return is;
+ }
+
public static InputStream getClasspathResourceStream(String path, Class<?> callingClass, Bus bus) {
InputStream is = ClassLoaderUtils.getResourceAsStream(path, callingClass);
if (is == null && bus != null) {
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/schemas/SchemaHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/schemas/SchemaHandler.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/schemas/SchemaHandler.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/schemas/SchemaHandler.java Mon Feb 8 16:41:11 2010
@@ -20,8 +20,6 @@
package org.apache.cxf.jaxrs.utils.schemas;
import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
@@ -43,7 +41,6 @@
public class SchemaHandler {
private static final Logger LOG = LogUtils.getL7dLogger(SchemaHandler.class);
- private static final String CLASSPATH_PREFIX = "classpath:";
private Schema schema;
private Bus bus;
@@ -71,23 +68,10 @@
try {
List<Source> sources = new ArrayList<Source>();
for (String loc : locations) {
- InputStream is = null;
- if (loc.startsWith(CLASSPATH_PREFIX)) {
- String path = loc.substring(CLASSPATH_PREFIX.length());
- is = ResourceUtils.getClasspathResourceStream(path, SchemaHandler.class, bus);
- if (is == null) {
- LOG.warning("No schema resource " + loc + " is available on classpath");
- return null;
- }
- } else {
- File f = new File(loc);
- if (!f.exists()) {
- LOG.warning("No schema resource " + loc + " is available on local disk");
- return null;
- }
- is = new FileInputStream(f);
+ InputStream is = ResourceUtils.getResourceStream(loc, bus);
+ if (is == null) {
+ return null;
}
-
Reader r = new BufferedReader(
new InputStreamReader(is, "UTF-8"));
sources.add(new StreamSource(r));
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/xml/XMLSourceTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/xml/XMLSourceTest.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/xml/XMLSourceTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/xml/XMLSourceTest.java Mon Feb 8 16:41:11 2010
@@ -21,16 +21,79 @@
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URI;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
+import org.apache.cxf.common.xmlschema.XmlSchemaConstants;
+
import org.junit.Assert;
import org.junit.Test;
public class XMLSourceTest extends Assert {
+
+ @Test
+ public void testNodeStringValue() {
+ InputStream is = getClass().getResourceAsStream("/book1.xsd");
+ XMLSource xp = new XMLSource(is);
+ Map<String, String> nsMap =
+ Collections.singletonMap("xs", XmlSchemaConstants.XSD_NAMESPACE_URI);
+ String value = xp.getNode("/xs:schema", nsMap, String.class);
+ assertFalse(value.contains("<?xml"));
+ assertTrue(value.startsWith("<xs:schema"));
+ }
+
+ @Test
+ public void testAttributeValue() {
+ InputStream is = new ByteArrayInputStream("<foo><bar attr=\"baz\">barValue</bar></foo>".getBytes());
+ XMLSource xp = new XMLSource(is);
+ assertEquals("baz", xp.getValue("/foo/bar/@attr"));
+ }
+
+ @Test
+ public void testNodeTextValue() {
+ InputStream is = new ByteArrayInputStream("<foo><bar attr=\"baz\">barValue</bar></foo>".getBytes());
+ XMLSource xp = new XMLSource(is);
+ assertEquals("barValue", xp.getValue("/foo/bar"));
+ }
+
+ @Test
+ public void testAttributeValues() {
+ InputStream is = new ByteArrayInputStream(
+ "<foo><bar attr=\"baz\">bar1</bar><bar attr=\"baz2\">bar2</bar></foo>".getBytes());
+ XMLSource xp = new XMLSource(is);
+ List<String> values = Arrays.asList(xp.getValues("/foo/bar/@attr"));
+ assertEquals(2, values.size());
+ assertTrue(values.contains("baz"));
+ assertTrue(values.contains("baz2"));
+ }
+
+ @Test
+ public void testNodeTextValues() {
+ InputStream is = new ByteArrayInputStream(
+ "<foo><bar attr=\"baz\">bar1</bar><bar attr=\"baz2\">bar2</bar></foo>".getBytes());
+ XMLSource xp = new XMLSource(is);
+ List<String> values = Arrays.asList(xp.getValues("/foo/bar/text()"));
+ assertEquals(2, values.size());
+ assertTrue(values.contains("bar1"));
+ assertTrue(values.contains("bar2"));
+ }
+
+ @Test
+ public void testIntegerValues() {
+ InputStream is = new ByteArrayInputStream(
+ "<foo><bar attr=\"1\"/><bar attr=\"2\"/></foo>".getBytes());
+ XMLSource xp = new XMLSource(is);
+ Integer[] values = xp.getNodes("/foo/bar/@attr", Integer.class);
+ assertEquals(2, values.length);
+ assertTrue(values[0] == 1 && values[1] == 2 || values[0] == 2 && values[1] == 1);
+ }
+
@Test
public void testGetNodeNoNamespace() {
InputStream is = new ByteArrayInputStream("<foo><bar/></foo>".getBytes());
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java Mon Feb 8 16:41:11 2010
@@ -113,6 +113,7 @@
String method,
String methodHeader) {
Message m = new MessageImpl();
+ m.put("org.apache.cxf.http.case_insensitive_queries", false);
Exchange e = new ExchangeImpl();
m.setExchange(e);
control.reset();
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java Mon Feb 8 16:41:11 2010
@@ -24,6 +24,7 @@
import org.apache.cxf.jaxrs.model.URITemplate;
import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.ExchangeImpl;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.service.model.EndpointInfo;
@@ -87,10 +88,31 @@
assertEquals("Wrong query value", qps.getFirst("n"), "1%202");
u = new UriInfoImpl(mockMessage("http://localhost:8080/baz", "/bar",
- "n=1%202&n=3&b=2&a%2Eb=ab"),
+ "N=0&n=1%202&n=3&b=2&a%2Eb=ab"),
null);
qps = u.getQueryParameters();
+ assertEquals("Number of queiries is wrong", 4, qps.size());
+ assertEquals("Wrong query value", qps.get("N").get(0), "0");
+ assertEquals("Wrong query value", qps.get("n").get(0), "1 2");
+ assertEquals("Wrong query value", qps.get("n").get(1), "3");
+ assertEquals("Wrong query value", qps.get("b").get(0), "2");
+ assertEquals("Wrong query value", qps.get("a.b").get(0), "ab");
+ }
+
+ @Test
+ public void testGetCaseinsensitiveQueryParameters() {
+ UriInfoImpl u = new UriInfoImpl(mockMessage("http://localhost:8080/baz", "/bar"),
+ null);
+ assertEquals("unexpected queries", 0, u.getQueryParameters().size());
+
+ Message m = mockMessage("http://localhost:8080/baz", "/bar",
+ "N=1%202&n=3&b=2&a%2Eb=ab");
+ m.put("org.apache.cxf.http.case_insensitive_queries", "true");
+
+ u = new UriInfoImpl(m, null);
+
+ MultivaluedMap<String, String> qps = u.getQueryParameters();
assertEquals("Number of queiries is wrong", 3, qps.size());
assertEquals("Wrong query value", qps.get("n").get(0), "1 2");
assertEquals("Wrong query value", qps.get("n").get(1), "3");
@@ -207,11 +229,10 @@
String query, String fragment) {
Message m = new MessageImpl();
control.reset();
- Exchange e = control.createMock(Exchange.class);
+ Exchange e = new ExchangeImpl();
m.setExchange(e);
ServletDestination d = control.createMock(ServletDestination.class);
- e.getDestination();
- EasyMock.expectLastCall().andReturn(d).anyTimes();
+ e.setDestination(d);
EndpointInfo epr = new EndpointInfo();
epr.setAddress(baseAddress);
d.getEndpointInfo();
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookStore.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookStore.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookStore.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookStore.java Mon Feb 8 16:41:11 2010
@@ -33,6 +33,7 @@
import javax.ws.rs.core.HttpHeaders;
import org.apache.cxf.jaxrs.ext.Description;
+import org.apache.cxf.jaxrs.ext.xml.XMLName;
import org.apache.cxf.jaxrs.fortest.jaxb.packageinfo.Book2;
import org.apache.cxf.jaxrs.model.wadl.jaxb.Book;
import org.apache.cxf.jaxrs.model.wadl.jaxb.Chapter;
@@ -72,7 +73,8 @@
@CookieParam("cid") int cookieId,
@QueryParam("provider.bar") int queryParam,
@Context HttpHeaders headers,
- Book b) {
+ @XMLName(value = "{http://books}thesuperbook2", prefix = "p1")
+ Book2 b) {
return new Book(1);
}
@@ -105,6 +107,7 @@
@Path("book2")
@GET
+ @XMLName(value = "{http://books}thesuperbook2", prefix = "p1")
public Book2 getBook2() {
return new Book2();
}
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java?rev=907718&r1=907717&r2=907718&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java Mon Feb 8 16:41:11 2010
@@ -20,6 +20,7 @@
import java.io.StringReader;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import javax.ws.rs.core.HttpHeaders;
@@ -64,8 +65,134 @@
}
@Test
+ public void testCustomSchemaJaxbContextPrefixes() throws Exception {
+ WadlGenerator wg = new WadlGenerator();
+ wg.setSchemaLocations(Collections.singletonList("classpath:/book1.xsd"));
+
+ ClassResourceInfo cri =
+ ResourceUtils.createClassResourceInfo(BookStore.class, BookStore.class, true, true);
+ Message m = mockMessage("http://localhost:8080/baz", "/bar", WadlGenerator.WADL_QUERY, null);
+
+ Response r = wg.handleRequest(m, cri);
+ checkResponse(r);
+ Document doc = DOMUtils.readXml(new StringReader(r.getEntity().toString()));
+ checkGrammars(doc.getDocumentElement(), "thebook", "thebook2", "thechapter");
+ List<Element> els = getWadlResourcesInfo(doc, "http://localhost:8080/baz", 1);
+ checkBookStoreInfo(els.get(0), "prefix1:thebook", "prefix1:thebook2", "prefix1:thechapter");
+ }
+
+ @Test
+ public void testCustomSchemaWithImportJaxbContextPrefixes() throws Exception {
+ WadlGenerator wg = new WadlGenerator();
+ wg.setSchemaLocations(Collections.singletonList("classpath:/books.xsd"));
+
+ ClassResourceInfo cri =
+ ResourceUtils.createClassResourceInfo(BookStore.class, BookStore.class, true, true);
+ Message m = mockMessage("http://localhost:8080/baz", "/bar", WadlGenerator.WADL_QUERY, null);
+
+ Response r = wg.handleRequest(m, cri);
+ checkResponse(r);
+ Document doc = DOMUtils.readXml(new StringReader(r.getEntity().toString()));
+ List<Element> grammarEls = DOMUtils.getChildrenWithName(doc.getDocumentElement(),
+ WadlGenerator.WADL_NS, "grammars");
+ assertEquals(1, grammarEls.size());
+ List<Element> schemasEls = DOMUtils.getChildrenWithName(grammarEls.get(0),
+ XmlSchemaConstants.XSD_NAMESPACE_URI, "schema");
+ assertEquals(1, schemasEls.size());
+ assertEquals("http://books", schemasEls.get(0).getAttribute("targetNamespace"));
+ List<Element> elementEls = DOMUtils.getChildrenWithName(schemasEls.get(0),
+ XmlSchemaConstants.XSD_NAMESPACE_URI, "element");
+ assertEquals(1, elementEls.size());
+ assertTrue(checkElement(elementEls, "books", "tns:books"));
+
+ List<Element> complexTypesEls = DOMUtils.getChildrenWithName(schemasEls.get(0),
+ XmlSchemaConstants.XSD_NAMESPACE_URI, "complexType");
+ assertEquals(1, complexTypesEls.size());
+ assertTrue(checkComplexType(complexTypesEls, "books"));
+
+ List<Element> importEls = DOMUtils.getChildrenWithName(schemasEls.get(0),
+ XmlSchemaConstants.XSD_NAMESPACE_URI, "import");
+ assertEquals(1, importEls.size());
+ assertEquals("http://localhost:8080/baz/book1.xsd",
+ importEls.get(0).getAttribute("schemaLocation"));
+ }
+
+ @Test
+ public void testExternalSchemaJaxbContextPrefixes() throws Exception {
+ WadlGenerator wg = new WadlGenerator();
+ wg.setExternalLinks(Collections.singletonList("http://books.xsd"));
+
+ ClassResourceInfo cri =
+ ResourceUtils.createClassResourceInfo(BookStore.class, BookStore.class, true, true);
+ Message m = mockMessage("http://localhost:8080/baz", "/bar", WadlGenerator.WADL_QUERY, null);
+
+ Response r = wg.handleRequest(m, cri);
+ checkResponse(r);
+ Document doc = DOMUtils.readXml(new StringReader(r.getEntity().toString()));
+ checkGrammarsWithLinks(doc.getDocumentElement(), Collections.singletonList("http://books.xsd"));
+ List<Element> els = getWadlResourcesInfo(doc, "http://localhost:8080/baz", 1);
+ checkBookStoreInfo(els.get(0), "prefix1:thebook", "prefix1:thebook2", "prefix1:thechapter");
+ }
+
+ @Test
+ public void testExternalRelativeSchemaJaxbContextPrefixes() throws Exception {
+ WadlGenerator wg = new WadlGenerator();
+ wg.setExternalLinks(Collections.singletonList("books.xsd"));
+
+ ClassResourceInfo cri =
+ ResourceUtils.createClassResourceInfo(BookStore.class, BookStore.class, true, true);
+ Message m = mockMessage("http://localhost:8080/baz", "/bar", WadlGenerator.WADL_QUERY, null);
+
+ Response r = wg.handleRequest(m, cri);
+ checkResponse(r);
+ Document doc = DOMUtils.readXml(new StringReader(r.getEntity().toString()));
+ checkGrammarsWithLinks(doc.getDocumentElement(),
+ Collections.singletonList("http://localhost:8080/baz/books.xsd"));
+ List<Element> els = getWadlResourcesInfo(doc, "http://localhost:8080/baz", 1);
+ checkBookStoreInfo(els.get(0), "prefix1:thebook", "prefix1:thebook2", "prefix1:thechapter");
+ }
+
+ @Test
+ public void testExternalSchemaCustomPrefix() throws Exception {
+ WadlGenerator wg = new WadlGenerator();
+ wg.setExternalLinks(Collections.singletonList("http://books"));
+ wg.setUseJaxbContextForQnames(false);
+
+ ClassResourceInfo cri =
+ ResourceUtils.createClassResourceInfo(BookStore.class, BookStore.class, true, true);
+ Message m = mockMessage("http://localhost:8080/baz", "/bar", WadlGenerator.WADL_QUERY, null);
+
+ Response r = wg.handleRequest(m, cri);
+ checkResponse(r);
+ Document doc = DOMUtils.readXml(new StringReader(r.getEntity().toString()));
+ checkGrammarsWithLinks(doc.getDocumentElement(),
+ Collections.singletonList("http://books"));
+ List<Element> els = getWadlResourcesInfo(doc, "http://localhost:8080/baz", 1);
+ checkBookStoreInfo(els.get(0), "p1:thesuperbook", "p1:thesuperbook2", "p1:thesuperchapter");
+ }
+
+ @Test
+ public void testCustomSchemaAndSchemaPrefixes() throws Exception {
+ WadlGenerator wg = new WadlGenerator();
+ wg.setSchemaLocations(Collections.singletonList("classpath:/book2.xsd"));
+ wg.setUseJaxbContextForQnames(false);
+
+ ClassResourceInfo cri =
+ ResourceUtils.createClassResourceInfo(BookStore.class, BookStore.class, true, true);
+ Message m = mockMessage("http://localhost:8080/baz", "/bar", WadlGenerator.WADL_QUERY, null);
+
+ Response r = wg.handleRequest(m, cri);
+ checkResponse(r);
+ Document doc = DOMUtils.readXml(new StringReader(r.getEntity().toString()));
+ checkGrammars(doc.getDocumentElement(), "book", "book2", "chapter");
+ List<Element> els = getWadlResourcesInfo(doc, "http://localhost:8080/baz", 1);
+ checkBookStoreInfo(els.get(0), "prefix1:book", "prefix1:book2", "prefix1:chapter");
+ }
+
+ @Test
public void testSingleRootResource() throws Exception {
WadlGenerator wg = new WadlGenerator();
+
ClassResourceInfo cri =
ResourceUtils.createClassResourceInfo(BookStore.class, BookStore.class, true, true);
Message m = mockMessage("http://localhost:8080/baz", "/bar", WadlGenerator.WADL_QUERY, null);
@@ -73,8 +200,9 @@
Response r = wg.handleRequest(m, cri);
checkResponse(r);
Document doc = DOMUtils.readXml(new StringReader(r.getEntity().toString()));
+ checkGrammars(doc.getDocumentElement(), "thebook", "thebook2", "thechapter");
List<Element> els = getWadlResourcesInfo(doc, "http://localhost:8080/baz", 1);
- checkBookStoreInfo(els.get(0));
+ checkBookStoreInfo(els.get(0), "prefix1:thebook", "prefix1:thebook2", "prefix1:thechapter");
}
@@ -127,14 +255,14 @@
Response r = wg.handleRequest(m, null);
checkResponse(r);
Document doc = DOMUtils.readXml(new StringReader(r.getEntity().toString()));
- checkGrammars(doc.getDocumentElement());
+ checkGrammars(doc.getDocumentElement(), "thebook", "thebook2", "thechapter");
List<Element> els = getWadlResourcesInfo(doc, "http://localhost:8080/baz", 2);
- checkBookStoreInfo(els.get(0));
+ checkBookStoreInfo(els.get(0), "prefix1:thebook", "prefix1:thebook2", "prefix1:thechapter");
Element orderResource = els.get(1);
assertEquals("/orders", orderResource.getAttribute("path"));
}
- private void checkGrammars(Element appElement) {
+ private void checkGrammars(Element appElement, String bookEl, String book2El, String chapterEl) {
List<Element> grammarEls = DOMUtils.getChildrenWithName(appElement, WadlGenerator.WADL_NS,
"grammars");
assertEquals(1, grammarEls.size());
@@ -145,9 +273,9 @@
List<Element> elementEls = DOMUtils.getChildrenWithName(schemasEls.get(0),
XmlSchemaConstants.XSD_NAMESPACE_URI, "element");
assertEquals(3, elementEls.size());
- assertTrue(checkElement(elementEls, "thebook", "tns:book"));
- assertTrue(checkElement(elementEls, "thebook2", "tns:book2"));
- assertTrue(checkElement(elementEls, "thechapter", "tns:chapter"));
+ assertTrue(checkElement(elementEls, bookEl, "tns:book"));
+ assertTrue(checkElement(elementEls, book2El, "tns:book2"));
+ assertTrue(checkElement(elementEls, chapterEl, "tns:chapter"));
List<Element> complexTypesEls = DOMUtils.getChildrenWithName(schemasEls.get(0),
XmlSchemaConstants.XSD_NAMESPACE_URI, "complexType");
@@ -158,6 +286,23 @@
assertTrue(checkComplexType(complexTypesEls, "chapter"));
}
+ private void checkGrammarsWithLinks(Element appElement, List<String> links) {
+ assertTrue(links.size() > 0);
+ List<Element> grammarEls = DOMUtils.getChildrenWithName(appElement, WadlGenerator.WADL_NS,
+ "grammars");
+ assertEquals(1, grammarEls.size());
+ List<Element> schemasEls = DOMUtils.getChildrenWithName(grammarEls.get(0),
+ XmlSchemaConstants.XSD_NAMESPACE_URI, "schema");
+ assertEquals(0, schemasEls.size());
+
+ List<Element> includeEls = DOMUtils.getChildrenWithName(grammarEls.get(0), WadlGenerator.WADL_NS,
+ "include");
+ assertEquals(links.size(), includeEls.size());
+ for (Element el : includeEls) {
+ assertTrue(links.contains(el.getAttribute("href")));
+ }
+ }
+
private boolean checkComplexType(List<Element> els, String name) {
for (Element e : els) {
if (name.equals(e.getAttribute("name"))) {
@@ -177,31 +322,30 @@
return false;
}
- private void checkBookStoreInfo(Element resource) {
+ private void checkBookStoreInfo(Element resource, String bookEl, String book2El, String chapterEl) {
assertEquals("/bookstore/{id}", resource.getAttribute("path"));
checkRootDocs(resource);
List<Element> resourceEls = DOMUtils.getChildrenWithName(resource,
WadlGenerator.WADL_NS, "resource");
- assertEquals(7, resourceEls.size());
- assertEquals("/", resourceEls.get(0).getAttribute("path"));
- assertEquals("/book2", resourceEls.get(1).getAttribute("path"));
- assertEquals("/books/{bookid}", resourceEls.get(2).getAttribute("path"));
- assertEquals("/chapter", resourceEls.get(3).getAttribute("path"));
- assertEquals("/books/{bookid}", resourceEls.get(4).getAttribute("path"));
- assertEquals("/booksubresource", resourceEls.get(5).getAttribute("path"));
- assertEquals("/itself", resourceEls.get(6).getAttribute("path"));
+ assertEquals(6, resourceEls.size());
+ assertEquals("/book2", resourceEls.get(0).getAttribute("path"));
+ assertEquals("/books/{bookid}", resourceEls.get(1).getAttribute("path"));
+ assertEquals("/chapter", resourceEls.get(2).getAttribute("path"));
+ assertEquals("/books/{bookid}", resourceEls.get(3).getAttribute("path"));
+ assertEquals("/booksubresource", resourceEls.get(4).getAttribute("path"));
+ assertEquals("/itself", resourceEls.get(5).getAttribute("path"));
- // verify repource starting with "/"
+ // verify root resource starting with "/"
// must have a single template parameter
- List<Element> paramsEls = DOMUtils.getChildrenWithName(resourceEls.get(0),
+ List<Element> paramsEls = DOMUtils.getChildrenWithName(resource,
WadlGenerator.WADL_NS, "param");
assertEquals(1, paramsEls.size());
checkParameter(paramsEls.get(0), "id", "template", "xs:long");
// must have 2 methods, GET and PUT
- List<Element> methodEls = DOMUtils.getChildrenWithName(resourceEls.get(0),
+ List<Element> methodEls = DOMUtils.getChildrenWithName(resource,
WadlGenerator.WADL_NS, "method");
assertEquals(2, methodEls.size());
@@ -236,10 +380,10 @@
verifyResponseWithStatus(methodEls.get(1), "204");
// verify resource starting with /book2
- verifyGetResourceMethod(resourceEls.get(1), "prefix1:thebook2");
+ verifyGetResourceMethod(resourceEls.get(0), book2El);
//verify resource starting with /books/{bookid}
- paramsEls = DOMUtils.getChildrenWithName(resourceEls.get(2),
+ paramsEls = DOMUtils.getChildrenWithName(resourceEls.get(1),
WadlGenerator.WADL_NS, "param");
// should have 3 parameters
assertEquals(3, paramsEls.size());
@@ -248,7 +392,7 @@
checkParameter(paramsEls.get(2), "mid", "matrix", "xs:int");
// and 2 methods
- methodEls = DOMUtils.getChildrenWithName(resourceEls.get(2),
+ methodEls = DOMUtils.getChildrenWithName(resourceEls.get(1),
WadlGenerator.WADL_NS, "method");
assertEquals(2, methodEls.size());
@@ -264,29 +408,29 @@
assertEquals(2, paramsEls.size());
checkParameter(paramsEls.get(0), "hid", "header", "xs:int");
checkParameter(paramsEls.get(1), "provider.bar", "query", "xs:int");
- verifyXmlJsonRepresentations(requestEls.get(0), "prefix1:thebook");
+ verifyXmlJsonRepresentations(requestEls.get(0), book2El);
// PUT
assertEquals("PUT", methodEls.get(1).getAttribute("name"));
requestEls = DOMUtils.getChildrenWithName(methodEls.get(1),
WadlGenerator.WADL_NS, "request");
assertEquals(1, requestEls.size());
- verifyXmlJsonRepresentations(requestEls.get(0), "prefix1:thebook");
+ verifyXmlJsonRepresentations(requestEls.get(0), bookEl);
verifyResponseWithStatus(methodEls.get(1), "204");
// verify resource starting with /chapter
- verifyGetResourceMethod(resourceEls.get(3), "prefix1:thechapter");
+ verifyGetResourceMethod(resourceEls.get(2), chapterEl);
// verify resource starting from /booksubresource
// should have 2 parameters
- paramsEls = DOMUtils.getChildrenWithName(resourceEls.get(5),
+ paramsEls = DOMUtils.getChildrenWithName(resourceEls.get(4),
WadlGenerator.WADL_NS, "param");
assertEquals(2, paramsEls.size());
checkParameter(paramsEls.get(0), "id", "template", "xs:int");
checkParameter(paramsEls.get(1), "mid", "matrix", "xs:int");
// should have 4 child resources
- List<Element> subResourceEls = DOMUtils.getChildrenWithName(resourceEls.get(5),
+ List<Element> subResourceEls = DOMUtils.getChildrenWithName(resourceEls.get(4),
WadlGenerator.WADL_NS, "resource");
assertEquals(4, subResourceEls.size());
assertEquals("/book", subResourceEls.get(0).getAttribute("path"));
@@ -295,7 +439,7 @@
assertEquals("/chapter/{cid}", subResourceEls.get(3).getAttribute("path"));
// verify subresource /book
// GET
- verifyGetResourceMethod(subResourceEls.get(0), "prefix1:thebook");
+ verifyGetResourceMethod(subResourceEls.get(0), bookEl);
// verify subresource /chapter/{id}
List<Element> chapterMethodEls = DOMUtils.getChildrenWithName(subResourceEls.get(3),
@@ -307,7 +451,7 @@
assertEquals(1, paramsEls.size());
checkParameter(paramsEls.get(0), "cid", "template", "xs:int");
// GET
- verifyGetResourceMethod(chapterMethodEls.get(0), "prefix1:thechapter");
+ verifyGetResourceMethod(chapterMethodEls.get(0), chapterEl);
}
private void checkRootDocs(Element el) {