/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 *******************************************************************************/ package org.ebayopensource.turmeric.tools.codegen.external.wsdl.parser; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import org.ebayopensource.turmeric.tools.codegen.util.CodeGenUtil; import org.xml.sax.InputSource; import com.ibm.wsdl.util.StringUtils; /** * Implementation of javax.wsdl.xml.WSDLLocator. This class can be used to * locate a wsdl document and its imports using a ClassLoader. This is useful * when the wsdl is located in a jar/zip file on the classpath. * * */ public class DefaultWSDLLocatorImpl implements javax.wsdl.xml.WSDLLocator { Reader baseReader = null; InputStream baseInputStream = null; InputStream importInputStream = null; String contextURI = null; String wsdlLocation = null; String documentBase = null; String importBase = null; ClassLoader loader = null; /** * Create an instance of DefaultWSDLLocatorImpl. * @param ctxt The context uri for the wsdl location * @param wsdlURI The uri for the base wsdl document * @param cl A ClassLoader to use in locating the base wsdl document and imports */ public DefaultWSDLLocatorImpl(String ctxt, String wsdlURI, ClassLoader cl) { contextURI = ctxt; wsdlLocation = wsdlURI; loader = cl; } /** * Create an instance of DefaultWSDLLocatorImpl. * @param docBase The uri for the base wsdl document * @param reader A reader "directed at" the base wsdl document * @param cl A ClassLoader to use in locating the base wsdl document and imports */ public DefaultWSDLLocatorImpl(String docBase, Reader reader, ClassLoader cl) { documentBase = docBase; baseReader = reader; loader = cl; } /** * Get an InputSource for the base wsdl document. Returns null if the document * cannot be located. * @return The InputSource or null if the import cannot be resolved */ public InputSource getBaseInputSource() { if (baseReader != null) { return new InputSource(baseReader); } if (baseInputStream == null) { try { URL url = null; URL contextURL = (contextURI != null) ? StringUtils.getURL(null, contextURI) : null; if (loader != null) { try { if (contextURL != null) url = new URL(contextURL, wsdlLocation); else { if (wsdlLocation.indexOf(":") == -1) url = new URL("file", null, wsdlLocation); else url = new URL(wsdlLocation); } String wsdlRelativeLocation = url.getPath(); if (wsdlRelativeLocation.startsWith("/")) wsdlRelativeLocation = wsdlRelativeLocation.substring(1); baseInputStream = loader.getResourceAsStream(wsdlRelativeLocation); } catch (Exception exc) { //NOPMD } } if (baseInputStream == null) { url = StringUtils.getURL(contextURL, wsdlLocation); baseInputStream = StringUtils.getContentAsInputStream(url); } if (url != null) { documentBase = url.toString(); } else if (baseInputStream == null) { documentBase = wsdlLocation; } } catch (Exception e) { //NOPMD documentBase = wsdlLocation; } } if (baseInputStream == null) { return null; } return new InputSource(baseInputStream); } /** * Get an InputSource for an imported wsdl document. Returns null if the import document * cannot be located. * @param base The document base uri for the parent wsdl document * @param relativeLocation The relative uri of the import wsdl document * @return The InputSource or null if the import cannot be resolved */ public InputSource getImportInputSource(String base, String relativeLocation) { // Reset importInputStream if finding import within import importInputStream = null; boolean triedSU = false; try { // If a ClassLoader was used to load the base document, chances // are we need to use it to find the import. URL url = null; if (loader != null) { if (relativeLocation.startsWith("/") || relativeLocation.startsWith("\\")) { // Relative location has been specified from a root dir. However, // using a ClassLoader, root dirs don't mean anything. relativeLocation = relativeLocation.substring(1, relativeLocation.length()); importInputStream = loader.getResourceAsStream(relativeLocation); } else if (relativeLocation.indexOf("://") != -1) { // This is a fully specified URL of some kind so don't use the // ClassLoader to find the import. triedSU = true; url = StringUtils.getURL(null, relativeLocation); importInputStream = StringUtils.getContentAsInputStream(url); } else { // Import location has been specified relative to the base document // and so we can to try to form the complete path to it. if (base != null) { int i = base.lastIndexOf("/"); if (i == -1) i = base.lastIndexOf("\\"); if (i != -1) { String path = base.substring(0, i + 1); String resolvedPath = path + relativeLocation; if (relativeLocation.startsWith("..")) { resolvedPath = resolvePath(path, relativeLocation); } if (resolvedPath == null) { throw new Exception("Invalid Path"); } // Make sure that resolved path starts with file: if (resolvedPath.startsWith("file:")) { url = new URL(null, resolvedPath); } else { url = new URL(null, "file:" + resolvedPath); } } else { url = new URL(null, "file:" + relativeLocation); } importInputStream = loader.getResourceAsStream(url.getPath()); } else { url = new URL(null, "file:" + relativeLocation); importInputStream = loader.getResourceAsStream(url.getPath()); } } } else { triedSU = true; URL contextURL = (base != null) ? StringUtils.getURL(null, base) : null; url = StringUtils.getURL(contextURL, relativeLocation); importInputStream = StringUtils.getContentAsInputStream(url); } if (importInputStream == null) { if (!triedSU) { try { URL contextURL = (base != null) ? StringUtils.getURL(null, base) : null; URL url2 = StringUtils.getURL(contextURL, relativeLocation); importInputStream = StringUtils.getContentAsInputStream(url2); importBase = (url2 == null) ? relativeLocation : url2.toString(); } catch (Exception e2) { //NOPMD // we can't find the import so set a temporary value for the import URI. This is // necessary to avoid a NullPointerException in WSDLReaderImpl importBase = "unknownImportURI"; } } else { // we can't find the import so set a temporary value for the import URI. This is // necessary to avoid a NullPointerException in WSDLReaderImpl importBase = "unknownImportURI"; } } else { importBase = (url == null) ? relativeLocation : url.toString(); } } catch (Exception e) { // If we have not tried using a non-ClassLoader route, try it now // as a last resort. if (!triedSU) { try { URL contextURL = (base != null) ? StringUtils.getURL(null, base) : null; URL url = StringUtils.getURL(contextURL, relativeLocation); importInputStream = StringUtils.getContentAsInputStream(url); importBase = (url == null) ? relativeLocation : url.toString(); } catch (Exception e2) { // we can't find the import so set a temporary value for the import URI. This is // necessary to avoid a NullPointerException in WSDLReaderImpl importBase = "unknownImportURI"; } } else { // we can't find the import so set a temporary value for the import URI. This is // necessary to avoid a NullPointerException in WSDLReaderImpl importBase = "unknownImportURI"; } } if (importInputStream == null) { return null; } return new InputSource(importInputStream); } /** * @deprecated Old WSDLLocator method, no longer on the interface */ public Reader getBaseReader() { InputSource is = getBaseInputSource(); if (is == null) return null; if (is.getCharacterStream() != null) { return is.getCharacterStream(); } else if (is.getByteStream() != null) { return new InputStreamReader(is.getByteStream()); } return null; } /** * @deprecated Old WSDLLocator method, no longer on the interface */ public Reader getImportReader(String base, String relativeLocation) { InputSource is = getImportInputSource(base, relativeLocation); if (is == null) return null; if (is.getCharacterStream() != null) { return is.getCharacterStream(); } else if (is.getByteStream() != null) { return new InputStreamReader(is.getByteStream()); } return null; } /** * Get the document base uri for the base wsdl document * @return The document base uri */ public String getBaseURI() { return documentBase; } /** * Get the document base uri for the last import document to be resolved * by this locator. This is useful if resolving imports within imports. * @return The document base uri */ public String getLatestImportURI() { return importBase; } /** * Resolve a path when the relative location begins with .. */ private String resolvePath(String ba, String rel) { StringBuffer sb = new StringBuffer(rel); int dd = 0; while(sb.length() > 0) { if(sb.length() > 3 && sb.charAt(0) == '.' && sb.charAt(1) == '.' && (sb.charAt(2) == '/' || sb.charAt(2) == '\\')) { dd++; sb.delete(0,3); } else { break; } } StringBuffer sb2 = new StringBuffer(ba); int j = sb2.length()-1; int found = 0; for (int k = j; k>=0; k--) { if (k!=j && (sb2.charAt(k) == '/' || sb2.charAt(k) == '\\')) { found++; } if (found < dd) { sb2.deleteCharAt(k); } else { break; } } if (found+1 < dd) return null; return sb2.toString() + sb.toString(); } /** * Close any Reader or stream objects that have been created * @throws IOException If a call to close() on one of the Reader or stream objects fails */ public void close() { CodeGenUtil.closeQuietly(baseReader); CodeGenUtil.closeQuietly(importInputStream); CodeGenUtil.closeQuietly(baseInputStream); } }