TUSCANY-3298: Enable JAXB wrappers for WSDL generation

git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1041912 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
nash 2010-12-03 17:07:02 +00:00
parent eeabc3ec37
commit b45ddbd9b9
7 changed files with 133 additions and 24 deletions

View file

@ -38,9 +38,12 @@ public interface FileTransferService {
public String uploadDataHandlerFile(DataHandler attachment) throws Exception;
public String uploadOMElementFile(OMElement attachment) throws Exception;
// TUSCANY-3805: produces WSDL generation error with fix for TUSCANY-3298
/*
//This method uses an user defined interface MyException as parameter type.
public String sendMyException(@XmlJavaTypeAdapter(MyExceptionAdapter.class) MyException attachment)
throws Exception;
*/
}

View file

@ -344,7 +344,8 @@ public class Interface2WSDLGenerator {
// call each helper in turn to populate the wsdl.types element
XmlSchemaCollection schemaCollection = new XmlSchemaCollection();
for (Map.Entry<XMLTypeHelper, List<DataType>> en: getDataTypes(interfaze, false, helpers).entrySet()) {
// TUSCANY-3298: enable JAXB wrapper generation
for (Map.Entry<XMLTypeHelper, List<DataType>> en: getDataTypes(interfaze, true, helpers).entrySet()) {
XMLTypeHelper helper = en.getKey();
if (helper == null) {
continue;
@ -1112,6 +1113,11 @@ public class Interface2WSDLGenerator {
dataType.getLogical());
ElementInfo element = new ElementInfo(name, typeInfo);
element.setMany(byte[].class != javaType && javaType.isArray());
// TUSCANY-3298: Check the "many" flag set by databinding introspection
Object logical = dataType.getLogical();
if (logical instanceof XMLType && ((XMLType)logical).isMany()) {
element.setMany(true);
}
element.setNillable(!javaType.isPrimitive());
return element;
}

View file

@ -121,13 +121,29 @@ public class Input2InputTransformer extends BaseTransformer<Object[], Object[]>
for (int i = 0; i < list1.size(); i++) {
String n1 = list1.get(i).getQName().getLocalPart();
String n2 = list2.get(i).getQName().getLocalPart();
if (!n1.equals(n2)) {
// TUSCANY-3298: In the following situation:
// 1. The child is a java.util.Map type
// 2. The child's name is a Java keyword (e.g., return)
// 3. Tuscany is using a generated JAXB wrapper class for WSDL generation
// the Java to WSDL generation process results in the WSDL element name
// having a leading underscore added to the actual element name. This is
// because of a known JAXB issue that prevents the @XmlElement annotation
// being used on a java.util.Map type property field in the wrapper bean
// (see https://jaxb.dev.java.net/issues/show_bug.cgi?id=268).
// To prevent the compatibility match from failing in this situation,
// we strip any leading underscore before doing the comparison.
if (!stripLeadingUnderscore(n1).equals(stripLeadingUnderscore(n2))) {
return false;
}
}
return true;
}
private static String stripLeadingUnderscore(String name) {
return name.startsWith("_") ? name.substring(1) : name;
}
@SuppressWarnings("unchecked")
public Object[] transform(Object[] source, TransformationContext context) {
// Check if the source operation is wrapped

View file

@ -142,13 +142,29 @@ public class Output2OutputTransformer extends BaseTransformer<Object, Object> im
for (int i = 0; i < list1.size(); i++) {
String n1 = list1.get(i).getQName().getLocalPart();
String n2 = list2.get(i).getQName().getLocalPart();
if (!n1.equals(n2)) {
// TUSCANY-3298: In the following situation:
// 1. The child is a java.util.Map type
// 2. The child's name is a Java keyword (e.g., return)
// 3. Tuscany is using a generated JAXB wrapper class for WSDL generation
// the Java to WSDL generation process results in the WSDL element name
// having a leading underscore added to the actual element name. This is
// because of a known JAXB issue that prevents the @XmlElement annotation
// being used on a java.util.Map type property field in the wrapper bean
// (see https://jaxb.dev.java.net/issues/show_bug.cgi?id=268).
// To prevent the compatibility match from failing in this situation,
// we strip any leading underscore before doing the comparison.
if (!stripLeadingUnderscore(n1).equals(stripLeadingUnderscore(n2))) {
return false;
}
}
return true;
}
private static String stripLeadingUnderscore(String name) {
return name.startsWith("_") ? name.substring(1) : name;
}
@SuppressWarnings("unchecked")
public Object transform(Object response, TransformationContext context) {
try {

View file

@ -24,8 +24,10 @@ import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.bind.JAXBContext;
@ -343,29 +345,54 @@ public class JAXBContextHelper {
WrapperInfo inputWrapperInfo = op.getInputWrapper();
WrapperInfo outputWrapperInfo = op.getOutputWrapper();
// TUSCANY-3298: Add the wrapper type instead of individual elements
// if possible. JAXB will implicitly add all types that are statically
// reachable from the wrapper class, with the exception of type arguments
// for parameterized types that aren't collections.
DataType dt1 = null;
if (useWrapper && (inputWrapperInfo != null)) {
DataType dt1 = inputWrapperInfo.getWrapperType();
dt1 = inputWrapperInfo.getWrapperType();
if (dt1 != null) {
dataTypes.add(dt1);
for (DataType in : op.getInputType().getLogical()) {
if (isParameterizedNonCollectionType(in)) {
// JAXB won't add the type arguments, so we need to add them
dataTypes.add(in);
}
}
}
}
if (dt1 == null) {
// We couldn't add the wrapper, so add the elements individually
for (DataType dt : op.getInputType().getLogical()) {
dataTypes.add(dt);
}
}
// TUSCANY-3298: Add the wrapper type instead of the output type
// if possible. JAXB will implicitly add all types that are statically
// reachable from the wrapper class, with the exception of type arguments
// for parameterized types that aren't collections or maps.
DataType dt2 = null;
if (useWrapper && (outputWrapperInfo != null)) {
DataType dt2 = outputWrapperInfo.getWrapperType();
if (dt2 != null) {
dataTypes.add(dt2);
}
}
// FIXME: [rfeng] We may need to find the referenced classes in the child types
// else
{
for (DataType dt1 : op.getInputType().getLogical()) {
dataTypes.add(dt1);
}
DataType dt2 = op.getOutputType();
dt2 = outputWrapperInfo.getWrapperType();
if (dt2 != null) {
dataTypes.add(dt2);
DataType out = op.getOutputType();
if (out != null && isParameterizedNonCollectionType(out)) {
// JAXB won't add the type arguments, so we need to add them
dataTypes.add(out);
}
}
}
if (dt2 == null) {
// We couldn't add the wrapper, so add the output type directly
dt2 = op.getOutputType();
if (dt2 != null) {
dataTypes.add(dt2);
}
}
for (DataType<DataType> dt3 : op.getFaultTypes()) {
DataType dt4 = dt3.getLogical();
if (dt4 != null) {
@ -374,6 +401,23 @@ public class JAXBContextHelper {
}
}
/*
* We need to add parameterized non-collection types to the JAXB context
* explicitly, because type argument information for these types is erased
* from the generated wrapper bean.
*/
private static boolean isParameterizedNonCollectionType(DataType dt) {
Type type = dt.getGenericType();
if (type instanceof ParameterizedType) {
Class physical = dt.getPhysical();
if (!Collection.class.isAssignableFrom(physical) &&
!Map.class.isAssignableFrom(physical)) {
return true;
}
}
return false;
}
@SuppressWarnings("unchecked")
public static Class<?> getJavaType(DataType<?> dataType) {
if (dataType == null) {

View file

@ -19,8 +19,10 @@
package org.apache.tuscany.sca.databinding.sdo;
import java.lang.reflect.ParameterizedType;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import javax.xml.namespace.QName;
@ -60,7 +62,7 @@ public class SDODataBinding extends BaseDataBinding {
@Override
public boolean introspect(DataType dataType, final Operation operation) {
final Class javaType = dataType.getPhysical();
Class javaType = dataType.getPhysical();
// Allow privileged access to read system properties. Requires PropertyPermission
// java.specification.version read in security policy.
final HelperContext context = AccessController.doPrivileged(new PrivilegedAction<HelperContext>() {
@ -72,11 +74,33 @@ public class SDODataBinding extends BaseDataBinding {
final Type type = context.getTypeHelper().getType(javaType);
if (type == null) {
// FIXME: Need a better to test dynamic SDO
// TUSCANY-3298: get underlying element type for collections
boolean isMany = false;
if (Collection.class.isAssignableFrom(javaType)) {
java.lang.reflect.Type genericType = dataType.getGenericType();
if (genericType instanceof ParameterizedType) {
java.lang.reflect.Type actualType = ((ParameterizedType)genericType).getActualTypeArguments()[0];
if (actualType instanceof Class) {
javaType = (Class)actualType;
isMany = true;
}
}
}
if (DataObject.class.isAssignableFrom(javaType)) {
// Dynamic SDO
dataType.setDataBinding(getName());
if (dataType.getLogical() == null) {
dataType.setLogical(XMLType.UNKNOWN);
// TUSCANY-3298: use XMLType many value to indicate a collection
Object logical = dataType.getLogical();
if (logical == null) {
if (!isMany) {
dataType.setLogical(XMLType.UNKNOWN);
} else {
XMLType xmlType = new XMLType(null, null);
xmlType.setMany(true);
dataType.setLogical(xmlType);
}
} else if (logical instanceof XMLType && isMany) {
((XMLType)logical).setMany(true);
}
return true;
}

View file

@ -70,16 +70,16 @@ public class SDOTypeHelper implements XMLTypeHelper {
QName xmlType = JavaXMLMapper.getXMLType(javaType);
if (xmlType != null) {
return new TypeInfo(xmlType, true, null);
} else if (javaType == commonj.sdo.DataObject.class) {
return new TypeInfo(SimpleTypeMapperImpl.XSD_ANYTYPE, true, null);
} else {
// introspect(javaType, xsdTypesMap, typesMap);
if (logical instanceof XMLType) {
xmlType = ((XMLType)logical).getTypeName();
}
if (xmlType == null) {
xmlType =
new QName(JavaXMLMapper.getNamespace(javaType), Introspector.decapitalize(javaType.getSimpleName()));
// TUSCANY-3298: dynamic SDO or collection of dynamic SDO
return new TypeInfo(SimpleTypeMapperImpl.XSD_ANYTYPE, true, null);
//xmlType =
// new QName(JavaXMLMapper.getNamespace(javaType), Introspector.decapitalize(javaType.getSimpleName()));
}
return new TypeInfo(xmlType, false, null);
}