src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.messaging.saaj.client.p2p;
    28 import java.io.*;
    29 import java.lang.reflect.Method;
    30 import java.net.*;
    31 import java.security.*;
    32 import java.util.Iterator;
    33 import java.util.StringTokenizer;
    34 import java.util.logging.Level;
    35 import java.util.logging.Logger;
    37 import javax.xml.soap.*;
    39 import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl;
    40 import com.sun.xml.internal.messaging.saaj.util.*;
    42 /**
    43  * This represents a "connection" to the simple HTTP-based provider.
    44  *
    45  * @author Anil Vijendran (akv@eng.sun.com)
    46  * @author Rajiv Mordani (rajiv.mordani@sun.com)
    47  * @author Manveen Kaur (manveen.kaur@sun.com)
    48  *
    49  */
    50 class HttpSOAPConnection extends SOAPConnection {
    52     public static final String vmVendor = SAAJUtil.getSystemProperty("java.vendor.url");
    53     private static final String sunVmVendor = "http://java.sun.com/";
    54     private static final String ibmVmVendor = "http://www.ibm.com/";
    55     private static final boolean isSunVM = sunVmVendor.equals(vmVendor) ? true: false;
    56     private static final boolean isIBMVM = ibmVmVendor.equals(vmVendor) ? true : false;
    57     private static final String JAXM_URLENDPOINT="javax.xml.messaging.URLEndpoint";
    59     protected static final Logger log =
    60         Logger.getLogger(LogDomainConstants.HTTP_CONN_DOMAIN,
    61                          "com.sun.xml.internal.messaging.saaj.client.p2p.LocalStrings");
    64     MessageFactory messageFactory = null;
    66     boolean closed = false;
    68     public HttpSOAPConnection() throws SOAPException {
    70         try {
    71             messageFactory = MessageFactory.newInstance(SOAPConstants.DYNAMIC_SOAP_PROTOCOL);
    72         } catch (NoSuchMethodError ex) {
    73             //fallback to default SOAP 1.1 in this case for backward compatibility
    74             messageFactory = MessageFactory.newInstance();
    75         } catch (Exception ex) {
    76             log.log(Level.SEVERE, "SAAJ0001.p2p.cannot.create.msg.factory", ex);
    77             throw new SOAPExceptionImpl("Unable to create message factory", ex);
    78         }
    79     }
    81     public void close() throws SOAPException {
    82         if (closed) {
    83             log.severe("SAAJ0002.p2p.close.already.closed.conn");
    84             throw new SOAPExceptionImpl("Connection already closed");
    85         }
    87         messageFactory = null;
    88         closed = true;
    89     }
    91    public SOAPMessage call(SOAPMessage message, Object endPoint)
    92         throws SOAPException {
    93         if (closed) {
    94             log.severe("SAAJ0003.p2p.call.already.closed.conn");
    95             throw new SOAPExceptionImpl("Connection is closed");
    96         }
    98         Class urlEndpointClass = null;
    99         ClassLoader loader = Thread.currentThread().getContextClassLoader();
   100         try {
   101             if (loader != null) {
   102                 urlEndpointClass = loader.loadClass(JAXM_URLENDPOINT);
   103             } else {
   104                 urlEndpointClass = Class.forName(JAXM_URLENDPOINT);
   105             }
   106         } catch (ClassNotFoundException ex) {
   107             //Do nothing. URLEndpoint is available only when JAXM is there.
   108             if (log.isLoggable(Level.FINEST))
   109                 log.finest("SAAJ0090.p2p.endpoint.available.only.for.JAXM");
   110         }
   112         if (urlEndpointClass != null) {
   113             if (urlEndpointClass.isInstance(endPoint)) {
   114                 String url = null;
   116                 try {
   117                     Method m = urlEndpointClass.getMethod("getURL", (Class[])null);
   118                     url = (String) m.invoke(endPoint, (Object[])null);
   119                 } catch (Exception ex) {
   120                     // TBD -- exception chaining
   121                     log.log(Level.SEVERE,"SAAJ0004.p2p.internal.err",ex);
   122                     throw new SOAPExceptionImpl(
   123                         "Internal error: " + ex.getMessage());
   124                 }
   125                 try {
   126                     endPoint = new URL(url);
   127                 } catch (MalformedURLException mex) {
   128                     log.log(Level.SEVERE,"SAAJ0005.p2p.", mex);
   129                     throw new SOAPExceptionImpl("Bad URL: " + mex.getMessage());
   130                 }
   131             }
   132         }
   134         if (endPoint instanceof java.lang.String) {
   135             try {
   136                 endPoint = new URL((String) endPoint);
   137             } catch (MalformedURLException mex) {
   138                 log.log(Level.SEVERE, "SAAJ0006.p2p.bad.URL", mex);
   139                 throw new SOAPExceptionImpl("Bad URL: " + mex.getMessage());
   140             }
   141         }
   143         if (endPoint instanceof URL)
   144             try {
   145                 SOAPMessage response = post(message, (URL)endPoint);
   146                 return response;
   147             } catch (Exception ex) {
   148                 // TBD -- chaining?
   149                 throw new SOAPExceptionImpl(ex);
   150             } else {
   151             log.severe("SAAJ0007.p2p.bad.endPoint.type");
   152             throw new SOAPExceptionImpl("Bad endPoint type " + endPoint);
   153         }
   154     }
   156     SOAPMessage post(SOAPMessage message, URL endPoint) throws SOAPException, IOException {
   157         boolean isFailure = false;
   159         URL url = null;
   160         HttpURLConnection httpConnection = null;
   162         int responseCode = 0;
   163         try {
   164             if (endPoint.getProtocol().equals("https"))
   165                 //if(!setHttps)
   166                 initHttps();
   167             // Process the URL
   168             URI uri = new URI(endPoint.toString());
   169             String userInfo = uri.getRawUserInfo();
   171             url = endPoint;
   173             if (dL > 0)
   174                 d("uri: " + userInfo + " " + url + " " + uri);
   176             // TBD
   177             //    Will deal with https later.
   178             if (!url.getProtocol().equalsIgnoreCase("http")
   179                 && !url.getProtocol().equalsIgnoreCase("https")) {
   180                 log.severe("SAAJ0052.p2p.protocol.mustbe.http.or.https");
   181                 throw new IllegalArgumentException(
   182                     "Protocol "
   183                         + url.getProtocol()
   184                         + " not supported in URL "
   185                         + url);
   186             }
   187             httpConnection = (HttpURLConnection) createConnection(url);
   189             httpConnection.setRequestMethod("POST");
   191             httpConnection.setDoOutput(true);
   192             httpConnection.setDoInput(true);
   193             httpConnection.setUseCaches(false);
   194             httpConnection.setInstanceFollowRedirects(true);
   196             if (message.saveRequired())
   197                 message.saveChanges();
   199             MimeHeaders headers = message.getMimeHeaders();
   201             Iterator it = headers.getAllHeaders();
   202             boolean hasAuth = false; // true if we find explicit Auth header
   203             while (it.hasNext()) {
   204                 MimeHeader header = (MimeHeader) it.next();
   206                 String[] values = headers.getHeader(header.getName());
   207                 if (values.length == 1)
   208                     httpConnection.setRequestProperty(
   209                         header.getName(),
   210                         header.getValue());
   211                 else {
   212                     StringBuffer concat = new StringBuffer();
   213                     int i = 0;
   214                     while (i < values.length) {
   215                         if (i != 0)
   216                             concat.append(',');
   217                         concat.append(values[i]);
   218                         i++;
   219                     }
   221                     httpConnection.setRequestProperty(
   222                         header.getName(),
   223                         concat.toString());
   224                 }
   226                 if ("Authorization".equals(header.getName())) {
   227                     hasAuth = true;
   228                     if (log.isLoggable(Level.FINE))
   229                         log.fine("SAAJ0091.p2p.https.auth.in.POST.true");
   230                 }
   231             }
   233             if (!hasAuth && userInfo != null) {
   234                 initAuthUserInfo(httpConnection, userInfo);
   235             }
   237             OutputStream out = httpConnection.getOutputStream();
   238             try {
   239                 message.writeTo(out);
   240                 out.flush();
   241             } finally {
   242                 out.close();
   243             }
   245             httpConnection.connect();
   247             try {
   249                 responseCode = httpConnection.getResponseCode();
   251                 // let HTTP_INTERNAL_ERROR (500) through because it is used for SOAP faults
   252                 if (responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR) {
   253                     isFailure = true;
   254                 }
   255                 //else if (responseCode != HttpURLConnection.HTTP_OK)
   256                 //else if (!(responseCode >= HttpURLConnection.HTTP_OK && responseCode < 207))
   257                 else if ((responseCode / 100) != 2) {
   258                     log.log(Level.SEVERE,
   259                             "SAAJ0008.p2p.bad.response",
   260                             new String[] {httpConnection.getResponseMessage()});
   261                     throw new SOAPExceptionImpl(
   262                         "Bad response: ("
   263                             + responseCode
   264                             + httpConnection.getResponseMessage());
   266                 }
   267             } catch (IOException e) {
   268                 // on JDK1.3.1_01, we end up here, but then getResponseCode() succeeds!
   269                 responseCode = httpConnection.getResponseCode();
   270                 if (responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR) {
   271                     isFailure = true;
   272                 } else {
   273                     throw e;
   274                 }
   276             }
   278         } catch (SOAPException ex) {
   279             throw ex;
   280         } catch (Exception ex) {
   281             log.severe("SAAJ0009.p2p.msg.send.failed");
   282             throw new SOAPExceptionImpl("Message send failed", ex);
   283         }
   285         SOAPMessage response = null;
   286         InputStream httpIn = null;
   287         if (responseCode == HttpURLConnection.HTTP_OK || isFailure) {
   288             try {
   289                 MimeHeaders headers = new MimeHeaders();
   291                 String key, value;
   293                 // Header field 0 is the status line so we skip it.
   295                 int i = 1;
   297                 while (true) {
   298                     key = httpConnection.getHeaderFieldKey(i);
   299                     value = httpConnection.getHeaderField(i);
   301                     if (key == null && value == null)
   302                         break;
   304                     if (key != null) {
   305                         StringTokenizer values =
   306                             new StringTokenizer(value, ",");
   307                         while (values.hasMoreTokens())
   308                             headers.addHeader(key, values.nextToken().trim());
   309                     }
   310                     i++;
   311                 }
   313                 httpIn =
   314                     (isFailure
   315                         ? httpConnection.getErrorStream()
   316                         : httpConnection.getInputStream());
   318                 byte[] bytes = readFully(httpIn);
   320                 int length =
   321                     httpConnection.getContentLength() == -1
   322                         ? bytes.length
   323                         : httpConnection.getContentLength();
   325                 // If no reply message is returned,
   326                 // content-Length header field value is expected to be zero.
   327                 if (length == 0) {
   328                     response = null;
   329                     log.warning("SAAJ0014.p2p.content.zero");
   330                 } else {
   331                     ByteInputStream in = new ByteInputStream(bytes, length);
   332                     response = messageFactory.createMessage(headers, in);
   333                 }
   335             } catch (SOAPException ex) {
   336                 throw ex;
   337             } catch (Exception ex) {
   338                 log.log(Level.SEVERE,"SAAJ0010.p2p.cannot.read.resp", ex);
   339                 throw new SOAPExceptionImpl(
   340                     "Unable to read response: " + ex.getMessage());
   341             } finally {
   342                if (httpIn != null)
   343                    httpIn.close();
   344                httpConnection.disconnect();
   345             }
   346         }
   347         return response;
   348     }
   350     // Object identifies where the request should be sent.
   351     // It is required to support objects of type String and java.net.URL.
   353     public SOAPMessage get(Object endPoint) throws SOAPException {
   354         if (closed) {
   355             log.severe("SAAJ0011.p2p.get.already.closed.conn");
   356             throw new SOAPExceptionImpl("Connection is closed");
   357         }
   358         Class urlEndpointClass = null;
   360         try {
   361             urlEndpointClass = Class.forName("javax.xml.messaging.URLEndpoint");
   362         } catch (Exception ex) {
   363             //Do nothing. URLEndpoint is available only when JAXM is there.
   364         }
   366         if (urlEndpointClass != null) {
   367             if (urlEndpointClass.isInstance(endPoint)) {
   368                 String url = null;
   370                 try {
   371                     Method m = urlEndpointClass.getMethod("getURL", (Class[])null);
   372                     url = (String) m.invoke(endPoint, (Object[])null);
   373                 } catch (Exception ex) {
   374                     log.severe("SAAJ0004.p2p.internal.err");
   375                     throw new SOAPExceptionImpl(
   376                         "Internal error: " + ex.getMessage());
   377                 }
   378                 try {
   379                     endPoint = new URL(url);
   380                 } catch (MalformedURLException mex) {
   381                     log.severe("SAAJ0005.p2p.");
   382                     throw new SOAPExceptionImpl("Bad URL: " + mex.getMessage());
   383                 }
   384             }
   385         }
   387         if (endPoint instanceof java.lang.String) {
   388             try {
   389                 endPoint = new URL((String) endPoint);
   390             } catch (MalformedURLException mex) {
   391                 log.severe("SAAJ0006.p2p.bad.URL");
   392                 throw new SOAPExceptionImpl("Bad URL: " + mex.getMessage());
   393             }
   394         }
   396         if (endPoint instanceof URL)
   397             try {
   398                 SOAPMessage response = doGet((URL)endPoint);
   399                 return response;
   400             } catch (Exception ex) {
   401                 throw new SOAPExceptionImpl(ex);
   402             } else
   403             throw new SOAPExceptionImpl("Bad endPoint type " + endPoint);
   404     }
   406     SOAPMessage doGet(URL endPoint) throws SOAPException, IOException {
   407         boolean isFailure = false;
   409         URL url = null;
   410         HttpURLConnection httpConnection = null;
   412         int responseCode = 0;
   413         try {
   414             /// Is https GET allowed??
   415             if (endPoint.getProtocol().equals("https"))
   416                 initHttps();
   417             // Process the URL
   418             URI uri = new URI(endPoint.toString());
   419             String userInfo = uri.getRawUserInfo();
   421             url = endPoint;
   423             if (dL > 0)
   424                 d("uri: " + userInfo + " " + url + " " + uri);
   426             // TBD
   427             //    Will deal with https later.
   428             if (!url.getProtocol().equalsIgnoreCase("http")
   429                 && !url.getProtocol().equalsIgnoreCase("https")) {
   430                 log.severe("SAAJ0052.p2p.protocol.mustbe.http.or.https");
   431                 throw new IllegalArgumentException(
   432                     "Protocol "
   433                         + url.getProtocol()
   434                         + " not supported in URL "
   435                         + url);
   436             }
   437             httpConnection = (HttpURLConnection) createConnection(url);
   439             httpConnection.setRequestMethod("GET");
   441             httpConnection.setDoOutput(true);
   442             httpConnection.setDoInput(true);
   443             httpConnection.setUseCaches(false);
   444             httpConnection.setFollowRedirects(true);
   446             httpConnection.connect();
   448             try {
   450                 responseCode = httpConnection.getResponseCode();
   452                 // let HTTP_INTERNAL_ERROR (500) through because it is used for SOAP faults
   453                 if (responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR) {
   454                     isFailure = true;
   455                 } else if ((responseCode / 100) != 2) {
   456                     log.log(Level.SEVERE,
   457                             "SAAJ0008.p2p.bad.response",
   458                             new String[] { httpConnection.getResponseMessage()});
   459                     throw new SOAPExceptionImpl(
   460                         "Bad response: ("
   461                             + responseCode
   462                             + httpConnection.getResponseMessage());
   464                 }
   465             } catch (IOException e) {
   466                 // on JDK1.3.1_01, we end up here, but then getResponseCode() succeeds!
   467                 responseCode = httpConnection.getResponseCode();
   468                 if (responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR) {
   469                     isFailure = true;
   470                 } else {
   471                     throw e;
   472                 }
   474             }
   476         } catch (SOAPException ex) {
   477             throw ex;
   478         } catch (Exception ex) {
   479             log.severe("SAAJ0012.p2p.get.failed");
   480             throw new SOAPExceptionImpl("Get failed", ex);
   481         }
   483         SOAPMessage response = null;
   484         InputStream httpIn = null;
   485         if (responseCode == HttpURLConnection.HTTP_OK || isFailure) {
   486             try {
   487                 MimeHeaders headers = new MimeHeaders();
   489                 String key, value;
   491                 // Header field 0 is the status line so we skip it.
   493                 int i = 1;
   495                 while (true) {
   496                     key = httpConnection.getHeaderFieldKey(i);
   497                     value = httpConnection.getHeaderField(i);
   499                     if (key == null && value == null)
   500                         break;
   502                     if (key != null) {
   503                         StringTokenizer values =
   504                             new StringTokenizer(value, ",");
   505                         while (values.hasMoreTokens())
   506                             headers.addHeader(key, values.nextToken().trim());
   507                     }
   508                     i++;
   509                 }
   511                 httpIn =
   512                         (isFailure
   513                         ? httpConnection.getErrorStream()
   514                         : httpConnection.getInputStream());
   515                 // If no reply message is returned,
   516                 // content-Length header field value is expected to be zero.
   517                 // java SE 6 documentation says :
   518                 // available() : an estimate of the number of bytes that can be read
   519                 //(or skipped over) from this input stream without blocking
   520                 //or 0 when it reaches the end of the input stream.
   521                 if ((httpIn == null )
   522                         || (httpConnection.getContentLength() == 0)
   523                         || (httpIn.available() == 0)) {
   524                     response = null;
   525                     log.warning("SAAJ0014.p2p.content.zero");
   526                 } else {
   527                     response = messageFactory.createMessage(headers, httpIn);
   528                 }
   530             } catch (SOAPException ex) {
   531                 throw ex;
   532             } catch (Exception ex) {
   533                 log.log(Level.SEVERE,
   534                         "SAAJ0010.p2p.cannot.read.resp",
   535                         ex);
   536                 throw new SOAPExceptionImpl(
   537                     "Unable to read response: " + ex.getMessage());
   538             } finally {
   539                if (httpIn != null)
   540                    httpIn.close();
   541                httpConnection.disconnect();
   542             }
   543         }
   544         return response;
   545     }
   547     private byte[] readFully(InputStream istream) throws IOException {
   548         ByteArrayOutputStream bout = new ByteArrayOutputStream();
   549         byte[] buf = new byte[1024];
   550         int num = 0;
   552         while ((num = istream.read(buf)) != -1) {
   553             bout.write(buf, 0, num);
   554         }
   556         byte[] ret = bout.toByteArray();
   558         return ret;
   559     }
   561     //private static String SSL_PKG = "com.sun.net.ssl.internal.www.protocol";
   562     //private static String SSL_PROVIDER =
   563       //  "com.sun.net.ssl.internal.ssl.Provider";
   564     private static final String SSL_PKG;
   565     private static final String SSL_PROVIDER;
   567     static {
   568         if (isIBMVM) {
   569             SSL_PKG ="com.ibm.net.ssl.internal.www.protocol";
   570             SSL_PROVIDER ="com.ibm.net.ssl.internal.ssl.Provider";
   571         } else {
   572             //if not IBM VM default to Sun.
   573             SSL_PKG = "com.sun.net.ssl.internal.www.protocol";
   574             SSL_PROVIDER ="com.sun.net.ssl.internal.ssl.Provider";
   575         }
   576     }
   578     private void initHttps() {
   579         //if(!setHttps) {
   580         String pkgs = SAAJUtil.getSystemProperty("java.protocol.handler.pkgs");
   581         if (log.isLoggable(Level.FINE))
   582             log.log(Level.FINE, "SAAJ0053.p2p.providers", new String[] { pkgs });
   584         if (pkgs == null || pkgs.indexOf(SSL_PKG) < 0) {
   585             if (pkgs == null)
   586                 pkgs = SSL_PKG;
   587             else
   588                 pkgs = pkgs + "|" + SSL_PKG;
   589             System.setProperty("java.protocol.handler.pkgs", pkgs);
   590             if (log.isLoggable(Level.FINE))
   591                 log.log(Level.FINE, "SAAJ0054.p2p.set.providers",
   592                         new String[] { pkgs });
   593             try {
   594                 Class c = Class.forName(SSL_PROVIDER);
   595                 Provider p = (Provider) c.newInstance();
   596                 Security.addProvider(p);
   597                 if (log.isLoggable(Level.FINE))
   598                     log.log(Level.FINE, "SAAJ0055.p2p.added.ssl.provider",
   599                             new String[] { SSL_PROVIDER });
   600                 //System.out.println("Added SSL_PROVIDER " + SSL_PROVIDER);
   601                 //setHttps = true;
   602             } catch (Exception ex) {
   603             }
   604         }
   605         //}
   606     }
   608     private void initAuthUserInfo(HttpURLConnection conn, String userInfo) {
   609         String user;
   610         String password;
   611         if (userInfo != null) { // get the user and password
   612             //System.out.println("UserInfo= " + userInfo );
   613             int delimiter = userInfo.indexOf(':');
   614             if (delimiter == -1) {
   615                 user = ParseUtil.decode(userInfo);
   616                 password = null;
   617             } else {
   618                 user = ParseUtil.decode(userInfo.substring(0, delimiter++));
   619                 password = ParseUtil.decode(userInfo.substring(delimiter));
   620             }
   622             String plain = user + ":";
   623             byte[] nameBytes = plain.getBytes();
   624             byte[] passwdBytes = password.getBytes();
   626             // concatenate user name and password bytes and encode them
   627             byte[] concat = new byte[nameBytes.length + passwdBytes.length];
   629             System.arraycopy(nameBytes, 0, concat, 0, nameBytes.length);
   630             System.arraycopy(
   631                 passwdBytes,
   632                 0,
   633                 concat,
   634                 nameBytes.length,
   635                 passwdBytes.length);
   636             String auth = "Basic " + new String(Base64.encode(concat));
   637             conn.setRequestProperty("Authorization", auth);
   638             if (dL > 0)
   639                 d("Adding auth " + auth);
   640         }
   641     }
   643     private static final int dL = 0;
   644     private void d(String s) {
   645         log.log(Level.SEVERE,
   646                 "SAAJ0013.p2p.HttpSOAPConnection",
   647                 new String[] { s });
   648         System.err.println("HttpSOAPConnection: " + s);
   649     }
   651     private java.net.HttpURLConnection createConnection(URL endpoint)
   652         throws IOException {
   653         return (HttpURLConnection) endpoint.openConnection();
   654     }
   656 }

mercurial