KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > invocation > http > interfaces > Util


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.invocation.http.interfaces;
23
24 import java.io.InputStream JavaDoc;
25 import java.io.ObjectInputStream JavaDoc;
26 import java.io.ObjectStreamException JavaDoc;
27 import java.io.OutputStream JavaDoc;
28 import java.io.ObjectOutputStream JavaDoc;
29 import java.lang.reflect.InvocationTargetException JavaDoc;
30 import java.lang.reflect.Method JavaDoc;
31 import java.net.Authenticator JavaDoc;
32 import java.net.HttpURLConnection JavaDoc;
33 import java.net.MalformedURLException JavaDoc;
34 import java.net.URL JavaDoc;
35 import java.security.PrivilegedAction JavaDoc;
36 import java.security.AccessController JavaDoc;
37 import java.util.zip.GZIPInputStream JavaDoc;
38
39 import javax.net.ssl.HttpsURLConnection;
40 import javax.net.ssl.SSLSocketFactory;
41
42 import org.jboss.invocation.Invocation;
43 import org.jboss.invocation.InvocationException;
44 import org.jboss.invocation.MarshalledValue;
45 import org.jboss.logging.Logger;
46 import org.jboss.security.SecurityAssociationAuthenticator;
47 import org.jboss.net.ssl.SSLSocketFactoryBuilder;
48
49 /** Common client utility methods
50  *
51  * @author Scott.Stark@jboss.org
52  * @version $Revision: 44276 $
53 */

