Author: scheu Date: Mon May 3 19:46:00 2010 New Revision: 940586 URL: http://svn.apache.org/viewvc?rev=940586&view=rev Log: AXIS2-4701 Contributor:Rich Scheuerle Support JAXB enums that lack certain annotations or generated methods...also added unit tests of new code.
Added: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/utility/XmlEnumUtils.java axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample.java axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample2.java axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample3.java axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/XmlEnumUtilsTest.java Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java?rev=940586&r1=940585&r2=940586&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java (original) +++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java Mon May 3 19:46:00 2010 @@ -30,6 +30,7 @@ import org.apache.axis2.jaxws.message.ut import org.apache.axis2.jaxws.spi.Constants; import org.apache.axis2.jaxws.utility.JavaUtils; import org.apache.axis2.jaxws.utility.XMLRootElementUtil; +import org.apache.axis2.jaxws.utility.XmlEnumUtils; import org.apache.axis2.description.Parameter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -603,12 +604,10 @@ public class JAXBDSContext { + " as Enum"); } - JAXBElement<String> enumValue = u.unmarshal(reader, String.class); + JAXBElement<String> enumValue = u.unmarshal(reader, XmlEnumUtils.getConversionType(type)); if (enumValue != null) { - Method m = - type.getMethod("fromValue", new Class[] { String.class }); - jaxb = m.invoke(null, new Object[] { enumValue.getValue() }); + jaxb = XmlEnumUtils.fromValue(type, enumValue.getValue()); } else { jaxb = null; } Added: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/utility/XmlEnumUtils.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/utility/XmlEnumUtils.java?rev=940586&view=auto ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/utility/XmlEnumUtils.java (added) +++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/utility/XmlEnumUtils.java Mon May 3 19:46:00 2010 @@ -0,0 +1,222 @@ +/* + * 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.axis2.jaxws.utility; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +import javax.xml.bind.annotation.XmlEnum; + +import org.apache.axis2.java.security.AccessController; +import org.apache.axis2.jaxws.ExceptionFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Utility methods for JAXB Enum classes + */ +public class XmlEnumUtils { + private static final Log log = LogFactory.getLog(XmlEnumUtils.class); + /** + * Static Utility classes have private construcors + */ + private XmlEnumUtils() {} + + /** + * @param e Class of enum + * @return a base type that can be used for constructing the enum + */ + public static Class getConversionType(final Class e) { + Class cls = null; + if (log.isDebugEnabled()) { + log.debug("getConversionType for " + e); + } + try { + cls = (Class) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + // Look for forName method that is generated by JAXB. + Method m = fromValueMethod(e, String.class); + if (m != null) { + return String.class; + } + + // If we cannot find forName(String) then look for @XmlEnum value + // and then look for a forName with the indicated base type + if (log.isDebugEnabled()) { + log.debug("try looking for @XmlEnum "); + } + XmlEnum xmlEnum = (XmlEnum) + e.getAnnotation(XmlEnum.class); + if (xmlEnum != null) { + Class argClass = xmlEnum.value(); + m = fromValueMethod(e, argClass); + if (m !=null) { + return argClass; + } + Class primitiveClass = getPrimitiveClass(argClass); + if (primitiveClass != null) { + m = fromValueMethod(e, primitiveClass); + if (m != null) { + return argClass; + } + } + } + + // If still not found look for valueOf(String) method + if (log.isDebugEnabled()) { + log.debug("try looking for valueOf method "); + } + m = valueOfMethod(e); + if (m != null) { + return String.class; + } + + throw ExceptionFactory.makeWebServiceException(new IllegalArgumentException()); + }}); + } finally { + if (log.isDebugEnabled()) { + log.debug("getConversionType is" + cls); + } + } + return cls; + } + + /** + * @param e enumeration class + * @param convObject Object of conversion type + * @return Object of enum + */ + public static Object fromValue(final Class e, final Object convObject) { + Object enumValue = null; + if (log.isDebugEnabled()) { + log.debug("fromValue for " + JavaUtils.getObjectIdentity(convObject)); + } + try { + enumValue = + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws InvocationTargetException, IllegalAccessException { + Method m = getConversionMethod(e); + return m.invoke(null, new Object[] { convObject }); + }}); + } catch (PrivilegedActionException pae) { + throw ExceptionFactory.makeWebServiceException(pae.getException()); + } finally { + if (log.isDebugEnabled()) { + log.debug("getEnumValue is" + JavaUtils.getObjectIdentity(enumValue)); + } + } + return enumValue; + } + + private static Method getConversionMethod(Class cls) { + // Look for forName method that is generated by JAXB. + Method m = fromValueMethod(cls, String.class); + if (m != null) { + return m; + } + + // If cannot find forName(String) then look for @XmlEnum value + if (log.isDebugEnabled()) { + log.debug("try looking for @XmlEnum "); + } + XmlEnum xmlEnum = (XmlEnum) + cls.getAnnotation(XmlEnum.class); + if (xmlEnum != null) { + Class argClass = xmlEnum.value(); + m = fromValueMethod(cls, argClass); + if (m !=null) { + return m; + } + Class primitiveClass = getPrimitiveClass(argClass); + if (primitiveClass != null) { + m = fromValueMethod(cls, primitiveClass); + if (m != null) { + return m; + } + } + } + + // Look for valueOf(String) method + if (log.isDebugEnabled()) { + log.debug("try looking for valueOf method "); + } + m = valueOfMethod(cls); + if (m != null) { + return m; + } + + throw new IllegalArgumentException(); + } + /** + * @param cls + * @param argClass + * @return Method of fromValue with argClass + */ + private static Method fromValueMethod(Class cls, Class argClass) { + try { + return cls.getMethod("fromValue", new Class[] { argClass }); + } catch (Throwable t) { + return null; + } + } + + /** + * @param cls + * @param argClass + * @return Method of valueOf with argClass + */ + private static Method valueOfMethod(Class cls) { + try { + return cls.getMethod("valueOf", new Class[] { String.class }); + } catch (Throwable t) { + return null; + } + } + + /* + * @param cls possible wrapper class + * @return primitive class if this is a wrapper class + */ + private static Class getPrimitiveClass(Class cls) { + if (Integer.class.equals(cls)) { + return int.class; + } else if (Short.class.equals(cls)) { + return short.class; + } else if (Boolean.class.equals(cls)) { + return boolean.class; + } else if (Byte.class.equals(cls)) { + return byte.class; + } else if (Long.class.equals(cls)) { + return long.class; + } else if (Double.class.equals(cls)) { + return double.class; + } else if (Float.class.equals(cls)) { + return float.class; + } else if (Character.class.equals(cls)) { + return char.class; + } + + return null; + } + +} Added: axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample.java?rev=940586&view=auto ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample.java (added) +++ axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample.java Mon May 3 19:46:00 2010 @@ -0,0 +1,33 @@ +/* + * 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.axis2.jaxws.misc; + +import javax.xml.bind.annotation.XmlType; + +/** + * Sample Enum + */ +...@xmltype(name="SampleEnum", namespace="urn://misc.jaxws.axis2.apache.org") +public enum EnumSample { + DATA_A, DATA_B, DATA_C +} \ No newline at end of file Added: axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample2.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample2.java?rev=940586&view=auto ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample2.java (added) +++ axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample2.java Mon May 3 19:46:00 2010 @@ -0,0 +1,35 @@ +/* + * 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.axis2.jaxws.misc; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlType; + +/** + * Sample Enum + */ +...@xmlenum(value=java.lang.String.class) +...@xmltype(name="SampleEnum", namespace="urn://misc.jaxws.axis2.apache.org") +public enum EnumSample2 { + DATA_A2, DATA_B2, DATA_C2 +} \ No newline at end of file Added: axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample3.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample3.java?rev=940586&view=auto ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample3.java (added) +++ axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/EnumSample3.java Mon May 3 19:46:00 2010 @@ -0,0 +1,51 @@ +/* + * 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.axis2.jaxws.misc; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlType; + +/** + * Sample Enum + */ +...@xmlenum(value=java.lang.Integer.class) +...@xmltype(name="SampleEnum", namespace="urn://misc.jaxws.axis2.apache.org") +public enum EnumSample3 { + DATA_A3(10), DATA_B3(20), DATA_C3(30); + final private Integer value; + EnumSample3(int data) { + value = data; + } + public int value() { return value; } + public static EnumSample3 fromValue(int value) { + if (value == 10) { + return DATA_A3; + } else if (value == 20) { + return DATA_B3; + } else if (value == 30) { + return DATA_C3; + } + return null; + } + +} \ No newline at end of file Added: axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/XmlEnumUtilsTest.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/XmlEnumUtilsTest.java?rev=940586&view=auto ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/XmlEnumUtilsTest.java (added) +++ axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/misc/XmlEnumUtilsTest.java Mon May 3 19:46:00 2010 @@ -0,0 +1,57 @@ +/* + * 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.axis2.jaxws.misc; + +import junit.framework.TestCase; +import org.apache.axis2.jaxws.utility.XmlEnumUtils; + +/** + * Tests Namespace to Package Algorithm + */ +public class XmlEnumUtilsTest extends TestCase { + + public void test01() throws Exception { + Class cls = XmlEnumUtils.getConversionType(EnumSample.class); + assertTrue(String.class.equals(cls)); + + Object value = XmlEnumUtils.fromValue(EnumSample.class, "DATA_C"); + assertTrue(EnumSample.DATA_C == value); + } + + public void test02() throws Exception { + Class cls = XmlEnumUtils.getConversionType(EnumSample2.class); + assertTrue(String.class.equals(cls)); + + + Object value = XmlEnumUtils.fromValue(EnumSample2.class,"DATA_C2"); + assertTrue(EnumSample2.DATA_C2 == value); + } + + public void test03() throws Exception { + Class cls = XmlEnumUtils.getConversionType(EnumSample3.class); + assertTrue(Integer.class.equals(cls)); + + Object value = XmlEnumUtils.fromValue(EnumSample3.class,30); + assertTrue(EnumSample3.DATA_C3 == value); + } +}