package org.fireflow.service.webservice; import java.io.File; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.util.Iterator; import java.util.List; import java.util.Vector; import javax.wsdl.Definition; import javax.wsdl.Input; import javax.wsdl.Message; import javax.wsdl.Operation; import javax.wsdl.Output; import javax.wsdl.Part; import javax.wsdl.Types; import javax.wsdl.WSDLException; import javax.wsdl.extensions.ExtensibilityElement; import javax.wsdl.extensions.schema.Schema; import javax.wsdl.factory.WSDLFactory; import javax.wsdl.xml.WSDLReader; import javax.xml.namespace.QName; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ws.commons.schema.XmlSchemaCollection; import org.apache.ws.commons.schema.resolver.DefaultURIResolver; import org.apache.ws.commons.schema.resolver.URIResolver; import org.fireflow.model.InvalidModelException; import org.fireflow.model.data.impl.InputImpl; import org.fireflow.model.data.impl.OutputImpl; import org.fireflow.model.servicedef.ServiceDef; import org.fireflow.model.servicedef.impl.AbstractServiceDef; import org.fireflow.model.servicedef.impl.CommonInterfaceDef; import org.fireflow.model.servicedef.impl.OperationDefImpl; import org.w3c.dom.Element; import org.xml.sax.InputSource; import com.ibm.wsdl.factory.WSDLFactoryImpl; public class WebServiceDef extends AbstractServiceDef implements ServiceDef { /** * */ private static final long serialVersionUID = 3168927065098105863L; private static final Log log = LogFactory.getLog(WebServiceDef.class); protected static final String SCHEMA_FILE_PREFIX = "wsdl_schema_"; protected static final String CLASSPATH_URL_PREFIX = "classpath:"; protected String wsdlURLString = null; protected Definition wsdlDefinition = null; protected String portName = null; public void setPortName(String portName) { this.portName = portName; } public String getPortName() { return this.portName; } public String getWsdlURL() { return wsdlURLString; } public void setWsdlURL(String wsdlURL) { this.wsdlURLString = wsdlURL; } public Definition getWsdlDefinition() { return wsdlDefinition; } protected Definition resolveWsdlDefinition(String urlStr) throws InvalidModelException { String _urlString = urlStr; if (urlStr.toLowerCase().startsWith(CLASSPATH_URL_PREFIX)) { String tmpStr = urlStr.substring(CLASSPATH_URL_PREFIX.length()); URL url = WebServiceDef.class.getResource(tmpStr); if (url == null) { throw new InvalidModelException( "The wsdl can NOT be found at path[" + urlStr + "]"); } _urlString = url.toString(); } WSDLFactory factory = new WSDLFactoryImpl(); WSDLReader reader = factory.newWSDLReader(); Definition implDef = null; try { implDef = reader.readWSDL(_urlString); } catch (WSDLException e) { log.error("Can NOT read wsdl from " + _urlString, e); throw new InvalidModelException("Can NOT read wsdl from path[" + urlStr + "]", e); } return implDef; } public void afterPropertiesSet() throws InvalidModelException { this.invokerClassName = "org.fireflow.service.webservice.WebServiceCallerInvoker"; if (!StringUtils.isEmpty(wsdlURLString)) { wsdlDefinition = resolveWsdlDefinition(wsdlURLString); } else { throw new InvalidModelException( "The wsdl url of a web service can NOT be empty."); } if (wsdlDefinition != null) { // 1、构建interface buildInterfaceInfo(); // 2、构建XmlSchemaCollection buildSchemaInfo(); } } private void buildSchemaInfo() { XmlSchemaCollection schemaCollection = new XmlSchemaCollection(); URIResolver originalURIResolver = schemaCollection.getSchemaResolver(); WsdlSchemaURIResolver uriResolver = new WsdlSchemaURIResolver(); schemaCollection.setSchemaResolver(uriResolver); schemaCollection.setBaseUri(wsdlDefinition.getDocumentBaseURI()); Types types = wsdlDefinition.getTypes(); if (types != null) { Vector<Schema> schemaExtElemList = findExtensibilityElement(types .getExtensibilityElements()); for (int i = 0; i < schemaExtElemList.size(); i++) { Schema schemaElement = schemaExtElemList.elementAt(i); Element w3cSchemaElement = schemaElement.getElement(); //Map imports = schemaElement.getImports(); schemaCollection.read(w3cSchemaElement, SCHEMA_FILE_PREFIX + i + ".xsd"); // schemaCollection.read(w3cSchemaElement); } } this.setXmlSchemaCollection(schemaCollection); } private static Vector<Schema> findExtensibilityElement( List extensibilityElements) { Vector<Schema> elements = new Vector<Schema>(); if (extensibilityElements != null) { Iterator iter = extensibilityElements.iterator(); while (iter.hasNext()) { ExtensibilityElement elment = (ExtensibilityElement) iter .next(); if (elment instanceof Schema) { elements.add((Schema) elment); } } } return elements; } private void buildInterfaceInfo() { String targetNsUri = wsdlDefinition.getTargetNamespace(); QName serviceQName = new QName(targetNsUri, this.getName()); javax.wsdl.Service wsdlService = wsdlDefinition .getService(serviceQName); javax.wsdl.Port wsdlPort = wsdlService.getPort(this.getPortName()); javax.wsdl.PortType wsdlPortType = wsdlPort.getBinding().getPortType(); QName portTypeQName = wsdlPortType.getQName(); CommonInterfaceDef commonInterface = new CommonInterfaceDef(); // commonInterface.setNamespaceUri(portTypeQName.getNamespaceURI()); commonInterface.setName(portTypeQName.getLocalPart()); List wsdlOperationList = wsdlPortType.getOperations(); for (int i = 0; i < wsdlOperationList.size(); i++) { Operation wsdlOp = (Operation) wsdlOperationList.get(i); OperationDefImpl op = new OperationDefImpl(); op.setOperationName(wsdlOp.getName()); Input wsdlInput = wsdlOp.getInput(); Message wsdlInputMessage = wsdlInput.getMessage(); List<Part> wsdlMessageParts = wsdlInputMessage .getOrderedParts(null); for (Part part : wsdlMessageParts) { InputImpl input = new InputImpl(); input.setName(part.getName()); input.setDisplayName(part.getName()); if (part.getElementName() != null) { input.setDataType(part.getElementName()); } else { input.setDataType(part.getTypeName()); } op.getInputs().add(input); } Output wsdlOutput = wsdlOp.getOutput(); Message wsdlOutputMessage = wsdlOutput.getMessage(); List<Part> wsdlOutputParts = wsdlOutputMessage .getOrderedParts(null); for (Part part : wsdlOutputParts) { OutputImpl output = new OutputImpl(); output.setName(part.getName()); if (part.getElementName() != null) { output.setDataType(part.getElementName()); } else { part.getTypeName(); } op.getOutputs().add(output); } commonInterface.getOperations().add(op); } this.setInterface(commonInterface); } } class WsdlSchemaURIResolver extends DefaultURIResolver { public InputSource resolveEntity(String namespace, String schemaLocation, String baseUri) { if (baseUri != null && baseUri.startsWith(WebServiceDef.SCHEMA_FILE_PREFIX)) { String ref = null; return this.resolveEntity(namespace, schemaLocation, this.getCollectionBaseURI()); } else if (baseUri != null) { try { File baseFile = null; try { URI uri = new URI(baseUri); baseFile = new File(uri); if (!baseFile.exists()) { baseFile = new File(baseUri); } } catch (Throwable ex) { baseFile = new File(baseUri); } if (baseFile != null && baseFile.exists()) { baseUri = baseFile.toURI().toString(); } else if (this.getCollectionBaseURI() != null) { baseFile = new File(this.getCollectionBaseURI()); if (baseFile.exists()) { baseUri = baseFile.toURI().toString(); } } String ref = new URL(new URL(baseUri), schemaLocation) .toString(); return new InputSource(ref); } catch (MalformedURLException e1) { throw new RuntimeException(e1); } } return new InputSource(schemaLocation); } }