001: /*
002: * The Apache Software License, Version 1.1
003: *
004: *
005: * Copyright (c) 2002 The Apache Software Foundation. All rights
006: * reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * 1. Redistributions of source code must retain the above copyright
013: * notice, this list of conditions and the following disclaimer.
014: *
015: * 2. Redistributions in binary form must reproduce the above copyright
016: * notice, this list of conditions and the following disclaimer in
017: * the documentation and/or other materials provided with the
018: * distribution.
019: *
020: * 3. The end-user documentation included with the redistribution,
021: * if any, must include the following acknowledgment:
022: * "This product includes software developed by the
023: * Apache Software Foundation (http://www.apache.org/)."
024: * Alternately, this acknowledgment may appear in the software itself,
025: * if and wherever such third-party acknowledgments normally appear.
026: *
027: * 4. The names "WSIF" and "Apache Software Foundation" must
028: * not be used to endorse or promote products derived from this
029: * software without prior written permission. For written
030: * permission, please contact apache@apache.org.
031: *
032: * 5. Products derived from this software may not be called "Apache",
033: * nor may "Apache" appear in their name, without prior written
034: * permission of the Apache Software Foundation.
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
040: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: * ====================================================================
049: *
050: * This software consists of voluntary contributions made by many
051: * individuals on behalf of the Apache Software Foundation and was
052: * originally based on software copyright (c) 2001, 2002, International
053: * Business Machines, Inc., http://www.apache.org. For more
054: * information on the Apache Software Foundation, please see
055: * <http://www.apache.org/>.
056: */
057:
058: package org.apache.wsif.wsdl;
059:
060: import java.io.IOException;
061: import java.io.InputStream;
062: import java.io.InputStreamReader;
063: import java.io.Reader;
064: import java.net.URL;
065:
066: import org.apache.wsif.logging.Trc;
067:
068: import com.ibm.wsdl.util.StringUtils;
069:
070: /**
071: * Implementation of javax.wsdl.xml.WSDLLocator. This class can be used to
072: * locate a wsdl document and its imports using a ClassLoader. This is useful
073: * when the wsdl is located in a jar/zip file.
074: *
075: * @author Owen Burroughs <owenb@apache.org>
076: */
077: public class WSIFWSDLLocatorImpl implements javax.wsdl.xml.WSDLLocator {
078:
079: Reader baseReader = null;
080: Reader importReader = null;
081: String contextURI = null;
082: String wsdlLocation = null;
083: String documentBase = null;
084: String importBase = null;
085: ClassLoader loader = null;
086:
087: /**
088: * Create an instance of WSIFWSDLLocatorImpl.
089: * @param ctxt The context uri for the wsdl location
090: * @param wsdlURI The uri for the base wsdl document
091: * @param cl A ClassLoader to use in locating the base wsdl document and imports
092: */
093: public WSIFWSDLLocatorImpl(String ctxt, String wsdlURI,
094: ClassLoader cl) {
095: Trc.entry(this , ctxt, wsdlURI, cl);
096: contextURI = ctxt;
097: wsdlLocation = wsdlURI;
098: loader = cl;
099: Trc.exit();
100: }
101:
102: /**
103: * Create an instance of WSIFWSDLLocatorImpl.
104: * @param docBase The uri for the base wsdl document
105: * @param reader A reader "directed at" the base wsdl document
106: * @param cl A ClassLoader to use in locating the base wsdl document and imports
107: */
108: public WSIFWSDLLocatorImpl(String docBase, Reader reader,
109: ClassLoader cl) {
110: Trc.entry(this , docBase, cl);
111: documentBase = docBase;
112: baseReader = reader;
113: loader = cl;
114: Trc.exit();
115: }
116:
117: /**
118: * Get a reader for the base wsdl document. Returns null if the document
119: * cannot be located.
120: * @return The reader or null if the import cannot be resolved
121: */
122: public Reader getBaseReader() {
123: Trc.entry(this );
124: if (baseReader == null) {
125: try {
126: URL url = null;
127: URL contextURL = (contextURI != null) ? StringUtils
128: .getURL(null, contextURI) : null;
129: if (loader != null) {
130: InputStream in = null;
131: try {
132: if (contextURL != null)
133: url = new URL(contextURL, wsdlLocation);
134: else {
135: if (wsdlLocation.indexOf(":") == -1)
136: url = new URL("file", null,
137: wsdlLocation);
138: else
139: url = new URL(wsdlLocation);
140: }
141: String wsdlRelativeLocation = url.getPath();
142: if (wsdlRelativeLocation.startsWith("/"))
143: wsdlRelativeLocation = wsdlRelativeLocation
144: .substring(1);
145: in = loader
146: .getResourceAsStream(wsdlRelativeLocation);
147: baseReader = new InputStreamReader(in);
148: } catch (Exception exc) {
149: Trc.ignoredException(exc);
150: }
151: }
152: if (baseReader == null) {
153: url = StringUtils.getURL(contextURL, wsdlLocation);
154: baseReader = StringUtils.getContentAsReader(url);
155: }
156: if (url != null)
157: documentBase = url.toString();
158: } catch (Exception e) {
159: Trc.exception(e);
160: documentBase = wsdlLocation;
161: }
162: }
163: Trc.exit();
164: return baseReader;
165: }
166:
167: /**
168: * Get a reader for an imported wsdl document. Returns null if the import document
169: * cannot be located.
170: * @param base The document base uri for the parent wsdl document
171: * @param relativeLocation The relative uri of the import wsdl document
172: * @return The reader or null if the import cannot be resolved
173: */
174: public Reader getImportReader(String base, String relativeLocation) {
175: Trc.entry(this , base, relativeLocation);
176:
177: // Reset importReader if finding import within import
178: importReader = null;
179: boolean triedSU = false;
180: try {
181: // If a ClassLoader was used to load the base document, chances
182: // are we need to use it to find the import.
183: URL url = null;
184: if (loader != null) {
185: if (relativeLocation.startsWith("/")
186: || relativeLocation.startsWith("\\")) {
187: // Relative location has been specified from a root dir. However,
188: // using a ClassLoader, root dirs don't mean anything.
189: relativeLocation = relativeLocation.substring(1,
190: relativeLocation.length());
191: InputStream in = loader
192: .getResourceAsStream(relativeLocation);
193: importReader = new InputStreamReader(in);
194: } else if (relativeLocation.indexOf("://") != -1) {
195: // This is a fully specified URL of some kind so don't use the
196: // ClassLoader to find the import.
197: triedSU = true;
198: url = StringUtils.getURL(null, relativeLocation);
199: importReader = StringUtils.getContentAsReader(url);
200: } else {
201: // Import location has been specified relative to the base document
202: // and so we can to try to form the complete path to it.
203: if (base != null) {
204: int i = base.lastIndexOf("/");
205: if (i == -1)
206: i = base.lastIndexOf("\\");
207: if (i != -1) {
208: String path = base.substring(0, i + 1);
209: String resolvedPath = path
210: + relativeLocation;
211: if (relativeLocation.startsWith("..")) {
212: resolvedPath = resolvePath(path,
213: relativeLocation);
214: }
215: if (resolvedPath == null) {
216: throw new Exception("Invalid Path");
217: }
218:
219: // Make sure that resolved path starts with file:
220: if (resolvedPath.startsWith("file:")) {
221: url = new URL(null, resolvedPath);
222: } else {
223: url = new URL(null, "file:"
224: + resolvedPath);
225: }
226: } else {
227: url = new URL(null, "file:"
228: + relativeLocation);
229: }
230: InputStream in = loader.getResourceAsStream(url
231: .getPath());
232: importReader = new InputStreamReader(in);
233: } else {
234: url = new URL(null, "file:" + relativeLocation);
235: InputStream in = loader.getResourceAsStream(url
236: .getPath());
237: importReader = new InputStreamReader(in);
238: }
239: }
240: } else {
241: triedSU = true;
242: URL contextURL = (base != null) ? StringUtils.getURL(
243: null, base) : null;
244: url = StringUtils.getURL(contextURL, relativeLocation);
245: importReader = StringUtils.getContentAsReader(url);
246: }
247: importBase = (url == null) ? relativeLocation : url
248: .toString();
249: } catch (Exception e) {
250: Trc.exception(e);
251: // If we have not tried using a non-ClassLoader route, try it now
252: // as a last resort.
253: if (!triedSU) {
254: try {
255: URL contextURL = (base != null) ? StringUtils
256: .getURL(null, base) : null;
257: URL url = StringUtils.getURL(contextURL,
258: relativeLocation);
259: importReader = StringUtils.getContentAsReader(url);
260: importBase = (url == null) ? relativeLocation : url
261: .toString();
262: } catch (Exception e2) {
263: Trc.exception(e2);
264: // we can't find the import so set a temporary value for the import URI. This is
265: // necessary to avoid a NullPointerException in WSDLReaderImpl
266: importBase = "unknownImportURI";
267: }
268: } else {
269: // we can't find the import so set a temporary value for the import URI. This is
270: // necessary to avoid a NullPointerException in WSDLReaderImpl
271: importBase = "unknownImportURI";
272: }
273: }
274: Trc.exit();
275: return importReader;
276: }
277:
278: /**
279: * Get the document base uri for the base wsdl document
280: * @return The document base uri
281: */
282: public String getBaseURI() {
283: Trc.entry(this );
284: Trc.exit(documentBase);
285: return documentBase;
286: }
287:
288: /**
289: * Get the document base uri for the last import document to be resolved
290: * by this locator. This is useful if resolving imports within imports.
291: * @return The document base uri
292: */
293: public String getLatestImportURI() {
294: Trc.entry(this );
295: Trc.exit(importBase);
296: return importBase;
297: }
298:
299: /**
300: * Resolve a path when the relative location begins with ..
301: */
302: private String resolvePath(String ba, String rel) {
303: StringBuffer sb = new StringBuffer(rel);
304: int dd = 0;
305: while (sb.length() > 0) {
306: if (sb.length() > 3 && sb.charAt(0) == '.'
307: && sb.charAt(1) == '.'
308: && (sb.charAt(2) == '/' || sb.charAt(2) == '\\')) {
309: dd++;
310: sb.delete(0, 3);
311: } else {
312: break;
313: }
314: }
315: StringBuffer sb2 = new StringBuffer(ba);
316: int j = sb2.length() - 1;
317: int found = 0;
318: for (int k = j; k >= 0; k--) {
319: if (k != j
320: && (sb2.charAt(k) == '/' || sb2.charAt(k) == '\\')) {
321: found++;
322: }
323: if (found < dd) {
324: sb2.deleteCharAt(k);
325: } else {
326: break;
327: }
328: }
329: if (found + 1 < dd)
330: return null;
331: return sb2.toString() + sb.toString();
332: }
333:
334: /**
335: * Close any Reader objects that have been created
336: * @throws IOException If a call to close() on one of the Reader objects fails
337: */
338: public void close() throws IOException {
339: if (baseReader != null)
340: baseReader.close();
341: if (importReader != null)
342: importReader.close();
343: }
344: }
|