Author: sergeyb
Date: Tue Mar 13 23:46:00 2012
New Revision: 1300418
URL: http://svn.apache.org/viewvc?rev=1300418&view=rev
Log:
Merged revisions 1299086,1299747 via svnmerge from
https://svn.apache.org/repos/asf/cxf/trunk
........
r1299086 | sergeyb | 2012-03-09 22:45:36 +0000 (Fri, 09 Mar 2012) | 1 line
[CXF-4172] Completing the messy workaround for Jettison, most of this code
will be hidden in the next Jettison release
........
r1299747 | sergeyb | 2012-03-12 17:24:22 +0000 (Mon, 12 Mar 2012) | 1 line
[CXF-4172] Adding tests for Source and Document
........
Modified:
cxf/branches/2.5.x-fixes/ (props changed)
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServiceImpl.java
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONUtils.java
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/SourceProvider.java
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/SourceProviderTest.java
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml
Propchange: cxf/branches/2.5.x-fixes/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Mar 13 23:46:00 2012
@@ -1 +1 @@
-/cxf/trunk:1236902,1297296,1298470,1298601-1298624,1298830,1298832,1299635,1299682,1299707,1300342
+/cxf/trunk:1236902,1297296,1298470,1298601-1298624,1298830,1298832,1299086,1299635,1299682,1299707,1299747,1300342
Propchange: cxf/branches/2.5.x-fixes/
------------------------------------------------------------------------------
Binary property 'svnmerge-integrated' - no diff available.
Modified:
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServiceImpl.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServiceImpl.java?rev=1300418&r1=1300417&r2=1300418&view=diff
==============================================================================
---
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServiceImpl.java
(original)
+++
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServiceImpl.java
Tue Mar 13 23:46:00 2012
@@ -29,6 +29,7 @@ import java.util.concurrent.Executor;
import javax.ws.rs.core.Response;
import javax.xml.namespace.QName;
+import javax.xml.transform.Source;
import org.apache.cxf.common.util.PackageUtils;
import org.apache.cxf.configuration.Configurable;
@@ -150,7 +151,7 @@ public class JAXRSServiceImpl extends Ab
private void createMessagePartInfo(OperationInfo oi, Class<?> type, QName
qname, Method m,
boolean input) {
- if (type == void.class) {
+ if (type == void.class || Source.class.isAssignableFrom(type)) {
return;
}
if (InjectionUtils.isPrimitive(type) || Response.class == type) {
Modified:
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONUtils.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONUtils.java?rev=1300418&r1=1300417&r2=1300418&view=diff
==============================================================================
---
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONUtils.java
(original)
+++
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONUtils.java
Tue Mar 13 23:46:00 2012
@@ -18,6 +18,8 @@
*/
package org.apache.cxf.jaxrs.provider;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
@@ -48,6 +50,7 @@ import org.codehaus.jettison.AbstractXML
import org.codehaus.jettison.AbstractXMLStreamWriter;
import org.codehaus.jettison.badgerfish.BadgerFishXMLInputFactory;
import org.codehaus.jettison.badgerfish.BadgerFishXMLOutputFactory;
+import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.codehaus.jettison.json.JSONTokener;
@@ -157,6 +160,7 @@ public final class JSONUtils {
}
private static class JettisonMappedReaderFactory extends
AbstractXMLInputFactory {
+ private static final int INPUT_BUF_SIZE = 4096;
private MappedNamespaceConvention convention;
private DocumentDepthProperties depthProps;
public JettisonMappedReaderFactory(Map<?, ?> nstojns,
DocumentDepthProperties depthProps) {
@@ -171,24 +175,194 @@ public final class JSONUtils {
} catch (JSONException e) {
throw new XMLStreamException(e);
}
- }
+ }
+ private String readAll(InputStream in, String encoding)
+ throws IOException {
+
+ final byte[] buffer = new byte[INPUT_BUF_SIZE];
+ ByteArrayOutputStream bos = null;
+ while (true) {
+ int count = in.read(buffer);
+ if (count < 0) { // EOF
+ break;
+ }
+ if (bos == null) {
+ int cap;
+ if (count < 64) {
+ cap = 64;
+ } else if (count == INPUT_BUF_SIZE) {
+ // Let's assume there's more coming, not just this
chunk
+ cap = INPUT_BUF_SIZE * 4;
+ } else {
+ cap = count;
+ }
+ bos = new ByteArrayOutputStream(cap);
+ }
+ bos.write(buffer, 0, count);
+ }
+ return (bos == null) ? "" : bos.toString(encoding);
+ }
+ public XMLStreamReader createXMLStreamReader(InputStream is, String
charset)
+ throws XMLStreamException {
+ /* !!! This is not really correct: should (try to) auto-detect
+ * encoding, since JSON only allows 3 Unicode-based variants.
+ * For now it's ok to default to UTF-8 though.
+ */
+ if (charset == null) {
+ charset = "UTF-8";
+ }
+ try {
+ String doc = readAll(is, charset);
+ return createXMLStreamReader(new JettisonJSONTokener(doc,
depthProps));
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+ }
+
+ private static class JettisonJSONTokener extends JSONTokener {
+ private DocumentDepthProperties depthProps;
+ public JettisonJSONTokener(String s, DocumentDepthProperties
depthProps) {
+ super(s);
+ this.depthProps = depthProps;
+ }
+ public Object nextValue() throws JSONException {
+ char c = nextClean();
+ switch (c) {
+ case '"':
+ case '\'':
+ return nextString(c);
+ case '{':
+ back();
+ return new JettisonJSONObject(this, depthProps);
+ case '[':
+ back();
+ return new JSONArray(this);
+ default:
+ }
+
+ return finalize(c);
+ }
+ private Object finalize(char c) throws JSONException {
+ StringBuffer sb = new StringBuffer();
+ char b = c;
+ while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
+ sb.append(c);
+ c = next();
+ }
+ back();
+
+ String s = sb.toString().trim();
+ if (s.length() == 0) {
+ throw new JSONException("Missing value.");
+ }
+ Object res = null;
+ if (s.equalsIgnoreCase("true")) {
+ res = Boolean.TRUE;
+ } else if (s.equalsIgnoreCase("false")) {
+ res = Boolean.FALSE;
+ } else if (s.equalsIgnoreCase("null")) {
+ res = JSONObject.NULL;
+ }
+ if (res != null) {
+ return res;
+ }
+ if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') {
+ if (b == '0') {
+ if (s.length() > 2 && (s.charAt(1) == 'x' || s.charAt(1)
== 'X')) {
+ try {
+ res = new Integer(Integer.parseInt(s.substring(2),
+ 16));
+ } catch (Exception e) {
+ /* Ignore the error */
+ }
+ } else {
+ try {
+ res = new Integer(Integer.parseInt(s, 8));
+ } catch (Exception e) {
+ /* Ignore the error */
+ }
+ }
+ }
+ if (res == null) {
+ try {
+ res = new Integer(s);
+ } catch (Exception e) {
+ try {
+ res = new Long(s);
+ } catch (Exception f) {
+ try {
+ res = new Double(s);
+ } catch (Exception g) {
+ res = s;
+ }
+ }
+ }
+ }
+ if (res != null) {
+ return res;
+ }
+ }
+ return s;
+ }
}
private static class JettisonJSONObject extends JSONObject {
private static final long serialVersionUID = 9016458891093343731L;
private int threshold;
- public JettisonJSONObject(JSONTokener tokener, DocumentDepthProperties
depthProps)
+
+ public JettisonJSONObject(JSONTokener x, DocumentDepthProperties
depthProps)
throws JSONException {
- super(tokener);
this.threshold = depthProps.getElementCountThreshold() != -1
? depthProps.getElementCountThreshold() :
depthProps.getInnerElementCountThreshold();
+ String key;
+ char c;
+ if (x.nextClean() != '{') {
+ throw x.syntaxError("A JSONObject text must begin with '{'");
+ }
+ for (;;) {
+ c = x.nextClean();
+ switch (c) {
+ case 0:
+ throw x.syntaxError("A JSONObject text must end with '}'");
+ case '}':
+ return;
+ default:
+ x.back();
+ key = x.nextValue().toString();
+ }
+
+ c = x.nextClean();
+ if (c == '=') {
+ if (x.next() != '>') {
+ x.back();
+ }
+ } else if (c != ':') {
+ throw x.syntaxError("Expected a ':' after a key");
+ }
+ put(key, x.nextValue()); //NOPMD
+ switch (x.nextClean()) {
+ case ';':
+ case ',':
+ if (x.nextClean() == '}') {
+ return;
+ }
+ x.back();
+ break;
+ case '}':
+ return;
+ default:
+ throw new JSONException("Expected a ',' or '}'");
+ }
+ }
}
- @Override
public JSONObject put(String key, Object value) throws JSONException {
+ JSONObject obj = super.put(key, value);
if (threshold != -1 && super.length() >= threshold) {
throw new DepthExceededStaxException();
}
- return super.put(key, value);
+ return obj;
+
}
}
Modified:
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/SourceProvider.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/SourceProvider.java?rev=1300418&r1=1300417&r2=1300418&view=diff
==============================================================================
---
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/SourceProvider.java
(original)
+++
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/SourceProvider.java
Tue Mar 13 23:46:00 2012
@@ -48,6 +48,7 @@ import org.apache.cxf.io.CachedOutputStr
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.ext.xml.XMLSource;
import org.apache.cxf.jaxrs.utils.HttpUtils;
+import org.apache.cxf.staxutils.DepthExceededStaxException;
import org.apache.cxf.staxutils.StaxSource;
import org.apache.cxf.staxutils.StaxUtils;
@@ -92,6 +93,8 @@ public class SourceProvider extends Abst
try {
Document doc = StaxUtils.read(reader);
return docRequired ? doc : new DOMSource(doc);
+ } catch (DepthExceededStaxException e) {
+ throw new WebApplicationException(413);
} catch (Exception e) {
IOException ioex = new IOException("Problem creating a Source
object");
ioex.setStackTrace(e.getStackTrace());
@@ -184,11 +187,12 @@ public class SourceProvider extends Abst
protected String getPreferredSource() {
MessageContext mc = getContext();
+ String source = null;
if (mc != null) {
- return (String)mc.getContextualProperty(PREFERRED_FORMAT);
- } else {
- return "sax";
- }
+ source = (String)mc.getContextualProperty(PREFERRED_FORMAT);
+ }
+ return source != null ? source : "sax";
+
}
protected MessageContext getContext() {
Modified:
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/SourceProviderTest.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/SourceProviderTest.java?rev=1300418&r1=1300417&r2=1300418&view=diff
==============================================================================
---
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/SourceProviderTest.java
(original)
+++
cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/SourceProviderTest.java
Tue Mar 13 23:46:00 2012
@@ -76,7 +76,7 @@ public class SourceProviderTest extends
public void testReadFrom() throws Exception {
SourceProvider p = new TestSourceProvider();
assertSame(StreamSource.class, verifyRead(p,
StreamSource.class).getClass());
- assertSame(StreamSource.class, verifyRead(p, Source.class).getClass());
+ assertSame(StaxSource.class, verifyRead(p, Source.class).getClass());
assertSame(StaxSource.class, verifyRead(p,
SAXSource.class).getClass());
assertSame(StaxSource.class, verifyRead(p,
StaxSource.class).getClass());
assertSame(DOMSource.class, verifyRead(p, DOMSource.class).getClass());
Modified:
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java?rev=1300418&r1=1300417&r2=1300418&view=diff
==============================================================================
---
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java
(original)
+++
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java
Tue Mar 13 23:46:00 2012
@@ -20,6 +20,7 @@
package org.apache.cxf.systest.jaxrs;
+import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;
@@ -34,12 +35,17 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
import org.apache.cxf.annotations.Logging;
+import org.apache.cxf.staxutils.DepthExceededStaxException;
+import org.apache.cxf.staxutils.StaxUtils;
@Path("/")
@Produces("application/json")
@@ -147,6 +153,27 @@ public class BookStoreSpring {
}
@POST
+ @Path("depth-source")
+ @Consumes({"application/xml" })
+ public void postSourceBook(Source source) {
+ try {
+ StaxUtils.copy(source, new ByteArrayOutputStream());
+ } catch (DepthExceededStaxException ex) {
+ throw new WebApplicationException(413);
+ } catch (Exception ex) {
+ // ignore for now
+ }
+ throw new WebApplicationException(500);
+ }
+
+ @POST
+ @Path("depth-dom")
+ @Consumes({"application/xml" })
+ public void postDomBook(DOMSource source) {
+ // complete
+ }
+
+ @POST
@Path("depth-form")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void depthForm(MultivaluedMap<String, String> map) {
Modified:
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java?rev=1300418&r1=1300417&r2=1300418&view=diff
==============================================================================
---
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java
(original)
+++
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java
Tue Mar 13 23:46:00 2012
@@ -65,7 +65,7 @@ public class JAXRSClientServerSpringBook
@BeforeClass
public static void startServers() throws Exception {
assertTrue("server did not launch correctly",
- launchServer(BookServerSpring.class));
+ launchServer(BookServerSpring.class, true));
}
@Test
@@ -232,6 +232,25 @@ public class JAXRSClientServerSpringBook
}
@Test
+ public void testBookDepthExceededXMLSource() throws Exception {
+ String endpointAddress =
+ "http://localhost:" + PORT + "/the/thebooks9/depth-source";
+ WebClient wc = WebClient.create(endpointAddress);
+ Response r = wc.post(new Book("CXF", 123L));
+ assertEquals(413, r.getStatus());
+ }
+
+ @Test
+ public void testBookDepthExceededXMLDom() throws Exception {
+ String endpointAddress =
+ "http://localhost:" + PORT + "/the/thebooks9/depth-dom";
+ WebClient wc = WebClient.create(endpointAddress);
+
WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(1000000L);
+ Response r = wc.post(new Book("CXF", 123L));
+ assertEquals(413, r.getStatus());
+ }
+
+ @Test
public void testBookDepthExceededJettison() throws Exception {
String endpointAddress =
"http://localhost:" + PORT + "/the/thebooks10/depth";
@@ -259,7 +278,6 @@ public class JAXRSClientServerSpringBook
WebClient client = WebClient.create(url);
client.accept("application/json, application/x-javascript");
client.query("_jsonp", "callback");
-
WebClient.getConfig(client).getHttpConduit().getClient().setReceiveTimeout(1000000L);
Response r = client.get();
assertEquals("application/x-javascript",
r.getMetadata().getFirst("Content-Type"));
assertEquals("callback({\"Book\":{\"id\":123,\"name\":\"CXF in
Action\"}});",
Modified:
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml
URL:
http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml?rev=1300418&r1=1300417&r2=1300418&view=diff
==============================================================================
---
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml
(original)
+++
cxf/branches/2.5.x-fixes/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml
Tue Mar 13 23:46:00 2012
@@ -221,7 +221,7 @@ http://cxf.apache.org/schemas/core.xsd">
<ref bean="serviceBean" />
</jaxrs:serviceBeans>
<jaxrs:properties>
- <entry key="org.apache.cxf.staxutils.innerElementLevelThreshold"
value="2"/>
+ <entry key="org.apache.cxf.staxutils.innerElementCountThreshold"
value="2"/>
</jaxrs:properties>
</jaxrs:server>