Return-Path: Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: (qmail 48433 invoked from network); 8 Apr 2009 10:55:20 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 8 Apr 2009 10:55:20 -0000 Received: (qmail 89324 invoked by uid 500); 8 Apr 2009 10:55:19 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 89226 invoked by uid 500); 8 Apr 2009 10:55:19 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 89217 invoked by uid 99); 8 Apr 2009 10:55:19 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 08 Apr 2009 10:55:19 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 08 Apr 2009 10:55:16 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 74E9923889BB; Wed, 8 Apr 2009 10:54:55 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r763176 - in /cxf/trunk/rt/frontend/jaxrs/src: main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java test/java/org/apache/cxf/jaxrs/Customer.java test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java Date: Wed, 08 Apr 2009 10:54:55 -0000 To: commits@cxf.apache.org From: sergeyb@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090408105455.74E9923889BB@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: sergeyb Date: Wed Apr 8 10:54:54 2009 New Revision: 763176 URL: http://svn.apache.org/viewvc?rev=763176&view=rev Log: CXF-2153 : applying a patch on behalf of Craig Muchinsky Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/Customer.java cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java?rev=763176&r1=763175&r2=763176&view=diff ============================================================================== --- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java (original) +++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java Wed Apr 8 10:54:54 2009 @@ -31,7 +31,9 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -62,6 +64,7 @@ import org.apache.cxf.common.util.PrimitiveUtils; import org.apache.cxf.jaxrs.ext.MessageContext; import org.apache.cxf.jaxrs.ext.ParameterHandler; +import org.apache.cxf.jaxrs.impl.MetadataMap; import org.apache.cxf.jaxrs.impl.PathSegmentImpl; import org.apache.cxf.jaxrs.impl.tl.ThreadLocalContextResolver; import org.apache.cxf.jaxrs.impl.tl.ThreadLocalHttpHeaders; @@ -133,6 +136,23 @@ }); } + + @SuppressWarnings("unchecked") + public static Object extractFieldValue(final Field f, + final Object o) { + return AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + f.setAccessible(true); + try { + return f.get(o); + } catch (IllegalAccessException ex) { + reportServerError("FIELD_ACCESS_FAILURE", + f.getType().getName()); + } + return null; + } + }); + } public static Class getActualType(Type genericType) { @@ -168,6 +188,19 @@ reportServerError("METHOD_INJECTION_FAILURE", method.getName()); } } + + public static Object extractFromMethod(Object requestObject, + Method method) { + try { + Method methodToInvoke = checkProxy(method, requestObject); + return methodToInvoke.invoke(requestObject); + } catch (IllegalAccessException ex) { + reportServerError("METHOD_ACCESS_FAILURE", method.getName()); + } catch (Exception ex) { + reportServerError("METHOD_INJECTION_FAILURE", method.getName()); + } + return null; + } public static Object handleParameter(String value, Class pClass, @@ -275,90 +308,250 @@ reportServerError("CLASS_INSTANTIATION_FAILURE", paramType.getName()); } + Map> parsedValues = + new HashMap>(); for (Map.Entry> entry : values.entrySet()) { - boolean injected = false; - for (Method m : paramType.getMethods()) { - if (m.getName().equalsIgnoreCase("set" + entry.getKey()) - && m.getParameterTypes().length == 1) { - Object paramValue = handleParameter(entry.getValue().get(0), - m.getParameterTypes()[0], - pType, message); - if (paramValue != null) { - injectThroughMethod(bean, m, paramValue); - injected = true; - break; - } - } + String memberKey = entry.getKey(); + String beanKey = null; + + int idx = memberKey.indexOf('.'); + if (idx == -1) { + beanKey = "." + memberKey; + } else { + beanKey = memberKey.substring(0, idx); + memberKey = memberKey.substring(idx + 1); } - if (injected) { - continue; + + MultivaluedMap value = parsedValues.get(beanKey); + if (value == null) { + value = new MetadataMap(); + parsedValues.put(beanKey, value); } - for (Field f : paramType.getFields()) { - if (f.getName().equalsIgnoreCase(entry.getKey())) { - Object paramValue = handleParameter(entry.getValue().get(0), - f.getType(), pType, message); - if (paramValue != null) { - injectFieldValue(f, bean, paramValue); + value.put(memberKey, entry.getValue()); + } + + if (parsedValues.size() > 0) { + for (Map.Entry> entry : parsedValues.entrySet()) { + String memberKey = entry.getKey(); + + boolean isbean = !memberKey.startsWith("."); + if (!isbean) { + memberKey = memberKey.substring(1); + } + + Object setter = null; + Object getter = null; + for (Method m : paramType.getMethods()) { + if (m.getName().equalsIgnoreCase("set" + memberKey) + && m.getParameterTypes().length == 1) { + setter = m; + } else if (m.getName().equalsIgnoreCase("get" + memberKey) + && m.getReturnType() != Void.TYPE) { + getter = m; + } + if (setter != null && getter != null) { break; } } + if (setter == null) { + for (Field f : paramType.getFields()) { + if (f.getName().equalsIgnoreCase(memberKey)) { + setter = f; + getter = f; + break; + } + } + } + + if (setter != null && getter != null) { + Class type = null; + Type genericType = null; + Object paramValue = null; + if (setter instanceof Method) { + type = Method.class.cast(setter).getParameterTypes()[0]; + genericType = Method.class.cast(setter).getGenericParameterTypes()[0]; + paramValue = InjectionUtils.extractFromMethod(bean, (Method) getter); + } else { + type = Field.class.cast(setter).getType(); + genericType = Field.class.cast(setter).getGenericType(); + paramValue = InjectionUtils.extractFieldValue((Field) getter, bean); + } + + List> processedValuesList = + processValues(type, genericType, entry.getValue(), isbean); + + for (MultivaluedMap processedValues : processedValuesList) { + if (InjectionUtils.isSupportedCollectionOrArray(type)) { + Object appendValue = InjectionUtils.injectIntoCollectionOrArray(type, + genericType, processedValues, + isbean, true, + pType, message); + paramValue = InjectionUtils.mergeCollectionsOrArrays(paramValue, appendValue, + genericType); + } else if (isbean) { + paramValue = InjectionUtils.handleBean(type, processedValues, + pType, message); + } else { + paramValue = InjectionUtils.handleParameter( + processedValues.values().iterator().next().get(0), + type, + pType, message); + } + + if (paramValue != null) { + if (setter instanceof Method) { + InjectionUtils.injectThroughMethod(bean, (Method) setter, paramValue); + } else { + InjectionUtils.injectFieldValue((Field) setter, bean, paramValue); + } + } + } + } } } return bean; } - - @SuppressWarnings("unchecked") - public static Object injectIntoList(Type genericType, List values, - boolean decoded, ParameterType pathParam, Message message) { - Class realType = InjectionUtils.getActualType(genericType); - values = checkPathSegment(values, realType, pathParam); - List theValues = new ArrayList(); - for (String r : values) { - String value = decodeValue(r, decoded, pathParam); - - Object o = InjectionUtils.handleParameter(value, realType, pathParam, message); - if (o != null) { - theValues.add(o); + + private static List> processValues(Class type, Type genericType, + MultivaluedMap values, + boolean isbean) { + List> valuesList = + new ArrayList>(); + + if (isbean && InjectionUtils.isSupportedCollectionOrArray(type)) { + Class realType = InjectionUtils.getActualType(genericType); + for (Map.Entry> entry : values.entrySet()) { + String memberKey = entry.getKey(); + Class memberType = null; + + for (Method m : realType.getMethods()) { + if (m.getName().equalsIgnoreCase("set" + memberKey) + && m.getParameterTypes().length == 1) { + memberType = m.getParameterTypes()[0]; + break; + } + } + if (memberType == null) { + for (Field f : realType.getFields()) { + if (f.getName().equalsIgnoreCase(memberKey)) { + memberType = f.getType(); + break; + } + } + } + + // Strip values tied to collection/array fields from beans that are within + // collection/array themselves, the only way to support this would be to have + // an indexing syntax for nested beans, perhaps like this: + // a(0).b=1&a(0).b=2&a(1).b=3&a(1).b=4 + // For now though we simply don't support this capability. To illustrate, the 'c' + // param is dropped from this multivaluedmap example since it is a list: + // {c=[71, 81, 91, 72, 82, 92], a=[C1, C2], b=[790, 791]} + if (memberType != null && InjectionUtils.isSupportedCollectionOrArray(memberType)) { + continue; + } + + // Split multivaluedmap value list contents into separate multivaluedmap instances + // whose list contents are only 1 level deep, for example: + // {a=[C1, C2], b=[790, 791]} + // becomes these 2 separate multivaluedmap instances: + // {a=[C1], b=[790]} and {a=[C2], b=[791]} + int idx = 0; + for (String value : entry.getValue()) { + MultivaluedMap splitValues = + (idx < valuesList.size()) ? valuesList.get(idx) : null; + if (splitValues == null) { + splitValues = new MetadataMap(); + valuesList.add(splitValues); + } + splitValues.add(memberKey, value); + idx++; + } } + } else { + valuesList.add(values); } - return theValues; + + return valuesList; } - - public static Object injectIntoArray(Type genericType, List values, - boolean decoded, ParameterType pathParam, Message message) { + + public static boolean isSupportedCollectionOrArray(Class type) { + return List.class.isAssignableFrom(type) + || Set.class.isAssignableFrom(type) + || SortedSet.class.isAssignableFrom(type) + || type.isArray(); + } + + @SuppressWarnings("unchecked") + private static Object mergeCollectionsOrArrays(Object first, Object second, Type genericType) { + if (first == null) { + return second; + } else if (first instanceof Collection) { + Collection.class.cast(first).addAll((Collection) second); + return first; + } else { + int firstLen = Array.getLength(first); + int secondLen = Array.getLength(second); + Object mergedArray = Array.newInstance(InjectionUtils.getActualType(genericType), + firstLen + secondLen); + System.arraycopy(first, 0, mergedArray, 0, firstLen); + System.arraycopy(second, 0, mergedArray, firstLen, secondLen); + return mergedArray; + } + } + + private static Object injectIntoCollectionOrArray(Class rawType, Type genericType, + MultivaluedMap values, + boolean isbean, boolean decoded, + ParameterType pathParam, Message message) { + Class type = null; + if (List.class.isAssignableFrom(rawType)) { + type = ArrayList.class; + } else if (Set.class.isAssignableFrom(rawType)) { + type = HashSet.class; + } else if (SortedSet.class.isAssignableFrom(rawType)) { + type = TreeSet.class; + } + Class realType = InjectionUtils.getActualType(genericType); - values = checkPathSegment(values, realType, pathParam); - Object[] array = (Object[])Array.newInstance(realType, values.size()); - for (int i = 0; i < values.size(); i++) { - String value = decodeValue(values.get(i), decoded, pathParam); - Object o = InjectionUtils.handleParameter(value, realType, pathParam, message); - if (o != null) { - array[i] = o; + + Object theValues = null; + if (type != null) { + try { + theValues = type.newInstance(); + } catch (IllegalAccessException ex) { + reportServerError("CLASS_ACCESS_FAILURE", type.getName()); + } catch (Exception ex) { + reportServerError("CLASS_INSTANTIATION_FAILURE", type.getName()); + } + } else { + theValues = Array.newInstance(realType, isbean ? 1 : values.values().iterator().next().size()); + } + if (isbean) { + Object o = InjectionUtils.handleBean(realType, values, pathParam, message); + addToCollectionValues(theValues, o, 0); + } else { + List valuesList = values.values().iterator().next(); + valuesList = checkPathSegment(valuesList, realType, pathParam); + for (int ind = 0; ind < valuesList.size(); ind++) { + String value = decodeValue(valuesList.get(ind), decoded, pathParam); + Object o = InjectionUtils.handleParameter(value, realType, pathParam, message); + addToCollectionValues(theValues, o, ind); } } - return array; + return theValues; } - @SuppressWarnings("unchecked") - public static Object injectIntoSet(Type genericType, List values, - boolean sorted, - boolean decoded, - ParameterType pathParam, Message message) { - Class realType = InjectionUtils.getActualType(genericType); - - values = checkPathSegment(values, realType, pathParam); - - Set theValues = sorted ? new TreeSet() : new HashSet(); - for (String r : values) { - String value = decodeValue(r, decoded, pathParam); - Object o = InjectionUtils.handleParameter(value, realType, pathParam, message); - if (o != null) { - theValues.add(o); + private static void addToCollectionValues(Object theValues, Object o, int index) { + if (o != null) { + if (theValues instanceof Collection) { + Collection.class.cast(theValues).add(o); + } else { + ((Object[]) theValues)[index] = o; } } - return theValues; } private static List checkPathSegment(List values, Class type, @@ -403,17 +596,11 @@ } Object value = null; - if (List.class.isAssignableFrom(paramType)) { - value = InjectionUtils.injectIntoList(genericType, paramValues, decoded, pathParam, - message); - } else if (Set.class.isAssignableFrom(paramType)) { - value = InjectionUtils.injectIntoSet(genericType, paramValues, false, decoded, pathParam, - message); - } else if (SortedSet.class.isAssignableFrom(paramType)) { - value = InjectionUtils.injectIntoSet(genericType, paramValues, true, decoded, pathParam, - message); - } else if (paramType.isArray()) { - value = InjectionUtils.injectIntoArray(genericType, paramValues, decoded, pathParam, message); + if (InjectionUtils.isSupportedCollectionOrArray(paramType)) { + MultivaluedMap paramValuesMap = new MetadataMap(); + paramValuesMap.put("", paramValues); + value = InjectionUtils.injectIntoCollectionOrArray(paramType, genericType, paramValuesMap, + false, decoded, pathParam, message); } else { String result = null; if (paramValues.size() > 0) { Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/Customer.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/Customer.java?rev=763176&r1=763175&r2=763176&view=diff ============================================================================== --- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/Customer.java (original) +++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/Customer.java Wed Apr 8 10:54:54 2009 @@ -55,18 +55,35 @@ public static class CustomerBean { private String a; private Long b; + private List c; + private CustomerBean d; + //CHECKSTYLE:OFF + public List e; + //CHECKSTYLE:ON public void setA(String aString) { this.a = aString; } public void setB(Long bLong) { this.b = bLong; } + public void setC(List cStringList) { + this.c = cStringList; + } + public void setD(CustomerBean dCustomerBean) { + this.d = dCustomerBean; + } public String getA() { return a; } public Long getB() { return b; } + public List getC() { + return c; + } + public CustomerBean getD() { + return d; + } } Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java?rev=763176&r1=763175&r2=763176&view=diff ============================================================================== --- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java (original) +++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java Wed Apr 8 10:54:54 2009 @@ -630,37 +630,73 @@ Class[] argType = {Customer.CustomerBean.class}; Method m = Customer.class.getMethod("testQueryBean", argType); MessageImpl messageImpl = new MessageImpl(); - messageImpl.put(Message.QUERY_STRING, "a=aValue&b=123"); - List params = JAXRSUtils.processParameters(new OperationResourceInfo(m, null), - null, - messageImpl); - assertEquals("Bean should be created", 1, params.size()); - Customer.CustomerBean cb = (Customer.CustomerBean)params.get(0); - assertNotNull(cb); - - assertEquals("aValue", cb.getA()); - assertEquals(new Long(123), cb.getB()); + + MessageImpl complexMessageImpl = new MessageImpl(); + complexMessageImpl.put(Message.QUERY_STRING, "c=1&a=A&b=123&c=2&c=3&" + + "d.c=4&d.a=B&d.b=456&d.c=5&d.c=6&" + + "e.c=41&e.a=B1&e.b=457&e.c=51&e.c=61&" + + "e.c=42&e.a=B2&e.b=458&e.c=52&e.c=62&" + + "d.d.c=7&d.d.a=C&d.d.b=789&d.d.c=8&d.d.c=9&" + + "d.e.c=71&d.e.a=C1&d.e.b=790&d.e.c=81&d.e.c=91&" + + "d.e.c=72&d.e.a=C2&d.e.b=791&d.e.c=82&d.e.c=92"); + + verifyParametersBean(m, null, messageImpl, null, complexMessageImpl); } @Test public void testPathParametersBean() throws Exception { Class[] argType = {Customer.CustomerBean.class}; Method m = Customer.class.getMethod("testPathBean", argType); - MessageImpl messageImpl = new MessageImpl(); - - MultivaluedMap pathTamplates = new MetadataMap(); - pathTamplates.add("a", "aValue"); - pathTamplates.add("b", "123"); - List params = JAXRSUtils.processParameters(new OperationResourceInfo(m, null), - pathTamplates, - messageImpl); - assertEquals("Bean should be created", 1, params.size()); - Customer.CustomerBean cb = (Customer.CustomerBean)params.get(0); - assertNotNull(cb); - assertEquals("aValue", cb.getA()); - assertEquals(new Long(123), cb.getB()); + MultivaluedMap pathTemplates = new MetadataMap(); + pathTemplates.add("a", "aValue"); + pathTemplates.add("b", "123"); + + MultivaluedMap complexPathTemplates = new MetadataMap(); + complexPathTemplates.add("c", "1"); + complexPathTemplates.add("a", "A"); + complexPathTemplates.add("b", "123"); + complexPathTemplates.add("c", "2"); + complexPathTemplates.add("c", "3"); + + complexPathTemplates.add("d.c", "4"); + complexPathTemplates.add("d.a", "B"); + complexPathTemplates.add("d.b", "456"); + complexPathTemplates.add("d.c", "5"); + complexPathTemplates.add("d.c", "6"); + + complexPathTemplates.add("e.c", "41"); + complexPathTemplates.add("e.a", "B1"); + complexPathTemplates.add("e.b", "457"); + complexPathTemplates.add("e.c", "51"); + complexPathTemplates.add("e.c", "61"); + + complexPathTemplates.add("e.c", "42"); + complexPathTemplates.add("e.a", "B2"); + complexPathTemplates.add("e.b", "458"); + complexPathTemplates.add("e.c", "52"); + complexPathTemplates.add("e.c", "62"); + + complexPathTemplates.add("d.d.c", "7"); + complexPathTemplates.add("d.d.a", "C"); + complexPathTemplates.add("d.d.b", "789"); + complexPathTemplates.add("d.d.c", "8"); + complexPathTemplates.add("d.d.c", "9"); + + complexPathTemplates.add("d.e.c", "71"); + complexPathTemplates.add("d.e.a", "C1"); + complexPathTemplates.add("d.e.b", "790"); + complexPathTemplates.add("d.e.c", "81"); + complexPathTemplates.add("d.e.c", "91"); + + complexPathTemplates.add("d.e.c", "72"); + complexPathTemplates.add("d.e.a", "C2"); + complexPathTemplates.add("d.e.b", "791"); + complexPathTemplates.add("d.e.c", "82"); + complexPathTemplates.add("d.e.c", "92"); + + verifyParametersBean(m, pathTemplates, new MessageImpl(), complexPathTemplates, new MessageImpl()); } @Test @@ -669,15 +705,17 @@ Method m = Customer.class.getMethod("testMatrixBean", argType); MessageImpl messageImpl = new MessageImpl(); messageImpl.put(Message.REQUEST_URI, "/bar;a=aValue/baz;b=123"); - List params = JAXRSUtils.processParameters(new OperationResourceInfo(m, null), - new MetadataMap(), - messageImpl); - assertEquals("Bean should be created", 1, params.size()); - Customer.CustomerBean cb = (Customer.CustomerBean)params.get(0); - assertNotNull(cb); - - assertEquals("aValue", cb.getA()); - assertEquals(new Long(123), cb.getB()); + + MessageImpl complexMessageImpl = new MessageImpl(); + complexMessageImpl.put(Message.REQUEST_URI, "/bar;c=1/bar;a=A/bar;b=123/bar;c=2/bar;c=3" + + "/bar;d.c=4/bar;d.a=B/bar;d.b=456/bar;d.c=5/bar;d.c=6" + + "/bar;e.c=41/bar;e.a=B1/bar;e.b=457/bar;e.c=51/bar;e.c=61" + + "/bar;e.c=42/bar;e.a=B2/bar;e.b=458/bar;e.c=52/bar;e.c=62" + + "/bar;d.d.c=7/bar;d.d.a=C/bar;d.d.b=789/bar;d.d.c=8/bar;d.d.c=9" + + "/bar;d.e.c=71/bar;d.e.a=C1/bar;d.e.b=790/bar;d.e.c=81/bar;d.e.c=91" + + "/bar;d.e.c=72/bar;d.e.a=C2/bar;d.e.b=791/bar;d.e.c=82/bar;d.e.c=92"); + + verifyParametersBean(m, null, messageImpl, null, complexMessageImpl); } @Test @@ -688,15 +726,106 @@ messageImpl.put(Message.REQUEST_URI, "/bar"); String body = "a=aValue&b=123"; messageImpl.setContent(InputStream.class, new ByteArrayInputStream(body.getBytes())); + + MessageImpl complexMessageImpl = new MessageImpl(); + complexMessageImpl.put(Message.REQUEST_URI, "/bar"); + body = "c=1&a=A&b=123&c=2&c=3&" + + "d.c=4&d.a=B&d.b=456&d.c=5&d.c=6&" + + "e.c=41&e.a=B1&e.b=457&e.c=51&e.c=61&" + + "e.c=42&e.a=B2&e.b=458&e.c=52&e.c=62&" + + "d.d.c=7&d.d.a=C&d.d.b=789&d.d.c=8&d.d.c=9&" + + "d.e.c=71&d.e.a=C1&d.e.b=790&d.e.c=81&d.e.c=91&" + + "d.e.c=72&d.e.a=C2&d.e.b=791&d.e.c=82&d.e.c=92"; + complexMessageImpl.setContent(InputStream.class, new ByteArrayInputStream(body.getBytes())); + + verifyParametersBean(m, null, messageImpl, null, complexMessageImpl); + } + + private void verifyParametersBean(Method m, + MultivaluedMap simpleValues, + MessageImpl simpleMessageImpl, + MultivaluedMap complexValues, + MessageImpl complexMessageImpl) throws Exception { List params = JAXRSUtils.processParameters(new OperationResourceInfo(m, null), - new MetadataMap(), - messageImpl); + simpleValues, + simpleMessageImpl); assertEquals("Bean should be created", 1, params.size()); Customer.CustomerBean cb = (Customer.CustomerBean)params.get(0); assertNotNull(cb); assertEquals("aValue", cb.getA()); assertEquals(new Long(123), cb.getB()); + + params = JAXRSUtils.processParameters(new OperationResourceInfo(m, null), + complexValues, + complexMessageImpl); + assertEquals("Bean should be created", 1, params.size()); + Customer.CustomerBean cb1 = (Customer.CustomerBean)params.get(0); + assertNotNull(cb1); + + assertEquals("A", cb1.getA()); + assertEquals(new Long(123), cb1.getB()); + List list1 = (List)cb1.getC(); + assertEquals(3, list1.size()); + assertEquals("1", list1.get(0)); + assertEquals("2", list1.get(1)); + assertEquals("3", list1.get(2)); + + Customer.CustomerBean cb2 = cb1.getD(); + assertNotNull(cb2); + + assertEquals("B", cb2.getA()); + assertEquals(new Long(456), cb2.getB()); + List list2 = (List)cb2.getC(); + assertEquals(3, list2.size()); + assertEquals("4", list2.get(0)); + assertEquals("5", list2.get(1)); + assertEquals("6", list2.get(2)); + + List cb2List = cb1.e; + assertEquals(2, cb2List.size()); + + int idx = 1; + for (Customer.CustomerBean cb2E : cb2List) { + assertNotNull(cb2E); + + assertEquals("B" + idx, cb2E.getA()); + assertEquals(new Long(456 + idx), cb2E.getB()); + // ensure C was stripped properly since lists within lists are not supported + assertNull(cb2E.getC()); + assertNull(cb2E.getD()); + assertNull(cb2E.e); + + idx++; + } + + Customer.CustomerBean cb3 = cb2.getD(); + assertNotNull(cb3); + + assertEquals("C", cb3.getA()); + assertEquals(new Long(789), cb3.getB()); + List list3 = (List)cb3.getC(); + assertEquals(3, list3.size()); + assertEquals("7", list3.get(0)); + assertEquals("8", list3.get(1)); + assertEquals("9", list3.get(2)); + + List cb3List = cb2.e; + assertEquals(2, cb3List.size()); + + idx = 1; + for (Customer.CustomerBean cb3E : cb3List) { + assertNotNull(cb3E); + + assertEquals("C" + idx, cb3E.getA()); + assertEquals(new Long(789 + idx), cb3E.getB()); + // ensure C was stripped properly since lists within lists are not supported + assertNull(cb3E.getC()); + assertNull(cb3E.getD()); + assertNull(cb3E.e); + + idx++; + } } @Test