KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jnp > server > Main


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.jnp.server;
23
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.ObjectOutputStream JavaDoc;
27 import java.io.OutputStream JavaDoc;
28 import java.lang.reflect.Method JavaDoc;
29 import java.net.InetAddress JavaDoc;
30 import java.net.ServerSocket JavaDoc;
31 import java.net.Socket JavaDoc;
32 import java.net.UnknownHostException JavaDoc;
33 import java.rmi.MarshalledObject JavaDoc;
34 import java.rmi.Remote JavaDoc;
35 import java.rmi.server.RMIClientSocketFactory JavaDoc;
36 import java.rmi.server.RMIServerSocketFactory JavaDoc;
37 import java.rmi.server.UnicastRemoteObject JavaDoc;
38
39 import javax.net.ServerSocketFactory;
40
41 import org.jboss.logging.Logger;
42 import org.jboss.net.sockets.DefaultSocketFactory;
43 import org.jboss.util.threadpool.BasicThreadPool;
44 import org.jboss.util.threadpool.ThreadPool;
45 import org.jnp.interfaces.Naming;
46 import org.jnp.interfaces.NamingContext;
47
48 /**
49  * A main() entry point for running the jnp naming service implementation as
50  * a standalone process.
51  *
52  * @author Rickard Oberg
53  * @author Scott.Stark@jboss.org
54  * @version $Revision: 41359 $
55  */

