/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.modelgenerator.wsdl.model.impl; import java.net.URI; import java.net.URL; import java.text.MessageFormat; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.wsdl.BindingFault; import javax.wsdl.BindingInput; import javax.wsdl.BindingOutput; import javax.wsdl.Definition; import javax.wsdl.Input; import javax.wsdl.OperationType; import javax.wsdl.Output; import javax.wsdl.WSDLException; import javax.wsdl.extensions.http.HTTPAddress; import javax.wsdl.extensions.soap.SOAPAddress; import javax.wsdl.extensions.soap.SOAPBinding; import javax.wsdl.extensions.soap.SOAPBody; import javax.wsdl.extensions.soap.SOAPOperation; import javax.wsdl.extensions.soap12.SOAP12Address; import javax.wsdl.extensions.soap12.SOAP12Operation; import javax.xml.namespace.QName; import org.eclipse.xsd.XSDSchema; import org.teiid.designer.modelgenerator.wsdl.ModelGeneratorWsdlPlugin; import org.teiid.designer.modelgenerator.wsdl.SoapBindingInfo; import org.teiid.designer.modelgenerator.wsdl.TableBuilder; import org.teiid.designer.modelgenerator.wsdl.model.Binding; import org.teiid.designer.modelgenerator.wsdl.model.Fault; import org.teiid.designer.modelgenerator.wsdl.model.Message; import org.teiid.designer.modelgenerator.wsdl.model.Model; import org.teiid.designer.modelgenerator.wsdl.model.Operation; import org.teiid.designer.modelgenerator.wsdl.model.Part; import org.teiid.designer.modelgenerator.wsdl.model.Port; import org.teiid.designer.modelgenerator.wsdl.model.Service; import org.teiid.designer.modelgenerator.wsdl.util.ExtendedWSDLReader; import org.teiid.designer.modelgenerator.wsdl.util.WSDLSchemaExtractor; import org.teiid.designer.schema.tools.processing.SchemaProcessor; import org.teiid.designer.schema.tools.processing.internal.SchemaProcessorImpl; import org.teiid.designer.ui.common.ICredentialsCommon.SecurityType; import com.ibm.wsdl.ImportImpl; /** * This class generates a lightweight model of the WSDL file leaving out a lot of the things from the javax.wsdl model and even * more from the eclipse emf wsdl model It uses IBM's WSDL4J model to build our own model Its lightweight to avoid memory * consumption problems that were seen in the schema importer The usage model is as follows: String myWSDL = "c:\temp\my.wsdl"; * ModelBuilder builder = new ModelBuilder(); builder.setWSDL(myWSDL); if(!builder.isWSDLParsed()) { WSDLException myEx = * builder.getWSDLException(); handleExceptionInSomeWay(myEx); } Model wsdlModel = builder.getModel(); * * @since 8.0 */ public class ModelBuilder { private String m_wsdlURI; private SecurityType m_securityType = SecurityType.None; private String m_userName; private String m_password; private Definition m_wsdlDef; private Exception m_wsdlException; private XSDSchema[] m_schemas; private WSDLSchemaExtractor extractor; private static String DEFAULT_STYLE = "document"; //$NON-NLS-1$ public ModelBuilder() { } public void setAuthentication(SecurityType securityType, String userName, String password) { m_securityType = securityType; m_userName = userName; m_password = password; m_wsdlDef = null; } public void setWSDL( String wsdlUri ) { m_wsdlURI = wsdlUri; try { m_wsdlDef = getDefinition(); } catch (WSDLException wx) { m_wsdlDef = null; m_wsdlException = wx; } extractor = new WSDLSchemaExtractor(); } private ExtendedWSDLReader getWSDLReader() { return new ExtendedWSDLReader(); } private Definition getDefinition() throws WSDLException { ExtendedWSDLReader reader = getWSDLReader(); Definition def; if (SecurityType.None.equals(m_securityType)) { def = reader.readWSDL(m_wsdlURI); } else if (SecurityType.Digest.equals(m_securityType)) { def = reader.readWSDLWithDigest(null, m_wsdlURI, m_userName, m_password); } else { def = reader.readWSDL(m_wsdlURI, m_userName, m_password); } return def; } public boolean isWSDLParsed() { return !(m_wsdlDef == null); } public Exception getWSDLException() { return m_wsdlException; } public Model getModel() throws Exception { // wsdl isn't set or can't be read if (m_wsdlDef == null) return null; Model theModel = createModel(); return theModel; } private Model createModel() throws Exception { Model theModel = new ModelImpl(); Map namespaceMap = m_wsdlDef.getNamespaces(); theModel.setNamespaces(namespaceMap); extractor.findSchema(m_wsdlURI, m_securityType, m_userName, m_password); // Get the embedded schema from imported WSDLs extractImportedWSDL(m_wsdlDef); m_schemas = extractor.getSchemas(); setSchemaModel(); theModel.setSchemas(m_schemas); Service[] svcs = createServices(getServices(), theModel); theModel.setServices(svcs); return theModel; } private void extractImportedWSDL( Definition def ) throws Exception { Map imports = def.getImports(); if (!imports.isEmpty()) { Set keys = imports.keySet(); for (Iterator iter = keys.iterator(); iter.hasNext();) { String namespace = (String)iter.next(); List importImpls = (List)imports.get(namespace); for (Iterator itera = importImpls.iterator(); itera.hasNext();) { ImportImpl impImpl = (ImportImpl)itera.next(); Definition imported = impImpl.getDefinition(); URI baseURI = new URI(imported.getDocumentBaseURI()); URL baseURL = baseURI.toURL(); extractor.findSchema(baseURL.toString(), m_securityType, m_userName, m_password); extractImportedWSDL(imported); } } } } private Map getServices() { Map services = m_wsdlDef.getServices(); Map imports = m_wsdlDef.getImports(); if (!imports.isEmpty()) { Set keys = imports.keySet(); for (Iterator iter = keys.iterator(); iter.hasNext();) { String namespace = (String)iter.next(); List importImpls = (List)imports.get(namespace); for (Iterator itera = importImpls.iterator(); itera.hasNext();) { ImportImpl impImpl = (ImportImpl)itera.next(); Map importedServices = impImpl.getDefinition().getServices(); services.putAll(importedServices); } } } return services; } private Service[] createServices( Map services, Model theModel ) { Service[] retVal = new Service[services.size()]; int arrayCtr = 0; Iterator keyIter = services.keySet().iterator(); while (keyIter.hasNext()) { QName key = (QName)keyIter.next(); ServiceImpl impl = new ServiceImpl(); impl.setModel(theModel); javax.wsdl.Service svc = (javax.wsdl.Service)services.get(key); impl.setId(key.toString()); impl.setName(key.getLocalPart()); impl.setNamespaceURI(key.getNamespaceURI()); impl.setPorts(getPortsForService(impl, svc.getPorts())); retVal[arrayCtr++] = impl; } return retVal; } private Port[] getPortsForService( Service service, Map ports ) { Port[] retVal = new Port[ports.size()]; int arrayCtr = 0; String bindingTypeURI = null; Iterator qnameIter = ports.keySet().iterator(); while (qnameIter.hasNext()) { String name = (String)qnameIter.next(); PortImpl port = new PortImpl(service); javax.wsdl.Port pt = (javax.wsdl.Port)ports.get(name); port.setId(name); port.setName(name); port.setNamespaceURI(service.getNamespaceURI()); List port_extens_elements = pt.getExtensibilityElements(); Iterator p_iter = port_extens_elements.iterator(); while (p_iter.hasNext()) { Object pe_next = p_iter.next(); if (pe_next instanceof SOAPAddress) { SOAPAddress address = (SOAPAddress)pe_next; bindingTypeURI = address.getElementType().getNamespaceURI(); port.setBindingTypeURI(bindingTypeURI); port.setLocationURI(address.getLocationURI()); } else { if (pe_next instanceof SOAP12Address) { SOAP12Address address = (SOAP12Address)pe_next; bindingTypeURI = address.getElementType().getNamespaceURI(); port.setBindingTypeURI(bindingTypeURI); port.setLocationURI(address.getLocationURI()); } else { if (pe_next instanceof HTTPAddress) { HTTPAddress address = (HTTPAddress)pe_next; bindingTypeURI = address.getElementType().getNamespaceURI(); port.setBindingTypeURI(bindingTypeURI); port.setLocationURI(address.getLocationURI()); } } } } Binding binding = new BindingImpl(port); javax.wsdl.Binding bind = pt.getBinding(); binding.setId(bind.getQName().toString()); binding.setName(bind.getQName().getLocalPart()); List extens = bind.getExtensibilityElements(); Iterator iter = extens.iterator(); while (iter.hasNext()) { Object next = iter.next(); if (next instanceof SOAPBinding) { SOAPBinding soap = (SOAPBinding)next; binding.setTransportURI(soap.getTransportURI()); binding.setStyle(soap.getStyle()); } } binding.setOperations(getOperationsForBinding(binding, bind.getBindingOperations())); port.setBinding(binding); retVal[arrayCtr++] = port; } return retVal; } private Operation[] getOperationsForBinding( Binding binding, List operations ) { Operation[] retVal = new Operation[operations.size()]; int arrayPtr = 0; Iterator opIter = operations.iterator(); while (opIter.hasNext()) { javax.wsdl.BindingOperation boper = (javax.wsdl.BindingOperation)opIter.next(); javax.wsdl.Operation oper = boper.getOperation(); Operation operation = new OperationImpl(binding); operation.setId(binding.getId() + "." + oper.getName()); //$NON-NLS-1$ operation.setName(oper.getName()); OperationType style = oper.getStyle(); if (style != null) operation.setStyle(style.toString()); operation.setInputMessage(getInputMessageForOperation(operation, oper.getInput(), boper.getBindingInput())); if (oper.getOutput() != null) { operation.setOutputMessage(getOutputMessageForOperation(operation, oper.getOutput(), boper.getBindingOutput())); } Map faults = oper.getFaults(); Map bFaults = boper.getBindingFaults(); operation.setFaults(getFaultsForOperation(operation, faults, bFaults)); List elems = boper.getExtensibilityElements(); for (Iterator iter = elems.iterator(); iter.hasNext();) { Object next = iter.next(); if (next instanceof SOAPOperation) { SOAPOperation soapO = (SOAPOperation)next; operation.setSOAPAction(soapO.getSoapActionURI()); // sometimes the style is specified on the soap operation if (binding.getStyle() == null) { String soapStyle = soapO.getStyle(); if (soapStyle != null) { binding.setStyle(soapStyle); } } } else if (next instanceof SOAP12Operation) { SOAP12Operation soapO = (SOAP12Operation)next; operation.setSOAPAction(soapO.getSoapActionURI()); // sometimes the style is specified on the soap operation if (binding.getStyle() == null) { String soapStyle = soapO.getStyle(); if (soapStyle != null) { binding.setStyle(soapStyle); } } } } if (operation.getBinding().getStyle() == null) { //Per the spec, if the binding style is not set (rpc or document) //the default should be "document". //see http://www.w3.org/TR/wsdl#_soap:binding operation.getBinding().setStyle(DEFAULT_STYLE); createBindingInfo(operation); } retVal[arrayPtr++] = operation; } return retVal; } private Fault[] getFaultsForOperation( Operation operation, Map faults, Map bindingFaults ) { Fault[] faultArr = new Fault[faults.size()]; Iterator faultIter = faults.keySet().iterator(); Iterator faultBIter = bindingFaults.keySet().iterator(); int ctr = 0; while (faultIter.hasNext()) { Object key = faultIter.next(); Object bKey = faultBIter.next(); javax.wsdl.Fault fault = (javax.wsdl.Fault)faults.get(key); BindingFault bFault = (BindingFault)bindingFaults.get(bKey); Fault newFault = new FaultImpl(operation); newFault.setName(fault.getName()); newFault.setId(fault.getName()); Message message = new MessageImpl(newFault); javax.wsdl.Message msg = fault.getMessage(); message.setName(newFault.getName()); message.setId(msg.getQName().toString()); message.setType(Message.FAULT_TYPE); List elems = bFault.getExtensibilityElements(); for (Iterator iter = elems.iterator(); iter.hasNext();) { Object next = iter.next(); if (next instanceof SOAPBody) { SOAPBody body = (SOAPBody)next; if (body.getEncodingStyles() != null) { StringBuffer buff = new StringBuffer(); for (Iterator encIter = body.getEncodingStyles().iterator(); encIter.hasNext();) { buff.append(encIter.next().toString()); buff.append(" "); //$NON-NLS-1$ } message.setEncodingStyle(buff.toString().trim()); } message.setUse(body.getUse()); message.setNamespaceURI(body.getNamespaceURI()); if (body.getNamespaceURI() != null && !body.getNamespaceURI().equals("")) { //$NON-NLS-1$ Model theModel = operation.getBinding().getPort().getService().getModel(); theModel.addNamespaceToMap(body.getNamespaceURI()); } } } Part[] parts = getPartsForMessage(message, msg.getParts()); message.setParts(parts); newFault.setMessage(message); faultArr[ctr++] = newFault; } return faultArr; } private Message getInputMessageForOperation( Operation operation, Input input, BindingInput bIn ) { Message inputMessage = new MessageImpl(operation); javax.wsdl.Message message = input.getMessage(); inputMessage.setName(message.getQName().getLocalPart()); inputMessage.setId(message.getQName().toString()); inputMessage.setType(Message.REQUEST_TYPE); List elems = bIn.getExtensibilityElements(); for (Iterator iter = elems.iterator(); iter.hasNext();) { Object next = iter.next(); if (next instanceof SOAPBody) { SOAPBody body = (SOAPBody)next; if (body.getEncodingStyles() != null) { StringBuffer buff = new StringBuffer(); for (Iterator encIter = body.getEncodingStyles().iterator(); encIter.hasNext();) { buff.append(encIter.next().toString()); buff.append(" "); //$NON-NLS-1$ } inputMessage.setEncodingStyle(buff.toString().trim()); } inputMessage.setUse(body.getUse()); inputMessage.setNamespaceURI(body.getNamespaceURI()); if (body.getNamespaceURI() != null && !body.getNamespaceURI().equals("")) { //$NON-NLS-1$ Model theModel = operation.getBinding().getPort().getService().getModel(); theModel.addNamespaceToMap(body.getNamespaceURI()); } } } Part[] parts = getPartsForMessage(inputMessage, message.getParts()); inputMessage.setParts(parts); return inputMessage; } private Message getOutputMessageForOperation( Operation operation, Output output, BindingOutput bOut ) { Message outputMessage = new MessageImpl(operation); javax.wsdl.Message message = output.getMessage(); outputMessage.setName(message.getQName().getLocalPart()); outputMessage.setId(message.getQName().toString()); outputMessage.setType(Message.RESPONSE_TYPE); List elems = bOut.getExtensibilityElements(); for (Iterator iter = elems.iterator(); iter.hasNext();) { Object next = iter.next(); if (next instanceof SOAPBody) { SOAPBody body = (SOAPBody)next; if (body.getEncodingStyles() != null) { StringBuffer buff = new StringBuffer(); for (Iterator encIter = body.getEncodingStyles().iterator(); encIter.hasNext();) { buff.append(encIter.next().toString()); buff.append(" "); //$NON-NLS-1$ } outputMessage.setEncodingStyle(buff.toString().trim()); } outputMessage.setUse(body.getUse()); outputMessage.setNamespaceURI(body.getNamespaceURI()); if (body.getNamespaceURI() != null && !body.getNamespaceURI().equals("")) { //$NON-NLS-1$ Model theModel = operation.getBinding().getPort().getService().getModel(); theModel.addNamespaceToMap(body.getNamespaceURI()); } } } Part[] parts = getPartsForMessage(outputMessage, message.getParts()); outputMessage.setParts(parts); return outputMessage; } private Part[] getPartsForMessage( Message msg, Map parts ) { Part[] partArr = new Part[parts.size()]; int ctr = 0; Iterator partIter = parts.keySet().iterator(); while (partIter.hasNext()) { Object key = partIter.next(); javax.wsdl.Part part = (javax.wsdl.Part)parts.get(key); Part newPart = new PartImpl(msg); newPart.setName(part.getName()); newPart.setId(part.getName()); if (part.getElementName() != null) { newPart.setElementName(part.getElementName().getLocalPart()); newPart.setElementNamespace(part.getElementName().getNamespaceURI()); } if (part.getTypeName() != null) { newPart.setTypeName(part.getTypeName().getLocalPart()); newPart.setTypeNamespace(part.getTypeName().getNamespaceURI()); } Operation oper; if (newPart.getMessage().getFault() == null) { oper = newPart.getMessage().getOperation(); } else { oper = newPart.getMessage().getFault().getOperation(); } if (!resolvePart(newPart)) { oper.setCanModel(false); String message = ModelGeneratorWsdlPlugin.Util.getString("ModelBuilder.cannot.resolve.element"); //$NON-NLS-1$ String fMsg = MessageFormat.format(message, newPart.getName(), newPart.getMessage().getName()); oper.addProblemMessage(fMsg); } partArr[ctr++] = newPart; } return partArr; } private void setSchemaModel() throws Exception { // process the schemas and get the schema model SchemaProcessor processor = new SchemaProcessorImpl(null); processor.representTypes(true); processor.processSchemas(m_schemas); processor.getSchemaModel(); } private boolean resolvePart( Part newPart ) { String elementNS = newPart.getElementNamespace(); String typeNS = newPart.getTypeNamespace(); // schema types are always good if (TableBuilder.XML_SCHEMA_URI.equalsIgnoreCase(elementNS) || TableBuilder.XML_SCHEMA_URI.equalsIgnoreCase(typeNS)) { return true; } boolean resolved = false; for (int i = 0; i < m_schemas.length; i++) { String tns = m_schemas[i].getTargetNamespace(); if (null != tns) { if (tns.equals(typeNS)) resolved = true; if (tns.equals(elementNS)) resolved = true; } } return resolved; } private void createBindingInfo( Operation oper ) { Binding bind = oper.getBinding(); Port targetport = bind.getPort(); SoapBindingInfo info = new SoapBindingInfo(); // info.setDestinationURL(bind.getTransportURI()); info.setDestinationURL(targetport.getLocationURI()); String docType = bind.getStyle(); String encType = oper.getInputMessage().getEncodingStyle(); if (docType.equalsIgnoreCase("RPC")) { //$NON-NLS-1$ if (encType != null) { info.setStyle(SoapBindingInfo.STYLE_RPC_ENCODED); } else { info.setStyle(SoapBindingInfo.STYLE_RPC_LITERAL); } } else { if (encType != null) { info.setStyle(SoapBindingInfo.STYLE_DOCUMENT_ENCODED); } else { info.setStyle(SoapBindingInfo.STYLE_DOCUMENT_LITERAL); } } info.setOperationName(oper.getBinding().getPort().getService().getName()); oper.setSoapBindingInfo(info); } }