1 17 package org.apache.geronimo.axis.builder; 18 19 import java.beans.IntrospectionException ; 20 import java.beans.Introspector ; 21 import java.beans.PropertyDescriptor ; 22 import java.lang.reflect.Field ; 23 import java.util.ArrayList ; 24 import java.util.Collection ; 25 import java.util.HashMap ; 26 import java.util.HashSet ; 27 import java.util.Iterator ; 28 import java.util.List ; 29 import java.util.Map ; 30 import java.util.Set ; 31 import javax.xml.namespace.QName ; 32 import javax.xml.rpc.encoding.DeserializerFactory ; 33 import javax.xml.rpc.encoding.SerializerFactory ; 34 35 import org.apache.axis.description.AttributeDesc; 36 import org.apache.axis.description.ElementDesc; 37 import org.apache.axis.description.FieldDesc; 38 import org.apache.axis.description.OperationDesc; 39 import org.apache.axis.description.ParameterDesc; 40 import org.apache.axis.encoding.DefaultJAXRPC11TypeMappingImpl; 41 import org.apache.axis.encoding.DefaultSOAPEncodingTypeMappingImpl; 42 import org.apache.axis.encoding.TypeMappingImpl; 43 import org.apache.axis.encoding.XMLType; 44 import org.apache.axis.encoding.ser.ArrayDeserializerFactory; 45 import org.apache.axis.encoding.ser.ArraySerializerFactory; 46 import org.apache.axis.encoding.ser.BeanDeserializerFactory; 47 import org.apache.axis.encoding.ser.BeanSerializerFactory; 48 import org.apache.axis.encoding.ser.EnumDeserializerFactory; 49 import org.apache.axis.encoding.ser.EnumSerializerFactory; 50 import org.apache.axis.encoding.ser.SimpleListDeserializerFactory; 51 import org.apache.axis.encoding.ser.SimpleListSerializerFactory; 52 import org.apache.commons.logging.Log; 53 import org.apache.commons.logging.LogFactory; 54 import org.apache.geronimo.axis.client.ArrayTypeInfo; 55 import org.apache.geronimo.axis.client.TypeInfo; 56 import org.apache.geronimo.common.DeploymentException; 57 import org.apache.geronimo.kernel.ClassLoading; 58 import org.apache.geronimo.xbeans.j2ee.JavaWsdlMappingType; 59 import org.apache.geronimo.xbeans.j2ee.JavaXmlTypeMappingType; 60 import org.apache.geronimo.xbeans.j2ee.VariableMappingType; 61 import org.apache.geronimo.webservices.builder.SchemaTypeKey; 62 import org.apache.xmlbeans.SchemaLocalAttribute; 63 import org.apache.xmlbeans.SchemaParticle; 64 import org.apache.xmlbeans.SchemaProperty; 65 import org.apache.xmlbeans.SchemaType; 66 import org.apache.xmlbeans.soap.SOAPArrayType; 67 import org.apache.xmlbeans.soap.SchemaWSDLArrayType; 68 69 72 public class HeavyweightTypeInfoBuilder implements TypeInfoBuilder { 73 private static final String SOAP_ENCODING_NS = "http://schemas.xmlsoap.org/soap/encoding/"; 74 private static final String XML_SCHEMA_NS = "http://www.w3.org/2001/XMLSchema"; 75 76 private static final Log log = LogFactory.getLog(HeavyweightTypeInfoBuilder.class); 77 78 private final ClassLoader cl; 79 private final Map schemaTypeKeyToSchemaTypeMap; 80 private final Set wrapperElementQNames; 81 private final Collection operations; 82 private final boolean hasEncoded; 83 84 public HeavyweightTypeInfoBuilder(ClassLoader cl, Map schemaTypeKeyToSchemaTypeMap, Set wrapperElementQNames, Collection operations, boolean hasEncoded) { 85 this.cl = cl; 86 this.schemaTypeKeyToSchemaTypeMap = schemaTypeKeyToSchemaTypeMap; 87 this.wrapperElementQNames = wrapperElementQNames; 88 this.operations = operations; 89 this.hasEncoded = hasEncoded; 90 } 91 92 public List buildTypeInfo(JavaWsdlMappingType mapping) throws DeploymentException { 93 List typeInfoList = new ArrayList (); 94 95 Set mappedTypeQNames = new HashSet (); 96 97 JavaXmlTypeMappingType[] javaXmlTypeMappings = mapping.getJavaXmlTypeMappingArray(); 98 for (int j = 0; j < javaXmlTypeMappings.length; j++) { 99 JavaXmlTypeMappingType javaXmlTypeMapping = javaXmlTypeMappings[j]; 100 101 SchemaTypeKey key; 102 boolean isElement = javaXmlTypeMapping.getQnameScope().getStringValue().equals("element"); 103 boolean isSimpleType = javaXmlTypeMapping.getQnameScope().getStringValue().equals("simpleType"); 104 if (javaXmlTypeMapping.isSetRootTypeQname()) { 105 QName typeQName = javaXmlTypeMapping.getRootTypeQname().getQNameValue(); 106 key = new SchemaTypeKey(typeQName, isElement, isSimpleType, false, null); 107 108 if (wrapperElementQNames.contains(typeQName)) { 110 continue; 111 } 112 } else if (javaXmlTypeMapping.isSetAnonymousTypeQname()) { 113 String anonTypeQNameString = javaXmlTypeMapping.getAnonymousTypeQname().getStringValue(); 114 int pos = anonTypeQNameString.lastIndexOf(":"); 115 if (pos == -1) { 116 throw new DeploymentException("anon QName is invalid, no final ':' " + anonTypeQNameString); 117 } 118 119 QName typeQName = new QName (anonTypeQNameString.substring(0, pos), anonTypeQNameString.substring(pos + 1)); 121 key = new SchemaTypeKey(typeQName, isElement, isSimpleType, true, null); 122 123 if (wrapperElementQNames.contains(new QName (anonTypeQNameString.substring(0, pos), anonTypeQNameString.substring(pos + 2)))) { 125 continue; 126 } 127 } else { 128 throw new DeploymentException("either root type qname or anonymous type qname must be set"); 129 } 130 131 SchemaType schemaType = (SchemaType) schemaTypeKeyToSchemaTypeMap.get(key); 132 if (schemaType == null) { 133 if (null != TypeMappingLookup.getFactoryPair(key.getqName())) { 135 continue; 136 } 137 log.warn("Schema type key " + key + " not found in analyzed schema: " + schemaTypeKeyToSchemaTypeMap); 139 continue; 140 } 141 mappedTypeQNames.add(key.getqName()); 142 143 String className = javaXmlTypeMapping.getJavaType().getStringValue().trim(); 144 Class clazz = null; 145 try { 146 clazz = ClassLoading.loadClass(className, cl); 147 } catch (ClassNotFoundException e2) { 148 throw new DeploymentException("Could not load java type", e2); 149 } 150 151 TypeInfo.UpdatableTypeInfo internalTypeInfo = defineSerializerPair(schemaType, clazz); 152 153 populateInternalTypeInfo(clazz, key, schemaType, javaXmlTypeMapping, internalTypeInfo); 154 155 typeInfoList.add(internalTypeInfo.buildTypeInfo()); 156 } 157 158 Map qNameToKey = new HashMap (); 159 for (Iterator iter = schemaTypeKeyToSchemaTypeMap.keySet().iterator(); iter.hasNext();) { 160 SchemaTypeKey key = (SchemaTypeKey) iter.next(); 161 qNameToKey.put(key.getqName(), key); 162 } 163 164 for (Iterator iter = operations.iterator(); iter.hasNext();) { 165 OperationDesc operationDesc = (OperationDesc) iter.next(); 166 ArrayList parameters = new ArrayList (operationDesc.getParameters()); 167 ParameterDesc returnParameterDesc = operationDesc.getReturnParamDesc(); 168 if (null != returnParameterDesc.getTypeQName() && 169 false == returnParameterDesc.getTypeQName().equals(XMLType.AXIS_VOID)) { 170 parameters.add(returnParameterDesc); 171 } 172 for (Iterator iterator = parameters.iterator(); iterator.hasNext();) { 173 ParameterDesc parameterDesc = (ParameterDesc) iterator.next(); 174 QName typeQName = parameterDesc.getTypeQName(); 175 if (null == typeQName) { 176 continue; 177 } else if (mappedTypeQNames.contains(typeQName)) { 178 continue; 179 } else if (typeQName.getNamespaceURI().equals(XML_SCHEMA_NS) || 180 typeQName.getNamespaceURI().equals(SOAP_ENCODING_NS)) { 181 continue; 182 } 183 184 SchemaTypeKey key = (SchemaTypeKey) qNameToKey.get(typeQName); 185 if (null == key) { 186 log.warn("Type QName [" + typeQName + "] defined by operation [" + 187 operationDesc + "] has not been found in schema: " + schemaTypeKeyToSchemaTypeMap); 188 continue; 189 } 190 SchemaType schemaType = (SchemaType) schemaTypeKeyToSchemaTypeMap.get(key); 191 mappedTypeQNames.add(key.getqName()); 192 193 if (false == schemaType.isSimpleType()) { 194 if (false == parameterDesc.getJavaType().isArray()) { 195 if (false == mappedTypeQNames.contains(schemaType.getName())) { 196 log.warn("Operation [" + operationDesc + "] uses XML type [" + schemaType + 199 "], whose mapping is not declared by the jaxrpc mapping file.\n Continuing deployment; " + 200 "yet, the deployment is not-portable."); 201 } 202 continue; 203 } 204 } 205 206 Class clazz = parameterDesc.getJavaType(); 207 TypeInfo.UpdatableTypeInfo internalTypeInfo = defineSerializerPair(schemaType, clazz); 208 setTypeQName(internalTypeInfo, key); 209 internalTypeInfo.setFields(new FieldDesc[0]); 210 211 typeInfoList.add(internalTypeInfo.buildTypeInfo()); 212 } 213 } 214 215 return typeInfoList; 216 } 217 218 private TypeInfo.UpdatableTypeInfo defineSerializerPair(SchemaType schemaType, Class clazz) 219 throws DeploymentException { 220 TypeInfo.UpdatableTypeInfo internalTypeInfo = new TypeInfo.UpdatableTypeInfo(); 221 Class serializerFactoryClass = null; 222 Class deserializerFactoryClass = null; 223 if (schemaType.isSimpleType()) { 224 if (SchemaType.ATOMIC == schemaType.getSimpleVariety()) { 225 if (clazz.isArray()) { 226 internalTypeInfo = new ArrayTypeInfo.UpdatableArrayTypeInfo(); 227 serializerFactoryClass = ArraySerializerFactory.class; 228 deserializerFactoryClass = ArrayDeserializerFactory.class; 229 } else if (null != schemaType.getEnumerationValues()) { 231 serializerFactoryClass = EnumSerializerFactory.class; 232 deserializerFactoryClass = EnumDeserializerFactory.class; 233 } else { 234 QName typeQName = schemaType.getPrimitiveType().getName(); 235 FactoryPair pair = (FactoryPair) TypeMappingLookup.getFactoryPair(typeQName); 236 if (null == pair) { 237 throw new DeploymentException("Primitive type [" + typeQName + "] is not registered."); 238 } 239 serializerFactoryClass = pair.serializerFactoryClass; 240 deserializerFactoryClass = pair.deserializerFactoryClass; 241 } 242 } else if (SchemaType.LIST == schemaType.getSimpleVariety()) { 243 serializerFactoryClass = SimpleListSerializerFactory.class; 244 deserializerFactoryClass = SimpleListDeserializerFactory.class; 245 } else { 246 throw new DeploymentException("Schema type [" + schemaType + "] is invalid."); 247 } 248 } else { 249 if (clazz.isArray()) { 250 internalTypeInfo = new ArrayTypeInfo.UpdatableArrayTypeInfo(); 251 serializerFactoryClass = ArraySerializerFactory.class; 252 deserializerFactoryClass = ArrayDeserializerFactory.class; 253 QName componentType = null; 254 SchemaLocalAttribute arrayTypeAttribute = schemaType.getAttributeModel().getAttribute(new QName (SOAP_ENCODING_NS, "arrayType")); 263 if (arrayTypeAttribute != null) { 264 SchemaWSDLArrayType wsdlArrayType = (SchemaWSDLArrayType) arrayTypeAttribute; 265 SOAPArrayType soapArrayType = wsdlArrayType.getWSDLArrayType(); 266 if (soapArrayType != null) { 267 componentType = soapArrayType.getQName(); 268 log.debug("extracted componentType " + componentType + " from schemaType " + schemaType); 269 } else { 270 log.info("no SOAPArrayType for component from schemaType " + schemaType); 271 } 272 } else { 273 log.warn("No soap array info for schematype: " + schemaType); 274 } 275 if (componentType == null) { 276 if (schemaType.getBaseType().getName().equals(new QName (SOAP_ENCODING_NS, "Array"))) { 288 SchemaProperty[] properties = schemaType.getDerivedProperties(); 289 if (properties.length != 1) { 290 throw new DeploymentException("more than one element inside array definition: " + schemaType); 291 } 292 componentType = properties[0].getType().getName(); 293 log.debug("determined component type from element type"); 294 } 295 296 } 297 298 ((ArrayTypeInfo.UpdatableArrayTypeInfo)internalTypeInfo).setComponentType(componentType); 299 } else { 301 QName typeQName; 302 if (SchemaType.SIMPLE_CONTENT == schemaType.getContentType()) { 303 typeQName = schemaType.getBaseType().getName(); 304 } else if (SchemaType.EMPTY_CONTENT == schemaType.getContentType() || 305 SchemaType.ELEMENT_CONTENT == schemaType.getContentType() || 306 SchemaType.MIXED_CONTENT == schemaType.getContentType()) { 307 typeQName = schemaType.getName(); 308 } else { 309 throw new DeploymentException("Schema type [" + schemaType + "] is invalid."); 310 } 311 FactoryPair pair = (FactoryPair) TypeMappingLookup.getFactoryPair(typeQName); 312 if (null != pair) { 313 serializerFactoryClass = pair.serializerFactoryClass; 314 deserializerFactoryClass = pair.deserializerFactoryClass; 315 } else { 316 serializerFactoryClass = BeanSerializerFactory.class; 317 deserializerFactoryClass = BeanDeserializerFactory.class; 318 } 319 } 320 } 321 322 internalTypeInfo.setClazz(clazz); 323 internalTypeInfo.setSerializerClass(serializerFactoryClass); 324 internalTypeInfo.setDeserializerClass(deserializerFactoryClass); 325 return internalTypeInfo; 326 } 327 328 private void setTypeQName(TypeInfo.UpdatableTypeInfo typeInfo, SchemaTypeKey key) { 329 QName axisKey = key.getElementQName(); 331 if (axisKey == null) { 332 axisKey = key.getqName(); 333 } 334 typeInfo.setQName(axisKey); 335 } 336 337 private void populateInternalTypeInfo(Class javaClass, SchemaTypeKey key, SchemaType schemaType, JavaXmlTypeMappingType javaXmlTypeMapping, TypeInfo.UpdatableTypeInfo typeInfo) throws DeploymentException { 338 String ns = key.getqName().getNamespaceURI(); 339 typeInfo.setCanSearchParents(schemaType.getDerivationType() == SchemaType.DT_RESTRICTION); 340 341 setTypeQName(typeInfo, key); 342 343 Map paramNameToType = new HashMap (); 344 if (null == schemaType.getContentModel()) { 345 ; 346 } else if (SchemaParticle.SEQUENCE == schemaType.getContentModel().getParticleType() 347 || SchemaParticle.ALL == schemaType.getContentModel().getParticleType()) { 348 SchemaParticle[] properties = schemaType.getContentModel().getParticleChildren(); 349 for (int i = 0; i < properties.length; i++) { 350 SchemaParticle parameter = properties[i]; 351 paramNameToType.put(parameter.getName(), parameter); 352 } 353 } else if (SchemaParticle.ELEMENT == schemaType.getContentModel().getParticleType()) { 354 SchemaParticle parameter = schemaType.getContentModel(); 355 paramNameToType.put(parameter.getName(), parameter); 356 } else { 357 throw new DeploymentException("Only element, sequence, and all particle types are supported." + 358 " SchemaType name =" + schemaType.getName()); 359 } 360 361 Map attNameToType = new HashMap (); 362 if (null != schemaType.getAttributeModel()) { 363 SchemaLocalAttribute[] attributes = schemaType.getAttributeModel().getAttributes(); 364 for (int i = 0; i < attributes.length; i++) { 365 SchemaLocalAttribute attribute = attributes[i]; 366 Object old = attNameToType.put(attribute.getName().getLocalPart(), attribute); 367 if (old != null) { 368 throw new DeploymentException("Complain to your expert group member, spec does not support attributes with the same local name and differing namespaces: original: " + old + ", duplicate local name: " + attribute); 369 } 370 } 371 } 372 373 VariableMappingType[] variableMappings = javaXmlTypeMapping.getVariableMappingArray(); 374 375 if (javaClass.isArray()) { 377 if (0 != variableMappings.length) { 378 log.warn("Ignoring variable-mapping defined for class " + javaClass + " which is an array."); 380 } 381 typeInfo.setFields(new FieldDesc[0]); 382 return; 383 } 384 385 FieldDesc[] fields = new FieldDesc[variableMappings.length]; 386 typeInfo.setFields(fields); 387 388 PropertyDescriptor [] propertyDescriptors = new PropertyDescriptor [0]; 389 try { 390 propertyDescriptors = Introspector.getBeanInfo(javaClass).getPropertyDescriptors(); 391 } catch (IntrospectionException e) { 392 throw new DeploymentException("Class " + javaClass + " is not a valid javabean", e); 393 } 394 Map properties = new HashMap (); 395 for (int i = 0; i < propertyDescriptors.length; i++) { 396 PropertyDescriptor propertyDescriptor = propertyDescriptors[i]; 397 properties.put(propertyDescriptor.getName(), propertyDescriptor.getPropertyType()); 398 } 399 for (int i = 0; i < variableMappings.length; i++) { 400 VariableMappingType variableMapping = variableMappings[i]; 401 String fieldName = variableMapping.getJavaVariableName().getStringValue().trim(); 402 403 if (variableMapping.isSetXmlAttributeName()) { 404 AttributeDesc attributeDesc = new AttributeDesc(); 405 attributeDesc.setFieldName(fieldName); 406 Class javaType = (Class ) properties.get(fieldName); 407 if (javaType == null) { 408 throw new DeploymentException("field name " + fieldName + " not found in " + properties); 409 } 410 String attributeLocalName = variableMapping.getXmlAttributeName().getStringValue().trim(); 411 QName xmlName = new QName ("", attributeLocalName); 412 attributeDesc.setXmlName(xmlName); 413 414 SchemaLocalAttribute attribute = (SchemaLocalAttribute) attNameToType.get(attributeLocalName); 415 if (null == attribute) { 416 throw new DeploymentException("attribute " + xmlName + " not found in schema " + schemaType.getName()); 417 } 418 attributeDesc.setXmlType(attribute.getType().getName()); 419 420 fields[i] = attributeDesc; 421 } else { 422 ElementDesc elementDesc = new ElementDesc(); 423 elementDesc.setFieldName(fieldName); 424 Class javaType = (Class ) properties.get(fieldName); 425 if (javaType == null) { 426 try { 428 Field field = javaClass.getField(fieldName); 429 javaType = field.getType(); 430 } catch (NoSuchFieldException e) { 431 throw new DeploymentException("field name " + fieldName + " not found in " + properties); 432 } 433 } 434 QName xmlName = new QName ("", variableMapping.getXmlElementName().getStringValue().trim()); 435 SchemaParticle particle = (SchemaParticle) paramNameToType.get(xmlName); 436 if (null == particle) { 437 xmlName = new QName (ns, variableMapping.getXmlElementName().getStringValue().trim()); 438 particle = (SchemaParticle) paramNameToType.get(xmlName); 439 if (null == particle) { 440 throw new DeploymentException("element " + xmlName + " not found in schema " + schemaType.getName()); 441 } 442 } else if (SchemaParticle.ELEMENT != particle.getParticleType()) { 443 throw new DeploymentException(xmlName + " is not an element in schema " + schemaType.getName()); 444 } 445 elementDesc.setNillable(particle.isNillable() || hasEncoded); 446 elementDesc.setXmlName(xmlName); 447 if (null != particle.getType().getName()) { 448 elementDesc.setXmlType(particle.getType().getName()); 449 } else { 450 QName anonymousName; 451 if (key.isAnonymous()) { 452 anonymousName = new QName (key.getqName().getNamespaceURI(), key.getqName().getLocalPart() + 453 ">" + particle.getName().getLocalPart()); 454 } else { 455 anonymousName = new QName (key.getqName().getNamespaceURI(), 456 ">" + key.getqName().getLocalPart() + ">" + particle.getName().getLocalPart()); 457 } 458 elementDesc.setXmlType(anonymousName); 459 } 460 461 if (javaType.isArray()) { 462 elementDesc.setMinOccurs(particle.getIntMinOccurs()); 463 elementDesc.setMaxOccurs(particle.getIntMaxOccurs()); 464 elementDesc.setMaxOccursUnbounded(particle.getIntMaxOccurs() > 1); 466 } 467 468 fields[i] = elementDesc; 469 } 470 } 471 } 472 473 private static class TypeMappingLookup { 474 private static final TypeMappingImpl SOAP_TM = DefaultSOAPEncodingTypeMappingImpl.getSingleton(); 475 private static final TypeMappingImpl JAXRPC_TM = DefaultJAXRPC11TypeMappingImpl.getSingleton(); 476 477 public static FactoryPair getFactoryPair(QName xmlType) { 478 Class clazz = SOAP_TM.getClassForQName(xmlType, null, null); 479 SerializerFactory sf; 480 DeserializerFactory df; 481 if (null != clazz) { 482 sf = SOAP_TM.getSerializer(clazz, xmlType); 483 df = SOAP_TM.getDeserializer(clazz, xmlType, null); 484 } else { 485 clazz = JAXRPC_TM.getClassForQName(xmlType, null, null); 486 if (null == clazz) { 487 return null; 488 } 489 sf = JAXRPC_TM.getSerializer(clazz, xmlType); 490 df = JAXRPC_TM.getDeserializer(clazz, xmlType, null); 491 } 492 return new FactoryPair(sf.getClass(), df.getClass()); 493 } 494 } 495 496 private static class FactoryPair { 497 private final Class serializerFactoryClass; 498 private final Class deserializerFactoryClass; 499 500 private FactoryPair(Class serializerFactoryClass, Class deserializerFactoryClass) { 501 this.serializerFactoryClass = serializerFactoryClass; 502 this.deserializerFactoryClass = deserializerFactoryClass; 503 } 504 } 505 } 506 | Popular Tags |