54 public class Util
55 {
56    /** A property to override the default https url host verification */
57    public static final String JavaDoc IGNORE_HTTPS_HOST = "org.jboss.security.ignoreHttpsHost";
58    /** A property to install the https connection ssl socket factory */
59    public static final String JavaDoc SSL_FACTORY_BUILDER = "org.jboss.security.httpInvoker.sslSocketFactoryBuilder";
60    /**
61     * A serialized MarshalledInvocation
62     */

63    private static String JavaDoc REQUEST_CONTENT_TYPE =
64       "application/x-java-serialized-object; class=org.jboss.invocation.MarshalledInvocation";
65    private static Logger log = Logger.getLogger(Util.class);
66    /** A custom SSLSocketFactory builder to use for https connections */
67    private static SSLSocketFactoryBuilder sslSocketFactoryBuilder;
68
69    static class SetAuthenticator implements PrivilegedAction JavaDoc
70    {
71       public Object JavaDoc run()
72       {
73          Authenticator.setDefault(new SecurityAssociationAuthenticator());
74          return null;
75       }
76       
77    }
78    static class ReadSSLBuilder implements PrivilegedAction JavaDoc
79    {
80       public Object JavaDoc run()
81       {
82          String JavaDoc value = System.getProperty(SSL_FACTORY_BUILDER);
83          return value;
84       }
85    }
86
87    static
88    {
89       // Install the java.net.Authenticator to use
90
try
91       {
92          SetAuthenticator action = new SetAuthenticator();
93          AccessController.doPrivileged(action);
94       }
95       catch(Exception JavaDoc e)
96       {
97          log.warn("Failed to install SecurityAssociationAuthenticator", e);
98       }
99       ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
100
101       String JavaDoc factoryFactoryFQCN = null;
102       try
103       {
104          ReadSSLBuilder action = new ReadSSLBuilder();
105          factoryFactoryFQCN = (String JavaDoc) AccessController.doPrivileged(action);
106       }
107       catch(Exception JavaDoc e)
108       {
109          log.warn("Failed to read "+SSL_FACTORY_BUILDER, e);
110       }
111
112       if (factoryFactoryFQCN != null)
113       {
114          try
115          {
116             Class JavaDoc clazz = loader.loadClass(factoryFactoryFQCN);
117             sslSocketFactoryBuilder = (SSLSocketFactoryBuilder) clazz.newInstance();
118    }
119          catch (Exception JavaDoc e)
120          {
121             log.warn("Could not instantiate SSLSocketFactoryFactory", e);
122          }
123       }
124    }
125
126    /** Install the SecurityAssociationAuthenticator as the default
127     * java.net.Authenticator
128     */

129    public static void init()
130    {
131       try
132       {
133          SetAuthenticator action = new SetAuthenticator();
134          AccessController.doPrivileged(action);
135       }
136       catch(Exception JavaDoc e)
137       {
138          log.warn("Failed to install SecurityAssociationAuthenticator", e);
139       }
140    }
141
142    /** Post the Invocation as a serialized MarshalledInvocation object. This is
143     using the URL class for now but this should be improved to a cluster aware
144     layer with full usage of HTTP 1.1 features, pooling, etc.
145    */

146    public static Object JavaDoc invoke(URL JavaDoc externalURL, Invocation mi)
147       throws Exception JavaDoc
148    {
149       if( log.isTraceEnabled() )
150          log.trace("invoke, externalURL="+externalURL);
151       /* Post the MarshalledInvocation data. This is using the URL class
152        for now but this should be improved to a cluster aware layer with
153        full usage of HTTP 1.1 features, pooling, etc.
154        */

155       HttpURLConnection JavaDoc conn = (HttpURLConnection JavaDoc) externalURL.openConnection();
156       configureHttpsHostVerifier(conn);
157       conn.setDoInput(true);
158       conn.setDoOutput(true);
159       conn.setRequestProperty("ContentType", REQUEST_CONTENT_TYPE);
160       conn.setRequestMethod("POST");
161       // @todo this should be configurable
162
conn.setRequestProperty("Accept-Encoding", "x-gzip,x-deflate,gzip,deflate");
163       OutputStream JavaDoc os = conn.getOutputStream();
164       ObjectOutputStream JavaDoc oos = new ObjectOutputStream JavaDoc(os);
165       try
166       {
167          oos.writeObject(mi);
168          oos.flush();
169       }
170       catch (ObjectStreamException JavaDoc e)
171       {
172          // This generally represents a programming/deployment error,
173
// not a communication problem
174
throw new InvocationException(e);
175       }
176
177       // Get the response MarshalledValue object
178
InputStream JavaDoc is = conn.getInputStream();
179       // Check the headers for gzip Content-Encoding
180
String JavaDoc encoding = conn.getHeaderField("Content-Encoding");
181       if( encoding != null && encoding.indexOf("gzip") >= 0 )
182          is = new GZIPInputStream JavaDoc(is);
183       ObjectInputStream JavaDoc ois = new ObjectInputStream JavaDoc(is);
184       MarshalledValue mv = (MarshalledValue) ois.readObject();
185       // A hack for jsse connection pooling (see patch ).
186
ois.read();
187       ois.close();
188       oos.close();
189
190       // If the encoded value is an exception throw it
191
Object JavaDoc value = mv.get();
192       if( value instanceof Exception JavaDoc )
193       {
194          throw (Exception JavaDoc) value;
195       }
196
197       return value;
198    }
199
200    /** Given an Https URL connection check the org.jboss.security.ignoreHttpsHost
201     * system property and if true, install the AnyhostVerifier as the
202     * com.sun.net.ssl.HostnameVerifier or javax.net.ssl.HostnameVerifier
203     * depending on the version of JSSE seen. If HttpURLConnection is not a
204     * HttpsURLConnection then nothing is done.
205     *
206     * @param conn a HttpsURLConnection
207     */

208    public static void configureHttpsHostVerifier(HttpURLConnection JavaDoc conn)
209    {
210       if ( conn instanceof HttpsURLConnection )
211       {
212          // See if the org.jboss.security.ignoreHttpsHost property is set
213
if (Boolean.getBoolean(IGNORE_HTTPS_HOST) == true)
214          {
215             AnyhostVerifier.setHostnameVerifier(conn);
216          }
217       }
218    }
219
220    /** Override the SSLSocketFactory used by the HttpsURLConnection. This method
221     * will invoke setSSLSocketFactory on any HttpsURLConnection if there was
222     * a SSLSocketFactoryBuilder implementation specified via the
223     * org.jboss.security.httpInvoker.sslSocketFactoryBuilder system property.
224     *
225     * @param conn possibly a HttpsURLConnection
226     * @throws InvocationTargetException thrown on failure to invoke setSSLSocketFactory
227    */

228    public static void configureSSLSocketFactory(HttpURLConnection JavaDoc conn)
229       throws InvocationTargetException JavaDoc
230    {
231       Class JavaDoc connClass = conn.getClass();
232       if ( conn instanceof HttpsURLConnection && sslSocketFactoryBuilder != null)
233       {
234          try
235          {
236             SSLSocketFactory socketFactory = sslSocketFactoryBuilder.getSocketFactory();
237             Class JavaDoc[] sig = {SSLSocketFactory.class};
238             Method JavaDoc method = connClass.getMethod("setSSLSocketFactory", sig);
239             Object JavaDoc[] args = {socketFactory};
240             method.invoke(conn, args);
241             log.trace("Socket factory set on connection");
242          }
243          catch(Exception JavaDoc e)
244          {
245             throw new InvocationTargetException JavaDoc(e);
246          }
247       }
248    }
249
250    /**
251     * First try to use the externalURLValue as a URL string and if this
252     * fails to produce a valid URL treat the externalURLValue as a system
253     * property name from which to obtain the URL string. This allows the
254     * proxy url to not be set until the proxy is unmarshalled in the client
255     * vm, and is necessary when the server is sitting behind a firewall or
256     * proxy and does not know what its public http interface is named.
257     */

258    public static URL JavaDoc resolveURL(String JavaDoc urlValue) throws MalformedURLException JavaDoc
259    {
260       if( urlValue == null )
261          return null;
262
263       URL JavaDoc externalURL = null;
264       try
265       {
266          externalURL = new URL JavaDoc(urlValue);
267       }
268       catch(MalformedURLException JavaDoc e)
269       {
270          // See if externalURL refers to a property
271
String JavaDoc urlProperty = System.getProperty(urlValue);
272          if( urlProperty == null )
273             throw e;
274          externalURL = new URL JavaDoc(urlProperty);
275       }
276       return externalURL;
277    }
278 }
279
Popular Tags