http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java ---------------------------------------------------------------------- diff --git a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java new file mode 100644 index 0000000..2f69bb1 --- /dev/null +++ b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java @@ -0,0 +1,1627 @@ +// *************************************************************************************************************************** +// * 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.juneau.rest.test; + +import static org.apache.juneau.rest.test.TestUtils.*; +import static org.apache.juneau.rest.test.pojos.Constants.*; +import static org.junit.Assert.*; + +import java.util.*; + +import org.apache.juneau.html.*; +import org.apache.juneau.jena.*; +import org.apache.juneau.json.*; +import org.apache.juneau.msgpack.*; +import org.apache.juneau.parser.*; +import org.apache.juneau.remoteable.*; +import org.apache.juneau.rest.test.pojos.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.uon.*; +import org.apache.juneau.urlencoding.*; +import org.apache.juneau.utils.*; +import org.apache.juneau.xml.*; +import org.junit.*; +import org.junit.runner.*; +import org.junit.runners.*; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RunWith(Parameterized.class) +public class ThirdPartyProxyTest extends RestTestcase { + + @Parameterized.Parameters + public static Collection<Object[]> getParameters() { + return Arrays.asList(new Object[][] { + { /* 0 */ "Json", JsonSerializer.DEFAULT, JsonParser.DEFAULT }, + { /* 1 */ "Xml", XmlSerializer.DEFAULT, XmlParser.DEFAULT }, + { /* 2 */ "Mixed", JsonSerializer.DEFAULT, XmlParser.DEFAULT }, + { /* 3 */ "Html", HtmlSerializer.DEFAULT, HtmlParser.DEFAULT }, + { /* 4 */ "MessagePack", MsgPackSerializer.DEFAULT, MsgPackParser.DEFAULT }, + { /* 5 */ "UrlEncoding", UrlEncodingSerializer.DEFAULT, UrlEncodingParser.DEFAULT }, + { /* 6 */ "Uon", UonSerializer.DEFAULT, UonParser.DEFAULT }, + { /* 7 */ "RdfXml", RdfSerializer.DEFAULT_XMLABBREV, RdfParser.DEFAULT_XML }, + }); + } + + private ThirdPartyProxy proxy; + + public ThirdPartyProxyTest(String label, Serializer serializer, Parser parser) { + proxy = getCached(label, ThirdPartyProxy.class); + if (proxy == null) { + this.proxy = getClient(label, serializer, parser).getRemoteableProxy(ThirdPartyProxy.class, null, serializer, parser); + cache(label, proxy); + } + } + + //-------------------------------------------------------------------------------- + // Header tests + //-------------------------------------------------------------------------------- + + @Test + public void a01_primitiveHeaders() throws Exception { + String r = proxy.primitiveHeaders( + "foo", + null, + 123, + 123, + null, + true, + 1.0f, + 1.0f + ); + assertEquals("OK", r); + } + + @Test + public void a02_primitiveCollectionHeaders() throws Exception { + String r = proxy.primitiveCollectionHeaders( + new int[][][]{{{1,2},null},null}, + new Integer[][][]{{{1,null},null},null}, + new String[][][]{{{"foo",null},null},null}, + new AList<Integer>().append(1).append(null), + new AList<List<List<Integer>>>() + .append( + new AList<List<Integer>>() + .append(new AList<Integer>().append(1).append(null)) + .append(null) + ) + .append(null) + , + new AList<Integer[][][]>().append(new Integer[][][]{{{1,null},null},null}).append(null), + new AList<int[][][]>().append(new int[][][]{{{1,2},null},null}).append(null), + Arrays.asList("foo","bar",null) + ); + assertEquals("OK", r); + } + + @Test + public void a03_beanHeaders() throws Exception { + String r = proxy.beanHeaders( + new ABean().init(), + null, + new ABean[][][]{{{new ABean().init(),null},null},null}, + new AList<ABean>().append(new ABean().init()).append(null), + new AList<ABean[][][]>().append(new ABean[][][]{{{new ABean().init(),null},null},null}).append(null), + new AMap<String,ABean>().append("foo",new ABean().init()), + new AMap<String,List<ABean>>().append("foo",Arrays.asList(new ABean().init())), + new AMap<String,List<ABean[][][]>>().append("foo",new AList<ABean[][][]>().append(new ABean[][][]{{{new ABean().init(),null},null},null}).append(null)), + new AMap<Integer,List<ABean>>().append(1,Arrays.asList(new ABean().init())) + ); + assertEquals("OK", r); + } + + + @Test + public void a04_typedBeanHeaders() throws Exception { + String r = proxy.typedBeanHeaders( + new TypedBeanImpl().init(), + null, + new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}, + new AList<TypedBean>().append(new TypedBeanImpl().init()).append(null), + new AList<TypedBean[][][]>().append(new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}).append(null), + new AMap<String,TypedBean>().append("foo",new TypedBeanImpl().init()), + new AMap<String,List<TypedBean>>().append("foo",Arrays.asList((TypedBean)new TypedBeanImpl().init())), + new AMap<String,List<TypedBean[][][]>>().append("foo",new AList<TypedBean[][][]>().append(new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}).append(null)), + new AMap<Integer,List<TypedBean>>().append(1,Arrays.asList((TypedBean)new TypedBeanImpl().init())) + ); + assertEquals("OK", r); + } + + @Test + public void a05_swappedPojoHeaders() throws Exception { + String r = proxy.swappedPojoHeaders( + new SwappedPojo(), + new SwappedPojo[][][]{{{new SwappedPojo(),null},null},null}, + new AMap<SwappedPojo,SwappedPojo>().append(new SwappedPojo(), new SwappedPojo()), + new AMap<SwappedPojo,SwappedPojo[][][]>().append(new SwappedPojo(), new SwappedPojo[][][]{{{new SwappedPojo(),null},null},null}) + ); + assertEquals("OK", r); + } + + @Test + public void a06_implicitSwappedPojoHeaders() throws Exception { + String r = proxy.implicitSwappedPojoHeaders( + new ImplicitSwappedPojo(), + new ImplicitSwappedPojo[][][]{{{new ImplicitSwappedPojo(),null},null},null}, + new AMap<ImplicitSwappedPojo,ImplicitSwappedPojo>().append(new ImplicitSwappedPojo(), new ImplicitSwappedPojo()), + new AMap<ImplicitSwappedPojo,ImplicitSwappedPojo[][][]>().append(new ImplicitSwappedPojo(), new ImplicitSwappedPojo[][][]{{{new ImplicitSwappedPojo(),null},null},null}) + ); + assertEquals("OK", r); + } + + @Test + public void a07_enumHeaders() throws Exception { + String r = proxy.enumHeaders( + TestEnum.TWO, + null, + new TestEnum[][][]{{{TestEnum.TWO,null},null},null}, + new AList<TestEnum>().append(TestEnum.TWO).append(null), + new AList<List<List<TestEnum>>>() + .append( + new AList<List<TestEnum>>() + .append( + new AList<TestEnum>().append(TestEnum.TWO).append(null) + ) + .append(null) + ).append(null), + new AList<TestEnum[][][]>().append(new TestEnum[][][]{{{TestEnum.TWO,null},null},null}).append(null), + new AMap<TestEnum,TestEnum>().append(TestEnum.ONE,TestEnum.TWO), + new AMap<TestEnum,TestEnum[][][]>().append(TestEnum.ONE, new TestEnum[][][]{{{TestEnum.TWO,null},null},null}), + new AMap<TestEnum,List<TestEnum[][][]>>().append(TestEnum.ONE, new AList<TestEnum[][][]>().append(new TestEnum[][][]{{{TestEnum.TWO,null},null},null}).append(null)) + ); + assertEquals("OK", r); + } + + //-------------------------------------------------------------------------------- + // Query tests + //-------------------------------------------------------------------------------- + + @Test + public void b01_primitiveQueries() throws Exception { + String r = proxy.primitiveQueries( + "foo", + null, + 123, + 123, + null, + true, + 1.0f, + 1.0f + ); + assertEquals("OK", r); + } + + @Test + public void b02_primitiveCollectionQueries() throws Exception { + String r = proxy.primitiveCollectionQueries( + new int[][][]{{{1,2},null},null}, + new Integer[][][]{{{1,null},null},null}, + new String[][][]{{{"foo",null},null},null}, + new AList<Integer>().append(1).append(null), + new AList<List<List<Integer>>>() + .append( + new AList<List<Integer>>() + .append(new AList<Integer>().append(1).append(null)) + .append(null) + ) + .append(null) + , + new AList<Integer[][][]>().append(new Integer[][][]{{{1,null},null},null}).append(null), + new AList<int[][][]>().append(new int[][][]{{{1,2},null},null}).append(null), + Arrays.asList("foo","bar",null) + ); + assertEquals("OK", r); + } + + @Test + public void b03_beanQueries() throws Exception { + String r = proxy.beanQueries( + new ABean().init(), + null, + new ABean[][][]{{{new ABean().init(),null},null},null}, + new AList<ABean>().append(new ABean().init()).append(null), + new AList<ABean[][][]>().append(new ABean[][][]{{{new ABean().init(),null},null},null}).append(null), + new AMap<String,ABean>().append("foo",new ABean().init()), + new AMap<String,List<ABean>>().append("foo",Arrays.asList(new ABean().init())), + new AMap<String,List<ABean[][][]>>().append("foo",new AList<ABean[][][]>().append(new ABean[][][]{{{new ABean().init(),null},null},null}).append(null)), + new AMap<Integer,List<ABean>>().append(1,Arrays.asList(new ABean().init())) + ); + assertEquals("OK", r); + } + + + @Test + public void b04_typedBeanQueries() throws Exception { + String r = proxy.typedBeanQueries( + new TypedBeanImpl().init(), + null, + new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}, + new AList<TypedBean>().append(new TypedBeanImpl().init()).append(null), + new AList<TypedBean[][][]>().append(new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}).append(null), + new AMap<String,TypedBean>().append("foo",new TypedBeanImpl().init()), + new AMap<String,List<TypedBean>>().append("foo",Arrays.asList((TypedBean)new TypedBeanImpl().init())), + new AMap<String,List<TypedBean[][][]>>().append("foo",new AList<TypedBean[][][]>().append(new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}).append(null)), + new AMap<Integer,List<TypedBean>>().append(1,Arrays.asList((TypedBean)new TypedBeanImpl().init())) + ); + assertEquals("OK", r); + } + + @Test + public void b05_swappedPojoQueries() throws Exception { + String r = proxy.swappedPojoQueries( + new SwappedPojo(), + new SwappedPojo[][][]{{{new SwappedPojo(),null},null},null}, + new AMap<SwappedPojo,SwappedPojo>().append(new SwappedPojo(), new SwappedPojo()), + new AMap<SwappedPojo,SwappedPojo[][][]>().append(new SwappedPojo(), new SwappedPojo[][][]{{{new SwappedPojo(),null},null},null}) + ); + assertEquals("OK", r); + } + + @Test + public void b06_implicitSwappedPojoQueries() throws Exception { + String r = proxy.implicitSwappedPojoQueries( + new ImplicitSwappedPojo(), + new ImplicitSwappedPojo[][][]{{{new ImplicitSwappedPojo(),null},null},null}, + new AMap<ImplicitSwappedPojo,ImplicitSwappedPojo>().append(new ImplicitSwappedPojo(), new ImplicitSwappedPojo()), + new AMap<ImplicitSwappedPojo,ImplicitSwappedPojo[][][]>().append(new ImplicitSwappedPojo(), new ImplicitSwappedPojo[][][]{{{new ImplicitSwappedPojo(),null},null},null}) + ); + assertEquals("OK", r); + } + + @Test + public void b07_enumQueries() throws Exception { + String r = proxy.enumQueries( + TestEnum.TWO, + null, + new TestEnum[][][]{{{TestEnum.TWO,null},null},null}, + new AList<TestEnum>().append(TestEnum.TWO).append(null), + new AList<List<List<TestEnum>>>() + .append( + new AList<List<TestEnum>>() + .append( + new AList<TestEnum>().append(TestEnum.TWO).append(null) + ) + .append(null) + ).append(null), + new AList<TestEnum[][][]>().append(new TestEnum[][][]{{{TestEnum.TWO,null},null},null}).append(null), + new AMap<TestEnum,TestEnum>().append(TestEnum.ONE,TestEnum.TWO), + new AMap<TestEnum,TestEnum[][][]>().append(TestEnum.ONE, new TestEnum[][][]{{{TestEnum.TWO,null},null},null}), + new AMap<TestEnum,List<TestEnum[][][]>>().append(TestEnum.ONE, new AList<TestEnum[][][]>().append(new TestEnum[][][]{{{TestEnum.TWO,null},null},null}).append(null)) + ); + assertEquals("OK", r); + } + + //-------------------------------------------------------------------------------- + // FormData tests + //-------------------------------------------------------------------------------- + + @Test + public void c01_primitiveFormData() throws Exception { + String r = proxy.primitiveFormData( + "foo", + null, + 123, + 123, + null, + true, + 1.0f, + 1.0f + ); + assertEquals("OK", r); + } + + @Test + public void c02_primitiveCollectionFormData() throws Exception { + String r = proxy.primitiveCollectionFormData( + new int[][][]{{{1,2},null},null}, + new Integer[][][]{{{1,null},null},null}, + new String[][][]{{{"foo",null},null},null}, + new AList<Integer>().append(1).append(null), + new AList<List<List<Integer>>>() + .append( + new AList<List<Integer>>() + .append(new AList<Integer>().append(1).append(null)) + .append(null) + ) + .append(null) + , + new AList<Integer[][][]>().append(new Integer[][][]{{{1,null},null},null}).append(null), + new AList<int[][][]>().append(new int[][][]{{{1,2},null},null}).append(null), + Arrays.asList("foo","bar",null) + ); + assertEquals("OK", r); + } + + @Test + public void c03_beanFormData() throws Exception { + String r = proxy.beanFormData( + new ABean().init(), + null, + new ABean[][][]{{{new ABean().init(),null},null},null}, + new AList<ABean>().append(new ABean().init()).append(null), + new AList<ABean[][][]>().append(new ABean[][][]{{{new ABean().init(),null},null},null}).append(null), + new AMap<String,ABean>().append("foo",new ABean().init()), + new AMap<String,List<ABean>>().append("foo",Arrays.asList(new ABean().init())), + new AMap<String,List<ABean[][][]>>().append("foo",new AList<ABean[][][]>().append(new ABean[][][]{{{new ABean().init(),null},null},null}).append(null)), + new AMap<Integer,List<ABean>>().append(1,Arrays.asList(new ABean().init())) + ); + assertEquals("OK", r); + } + + + @Test + public void c04_typedBeanFormData() throws Exception { + String r = proxy.typedBeanFormData( + new TypedBeanImpl().init(), + null, + new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}, + new AList<TypedBean>().append(new TypedBeanImpl().init()).append(null), + new AList<TypedBean[][][]>().append(new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}).append(null), + new AMap<String,TypedBean>().append("foo",new TypedBeanImpl().init()), + new AMap<String,List<TypedBean>>().append("foo",Arrays.asList((TypedBean)new TypedBeanImpl().init())), + new AMap<String,List<TypedBean[][][]>>().append("foo",new AList<TypedBean[][][]>().append(new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}).append(null)), + new AMap<Integer,List<TypedBean>>().append(1,Arrays.asList((TypedBean)new TypedBeanImpl().init())) + ); + assertEquals("OK", r); + } + + @Test + public void c05_swappedPojoFormData() throws Exception { + String r = proxy.swappedPojoFormData( + new SwappedPojo(), + new SwappedPojo[][][]{{{new SwappedPojo(),null},null},null}, + new AMap<SwappedPojo,SwappedPojo>().append(new SwappedPojo(), new SwappedPojo()), + new AMap<SwappedPojo,SwappedPojo[][][]>().append(new SwappedPojo(), new SwappedPojo[][][]{{{new SwappedPojo(),null},null},null}) + ); + assertEquals("OK", r); + } + + @Test + public void c06_implicitSwappedPojoFormData() throws Exception { + String r = proxy.implicitSwappedPojoFormData( + new ImplicitSwappedPojo(), + new ImplicitSwappedPojo[][][]{{{new ImplicitSwappedPojo(),null},null},null}, + new AMap<ImplicitSwappedPojo,ImplicitSwappedPojo>().append(new ImplicitSwappedPojo(), new ImplicitSwappedPojo()), + new AMap<ImplicitSwappedPojo,ImplicitSwappedPojo[][][]>().append(new ImplicitSwappedPojo(), new ImplicitSwappedPojo[][][]{{{new ImplicitSwappedPojo(),null},null},null}) + ); + assertEquals("OK", r); + } + + @Test + public void c07_enumFormData() throws Exception { + String r = proxy.enumFormData( + TestEnum.TWO, + null, + new TestEnum[][][]{{{TestEnum.TWO,null},null},null}, + new AList<TestEnum>().append(TestEnum.TWO).append(null), + new AList<List<List<TestEnum>>>() + .append( + new AList<List<TestEnum>>() + .append( + new AList<TestEnum>().append(TestEnum.TWO).append(null) + ) + .append(null) + ).append(null), + new AList<TestEnum[][][]>().append(new TestEnum[][][]{{{TestEnum.TWO,null},null},null}).append(null), + new AMap<TestEnum,TestEnum>().append(TestEnum.ONE,TestEnum.TWO), + new AMap<TestEnum,TestEnum[][][]>().append(TestEnum.ONE, new TestEnum[][][]{{{TestEnum.TWO,null},null},null}), + new AMap<TestEnum,List<TestEnum[][][]>>().append(TestEnum.ONE, new AList<TestEnum[][][]>().append(new TestEnum[][][]{{{TestEnum.TWO,null},null},null}).append(null)) + ); + assertEquals("OK", r); + } + + //-------------------------------------------------------------------------------- + // Test return types. + //-------------------------------------------------------------------------------- + + // Various primitives + @Test + public void da01_returnVoid() { + proxy.returnVoid(); + } + + @Test + public void da02_returnInteger() { + assertEquals((Integer)1, proxy.returnInteger()); + } + + @Test + public void da03_returnInt() { + assertEquals(1, proxy.returnInt()); + } + + @Test + public void da04_returnBoolean() { + assertEquals(true, proxy.returnBoolean()); + } + + @Test + public void da05_returnFloat() { + assertTrue(1f == proxy.returnFloat()); + } + + @Test + public void da06_returnFloatObject() { + assertTrue(1f == proxy.returnFloatObject()); + } + + @Test + public void da07_returnString() { + assertEquals("foobar", proxy.returnString()); + } + + @Test + public void da08_returnNullString() { + assertNull(proxy.returnNullString()); + } + + @Test + public void da09_returnInt3dArray() { + assertObjectEquals("[[[1,2],null],null]", proxy.returnInt3dArray()); + } + + @Test + public void da10_returnInteger3dArray() { + assertObjectEquals("[[[1,null],null],null]", proxy.returnInteger3dArray()); + } + + @Test + public void da11_returnString3dArray() { + assertObjectEquals("[[['foo','bar',null],null],null]", proxy.returnString3dArray()); + } + + @Test + public void da12_returnIntegerList() { + List<Integer> x = proxy.returnIntegerList(); + assertObjectEquals("[1,null]", x); + assertClass(Integer.class, x.get(0)); + } + + @Test + public void da13_returnInteger3dList() { + List<List<List<Integer>>> x = proxy.returnInteger3dList(); + assertObjectEquals("[[[1,null],null],null]", x); + assertClass(Integer.class, x.get(0).get(0).get(0)); + } + + @Test + public void da14_returnInteger1d3dList() { + List<Integer[][][]> x = proxy.returnInteger1d3dList(); + assertObjectEquals("[[[[1,null],null],null],null]", x); + assertClass(Integer.class, x.get(0)[0][0][0]); + } + + @Test + public void da15_returnInt1d3dList() { + List<int[][][]> x = proxy.returnInt1d3dList(); + assertObjectEquals("[[[[1,2],null],null],null]", x); + assertClass(int[][][].class, x.get(0)); + } + + @Test + public void da16_returnStringList() { + assertObjectEquals("['foo','bar',null]", proxy.returnStringList()); + } + + // Beans + + @Test + public void db01_returnBean() { + ABean x = proxy.returnBean(); + assertObjectEquals("{a:1,b:'foo'}", x); + assertClass(ABean.class, x); + } + + @Test + public void db02_returnBean3dArray() { + ABean[][][] x = proxy.returnBean3dArray(); + assertObjectEquals("[[[{a:1,b:'foo'},null],null],null]", x); + assertClass(ABean.class, x[0][0][0]); + } + + @Test + public void db03_returnBeanList() { + List<ABean> x = proxy.returnBeanList(); + assertObjectEquals("[{a:1,b:'foo'}]", x); + assertClass(ABean.class, x.get(0)); + } + + @Test + public void db04_returnBean1d3dList() { + List<ABean[][][]> x = proxy.returnBean1d3dList(); + assertObjectEquals("[[[[{a:1,b:'foo'},null],null],null],null]", x); + assertClass(ABean.class, x.get(0)[0][0][0]); + } + + @Test + public void db05_returnBeanMap() { + Map<String,ABean> x = proxy.returnBeanMap(); + assertObjectEquals("{foo:{a:1,b:'foo'}}", x); + assertClass(ABean.class, x.get("foo")); + } + + @Test + public void db06_returnBeanListMap() { + Map<String,List<ABean>> x = proxy.returnBeanListMap(); + assertObjectEquals("{foo:[{a:1,b:'foo'}]}", x); + assertClass(ABean.class, x.get("foo").get(0)); + } + + @Test + public void db07_returnBean1d3dListMap() { + Map<String,List<ABean[][][]>> x = proxy.returnBean1d3dListMap(); + assertObjectEquals("{foo:[[[[{a:1,b:'foo'},null],null],null],null]}", x); + assertClass(ABean.class, x.get("foo").get(0)[0][0][0]); + } + + @Test + public void db08_returnBeanListMapIntegerKeys() { + // Note: JsonSerializer serializes key as string. + Map<Integer,List<ABean>> x = proxy.returnBeanListMapIntegerKeys(); + assertObjectEquals("{'1':[{a:1,b:'foo'}]}", x); + assertClass(Integer.class, x.keySet().iterator().next()); + } + + // Typed beans + + @Test + public void dc01_returnTypedBean() { + TypedBean x = proxy.returnTypedBean(); + assertObjectEquals("{_type:'TypedBeanImpl',a:1,b:'foo'}", x); + assertClass(TypedBeanImpl.class, x); + } + + @Test + public void dc02_returnTypedBean3dArray() { + TypedBean[][][] x = proxy.returnTypedBean3dArray(); + assertObjectEquals("[[[{_type:'TypedBeanImpl',a:1,b:'foo'},null],null],null]", x); + assertClass(TypedBeanImpl.class, x[0][0][0]); + } + + @Test + public void dc03_returnTypedBeanList() { + List<TypedBean> x = proxy.returnTypedBeanList(); + assertObjectEquals("[{_type:'TypedBeanImpl',a:1,b:'foo'}]", x); + assertClass(TypedBeanImpl.class, x.get(0)); + } + + @Test + public void dc04_returnTypedBean1d3dList() { + List<TypedBean[][][]> x = proxy.returnTypedBean1d3dList(); + assertObjectEquals("[[[[{_type:'TypedBeanImpl',a:1,b:'foo'},null],null],null],null]", x); + assertClass(TypedBeanImpl.class, x.get(0)[0][0][0]); + } + + @Test + public void dc05_returnTypedBeanMap() { + Map<String,TypedBean> x = proxy.returnTypedBeanMap(); + assertObjectEquals("{foo:{_type:'TypedBeanImpl',a:1,b:'foo'}}", x); + assertClass(TypedBeanImpl.class, x.get("foo")); + } + + @Test + public void dc06_returnTypedBeanListMap() { + Map<String,List<TypedBean>> x = proxy.returnTypedBeanListMap(); + assertObjectEquals("{foo:[{_type:'TypedBeanImpl',a:1,b:'foo'}]}", x); + assertClass(TypedBeanImpl.class, x.get("foo").get(0)); + } + + @Test + public void dc07_returnTypedBean1d3dListMap() { + Map<String,List<TypedBean[][][]>> x = proxy.returnTypedBean1d3dListMap(); + assertObjectEquals("{foo:[[[[{_type:'TypedBeanImpl',a:1,b:'foo'},null],null],null],null]}", x); + assertClass(TypedBeanImpl.class, x.get("foo").get(0)[0][0][0]); + } + + @Test + public void dc08_returnTypedBeanListMapIntegerKeys() { + // Note: JsonSerializer serializes key as string. + Map<Integer,List<TypedBean>> x = proxy.returnTypedBeanListMapIntegerKeys(); + assertObjectEquals("{'1':[{_type:'TypedBeanImpl',a:1,b:'foo'}]}", x); + assertClass(TypedBeanImpl.class, x.get(1).get(0)); + } + + // Swapped POJOs + + @Test + public void dd01_returnSwappedPojo() { + SwappedPojo x = proxy.returnSwappedPojo(); + assertObjectEquals("'"+SWAP+"'", x); + assertTrue(x.wasUnswapped); + } + + @Test + public void dd02_returnSwappedPojo3dArray() { + SwappedPojo[][][] x = proxy.returnSwappedPojo3dArray(); + assertObjectEquals("[[['"+SWAP+"',null],null],null]", x); + assertTrue(x[0][0][0].wasUnswapped); + } + + @Test + public void dd03_returnSwappedPojoMap() { + Map<SwappedPojo,SwappedPojo> x = proxy.returnSwappedPojoMap(); + assertObjectEquals("{'"+SWAP+"':'"+SWAP+"'}", x); + Map.Entry<SwappedPojo,SwappedPojo> e = x.entrySet().iterator().next(); + assertTrue(e.getKey().wasUnswapped); + assertTrue(e.getValue().wasUnswapped); + } + + @Test + public void dd04_returnSwappedPojo3dMap() { + Map<SwappedPojo,SwappedPojo[][][]> x = proxy.returnSwappedPojo3dMap(); + assertObjectEquals("{'"+SWAP+"':[[['"+SWAP+"',null],null],null]}", x); + Map.Entry<SwappedPojo,SwappedPojo[][][]> e = x.entrySet().iterator().next(); + assertTrue(e.getKey().wasUnswapped); + assertTrue(e.getValue()[0][0][0].wasUnswapped); + } + + // Implicit swapped POJOs + + @Test + public void de01_returnImplicitSwappedPojo() { + ImplicitSwappedPojo x = proxy.returnImplicitSwappedPojo(); + assertObjectEquals("'"+SWAP+"'", x); + assertTrue(x.wasUnswapped); + } + + @Test + public void de02_returnImplicitSwappedPojo3dArray() { + ImplicitSwappedPojo[][][] x = proxy.returnImplicitSwappedPojo3dArray(); + assertObjectEquals("[[['"+SWAP+"',null],null],null]", x); + assertTrue(x[0][0][0].wasUnswapped); + } + + @Test + public void de03_returnImplicitSwappedPojoMap() { + Map<ImplicitSwappedPojo,ImplicitSwappedPojo> x = proxy.returnImplicitSwappedPojoMap(); + assertObjectEquals("{'"+SWAP+"':'"+SWAP+"'}", x); + Map.Entry<ImplicitSwappedPojo,ImplicitSwappedPojo> e = x.entrySet().iterator().next(); + assertTrue(e.getKey().wasUnswapped); + assertTrue(e.getValue().wasUnswapped); + } + + @Test + public void de04_returnImplicitSwappedPojo3dMap() { + Map<ImplicitSwappedPojo,ImplicitSwappedPojo[][][]> x = proxy.returnImplicitSwappedPojo3dMap(); + assertObjectEquals("{'"+SWAP+"':[[['"+SWAP+"',null],null],null]}", x); + Map.Entry<ImplicitSwappedPojo,ImplicitSwappedPojo[][][]> e = x.entrySet().iterator().next(); + assertTrue(e.getKey().wasUnswapped); + assertTrue(e.getValue()[0][0][0].wasUnswapped); + } + + // Enums + + @Test + public void df01_returnEnum() { + TestEnum x = proxy.returnEnum(); + assertObjectEquals("'TWO'", x); + } + + @Test + public void df02_returnEnum3d() { + TestEnum[][][] x = proxy.returnEnum3d(); + assertObjectEquals("[[['TWO',null],null],null]", x); + assertClass(TestEnum.class, x[0][0][0]); + } + + @Test + public void df03_returnEnumList() { + List<TestEnum> x = proxy.returnEnumList(); + assertObjectEquals("['TWO',null]", x); + assertClass(TestEnum.class, x.get(0)); + } + + @Test + public void df04_returnEnum3dList() { + List<List<List<TestEnum>>> x = proxy.returnEnum3dList(); + assertObjectEquals("[[['TWO',null],null,null]]", x); + assertClass(TestEnum.class, x.get(0).get(0).get(0)); + } + + @Test + public void df05_returnEnum1d3dList() { + List<TestEnum[][][]> x = proxy.returnEnum1d3dList(); + assertObjectEquals("[[[['TWO',null],null],null],null]", x); + assertClass(TestEnum[][][].class, x.get(0)); + } + + @Test + public void df06_returnEnumMap() { + Map<TestEnum,TestEnum> x = proxy.returnEnumMap(); + assertObjectEquals("{ONE:'TWO'}", x); + Map.Entry<TestEnum,TestEnum> e = x.entrySet().iterator().next(); + assertClass(TestEnum.class, e.getKey()); + assertClass(TestEnum.class, e.getValue()); + } + + @Test + public void df07_returnEnum3dArrayMap() { + Map<TestEnum,TestEnum[][][]> x = proxy.returnEnum3dArrayMap(); + assertObjectEquals("{ONE:[[['TWO',null],null],null]}", x); + Map.Entry<TestEnum,TestEnum[][][]> e = x.entrySet().iterator().next(); + assertClass(TestEnum.class, e.getKey()); + assertClass(TestEnum[][][].class, e.getValue()); + } + + @Test + public void df08_returnEnum1d3dListMap() { + Map<TestEnum,List<TestEnum[][][]>> x = proxy.returnEnum1d3dListMap(); + assertObjectEquals("{ONE:[[[['TWO',null],null],null],null]}", x); + assertClass(TestEnum[][][].class, x.get(TestEnum.ONE).get(0)); + } + + //-------------------------------------------------------------------------------- + // Test Body + //-------------------------------------------------------------------------------- + + // Various primitives + + @Test + public void ea01_setInt() { + proxy.setInt(1); + } + + @Test + public void ea02_setWrongInt() { + try { + proxy.setInt(2); + fail("Exception expected"); + } catch (AssertionError e) { // AssertionError thrown on server side. + assertEquals("expected:<1> but was:<2>", e.getMessage()); + } + } + + @Test + public void ea03_setInteger() { + proxy.setInteger(1); + } + + @Test + public void ea04_setBoolean() { + proxy.setBoolean(true); + } + + @Test + public void ea05_setFloat() { + proxy.setFloat(1f); + } + + @Test + public void ea06_setFloatObject() { + proxy.setFloatObject(1f); + } + + @Test + public void ea07_setString() { + proxy.setString("foo"); + } + + @Test + public void ea08_setNullString() { + proxy.setNullString(null); + } + + @Test + public void ea09_setNullStringBad() { + try { + proxy.setNullString("foo"); + fail("Exception expected"); + } catch (AssertionError e) { // AssertionError thrown on server side. + assertEquals("expected null, but was:<foo>", e.getLocalizedMessage()); + } + } + + @Test + public void ea10_setInt3dArray() { + proxy.setInt3dArray(new int[][][]{{{1,2},null},null}); + } + + @Test + public void ea11_setInteger3dArray() { + proxy.setInteger3dArray(new Integer[][][]{{{1,null},null},null}); + } + + @Test + public void ea12_setString3dArray() { + proxy.setString3dArray(new String[][][]{{{"foo",null},null},null}); + } + + @Test + public void ea13_setIntegerList() { + proxy.setIntegerList(new AList<Integer>().append(1).append(null)); + } + + @Test + public void ea14_setInteger3dList() { + proxy.setInteger3dList( + new AList<List<List<Integer>>>() + .append( + new AList<List<Integer>>() + .append(new AList<Integer>().append(1).append(null)) + .append(null) + ) + .append(null) + ); + } + + @Test + public void ea15_setInteger1d3dList() { + proxy.setInteger1d3dList( + new AList<Integer[][][]>().append(new Integer[][][]{{{1,null},null},null}).append(null) + ); + } + + @Test + public void ea16_setInt1d3dList() { + proxy.setInt1d3dList( + new AList<int[][][]>().append(new int[][][]{{{1,2},null},null}).append(null) + ); + } + + @Test + public void ea17_setStringList() { + proxy.setStringList(Arrays.asList("foo","bar",null)); + } + + // Beans + @Test + public void eb01_setBean() { + proxy.setBean(new ABean().init()); + } + + @Test + public void eb02_setBean3dArray() { + proxy.setBean3dArray(new ABean[][][]{{{new ABean().init(),null},null},null}); + } + + @Test + public void eb03_setBeanList() { + proxy.setBeanList(Arrays.asList(new ABean().init())); + } + + @Test + public void eb04_setBean1d3dList() { + proxy.setBean1d3dList(new AList<ABean[][][]>().append(new ABean[][][]{{{new ABean().init(),null},null},null}).append(null)); + } + + @Test + public void eb05_setBeanMap() { + proxy.setBeanMap(new AMap<String,ABean>().append("foo",new ABean().init())); + } + + @Test + public void eb06_setBeanListMap() { + proxy.setBeanListMap(new AMap<String,List<ABean>>().append("foo",Arrays.asList(new ABean().init()))); + } + + @Test + public void eb07_setBean1d3dListMap() { + proxy.setBean1d3dListMap(new AMap<String,List<ABean[][][]>>().append("foo",new AList<ABean[][][]>().append(new ABean[][][]{{{new ABean().init(),null},null},null}).append(null))); + } + + @Test + public void eb08_setBeanListMapIntegerKeys() { + proxy.setBeanListMapIntegerKeys(new AMap<Integer,List<ABean>>().append(1,Arrays.asList(new ABean().init()))); + } + + // Typed beans + + @Test + public void ec01_setTypedBean() { + proxy.setTypedBean(new TypedBeanImpl().init()); + } + + @Test + public void ec02_setTypedBean3dArray() { + proxy.setTypedBean3dArray(new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}); + } + + @Test + public void ec03_setTypedBeanList() { + proxy.setTypedBeanList(Arrays.asList((TypedBean)new TypedBeanImpl().init())); + } + + @Test + public void ec04_setTypedBean1d3dList() { + proxy.setTypedBean1d3dList(new AList<TypedBean[][][]>().append(new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}).append(null)); + } + + @Test + public void ec05_setTypedBeanMap() { + proxy.setTypedBeanMap(new AMap<String,TypedBean>().append("foo",new TypedBeanImpl().init())); + } + + @Test + public void ec06_setTypedBeanListMap() { + proxy.setTypedBeanListMap(new AMap<String,List<TypedBean>>().append("foo",Arrays.asList((TypedBean)new TypedBeanImpl().init()))); + } + + @Test + public void ec07_setTypedBean1d3dListMap() { + proxy.setTypedBean1d3dListMap(new AMap<String,List<TypedBean[][][]>>().append("foo",new AList<TypedBean[][][]>().append(new TypedBean[][][]{{{new TypedBeanImpl().init(),null},null},null}).append(null))); + } + + @Test + public void ec08_setTypedBeanListMapIntegerKeys() { + proxy.setTypedBeanListMapIntegerKeys(new AMap<Integer,List<TypedBean>>().append(1,Arrays.asList((TypedBean)new TypedBeanImpl().init()))); + } + + // Swapped POJOs + + @Test + public void ed01_setSwappedPojo() { + proxy.setSwappedPojo(new SwappedPojo()); + } + + @Test + public void ed02_setSwappedPojo3dArray() { + proxy.setSwappedPojo3dArray(new SwappedPojo[][][]{{{new SwappedPojo(),null},null},null}); + } + + @Test + public void ed03_setSwappedPojoMap() { + proxy.setSwappedPojoMap(new AMap<SwappedPojo,SwappedPojo>().append(new SwappedPojo(), new SwappedPojo())); + } + + @Test + public void ed04_setSwappedPojo3dMap() { + proxy.setSwappedPojo3dMap(new AMap<SwappedPojo,SwappedPojo[][][]>().append(new SwappedPojo(), new SwappedPojo[][][]{{{new SwappedPojo(),null},null},null})); + } + + // Implicit swapped POJOs + @Test + public void ee01_setImplicitSwappedPojo() { + proxy.setImplicitSwappedPojo(new ImplicitSwappedPojo()); + } + + @Test + public void ee02_setImplicitSwappedPojo3dArray() { + proxy.setImplicitSwappedPojo3dArray(new ImplicitSwappedPojo[][][]{{{new ImplicitSwappedPojo(),null},null},null}); + } + + @Test + public void ee03_setImplicitSwappedPojoMap() { + proxy.setImplicitSwappedPojoMap(new AMap<ImplicitSwappedPojo,ImplicitSwappedPojo>().append(new ImplicitSwappedPojo(), new ImplicitSwappedPojo())); + } + + @Test + public void ee04_setImplicitSwappedPojo3dMap() { + proxy.setImplicitSwappedPojo3dMap(new AMap<ImplicitSwappedPojo,ImplicitSwappedPojo[][][]>().append(new ImplicitSwappedPojo(), new ImplicitSwappedPojo[][][]{{{new ImplicitSwappedPojo(),null},null},null})); + } + + // Enums + + @Test + public void ef01_setEnum() { + proxy.setEnum(TestEnum.TWO); + } + + @Test + public void ef02_setEnum3d() { + proxy.setEnum3d(new TestEnum[][][]{{{TestEnum.TWO,null},null},null}); + } + + @Test + public void ef03_setEnumList() { + proxy.setEnumList(new AList<TestEnum>().append(TestEnum.TWO).append(null)); + } + + @Test + public void ef04_setEnum3dList() { + proxy.setEnum3dList( + new AList<List<List<TestEnum>>>() + .append( + new AList<List<TestEnum>>() + .append( + new AList<TestEnum>().append(TestEnum.TWO).append(null) + ) + .append(null) + .append(null) + ) + ); + } + + @Test + public void ef05_setEnum1d3dList() { + proxy.setEnum1d3dList(new AList<TestEnum[][][]>().append(new TestEnum[][][]{{{TestEnum.TWO,null},null},null}).append(null)); + } + + @Test + public void ef06_setEnumMap() { + proxy.setEnumMap(new AMap<TestEnum,TestEnum>().append(TestEnum.ONE,TestEnum.TWO)); + } + + @Test + public void ef07_setEnum3dArrayMap() { + proxy.setEnum3dArrayMap(new AMap<TestEnum,TestEnum[][][]>().append(TestEnum.ONE, new TestEnum[][][]{{{TestEnum.TWO,null},null},null})); + } + + @Test + public void ef08_setEnum1d3dListMap() { + proxy.setEnum1d3dListMap(new AMap<TestEnum,List<TestEnum[][][]>>().append(TestEnum.ONE, new AList<TestEnum[][][]>().append(new TestEnum[][][]{{{TestEnum.TWO,null},null},null}).append(null))); + } + + + //-------------------------------------------------------------------------------- + // Proxy class + //-------------------------------------------------------------------------------- + + @Remoteable(path="/testThirdPartyProxy") + public static interface ThirdPartyProxy { + + //-------------------------------------------------------------------------------- + // Header tests + //-------------------------------------------------------------------------------- + + @RemoteMethod(httpMethod="GET", path="/primitiveHeaders") + String primitiveHeaders( + @Header("h1") String h1, + @Header("h1n") String h1n, + @Header("h2") int h2, + @Header("h3") Integer h3, + @Header("h3n") Integer h3n, + @Header("h4") Boolean h4, + @Header("h5") float h5, + @Header("h6") Float h6 + ); + + @RemoteMethod(httpMethod="GET", path="/primitiveCollectionHeaders") + String primitiveCollectionHeaders( + @Header("h1") int[][][] h1, + @Header("h2") Integer[][][] h2, + @Header("h3") String[][][] h3, + @Header("h4") List<Integer> h4, + @Header("h5") List<List<List<Integer>>> h5, + @Header("h6") List<Integer[][][]> h6, + @Header("h7") List<int[][][]> h7, + @Header("h8") List<String> h8 + ); + + @RemoteMethod(httpMethod="GET", path="/beanHeaders") + String beanHeaders( + @Header("h1") ABean h1, + @Header("h1n") ABean h1n, + @Header("h2") ABean[][][] h2, + @Header("h3") List<ABean> h3, + @Header("h4") List<ABean[][][]> h4, + @Header("h5") Map<String,ABean> h5, + @Header("h6") Map<String,List<ABean>> h6, + @Header("h7") Map<String,List<ABean[][][]>> h7, + @Header("h8") Map<Integer,List<ABean>> h8 + ); + + @RemoteMethod(httpMethod="GET", path="/typedBeanHeaders") + String typedBeanHeaders( + @Header("h1") TypedBean h1, + @Header("h1n") TypedBean h1n, + @Header("h2") TypedBean[][][] h2, + @Header("h3") List<TypedBean> h3, + @Header("h4") List<TypedBean[][][]> h4, + @Header("h5") Map<String,TypedBean> h5, + @Header("h6") Map<String,List<TypedBean>> h6, + @Header("h7") Map<String,List<TypedBean[][][]>> h7, + @Header("h8") Map<Integer,List<TypedBean>> h8 + ); + + @RemoteMethod(httpMethod="GET", path="/swappedPojoHeaders") + String swappedPojoHeaders( + @Header("h1") SwappedPojo h1, + @Header("h2") SwappedPojo[][][] h2, + @Header("h3") Map<SwappedPojo,SwappedPojo> h3, + @Header("h4") Map<SwappedPojo,SwappedPojo[][][]> h4 + ); + + @RemoteMethod(httpMethod="GET", path="/implicitSwappedPojoHeaders") + String implicitSwappedPojoHeaders( + @Header("h1") ImplicitSwappedPojo h1, + @Header("h2") ImplicitSwappedPojo[][][] h2, + @Header("h3") Map<ImplicitSwappedPojo,ImplicitSwappedPojo> h3, + @Header("h4") Map<ImplicitSwappedPojo,ImplicitSwappedPojo[][][]> h4 + ); + + @RemoteMethod(httpMethod="GET", path="/enumHeaders") + String enumHeaders( + @Header("h1") TestEnum h1, + @Header("h1n") TestEnum h1n, + @Header("h2") TestEnum[][][] h2, + @Header("h3") List<TestEnum> h3, + @Header("h4") List<List<List<TestEnum>>> h4, + @Header("h5") List<TestEnum[][][]> h5, + @Header("h6") Map<TestEnum,TestEnum> h6, + @Header("h7") Map<TestEnum,TestEnum[][][]> h7, + @Header("h8") Map<TestEnum,List<TestEnum[][][]>> h8 + ); + + //-------------------------------------------------------------------------------- + // Query tests + //-------------------------------------------------------------------------------- + + @RemoteMethod(httpMethod="GET", path="/primitiveQueries") + String primitiveQueries( + @Query("h1") String h1, + @Query("h1n") String h1n, + @Query("h2") int h2, + @Query("h3") Integer h3, + @Query("h3n") Integer h3n, + @Query("h4") Boolean h4, + @Query("h5") float h5, + @Query("h6") Float h6 + ); + + @RemoteMethod(httpMethod="GET", path="/primitiveCollectionQueries") + String primitiveCollectionQueries( + @Query("h1") int[][][] h1, + @Query("h2") Integer[][][] h2, + @Query("h3") String[][][] h3, + @Query("h4") List<Integer> h4, + @Query("h5") List<List<List<Integer>>> h5, + @Query("h6") List<Integer[][][]> h6, + @Query("h7") List<int[][][]> h7, + @Query("h8") List<String> h8 + ); + + @RemoteMethod(httpMethod="GET", path="/beanQueries") + String beanQueries( + @Query("h1") ABean h1, + @Query("h1n") ABean h1n, + @Query("h2") ABean[][][] h2, + @Query("h3") List<ABean> h3, + @Query("h4") List<ABean[][][]> h4, + @Query("h5") Map<String,ABean> h5, + @Query("h6") Map<String,List<ABean>> h6, + @Query("h7") Map<String,List<ABean[][][]>> h7, + @Query("h8") Map<Integer,List<ABean>> h8 + ); + + @RemoteMethod(httpMethod="GET", path="/typedBeanQueries") + String typedBeanQueries( + @Query("h1") TypedBean h1, + @Query("h1n") TypedBean h1n, + @Query("h2") TypedBean[][][] h2, + @Query("h3") List<TypedBean> h3, + @Query("h4") List<TypedBean[][][]> h4, + @Query("h5") Map<String,TypedBean> h5, + @Query("h6") Map<String,List<TypedBean>> h6, + @Query("h7") Map<String,List<TypedBean[][][]>> h7, + @Query("h8") Map<Integer,List<TypedBean>> h8 + ); + + @RemoteMethod(httpMethod="GET", path="/swappedPojoQueries") + String swappedPojoQueries( + @Query("h1") SwappedPojo h1, + @Query("h2") SwappedPojo[][][] h2, + @Query("h3") Map<SwappedPojo,SwappedPojo> h3, + @Query("h4") Map<SwappedPojo,SwappedPojo[][][]> h4 + ); + + @RemoteMethod(httpMethod="GET", path="/implicitSwappedPojoQueries") + String implicitSwappedPojoQueries( + @Query("h1") ImplicitSwappedPojo h1, + @Query("h2") ImplicitSwappedPojo[][][] h2, + @Query("h3") Map<ImplicitSwappedPojo,ImplicitSwappedPojo> h3, + @Query("h4") Map<ImplicitSwappedPojo,ImplicitSwappedPojo[][][]> h4 + ); + + @RemoteMethod(httpMethod="GET", path="/enumQueries") + String enumQueries( + @Query("h1") TestEnum h1, + @Query("h1n") TestEnum h1n, + @Query("h2") TestEnum[][][] h2, + @Query("h3") List<TestEnum> h3, + @Query("h4") List<List<List<TestEnum>>> h4, + @Query("h5") List<TestEnum[][][]> h5, + @Query("h6") Map<TestEnum,TestEnum> h6, + @Query("h7") Map<TestEnum,TestEnum[][][]> h7, + @Query("h8") Map<TestEnum,List<TestEnum[][][]>> h8 + ); + + //-------------------------------------------------------------------------------- + // FormData tests + //-------------------------------------------------------------------------------- + + @RemoteMethod(httpMethod="POST", path="/primitiveFormData") + String primitiveFormData( + @FormData("h1") String h1, + @FormData("h1n") String h1n, + @FormData("h2") int h2, + @FormData("h3") Integer h3, + @FormData("h3n") Integer h3n, + @FormData("h4") Boolean h4, + @FormData("h5") float h5, + @FormData("h6") Float h6 + ); + + @RemoteMethod(httpMethod="POST", path="/primitiveCollectionFormData") + String primitiveCollectionFormData( + @FormData("h1") int[][][] h1, + @FormData("h2") Integer[][][] h2, + @FormData("h3") String[][][] h3, + @FormData("h4") List<Integer> h4, + @FormData("h5") List<List<List<Integer>>> h5, + @FormData("h6") List<Integer[][][]> h6, + @FormData("h7") List<int[][][]> h7, + @FormData("h8") List<String> h8 + ); + + @RemoteMethod(httpMethod="POST", path="/beanFormData") + String beanFormData( + @FormData("h1") ABean h1, + @FormData("h1n") ABean h1n, + @FormData("h2") ABean[][][] h2, + @FormData("h3") List<ABean> h3, + @FormData("h4") List<ABean[][][]> h4, + @FormData("h5") Map<String,ABean> h5, + @FormData("h6") Map<String,List<ABean>> h6, + @FormData("h7") Map<String,List<ABean[][][]>> h7, + @FormData("h8") Map<Integer,List<ABean>> h8 + ); + + @RemoteMethod(httpMethod="POST", path="/typedBeanFormData") + String typedBeanFormData( + @FormData("h1") TypedBean h1, + @FormData("h1n") TypedBean h1n, + @FormData("h2") TypedBean[][][] h2, + @FormData("h3") List<TypedBean> h3, + @FormData("h4") List<TypedBean[][][]> h4, + @FormData("h5") Map<String,TypedBean> h5, + @FormData("h6") Map<String,List<TypedBean>> h6, + @FormData("h7") Map<String,List<TypedBean[][][]>> h7, + @FormData("h8") Map<Integer,List<TypedBean>> h8 + ); + + @RemoteMethod(httpMethod="POST", path="/swappedPojoFormData") + String swappedPojoFormData( + @FormData("h1") SwappedPojo h1, + @FormData("h2") SwappedPojo[][][] h2, + @FormData("h3") Map<SwappedPojo,SwappedPojo> h3, + @FormData("h4") Map<SwappedPojo,SwappedPojo[][][]> h4 + ); + + @RemoteMethod(httpMethod="POST", path="/implicitSwappedPojoFormData") + String implicitSwappedPojoFormData( + @FormData("h1") ImplicitSwappedPojo h1, + @FormData("h2") ImplicitSwappedPojo[][][] h2, + @FormData("h3") Map<ImplicitSwappedPojo,ImplicitSwappedPojo> h3, + @FormData("h4") Map<ImplicitSwappedPojo,ImplicitSwappedPojo[][][]> h4 + ); + + @RemoteMethod(httpMethod="POST", path="/enumFormData") + String enumFormData( + @FormData("h1") TestEnum h1, + @FormData("h1n") TestEnum h1n, + @FormData("h2") TestEnum[][][] h2, + @FormData("h3") List<TestEnum> h3, + @FormData("h4") List<List<List<TestEnum>>> h4, + @FormData("h5") List<TestEnum[][][]> h5, + @FormData("h6") Map<TestEnum,TestEnum> h6, + @FormData("h7") Map<TestEnum,TestEnum[][][]> h7, + @FormData("h8") Map<TestEnum,List<TestEnum[][][]>> h8 + ); + + //-------------------------------------------------------------------------------- + // Test return types. + //-------------------------------------------------------------------------------- + + // Various primitives + + @RemoteMethod(httpMethod="GET", path="/returnVoid") + void returnVoid(); + + @RemoteMethod(httpMethod="GET", path="/returnInt") + int returnInt(); + + @RemoteMethod(httpMethod="GET", path="/returnInteger") + Integer returnInteger(); + + @RemoteMethod(httpMethod="GET", path="/returnBoolean") + boolean returnBoolean(); + + @RemoteMethod(httpMethod="GET", path="/returnFloat") + float returnFloat(); + + @RemoteMethod(httpMethod="GET", path="/returnFloatObject") + Float returnFloatObject(); + + @RemoteMethod(httpMethod="GET", path="/returnString") + String returnString(); + + @RemoteMethod(httpMethod="GET", path="/returnNullString") + String returnNullString(); + + @RemoteMethod(httpMethod="GET", path="/returnInt3dArray") + int[][][] returnInt3dArray(); + + @RemoteMethod(httpMethod="GET", path="/returnInteger3dArray") + Integer[][][] returnInteger3dArray(); + + @RemoteMethod(httpMethod="GET", path="/returnString3dArray") + String[][][] returnString3dArray(); + + @RemoteMethod(httpMethod="GET", path="/returnIntegerList") + List<Integer> returnIntegerList(); + + @RemoteMethod(httpMethod="GET", path="/returnInteger3dList") + List<List<List<Integer>>> returnInteger3dList(); + + @RemoteMethod(httpMethod="GET", path="/returnInteger1d3dList") + List<Integer[][][]> returnInteger1d3dList(); + + @RemoteMethod(httpMethod="GET", path="/returnInt1d3dList") + List<int[][][]> returnInt1d3dList(); + + @RemoteMethod(httpMethod="GET", path="/returnStringList") + List<String> returnStringList(); + + // Beans + + @RemoteMethod(httpMethod="GET", path="/returnBean") + ABean returnBean(); + + @RemoteMethod(httpMethod="GET", path="/returnBean3dArray") + ABean[][][] returnBean3dArray(); + + @RemoteMethod(httpMethod="GET", path="/returnBeanList") + List<ABean> returnBeanList(); + + @RemoteMethod(httpMethod="GET", path="/returnBean1d3dList") + List<ABean[][][]> returnBean1d3dList(); + + @RemoteMethod(httpMethod="GET", path="/returnBeanMap") + Map<String,ABean> returnBeanMap(); + + @RemoteMethod(httpMethod="GET", path="/returnBeanListMap") + Map<String,List<ABean>> returnBeanListMap(); + + @RemoteMethod(httpMethod="GET", path="/returnBean1d3dListMap") + Map<String,List<ABean[][][]>> returnBean1d3dListMap(); + + @RemoteMethod(httpMethod="GET", path="/returnBeanListMapIntegerKeys") + Map<Integer,List<ABean>> returnBeanListMapIntegerKeys(); + + // Typed beans + + @RemoteMethod(httpMethod="GET", path="/returnTypedBean") + TypedBean returnTypedBean(); + + @RemoteMethod(httpMethod="GET", path="/returnTypedBean3dArray") + TypedBean[][][] returnTypedBean3dArray(); + + @RemoteMethod(httpMethod="GET", path="/returnTypedBeanList") + List<TypedBean> returnTypedBeanList(); + + @RemoteMethod(httpMethod="GET", path="/returnTypedBean1d3dList") + List<TypedBean[][][]> returnTypedBean1d3dList(); + + @RemoteMethod(httpMethod="GET", path="/returnTypedBeanMap") + Map<String,TypedBean> returnTypedBeanMap(); + + @RemoteMethod(httpMethod="GET", path="/returnTypedBeanListMap") + Map<String,List<TypedBean>> returnTypedBeanListMap(); + + @RemoteMethod(httpMethod="GET", path="/returnTypedBean1d3dListMap") + Map<String,List<TypedBean[][][]>> returnTypedBean1d3dListMap(); + + @RemoteMethod(httpMethod="GET", path="/returnTypedBeanListMapIntegerKeys") + Map<Integer,List<TypedBean>> returnTypedBeanListMapIntegerKeys(); + + // Swapped POJOs + + @RemoteMethod(httpMethod="GET", path="/returnSwappedPojo") + SwappedPojo returnSwappedPojo(); + + @RemoteMethod(httpMethod="GET", path="/returnSwappedPojo3dArray") + SwappedPojo[][][] returnSwappedPojo3dArray(); + + @RemoteMethod(httpMethod="GET", path="/returnSwappedPojoMap") + Map<SwappedPojo,SwappedPojo> returnSwappedPojoMap(); + + @RemoteMethod(httpMethod="GET", path="/returnSwappedPojo3dMap") + Map<SwappedPojo,SwappedPojo[][][]> returnSwappedPojo3dMap(); + + // Implicit swapped POJOs + + @RemoteMethod(httpMethod="GET", path="/returnImplicitSwappedPojo") + ImplicitSwappedPojo returnImplicitSwappedPojo(); + + @RemoteMethod(httpMethod="GET", path="/returnImplicitSwappedPojo3dArray") + ImplicitSwappedPojo[][][] returnImplicitSwappedPojo3dArray(); + + @RemoteMethod(httpMethod="GET", path="/returnImplicitSwappedPojoMap") + Map<ImplicitSwappedPojo,ImplicitSwappedPojo> returnImplicitSwappedPojoMap(); + + @RemoteMethod(httpMethod="GET", path="/returnImplicitSwappedPojo3dMap") + Map<ImplicitSwappedPojo,ImplicitSwappedPojo[][][]> returnImplicitSwappedPojo3dMap(); + + // Enums + + @RemoteMethod(httpMethod="GET", path="/returnEnum") + TestEnum returnEnum(); + + @RemoteMethod(httpMethod="GET", path="/returnEnum3d") + TestEnum[][][] returnEnum3d(); + + @RemoteMethod(httpMethod="GET", path="/returnEnumList") + List<TestEnum> returnEnumList(); + + @RemoteMethod(httpMethod="GET", path="/returnEnum3dList") + List<List<List<TestEnum>>> returnEnum3dList(); + + @RemoteMethod(httpMethod="GET", path="/returnEnum1d3dList") + List<TestEnum[][][]> returnEnum1d3dList(); + + @RemoteMethod(httpMethod="GET", path="/returnEnumMap") + Map<TestEnum,TestEnum> returnEnumMap(); + + @RemoteMethod(httpMethod="GET", path="/returnEnum3dArrayMap") + Map<TestEnum,TestEnum[][][]> returnEnum3dArrayMap(); + + @RemoteMethod(httpMethod="GET", path="/returnEnum1d3dListMap") + Map<TestEnum,List<TestEnum[][][]>> returnEnum1d3dListMap(); + + //-------------------------------------------------------------------------------- + // Test parameters + //-------------------------------------------------------------------------------- + + // Various primitives + + @RemoteMethod(httpMethod="POST", path="/setInt") + void setInt(@Body int x); + + @RemoteMethod(httpMethod="POST", path="/setInteger") + void setInteger(@Body Integer x); + + @RemoteMethod(httpMethod="POST", path="/setBoolean") + void setBoolean(@Body boolean x); + + @RemoteMethod(httpMethod="POST", path="/setFloat") + void setFloat(@Body float x); + + @RemoteMethod(httpMethod="POST", path="/setFloatObject") + void setFloatObject(@Body Float x); + + @RemoteMethod(httpMethod="POST", path="/setString") + void setString(@Body String x); + + @RemoteMethod(httpMethod="POST", path="/setNullString") + void setNullString(@Body String x); + + @RemoteMethod(httpMethod="POST", path="/setInt3dArray") + void setInt3dArray(@Body int[][][] x); + + @RemoteMethod(httpMethod="POST", path="/setInteger3dArray") + void setInteger3dArray(@Body Integer[][][] x); + + @RemoteMethod(httpMethod="POST", path="/setString3dArray") + void setString3dArray(@Body String[][][] x); + + @RemoteMethod(httpMethod="POST", path="/setIntegerList") + void setIntegerList(@Body List<Integer> x); + + @RemoteMethod(httpMethod="POST", path="/setInteger3dList") + void setInteger3dList(@Body List<List<List<Integer>>> x); + + @RemoteMethod(httpMethod="POST", path="/setInteger1d3dList") + void setInteger1d3dList(@Body List<Integer[][][]> x); + + @RemoteMethod(httpMethod="POST", path="/setInt1d3dList") + void setInt1d3dList(@Body List<int[][][]> x); + + @RemoteMethod(httpMethod="POST", path="/setStringList") + void setStringList(@Body List<String> x); + + // Beans + + @RemoteMethod(httpMethod="POST", path="/setBean") + void setBean(@Body ABean x); + + @RemoteMethod(httpMethod="POST", path="/setBean3dArray") + void setBean3dArray(@Body ABean[][][] x); + + @RemoteMethod(httpMethod="POST", path="/setBeanList") + void setBeanList(@Body List<ABean> x); + + @RemoteMethod(httpMethod="POST", path="/setBean1d3dList") + void setBean1d3dList(@Body List<ABean[][][]> x); + + @RemoteMethod(httpMethod="POST", path="/setBeanMap") + void setBeanMap(@Body Map<String,ABean> x); + + @RemoteMethod(httpMethod="POST", path="/setBeanListMap") + void setBeanListMap(@Body Map<String,List<ABean>> x); + + @RemoteMethod(httpMethod="POST", path="/setBean1d3dListMap") + void setBean1d3dListMap(@Body Map<String,List<ABean[][][]>> x); + + @RemoteMethod(httpMethod="POST", path="/setBeanListMapIntegerKeys") + void setBeanListMapIntegerKeys(@Body Map<Integer,List<ABean>> x); + + // Typed beans + + @RemoteMethod(httpMethod="POST", path="/setTypedBean") + void setTypedBean(@Body TypedBean x); + + @RemoteMethod(httpMethod="POST", path="/setTypedBean3dArray") + void setTypedBean3dArray(@Body TypedBean[][][] x); + + @RemoteMethod(httpMethod="POST", path="/setTypedBeanList") + void setTypedBeanList(@Body List<TypedBean> x); + + @RemoteMethod(httpMethod="POST", path="/setTypedBean1d3dList") + void setTypedBean1d3dList(@Body List<TypedBean[][][]> x); + + @RemoteMethod(httpMethod="POST", path="/setTypedBeanMap") + void setTypedBeanMap(@Body Map<String,TypedBean> x); + + @RemoteMethod(httpMethod="POST", path="/setTypedBeanListMap") + void setTypedBeanListMap(@Body Map<String,List<TypedBean>> x); + + @RemoteMethod(httpMethod="POST", path="/setTypedBean1d3dListMap") + void setTypedBean1d3dListMap(@Body Map<String,List<TypedBean[][][]>> x); + + @RemoteMethod(httpMethod="POST", path="/setTypedBeanListMapIntegerKeys") + void setTypedBeanListMapIntegerKeys(@Body Map<Integer,List<TypedBean>> x); + + // Swapped POJOs + + @RemoteMethod(httpMethod="POST", path="/setSwappedPojo") + void setSwappedPojo(@Body SwappedPojo x); + + @RemoteMethod(httpMethod="POST", path="/setSwappedPojo3dArray") + void setSwappedPojo3dArray(@Body SwappedPojo[][][] x); + + @RemoteMethod(httpMethod="POST", path="/setSwappedPojoMap") + void setSwappedPojoMap(@Body Map<SwappedPojo,SwappedPojo> x); + + @RemoteMethod(httpMethod="POST", path="/setSwappedPojo3dMap") + void setSwappedPojo3dMap(@Body Map<SwappedPojo,SwappedPojo[][][]> x); + + // Implicit swapped POJOs + + @RemoteMethod(httpMethod="POST", path="/setImplicitSwappedPojo") + void setImplicitSwappedPojo(@Body ImplicitSwappedPojo x); + + @RemoteMethod(httpMethod="POST", path="/setImplicitSwappedPojo3dArray") + void setImplicitSwappedPojo3dArray(@Body ImplicitSwappedPojo[][][] x); + + @RemoteMethod(httpMethod="POST", path="/setImplicitSwappedPojoMap") + void setImplicitSwappedPojoMap(@Body Map<ImplicitSwappedPojo,ImplicitSwappedPojo> x); + + @RemoteMethod(httpMethod="POST", path="/setImplicitSwappedPojo3dMap") + void setImplicitSwappedPojo3dMap(@Body Map<ImplicitSwappedPojo,ImplicitSwappedPojo[][][]> x); + + // Enums + + @RemoteMethod(httpMethod="POST", path="/setEnum") + void setEnum(@Body TestEnum x); + + @RemoteMethod(httpMethod="POST", path="/setEnum3d") + void setEnum3d(@Body TestEnum[][][] x); + + @RemoteMethod(httpMethod="POST", path="/setEnumList") + void setEnumList(@Body List<TestEnum> x); + + @RemoteMethod(httpMethod="POST", path="/setEnum3dList") + void setEnum3dList(@Body List<List<List<TestEnum>>> x); + + @RemoteMethod(httpMethod="POST", path="/setEnum1d3dList") + void setEnum1d3dList(@Body List<TestEnum[][][]> x); + + @RemoteMethod(httpMethod="POST", path="/setEnumMap") + void setEnumMap(@Body Map<TestEnum,TestEnum> x); + + @RemoteMethod(httpMethod="POST", path="/setEnum3dArrayMap") + void setEnum3dArrayMap(@Body Map<TestEnum,TestEnum[][][]> x); + + @RemoteMethod(httpMethod="POST", path="/setEnum1d3dListMap") + void setEnum1d3dListMap(@Body Map<TestEnum,List<TestEnum[][][]>> x); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java ---------------------------------------------------------------------- diff --git a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java index ec817ff..985c115 100644 --- a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java +++ b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java @@ -34,6 +34,7 @@ import org.junit.runners.Suite.*; ContentTest.class, DefaultContentTypesTest.class, ErrorConditionsTest.class, + FormDataTest.class, GroupsTest.class, GzipTest.class, InheritanceTest.class, @@ -57,6 +58,7 @@ import org.junit.runners.Suite.*; RestUtilsTest.class, SerializersTest.class, StaticFilesTest.class, + ThirdPartyProxyTest.class, TransformsTest.class, UrisTest.class, UrlContentTest.class, http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest/src/main/java/org/apache/juneau/rest/Redirect.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/Redirect.java b/juneau-rest/src/main/java/org/apache/juneau/rest/Redirect.java index f08d679..973452a 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/Redirect.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/Redirect.java @@ -132,13 +132,13 @@ public final class Redirect { /** * Calculates the URL to redirect to. * - * @param s Use this serializer to encode arguments using the {@link UrlEncodingSerializer#serializeUrlPart(Object)} method. + * @param s Use this serializer to encode arguments using the {@link UrlEncodingSerializer#serializePart(Object,Boolean,Boolean)} method. * @return The URL to redirect to. */ public String toUrl(UrlEncodingSerializer s) { if (url != null && args != null && args.length > 0) { for (int i = 0; i < args.length; i++) - args[i] = s.serializeUrlPart(args[i]); + args[i] = s.serializePart(args[i], null, true); return MessageFormat.format(url, args); } return url; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest/src/main/java/org/apache/juneau/rest/RestCallHandler.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestCallHandler.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestCallHandler.java index 5d6a780..676e9ae 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestCallHandler.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestCallHandler.java @@ -14,6 +14,7 @@ package org.apache.juneau.rest; import static java.util.logging.Level.*; import static javax.servlet.http.HttpServletResponse.*; +import static org.apache.juneau.internal.StringUtils.*; import java.io.*; import java.util.*; @@ -114,7 +115,7 @@ public class RestCallHandler { final HttpServletRequest childRequest = new HttpServletRequestWrapper(r1) { @Override /* ServletRequest */ public String getPathInfo() { - return RestUtils.decode(pathInfoRemainder); + return urlDecode(pathInfoRemainder); } @Override /* ServletRequest */ public String getServletPath() { @@ -269,6 +270,13 @@ public class RestCallHandler { res.setStatus(status); res.setContentType("text/plain"); res.setHeader("Content-Encoding", "identity"); + + Throwable t = e.getRootCause(); + if (t != null) { + res.setHeader("Exception-Name", t.getClass().getName()); + res.setHeader("Exception-Message", t.getMessage()); + } + PrintWriter w = null; try { w = res.getWriter(); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java index 2e39b74..2875805 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java @@ -13,9 +13,11 @@ package org.apache.juneau.rest; import static javax.servlet.http.HttpServletResponse.*; +import static org.apache.juneau.internal.StringUtils.*; import java.io.*; import java.lang.reflect.*; +import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; @@ -412,6 +414,10 @@ public final class RestContext extends Context { if ("PROXY".equals(httpMethod)) { final ClassMeta<?> interfaceClass = beanContext.getClassMeta(method.getGenericReturnType()); + final Map<String,Method> remoteableMethods = interfaceClass.getRemoteableMethods(); + if (remoteableMethods.isEmpty()) + throw new RestException(SC_INTERNAL_SERVER_ERROR, "Method {0} returns an interface {1} that doesn't define any remoteable methods.", ClassUtils.getMethodSignature(method), interfaceClass.getReadableName()); + sm = new CallMethod(resource, method, this) { @Override @@ -424,31 +430,20 @@ public final class RestContext extends Context { final Object o = res.getOutput(); if ("GET".equals(req.getMethod())) { - res.setOutput(ClassUtils.getMethodInfo(interfaceClass.getProxyableMethods().values())); + res.setOutput(ClassUtils.getMethodInfo(remoteableMethods.values())); return SC_OK; } else if ("POST".equals(req.getMethod())) { if (pathInfo.indexOf('/') != -1) pathInfo = pathInfo.substring(pathInfo.lastIndexOf('/')+1); - pathInfo = RestUtils.decode(pathInfo); - java.lang.reflect.Method m = interfaceClass.getProxyableMethods().get(pathInfo); + pathInfo = urlDecode(pathInfo); + java.lang.reflect.Method m = remoteableMethods.get(pathInfo); if (m != null) { try { // Parse the args and invoke the method. Parser p = req.getParser(); Object input = p.isReaderParser() ? req.getReader() : req.getInputStream(); - Object output = null; - try { - output = m.invoke(o, p.parseArgs(input, m.getGenericParameterTypes())); - } catch (InvocationTargetException e) { - res.setHeader("Exception-Name", e.getCause().getClass().getName()); - res.setHeader("Exception-Message", e.getCause().getMessage()); - throw e; - } catch (Exception e) { - res.setHeader("Exception-Name", e.getClass().getName()); - res.setHeader("Exception-Message", e.getMessage()); - throw e; - } + Object output = m.invoke(o, p.parseArgs(input, m.getGenericParameterTypes())); res.setOutput(output); return SC_OK; } catch (Exception e) { @@ -595,7 +590,7 @@ public final class RestContext extends Context { defaultCharset = ps.getProperty(REST_defaultCharset, String.class, "utf-8"); paramFormat = ps.getProperty(REST_paramFormat, String.class, ""); - for (String m : StringUtils.split(ps.getProperty(REST_allowMethodParam, String.class, ""), ',')) + for (String m : split(ps.getProperty(REST_allowMethodParam, String.class, ""), ',')) if (m.equals("true")) // For backwards compatibility when this was a boolean field. allowMethodParams.add("*"); else @@ -659,7 +654,7 @@ public final class RestContext extends Context { for (Object o : sc.styleSheets) { if (o instanceof Pair) { Pair<Class<?>,String> p = (Pair<Class<?>,String>)o; - for (String path : StringUtils.split(vr.resolve(StringUtils.toString(p.second())), ',')) + for (String path : split(vr.resolve(StringUtils.toString(p.second())), ',')) if (path.startsWith("file://")) contents.add(new FileInputStream(path)); else @@ -782,15 +777,15 @@ public final class RestContext extends Context { */ public StreamResource resolveStaticFile(String pathInfo) throws IOException { if (! staticFilesCache.containsKey(pathInfo)) { - String p = RestUtils.decode(RestUtils.trimSlashes(pathInfo)); + String p = urlDecode(trimSlashes(pathInfo)); if (p.indexOf("..") != -1) throw new RestException(SC_NOT_FOUND, "Invalid path"); for (Map.Entry<String,String> e : staticFilesMap.entrySet()) { - String key = RestUtils.trimSlashes(e.getKey()); + String key = trimSlashes(e.getKey()); if (p.startsWith(key)) { String remainder = (p.equals(key) ? "" : p.substring(key.length())); if (remainder.isEmpty() || remainder.startsWith("/")) { - String p2 = RestUtils.trimSlashes(e.getValue()) + remainder; + String p2 = trimSlashes(e.getValue()) + remainder; InputStream is = getResource(p2, null); if (is != null) { try { @@ -1211,7 +1206,7 @@ public final class RestContext extends Context { * @return <jk>true</jk> if this resource allows the specified method to be overridden. */ protected boolean allowMethodParam(String m) { - return (! StringUtils.isEmpty(m) && (allowMethodParams.contains(m) || allowMethodParams.contains("*"))); + return (! isEmpty(m) && (allowMethodParams.contains(m) || allowMethodParams.contains("*"))); } /** @@ -1448,7 +1443,7 @@ public final class RestContext extends Context { * @return <jk>true</jk> if the specified path refers to a static file. */ protected boolean isStaticFile(String p) { - return StringUtils.pathStartsWith(p, staticFilesPrefixes); + return pathStartsWith(p, staticFilesPrefixes); } /** http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest/src/main/java/org/apache/juneau/rest/RestException.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestException.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestException.java index 299883a..c9a9a5c 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestException.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestException.java @@ -12,6 +12,7 @@ // *************************************************************************************************************************** package org.apache.juneau.rest; +import java.lang.reflect.*; import java.text.*; /** @@ -64,6 +65,24 @@ public class RestException extends RuntimeException { return this; } + /** + * Returns the root cause of this exception. + * The root cause is the first exception in the init-cause parent chain that's not one of the following: + * <ul> + * <li>{@link RestException} + * <li>{@link InvocationTargetException} + * </ul> + * @return The root cause of this exception, or <jk>null</jk> if no root cause was found. + */ + public Throwable getRootCause() { + Throwable t = this; + while(t != null) { + t = t.getCause(); + if (! (t instanceof RestException || t instanceof InvocationTargetException)) + return t; + } + return null; + } /** * Returns all error messages from all errors in this stack. http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java index 99f09d0..86d2db7 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestRequest.java @@ -15,6 +15,7 @@ package org.apache.juneau.rest; import static java.util.Collections.*; import static java.util.logging.Level.*; import static javax.servlet.http.HttpServletResponse.*; +import static org.apache.juneau.internal.StringUtils.*; import java.io.*; import java.lang.reflect.*; @@ -81,6 +82,7 @@ public final class RestRequest extends HttpServletRequestWrapper { private BeanSession beanSession; private VarResolverSession varSession; private final Map<String,String[]> queryParams; + private Map<String,String> formData; private final Map<String,String> defaultServletHeaders; private Map<String,String> defaultMethodHeaders, overriddenHeaders, overriddenQueryParams, overriddenFormDataParams, pathParameters; private boolean isPost; @@ -316,10 +318,11 @@ public final class RestRequest extends HttpServletRequestWrapper { * <br>Ignored if the main type is not a map or collection. * @param <T> The class type to convert the header value to. * @return The parameter value converted to the specified class type. + * @throws ParseException If the header could not be converted to the specified type. */ - public <T> T getHeader(String name, Type type, Type...args) { + public <T> T getHeader(String name, Type type, Type...args) throws ParseException { String h = getHeader(name); - return (T)beanSession.convertToType(null, h, beanSession.getClassMeta(type, args)); + return urlEncodingParser.parsePart(h, type, args); } /** @@ -801,7 +804,7 @@ public final class RestRequest extends HttpServletRequestWrapper { if (s != null) return s; - return super.getParameter(name); + return getFormParameterInner(name); } /** @@ -812,7 +815,7 @@ public final class RestRequest extends HttpServletRequestWrapper { * @return The parameter value, or the default value if <jk>null</jk> or empty. */ public String getFormDataParameter(String name, String def) { - String val = getParameter(name); + String val = getFormParameterInner(name); if (val == null || val.isEmpty()) return def; return val; @@ -953,9 +956,22 @@ public final class RestRequest extends HttpServletRequestWrapper { return getParameterMap().containsKey(name); } + /** + * Retrieves the URL-encoded from data from the request if the body has already been cached locally. + */ + private Map<String,String> getFormData() { + try { + if (formData == null) + formData = urlEncodingParser.parse(body, Map.class, String.class, String.class); + return formData; + } catch (ParseException e) { + throw new RestException(SC_INTERNAL_SERVER_ERROR, e); + } + } + /* Workhorse method */ <T> T getFormDataParameter(String name, T def, ClassMeta<T> cm) throws ParseException { - String val = getParameter(name); + String val = getFormParameterInner(name); if (val == null) return def; return parseParameter(val, cm); @@ -963,12 +979,16 @@ public final class RestRequest extends HttpServletRequestWrapper { /* Workhorse method */ <T> T getFormDataParameter(String name, ClassMeta<T> cm) throws ParseException { - String val = getParameter(name); + String val = getFormParameterInner(name); if (cm.isPrimitive() && (val == null || val.isEmpty())) return cm.getPrimitiveDefault(); return parseParameter(val, cm); } + private String getFormParameterInner(String name) { + return (body == null ? super.getParameter(name) : getFormData().get(name)); + } + /* Workhorse method */ @SuppressWarnings("rawtypes") <T> T getFormDataParameters(String name, ClassMeta<T> cm) throws ParseException { @@ -1101,7 +1121,7 @@ public final class RestRequest extends HttpServletRequestWrapper { Object attr = getPathParameter(name); T t = null; if (attr != null) - t = urlEncodingParser.parseParameter(attr.toString(), cm); + t = urlEncodingParser.parsePart(attr.toString(), cm); if (t == null && cm.isPrimitive()) return cm.getPrimitiveDefault(); return t; @@ -1392,9 +1412,9 @@ public final class RestRequest extends HttpServletRequestWrapper { public URL getURL(String path) throws MalformedURLException { if (path.startsWith("http://") || path.startsWith("https://")) return new URL(path); - if (StringUtils.startsWith(path, '/')) + if (startsWith(path, '/')) return new URL(getScheme(), getLocalName(), getLocalPort(), path); - return new URL(getScheme(), getLocalName(), getLocalPort(), getContextPath() + getServletPath() + (StringUtils.isEmpty(path) ? "" : ('/' + path))); + return new URL(getScheme(), getLocalName(), getLocalPort(), getContextPath() + getServletPath() + (isEmpty(path) ? "" : ('/' + path))); } /** @@ -1462,7 +1482,7 @@ public final class RestRequest extends HttpServletRequestWrapper { * @return The path remainder string. */ public String getPathRemainder() { - return RestUtils.decode(pathRemainder); + return urlDecode(pathRemainder); } /** @@ -1515,7 +1535,7 @@ public final class RestRequest extends HttpServletRequestWrapper { */ public String getRequestParentURI() { String uri = getRequestURI(); - while (StringUtils.endsWith(uri, '/')) + while (endsWith(uri, '/')) uri = uri.substring(0, uri.length()-1); int i = uri.lastIndexOf('/'); if (i <= 0) @@ -1529,7 +1549,7 @@ public final class RestRequest extends HttpServletRequestWrapper { * @return The trimmed request URI. */ public String getTrimmedRequestURI() { - return RestUtils.trimTrailingSlashes(getRequestURI()); + return trimTrailingSlashes(getRequestURI()); } /** @@ -1538,7 +1558,7 @@ public final class RestRequest extends HttpServletRequestWrapper { * @return The trimmed request URL. */ public StringBuffer getTrimmedRequestURL() { - return RestUtils.trimTrailingSlashes(getRequestURL()); + return trimTrailingSlashes(getRequestURL()); } /** @@ -1632,11 +1652,11 @@ public final class RestRequest extends HttpServletRequestWrapper { */ protected String getPageTitle() { String s = pageTitle; - if (StringUtils.isEmpty(s)) + if (isEmpty(s)) s = context.getMessages().findFirstString(getLocale(), javaMethod.getName() + ".pageTitle"); - if (StringUtils.isEmpty(s)) + if (isEmpty(s)) s = context.getMessages().findFirstString(getLocale(), "pageTitle"); - if (! StringUtils.isEmpty(s)) + if (! isEmpty(s)) return resolveVars(s); s = getServletTitle(); return s; @@ -1649,14 +1669,14 @@ public final class RestRequest extends HttpServletRequestWrapper { */ protected String getPageText() { String s = pageText; - if (StringUtils.isEmpty(s)) + if (isEmpty(s)) s = context.getMessages().findFirstString(getLocale(), javaMethod.getName() + ".pageText"); - if (StringUtils.isEmpty(s)) + if (isEmpty(s)) s = context.getMessages().findFirstString(getLocale(), "pageText"); - if (! StringUtils.isEmpty(s)) + if (! isEmpty(s)) return resolveVars(s); s = getMethodSummary(); - if (StringUtils.isEmpty(s)) + if (isEmpty(s)) s = getServletDescription(); return s; } @@ -1668,9 +1688,9 @@ public final class RestRequest extends HttpServletRequestWrapper { */ protected String getPageLinks() { String s = pageLinks; - if (StringUtils.isEmpty(s)) + if (isEmpty(s)) s = context.getMessages().findFirstString(getLocale(), javaMethod.getName() + ".pageLinks"); - if (StringUtils.isEmpty(s)) + if (isEmpty(s)) s = context.getMessages().findFirstString(getLocale(), "pageLinks"); return resolveVars(s); } @@ -1950,9 +1970,12 @@ public final class RestRequest extends HttpServletRequestWrapper { if (javaMethod == null) { sb.append("***init() not called yet!***\n"); } else if (method.equals("PUT") || method.equals("POST")) { - sb.append("---Body---\n"); try { - sb.append(getBodyAsString()).append("\n"); + body = IOUtils.readBytes(getInputStream(), 1024); + sb.append("---Body UTF-8---\n"); + sb.append(new String(body, "UTF-8")).append("\n"); + sb.append("---Body Hex---\n"); + sb.append(StringUtils.toHex(body)).append("\n"); } catch (Exception e1) { sb.append(e1.getLocalizedMessage()); context.getLogger().log(WARNING, e1, "Error occurred while trying to read debug input."); @@ -1967,21 +1990,7 @@ public final class RestRequest extends HttpServletRequestWrapper { //-------------------------------------------------------------------------------- private <T> T parseParameter(String val, ClassMeta<T> c) throws ParseException { - if (val == null) - return null; - - // Shortcut - If we're returning a string and the value doesn't start with "'" or is "null", then - // just return the string since it's a plain value. - // This allows us to bypass the creation of a UonParserSession object. - if (c.getInnerClass() == String.class && val.length() > 0) { - char x = val.charAt(0); - if (x != '\'' && x != 'n' && val.indexOf('~') == -1) - return (T)val; - if (x == 'n' && "null".equals(val)) - return null; - } - - return urlEncodingParser.parseParameter(val, c); + return urlEncodingParser.parsePart(val, c); } /* http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java index 2d50376..00ac554 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestResponse.java @@ -74,7 +74,8 @@ public final class RestResponse extends HttpServletResponseWrapper { try { String passThroughHeaders = req.getHeader("x-response-headers"); if (passThroughHeaders != null) { - ObjectMap m = context.getUrlEncodingParser().parseParameter(passThroughHeaders, ObjectMap.class); + UrlEncodingParser p = context.getUrlEncodingParser(); + ObjectMap m = p.parsePart(passThroughHeaders, p.getBeanContext().getClassMeta(ObjectMap.class)); for (Map.Entry<String,Object> e : m.entrySet()) setHeader(e.getKey(), e.getValue().toString()); } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest/src/main/java/org/apache/juneau/rest/RestServlet.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestServlet.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestServlet.java index d7288d3..d91a7f0 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestServlet.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestServlet.java @@ -147,9 +147,9 @@ public abstract class RestServlet extends HttpServlet { context.getCallHandler().service(r1, r2); } catch (RestException e) { - context.getCallHandler().handleError(r1, r2, e); + r2.sendError(SC_INTERNAL_SERVER_ERROR, e.getLocalizedMessage()); } catch (Throwable e) { - context.getCallHandler().handleError(r1, r2, new RestException(SC_INTERNAL_SERVER_ERROR, e)); + r2.sendError(SC_INTERNAL_SERVER_ERROR, e.getLocalizedMessage()); } } @@ -249,7 +249,8 @@ public abstract class RestServlet extends HttpServlet { @Override /* GenericServlet */ public void destroy() { - context.destroy(); + if (context != null) + context.destroy(); super.destroy(); } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest/src/main/java/org/apache/juneau/rest/RestUtils.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestUtils.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestUtils.java index 607f659..73a89a9 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestUtils.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestUtils.java @@ -12,13 +12,10 @@ // *************************************************************************************************************************** package org.apache.juneau.rest; -import java.io.*; -import java.net.*; import java.util.*; import javax.servlet.http.*; -import org.apache.juneau.internal.*; import org.apache.juneau.utils.*; /** @@ -76,94 +73,6 @@ public final class RestUtils { ; /** - * Trims <js>'/'</js> characters from both the start and end of the specified string. - * - * @param s The string to trim. - * @return A new trimmed string, or the same string if no trimming was necessary. - */ - public static String trimSlashes(String s) { - if (s == null) - return null; - while (StringUtils.endsWith(s, '/')) - s = s.substring(0, s.length()-1); - while (s.length() > 0 && s.charAt(0) == '/') - s = s.substring(1); - return s; - } - - /** - * Trims <js>'/'</js> characters from the end of the specified string. - * - * @param s The string to trim. - * @return A new trimmed string, or the same string if no trimming was necessary. - */ - public static String trimTrailingSlashes(String s) { - if (s == null) - return null; - while (StringUtils.endsWith(s, '/')) - s = s.substring(0, s.length()-1); - return s; - } - - /** - * Trims <js>'/'</js> characters from the end of the specified string. - * - * @param s The string to trim. - * @return The same string buffer. - */ - public static StringBuffer trimTrailingSlashes(StringBuffer s) { - if (s == null) - return null; - while (s.length() > 0 && s.charAt(s.length()-1) == '/') - s.setLength(s.length()-1); - return s; - } - - /** - * Decodes a <code>application/x-www-form-urlencoded</code> string using <code>UTF-8</code> encoding scheme. - * - * @param s The string to decode. - * @return The decoded string, or <jk>null</jk> if input is <jk>null</jk>. - */ - public static String decode(String s) { - if (s == null) - return s; - boolean needsDecode = false; - for (int i = 0; i < s.length() && ! needsDecode; i++) { - char c = s.charAt(i); - if (c == '+' || c == '%') - needsDecode = true; - } - if (needsDecode) - try { - return URLDecoder.decode(s, "UTF-8"); - } catch (UnsupportedEncodingException e) {/* Won't happen */} - return s; - } - - // Characters that do not need to be URL-encoded - private static final AsciiSet unencodedChars = new AsciiSet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()\\"); - - /** - * Encodes a <code>application/x-www-form-urlencoded</code> string using <code>UTF-8</code> encoding scheme. - * - * @param s The string to encode. - * @return The encoded string, or <jk>null</jk> if input is <jk>null</jk>. - */ - public static String encode(String s) { - if (s == null) - return null; - boolean needsEncode = false; - for (int i = 0; i < s.length() && ! needsEncode; i++) - needsEncode |= (! unencodedChars.contains(s.charAt(i))); - if (needsEncode) - try { - return URLEncoder.encode(s, "UTF-8"); - } catch (UnsupportedEncodingException e) {/* Won't happen */} - return s; - } - - /** * Identical to {@link HttpServletRequest#getPathInfo()} but doesn't decode encoded characters. * * @param req The HTTP request http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest/src/main/java/org/apache/juneau/rest/UrlPathPattern.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/UrlPathPattern.java b/juneau-rest/src/main/java/org/apache/juneau/rest/UrlPathPattern.java index ad6eb60..1d97933 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/UrlPathPattern.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/UrlPathPattern.java @@ -12,12 +12,11 @@ // *************************************************************************************************************************** package org.apache.juneau.rest; -import static org.apache.juneau.rest.RestUtils.*; +import static org.apache.juneau.internal.StringUtils.*; import java.util.*; import java.util.regex.*; -import org.apache.juneau.internal.*; import org.apache.juneau.rest.annotation.*; /** @@ -53,7 +52,7 @@ public final class UrlPathPattern implements Comparable<UrlPathPattern> { List<String> vars = new LinkedList<String>(); private Builder(String patternString) { - if (! StringUtils.startsWith(patternString, '/')) + if (! startsWith(patternString, '/')) patternString = '/' + patternString; if (patternString.equals("/*")) { isOnlyDotAll = true; @@ -105,7 +104,7 @@ public final class UrlPathPattern implements Comparable<UrlPathPattern> { if (isDotAll && i == len-1) v[i] = m.group(i+1).isEmpty() ? null : m.group(i+1).substring(1); else - v[i] = decode(m.group(i+1)); + v[i] = urlDecode(m.group(i+1)); } return v; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7139635d/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java index 1720066..fdaa469 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java @@ -17,9 +17,9 @@ import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.*; -import org.apache.juneau.annotation.*; import org.apache.juneau.encoders.*; import org.apache.juneau.parser.*; +import org.apache.juneau.remoteable.*; import org.apache.juneau.rest.*; import org.apache.juneau.serializer.*;
