Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/jnp/server/Main.java


1   /*
2    * Distributable under LGPL license.
3    * See terms of license at gnu.org.
4    *
5    * Copyright 1999 by dreamBean Software,
6    * All rights reserved.
7    */
8   package org.jnp.server;
9   
10  import java.io.InputStream;
11  import java.io.IOException;
12  import java.io.ObjectOutputStream;
13  import java.net.InetAddress;
14  import java.net.Socket;
15  import java.net.ServerSocket;
16  import java.net.UnknownHostException;
17  import java.net.URL;
18  import java.rmi.Remote;
19  import java.rmi.MarshalledObject;
20  import java.rmi.server.RMIClientSocketFactory;
21  import java.rmi.server.RMIServerSocketFactory;
22  import java.rmi.server.UnicastRemoteObject;
23  import java.lang.reflect.Method;
24  import javax.net.ServerSocketFactory;
25  
26  import org.apache.log4j.Category;
27  import org.apache.log4j.PropertyConfigurator;
28  
29  import org.jnp.interfaces.Naming;
30  import org.jnp.interfaces.NamingContext;
31  import org.jboss.net.sockets.DefaultSocketFactory;
32  
33  /** A main() entry point for running the jnp naming service implementation as
34   a standalone process.
35   
36   @author oberg
37   @author Scott.Stark@jboss.org
38   @version $Revision: 1.12.2.6 $
39   */
40  public class Main implements Runnable, MainMBean
41  {
42     // Constants -----------------------------------------------------
43     
44     // Attributes ----------------------------------------------------
45     /** The Naming interface server implementation */
46     protected NamingServer theServer;
47     protected MarshalledObject serverStub;
48     /** The jnp server socket through which the NamingServer stub is vended */
49     protected ServerSocket serverSocket;
50     /** An optional custom client socket factory */
51     protected RMIClientSocketFactory clientSocketFactory;
52     /** An optional custom server socket factory */
53     protected RMIServerSocketFactory serverSocketFactory;
54     /** An optional custom server socket factory */
55     protected ServerSocketFactory jnpServerSocketFactory;
56     /** The class name of the optional custom client socket factory */
57     protected String clientSocketFactoryName;
58     /** The class name of the optional custom server socket factory */
59     protected String serverSocketFactoryName;
60     /** The class name of the optional custom JNP server socket factory */
61     protected String jnpServerSocketFactoryName;
62     /** The interface to bind to for the lookup socket. This is useful for
63      * multi-homed hosts that want control over which interfaces accept
64      * connections.
65      */
66     protected InetAddress bindAddress;
67     /** The interface to bind to for the Naming RMI server.
68      */ 
69     protected InetAddress rmiBindAddress;
70     /** The serverSocket listen queue depth */
71     protected int backlog = 50;
72     /** The jnp protocol listening port. The default is 1099, the same as
73      the RMI registry default port. */
74     protected int port = 1099;
75     /** The RMI port on which the Naming implementation will be exported. The
76      default is 0 which means use any available port. */
77     protected int rmiPort = 0;
78     /** A flag indicating if theServer will be set as the NamingContext.setLocal value */
79     protected boolean InstallGlobalService = true;
80     protected Category log;
81  
82     // Static --------------------------------------------------------
83     public static void main(String[] args)
84        throws Exception
85     {
86        // Make sure the config file can be found
87        ClassLoader loader = Thread.currentThread().getContextClassLoader();
88        URL url = loader.getResource("log4j.properties");
89        if( url == null )
90           System.err.println("Failed to find log4j.properties");
91        else
92           PropertyConfigurator.configure(url);
93        new Main().start();
94     }
95     
96     // Constructors --------------------------------------------------
97     public Main()
98     {
99        this("org.jboss.naming.Naming");
100    }
101    public Main(String categoryName)
102    {
103       // Load properties from properties file
104       try
105       {
106          ClassLoader loader = getClass().getClassLoader();
107          InputStream is = loader.getResourceAsStream("jnp.properties");
108          System.getProperties().load(is);
109       }
110       catch (Exception e)
111       {
112          // Ignore
113       }
114 
115       // Set configuration from the system properties
116       setPort(Integer.getInteger("jnp.port",getPort()).intValue());
117       setRmiPort(Integer.getInteger("jnp.rmiPort",getRmiPort()).intValue());
118       log = Category.getInstance(categoryName);
119    }
120 
121    // Public --------------------------------------------------------
122    public Naming getServer()
123    {
124       return theServer;
125    }
126 
127    public void setRmiPort(int p)
128    {
129       rmiPort = p;
130    }
131    public int getRmiPort()
132    {
133       return rmiPort;
134    }
135 
136    public void setPort(int p)
137    {
138       port = p;
139    }
140    public int getPort()
141    {
142       return port;
143    }
144 
145    public String getBindAddress()
146    {
147       String address = null;
148       if( bindAddress != null )
149          address = bindAddress.getHostAddress();
150       return address;
151    }
152    public void setBindAddress(String host) throws UnknownHostException
153    {
154       if( host == null || host.length() == 0 )
155          bindAddress = null;
156       else
157          bindAddress = InetAddress.getByName(host);
158    }
159 
160    public String getRmiBindAddress()
161    {
162       String address = null;
163       if( rmiBindAddress != null )
164          address = rmiBindAddress.getHostAddress();
165       return address;
166    }
167    public void setRmiBindAddress(String host) throws UnknownHostException
168    {
169       if( host == null || host.length() == 0 )
170          rmiBindAddress = null;
171       else
172          rmiBindAddress = InetAddress.getByName(host);
173    }
174 
175    public int getBacklog()
176    {
177       return backlog;
178    }
179    public void setBacklog(int backlog)
180    {
181       if( backlog <= 0 )
182          backlog = 50;
183       this.backlog = backlog;
184    }
185 
186    public boolean getInstallGlobalService()
187    {
188       return InstallGlobalService;
189    }
190    public void setInstallGlobalService(boolean flag)
191    {
192       this.InstallGlobalService = flag;
193    }
194 
195    public String getClientSocketFactory()
196    {
197       return clientSocketFactoryName;
198    }
199    public void setClientSocketFactory(String factoryClassName)
200       throws ClassNotFoundException, InstantiationException, IllegalAccessException
201    {
202       this.clientSocketFactoryName = factoryClassName;
203       ClassLoader loader = Thread.currentThread().getContextClassLoader();
204       Class clazz = loader.loadClass(clientSocketFactoryName);
205       clientSocketFactory = (RMIClientSocketFactory) clazz.newInstance();
206    }
207    
208    public String getServerSocketFactory()
209    {
210       return serverSocketFactoryName;
211    }
212    public void setServerSocketFactory(String factoryClassName)
213       throws ClassNotFoundException, InstantiationException, IllegalAccessException
214    {
215       this.serverSocketFactoryName = factoryClassName;
216       ClassLoader loader = Thread.currentThread().getContextClassLoader();
217       Class clazz = loader.loadClass(serverSocketFactoryName);
218       serverSocketFactory = (RMIServerSocketFactory) clazz.newInstance();
219    }
220 
221    public void setJNPServerSocketFactory(String factoryClassName)
222       throws ClassNotFoundException, InstantiationException, IllegalAccessException
223    {
224       this.jnpServerSocketFactoryName = factoryClassName;
225       ClassLoader loader = Thread.currentThread().getContextClassLoader();
226       Class clazz = loader.loadClass(jnpServerSocketFactoryName);
227       jnpServerSocketFactory = (ServerSocketFactory) clazz.newInstance();
228    }
229 
230    public void start()
231       throws Exception
232    {
233       log.info("Starting jnp server");
234       // Create the local naming service instance if it does not exist
235       if( theServer == null )
236       {
237          theServer = new NamingServer();
238          if( InstallGlobalService == true )
239          {
240             // Set local server reference
241             NamingContext.setLocal(theServer);
242          }
243       }
244 
245       /* Only export server RMI interface and setup the listening socket if
246         the port is >= 0. A value < 0 indicates the socket based access
247       */
248       if( this.port >= 0 )
249          initJnpInvoker();
250    }
251 
252    public void stop()
253    {
254       try
255       {
256          log.info("Stopping");
257          // Stop listener and unexport the RMI object
258          if( serverSocket != null )
259          {
260             UnicastRemoteObject.unexportObject(theServer, false);
261             ServerSocket s = serverSocket;
262             serverSocket = null;
263             s.close();
264          }
265          log.info("Stopped");
266       }
267       catch (Exception e)
268       {
269          log.error("Exception during shutdown", e);
270       }
271    }
272 
273    // Runnable implementation ---------------------------------------
274    public void run()
275    {
276       Socket socket = null;
277       
278       // Accept a connection
279       try
280       {
281          socket = serverSocket.accept();
282       } catch (IOException e)
283       {
284          if (serverSocket == null)
285             return; // Stopped by normal means
286 
287          log.error("Naming stopped", e);
288          log.info("Restarting naming");
289          try
290          {
291             start();
292          } catch (Exception ex)
293          {
294             log.error("Restart failed", ex);
295             return;
296          }
297       }
298 
299       // Create a new thread to accept the next connection
300       listen();
301       
302       // Return the naming server stub
303       try
304       {
305          ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
306          out.writeObject(serverStub);
307       }
308       catch (IOException ex)
309       {
310          log.error("Error writing response", ex);
311       }
312       finally
313       {
314          try
315          {
316             socket.close();
317          } catch (IOException e)
318          {
319          }
320       }
321    }
322    
323    // Y overrides ---------------------------------------------------
324    
325    // Package protected ---------------------------------------------
326    
327    // Protected -----------------------------------------------------
328    
329    protected void listen()
330    {
331       Thread t = new Thread(this, "JNP Server");
332       t.start();
333    }   
334 
335    /** This code should be moved to a seperate invoker in the org.jboss.naming
336     *package.
337     */
338    protected void initJnpInvoker() throws IOException
339    {
340       // Use either the rmiBindAddress or bindAddress for the RMI service
341       InetAddress addr = rmiBindAddress;
342       if( addr == null )
343          addr = bindAddress;
344       // If there is an address we need a socket factory
345       if( addr != null )
346       {
347          // If there is no serverSocketFactory use a default
348          if( serverSocketFactory == null )
349             serverSocketFactory = new DefaultSocketFactory(addr);
350          else
351          {
352             // See if the server socket supports setBindAddress(String)
353             try
354             {
355                Class[] parameterTypes = {String.class};
356                Class ssfClass = serverSocketFactory.getClass();
357                Method m = ssfClass.getMethod("setBindAddress", parameterTypes);
358                Object[] args = {bindAddress.getHostAddress()};
359                m.invoke(serverSocketFactory, args);
360             }
361             catch (NoSuchMethodException e)
362             {
363                log.warn("Socket factory does not support setBindAddress(String)");
364                // Go with default address
365             }
366             catch (Exception e)
367             {
368                log.warn("Failed to setBindAddress="+bindAddress+" on socket factory", e);
369                // Go with default address
370             }
371          }
372       }
373       log.debug("Creating NamingServer stub, theServer="+theServer
374          +",rmiPort="+rmiPort+",clientSocketFactory="+clientSocketFactory
375          +",serverSocketFactory="+serverSocketFactory);
376       Remote stub = UnicastRemoteObject.exportObject(theServer, rmiPort,
377          clientSocketFactory, serverSocketFactory);
378       log.debug("NamingServer stub: "+stub);
379       serverStub = new MarshalledObject(stub);
380  
381       // Start listener
382       try
383       {
384          // Get the default ServerSocketFactory is one was not specified
385          if( jnpServerSocketFactory == null )
386             jnpServerSocketFactory = ServerSocketFactory.getDefault();
387          serverSocket = jnpServerSocketFactory.createServerSocket(port, backlog, bindAddress);
388          // If an anonymous port was specified get the actual port used
389          if( port == 0 )
390             port = serverSocket.getLocalPort();
391          String msg = "Started jnpPort=" + port +", rmiPort=" + rmiPort
392             + ", backlog="+backlog+", bindAddress="+bindAddress
393             + ", Client SocketFactory="+clientSocketFactory
394             + ", Server SocketFactory="+serverSocketFactory;
395          log.info(msg);
396          listen();
397       }
398       catch (IOException e)
399       {
400          log.error("Could not start on port " + port, e);
401       }
402    }
403 
404    // Private -------------------------------------------------------
405    
406    // Inner classes -------------------------------------------------
407 }