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.axis2.jaxws.util;
021:
022: import org.apache.axis2.java.security.AccessController;
023: import org.apache.axis2.jaxws.ExceptionFactory;
024: import org.apache.axis2.jaxws.i18n.Messages;
025: import org.apache.axis2.metadata.factory.ResourceFinderFactory;
026: import org.apache.axis2.metadata.registry.MetadataFactoryRegistry;
027: import org.apache.axis2.metadata.resource.ResourceFinder;
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030:
031: import javax.wsdl.Binding;
032: import javax.wsdl.BindingOperation;
033: import javax.wsdl.Definition;
034: import javax.wsdl.Port;
035: import javax.wsdl.Service;
036: import javax.wsdl.WSDLException;
037: import javax.wsdl.extensions.ExtensibilityElement;
038: import javax.wsdl.extensions.soap.SOAPOperation;
039: import javax.wsdl.factory.WSDLFactory;
040: import javax.wsdl.xml.WSDLReader;
041: import javax.xml.namespace.QName;
042: import java.io.File;
043: import java.io.FileNotFoundException;
044: import java.io.IOException;
045: import java.io.InputStream;
046: import java.net.ConnectException;
047: import java.net.URI;
048: import java.net.URL;
049: import java.net.URLClassLoader;
050: import java.net.URLConnection;
051: import java.net.UnknownHostException;
052: import java.security.PrivilegedAction;
053: import java.security.PrivilegedActionException;
054: import java.security.PrivilegedExceptionAction;
055: import java.util.ArrayList;
056: import java.util.Enumeration;
057: import java.util.Iterator;
058: import java.util.List;
059: import java.util.Map;
060: import java.util.jar.JarEntry;
061: import java.util.jar.JarFile;
062:
063: public class WSDL4JWrapper implements WSDLWrapper {
064: private static final Log log = LogFactory
065: .getLog(WSDL4JWrapper.class);
066: private Definition wsdlDefinition = null;
067: private URL wsdlURL;
068:
069: public WSDL4JWrapper(URL wsdlURL) throws FileNotFoundException,
070: UnknownHostException, ConnectException, IOException,
071: WSDLException {
072: super ();
073: if (log.isDebugEnabled()) {
074: log.debug("Looking for wsdl file on client: "
075: + (wsdlURL != null ? wsdlURL.getPath() : null));
076: }
077: ClassLoader classLoader = (ClassLoader) AccessController
078: .doPrivileged(new PrivilegedAction() {
079: public Object run() {
080: return Thread.currentThread()
081: .getContextClassLoader();
082: }
083: });
084: this .wsdlURL = wsdlURL;
085: try {
086: URL url = wsdlURL;
087: String filePath = null;
088: boolean isFileProtocol = (url != null && "file".equals(url
089: .getProtocol())) ? true : false;
090: if (isFileProtocol) {
091: filePath = (url != null) ? url.getPath() : null;
092: //Check is the uri has relative path i.e path is not absolute and is not starting with a "/"
093: boolean isRelativePath = (filePath != null && !new File(
094: filePath).isAbsolute()) ? true : false;
095: if (isRelativePath) {
096: if (log.isDebugEnabled()) {
097: log.debug("WSDL URL has a relative path");
098: }
099: //Lets read the complete WSDL URL for relative path from class loader
100: //Use relative path of url to fetch complete URL.
101: url = getAbsoluteURL(classLoader, filePath);
102: if (url == null) {
103: if (log.isDebugEnabled()) {
104: log
105: .debug("WSDL URL for relative path not found in ClassLoader");
106: log
107: .warn("Unable to read WSDL from relative path, check the relative path");
108: log
109: .info("Relative path example: file:/WEB-INF/wsdl/<wsdlfilename>");
110: log
111: .warn("Using relative path as default wsdl URL to create wsdl Definition.");
112: }
113: url = wsdlURL;
114: } else {
115: if (log.isDebugEnabled()) {
116: log
117: .debug("WSDL URL found for relative path: "
118: + filePath
119: + " scheme: "
120: + url.getProtocol());
121: }
122: }
123: }
124: }
125:
126: URLConnection urlCon = url.openConnection();
127: InputStream is = null;
128: try {
129: is = getInputStream(urlCon);
130: } catch (IOException e) {
131: if (log.isDebugEnabled()) {
132: log
133: .debug("Could not open url connection. Trying to use "
134: + "classloader to get another URL.");
135: }
136: if (filePath != null) {
137: url = getAbsoluteURL(classLoader, filePath);
138: if (url == null) {
139: if (log.isDebugEnabled()) {
140: log
141: .debug("Could not locate URL for wsdl. Reporting error");
142: }
143: throw new WSDLException("WSDL4JWrapper : ", e
144: .getMessage(), e);
145: } else {
146: urlCon = url.openConnection();
147: if (log.isDebugEnabled()) {
148: log.debug("Found URL for WSDL from jar");
149: }
150: }
151: } else {
152: if (log.isDebugEnabled()) {
153: log
154: .debug("Could not get URL from classloader. Reporting "
155: + "error due to no file path.");
156: }
157: throw new WSDLException("WSDL4JWrapper : ", e
158: .getMessage(), e);
159: }
160: }
161: if (is != null) {
162: is.close();
163: }
164: final String explicitWsdl = urlCon.getURL().toString();
165: try {
166: wsdlDefinition = (Definition) AccessController
167: .doPrivileged(new PrivilegedExceptionAction() {
168: public Object run() throws WSDLException {
169: WSDLReader reader = getWSDLReader();
170: return reader.readWSDL(explicitWsdl);
171: }
172: });
173: } catch (PrivilegedActionException e) {
174: if (log.isDebugEnabled()) {
175: log
176: .debug("Exception thrown from AccessController: "
177: + e);
178: }
179: throw ExceptionFactory.makeWebServiceException(e
180: .getException());
181: }
182:
183: } catch (FileNotFoundException ex) {
184: throw ex;
185: } catch (UnknownHostException ex) {
186: throw ex;
187: } catch (ConnectException ex) {
188: throw ex;
189: } catch (IOException ex) {
190: throw ex;
191: } catch (Exception ex) {
192: throw new WSDLException("WSDL4JWrapper : ", ex.getMessage());
193: }
194: }
195:
196: private URL getAbsoluteURL(ClassLoader classLoader, String filePath) {
197: URL url = classLoader.getResource(filePath);
198: if (url == null) {
199: if (log.isDebugEnabled()) {
200: log
201: .debug("Could not get URL from classloader. Looking in a jar.");
202: }
203: if (classLoader instanceof URLClassLoader) {
204: URLClassLoader urlLoader = (URLClassLoader) classLoader;
205: url = getURLFromJAR(urlLoader, wsdlURL);
206: }
207: }
208: return url;
209: }
210:
211: private URL getURLFromJAR(URLClassLoader urlLoader, URL relativeURL) {
212:
213: URL[] urlList = null;
214: ResourceFinderFactory rff = (ResourceFinderFactory) MetadataFactoryRegistry
215: .getFactory(ResourceFinderFactory.class);
216: ResourceFinder cf = rff.getResourceFinder();
217: urlList = cf.getURLs(urlLoader);
218: if (urlList == null) {
219: if (log.isDebugEnabled()) {
220: log.debug("No URL's found in URL ClassLoader");
221: }
222: ExceptionFactory.makeWebServiceException(Messages
223: .getMessage("WSDL4JWrapperErr1"));
224: }
225:
226: for (URL url : urlList) {
227: if ("file".equals(url.getProtocol())) {
228: File f = new File(url.getPath());
229: // If file is not of type directory then its a jar file
230: if (f.exists() && !f.isDirectory()) {
231: try {
232: JarFile jf = new JarFile(f);
233: Enumeration<JarEntry> entries = jf.entries();
234: // read all entries in jar file and return the first
235: // wsdl file that matches
236: // the relative path
237: while (entries.hasMoreElements()) {
238: JarEntry je = entries.nextElement();
239: String name = je.getName();
240: if (name.endsWith(".wsdl")) {
241: String relativePath = relativeURL
242: .getPath();
243: if (relativePath.endsWith(name)) {
244: String path = f.getAbsolutePath();
245: // This check is necessary because Unix/Linux file paths begin
246: // with a '/'. When adding the prefix 'jar:file:/' we may end
247: // up with '//' after the 'file:' part. This causes the URL
248: // object to treat this like a remote resource
249: if (path != null
250: && path.indexOf("/") == 0) {
251: path = path.substring(1, path
252: .length());
253: }
254:
255: URL absoluteUrl = new URL(
256: "jar:file:/" + path + "!/"
257: + je.getName());
258: return absoluteUrl;
259: }
260: }
261: }
262: } catch (Exception e) {
263: throw ExceptionFactory
264: .makeWebServiceException(e);
265: }
266: }
267: }
268: }
269:
270: return null;
271: }
272:
273: private static WSDLReader getWSDLReader() throws WSDLException {
274: // Keep this method private
275: WSDLReader reader;
276: try {
277: reader = (WSDLReader) AccessController
278: .doPrivileged(new PrivilegedExceptionAction() {
279: public Object run() throws WSDLException {
280: WSDLFactory factory = WSDLFactory
281: .newInstance();
282: return factory.newWSDLReader();
283: }
284: });
285: } catch (PrivilegedActionException e) {
286: throw (WSDLException) e.getException();
287: }
288: return reader;
289: }
290:
291: public WSDL4JWrapper(URL wsdlURL, Definition wsdlDefinition)
292: throws WSDLException {
293: super ();
294: this .wsdlURL = wsdlURL;
295: this .wsdlDefinition = wsdlDefinition;
296:
297: }
298:
299: //TODO: Perform validations for each method to check for null parameters on QName.
300:
301: public Definition getDefinition() {
302: return wsdlDefinition;
303: }
304:
305: public Binding getFirstPortBinding(QName serviceQname) {
306: // TODO Auto-generated method stub
307: Service service = getService(serviceQname);
308: if (service == null) {
309: return null;
310: }
311: Map map = getService(serviceQname).getPorts();
312: if (map == null || map.isEmpty()) {
313: return null;
314: }
315: for (Object listObject : map.values()) {
316: Port wsdlPort = (Port) listObject;
317: return wsdlPort.getBinding();
318:
319: }
320: return null;
321:
322: }
323:
324: public String getOperationName(QName serviceQname, QName portQname) {
325: Port port = getPort(serviceQname, portQname);
326: Binding binding = port.getBinding();
327: if (binding == null) {
328: return null;
329: }
330:
331: List operations = binding.getBindingOperations();
332: for (Object opObj : operations) {
333: BindingOperation operation = (BindingOperation) opObj;
334: return operation.getName();
335: }
336: return null;
337: }
338:
339: private Port getPort(QName serviceQname, QName eprQname) {
340: Service service = getService(serviceQname);
341: if (service == null) {
342: return null;
343: }
344: return service.getPort(eprQname.getLocalPart());
345:
346: }
347:
348: public ArrayList getPortBinding(QName serviceQname) {
349: // TODO Auto-generated method stub
350: Map map = this .getService(serviceQname).getPorts();
351: if (map == null || map.isEmpty()) {
352: return null;
353: }
354: ArrayList<Binding> portBindings = new ArrayList<Binding>();
355: for (Object listObject : map.values()) {
356: Port wsdlPort = (Port) listObject;
357: Binding binding = wsdlPort.getBinding();
358: if (binding != null) {
359: portBindings.add(binding);
360: }
361:
362: }
363: return portBindings;
364:
365: }
366:
367: public String getPortBinding(QName serviceQname, QName portQname) {
368: Port port = getPort(serviceQname, portQname);
369: if (port == null) {
370: return null;
371: }
372: Binding binding = port.getBinding();
373: return binding.getQName().getLocalPart();
374: }
375:
376: public String[] getPorts(QName serviceQname) {
377: String[] portNames = null;
378: Service service = this .getService(serviceQname);
379: if (service == null) {
380: return null;
381: }
382: Map map = service.getPorts();
383: if (map == null || map.isEmpty()) {
384: return null;
385: }
386: portNames = new String[map.values().size()];
387: Iterator iter = map.values().iterator();
388: for (int i = 0; iter.hasNext(); i++) {
389: Port wsdlPort = (Port) iter.next();
390: if (wsdlPort != null) {
391: portNames[i] = wsdlPort.getName();
392: }
393: }
394: return portNames;
395: }
396:
397: public Service getService(QName serviceQname) {
398: // TODO Auto-generated method stub
399: if (serviceQname == null) {
400: return null;
401: }
402: return wsdlDefinition.getService(serviceQname);
403:
404: }
405:
406: public String getSOAPAction(QName serviceQname) {
407: // TODO Auto-generated method stub
408: Binding binding = getFirstPortBinding(serviceQname);
409: if (binding == null) {
410: return null;
411: }
412: List operations = binding.getBindingOperations();
413: for (Object opObj : operations) {
414: BindingOperation operation = (BindingOperation) opObj;
415: List exElements = operation.getExtensibilityElements();
416: for (Object elObj : exElements) {
417: ExtensibilityElement exElement = (ExtensibilityElement) elObj;
418: if (isSoapOperation(exElement)) {
419: SOAPOperation soapOperation = (SOAPOperation) exElement;
420: return soapOperation.getSoapActionURI();
421: }
422: }
423: }
424: return null;
425: }
426:
427: public String getSOAPAction(QName serviceQname, QName portQname) {
428: // TODO Auto-generated method stub
429: Port port = getPort(serviceQname, portQname);
430: if (port == null) {
431: return null;
432: }
433: Binding binding = port.getBinding();
434: if (binding == null) {
435: return null;
436: }
437: List operations = binding.getBindingOperations();
438: for (Object opObj : operations) {
439: BindingOperation operation = (BindingOperation) opObj;
440: List exElements = operation.getExtensibilityElements();
441: for (Object elObj : exElements) {
442: ExtensibilityElement exElement = (ExtensibilityElement) elObj;
443: if (isSoapOperation(exElement)) {
444: SOAPOperation soapOperation = (SOAPOperation) exElement;
445: return soapOperation.getSoapActionURI();
446: }
447: }
448: }
449: return null;
450: }
451:
452: public String getSOAPAction(QName serviceQname, QName portQname,
453: QName operationQname) {
454: Port port = getPort(serviceQname, portQname);
455: if (port == null) {
456: return null;
457: }
458: Binding binding = port.getBinding();
459: if (binding == null) {
460: return null;
461: }
462: List operations = binding.getBindingOperations();
463: if (operations == null) {
464: return null;
465: }
466: BindingOperation operation = null;
467: for (Object opObj : operations) {
468: operation = (BindingOperation) opObj;
469: }
470: List exElements = operation.getExtensibilityElements();
471: for (Object elObj : exElements) {
472: ExtensibilityElement exElement = (ExtensibilityElement) elObj;
473: if (isSoapOperation(exElement)) {
474: SOAPOperation soapOperation = (SOAPOperation) exElement;
475: if (soapOperation.getElementType().equals(
476: operationQname)) {
477: return soapOperation.getSoapActionURI();
478: }
479: }
480: }
481:
482: return null;
483: }
484:
485: public URL getWSDLLocation() {
486: // TODO Auto-generated method stub
487: return this .wsdlURL;
488: }
489:
490: private boolean isSoapOperation(ExtensibilityElement exElement) {
491: return WSDLWrapper.SOAP_11_OPERATION.equals(exElement
492: .getElementType());
493: //TODO: Add Soap12 support later
494: // || WSDLWrapper.SOAP_12_OPERATION.equals(exElement.getElementType());
495: }
496:
497: public String getTargetNamespace() {
498: // TODO Auto-generated method stub
499: return wsdlDefinition.getTargetNamespace();
500: }
501:
502: /**
503: * This method provides a Java2 Security compliant way to obtain the InputStream
504: * for a given URLConnection object. This is needed as a given URLConnection object
505: * may be an instance of a FileURLConnection object which would require access
506: * permissions if Java2 Security was enabled.
507: */
508: private InputStream getInputStream(URLConnection urlCon)
509: throws Exception {
510: final URLConnection finalURLCon = urlCon;
511: InputStream is = null;
512: try {
513: is = (InputStream) AccessController
514: .doPrivileged(new PrivilegedExceptionAction() {
515: public Object run() throws IOException {
516: return finalURLCon.getInputStream();
517: }
518: });
519: } catch (PrivilegedActionException e) {
520: throw e.getException();
521: }
522: return is;
523: }
524:
525: }
|