KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mx4j > remote > resolver > rmi > RMIResolver


1 /*
2  * Copyright (C) MX4J.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the MX4J License version 1.0.
6  * See the terms of the MX4J License in the documentation provided with this software.
7  */

8
9 package mx4j.remote.resolver.rmi;
10
11 import java.io.IOException JavaDoc;
12 import java.io.ByteArrayOutputStream JavaDoc;
13 import java.io.ObjectOutputStream JavaDoc;
14 import java.io.ByteArrayInputStream JavaDoc;
15 import java.io.ObjectInputStream JavaDoc;
16 import java.net.MalformedURLException JavaDoc;
17 import java.rmi.server.RMIClientSocketFactory JavaDoc;
18 import java.rmi.server.RMIServerSocketFactory JavaDoc;
19 import java.rmi.Remote JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.Map JavaDoc;
22
23 import javax.management.remote.JMXServiceURL JavaDoc;
24 import javax.management.remote.rmi.RMIConnectorServer JavaDoc;
25 import javax.management.remote.rmi.RMIJRMPServerImpl JavaDoc;
26 import javax.management.remote.rmi.RMIServer JavaDoc;
27 import javax.management.remote.rmi.RMIServerImpl JavaDoc;
28 import javax.naming.InitialContext JavaDoc;
29 import javax.naming.NamingException JavaDoc;
30
31 import mx4j.log.Logger;
32 import mx4j.remote.ConnectionResolver;
33 import mx4j.util.Base64Codec;
34
35 /**
36  * Resolver for RMI/JRMP protocol.
37  *
38  * @author <a HREF="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
39  * @version $Revision: 1.10 $
40  */

