/* * 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.ode.jbi.util; import java.net.URI; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.wsdl.Definition; import javax.wsdl.Fault; import javax.wsdl.Import; import javax.wsdl.Input; import javax.wsdl.Message; import javax.wsdl.Operation; import javax.wsdl.Output; import javax.wsdl.Part; import javax.wsdl.PortType; import javax.wsdl.Types; import javax.wsdl.extensions.ExtensibilityElement; import javax.wsdl.extensions.schema.SchemaImport; import javax.wsdl.factory.WSDLFactory; import javax.xml.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.ibm.wsdl.extensions.schema.SchemaImpl; public class WSDLFlattener { private static Log __log = LogFactory.getLog(WSDLFlattener.class); private Definition _definition; private SchemaCollection _schemas; private Map<QName, Definition> _flattened; private boolean _initialized; public WSDLFlattener(Definition definition) { this(definition, null); } public WSDLFlattener(Definition definition, SchemaCollection schemas) { if (definition == null) throw new NullPointerException("Null definition!"); this._definition = definition; this._flattened = new ConcurrentHashMap<QName, Definition>(); this._schemas = schemas; } /** * Parse the schemas referenced by the definition. * @throws Exception if an error occurs */ public void initialize() throws Exception { if (!_initialized) { if (_schemas == null) { this._schemas = new SchemaCollection(getUri(_definition.getDocumentBaseURI())); } parseSchemas(this._definition); _initialized = true; } } /** * Retrieve a flattened definition for a given port type name. * @param portType the port type to create a flat definition for * @return a flat definition for the port type * @throws Exception if an error occurs */ public Definition getDefinition(QName portType) throws Exception { Definition def = (Definition) _flattened.get(portType); if (def == null) { def = flattenDefinition(portType); _flattened.put(portType, def); } return def; } /** * @return Returns the definition. */ public Definition getDefinition() { return _definition; } /** * @param definition The definition to set. */ public void setDefinition(Definition definition) { this._definition = definition; } /** * @return Returns the schemas. */ public SchemaCollection getSchemas() throws Exception { return _schemas; } /** * @param schemas The schemas to set. */ public void setSchemas(SchemaCollection schemas) { this._schemas = schemas; } private Definition flattenDefinition(QName name) throws Exception { // Check that schemas have been loaded initialize(); // Create new definition Definition flat = WSDLFactory.newInstance().newDefinition(); flat.setTargetNamespace(name.getNamespaceURI()); addNamespaces(flat, _definition); // Create port type PortType defPort = _definition.getPortType(name); PortType flatPort = flat.createPortType(); flatPort.setQName(defPort.getQName()); flatPort.setUndefined(false); // Import all operations and related messages for (Iterator itOper = defPort.getOperations().iterator(); itOper.hasNext();) { Operation defOper = (Operation) itOper.next(); Operation flatOper = flat.createOperation(); flatOper.setName(defOper.getName()); flatOper.setStyle(defOper.getStyle()); flatOper.setUndefined(false); if (defOper.getInput() != null) { Input flatInput = flat.createInput(); flatInput.setName(defOper.getInput().getName()); if (defOper.getInput().getMessage() != null) { Message flatInputMsg = copyMessage(defOper.getInput().getMessage(), flat); flatInput.setMessage(flatInputMsg); flat.addMessage(flatInputMsg); } flatOper.setInput(flatInput); } if (defOper.getOutput() != null) { Output flatOutput = flat.createOutput(); flatOutput.setName(defOper.getOutput().getName()); if (defOper.getOutput().getMessage() != null) { Message flatOutputMsg = copyMessage(defOper.getOutput().getMessage(), flat); flatOutput.setMessage(flatOutputMsg); flat.addMessage(flatOutputMsg); } flatOper.setOutput(flatOutput); } for (Iterator itFault = defOper.getFaults().values().iterator(); itFault.hasNext();) { Fault defFault = (Fault) itFault.next(); Fault flatFault = flat.createFault(); flatFault.setName(defFault.getName()); if (defFault.getMessage() != null) { Message flatFaultMsg = copyMessage(defFault.getMessage(), flat); flatFault.setMessage(flatFaultMsg); flat.addMessage(flatFaultMsg); } flatOper.addFault(flatFault); } flatPort.addOperation(flatOper); } // Import schemas in definition if (_schemas.getSize() > 0) { Types types = flat.createTypes(); for (Iterator it = _schemas.getSchemas().iterator(); it.hasNext();) { javax.wsdl.extensions.schema.Schema imp = new SchemaImpl(); imp.setElement(((Schema)it.next()).getRoot()); imp.setElementType(new QName("http://www.w3.org/2001/XMLSchema", "schema")); types.addExtensibilityElement(imp); } flat.setTypes(types); } flat.addPortType(flatPort); return flat; } private void parseSchemas(Definition def) throws Exception { if (def.getTypes() != null && def.getTypes().getExtensibilityElements() != null) { for (Iterator iter = def.getTypes().getExtensibilityElements().iterator(); iter.hasNext();) { ExtensibilityElement element = (ExtensibilityElement) iter.next(); if (element instanceof javax.wsdl.extensions.schema.Schema) { javax.wsdl.extensions.schema.Schema schema = (javax.wsdl.extensions.schema.Schema) element; if (schema.getElement() != null) { _schemas.read(schema.getElement(), getUri(schema.getDocumentBaseURI())); } for (Iterator itImp = schema.getImports().values().iterator(); itImp.hasNext();) { Collection imps = (Collection) itImp.next(); for (Iterator itSi = imps.iterator(); itSi.hasNext();) { SchemaImport imp = (SchemaImport) itSi.next(); _schemas.read(imp.getSchemaLocationURI(), getUri(def.getDocumentBaseURI())); } } } } } if (def.getImports() != null) { for (Iterator itImp = def.getImports().values().iterator(); itImp.hasNext();) { Collection imps = (Collection) itImp.next(); for (Iterator iter = imps.iterator(); iter.hasNext();) { Import imp = (Import) iter.next(); parseSchemas(imp.getDefinition()); } } } } private void addNamespaces(Definition flat, Definition def) { for (Iterator itImport = def.getImports().values().iterator(); itImport.hasNext();) { List defImports = (List) itImport.next(); for (Iterator iter = defImports.iterator(); iter.hasNext();) { Import defImport = (Import) iter.next(); addNamespaces(flat, defImport.getDefinition()); } } for (Iterator itNs = def.getNamespaces().keySet().iterator(); itNs.hasNext();) { String key = (String) itNs.next(); String val = def.getNamespace(key); flat.addNamespace(key, val); } } private Message copyMessage(Message defMessage, Definition flat) { Message flatMsg = flat.createMessage(); flatMsg.setUndefined(false); if (defMessage.getQName() != null) { flatMsg.setQName(new QName(flat.getTargetNamespace(), defMessage.getQName().getLocalPart())); } for (Iterator itPart = defMessage.getParts().values().iterator(); itPart.hasNext();) { Part defPart = (Part) itPart.next(); Part flatPart = flat.createPart(); flatPart.setName(defPart.getName()); flatPart.setElementName(defPart.getElementName()); flatMsg.addPart(flatPart); } return flatMsg; } private URI getUri(String str) { if (str != null) { str = str.replaceAll(" ", "%20"); return URI.create(str); } return null; } }