KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sapia > ubik > rmi > server > transport > http > servlet > ServletTransportProvider


1 package org.sapia.ubik.rmi.server.transport.http.servlet;
2
3 import org.sapia.ubik.net.Request;
4 import org.sapia.ubik.net.ServerAddress;
5 import org.sapia.ubik.net.UriSyntaxException;
6 import org.sapia.ubik.rmi.server.Config;
7 import org.sapia.ubik.rmi.server.Log;
8 import org.sapia.ubik.rmi.server.RMICommand;
9 import org.sapia.ubik.rmi.server.Server;
10 import org.sapia.ubik.rmi.server.invocation.InvokeCommand;
11 import org.sapia.ubik.rmi.server.perf.PerfAnalyzer;
12 import org.sapia.ubik.rmi.server.transport.Connections;
13 import org.sapia.ubik.rmi.server.transport.TransportProvider;
14 import org.sapia.ubik.rmi.server.transport.http.HttpAddress;
15 import org.sapia.ubik.rmi.server.transport.http.HttpClientConnectionPool;
16 import org.sapia.ubik.rmi.server.transport.http.JdkClientConnectionPool;
17
18 import java.io.EOFException JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.io.InvalidClassException JavaDoc;
21 import java.io.NotSerializableException JavaDoc;
22
23 import java.rmi.RemoteException JavaDoc;
24
25 import java.util.Collections JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.Properties JavaDoc;
29
30 import javax.servlet.http.HttpServletRequest JavaDoc;
31 import javax.servlet.http.HttpServletResponse JavaDoc;
32
33
34 /**
35  * This transport provider is intended to be instantiated from within a servlet.
36  * The servlet delegates request handling to this instance's <code>handleRequest()</code>
37  * method.
38  * <p>
39  * The code excerpt below demonstrates how to create an instance of this class and
40  * use it in a servlet implementation:
41  *
42  * <pre>
43  * ...
44  *
45  * public void init(ServletConfig conf) throws ServletException {
46  * _provider = new ServletTransportProvider();
47  * TransportManager.registerProvider(_provider);
48  *
49  * Properties props = new Properties();
50  *
51  * // property below would normally be passed through a
52  * // servlet init parameter.
53  *
54  * props.setProperty(ServletConsts.SERVLET_URL_KEY,
55  * "http://localhost:8080/ubik");
56  *
57  * // this tells ubik "under" which transport our object will be exported
58  * props.setProperty(Consts.TRANSPORT_TYPE, ServletConsts.DEFAULT_SERVLET_TRANSPORT_TYPE);
59  *
60  * try{
61  * _foo = new UbikFoo();
62  * Hub.exportObject(_foo, props);
63  * }catch(RemoteException e){
64  * throw new ServletException("Could not export Foo", e);
65  * }
66  * }
67  *
68  * ...
69  *
70  * protected void service(HttpServletRequest req, HttpServletResponse res)
71  * throws ServletException, IOException {
72  * _provider.handleRequest(req, res);
73  * }
74  *
75  * ...
76  * </pre>
77  * <p>
78  * Then, in a client VM, to connect to the remote object, we proceed as follows:
79  * <pre>
80  * TransportManager.registerProvider(new ServletTransportProvider());
81  * Foo foo = (Foo)Hub.connect(new ServletAddress("http://localhost:8080/ubik"));
82  * </pre>
83  * <p>
84  * NOTE: there can be only ONE instance of this instance registered to the <code>Hub</code>
85  * <b>per web application</p>.
86  *
87  * @see #handleRequest(HttpServletRequest, HttpServletResponse)
88  *
89  * @author Yanick Duchesne
90  *
91  * <dl>
92  * <dt><b>Copyright:</b><dd>Copyright &#169; 2002-2004 <a HREF="http://www.sapia-oss.org">Sapia Open Source Software</a>. All Rights Reserved.</dd></dt>
93  * <dt><b>License:</b><dd>Read the license.txt file of the jar or visit the
94  * <a HREF="http://www.sapia-oss.org/license.html">license page</a> at the Sapia OSS web site</dd></dt>
95  * </dl>
96  */