41 public class RMIResolver extends ConnectionResolver
42 {
43    private static final String JavaDoc JNDI_CONTEXT = "/jndi/";
44    private static final String JavaDoc STUB_CONTEXT = "/stub/";
45
46
47 //********************************************************************************************************************//
48
// CLIENT METHODS
49

50
51    public Object JavaDoc lookupClient(JMXServiceURL JavaDoc url, Map JavaDoc environment) throws IOException JavaDoc
52    {
53       return lookupRMIServerStub(url, environment);
54    }
55
56    public Object JavaDoc bindClient(Object JavaDoc client, Map JavaDoc environment) throws IOException JavaDoc
57    {
58       // JRMP does not need anything special
59
return client;
60    }
61
62    protected RMIServer JavaDoc lookupRMIServerStub(JMXServiceURL JavaDoc url, Map JavaDoc environment) throws IOException JavaDoc
63    {
64       Logger logger = getLogger();
65
66       String JavaDoc path = url.getURLPath();
67       if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("JMXServiceURL for lookup is: '" + url + "'");
68
69       if (path != null)
70       {
71          if (path.startsWith(JNDI_CONTEXT))
72          {
73             return lookupStubInJNDI(url, environment);
74          }
75
76          return decodeStub(url, environment);
77       }
78
79       throw new MalformedURLException JavaDoc("Unsupported lookup " + url);
80    }
81
82    private RMIServer JavaDoc lookupStubInJNDI(JMXServiceURL JavaDoc url, Map JavaDoc environment) throws IOException JavaDoc
83    {
84       Logger logger = getLogger();
85
86       String JavaDoc path = url.getURLPath();
87       String JavaDoc name = path.substring(JNDI_CONTEXT.length());
88       if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Looking up RMI stub in JNDI under name " + name);
89
90       InitialContext JavaDoc ctx = null;
91       try
92       {
93          ctx = new InitialContext JavaDoc(new Hashtable JavaDoc(environment));
94          Object JavaDoc stub = ctx.lookup(name);
95          if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Found RMI stub in JNDI " + stub);
96          return narrowRMIServerStub(stub);
97       }
98       catch (NamingException JavaDoc x)
99       {
100          if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Cannot lookup RMI stub in JNDI", x);
101          throw new IOException JavaDoc(x.toString());
102       }
103       finally
104       {
105          try
106          {
107             if (ctx != null) ctx.close();
108          }
109          catch (NamingException JavaDoc x)
110          {
111             if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Cannot close InitialContext", x);
112          }
113       }
114    }
115
116    protected RMIServer JavaDoc narrowRMIServerStub(Object JavaDoc stub)
117    {
118       return (RMIServer JavaDoc)stub;
119    }
120
121    protected RMIServer JavaDoc decodeStub(JMXServiceURL JavaDoc url, Map JavaDoc environment) throws IOException JavaDoc
122    {
123       String JavaDoc path = url.getURLPath();
124       if (path.startsWith(STUB_CONTEXT))
125       {
126          byte[] encoded = path.substring(STUB_CONTEXT.length()).getBytes();
127          if (!Base64Codec.isArrayByteBase64(encoded)) throw new IOException JavaDoc("Encoded stub form is not a valid Base64 sequence: " + url);
128          byte[] decoded = Base64Codec.decodeBase64(encoded);
129          ByteArrayInputStream JavaDoc bais = new ByteArrayInputStream JavaDoc(decoded);
130          ObjectInputStream JavaDoc ois = null;
131          try
132          {
133             ois = new ObjectInputStream JavaDoc(bais);
134             return (RMIServer JavaDoc)ois.readObject();
135          }
136          catch (ClassNotFoundException JavaDoc x)
137          {
138             throw new IOException JavaDoc("Cannot decode stub from " + url + ": " + x);
139          }
140          finally
141          {
142             if (ois != null) ois.close();
143          }
144       }
145       throw new MalformedURLException JavaDoc("Unsupported binding: " + url);
146    }
147
148
149 //********************************************************************************************************************//
150
// SERVER METHODS
151

152
153    public Object JavaDoc createServer(JMXServiceURL JavaDoc url, Map JavaDoc environment) throws IOException JavaDoc
154    {
155       return createRMIServer(url, environment);
156    }
157
158    protected RMIServerImpl JavaDoc createRMIServer(JMXServiceURL JavaDoc url, Map JavaDoc environment) throws IOException JavaDoc
159    {
160       int port = url.getPort();
161       RMIClientSocketFactory JavaDoc clientFactory = (RMIClientSocketFactory JavaDoc)environment.get(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE);
162       RMIServerSocketFactory JavaDoc serverFactory = (RMIServerSocketFactory JavaDoc)environment.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE);
163       return new RMIJRMPServerImpl JavaDoc(port, clientFactory, serverFactory, environment);
164    }
165
166    public JMXServiceURL JavaDoc bindServer(Object JavaDoc server, JMXServiceURL JavaDoc url, Map JavaDoc environment) throws IOException JavaDoc
167    {
168       // See javax/management/remote/rmi/package-summary.html
169

170       RMIServerImpl JavaDoc rmiServer = (RMIServerImpl JavaDoc)server;
171
172       Logger logger = getLogger();
173       if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("JMXServiceURL for binding is: '" + url + "'");
174
175       if (isEncodedForm(url))
176       {
177          String JavaDoc path = encodeStub(rmiServer, environment);
178          return new JMXServiceURL JavaDoc(url.getProtocol(), url.getHost(), url.getPort(), path);
179       }
180
181       String JavaDoc jndiURL = parseJNDIForm(url);
182       if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("JMXServiceURL path for binding is: '" + jndiURL + "'");
183
184       InitialContext JavaDoc ctx = null;
185       try
186       {
187          ctx = new InitialContext JavaDoc(new Hashtable JavaDoc(environment));
188          boolean rebind = Boolean.valueOf((String JavaDoc)environment.get(RMIConnectorServer.JNDI_REBIND_ATTRIBUTE)).booleanValue();
189          if (rebind)
190             ctx.rebind(jndiURL, rmiServer.toStub());
191          else
192             ctx.bind(jndiURL, rmiServer.toStub());
193          if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Bound " + rmiServer + " to " + jndiURL);
194          return url;
195       }
196       catch (NamingException JavaDoc x)
197       {
198          if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Cannot bind server " + rmiServer + " to " + jndiURL, x);
199          throw new IOException JavaDoc(x.toString());
200       }
201       finally
202       {
203          try
204          {
205             if (ctx != null) ctx.close();
206          }
207          catch (NamingException JavaDoc x)
208          {
209             if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Cannot close InitialContext", x);
210          }
211       }
212    }
213
214    protected String JavaDoc encodeStub(RMIServerImpl JavaDoc rmiServer, Map JavaDoc environment) throws IOException JavaDoc
215    {
216       Remote JavaDoc stub = rmiServer.toStub();
217       ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
218       ObjectOutputStream JavaDoc oos = null;
219       try
220       {
221          oos = new ObjectOutputStream JavaDoc(baos);
222          oos.writeObject(stub);
223       }
224       finally
225       {
226          if (oos != null) oos.close();
227       }
228       byte[] bytes = baos.toByteArray();
229       byte[] encoded = Base64Codec.encodeBase64(bytes);
230       // Since the bytes are base 64 bytes, the encoding in creating the string is not important: any will work
231
return STUB_CONTEXT + new String JavaDoc(encoded);
232    }
233
234    protected boolean isEncodedForm(JMXServiceURL JavaDoc url)
235    {
236       String JavaDoc path = url.getURLPath();
237       if (path == null || path.length() == 0 || path.equals("/") || path.startsWith(STUB_CONTEXT)) return true;
238       return false;
239    }
240
241    private String JavaDoc parseJNDIForm(JMXServiceURL JavaDoc url) throws MalformedURLException JavaDoc
242    {
243       String JavaDoc path = url.getURLPath();
244       if (path.startsWith(JNDI_CONTEXT))
245       {
246          String JavaDoc jndiURL = path.substring(JNDI_CONTEXT.length());
247          if (jndiURL == null || jndiURL.length() == 0) throw new MalformedURLException JavaDoc("No JNDI URL specified: " + url);
248          return jndiURL;
249       }
250       throw new MalformedURLException JavaDoc("Unsupported binding: " + url);
251    }
252
253    public void unbindServer(Object JavaDoc server, JMXServiceURL JavaDoc url, Map JavaDoc environment) throws IOException JavaDoc
254    {
255       Logger logger = getLogger();
256       if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("JMXServiceURL for unbinding is: '" + url + "'");
257       // The server was not bound to JNDI (the stub was encoded), just return
258
if (isEncodedForm(url))
259       {
260          destroyServer(server, environment);
261          return;
262       }
263
264       String JavaDoc jndiURL = parseJNDIForm(url);
265       if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("JMXServiceURL path for binding is: '" + jndiURL + "'");
266
267       InitialContext JavaDoc ctx = null;
268       try
269       {
270          ctx = new InitialContext JavaDoc(new Hashtable JavaDoc(environment));
271          ctx.unbind(jndiURL);
272          if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Unbound " + server + " from " + jndiURL);
273       }
274       catch (NamingException JavaDoc x)
275       {
276          if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Cannot unbind server " + server + " to " + jndiURL, x);
277          throw new IOException JavaDoc(x.toString());
278       }
279       finally
280       {
281          try
282          {
283             if (ctx != null) ctx.close();
284          }
285          catch (NamingException JavaDoc x)
286          {
287             if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Cannot close InitialContext", x);
288          }
289       }
290    }
291
292    protected void destroyServer(Object JavaDoc server, Map JavaDoc environment) throws IOException JavaDoc
293    {
294    }
295 }
296
Popular Tags