diff options
author | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-11 23:20:01 +0000 |
---|---|---|
committer | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-11 23:20:01 +0000 |
commit | 9f79c8a050ff86907695027893e56080988c09d8 (patch) | |
tree | ef01b66b4a3ea89480b79fdd194f9694235d559b /sca-java-1.x/tags/2.0-M1/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGenerator.java | |
parent | fdd5b43d3c139cf2cbd1655d2efbfaf9032a5b5e (diff) |
Moving 2.x tags
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@835147 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-java-1.x/tags/2.0-M1/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGenerator.java')
-rw-r--r-- | sca-java-1.x/tags/2.0-M1/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGenerator.java | 841 |
1 files changed, 841 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/2.0-M1/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGenerator.java b/sca-java-1.x/tags/2.0-M1/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGenerator.java new file mode 100644 index 0000000000..ee02632096 --- /dev/null +++ b/sca-java-1.x/tags/2.0-M1/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGenerator.java @@ -0,0 +1,841 @@ +/* + * 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.tuscany.sca.binding.ws.wsdlgen; + +import java.lang.reflect.Method; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.wsdl.Binding; +import javax.wsdl.BindingOperation; +import javax.wsdl.Definition; +import javax.wsdl.Fault; +import javax.wsdl.Input; +import javax.wsdl.Message; +import javax.wsdl.OperationType; +import javax.wsdl.Output; +import javax.wsdl.Part; +import javax.wsdl.PortType; +import javax.wsdl.Types; +import javax.wsdl.WSDLException; +import javax.wsdl.extensions.schema.Schema; +import javax.wsdl.factory.WSDLFactory; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.XMLTypeHelper; +import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; +import org.apache.tuscany.sca.xsd.XSDFactory; +import org.apache.tuscany.sca.xsd.XSDefinition; +import org.apache.ws.commons.schema.XmlSchema; +import org.apache.ws.commons.schema.XmlSchemaCollection; +import org.apache.ws.commons.schema.XmlSchemaException; +import org.apache.ws.commons.schema.utils.NamespaceMap; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @version $Rev: 670103 $ $Date: 2008-06-21 01:35:00 +0100 (Sat, 21 Jun 2008) $ + */ +public class Interface2WSDLGenerator { + private static final Logger logger = Logger.getLogger(Interface2WSDLGenerator.class.getName()); + private static final String SCHEMA_NS = "http://www.w3.org/2001/XMLSchema"; + private static final String SCHEMA_NAME = "schema"; + private static final QName SCHEMA_QNAME = new QName(SCHEMA_NS, SCHEMA_NAME); + private static final String XMLNS_NS = "http://www.w3.org/2000/xmlns/"; + + private static final String ANYTYPE_NAME = "anyType"; + private static final QName ANYTYPE_QNAME = new QName(SCHEMA_NS, ANYTYPE_NAME); + + + private WSDLFactory factory; + private DataBindingExtensionPoint dataBindings; + private WSDLDefinitionGenerator definitionGenerator; + private boolean requiresSOAP12; + private ModelResolver resolver; + private XSDFactory xsdFactory; + private Monitor monitor; + + public Interface2WSDLGenerator(boolean requiresSOAP12, + ModelResolver resolver, + DataBindingExtensionPoint dataBindings, + XSDFactory xsdFactory, + Monitor monitor) throws WSDLException { + super(); + this.requiresSOAP12 = requiresSOAP12; + this.resolver = resolver; + definitionGenerator = new WSDLDefinitionGenerator(requiresSOAP12); + this.dataBindings = dataBindings; + this.xsdFactory = xsdFactory; + this.monitor = monitor; + this.factory = WSDLFactory.newInstance(); + } + + /** + * Log a warning message. + * @param problem + */ + private static void logWarning(Problem problem) { + Logger problemLogger = Logger.getLogger(problem.getSourceClassName(), problem.getBundleName()); + if (problemLogger != null){ + problemLogger.logp(Level.WARNING, problem.getSourceClassName(), null, problem.getMessageId(), problem.getMessageParams()); + } else { + logger.severe("Can't get logger " + problem.getSourceClassName()+ " with bundle " + problem.getBundleName()); + } + } + + /** + * Report a warning. + * @param message + * @param binding + * @param parameters + */ + private void warning(String message, Interface interfaze, String... messageParameters) { + Problem problem = monitor.createProblem(this.getClass().getName(), "wsdlgen-validation-messages", Severity.WARNING, interfaze, message, (Object[])messageParameters); + if (monitor != null) { + monitor.problem(problem); + } else { + logWarning(problem); + } + } + + /** + * Report a fatal error. + * @param message + * @param binding + * @param parameters + */ + private void fatal(String message, Interface interfaze, String... messageParameters) { + Problem problem = monitor.createProblem(this.getClass().getName(), "wsdlgen-validation-messages", Severity.ERROR, interfaze, message, (Object[])messageParameters); + throw new WSDLGenerationException(problem.toString(), null, problem); + } + + private XMLTypeHelper getTypeHelper(DataType type, Map<String, XMLTypeHelper> helpers) { + if (type == null) { + return null; + } + String db = type.getDataBinding(); + if (db == null) { + return null; + } + if ("java:array".equals(db)) { + DataType dt = (DataType)type.getLogical(); + db = dt.getDataBinding(); + } + return helpers.get(db); + } + + private boolean inputTypesCompatible(DataType wrapperType, DataType<List<DataType>> inputType, Map<String, XMLTypeHelper> helpers) { + XMLTypeHelper wrapperHelper = getTypeHelper(wrapperType, helpers); + for (DataType dt : inputType.getLogical()) { + if (getTypeHelper(dt, helpers) != wrapperHelper) { + return false; + } + } + return true; + } + + private boolean outputTypeCompatible(DataType wrapperType, DataType outputType, Map<String, XMLTypeHelper> helpers) { + if (getTypeHelper(outputType, helpers) != getTypeHelper(wrapperType, helpers)) { + return false; + } else { + return true; + } + } + + private void addDataType(Map<XMLTypeHelper, List<DataType>> map, DataType type, Map<String, XMLTypeHelper> helpers) { + if (type == null) { + return; + } + String db = type.getDataBinding(); + if (db == null) { + return; + } + if ("java:array".equals(db)) { + DataType dt = (DataType)type.getLogical(); + db = dt.getDataBinding(); + } + XMLTypeHelper helper = helpers.get(db); + List<DataType> types = map.get(helper); + if (types == null) { + types = new ArrayList<DataType>(); + map.put(helper, types); + } + types.add(type); + } + + private Map<XMLTypeHelper, List<DataType>> getDataTypes(Interface intf, boolean useWrapper, Map<String, XMLTypeHelper> helpers) { + Map<XMLTypeHelper, List<DataType>> dataTypes = new HashMap<XMLTypeHelper, List<DataType>>(); + for (Operation op : intf.getOperations()) { + WrapperInfo wrapper = op.getWrapper(); + DataType dt1 = null; + boolean useInputWrapper = useWrapper & wrapper != null; + if (useInputWrapper) { + dt1 = wrapper.getInputWrapperType(); + useInputWrapper &= inputTypesCompatible(dt1, op.getInputType(), helpers); + } + if (useInputWrapper) { + addDataType(dataTypes, dt1, helpers); + } else { + for (DataType dt : op.getInputType().getLogical()) { + addDataType(dataTypes, dt, helpers); + } + } + + DataType dt2 = null; + boolean useOutputWrapper = useWrapper & wrapper != null; + if (useOutputWrapper) { + dt2 = wrapper.getOutputWrapperType(); + useOutputWrapper &= outputTypeCompatible(dt2, op.getOutputType(), helpers); + } + if (useOutputWrapper) { + addDataType(dataTypes, dt2, helpers); + } else { + dt2 = op.getOutputType(); + addDataType(dataTypes, dt2, helpers); + } + + for (DataType<DataType> dt3 : op.getFaultTypes()) { + DataType dt4 = dt3.getLogical(); + addDataType(dataTypes, dt4, helpers); + } + } + return dataTypes; + } + + + public Definition generate(Interface interfaze, WSDLDefinition wsdlDefinition) throws WSDLException { + if (interfaze == null) { + return null; + } + if (interfaze instanceof WSDLInterface) { + return ((WSDLInterface)interfaze).getWsdlDefinition().getDefinition(); + } + JavaInterface iface = (JavaInterface)interfaze; + if (!interfaze.isRemotable()) { + fatal("InterfaceNotRemotable", interfaze, iface.getName()); + } + QName name = getQName(iface); + Definition definition = factory.newDefinition(); + if (requiresSOAP12) { + definition.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/"); + } else { + definition.addNamespace("SOAP", "http://schemas.xmlsoap.org/wsdl/soap/"); + } + definition.addNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/"); + definition.addNamespace("xs", SCHEMA_NS); + + String namespaceURI = name.getNamespaceURI(); + definition.setTargetNamespace(namespaceURI); + definition.setQName(new QName(namespaceURI, name.getLocalPart() + "Service", name.getPrefix())); + definition.addNamespace(name.getPrefix(), namespaceURI); + + PortType portType = definition.createPortType(); + portType.setQName(name); + Binding binding = definitionGenerator.createBinding(definition, portType); + Map<String, XMLTypeHelper> helpers = new HashMap<String, XMLTypeHelper>(); + Map<QName, List<ElementInfo>> wrappers = new HashMap<QName, List<ElementInfo>>(); + for (Operation op : interfaze.getOperations()) { + javax.wsdl.Operation operation = generateOperation(definition, op, helpers, wrappers); + portType.addOperation(operation); + String action = ((JavaOperation)op).getAction(); + if ((action == null || "".equals(action)) && !op.isWrapperStyle() && op.getWrapper() == null) { + // Bare style + action = "urn:" + op.getName(); + } + BindingOperation bindingOp = definitionGenerator.createBindingOperation(definition, operation, action); + binding.addBindingOperation(bindingOp); + } + portType.setUndefined(false); + definition.addPortType(portType); + binding.setUndefined(false); + definition.addBinding(binding); + wsdlDefinition.setBinding(binding); + + // 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()) { + XMLTypeHelper helper = en.getKey(); + if (helper == null) { + continue; + } + List<XSDefinition> xsDefinitions = helper.getSchemaDefinitions(xsdFactory, resolver, en.getValue()); + for (XSDefinition xsDef: xsDefinitions) { + addSchemaExtension(xsDef, schemaCollection, wsdlDefinition, definition); + } + } + + // remove global wrapper elements with schema definitions from generation list + for (QName wrapperName: new HashSet<QName>(wrappers.keySet())) { + if (wsdlDefinition.getXmlSchemaElement(wrapperName) != null) { + wrappers.remove(wrapperName); + } + } + + // generate schema elements for wrappers that aren't defined in the schemas + if (wrappers.size() > 0) { + int i = 0; + int index = 0; + Map<String, XSDefinition> wrapperXSDs = new HashMap<String, XSDefinition>(); + Map<Element, Map<String, String>> prefixMaps = new HashMap<Element, Map<String, String>>(); + for (Map.Entry<QName, List<ElementInfo>> entry: wrappers.entrySet()) { + String targetNS = entry.getKey().getNamespaceURI(); + Document schemaDoc = null; + Element schema = null; + XSDefinition xsDef = wrapperXSDs.get(targetNS); + if (xsDef != null) { + schemaDoc = xsDef.getDocument(); + schema = schemaDoc.getDocumentElement(); + } else { + schemaDoc = createDocument(); + schema = schemaDoc.createElementNS(SCHEMA_NS, "xs:schema"); + // The elementFormDefault should be set to unqualified, see TUSCANY-2388 + schema.setAttribute("elementFormDefault", "unqualified"); + schema.setAttribute("attributeFormDefault", "qualified"); + schema.setAttribute("targetNamespace", targetNS); + schema.setAttributeNS(XMLNS_NS, "xmlns:xs", SCHEMA_NS); + schemaDoc.appendChild(schema); + Schema schemaExt = createSchemaExt(definition); + schemaExt.setElement(schema); + prefixMaps.put(schema, new HashMap<String, String>()); + xsDef = xsdFactory.createXSDefinition(); + xsDef.setUnresolved(true); + xsDef.setNamespace(targetNS); + xsDef.setDocument(schemaDoc); + // TUSCANY-2465: Set the system id to avoid schema conflict + xsDef.setLocation(URI.create("xsd_" + index + ".xsd")); + index++; + wrapperXSDs.put(targetNS, xsDef); + } + Element wrapper = schemaDoc.createElementNS(SCHEMA_NS, "xs:element"); + schema.appendChild(wrapper); + wrapper.setAttribute("name", entry.getKey().getLocalPart()); + if (entry.getValue().size() == 1 && entry.getValue().get(0).getQName() == null) { + // special case for global fault element + QName typeName = entry.getValue().get(0).getType().getQName(); + String nsURI = typeName.getNamespaceURI(); + if ("".equals(nsURI)) { + wrapper.setAttribute("type", typeName.getLocalPart()); + addSchemaImport(schema, "", schemaDoc); + } else if (targetNS.equals(nsURI)) { + wrapper.setAttribute("type", typeName.getLocalPart()); + } else if (SCHEMA_NS.equals(nsURI)) { + wrapper.setAttribute("type", "xs:" + typeName.getLocalPart()); + } else { + Map<String, String> prefixMap = prefixMaps.get(schema); + String prefix = prefixMap.get(nsURI); + if (prefix == null) { + prefix = "ns" + i++; + prefixMap.put(nsURI, prefix); + schema.setAttributeNS(XMLNS_NS, "xmlns:" + prefix, nsURI); + addSchemaImport(schema, nsURI, schemaDoc); + } + wrapper.setAttribute("type", prefix + ":" + typeName.getLocalPart()); + } + } else { + // normal wrapper containing type definition inline + Element complexType = schemaDoc.createElementNS(SCHEMA_NS, "xs:complexType"); + wrapper.appendChild(complexType); + if (entry.getValue().size() > 0) { + Element sequence = schemaDoc.createElementNS(SCHEMA_NS, "xs:sequence"); + complexType.appendChild(sequence); + for (ElementInfo element: entry.getValue()) { + Element xsElement = schemaDoc.createElementNS(SCHEMA_NS, "xs:element"); + if (element.isMany()) { + xsElement.setAttribute("maxOccurs", "unbounded"); + } + xsElement.setAttribute("minOccurs", "0"); + xsElement.setAttribute("name", element.getQName().getLocalPart()); + if (element.isNillable()) { + xsElement.setAttribute("nillable", "true"); + } + QName typeName = element.getType().getQName(); + String nsURI = typeName.getNamespaceURI(); + if ("".equals(nsURI)) { + xsElement.setAttribute("type", typeName.getLocalPart()); + addSchemaImport(schema, "", schemaDoc); + } else if (SCHEMA_NS.equals(nsURI)) { + xsElement.setAttribute("type", "xs:" + typeName.getLocalPart()); + } else { + Map<String, String> prefixMap = prefixMaps.get(schema); + String prefix = prefixMap.get(nsURI); + if (prefix == null) { + if (targetNS.equals(nsURI)) { + prefix = "tns"; + } else { + prefix = "ns" + i++; + addSchemaImport(schema, nsURI, schemaDoc); + } + prefixMap.put(nsURI, prefix); + schema.setAttributeNS(XMLNS_NS, "xmlns:" + prefix, nsURI); + } + xsElement.setAttribute("type", prefix + ":" + typeName.getLocalPart()); + } + sequence.appendChild(xsElement); + } + } + } + } + + // resolve XSDefinitions containing generated wrappers + for (XSDefinition xsDef: wrapperXSDs.values()) { + loadXSD(schemaCollection, xsDef); + wsdlDefinition.getXmlSchemas().add(xsDef); + } + } + + return definition; + } + + private static void addSchemaImport(Element schema, String nsURI, Document schemaDoc) { + Element imp = schemaDoc.createElementNS(SCHEMA_NS, "xs:import"); + if (!"".equals(nsURI)) { + imp.setAttribute("namespace", nsURI); + } + NodeList childNodes = schema.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node childNode = childNodes.item(i); + if (childNode instanceof Element) { + schema.insertBefore(imp, childNode); + imp = null; + break; + } + } + if (imp != null) { + schema.appendChild(imp); + } + } + + private void addSchemaExtension(XSDefinition xsDef, + XmlSchemaCollection schemaCollection, + WSDLDefinition wsdlDefinition, + Definition definition) throws WSDLException { + if (xsDef.getAggregatedDefinitions() != null) { + for (XSDefinition xsd: xsDef.getAggregatedDefinitions()) { + addSchemaExtension(xsd, schemaCollection, wsdlDefinition, definition); + } + } else { + String nsURI = xsDef.getNamespace(); + Document document = xsDef.getDocument(); + if (document == null) { + try { + NamespaceMap prefixMap = new NamespaceMap(); + prefixMap.add("xs", SCHEMA_NS); + prefixMap.add("tns", nsURI); + XmlSchema schemaDef = xsDef.getSchema(); + schemaDef.setNamespaceContext(prefixMap); + Document[] docs = schemaDef.getAllSchemas(); + document = docs[docs.length-1]; + document.setDocumentURI(xsDef.getLocation().toString()); + xsDef.setDocument(document); + } catch (XmlSchemaException e) { + throw new RuntimeException(e); + } + } + loadXSD(schemaCollection, xsDef); + wsdlDefinition.getXmlSchemas().add(xsDef); + Element schema = document.getDocumentElement(); + Schema schemaExt = createSchemaExt(definition); + schemaExt.setDocumentBaseURI(document.getDocumentURI()); + schemaExt.setElement(schema); + } + } + + private static void loadXSD(XmlSchemaCollection schemaCollection, XSDefinition definition) { + if (definition.getSchema() != null) { + return; + } + if (definition.getDocument() != null) { + String uri = null; + if (definition.getLocation() != null) { + uri = definition.getLocation().toString(); + } + XmlSchema schema = schemaCollection.read(definition.getDocument(), uri, null); + if (definition.getSchemaCollection() == null) { + definition.setSchemaCollection(schemaCollection); + } + if (definition.getSchema() == null) { + definition.setSchema(schema); + } + } + } + + public Schema createSchemaExt(Definition definition) throws WSDLException { + Types types = definition.getTypes(); + if (types == null) { + types = definition.createTypes(); + definition.setTypes(types); + } + + Schema schemaExt = createSchema(definition); + types.addExtensibilityElement(schemaExt); + + return schemaExt; + } + + public Schema createSchema(Definition definition) throws WSDLException { + return (Schema)definition.getExtensionRegistry().createExtension(Types.class, SCHEMA_QNAME); + } + + private DocumentBuilderFactory documentBuilderFactory; + + public Document createDocument() { + Document document; + try { + if (documentBuilderFactory == null) { + documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + } + document = documentBuilderFactory.newDocumentBuilder().newDocument(); + } catch (ParserConfigurationException ex) { + throw new WSDLGenerationException(ex); + } + // document.setDocumentURI("http://"); + return document; + } + + protected QName getQName(Interface interfaze) { + JavaInterface iface = (JavaInterface)interfaze; + QName qname = iface.getQName(); + if (qname != null) { + return qname; + } else { + Class<?> javaClass = iface.getJavaClass(); + return new QName(JavaXMLMapper.getNamespace(javaClass), javaClass.getSimpleName(), "tns"); + } + } + + public javax.wsdl.Operation generateOperation(Definition definition, + Operation op, + Map<String, XMLTypeHelper> helpers, + Map<QName, List<ElementInfo>> wrappers) + throws WSDLException { + javax.wsdl.Operation operation = definition.createOperation(); + operation.setName(op.getName()); + operation.setUndefined(false); + + Input input = definition.createInput(); + Message inputMsg = definition.createMessage(); + String namespaceURI = definition.getQName().getNamespaceURI(); + QName inputMsgName = new QName(namespaceURI, op.getName()); + inputMsg.setQName(inputMsgName); + inputMsg.setUndefined(false); + definition.addMessage(inputMsg); + + List<ElementInfo> elements = null; + // FIXME: By default, java interface is mapped to doc-lit-wrapper style WSDL + if (op.getWrapper() != null) { + // Generate doc-lit-wrapper style + inputMsg.addPart(generateWrapperPart(definition, op, helpers, wrappers, true)); + } else { + // Bare style + int i = 0; + for (DataType d : op.getInputType().getLogical()) { + inputMsg.addPart(generatePart(definition, d, "arg" + i)); + elements = new ArrayList<ElementInfo>(); + ElementInfo element = getElementInfo(d.getPhysical(), d, null, helpers); + elements.add(element); + QName elementName = ((XMLType)d.getLogical()).getElementName(); + wrappers.put(elementName, elements); + i++; + } + } + input.setMessage(inputMsg); + operation.setInput(input); + + if (!op.isNonBlocking()) { + Output output = definition.createOutput(); + Message outputMsg = definition.createMessage(); + QName outputMsgName = new QName(namespaceURI, op.getName() + "Response"); + outputMsg.setQName(outputMsgName); + outputMsg.setUndefined(false); + definition.addMessage(outputMsg); + + if (op.getWrapper() != null) { + outputMsg.addPart(generateWrapperPart(definition, op, helpers, wrappers, false)); + } else { + DataType outputType = op.getOutputType(); + outputMsg.addPart(generatePart(definition, outputType, "return")); + if (outputType != null) { + elements = new ArrayList<ElementInfo>(); + ElementInfo element = getElementInfo(outputType.getPhysical(), outputType, null, helpers); + elements.add(element); + QName elementName = ((XMLType)outputType.getLogical()).getElementName(); + wrappers.put(elementName, elements); + } + } + output.setMessage(outputMsg); + + operation.setOutput(output); + operation.setStyle(OperationType.REQUEST_RESPONSE); + } else { + operation.setStyle(OperationType.ONE_WAY); + } + + for (DataType<DataType> faultType: op.getFaultTypes()) { + Fault fault = definition.createFault(); + QName faultName = ((XMLType)faultType.getLogical().getLogical()).getElementName(); + fault.setName(faultName.getLocalPart()); + Message faultMsg = definition.getMessage(faultName); + if (faultMsg == null) { + faultMsg = definition.createMessage(); + faultMsg.setQName(faultName); + faultMsg.setUndefined(false); + definition.addMessage(faultMsg); + faultMsg.addPart(generatePart(definition, faultType.getLogical(), faultName.getLocalPart())); + } + fault.setMessage(faultMsg); + operation.addFault(fault); + if (faultType.getLogical().getPhysical() != faultType.getPhysical()) { + // create special wrapper for type indirection to real fault bean + DataType logical = faultType.getLogical(); + elements = new ArrayList<ElementInfo>(); + elements.add(getElementInfo(logical.getPhysical(), logical, null, helpers)); + } else { + // convert synthesized fault bean to a wrapper type + for (DataType<XMLType> propDT: op.getFaultBeans().get(faultName)) { + XMLType logical = propDT.getLogical(); + elements = new ArrayList<ElementInfo>(); + elements.add(getElementInfo(propDT.getPhysical(), propDT, logical.getElementName(), helpers)); + } + } + wrappers.put(faultName, elements); + } + + operation.setUndefined(false); + return operation; + } + + public Part generatePart(Definition definition, DataType arg, String partName) { + Part part = definition.createPart(); + part.setName(partName); + if (arg != null && arg.getLogical() instanceof XMLType) { + XMLType xmlType = (XMLType)arg.getLogical(); + QName elementName = xmlType.getElementName(); + part.setElementName(elementName); + addNamespace(definition, elementName); + if (xmlType.getElementName() == null) { + QName typeName = xmlType.getTypeName(); + part.setTypeName(typeName); + addNamespace(definition, typeName); + } + } + return part; + } + + public Part generateWrapperPart(Definition definition, + Operation operation, + Map<String, XMLTypeHelper> helpers, + Map<QName, List<ElementInfo>> wrappers, + boolean input) throws WSDLException { + Part part = definition.createPart(); + String partName = input ? operation.getName() : (operation.getName() + "Response"); + part.setName(partName); + WrapperInfo opWrapper = operation.getWrapper(); + if (opWrapper != null) { + ElementInfo elementInfo = + input ? opWrapper.getInputWrapperElement() : opWrapper.getOutputWrapperElement(); + List<ElementInfo> elements = + input ? opWrapper.getInputChildElements() : opWrapper.getOutputChildElements(); + QName wrapperName = elementInfo.getQName(); + part.setElementName(wrapperName); + addNamespace(definition, wrapperName); + wrappers.put(wrapperName, elements); + + // FIXME: [rfeng] Ideally, we should try to register the wrappers only. But we are + // expriencing the problem that we cannot handle XSD imports + /* + Class<?> wrapperClass = input ? opWrapper.getInputWrapperClass() : opWrapper.getOutputWrapperClass(); + DataType wrapperDT = input ? opWrapper.getInputWrapperType() : opWrapper.getOutputWrapperType(); + if (wrapperClass != null) { + getElementInfo(wrapperClass, wrapperDT, wrapperName, helpers); + return part; + } + */ + + Method method = ((JavaOperation)operation).getJavaMethod(); + if (input) { + Class<?>[] paramTypes = method.getParameterTypes(); + for (int i = 0; i < paramTypes.length; i++) { + DataType dataType = operation.getInputType().getLogical().get(i); + elements.set(i, getElementInfo(paramTypes[i], dataType, elements.get(i).getQName(), helpers)); + } + } else { + Class<?> returnType = method.getReturnType(); + if (returnType != Void.TYPE) { + DataType dataType = operation.getOutputType(); + elements.set(0, getElementInfo(returnType, dataType, elements.get(0).getQName(), helpers)); + } + } + } + return part; + } + + private ElementInfo getElementInfo(Class javaType, + DataType dataType, + QName name, + Map<String, XMLTypeHelper> helpers) { + String db = dataType.getDataBinding(); + while ("java:array".equals(db)) { + dataType = (DataType)dataType.getLogical(); + db = dataType.getDataBinding(); + } + XMLTypeHelper helper = helpers.get(db); + if (helper == null) { + DataBinding dataBinding = dataBindings.getDataBinding(db); + if (dataBinding == null) { + QName element = name; + if (element == null || dataType.getLogical() instanceof XMLType) { + XMLType xmlType = (XMLType)dataType.getLogical(); + if (xmlType.getElementName() != null) { + element = xmlType.getElementName(); + } + } + return new ElementInfo(element, new TypeInfo(ANYTYPE_QNAME, false, null)); + // throw new ServiceRuntimeException("No data binding for " + db); + } + + helper = dataBinding.getXMLTypeHelper(); + if (helper == null) { + // Default to JAXB + helper = helpers.get(JAXBDataBinding.NAME); + if (helper == null) { + helper = dataBindings.getDataBinding(JAXBDataBinding.NAME).getXMLTypeHelper(); + helpers.put(JAXBDataBinding.NAME, helper); + } + } + helpers.put(db, helper); + } + TypeInfo typeInfo = helper.getTypeInfo(javaType.isArray() ? javaType.getComponentType() : javaType, + dataType.getLogical()); + ElementInfo element = new ElementInfo(name, typeInfo); + element.setMany(byte[].class != javaType && javaType.isArray()); + element.setNillable(!javaType.isPrimitive()); + return element; + } + + private static void addNamespace(Definition definition, QName name) { + String namespace = name.getNamespaceURI(); + if (definition.getPrefix(namespace) == null) { + definition.addNamespace("ns" + definition.getNamespaces().size(), namespace); + } + } + + /* + // currently not using the next three methods + public XmlSchemaType getXmlSchemaType(DataType type) { + return null; + } + + // FIXME: WE need to add databinding-specific Java2XSD generation + public Element generateXSD(DataType dataType) { + DataBinding dataBinding = dataBindings.getDataBinding(dataType.getDataBinding()); + if (dataBinding != null) { + // return dataBinding.generateSchema(dataType); + } + return null; + } + + public void generateWrapperElements(Operation op) { + XmlSchemaCollection collection = new XmlSchemaCollection(); + String ns = getQName(op.getInterface()).getNamespaceURI(); + XmlSchema schema = new XmlSchema(ns, collection); + schema.setAttributeFormDefault(new XmlSchemaForm(XmlSchemaForm.QUALIFIED)); + schema.setElementFormDefault(new XmlSchemaForm(XmlSchemaForm.QUALIFIED)); + + XmlSchemaElement inputElement = new XmlSchemaElement(); + inputElement.setQName(new QName(ns, op.getName())); + XmlSchemaComplexType inputType = new XmlSchemaComplexType(schema); + inputType.setName(""); + XmlSchemaSequence inputSeq = new XmlSchemaSequence(); + inputType.setParticle(inputSeq); + List<DataType> argTypes = op.getInputType().getLogical(); + for (DataType argType : argTypes) { + XmlSchemaElement child = new XmlSchemaElement(); + Object logical = argType.getLogical(); + if (logical instanceof XMLType) { + child.setName(((XMLType)logical).getElementName().getLocalPart()); + XmlSchemaType type = getXmlSchemaType(argType); + child.setType(type); + } + inputSeq.getItems().add(child); + } + inputElement.setType(inputType); + + XmlSchemaElement outputElement = new XmlSchemaElement(); + outputElement.setQName(new QName(ns, op.getName() + "Response")); + XmlSchemaComplexType outputType = new XmlSchemaComplexType(schema); + outputType.setName(""); + XmlSchemaSequence outputSeq = new XmlSchemaSequence(); + outputType.setParticle(outputSeq); + DataType returnType = op.getOutputType(); + XmlSchemaElement child = new XmlSchemaElement(); + Object logical = returnType.getLogical(); + if (logical instanceof XMLType) { + child.setName(((XMLType)logical).getElementName().getLocalPart()); + XmlSchemaType type = getXmlSchemaType(returnType); + child.setType(type); + } + outputSeq.getItems().add(child); + outputElement.setType(outputType); + + schema.getElements().add(inputElement.getQName(), inputElement); + schema.getElements().add(outputElement.getQName(), outputElement); + + } + */ + + public WSDLFactory getFactory() { + return factory; + } + + public void setFactory(WSDLFactory factory) { + this.factory = factory; + } + +} |