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.cxf.transport.http;
019:
020: import java.io.IOException;
021: import java.io.OutputStream;
022: import java.net.MalformedURLException;
023: import java.net.URL;
024: import java.util.Collection;
025: import java.util.List;
026: import java.util.Map;
027: import java.util.ResourceBundle;
028: import java.util.concurrent.ConcurrentHashMap;
029:
030: import javax.wsdl.Definition;
031: import javax.wsdl.Import;
032: import javax.wsdl.Types;
033: import javax.wsdl.WSDLException;
034: import javax.wsdl.extensions.ExtensibilityElement;
035: import javax.wsdl.extensions.schema.Schema;
036: import javax.wsdl.extensions.schema.SchemaImport;
037: import javax.wsdl.extensions.schema.SchemaReference;
038: import javax.wsdl.xml.WSDLWriter;
039: import javax.xml.parsers.ParserConfigurationException;
040:
041: import org.w3c.dom.Document;
042: import org.w3c.dom.Element;
043: import org.w3c.dom.NodeList;
044:
045: import org.xml.sax.InputSource;
046: import org.xml.sax.SAXException;
047:
048: import org.apache.cxf.Bus;
049: import org.apache.cxf.common.i18n.BundleUtils;
050: import org.apache.cxf.common.i18n.Message;
051: import org.apache.cxf.helpers.CastUtils;
052: import org.apache.cxf.helpers.XMLUtils;
053: import org.apache.cxf.service.model.EndpointInfo;
054: import org.apache.cxf.transports.http.QueryHandler;
055: import org.apache.cxf.wsdl.WSDLManager;
056: import org.apache.cxf.wsdl11.ResourceManagerWSDLLocator;
057: import org.apache.cxf.wsdl11.ServiceWSDLBuilder;
058:
059: public class WSDLQueryHandler implements QueryHandler {
060: private static final ResourceBundle BUNDLE = BundleUtils
061: .getBundle(WSDLQueryHandler.class);
062:
063: Bus bus;
064:
065: public WSDLQueryHandler(Bus b) {
066: bus = b;
067: }
068:
069: public String getResponseContentType(String baseUri, String ctx) {
070: if (baseUri.toLowerCase().contains("?wsdl")
071: || baseUri.toLowerCase().contains("?xsd=")) {
072: return "text/xml";
073: }
074: return null;
075: }
076:
077: public boolean isRecognizedQuery(String baseUri, String ctx,
078: EndpointInfo endpointInfo) {
079: if (baseUri != null
080: && (baseUri.toLowerCase().contains("?wsdl") || baseUri
081: .toLowerCase().contains("?xsd="))) {
082: return endpointInfo.getAddress().contains(ctx);
083: }
084: return false;
085: }
086:
087: public void writeResponse(String baseUri, String ctxUri,
088: EndpointInfo endpointInfo, OutputStream os) {
089: try {
090: int idx = baseUri.toLowerCase().indexOf("?wsdl");
091: String base = null;
092: String wsdl = "";
093: String xsd = null;
094: if (idx != -1) {
095: base = baseUri.substring(0, baseUri.toLowerCase()
096: .indexOf("?wsdl"));
097: wsdl = baseUri.substring(baseUri.toLowerCase().indexOf(
098: "?wsdl") + 5);
099: if (wsdl.length() > 0) {
100: wsdl = wsdl.substring(1);
101: }
102: } else {
103: base = baseUri.substring(0, baseUri.toLowerCase()
104: .indexOf("?xsd="));
105: xsd = baseUri.substring(baseUri.toLowerCase().indexOf(
106: "?xsd=") + 5);
107: }
108:
109: Map<String, Definition> mp = CastUtils
110: .cast((Map) endpointInfo.getService().getProperty(
111: WSDLQueryHandler.class.getName()));
112: Map<String, SchemaReference> smp = CastUtils
113: .cast((Map) endpointInfo.getService().getProperty(
114: WSDLQueryHandler.class.getName()
115: + ".Schemas"));
116:
117: if (mp == null) {
118: endpointInfo.getService().setProperty(
119: WSDLQueryHandler.class.getName(),
120: new ConcurrentHashMap());
121: mp = CastUtils.cast((Map) endpointInfo.getService()
122: .getProperty(WSDLQueryHandler.class.getName()));
123: }
124: if (smp == null) {
125: endpointInfo.getService().setProperty(
126: WSDLQueryHandler.class.getName() + ".Schemas",
127: new ConcurrentHashMap());
128: smp = CastUtils.cast((Map) endpointInfo.getService()
129: .getProperty(
130: WSDLQueryHandler.class.getName()
131: + ".Schemas"));
132: }
133:
134: if (!mp.containsKey(wsdl)) {
135: Definition def = new ServiceWSDLBuilder(bus,
136: endpointInfo.getService()).build();
137: mp.put("", def);
138: updateDefinition(def, mp, smp, base, endpointInfo);
139: }
140:
141: Document doc;
142: if (xsd == null) {
143: Definition def = mp.get(wsdl);
144:
145: WSDLWriter wsdlWriter = bus.getExtension(
146: WSDLManager.class).getWSDLFactory()
147: .newWSDLWriter();
148: def.setExtensionRegistry(bus.getExtension(
149: WSDLManager.class).getExtenstionRegistry());
150: doc = wsdlWriter.getDocument(def);
151: } else {
152: SchemaReference si = smp.get(xsd);
153: ResourceManagerWSDLLocator rml = new ResourceManagerWSDLLocator(
154: si.getReferencedSchema().getDocumentBaseURI(),
155: bus);
156:
157: InputSource src = rml.getBaseInputSource();
158: doc = XMLUtils.getParser().parse(src);
159: }
160:
161: NodeList nl = doc.getDocumentElement()
162: .getElementsByTagNameNS(
163: "http://www.w3.org/2001/XMLSchema",
164: "import");
165: for (int x = 0; x < nl.getLength(); x++) {
166: Element el = (Element) nl.item(x);
167: String sl = el.getAttribute("schemaLocation");
168: if (smp.containsKey(sl)) {
169: el.setAttribute("schemaLocation", base + "?xsd="
170: + sl);
171: }
172: }
173: nl = doc.getDocumentElement().getElementsByTagNameNS(
174: "http://www.w3.org/2001/XMLSchema", "include");
175: for (int x = 0; x < nl.getLength(); x++) {
176: Element el = (Element) nl.item(x);
177: String sl = el.getAttribute("schemaLocation");
178: if (smp.containsKey(sl)) {
179: el.setAttribute("schemaLocation", base + "?xsd="
180: + sl);
181: }
182: }
183: nl = doc.getDocumentElement().getElementsByTagNameNS(
184: "http://schemas.xmlsoap.org/wsdl/", "import");
185: for (int x = 0; x < nl.getLength(); x++) {
186: Element el = (Element) nl.item(x);
187: String sl = el.getAttribute("location");
188: if (mp.containsKey(sl)) {
189: el.setAttribute("location", base + "?wsdl=" + sl);
190: }
191: }
192:
193: XMLUtils.writeTo(doc, os);
194: } catch (WSDLException wex) {
195: throw new WSDLQueryException(new Message(
196: "COULD_NOT_PROVIDE_WSDL", BUNDLE, baseUri), wex);
197: } catch (SAXException e) {
198: throw new WSDLQueryException(new Message(
199: "COULD_NOT_PROVIDE_WSDL", BUNDLE, baseUri), e);
200: } catch (IOException e) {
201: throw new WSDLQueryException(new Message(
202: "COULD_NOT_PROVIDE_WSDL", BUNDLE, baseUri), e);
203: } catch (ParserConfigurationException e) {
204: throw new WSDLQueryException(new Message(
205: "COULD_NOT_PROVIDE_WSDL", BUNDLE, baseUri), e);
206: }
207: }
208:
209: protected void updateDefinition(Definition def,
210: Map<String, Definition> done,
211: Map<String, SchemaReference> doneSchemas, String base,
212: EndpointInfo ei) {
213: Collection<List> imports = CastUtils.cast((Collection<?>) def
214: .getImports().values());
215: for (List lst : imports) {
216: List<Import> impLst = CastUtils.cast(lst);
217: for (Import imp : impLst) {
218: String start = imp.getLocationURI();
219: try {
220: //check to see if it's aleady in a URL format. If so, leave it.
221: new URL(start);
222: } catch (MalformedURLException e) {
223: done.put(start, imp.getDefinition());
224: updateDefinition(imp.getDefinition(), done,
225: doneSchemas, base, ei);
226: }
227: }
228: }
229:
230: /* This doesn't actually work. Setting setSchemaLocationURI on the import
231: * for some reason doesn't actually result in the new URI being written
232: * */
233: Types types = def.getTypes();
234: if (types != null) {
235: for (ExtensibilityElement el : CastUtils.cast((List) types
236: .getExtensibilityElements(),
237: ExtensibilityElement.class)) {
238: if (el instanceof Schema) {
239: Schema see = (Schema) el;
240: updateSchemaImports(see, doneSchemas, base);
241: }
242: }
243: }
244: }
245:
246: protected void updateSchemaImports(Schema schema,
247: Map<String, SchemaReference> doneSchemas, String base) {
248: Collection<List> imports = CastUtils
249: .cast((Collection<?>) schema.getImports().values());
250: for (List lst : imports) {
251: List<SchemaImport> impLst = CastUtils.cast(lst);
252: for (SchemaImport imp : impLst) {
253: String start = imp.getSchemaLocationURI();
254: if (start != null && !doneSchemas.containsKey(start)) {
255: try {
256: //check to see if it's aleady in a URL format. If so, leave it.
257: new URL(start);
258: } catch (MalformedURLException e) {
259: doneSchemas.put(start, imp);
260: updateSchemaImports(imp.getReferencedSchema(),
261: doneSchemas, base);
262: }
263: }
264: }
265: }
266: List<SchemaReference> includes = CastUtils.cast(schema
267: .getIncludes());
268: for (SchemaReference included : includes) {
269: String start = included.getSchemaLocationURI();
270: if (start != null && !doneSchemas.containsKey(start)) {
271: try {
272: //check to see if it's aleady in a URL format. If so, leave it.
273: new URL(start);
274: } catch (MalformedURLException e) {
275: doneSchemas.put(start, included);
276: updateSchemaImports(included.getReferencedSchema(),
277: doneSchemas, base);
278: }
279: }
280: }
281: }
282: }
|