56 public class Main implements MainMBean
57 {
58    // Constants -----------------------------------------------------
59

60    // Attributes ----------------------------------------------------
61
/** The Naming interface server implementation */
62    protected NamingServer theServer;
63    protected MarshalledObject JavaDoc serverStub;
64    protected boolean isStubExported;
65    /** The jnp server socket through which the NamingServer stub is vended */
66    protected ServerSocket JavaDoc serverSocket;
67    /** An optional custom client socket factory */
68    protected RMIClientSocketFactory JavaDoc clientSocketFactory;
69    /** An optional custom server socket factory */
70    protected RMIServerSocketFactory JavaDoc serverSocketFactory;
71    /** An optional custom server socket factory */
72    protected ServerSocketFactory JavaDoc jnpServerSocketFactory;
73    /** The class name of the optional custom client socket factory */
74    protected String JavaDoc clientSocketFactoryName;
75    /** The class name of the optional custom server socket factory */
76    protected String JavaDoc serverSocketFactoryName;
77    /** The class name of the optional custom JNP server socket factory */
78    protected String JavaDoc jnpServerSocketFactoryName;
79    /** The interface to bind to for the lookup socket. This is useful for
80     * multi-homed hosts that want control over which interfaces accept
81     * connections */

82    protected InetAddress JavaDoc bindAddress;
83    /** The interface to bind to for the Naming RMI server */
84    protected InetAddress JavaDoc rmiBindAddress;
85    /** The serverSocket listen queue depth */
86    protected int backlog = 50;
87    /** The jnp protocol listening port. The default is 1099, the same as
88     the RMI registry default port. */

89    protected int port = 1099;
90    /** The RMI port on which the Naming implementation will be exported. The
91     default is 0 which means use any available port. */

92    protected int rmiPort = 0;
93    /** A flag indicating if theServer will be set as the NamingContext.setLocal value */
94    protected boolean InstallGlobalService = true;
95    protected Logger log;
96    /** The thread pool used to handle jnp stub lookup requests */
97    protected ThreadPool lookupPool;
98
99    // Static --------------------------------------------------------
100
public static void main(String JavaDoc[] args)
101       throws Exception JavaDoc
102    {
103       new Main().start();
104    }
105  
106    // Constructors --------------------------------------------------
107
public Main()
108    {
109       this("org.jboss.naming.Naming");
110    }
111    public Main(String JavaDoc categoryName)
112    {
113       // Load properties from properties file
114
try
115       {
116          ClassLoader JavaDoc loader = getClass().getClassLoader();
117          InputStream JavaDoc is = loader.getResourceAsStream("jnp.properties");
118          System.getProperties().load(is);
119       }
120       catch (Exception JavaDoc e)
121       {
122          // Ignore
123
}
124
125       // Set configuration from the system properties
126
setPort(Integer.getInteger("jnp.port",getPort()).intValue());
127       setRmiPort(Integer.getInteger("jnp.rmiPort",getRmiPort()).intValue());
128       log = Logger.getLogger(categoryName);
129    }
130
131    // Public --------------------------------------------------------
132
public Naming getServer()
133    {
134       return theServer;
135    }
136
137    public ThreadPool getLookupPool()
138    {
139       return lookupPool;
140    }
141    public void setLookupPool(ThreadPool lookupPool)
142    {
143       this.lookupPool = lookupPool;
144    }
145
146    public void setNamingProxy(Object JavaDoc proxy)
147       throws IOException JavaDoc
148    {
149       serverStub = new MarshalledObject JavaDoc(proxy);
150    }
151
152    public void setRmiPort(int p)
153    {
154       rmiPort = p;
155    }
156    public int getRmiPort()
157    {
158       return rmiPort;
159    }
160
161    public void setPort(int p)
162    {
163       port = p;
164    }
165    public int getPort()
166    {
167       return port;
168    }
169
170    public String JavaDoc getBindAddress()
171    {
172       String JavaDoc address = null;
173       if( bindAddress != null )
174          address = bindAddress.getHostAddress();
175       return address;
176    }
177    public void setBindAddress(String JavaDoc host) throws UnknownHostException JavaDoc
178    {
179       if( host == null || host.length() == 0 )
180          bindAddress = null;
181       else
182          bindAddress = InetAddress.getByName(host);
183    }
184
185    public String JavaDoc getRmiBindAddress()
186    {
187       String JavaDoc address = null;
188       if( rmiBindAddress != null )
189          address = rmiBindAddress.getHostAddress();
190       return address;
191    }
192    public void setRmiBindAddress(String JavaDoc host) throws UnknownHostException JavaDoc
193    {
194       if( host == null || host.length() == 0 )
195          rmiBindAddress = null;
196       else
197          rmiBindAddress = InetAddress.getByName(host);
198    }
199
200    public int getBacklog()
201    {
202       return backlog;
203    }
204    public void setBacklog(int backlog)
205    {
206       if( backlog <= 0 )
207          backlog = 50;
208       this.backlog = backlog;
209    }
210
211    public boolean getInstallGlobalService()
212    {
213       return InstallGlobalService;
214    }
215    public void setInstallGlobalService(boolean flag)
216    {
217       this.InstallGlobalService = flag;
218    }
219
220    public String JavaDoc getClientSocketFactory()
221    {
222       return clientSocketFactoryName;
223    }
224    public void setClientSocketFactory(String JavaDoc factoryClassName)
225       throws ClassNotFoundException JavaDoc, InstantiationException JavaDoc, IllegalAccessException JavaDoc
226    {
227       this.clientSocketFactoryName = factoryClassName;
228       ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
229       Class JavaDoc clazz = loader.loadClass(clientSocketFactoryName);
230       clientSocketFactory = (RMIClientSocketFactory JavaDoc) clazz.newInstance();
231    }
232    
233    public String JavaDoc getServerSocketFactory()
234    {
235       return serverSocketFactoryName;
236    }
237    public void setServerSocketFactory(String JavaDoc factoryClassName)
238       throws ClassNotFoundException JavaDoc, InstantiationException JavaDoc, IllegalAccessException JavaDoc
239    {
240       this.serverSocketFactoryName = factoryClassName;
241       ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
242       Class JavaDoc clazz = loader.loadClass(serverSocketFactoryName);
243       serverSocketFactory = (RMIServerSocketFactory JavaDoc) clazz.newInstance();
244    }
245
246    public void setJNPServerSocketFactory(String JavaDoc factoryClassName)
247       throws ClassNotFoundException JavaDoc, InstantiationException JavaDoc, IllegalAccessException JavaDoc
248    {
249       this.jnpServerSocketFactoryName = factoryClassName;
250       ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
251       Class JavaDoc clazz = loader.loadClass(jnpServerSocketFactoryName);
252       jnpServerSocketFactory = (ServerSocketFactory JavaDoc) clazz.newInstance();
253    }
254
255    public void start()
256       throws Exception JavaDoc
257    {
258       // Create the local naming service instance if it does not exist
259
if( theServer == null )
260       {
261          theServer = new NamingServer();
262          if( InstallGlobalService == true )
263          {
264             // Set local server reference
265
NamingContext.setLocal(theServer);
266          }
267       }
268
269       // Initialize the custom socket factories with any bind address
270
initCustomSocketFactories();
271       /* Only export server RMI interface and setup the listening socket if
272         the port is >= 0 and an external proxy has not been installed.
273         A value < 0 indicates no socket based access
274       */

275       if( this.serverStub == null && this.port >= 0 )
276       {
277          initJnpInvoker();
278       }
279       // Only bring up the bootstrap listener if there is a naming proxy
280
if( this.serverStub != null )
281       {
282          initBootstrapListener();
283       }
284    }
285
286    public void stop()
287    {
288       try
289       {
290          // Stop listener and unexport the RMI object
291
if( serverSocket != null )
292          {
293             ServerSocket JavaDoc s = serverSocket;
294             serverSocket = null;
295             s.close();
296          }
297          if( isStubExported == true )
298             UnicastRemoteObject.unexportObject(theServer, false);
299       }
300       catch (Exception JavaDoc e)
301       {
302          log.error("Exception during shutdown", e);
303       }
304    }
305
306    /** This code should be moved to a seperate invoker in the org.jboss.naming
307     *package.
308     */

309    protected void initJnpInvoker() throws IOException JavaDoc
310    {
311       log.debug("Creating NamingServer stub, theServer="+theServer
312          +",rmiPort="+rmiPort+",clientSocketFactory="+clientSocketFactory
313          +",serverSocketFactory="+serverSocketFactory);
314       Remote JavaDoc stub = UnicastRemoteObject.exportObject(theServer, rmiPort,
315          clientSocketFactory, serverSocketFactory);
316       log.debug("NamingServer stub: "+stub);
317       serverStub = new MarshalledObject JavaDoc(stub);
318    }
319
320    /** Bring up the bootstrap lookup port for obtaining the naming service
321     * proxy
322     */

323    protected void initBootstrapListener()
324    {
325       // Start listener
326
try
327       {
328          // Get the default ServerSocketFactory is one was not specified
329
if( jnpServerSocketFactory == null )
330             jnpServerSocketFactory = ServerSocketFactory.getDefault();
331          serverSocket = jnpServerSocketFactory.createServerSocket(port, backlog, bindAddress);
332          // If an anonymous port was specified get the actual port used
333
if( port == 0 )
334             port = serverSocket.getLocalPort();
335          String JavaDoc msg = "JNDI bootstrap JNP=" + bindAddress + ":" + port
336             + ", RMI=" + bindAddress + ":" + rmiPort
337             + ", backlog="+backlog;
338
339           if (clientSocketFactory == null)
340             msg+= ", no client SocketFactory";
341           else
342             msg+= ", Client SocketFactory="+clientSocketFactory.getClass().toString();
343
344           if (serverSocketFactory == null)
345             msg+= ", no server SocketFactory";
346           else
347             msg+= ", Server SocketFactory="+serverSocketFactory.getClass().toString();
348
349          log.info(msg);
350       }
351       catch (IOException JavaDoc e)
352       {
353          log.error("Could not start on port " + port, e);
354        }
355
356       if( lookupPool == null )
357          lookupPool = new BasicThreadPool("NamingBootstrap Pool");
358       AcceptHandler handler = new AcceptHandler();
359       lookupPool.run(handler);
360    }
361
362    /**
363     * Init the clientSocketFactory, serverSocketFactory using the bind address.
364     */

365    protected void initCustomSocketFactories()
366    {
367       // Use either the rmiBindAddress or bindAddress for the RMI service
368
InetAddress JavaDoc addr = rmiBindAddress != null ? rmiBindAddress : bindAddress;
369
370       if (clientSocketFactory != null)
371       {
372          // See if the client socket supports setBindAddress(String)
373
try
374          {
375             Class JavaDoc csfClass = clientSocketFactory.getClass();
376             Class JavaDoc[] parameterTypes = {String JavaDoc.class};
377             Method JavaDoc m = csfClass.getMethod("setBindAddress", parameterTypes);
378             Object JavaDoc[] args = {addr.getHostAddress()};
379             m.invoke(clientSocketFactory, args);
380          }
381          catch (NoSuchMethodException JavaDoc e)
382          {
383             log.warn("Socket factory does not support setBindAddress(String)");
384             // Go with default address
385
}
386          catch (Exception JavaDoc e)
387          {
388             log.warn("Failed to setBindAddress="+addr+" on socket factory", e);
389             // Go with default address
390
}
391       }
392
393       try
394       {
395          if (serverSocketFactory == null)
396             serverSocketFactory = new DefaultSocketFactory(addr);
397          else
398          {
399             if (addr != null)
400             {
401                // See if the server socket supports setBindAddress(String)
402
try
403                {
404                   Class JavaDoc ssfClass = serverSocketFactory.getClass();
405                   Class JavaDoc[] parameterTypes = {String JavaDoc.class};
406                   Method JavaDoc m = ssfClass.getMethod("setBindAddress", parameterTypes);
407                   Object JavaDoc[] args = {addr.getHostAddress()};
408                   m.invoke(serverSocketFactory, args);
409                }
410                catch (NoSuchMethodException JavaDoc e)
411                {
412                   log.warn("Socket factory does not support setBindAddress(String)");
413                   // Go with default address
414
}
415                catch (Exception JavaDoc e)
416                {
417                   log.warn("Failed to setBindAddress="+addr+" on socket factory", e);
418                   // Go with default address
419
}
420             }
421          }
422       }
423       catch (Exception JavaDoc e)
424       {
425          log.error("operation failed", e);
426          serverSocketFactory = null;
427       }
428    }
429
430    private class AcceptHandler implements Runnable JavaDoc
431    {
432       public void run()
433       {
434          boolean trace = log.isTraceEnabled();
435          while( serverSocket != null )
436          {
437             Socket JavaDoc socket = null;
438             // Accept a connection
439
try
440             {
441                socket = serverSocket.accept();
442                if( trace )
443                   log.trace("Accepted bootstrap client: "+socket);
444                BootstrapRequestHandler handler = new BootstrapRequestHandler(socket);
445                lookupPool.run(handler);
446             }
447             catch (IOException JavaDoc e)
448             {
449                // Stopped by normal means
450
if (serverSocket == null)
451                   return;
452                log.error("Naming accept handler stopping", e);
453             }
454             catch(Throwable JavaDoc e)
455             {
456                log.error("Unexpected exception during accept", e);
457             }
458          }
459       }
460    }
461
462    private class BootstrapRequestHandler implements Runnable JavaDoc
463    {
464       private Socket JavaDoc socket;
465       BootstrapRequestHandler(Socket JavaDoc socket)
466       {
467          this.socket = socket;
468       }
469       public void run()
470       {
471          // Return the naming server stub
472
try
473          {
474             OutputStream JavaDoc os = socket.getOutputStream();
475             ObjectOutputStream JavaDoc out = new ObjectOutputStream JavaDoc(os);
476             out.writeObject(serverStub);
477             out.close();
478          }
479          catch (IOException JavaDoc ex)
480          {
481             log.debug("Error writing response to " + socket.getInetAddress(), ex);
482          }
483          finally
484          {
485             try
486             {
487                socket.close();
488             } catch (IOException JavaDoc e)
489             {
490             }
491          }
492       }
493    }
494 }
495
Popular Tags