001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.geronimo.axis2;
019:
020: import java.io.OutputStream;
021: import java.net.MalformedURLException;
022: import java.net.URI;
023: import java.net.URISyntaxException;
024: import java.net.URL;
025: import java.util.ArrayList;
026: import java.util.Collection;
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.Map;
030: import java.util.concurrent.ConcurrentHashMap;
031:
032: import javax.wsdl.Definition;
033: import javax.wsdl.Import;
034: import javax.wsdl.Port;
035: import javax.wsdl.Service;
036: import javax.wsdl.Types;
037: import javax.wsdl.extensions.ExtensibilityElement;
038: import javax.wsdl.extensions.schema.Schema;
039: import javax.wsdl.extensions.schema.SchemaImport;
040: import javax.wsdl.extensions.schema.SchemaReference;
041: import javax.wsdl.extensions.soap.SOAPAddress;
042: import javax.wsdl.extensions.soap12.SOAP12Address;
043: import javax.wsdl.factory.WSDLFactory;
044: import javax.wsdl.xml.WSDLReader;
045: import javax.wsdl.xml.WSDLWriter;
046: import javax.xml.namespace.QName;
047: import javax.xml.transform.OutputKeys;
048: import javax.xml.transform.Source;
049: import javax.xml.transform.Transformer;
050: import javax.xml.transform.TransformerException;
051: import javax.xml.transform.TransformerFactory;
052: import javax.xml.transform.dom.DOMSource;
053: import javax.xml.transform.stream.StreamResult;
054:
055: import org.apache.axis2.description.AxisService;
056: import org.apache.commons.logging.Log;
057: import org.apache.commons.logging.LogFactory;
058: import org.apache.geronimo.webservices.WebServiceContainer.Request;
059: import org.w3c.dom.Element;
060: import org.w3c.dom.Node;
061: import org.w3c.dom.NodeList;
062:
063: public class WSDLQueryHandler {
064:
065: private static final Log LOG = LogFactory
066: .getLog(WSDLQueryHandler.class);
067:
068: private Map<String, Definition> mp = new ConcurrentHashMap<String, Definition>();
069: private Map<String, SchemaReference> smp = new ConcurrentHashMap<String, SchemaReference>();
070: private AxisService service;
071:
072: public WSDLQueryHandler(AxisService service) {
073: this .service = service;
074: }
075:
076: public void writeResponse(String baseUri, String wsdlUri,
077: OutputStream os) throws Exception {
078:
079: int idx = baseUri.toLowerCase().indexOf("?wsdl");
080: String base = null;
081: String wsdl = "";
082: String xsd = null;
083: if (idx != -1) {
084: base = baseUri.substring(0, baseUri.toLowerCase().indexOf(
085: "?wsdl"));
086: wsdl = baseUri.substring(baseUri.toLowerCase().indexOf(
087: "?wsdl") + 5);
088: if (wsdl.length() > 0) {
089: wsdl = wsdl.substring(1);
090: }
091: } else {
092: base = baseUri.substring(0, baseUri.toLowerCase().indexOf(
093: "?xsd="));
094: xsd = baseUri.substring(baseUri.toLowerCase().indexOf(
095: "?xsd=") + 5);
096: }
097:
098: if (!mp.containsKey(wsdl)) {
099: WSDLFactory factory = WSDLFactory.newInstance();
100: WSDLReader reader = factory.newWSDLReader();
101: reader.setFeature("javax.wsdl.importDocuments", true);
102: reader.setFeature("javax.wsdl.verbose", false);
103: Definition def = reader.readWSDL(wsdlUri);
104: updateDefinition(def, mp, smp, base);
105: updateServices(this .service.getName(), this .service
106: .getEndpointName(), def, base);
107: mp.put("", def);
108: }
109:
110: Element rootElement;
111:
112: if (xsd == null) {
113: Definition def = mp.get(wsdl);
114:
115: WSDLFactory factory = WSDLFactory.newInstance();
116: WSDLWriter writer = factory.newWSDLWriter();
117:
118: rootElement = writer.getDocument(def).getDocumentElement();
119: } else {
120: SchemaReference si = smp.get(xsd);
121: rootElement = si.getReferencedSchema().getElement();
122: }
123:
124: NodeList nl = rootElement.getElementsByTagNameNS(
125: "http://www.w3.org/2001/XMLSchema", "import");
126: for (int x = 0; x < nl.getLength(); x++) {
127: Element el = (Element) nl.item(x);
128: String sl = el.getAttribute("schemaLocation");
129: if (smp.containsKey(sl)) {
130: el.setAttribute("schemaLocation", base + "?xsd=" + sl);
131: }
132: }
133: nl = rootElement.getElementsByTagNameNS(
134: "http://www.w3.org/2001/XMLSchema", "include");
135: for (int x = 0; x < nl.getLength(); x++) {
136: Element el = (Element) nl.item(x);
137: String sl = el.getAttribute("schemaLocation");
138: if (smp.containsKey(sl)) {
139: el.setAttribute("schemaLocation", base + "?xsd=" + sl);
140: }
141: }
142: nl = rootElement.getElementsByTagNameNS(
143: "http://schemas.xmlsoap.org/wsdl/", "import");
144: for (int x = 0; x < nl.getLength(); x++) {
145: Element el = (Element) nl.item(x);
146: String sl = el.getAttribute("location");
147: if (mp.containsKey(sl)) {
148: el.setAttribute("location", base + "?wsdl=" + sl);
149: }
150: }
151:
152: writeTo(rootElement, os);
153: }
154:
155: protected void updateDefinition(Definition def,
156: Map<String, Definition> done,
157: Map<String, SchemaReference> doneSchemas, String base) {
158: Collection<List> imports = def.getImports().values();
159: for (List lst : imports) {
160: List<Import> impLst = lst;
161: for (Import imp : impLst) {
162: String start = imp.getLocationURI();
163: try {
164: //check to see if it's aleady in a URL format. If so, leave it.
165: new URL(start);
166: } catch (MalformedURLException e) {
167: done.put(start, imp.getDefinition());
168: updateDefinition(imp.getDefinition(), done,
169: doneSchemas, base);
170: }
171: }
172: }
173:
174: /* This doesn't actually work. Setting setSchemaLocationURI on the import
175: * for some reason doesn't actually result in the new URI being written
176: * */
177: Types types = def.getTypes();
178: if (types != null) {
179: for (ExtensibilityElement el : (List<ExtensibilityElement>) types
180: .getExtensibilityElements()) {
181: if (el instanceof Schema) {
182: Schema see = (Schema) el;
183: updateSchemaImports(see, doneSchemas, base);
184: }
185: }
186: }
187: }
188:
189: protected void updateSchemaImports(Schema schema,
190: Map<String, SchemaReference> doneSchemas, String base) {
191: Collection<List> imports = schema.getImports().values();
192: for (List lst : imports) {
193: List<SchemaImport> impLst = lst;
194: for (SchemaImport imp : impLst) {
195: String start = imp.getSchemaLocationURI();
196: if (start != null) {
197: try {
198: //check to see if it's aleady in a URL format. If so, leave it.
199: new URL(start);
200: } catch (MalformedURLException e) {
201: if (!doneSchemas.containsKey(start)) {
202: doneSchemas.put(start, imp);
203: updateSchemaImports(imp
204: .getReferencedSchema(),
205: doneSchemas, base);
206: }
207: }
208: }
209: }
210: }
211: List<SchemaReference> includes = schema.getIncludes();
212: for (SchemaReference included : includes) {
213: String start = included.getSchemaLocationURI();
214: if (start != null) {
215: try {
216: //check to see if it's aleady in a URL format. If so, leave it.
217: new URL(start);
218: } catch (MalformedURLException e) {
219: if (!doneSchemas.containsKey(start)) {
220: doneSchemas.put(start, included);
221: updateSchemaImports(included
222: .getReferencedSchema(), doneSchemas,
223: base);
224: }
225: }
226: }
227: }
228: }
229:
230: public static void writeTo(Node node, OutputStream os) {
231: writeTo(new DOMSource(node), os);
232: }
233:
234: public static void writeTo(Source src, OutputStream os) {
235: Transformer it;
236: try {
237: it = TransformerFactory.newInstance().newTransformer();
238: it.setOutputProperty(OutputKeys.METHOD, "xml");
239: it.setOutputProperty(OutputKeys.INDENT, "yes");
240: it.setOutputProperty(
241: "{http://xml.apache.org/xslt}indent-amount", "4");
242: it.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,
243: "false");
244: it.setOutputProperty(OutputKeys.ENCODING, "utf-8");
245: it.transform(src, new StreamResult(os));
246: } catch (TransformerException e) {
247: // TODO Auto-generated catch block
248: e.printStackTrace();
249: }
250: }
251:
252: private void updateServices(String serviceName, String portName,
253: Definition def, String baseUri) throws Exception {
254: boolean updated = false;
255: Map services = def.getServices();
256: if (services != null) {
257: ArrayList<QName> servicesToRemove = new ArrayList<QName>();
258:
259: Iterator serviceIterator = services.entrySet().iterator();
260: while (serviceIterator.hasNext()) {
261: Map.Entry serviceEntry = (Map.Entry) serviceIterator
262: .next();
263: QName currServiceName = (QName) serviceEntry.getKey();
264: if (currServiceName.getLocalPart().equals(serviceName)) {
265: Service service = (Service) serviceEntry.getValue();
266: updatePorts(portName, service, baseUri);
267: updated = true;
268: } else {
269: servicesToRemove.add(currServiceName);
270: }
271: }
272:
273: for (QName serviceToRemove : servicesToRemove) {
274: def.removeService(serviceToRemove);
275: }
276: }
277: if (!updated) {
278: LOG.warn("WSDL '" + serviceName + "' service not found.");
279: }
280: }
281:
282: private void updatePorts(String portName, Service service,
283: String baseUri) throws Exception {
284: boolean updated = false;
285: Map ports = service.getPorts();
286: if (ports != null) {
287: ArrayList<String> portsToRemove = new ArrayList<String>();
288:
289: Iterator portIterator = ports.entrySet().iterator();
290: while (portIterator.hasNext()) {
291: Map.Entry portEntry = (Map.Entry) portIterator.next();
292: String currPortName = (String) portEntry.getKey();
293: if (currPortName.equals(portName)) {
294: Port port = (Port) portEntry.getValue();
295: updatePortLocation(port, baseUri);
296: updated = true;
297: } else {
298: portsToRemove.add(currPortName);
299: }
300: }
301:
302: for (String portToRemove : portsToRemove) {
303: service.removePort(portToRemove);
304: }
305: }
306: if (!updated) {
307: LOG.warn("WSDL '" + portName + "' port not found.");
308: }
309: }
310:
311: private void updatePortLocation(Port port, String baseUri)
312: throws URISyntaxException {
313: List<?> exts = port.getExtensibilityElements();
314: if (exts != null && exts.size() > 0) {
315: ExtensibilityElement el = (ExtensibilityElement) exts
316: .get(0);
317: if (el instanceof SOAP12Address) {
318: SOAP12Address add = (SOAP12Address) el;
319: add.setLocationURI(baseUri);
320: } else if (el instanceof SOAPAddress) {
321: SOAPAddress add = (SOAPAddress) el;
322: add.setLocationURI(baseUri);
323: }
324: }
325: }
326: }
|