KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > burlap > client > BurlapProxyFactory


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution, if
19  * any, must include the following acknowlegement:
20  * "This product includes software developed by the
21  * Caucho Technology (http://www.caucho.com/)."
22  * Alternately, this acknowlegement may appear in the software itself,
23  * if and wherever such third-party acknowlegements normally appear.
24  *
25  * 4. The names "Burlap", "Resin", and "Caucho" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * info@caucho.com.
29  *
30  * 5. Products derived from this software may not be called "Resin"
31  * nor may "Resin" appear in their names without prior written
32  * permission of Caucho Technology.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
35  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37  * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
38  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
39  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
40  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
43  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
44  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45  *
46  * @author Scott Ferguson
47  */

48
49 package com.caucho.burlap.client;
50
51 import com.caucho.burlap.io.AbstractBurlapInput;
52 import com.caucho.burlap.io.BurlapInput;
53 import com.caucho.burlap.io.BurlapOutput;
54 import com.caucho.burlap.io.BurlapRemoteObject;
55 import com.caucho.burlap.io.BurlapRemoteResolver;
56 import com.caucho.services.client.ServiceProxyFactory;
57
58 import javax.naming.Context JavaDoc;
59 import javax.naming.Name JavaDoc;
60 import javax.naming.NamingException JavaDoc;
61 import javax.naming.RefAddr JavaDoc;
62 import javax.naming.Reference JavaDoc;
63 import javax.naming.spi.ObjectFactory JavaDoc;
64 import java.io.IOException JavaDoc;
65 import java.io.InputStream JavaDoc;
66 import java.io.OutputStream JavaDoc;
67 import java.lang.reflect.Proxy JavaDoc;
68 import java.net.HttpURLConnection JavaDoc;
69 import java.net.MalformedURLException JavaDoc;
70 import java.net.URL JavaDoc;
71 import java.net.URLConnection JavaDoc;
72 import java.util.Hashtable JavaDoc;
73
74 /**
75  * Factory for creating Burlap client stubs. The returned stub will
76  * call the remote object for all methods.
77  *
78  * <pre>
79  * String url = "http://localhost:8080/ejb/hello";
80  * HelloHome hello = (HelloHome) factory.create(HelloHome.class, url);
81  * </pre>
82  *
83  * After creation, the stub can be like a regular Java class. Because
84  * it makes remote calls, it can throw more exceptions than a Java class.
85  * In particular, it may throw protocol exceptions.
86  *
87  * The factory can also be configured as a JNDI resource. The factory
88  * expects to parameters: "type" and "url", corresponding to the two
89  * arguments to <code>create</code>
90  *
91  * In Resin 3.0, the above example would be configured as:
92  * <pre>
93  * &lt;reference>
94  * &lt;name>hessian/hello&lt;/name>
95  * &lt;factory>com.caucho.hessian.client.HessianProxyFactory&lt;/factory>
96  * &lt;init url="http://localhost:8080/ejb/hello"/>
97  * type="test.HelloHome"/>
98  * &lt;/reference>
99  * </pre>
100  *
101  * To get the above resource, use JNDI as follows:
102  * <pre>
103  * Context ic = new InitialContext();
104  * HelloHome hello = (HelloHome) ic.lookup("java:comp/env/burlap/hello");
105  *
106  * System.out.println("Hello: " + hello.helloWorld());
107  * </pre>
108  *
109  * <h3>Authentication</h3>
110  *
111  * <p>The proxy can use HTTP basic authentication if the user and the
112  * password are set.
113  */

114 public class BurlapProxyFactory implements ServiceProxyFactory, ObjectFactory JavaDoc {
115   private BurlapRemoteResolver _resolver;
116   
117   private String JavaDoc _user;
118   private String JavaDoc _password;
119   private String JavaDoc _basicAuth;
120
121   private boolean _isOverloadEnabled = false;
122
123   /**
124    * Creates the new proxy factory.
125    */

126   public BurlapProxyFactory()
127   {
128     _resolver = new BurlapProxyResolver(this);
129   }
130
131   /**
132    * Sets the user.
133    */

134   public void setUser(String JavaDoc user)
135   {
136     _user = user;
137     _basicAuth = null;
138   }
139
140   /**
141    * Sets the password.
142    */

143   public void setPassword(String JavaDoc password)
144   {
145     _password = password;
146     _basicAuth = null;
147   }
148
149   /**
150    * Returns true if overloaded methods are allowed (using mangling)
151    */

152   public boolean isOverloadEnabled()
153   {
154     return _isOverloadEnabled;
155   }
156
157   /**
158    * set true if overloaded methods are allowed (using mangling)
159    */

160   public void setOverloadEnabled(boolean isOverloadEnabled)
161   {
162     _isOverloadEnabled = isOverloadEnabled;
163   }
164
165   /**
166    * Returns the remote resolver.
167    */

168   public BurlapRemoteResolver getRemoteResolver()
169   {
170     return _resolver;
171   }
172
173   /**
174    * Creates the URL connection.
175    */

176   protected URLConnection JavaDoc openConnection(URL JavaDoc url)
177     throws IOException JavaDoc
178   {
179     URLConnection JavaDoc conn = url.openConnection();
180
181     conn.setDoOutput(true);
182
183     if (_basicAuth != null)
184       conn.setRequestProperty("Authorization", _basicAuth);
185     else if (_user != null && _password != null) {
186       _basicAuth = "Basic " + base64(_user + ":" + _password);
187       conn.setRequestProperty("Authorization", _basicAuth);
188     }
189
190     return conn;
191   }
192
193   /**
194    * Creates a new proxy with the specified URL. The API class uses
195    * the java.api.class value from _hessian_
196    *
197    * @param url the URL where the client object is located.
198    *
199    * @return a proxy to the object with the specified interface.
200    */

201   public Object JavaDoc create(String JavaDoc url)
202     throws MalformedURLException JavaDoc, ClassNotFoundException JavaDoc
203   {
204     BurlapMetaInfoAPI metaInfo;
205
206     metaInfo = (BurlapMetaInfoAPI) create(BurlapMetaInfoAPI.class, url);
207
208     String JavaDoc apiClassName =
209       (String JavaDoc) metaInfo._burlap_getAttribute("java.api.class");
210
211     if (apiClassName == null)
212       throw new BurlapRuntimeException(url + " has an unknown api.");
213
214     ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
215
216     Class JavaDoc apiClass = Class.forName(apiClassName, false, loader);
217
218     return create(apiClass, url);
219   }
220
221   /**
222    * Creates a new proxy with the specified URL. The returned object
223    * is a proxy with the interface specified by api.
224    *
225    * <pre>
226    * String url = "http://localhost:8080/ejb/hello");
227    * HelloHome hello = (HelloHome) factory.create(HelloHome.class, url);
228    * </pre>
229    *
230    * @param api the interface the proxy class needs to implement
231    * @param url the URL where the client object is located.
232    *
233    * @return a proxy to the object with the specified interface.
234    */

235   public Object JavaDoc create(Class JavaDoc api, String JavaDoc urlName)
236     throws MalformedURLException JavaDoc
237   {
238     URL JavaDoc url = new URL JavaDoc(urlName);
239
240     try {
241       // clear old keepalive connections
242
HttpURLConnection JavaDoc conn = (HttpURLConnection JavaDoc) url.openConnection();
243
244       conn.setRequestProperty("Connection", "close");
245
246       InputStream JavaDoc is = conn.getInputStream();
247
248       is.close();
249
250       conn.disconnect();
251     } catch (IOException JavaDoc e) {
252     }
253     
254     BurlapProxy handler = new BurlapProxy(this, url);
255
256     return Proxy.newProxyInstance(api.getClassLoader(),
257                                   new Class JavaDoc[] { api,
258                                                 BurlapRemoteObject.class },
259                                   handler);
260   }
261
262   public AbstractBurlapInput getBurlapInput(InputStream JavaDoc is)
263   {
264     AbstractBurlapInput in = new BurlapInput(is);
265     in.setRemoteResolver(getRemoteResolver());
266
267     return in;
268   }
269
270   public BurlapOutput getBurlapOutput(OutputStream JavaDoc os)
271   {
272     BurlapOutput out = new BurlapOutput(os);
273
274     return out;
275   }
276
277   /**
278    * JNDI object factory so the proxy can be used as a resource.
279    */

280   public Object JavaDoc getObjectInstance(Object JavaDoc obj, Name JavaDoc name,
281                                   Context JavaDoc nameCtx,
282                   Hashtable JavaDoc<?,?> environment)
283     throws Exception JavaDoc
284   {
285     Reference JavaDoc ref = (Reference JavaDoc) obj;
286
287     String JavaDoc api = null;
288     String JavaDoc url = null;
289     String JavaDoc user = null;
290     String JavaDoc password = null;
291
292     for (int i = 0; i < ref.size(); i++) {
293       RefAddr JavaDoc addr = ref.get(i);
294
295       String JavaDoc type = addr.getType();
296       String JavaDoc value = (String JavaDoc) addr.getContent();
297
298       if (type.equals("type"))
299         api = value;
300       else if (type.equals("url"))
301         url = value;
302       else if (type.equals("user"))
303         setUser(value);
304       else if (type.equals("password"))
305         setPassword(value);
306     }
307
308     if (url == null)
309       throw new NamingException JavaDoc("`url' must be configured for BurlapProxyFactory.");
310     // XXX: could use meta protocol to grab this
311
if (api == null)
312       throw new NamingException JavaDoc("`type' must be configured for BurlapProxyFactory.");
313
314     ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
315     Class JavaDoc apiClass = Class.forName(api, false, loader);
316
317     return create(apiClass, url);
318   }
319
320   /**
321    * Creates the Base64 value.
322    */

323   private String JavaDoc base64(String JavaDoc value)
324   {
325     StringBuffer JavaDoc cb = new StringBuffer JavaDoc();
326
327     int i = 0;
328     for (i = 0; i + 2 < value.length(); i += 3) {
329       long chunk = (int) value.charAt(i);
330       chunk = (chunk << 8) + (int) value.charAt(i + 1);
331       chunk = (chunk << 8) + (int) value.charAt(i + 2);
332         
333       cb.append(encode(chunk >> 18));
334       cb.append(encode(chunk >> 12));
335       cb.append(encode(chunk >> 6));
336       cb.append(encode(chunk));
337     }
338     
339     if (i + 1 < value.length()) {
340       long chunk = (int) value.charAt(i);
341       chunk = (chunk << 8) + (int) value.charAt(i + 1);
342       chunk <<= 8;
343
344       cb.append(encode(chunk >> 18));
345       cb.append(encode(chunk >> 12));
346       cb.append(encode(chunk >> 6));
347       cb.append('=');
348     }
349     else if (i < value.length()) {
350       long chunk = (int) value.charAt(i);
351       chunk <<= 16;
352
353       cb.append(encode(chunk >> 18));
354       cb.append(encode(chunk >> 12));
355       cb.append('=');
356       cb.append('=');
357     }
358
359     return cb.toString();
360   }
361
362   public static char encode(long d)
363   {
364     d &= 0x3f;
365     if (d < 26)
366       return (char) (d + 'A');
367     else if (d < 52)
368       return (char) (d + 'a' - 26);
369     else if (d < 62)
370       return (char) (d + '0' - 52);
371     else if (d == 62)
372       return '+';
373     else
374       return '/';
375   }
376 }
377
378
Popular Tags