97 public class ServletTransportProvider implements TransportProvider,
98   ServletConsts {
99   private static boolean _usesJakarta;
100
101   static {
102     try {
103       Class.forName("org.apache.commons.httpclient.HttpClient");
104       _usesJakarta = true;
105     } catch (Exception JavaDoc e) {
106     }
107   }
108
109   private PerfAnalyzer _perf = PerfAnalyzer.getInstance();
110   private ServletAddress _addr;
111   private String JavaDoc _transportType;
112   private Map JavaDoc _pools = Collections.synchronizedMap(new HashMap JavaDoc());
113
114   public ServletTransportProvider() {
115     this(DEFAULT_SERVLET_TRANSPORT_TYPE);
116   }
117
118   protected ServletTransportProvider(String JavaDoc transportType) {
119     _transportType = transportType;
120   }
121
122   /**
123    * @see org.sapia.ubik.rmi.server.transport.TransportProvider#getTransportType()
124    */

125   public String JavaDoc getTransportType() {
126     return _transportType;
127   }
128
129   /**
130    * @see org.sapia.ubik.rmi.server.transport.TransportProvider#newDefaultServer()
131    */

132   public Server newDefaultServer() throws RemoteException JavaDoc {
133     throw new UnsupportedOperationException JavaDoc(
134       "Transport provider does not support anonymous servers/dynamic ports");
135   }
136
137   /**
138    * This method returns a <code>Server</code> impl., given the properties passed in.
139    * A single property is expected: <code>ubik.rmi.transport.servlet.url</code>, whose
140    * value must correspond to the URL of the servlet that is encapsulating this instance.
141    *
142    * @see ServletConsts#SERVLET_URL_KEY
143    *
144    * @see org.sapia.ubik.rmi.server.transport.TransportProvider#newServer(java.util.Properties)
145    */

146   public Server newServer(Properties JavaDoc props) throws RemoteException JavaDoc {
147     String JavaDoc servletUrl = props.getProperty(SERVLET_URL_KEY);
148
149     if (servletUrl == null) {
150       throw new RemoteException JavaDoc("'" + SERVLET_URL_KEY + "' not specified");
151     }
152
153     try {
154       return new ServletServer(_addr = new ServletAddress(servletUrl));
155     } catch (UriSyntaxException e) {
156       throw new RemoteException JavaDoc("Could not parse servlet URL property", e);
157     }
158   }
159
160   /**
161    * Empty implementation.
162    *
163    * @see org.sapia.ubik.rmi.server.transport.TransportProvider#shutdown()
164    */

165   public void shutdown() {
166   }
167
168   /**
169    * @see org.sapia.ubik.rmi.server.transport.TransportProvider#getPoolFor(org.sapia.ubik.net.ServerAddress)
170    */

171   public synchronized Connections getPoolFor(ServerAddress address)
172     throws RemoteException JavaDoc {
173     Connections conns;
174
175     if ((conns = (Connections) _pools.get(address)) == null) {
176       try {
177         if (_usesJakarta) {
178           conns = new HttpClientConnectionPool((HttpAddress) address);
179         } else {
180           conns = new JdkClientConnectionPool((HttpAddress) address);
181         }
182
183         _pools.put(address, conns);
184       } catch (UriSyntaxException e) {
185         throw new RemoteException JavaDoc("Could not process given address", e);
186       }
187     }
188
189     return conns;
190   }
191
192   public void handleRequest(HttpServletRequest JavaDoc httpReq,
193     HttpServletResponse JavaDoc httpRes) {
194     ServletRmiConnection conn = new ServletRmiConnection(_addr, httpReq, httpRes);
195
196     Request req = new Request(conn, _addr);
197
198     if (Log.isDebug()) {
199       Log.debug(getClass(), "handling request");
200     }
201
202     RMICommand cmd;
203     Object JavaDoc resp = null;
204
205     try {
206       if (Log.isDebug()) {
207         Log.debug(getClass(), "receiving command");
208       }
209
210       cmd = (RMICommand) req.getConnection().receive();
211
212       if (Log.isDebug()) {
213         Log.debug(getClass(),
214           "command received: " + cmd.getClass().getName() + " from " +
215           req.getConnection().getServerAddress() + '@' + cmd.getVmId());
216       }
217
218       cmd.init(new Config(req.getServerAddress(), req.getConnection()));
219
220       try {
221         if (_perf.isEnabled()) {
222           if (cmd instanceof InvokeCommand) {
223             _perf.getTopic(getClass().getName() + ".RemoteCall").start();
224           }
225         }
226
227         resp = cmd.execute();
228
229         if (_perf.isEnabled()) {
230           if (cmd instanceof InvokeCommand) {
231             _perf.getTopic(getClass().getName() + ".RemoteCall").end();
232           }
233         }
234       } catch (Throwable JavaDoc t) {
235         t.printStackTrace();
236         t.fillInStackTrace();
237         resp = t;
238       }
239
240       if (_perf.isEnabled()) {
241         if (cmd instanceof InvokeCommand) {
242           _perf.getTopic(getClass().getName() + ".SendResponse").start();
243         }
244       }
245
246       conn.send(resp, cmd.getVmId(), cmd.getServerAddress().getTransportType());
247
248       if (_perf.isEnabled()) {
249         if (cmd instanceof InvokeCommand) {
250           _perf.getTopic(getClass().getName() + ".SendResponse").end();
251         }
252       }
253     } catch (RuntimeException JavaDoc e) {
254       Log.error(getClass(), "RuntimeException caught sending response", e);
255
256       try {
257         e.fillInStackTrace();
258         req.getConnection().send(e);
259       } catch (IOException JavaDoc e2) {
260         req.getConnection().close();
261
262         return;
263       }
264     } catch (ClassNotFoundException JavaDoc e) {
265       e.fillInStackTrace();
266       Log.error(getClass(), "Class not found while receiving sending request", e);
267
268       try {
269         req.getConnection().send(e);
270       } catch (IOException JavaDoc e2) {
271         e2.fillInStackTrace();
272         req.getConnection().close();
273
274         return;
275       }
276     } catch (EOFException JavaDoc e) {
277       e.fillInStackTrace();
278       req.getConnection().close();
279
280       return;
281     } catch (java.net.SocketException JavaDoc e) {
282       e.fillInStackTrace();
283       req.getConnection().close();
284
285       return;
286     } catch (NotSerializableException JavaDoc e) {
287       e.fillInStackTrace();
288       Log.error(getClass().getName(),
289         "Could not serialize class while sending response", e);
290
291       try {
292         req.getConnection().send(e);
293       } catch (IOException JavaDoc e2) {
294         req.getConnection().close();
295
296         return;
297       }
298     } catch (InvalidClassException JavaDoc e) {
299       e.fillInStackTrace();
300       Log.error(getClass(), "Class is invalid; object could not be sent", e);
301
302       e.fillInStackTrace();
303
304       try {
305         req.getConnection().send(e);
306       } catch (IOException JavaDoc e2) {
307         req.getConnection().close();
308
309         return;
310       }
311     } catch (java.io.IOException JavaDoc e) {
312       e.fillInStackTrace();
313
314       try {
315         req.getConnection().send(e);
316       } catch (IOException JavaDoc e2) {
317         req.getConnection().close();
318
319         return;
320       }
321     }
322   }
323 }
324
Popular Tags