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