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.io.UnsupportedEncodingException;
065: import java.net.URL;
066: import java.net.URLConnection;
067:
068: import javax.wsdl.WSDLException;
069:
070: /**
071: * Implementation of javax.wsdl.xml.WSDLLocator. This class can be used to
072: * locate a wsdl document behind an authenticating proxy. Only http and ftp
073: * urls for the wsdl location are supported.
074: *
075: * @author Owen Burroughs <owenb@apache.org>
076: */
077: public class AuthenticatingProxyWSDLLocatorImpl implements
078: javax.wsdl.xml.WSDLLocator {
079:
080: private static final String PROXY_AUTH = "Proxy-Authorization";
081: private static final char[] BASE64_CHARS = { 'A', 'B', 'C', 'D',
082: 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
083: 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
084: 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
085: 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
086: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
087: private static final char BASE64_PAD_CHAR = '=';
088:
089: Reader baseReader = null;
090: Reader importReader = null;
091: String documentBase = "";
092: String importBase = "";
093: String wsdlLocation = "";
094: String username = null;
095: String password = null;
096: String authString = null;
097:
098: /**
099: * Create an instance of AuthenticatingProxyWSDLLocatorImpl.
100: * @param wsdlLoc The uri for the base wsdl document
101: * @param un The username for proxy authentication
102: * @param passed The password for proxy authentication
103: */
104: public AuthenticatingProxyWSDLLocatorImpl(String wsdlLoc,
105: String un, String passwd) throws WSDLException {
106:
107: if (wsdlLoc == null
108: || (wsdlLoc.indexOf("http://") == -1 && wsdlLoc
109: .indexOf("ftp://") == -1)) {
110: throw new WSDLException(
111: WSDLException.OTHER_ERROR,
112: "Base wsdl location type not supported. The AuthenticatingProxyWSDLLocatorImpl class "
113: + "only supports http and ftp urls for base wsdl locations");
114: }
115: this .wsdlLocation = wsdlLoc;
116: this .username = un;
117: this .password = passwd;
118: }
119:
120: /**
121: * Get a reader for the base wsdl document. Returns null if the document
122: * cannot be located.
123: * @return The reader or null if the import cannot be resolved
124: */
125: public Reader getBaseReader() {
126: if (baseReader == null) {
127: try {
128: URL url = new URL(wsdlLocation);
129: URLConnection con = url.openConnection();
130: createAuthString();
131: if (authString != null) {
132: con.setRequestProperty(PROXY_AUTH, authString);
133: }
134: InputStream in = con.getInputStream();
135: if (in != null) {
136: baseReader = new InputStreamReader(in);
137: }
138: if (url != null)
139: documentBase = url.toString();
140: } catch (Exception e) {
141: documentBase = wsdlLocation;
142: }
143: }
144: return baseReader;
145: }
146:
147: /**
148: * Get a reader for an imported wsdl document. Returns null if the import document
149: * cannot be located.
150: * @param base The document base uri for the parent wsdl document
151: * @param relativeLocation The relative uri of the import wsdl document
152: * @return The reader or null if the import cannot be resolved
153: */
154: public Reader getImportReader(String base, String relativeLocation) {
155: try {
156: URL contextURL = (base != null) ? new URL(base) : null;
157: URL url = new URL(contextURL, relativeLocation);
158: URLConnection con = url.openConnection();
159: createAuthString();
160: if (authString != null) {
161: con.setRequestProperty(PROXY_AUTH, authString);
162: }
163: InputStream in = con.getInputStream();
164: if (in != null) {
165: importReader = new InputStreamReader(in);
166: }
167: importBase = (url == null) ? relativeLocation : url
168: .toString();
169: } catch (Exception e2) {
170: // we can't find the import so set a temporary value for the import URI. This is
171: // necessary to avoid a NullPointerException in WSDLReaderImpl
172: importBase = "unknownImportURI";
173: }
174: return importReader;
175: }
176:
177: /**
178: * Get the document base uri for the base wsdl document
179: * @return The document base uri
180: */
181: public String getBaseURI() {
182: return documentBase;
183: }
184:
185: /**
186: * Get the document base uri for the last import document to be resolved
187: * by this locator. This is useful if resolving imports within imports.
188: * @return The document base uri
189: */
190: public String getLatestImportURI() {
191: return importBase;
192: }
193:
194: /**
195: * Generate the proxy authentication header value. Base64 encoding
196: * code is based on that from Apache Axis and Apache SOAP, written
197: * by TAMURA Kent <kent@trl.ibm.co.jp>
198: */
199: private void createAuthString() {
200: // Don't recreate the String if it has already been created
201: if (authString != null)
202: return;
203: // Unless all information is provided we can't create the String
204: if (username == null || password == null)
205: return;
206:
207: byte[] data = null;
208: try {
209: data = (username + ":" + password).getBytes("8859_1");
210: } catch (UnsupportedEncodingException uee) {
211: return;
212: }
213: int len = data.length;
214: char[] out = new char[len / 3 * 4 + 4];
215: int readIndex = 0;
216: int writeIndex = 0;
217: int remainingBytes = len;
218: while (remainingBytes >= 3) {
219: int i = ((data[readIndex] & 0xff) << 16)
220: + ((data[readIndex + 1] & 0xff) << 8)
221: + (data[readIndex + 2] & 0xff);
222: out[writeIndex++] = BASE64_CHARS[i >> 18];
223: out[writeIndex++] = BASE64_CHARS[(i >> 12) & 0x3f];
224: out[writeIndex++] = BASE64_CHARS[(i >> 6) & 0x3f];
225: out[writeIndex++] = BASE64_CHARS[i & 0x3f];
226: readIndex += 3;
227: remainingBytes -= 3;
228: }
229: // Deal with adding padding characters if the number of bytes in the data
230: // array was not exactly divisible by 3.
231: if (remainingBytes == 1) {
232: int i = data[readIndex] & 0xff;
233: out[writeIndex++] = BASE64_CHARS[i >> 2];
234: out[writeIndex++] = BASE64_CHARS[(i << 4) & 0x3f];
235: out[writeIndex++] = BASE64_PAD_CHAR;
236: out[writeIndex++] = BASE64_PAD_CHAR;
237: } else if (remainingBytes == 2) {
238: int i = ((data[readIndex] & 0xff) << 8)
239: + (data[readIndex + 1] & 0xff);
240: out[writeIndex++] = BASE64_CHARS[i >> 10];
241: out[writeIndex++] = BASE64_CHARS[(i >> 4) & 0x3f];
242: out[writeIndex++] = BASE64_CHARS[(i << 2) & 0x3f];
243: out[writeIndex++] = BASE64_PAD_CHAR;
244: }
245:
246: String encoded = new String(out, 0, writeIndex);
247: authString = "Basic " + encoded;
248: }
249:
250: /**
251: * Close any Reader objects that have been created
252: * @throws IOException If a call to close() on one of the Reader objects fails
253: */
254: public void close() throws IOException {
255: if (baseReader != null)
256: baseReader.close();
257: if (importReader != null)
258: importReader.close();
259: }
260: }
|