001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.common.tools.wsdl;
018
019 import java.net.URI;
020 import java.util.Collection;
021 import java.util.HashMap;
022 import java.util.Iterator;
023 import java.util.List;
024 import java.util.Map;
025
026 import javax.wsdl.Definition;
027 import javax.wsdl.Fault;
028 import javax.wsdl.Import;
029 import javax.wsdl.Input;
030 import javax.wsdl.Message;
031 import javax.wsdl.Operation;
032 import javax.wsdl.Output;
033 import javax.wsdl.Part;
034 import javax.wsdl.PortType;
035 import javax.wsdl.Types;
036 import javax.wsdl.extensions.ExtensibilityElement;
037 import javax.wsdl.extensions.schema.SchemaImport;
038 import javax.wsdl.factory.WSDLFactory;
039 import javax.xml.namespace.QName;
040
041 import com.ibm.wsdl.extensions.schema.SchemaImpl;
042
043 public class WSDLFlattener {
044
045 private Definition definition;
046 private SchemaCollection schemas;
047 private Map<QName, Definition> flattened;
048 private boolean initialized;
049
050 public WSDLFlattener() {
051 this(null, null);
052 }
053
054 public WSDLFlattener(Definition definition) {
055 this(definition, null);
056 }
057
058 public WSDLFlattener(Definition definition, SchemaCollection schemas) {
059 this.definition = definition;
060 this.flattened = new HashMap<QName, Definition>();
061 this.schemas = schemas;
062 }
063
064 /**
065 * Parse the schemas referenced by the definition.
066 * @throws Exception if an error occurs
067 */
068 public void initialize() throws Exception {
069 if (!initialized) {
070 if (schemas == null) {
071 this.schemas = new SchemaCollection(getUri(this.definition.getDocumentBaseURI()));
072 }
073 parseSchemas(this.definition);
074 initialized = true;
075 }
076 }
077
078 /**
079 * Retrieve a flattened definition for a given port type name.
080 * @param portType the port type to create a flat definition for
081 * @return a flat definition for the port type
082 * @throws Exception if an error occurs
083 */
084 public Definition getDefinition(QName portType) throws Exception {
085 Definition def = flattened.get(portType);
086 if (def == null) {
087 def = flattenDefinition(portType);
088 flattened.put(portType, def);
089 }
090 return def;
091 }
092
093 /**
094 * @return Returns the definition.
095 */
096 public Definition getDefinition() {
097 return definition;
098 }
099
100 /**
101 * @param definition The definition to set.
102 */
103 public void setDefinition(Definition definition) {
104 this.definition = definition;
105 }
106
107 /**
108 * @return Returns the schemas.
109 */
110 public SchemaCollection getSchemas() throws Exception {
111 return schemas;
112 }
113
114 /**
115 * @param schemas The schemas to set.
116 */
117 public void setSchemas(SchemaCollection schemas) {
118 this.schemas = schemas;
119 }
120
121 private Definition flattenDefinition(QName name) throws Exception {
122 // Check that schemas have been loaded
123 initialize();
124 // Create new definition
125 Definition flat = WSDLFactory.newInstance().newDefinition();
126 flat.setTargetNamespace(name.getNamespaceURI());
127 addNamespaces(flat, definition);
128 // Create port type
129 PortType defPort = definition.getPortType(name);
130 PortType flatPort = flat.createPortType();
131 flatPort.setQName(defPort.getQName());
132 flatPort.setUndefined(false);
133 // Import all operations and related messages
134 for (Iterator itOper = defPort.getOperations().iterator(); itOper.hasNext();) {
135 Operation defOper = (Operation) itOper.next();
136 Operation flatOper = flat.createOperation();
137 flatOper.setName(defOper.getName());
138 flatOper.setStyle(defOper.getStyle());
139 flatOper.setUndefined(false);
140 if (defOper.getInput() != null) {
141 Input flatInput = flat.createInput();
142 flatInput.setName(defOper.getInput().getName());
143 if (defOper.getInput().getMessage() != null) {
144 Message flatInputMsg = copyMessage(defOper.getInput().getMessage(), flat);
145 flatInput.setMessage(flatInputMsg);
146 flat.addMessage(flatInputMsg);
147 }
148 flatOper.setInput(flatInput);
149 }
150 if (defOper.getOutput() != null) {
151 Output flatOutput = flat.createOutput();
152 flatOutput.setName(defOper.getOutput().getName());
153 if (defOper.getOutput().getMessage() != null) {
154 Message flatOutputMsg = copyMessage(defOper.getOutput().getMessage(), flat);
155 flatOutput.setMessage(flatOutputMsg);
156 flat.addMessage(flatOutputMsg);
157 }
158 flatOper.setOutput(flatOutput);
159 }
160 for (Iterator itFault = defOper.getFaults().values().iterator(); itFault.hasNext();) {
161 Fault defFault = (Fault) itFault.next();
162 Fault flatFault = flat.createFault();
163 flatFault.setName(defFault.getName());
164 if (defFault.getMessage() != null) {
165 Message flatFaultMsg = copyMessage(defFault.getMessage(), flat);
166 flatFault.setMessage(flatFaultMsg);
167 flat.addMessage(flatFaultMsg);
168 }
169 flatOper.addFault(flatFault);
170 }
171 flatPort.addOperation(flatOper);
172 }
173
174 // Import schemas in definition
175 if (schemas.getSize() > 0) {
176 Types types = flat.createTypes();
177 for (Iterator it = schemas.getSchemas().iterator(); it.hasNext();) {
178 javax.wsdl.extensions.schema.Schema imp = new SchemaImpl();
179 imp.setElement(((Schema)it.next()).getRoot());
180 imp.setElementType(new QName("http://www.w3.org/2001/XMLSchema", "schema"));
181 types.addExtensibilityElement(imp);
182 }
183 flat.setTypes(types);
184 }
185
186 flat.addPortType(flatPort);
187 return flat;
188 }
189
190 private void parseSchemas(Definition def) throws Exception {
191 if (def.getTypes() != null && def.getTypes().getExtensibilityElements() != null) {
192 for (Iterator iter = def.getTypes().getExtensibilityElements().iterator(); iter.hasNext();) {
193 ExtensibilityElement element = (ExtensibilityElement) iter.next();
194 if (element instanceof javax.wsdl.extensions.schema.Schema) {
195 javax.wsdl.extensions.schema.Schema schema = (javax.wsdl.extensions.schema.Schema) element;
196 if (schema.getElement() != null) {
197 schemas.read(schema.getElement(), getUri(schema.getDocumentBaseURI()));
198 }
199 for (Iterator itImp = schema.getImports().values().iterator(); itImp.hasNext();) {
200 Collection imps = (Collection) itImp.next();
201 for (Iterator itSi = imps.iterator(); itSi.hasNext();) {
202 SchemaImport imp = (SchemaImport) itSi.next();
203 schemas.read(imp.getSchemaLocationURI(), getUri(def.getDocumentBaseURI()));
204 }
205 }
206 }
207 }
208 }
209 if (def.getImports() != null) {
210 for (Iterator itImp = def.getImports().values().iterator(); itImp.hasNext();) {
211 Collection imps = (Collection) itImp.next();
212 for (Iterator iter = imps.iterator(); iter.hasNext();) {
213 Import imp = (Import) iter.next();
214 parseSchemas(imp.getDefinition());
215 }
216 }
217 }
218 }
219
220 private void addNamespaces(Definition flat, Definition def) {
221 for (Iterator itImport = def.getImports().values().iterator(); itImport.hasNext();) {
222 List defImports = (List) itImport.next();
223 for (Iterator iter = defImports.iterator(); iter.hasNext();) {
224 Import defImport = (Import) iter.next();
225 addNamespaces(flat, defImport.getDefinition());
226 }
227 }
228 for (Iterator itNs = def.getNamespaces().keySet().iterator(); itNs.hasNext();) {
229 String key = (String) itNs.next();
230 String val = def.getNamespace(key);
231 flat.addNamespace(key, val);
232 }
233 }
234
235 private Message copyMessage(Message defMessage, Definition flat) {
236 Message flatMsg = flat.createMessage();
237 flatMsg.setUndefined(false);
238 if (defMessage.getQName() != null) {
239 flatMsg.setQName(new QName(flat.getTargetNamespace(), defMessage.getQName().getLocalPart()));
240 }
241 for (Iterator itPart = defMessage.getParts().values().iterator(); itPart.hasNext();) {
242 Part defPart = (Part) itPart.next();
243 Part flatPart = flat.createPart();
244 flatPart.setName(defPart.getName());
245 flatPart.setElementName(defPart.getElementName());
246 flatMsg.addPart(flatPart);
247 }
248 return flatMsg;
249 }
250
251 private URI getUri(String str) {
252 if (str != null) {
253 str = str.replaceAll(" ", "%20");
254 return URI.create(str);
255 }
256 return null;
257 }
258
259 }