Mon, 04 May 2009 21:10:41 -0700
6658158: Mutable statics in SAAJ (findbugs)
6658163: txw2.DatatypeWriter.BUILDIN is a mutable static (findbugs)
Reviewed-by: darcy
duke@1 | 1 | /* |
tbell@45 | 2 | * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. |
duke@1 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@1 | 4 | * |
duke@1 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@1 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@1 | 7 | * published by the Free Software Foundation. Sun designates this |
duke@1 | 8 | * particular file as subject to the "Classpath" exception as provided |
duke@1 | 9 | * by Sun in the LICENSE file that accompanied this code. |
duke@1 | 10 | * |
duke@1 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@1 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@1 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@1 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@1 | 15 | * accompanied this code). |
duke@1 | 16 | * |
duke@1 | 17 | * You should have received a copy of the GNU General Public License version |
duke@1 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@1 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@1 | 20 | * |
duke@1 | 21 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
duke@1 | 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
duke@1 | 23 | * have any questions. |
duke@1 | 24 | */ |
tbell@45 | 25 | /* |
tbell@45 | 26 | * $Id: HttpSOAPConnection.java,v 1.41 2006/01/27 12:49:17 vj135062 Exp $ |
tbell@45 | 27 | * $Revision: 1.41 $ |
tbell@45 | 28 | * $Date: 2006/01/27 12:49:17 $ |
tbell@45 | 29 | */ |
tbell@45 | 30 | |
tbell@45 | 31 | |
duke@1 | 32 | package com.sun.xml.internal.messaging.saaj.client.p2p; |
duke@1 | 33 | |
duke@1 | 34 | import java.io.*; |
duke@1 | 35 | import java.lang.reflect.Method; |
duke@1 | 36 | import java.net.*; |
duke@1 | 37 | import java.security.*; |
duke@1 | 38 | import java.util.Iterator; |
duke@1 | 39 | import java.util.StringTokenizer; |
duke@1 | 40 | import java.util.logging.Level; |
duke@1 | 41 | import java.util.logging.Logger; |
duke@1 | 42 | |
duke@1 | 43 | import javax.xml.soap.*; |
duke@1 | 44 | |
duke@1 | 45 | import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl; |
duke@1 | 46 | import com.sun.xml.internal.messaging.saaj.util.*; |
duke@1 | 47 | |
duke@1 | 48 | /** |
duke@1 | 49 | * This represents a "connection" to the simple HTTP-based provider. |
duke@1 | 50 | * |
duke@1 | 51 | * @author Anil Vijendran (akv@eng.sun.com) |
duke@1 | 52 | * @author Rajiv Mordani (rajiv.mordani@sun.com) |
duke@1 | 53 | * @author Manveen Kaur (manveen.kaur@sun.com) |
duke@1 | 54 | * |
duke@1 | 55 | */ |
duke@1 | 56 | public class HttpSOAPConnection extends SOAPConnection { |
duke@1 | 57 | |
tbell@50 | 58 | public static final String vmVendor = System.getProperty("java.vendor.url"); |
tbell@50 | 59 | private static final String sunVmVendor = "http://java.sun.com/"; |
tbell@50 | 60 | private static final String ibmVmVendor = "http://www.ibm.com/"; |
tbell@50 | 61 | private static final boolean isSunVM = sunVmVendor.equals(vmVendor) ? true: false; |
tbell@50 | 62 | private static final boolean isIBMVM = ibmVmVendor.equals(vmVendor) ? true : false; |
tbell@50 | 63 | private static final String JAXM_URLENDPOINT="javax.xml.messaging.URLEndpoint"; |
tbell@50 | 64 | |
tbell@50 | 65 | protected static final Logger log = |
duke@1 | 66 | Logger.getLogger(LogDomainConstants.HTTP_CONN_DOMAIN, |
duke@1 | 67 | "com.sun.xml.internal.messaging.saaj.client.p2p.LocalStrings"); |
duke@1 | 68 | |
tbell@50 | 69 | public static final String defaultProxyHost = null; |
tbell@50 | 70 | public static final int defaultProxyPort = -1; |
duke@1 | 71 | |
duke@1 | 72 | MessageFactory messageFactory = null; |
duke@1 | 73 | |
duke@1 | 74 | boolean closed = false; |
duke@1 | 75 | |
duke@1 | 76 | public HttpSOAPConnection() throws SOAPException { |
duke@1 | 77 | proxyHost = defaultProxyHost; |
duke@1 | 78 | proxyPort = defaultProxyPort; |
duke@1 | 79 | |
duke@1 | 80 | try { |
duke@1 | 81 | messageFactory = MessageFactory.newInstance(SOAPConstants.DYNAMIC_SOAP_PROTOCOL); |
tbell@50 | 82 | } catch (NoSuchMethodError ex) { |
tbell@50 | 83 | //fallback to default SOAP 1.1 in this case for backward compatibility |
tbell@50 | 84 | messageFactory = MessageFactory.newInstance(); |
duke@1 | 85 | } catch (Exception ex) { |
duke@1 | 86 | log.log(Level.SEVERE, "SAAJ0001.p2p.cannot.create.msg.factory", ex); |
duke@1 | 87 | throw new SOAPExceptionImpl("Unable to create message factory", ex); |
duke@1 | 88 | } |
duke@1 | 89 | } |
duke@1 | 90 | |
duke@1 | 91 | public void close() throws SOAPException { |
duke@1 | 92 | if (closed) { |
duke@1 | 93 | log.severe("SAAJ0002.p2p.close.already.closed.conn"); |
duke@1 | 94 | throw new SOAPExceptionImpl("Connection already closed"); |
duke@1 | 95 | } |
duke@1 | 96 | |
duke@1 | 97 | messageFactory = null; |
duke@1 | 98 | closed = true; |
duke@1 | 99 | } |
duke@1 | 100 | |
duke@1 | 101 | public SOAPMessage call(SOAPMessage message, Object endPoint) |
duke@1 | 102 | throws SOAPException { |
duke@1 | 103 | if (closed) { |
duke@1 | 104 | log.severe("SAAJ0003.p2p.call.already.closed.conn"); |
duke@1 | 105 | throw new SOAPExceptionImpl("Connection is closed"); |
duke@1 | 106 | } |
duke@1 | 107 | |
duke@1 | 108 | Class urlEndpointClass = null; |
tbell@50 | 109 | ClassLoader loader = Thread.currentThread().getContextClassLoader(); |
duke@1 | 110 | |
duke@1 | 111 | try { |
tbell@50 | 112 | if (loader != null) { |
tbell@50 | 113 | urlEndpointClass = loader.loadClass(JAXM_URLENDPOINT); |
tbell@50 | 114 | } else { |
tbell@50 | 115 | urlEndpointClass = Class.forName(JAXM_URLENDPOINT); |
tbell@50 | 116 | } |
tbell@50 | 117 | } catch (ClassNotFoundException ex) { |
tbell@50 | 118 | //Do nothing. URLEndpoint is available only when JAXM is there. |
tbell@50 | 119 | log.finest("SAAJ0090.p2p.endpoint.available.only.for.JAXM"); |
tbell@50 | 120 | } |
duke@1 | 121 | |
duke@1 | 122 | if (urlEndpointClass != null) { |
duke@1 | 123 | if (urlEndpointClass.isInstance(endPoint)) { |
duke@1 | 124 | String url = null; |
duke@1 | 125 | |
duke@1 | 126 | try { |
duke@1 | 127 | Method m = urlEndpointClass.getMethod("getURL", (Class[])null); |
duke@1 | 128 | url = (String) m.invoke(endPoint, (Object[])null); |
duke@1 | 129 | } catch (Exception ex) { |
duke@1 | 130 | // TBD -- exception chaining |
duke@1 | 131 | log.log(Level.SEVERE,"SAAJ0004.p2p.internal.err",ex); |
duke@1 | 132 | throw new SOAPExceptionImpl( |
duke@1 | 133 | "Internal error: " + ex.getMessage()); |
duke@1 | 134 | } |
duke@1 | 135 | try { |
duke@1 | 136 | endPoint = new URL(url); |
duke@1 | 137 | } catch (MalformedURLException mex) { |
duke@1 | 138 | log.log(Level.SEVERE,"SAAJ0005.p2p.", mex); |
duke@1 | 139 | throw new SOAPExceptionImpl("Bad URL: " + mex.getMessage()); |
duke@1 | 140 | } |
duke@1 | 141 | } |
duke@1 | 142 | } |
duke@1 | 143 | |
duke@1 | 144 | if (endPoint instanceof java.lang.String) { |
duke@1 | 145 | try { |
duke@1 | 146 | endPoint = new URL((String) endPoint); |
duke@1 | 147 | } catch (MalformedURLException mex) { |
duke@1 | 148 | log.log(Level.SEVERE, "SAAJ0006.p2p.bad.URL", mex); |
duke@1 | 149 | throw new SOAPExceptionImpl("Bad URL: " + mex.getMessage()); |
duke@1 | 150 | } |
duke@1 | 151 | } |
duke@1 | 152 | |
duke@1 | 153 | if (endPoint instanceof URL) |
duke@1 | 154 | try { |
duke@1 | 155 | PriviledgedPost pp = |
duke@1 | 156 | new PriviledgedPost(this, message, (URL) endPoint); |
duke@1 | 157 | SOAPMessage response = |
duke@1 | 158 | (SOAPMessage) AccessController.doPrivileged(pp); |
duke@1 | 159 | |
duke@1 | 160 | return response; |
duke@1 | 161 | } catch (Exception ex) { |
duke@1 | 162 | // TBD -- chaining? |
duke@1 | 163 | throw new SOAPExceptionImpl(ex); |
duke@1 | 164 | } else { |
duke@1 | 165 | log.severe("SAAJ0007.p2p.bad.endPoint.type"); |
duke@1 | 166 | throw new SOAPExceptionImpl("Bad endPoint type " + endPoint); |
duke@1 | 167 | } |
duke@1 | 168 | } |
duke@1 | 169 | |
duke@1 | 170 | static class PriviledgedPost implements PrivilegedExceptionAction { |
duke@1 | 171 | |
duke@1 | 172 | HttpSOAPConnection c; |
duke@1 | 173 | SOAPMessage message; |
duke@1 | 174 | URL endPoint; |
duke@1 | 175 | |
duke@1 | 176 | PriviledgedPost( |
duke@1 | 177 | HttpSOAPConnection c, |
duke@1 | 178 | SOAPMessage message, |
duke@1 | 179 | URL endPoint) { |
duke@1 | 180 | this.c = c; |
duke@1 | 181 | this.message = message; |
duke@1 | 182 | this.endPoint = endPoint; |
duke@1 | 183 | } |
duke@1 | 184 | |
duke@1 | 185 | public Object run() throws Exception { |
duke@1 | 186 | return c.post(message, endPoint); |
duke@1 | 187 | } |
duke@1 | 188 | } |
duke@1 | 189 | |
duke@1 | 190 | // TBD |
duke@1 | 191 | // Fix this to do things better. |
duke@1 | 192 | |
duke@1 | 193 | private String proxyHost = null; |
duke@1 | 194 | |
duke@1 | 195 | static class PriviledgedSetProxyAction implements PrivilegedExceptionAction { |
duke@1 | 196 | |
duke@1 | 197 | String proxyHost = null; |
duke@1 | 198 | int proxyPort = 0; |
duke@1 | 199 | |
duke@1 | 200 | PriviledgedSetProxyAction(String host, int port) { |
duke@1 | 201 | this.proxyHost = host; |
duke@1 | 202 | this.proxyPort = port; |
duke@1 | 203 | } |
duke@1 | 204 | |
duke@1 | 205 | public Object run() throws Exception { |
duke@1 | 206 | System.setProperty("http.proxyHost", proxyHost); |
duke@1 | 207 | System.setProperty("http.proxyPort", new Integer(proxyPort).toString()); |
duke@1 | 208 | log.log(Level.FINE, "SAAJ0050.p2p.proxy.host", |
duke@1 | 209 | new String[] { proxyHost }); |
duke@1 | 210 | log.log(Level.FINE, "SAAJ0051.p2p.proxy.port", |
duke@1 | 211 | new String[] { new Integer(proxyPort).toString() }); |
duke@1 | 212 | return proxyHost; |
duke@1 | 213 | } |
duke@1 | 214 | } |
duke@1 | 215 | |
duke@1 | 216 | |
duke@1 | 217 | public void setProxy(String host, int port) { |
duke@1 | 218 | try { |
duke@1 | 219 | proxyPort = port; |
duke@1 | 220 | PriviledgedSetProxyAction ps = new PriviledgedSetProxyAction(host, port); |
duke@1 | 221 | proxyHost = (String) AccessController.doPrivileged(ps); |
duke@1 | 222 | } catch (Exception e) { |
duke@1 | 223 | throw new RuntimeException(e); |
duke@1 | 224 | } |
duke@1 | 225 | } |
duke@1 | 226 | |
duke@1 | 227 | public String getProxyHost() { |
duke@1 | 228 | return proxyHost; |
duke@1 | 229 | } |
duke@1 | 230 | |
duke@1 | 231 | private int proxyPort = -1; |
duke@1 | 232 | |
duke@1 | 233 | public int getProxyPort() { |
duke@1 | 234 | return proxyPort; |
duke@1 | 235 | } |
duke@1 | 236 | |
duke@1 | 237 | SOAPMessage post(SOAPMessage message, URL endPoint) throws SOAPException { |
duke@1 | 238 | boolean isFailure = false; |
duke@1 | 239 | |
duke@1 | 240 | URL url = null; |
duke@1 | 241 | HttpURLConnection httpConnection = null; |
duke@1 | 242 | |
duke@1 | 243 | int responseCode = 0; |
duke@1 | 244 | try { |
duke@1 | 245 | if (endPoint.getProtocol().equals("https")) |
duke@1 | 246 | //if(!setHttps) |
duke@1 | 247 | initHttps(); |
duke@1 | 248 | // Process the URL |
duke@1 | 249 | JaxmURI uri = new JaxmURI(endPoint.toString()); |
duke@1 | 250 | String userInfo = uri.getUserinfo(); |
duke@1 | 251 | |
duke@1 | 252 | url = endPoint; |
duke@1 | 253 | |
duke@1 | 254 | if (dL > 0) |
duke@1 | 255 | d("uri: " + userInfo + " " + url + " " + uri); |
duke@1 | 256 | |
duke@1 | 257 | // TBD |
duke@1 | 258 | // Will deal with https later. |
duke@1 | 259 | if (!url.getProtocol().equalsIgnoreCase("http") |
duke@1 | 260 | && !url.getProtocol().equalsIgnoreCase("https")) { |
duke@1 | 261 | log.severe("SAAJ0052.p2p.protocol.mustbe.http.or.https"); |
duke@1 | 262 | throw new IllegalArgumentException( |
duke@1 | 263 | "Protocol " |
duke@1 | 264 | + url.getProtocol() |
duke@1 | 265 | + " not supported in URL " |
duke@1 | 266 | + url); |
duke@1 | 267 | } |
duke@1 | 268 | httpConnection = (HttpURLConnection) createConnection(url); |
duke@1 | 269 | |
duke@1 | 270 | httpConnection.setRequestMethod("POST"); |
duke@1 | 271 | |
duke@1 | 272 | httpConnection.setDoOutput(true); |
duke@1 | 273 | httpConnection.setDoInput(true); |
duke@1 | 274 | httpConnection.setUseCaches(false); |
duke@1 | 275 | HttpURLConnection.setFollowRedirects(true); |
duke@1 | 276 | |
duke@1 | 277 | if (message.saveRequired()) |
duke@1 | 278 | message.saveChanges(); |
duke@1 | 279 | |
duke@1 | 280 | MimeHeaders headers = message.getMimeHeaders(); |
duke@1 | 281 | |
duke@1 | 282 | Iterator it = headers.getAllHeaders(); |
duke@1 | 283 | boolean hasAuth = false; // true if we find explicit Auth header |
duke@1 | 284 | while (it.hasNext()) { |
duke@1 | 285 | MimeHeader header = (MimeHeader) it.next(); |
duke@1 | 286 | |
duke@1 | 287 | String[] values = headers.getHeader(header.getName()); |
duke@1 | 288 | |
duke@1 | 289 | if (values.length == 1) |
duke@1 | 290 | httpConnection.setRequestProperty( |
duke@1 | 291 | header.getName(), |
duke@1 | 292 | header.getValue()); |
duke@1 | 293 | else { |
duke@1 | 294 | StringBuffer concat = new StringBuffer(); |
duke@1 | 295 | int i = 0; |
duke@1 | 296 | while (i < values.length) { |
duke@1 | 297 | if (i != 0) |
duke@1 | 298 | concat.append(','); |
duke@1 | 299 | concat.append(values[i]); |
duke@1 | 300 | i++; |
duke@1 | 301 | } |
duke@1 | 302 | |
duke@1 | 303 | httpConnection.setRequestProperty( |
duke@1 | 304 | header.getName(), |
duke@1 | 305 | concat.toString()); |
duke@1 | 306 | } |
duke@1 | 307 | |
duke@1 | 308 | if ("Authorization".equals(header.getName())) { |
duke@1 | 309 | hasAuth = true; |
duke@1 | 310 | log.fine("SAAJ0091.p2p.https.auth.in.POST.true"); |
duke@1 | 311 | } |
duke@1 | 312 | } |
duke@1 | 313 | |
duke@1 | 314 | if (!hasAuth && userInfo != null) { |
duke@1 | 315 | initAuthUserInfo(httpConnection, userInfo); |
duke@1 | 316 | } |
duke@1 | 317 | |
duke@1 | 318 | OutputStream out = httpConnection.getOutputStream(); |
duke@1 | 319 | message.writeTo(out); |
duke@1 | 320 | |
duke@1 | 321 | out.flush(); |
duke@1 | 322 | out.close(); |
duke@1 | 323 | |
duke@1 | 324 | httpConnection.connect(); |
duke@1 | 325 | |
duke@1 | 326 | try { |
duke@1 | 327 | |
duke@1 | 328 | responseCode = httpConnection.getResponseCode(); |
duke@1 | 329 | |
duke@1 | 330 | // let HTTP_INTERNAL_ERROR (500) through because it is used for SOAP faults |
duke@1 | 331 | if (responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR) { |
duke@1 | 332 | isFailure = true; |
duke@1 | 333 | } |
duke@1 | 334 | //else if (responseCode != HttpURLConnection.HTTP_OK) |
duke@1 | 335 | //else if (!(responseCode >= HttpURLConnection.HTTP_OK && responseCode < 207)) |
duke@1 | 336 | else if ((responseCode / 100) != 2) { |
duke@1 | 337 | log.log(Level.SEVERE, |
duke@1 | 338 | "SAAJ0008.p2p.bad.response", |
duke@1 | 339 | new String[] {httpConnection.getResponseMessage()}); |
duke@1 | 340 | throw new SOAPExceptionImpl( |
duke@1 | 341 | "Bad response: (" |
duke@1 | 342 | + responseCode |
duke@1 | 343 | + httpConnection.getResponseMessage()); |
duke@1 | 344 | |
duke@1 | 345 | } |
duke@1 | 346 | } catch (IOException e) { |
duke@1 | 347 | // on JDK1.3.1_01, we end up here, but then getResponseCode() succeeds! |
duke@1 | 348 | responseCode = httpConnection.getResponseCode(); |
duke@1 | 349 | if (responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR) { |
duke@1 | 350 | isFailure = true; |
duke@1 | 351 | } else { |
duke@1 | 352 | throw e; |
duke@1 | 353 | } |
duke@1 | 354 | |
duke@1 | 355 | } |
duke@1 | 356 | |
duke@1 | 357 | } catch (SOAPException ex) { |
duke@1 | 358 | throw ex; |
duke@1 | 359 | } catch (Exception ex) { |
duke@1 | 360 | log.severe("SAAJ0009.p2p.msg.send.failed"); |
duke@1 | 361 | throw new SOAPExceptionImpl("Message send failed", ex); |
duke@1 | 362 | } |
duke@1 | 363 | |
duke@1 | 364 | SOAPMessage response = null; |
duke@1 | 365 | if (responseCode == HttpURLConnection.HTTP_OK || isFailure) { |
duke@1 | 366 | try { |
duke@1 | 367 | MimeHeaders headers = new MimeHeaders(); |
duke@1 | 368 | |
duke@1 | 369 | String key, value; |
duke@1 | 370 | |
duke@1 | 371 | // Header field 0 is the status line so we skip it. |
duke@1 | 372 | |
duke@1 | 373 | int i = 1; |
duke@1 | 374 | |
duke@1 | 375 | while (true) { |
duke@1 | 376 | key = httpConnection.getHeaderFieldKey(i); |
duke@1 | 377 | value = httpConnection.getHeaderField(i); |
duke@1 | 378 | |
duke@1 | 379 | if (key == null && value == null) |
duke@1 | 380 | break; |
duke@1 | 381 | |
duke@1 | 382 | if (key != null) { |
duke@1 | 383 | StringTokenizer values = |
duke@1 | 384 | new StringTokenizer(value, ","); |
duke@1 | 385 | while (values.hasMoreTokens()) |
duke@1 | 386 | headers.addHeader(key, values.nextToken().trim()); |
duke@1 | 387 | } |
duke@1 | 388 | i++; |
duke@1 | 389 | } |
duke@1 | 390 | |
duke@1 | 391 | InputStream httpIn = |
duke@1 | 392 | (isFailure |
duke@1 | 393 | ? httpConnection.getErrorStream() |
duke@1 | 394 | : httpConnection.getInputStream()); |
duke@1 | 395 | |
duke@1 | 396 | byte[] bytes = readFully(httpIn); |
duke@1 | 397 | |
duke@1 | 398 | int length = |
duke@1 | 399 | httpConnection.getContentLength() == -1 |
duke@1 | 400 | ? bytes.length |
duke@1 | 401 | : httpConnection.getContentLength(); |
duke@1 | 402 | |
duke@1 | 403 | // If no reply message is returned, |
duke@1 | 404 | // content-Length header field value is expected to be zero. |
duke@1 | 405 | if (length == 0) { |
duke@1 | 406 | response = null; |
duke@1 | 407 | log.warning("SAAJ0014.p2p.content.zero"); |
duke@1 | 408 | } else { |
duke@1 | 409 | ByteInputStream in = new ByteInputStream(bytes, length); |
duke@1 | 410 | response = messageFactory.createMessage(headers, in); |
duke@1 | 411 | } |
duke@1 | 412 | |
duke@1 | 413 | httpIn.close(); |
duke@1 | 414 | httpConnection.disconnect(); |
duke@1 | 415 | |
duke@1 | 416 | } catch (SOAPException ex) { |
duke@1 | 417 | throw ex; |
duke@1 | 418 | } catch (Exception ex) { |
duke@1 | 419 | log.log(Level.SEVERE,"SAAJ0010.p2p.cannot.read.resp", ex); |
duke@1 | 420 | throw new SOAPExceptionImpl( |
duke@1 | 421 | "Unable to read response: " + ex.getMessage()); |
duke@1 | 422 | } |
duke@1 | 423 | } |
duke@1 | 424 | return response; |
duke@1 | 425 | } |
duke@1 | 426 | |
duke@1 | 427 | // Object identifies where the request should be sent. |
duke@1 | 428 | // It is required to support objects of type String and java.net.URL. |
duke@1 | 429 | |
duke@1 | 430 | public SOAPMessage get(Object endPoint) throws SOAPException { |
duke@1 | 431 | if (closed) { |
duke@1 | 432 | log.severe("SAAJ0011.p2p.get.already.closed.conn"); |
duke@1 | 433 | throw new SOAPExceptionImpl("Connection is closed"); |
duke@1 | 434 | } |
duke@1 | 435 | Class urlEndpointClass = null; |
duke@1 | 436 | |
duke@1 | 437 | try { |
duke@1 | 438 | urlEndpointClass = Class.forName("javax.xml.messaging.URLEndpoint"); |
duke@1 | 439 | } catch (Exception ex) { |
duke@1 | 440 | //Do nothing. URLEndpoint is available only when JAXM is there. |
duke@1 | 441 | } |
duke@1 | 442 | |
duke@1 | 443 | if (urlEndpointClass != null) { |
duke@1 | 444 | if (urlEndpointClass.isInstance(endPoint)) { |
duke@1 | 445 | String url = null; |
duke@1 | 446 | |
duke@1 | 447 | try { |
duke@1 | 448 | Method m = urlEndpointClass.getMethod("getURL", (Class[])null); |
duke@1 | 449 | url = (String) m.invoke(endPoint, (Object[])null); |
duke@1 | 450 | } catch (Exception ex) { |
duke@1 | 451 | log.severe("SAAJ0004.p2p.internal.err"); |
duke@1 | 452 | throw new SOAPExceptionImpl( |
duke@1 | 453 | "Internal error: " + ex.getMessage()); |
duke@1 | 454 | } |
duke@1 | 455 | try { |
duke@1 | 456 | endPoint = new URL(url); |
duke@1 | 457 | } catch (MalformedURLException mex) { |
duke@1 | 458 | log.severe("SAAJ0005.p2p."); |
duke@1 | 459 | throw new SOAPExceptionImpl("Bad URL: " + mex.getMessage()); |
duke@1 | 460 | } |
duke@1 | 461 | } |
duke@1 | 462 | } |
duke@1 | 463 | |
duke@1 | 464 | if (endPoint instanceof java.lang.String) { |
duke@1 | 465 | try { |
duke@1 | 466 | endPoint = new URL((String) endPoint); |
duke@1 | 467 | } catch (MalformedURLException mex) { |
duke@1 | 468 | log.severe("SAAJ0006.p2p.bad.URL"); |
duke@1 | 469 | throw new SOAPExceptionImpl("Bad URL: " + mex.getMessage()); |
duke@1 | 470 | } |
duke@1 | 471 | } |
duke@1 | 472 | |
duke@1 | 473 | if (endPoint instanceof URL) |
duke@1 | 474 | try { |
duke@1 | 475 | PriviledgedGet pg = new PriviledgedGet(this, (URL) endPoint); |
duke@1 | 476 | SOAPMessage response = |
duke@1 | 477 | (SOAPMessage) AccessController.doPrivileged(pg); |
duke@1 | 478 | |
duke@1 | 479 | return response; |
duke@1 | 480 | } catch (Exception ex) { |
duke@1 | 481 | throw new SOAPExceptionImpl(ex); |
duke@1 | 482 | } else |
duke@1 | 483 | throw new SOAPExceptionImpl("Bad endPoint type " + endPoint); |
duke@1 | 484 | } |
duke@1 | 485 | |
duke@1 | 486 | static class PriviledgedGet implements PrivilegedExceptionAction { |
duke@1 | 487 | |
duke@1 | 488 | HttpSOAPConnection c; |
duke@1 | 489 | URL endPoint; |
duke@1 | 490 | |
duke@1 | 491 | PriviledgedGet(HttpSOAPConnection c, URL endPoint) { |
duke@1 | 492 | this.c = c; |
duke@1 | 493 | this.endPoint = endPoint; |
duke@1 | 494 | } |
duke@1 | 495 | |
duke@1 | 496 | public Object run() throws Exception { |
duke@1 | 497 | return c.get(endPoint); |
duke@1 | 498 | } |
duke@1 | 499 | } |
duke@1 | 500 | |
duke@1 | 501 | SOAPMessage get(URL endPoint) throws SOAPException { |
duke@1 | 502 | boolean isFailure = false; |
duke@1 | 503 | |
duke@1 | 504 | URL url = null; |
duke@1 | 505 | HttpURLConnection httpConnection = null; |
duke@1 | 506 | |
duke@1 | 507 | int responseCode = 0; |
duke@1 | 508 | try { |
duke@1 | 509 | /// Is https GET allowed?? |
duke@1 | 510 | if (endPoint.getProtocol().equals("https")) |
duke@1 | 511 | initHttps(); |
duke@1 | 512 | // Process the URL |
duke@1 | 513 | JaxmURI uri = new JaxmURI(endPoint.toString()); |
duke@1 | 514 | String userInfo = uri.getUserinfo(); |
duke@1 | 515 | |
duke@1 | 516 | url = endPoint; |
duke@1 | 517 | |
duke@1 | 518 | if (dL > 0) |
duke@1 | 519 | d("uri: " + userInfo + " " + url + " " + uri); |
duke@1 | 520 | |
duke@1 | 521 | // TBD |
duke@1 | 522 | // Will deal with https later. |
duke@1 | 523 | if (!url.getProtocol().equalsIgnoreCase("http") |
duke@1 | 524 | && !url.getProtocol().equalsIgnoreCase("https")) { |
duke@1 | 525 | log.severe("SAAJ0052.p2p.protocol.mustbe.http.or.https"); |
duke@1 | 526 | throw new IllegalArgumentException( |
duke@1 | 527 | "Protocol " |
duke@1 | 528 | + url.getProtocol() |
duke@1 | 529 | + " not supported in URL " |
duke@1 | 530 | + url); |
duke@1 | 531 | } |
duke@1 | 532 | httpConnection = (HttpURLConnection) createConnection(url); |
duke@1 | 533 | |
duke@1 | 534 | httpConnection.setRequestMethod("GET"); |
duke@1 | 535 | |
duke@1 | 536 | httpConnection.setDoOutput(true); |
duke@1 | 537 | httpConnection.setDoInput(true); |
duke@1 | 538 | httpConnection.setUseCaches(false); |
duke@1 | 539 | HttpURLConnection.setFollowRedirects(true); |
duke@1 | 540 | |
duke@1 | 541 | httpConnection.connect(); |
duke@1 | 542 | |
duke@1 | 543 | try { |
duke@1 | 544 | |
duke@1 | 545 | responseCode = httpConnection.getResponseCode(); |
duke@1 | 546 | |
duke@1 | 547 | // let HTTP_INTERNAL_ERROR (500) through because it is used for SOAP faults |
duke@1 | 548 | if (responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR) { |
duke@1 | 549 | isFailure = true; |
duke@1 | 550 | } else if ((responseCode / 100) != 2) { |
duke@1 | 551 | log.log(Level.SEVERE, |
duke@1 | 552 | "SAAJ0008.p2p.bad.response", |
duke@1 | 553 | new String[] { httpConnection.getResponseMessage()}); |
duke@1 | 554 | throw new SOAPExceptionImpl( |
duke@1 | 555 | "Bad response: (" |
duke@1 | 556 | + responseCode |
duke@1 | 557 | + httpConnection.getResponseMessage()); |
duke@1 | 558 | |
duke@1 | 559 | } |
duke@1 | 560 | } catch (IOException e) { |
duke@1 | 561 | // on JDK1.3.1_01, we end up here, but then getResponseCode() succeeds! |
duke@1 | 562 | responseCode = httpConnection.getResponseCode(); |
duke@1 | 563 | if (responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR) { |
duke@1 | 564 | isFailure = true; |
duke@1 | 565 | } else { |
duke@1 | 566 | throw e; |
duke@1 | 567 | } |
duke@1 | 568 | |
duke@1 | 569 | } |
duke@1 | 570 | |
duke@1 | 571 | } catch (SOAPException ex) { |
duke@1 | 572 | throw ex; |
duke@1 | 573 | } catch (Exception ex) { |
duke@1 | 574 | log.severe("SAAJ0012.p2p.get.failed"); |
duke@1 | 575 | throw new SOAPExceptionImpl("Get failed", ex); |
duke@1 | 576 | } |
duke@1 | 577 | |
duke@1 | 578 | SOAPMessage response = null; |
duke@1 | 579 | if (responseCode == HttpURLConnection.HTTP_OK || isFailure) { |
duke@1 | 580 | try { |
duke@1 | 581 | MimeHeaders headers = new MimeHeaders(); |
duke@1 | 582 | |
duke@1 | 583 | String key, value; |
duke@1 | 584 | |
duke@1 | 585 | // Header field 0 is the status line so we skip it. |
duke@1 | 586 | |
duke@1 | 587 | int i = 1; |
duke@1 | 588 | |
duke@1 | 589 | while (true) { |
duke@1 | 590 | key = httpConnection.getHeaderFieldKey(i); |
duke@1 | 591 | value = httpConnection.getHeaderField(i); |
duke@1 | 592 | |
duke@1 | 593 | if (key == null && value == null) |
duke@1 | 594 | break; |
duke@1 | 595 | |
duke@1 | 596 | if (key != null) { |
duke@1 | 597 | StringTokenizer values = |
duke@1 | 598 | new StringTokenizer(value, ","); |
duke@1 | 599 | while (values.hasMoreTokens()) |
duke@1 | 600 | headers.addHeader(key, values.nextToken().trim()); |
duke@1 | 601 | } |
duke@1 | 602 | i++; |
duke@1 | 603 | } |
duke@1 | 604 | |
duke@1 | 605 | InputStream httpIn = |
duke@1 | 606 | (isFailure |
duke@1 | 607 | ? httpConnection.getErrorStream() |
duke@1 | 608 | : httpConnection.getInputStream()); |
duke@1 | 609 | |
duke@1 | 610 | byte[] bytes = readFully(httpIn); |
duke@1 | 611 | |
duke@1 | 612 | int length = |
duke@1 | 613 | httpConnection.getContentLength() == -1 |
duke@1 | 614 | ? bytes.length |
duke@1 | 615 | : httpConnection.getContentLength(); |
duke@1 | 616 | |
duke@1 | 617 | // If no reply message is returned, |
duke@1 | 618 | // content-Length header field value is expected to be zero. |
duke@1 | 619 | if (length == 0) { |
duke@1 | 620 | response = null; |
duke@1 | 621 | log.warning("SAAJ0014.p2p.content.zero"); |
duke@1 | 622 | } else { |
duke@1 | 623 | |
duke@1 | 624 | ByteInputStream in = new ByteInputStream(bytes, length); |
duke@1 | 625 | response = messageFactory.createMessage(headers, in); |
duke@1 | 626 | } |
duke@1 | 627 | |
duke@1 | 628 | httpIn.close(); |
duke@1 | 629 | httpConnection.disconnect(); |
duke@1 | 630 | |
duke@1 | 631 | } catch (SOAPException ex) { |
duke@1 | 632 | throw ex; |
duke@1 | 633 | } catch (Exception ex) { |
duke@1 | 634 | log.log(Level.SEVERE, |
duke@1 | 635 | "SAAJ0010.p2p.cannot.read.resp", |
duke@1 | 636 | ex); |
duke@1 | 637 | throw new SOAPExceptionImpl( |
duke@1 | 638 | "Unable to read response: " + ex.getMessage()); |
duke@1 | 639 | } |
duke@1 | 640 | } |
duke@1 | 641 | return response; |
duke@1 | 642 | } |
duke@1 | 643 | |
duke@1 | 644 | private byte[] readFully(InputStream istream) throws IOException { |
duke@1 | 645 | ByteArrayOutputStream bout = new ByteArrayOutputStream(); |
duke@1 | 646 | byte[] buf = new byte[1024]; |
duke@1 | 647 | int num = 0; |
duke@1 | 648 | |
duke@1 | 649 | while ((num = istream.read(buf)) != -1) { |
duke@1 | 650 | bout.write(buf, 0, num); |
duke@1 | 651 | } |
duke@1 | 652 | |
duke@1 | 653 | byte[] ret = bout.toByteArray(); |
duke@1 | 654 | |
duke@1 | 655 | return ret; |
duke@1 | 656 | } |
tbell@50 | 657 | //private static String SSL_PKG = "com.sun.net.ssl.internal.www.protocol"; |
tbell@50 | 658 | //private static String SSL_PROVIDER = |
tbell@50 | 659 | // "com.sun.net.ssl.internal.ssl.Provider"; |
tbell@50 | 660 | private static final String SSL_PKG; |
tbell@50 | 661 | private static final String SSL_PROVIDER; |
duke@1 | 662 | |
tbell@50 | 663 | |
tbell@50 | 664 | static { |
tbell@50 | 665 | if (isIBMVM) { |
tbell@50 | 666 | SSL_PKG ="com.ibm.net.ssl.internal.www.protocol"; |
tbell@50 | 667 | SSL_PROVIDER ="com.ibm.net.ssl.internal.ssl.Provider"; |
tbell@50 | 668 | } else { |
tbell@50 | 669 | //if not IBM VM default to Sun. |
tbell@50 | 670 | SSL_PKG = "com.sun.net.ssl.internal.www.protocol"; |
tbell@50 | 671 | SSL_PROVIDER ="com.sun.net.ssl.internal.ssl.Provider"; |
tbell@50 | 672 | } |
tbell@50 | 673 | } |
duke@1 | 674 | private void initHttps() { |
duke@1 | 675 | //if(!setHttps) { |
duke@1 | 676 | String pkgs = System.getProperty("java.protocol.handler.pkgs"); |
duke@1 | 677 | log.log(Level.FINE, |
duke@1 | 678 | "SAAJ0053.p2p.providers", |
duke@1 | 679 | new String[] { pkgs }); |
duke@1 | 680 | |
duke@1 | 681 | if (pkgs == null || pkgs.indexOf(SSL_PKG) < 0) { |
duke@1 | 682 | if (pkgs == null) |
duke@1 | 683 | pkgs = SSL_PKG; |
duke@1 | 684 | else |
duke@1 | 685 | pkgs = pkgs + "|" + SSL_PKG; |
duke@1 | 686 | System.setProperty("java.protocol.handler.pkgs", pkgs); |
duke@1 | 687 | log.log(Level.FINE, |
duke@1 | 688 | "SAAJ0054.p2p.set.providers", |
duke@1 | 689 | new String[] { pkgs }); |
duke@1 | 690 | try { |
duke@1 | 691 | Class c = Class.forName(SSL_PROVIDER); |
duke@1 | 692 | Provider p = (Provider) c.newInstance(); |
duke@1 | 693 | Security.addProvider(p); |
duke@1 | 694 | log.log(Level.FINE, |
duke@1 | 695 | "SAAJ0055.p2p.added.ssl.provider", |
duke@1 | 696 | new String[] { SSL_PROVIDER }); |
duke@1 | 697 | //System.out.println("Added SSL_PROVIDER " + SSL_PROVIDER); |
duke@1 | 698 | //setHttps = true; |
duke@1 | 699 | } catch (Exception ex) { |
duke@1 | 700 | } |
duke@1 | 701 | } |
duke@1 | 702 | //} |
duke@1 | 703 | } |
duke@1 | 704 | |
duke@1 | 705 | private void initAuthUserInfo(HttpURLConnection conn, String userInfo) { |
duke@1 | 706 | String user; |
duke@1 | 707 | String password; |
duke@1 | 708 | if (userInfo != null) { // get the user and password |
duke@1 | 709 | //System.out.println("UserInfo= " + userInfo ); |
duke@1 | 710 | int delimiter = userInfo.indexOf(':'); |
duke@1 | 711 | if (delimiter == -1) { |
duke@1 | 712 | user = ParseUtil.decode(userInfo); |
duke@1 | 713 | password = null; |
duke@1 | 714 | } else { |
duke@1 | 715 | user = ParseUtil.decode(userInfo.substring(0, delimiter++)); |
duke@1 | 716 | password = ParseUtil.decode(userInfo.substring(delimiter)); |
duke@1 | 717 | } |
duke@1 | 718 | |
duke@1 | 719 | String plain = user + ":"; |
duke@1 | 720 | byte[] nameBytes = plain.getBytes(); |
duke@1 | 721 | byte[] passwdBytes = password.getBytes(); |
duke@1 | 722 | |
duke@1 | 723 | // concatenate user name and password bytes and encode them |
duke@1 | 724 | byte[] concat = new byte[nameBytes.length + passwdBytes.length]; |
duke@1 | 725 | |
duke@1 | 726 | System.arraycopy(nameBytes, 0, concat, 0, nameBytes.length); |
duke@1 | 727 | System.arraycopy( |
duke@1 | 728 | passwdBytes, |
duke@1 | 729 | 0, |
duke@1 | 730 | concat, |
duke@1 | 731 | nameBytes.length, |
duke@1 | 732 | passwdBytes.length); |
duke@1 | 733 | String auth = "Basic " + new String(Base64.encode(concat)); |
duke@1 | 734 | conn.setRequestProperty("Authorization", auth); |
duke@1 | 735 | if (dL > 0) |
duke@1 | 736 | d("Adding auth " + auth); |
duke@1 | 737 | } |
duke@1 | 738 | } |
duke@1 | 739 | |
duke@1 | 740 | private static final int dL = 0; |
duke@1 | 741 | private void d(String s) { |
duke@1 | 742 | log.log(Level.SEVERE, |
duke@1 | 743 | "SAAJ0013.p2p.HttpSOAPConnection", |
duke@1 | 744 | new String[] { s }); |
duke@1 | 745 | System.err.println("HttpSOAPConnection: " + s); |
duke@1 | 746 | } |
duke@1 | 747 | |
duke@1 | 748 | private java.net.HttpURLConnection createConnection(URL endpoint) |
duke@1 | 749 | throws IOException { |
duke@1 | 750 | return (HttpURLConnection) endpoint.openConnection(); |
duke@1 | 751 | } |
duke@1 | 752 | |
duke@1 | 753 | } |