[Mulgara-svn] r503 - branches/nw-interface/src/jar/driver/java/org/mulgara/server/driver

pag at mulgara.org pag at mulgara.org
Fri Nov 2 21:09:02 UTC 2007


Author: pag
Date: 2007-11-02 15:09:01 -0600 (Fri, 02 Nov 2007)
New Revision: 503

Modified:
   branches/nw-interface/src/jar/driver/java/org/mulgara/server/driver/SessionFactoryFinder.java
Log:
More robust local server URIs acheived through querying the name registry

Modified: branches/nw-interface/src/jar/driver/java/org/mulgara/server/driver/SessionFactoryFinder.java
===================================================================
--- branches/nw-interface/src/jar/driver/java/org/mulgara/server/driver/SessionFactoryFinder.java	2007-11-02 20:12:14 UTC (rev 502)
+++ branches/nw-interface/src/jar/driver/java/org/mulgara/server/driver/SessionFactoryFinder.java	2007-11-02 21:09:01 UTC (rev 503)
@@ -42,6 +42,7 @@
 
 // Locally written packages
 import org.mulgara.server.*;
+import org.mulgara.util.Reflect;
 
 /**
  * Obtain a {@link SessionFactory} instance.
@@ -65,45 +66,38 @@
  */
 public abstract class SessionFactoryFinder {
 
-  /**
-   * Logger.
-   *
-   * This is named after the class.
-   */
-  private static final Logger logger =
-      Logger.getLogger(SessionFactoryFinder.class.getName());
+  /** Logger. This is named after the class. */
+  private static final Logger logger = Logger.getLogger(SessionFactoryFinder.class.getName());
 
-  /**
-   * A ZeroConf peer.
-   *
-   * This listens for servers on the LAN.
-   */
-  /*
-     private static JmDNS jmdns;
-   */
+  /* A ZeroConf peer. This listens for servers on the LAN. */
+  // private static JmDNS jmdns;
 
   /**
    * Map from a database's URI scheme to the name of a {@link SessionFactory}
    * implementation for it.
    */
-  private static final Map schemeMap = new HashMap();
+  private static final Map<String,String> schemeMap = new HashMap<String,String>();
 
+  /**
+   * Environment setup for setting up a context for the naming registry.
+   */
+  private static final Hashtable<String,String> localContextEnv = new Hashtable<String,String>();
+
   static {
     schemeMap.put("beep", "org.mulgara.server.beep.BEEPSessionFactory");
     schemeMap.put("rmi", "org.mulgara.server.rmi.RmiSessionFactory");
     schemeMap.put("local", "org.mulgara.server.local.LocalSessionFactory");
-
-    /*
-         try {
-      jmdns = new JmDNS(InetAddress.getLocalHost());
-     jmdns.addServiceListener("_itql._tcp.local", new ServerServiceListener());
-         }
-         catch (Exception e) {
-      logger.warn("Couldn't start ZeroConf peer", e);
-         }
-     */
+    localContextEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
+    localContextEnv.put(Context.PROVIDER_URL, "rmi://localhost");
+//    try {
+//      jmdns = new JmDNS(InetAddress.getLocalHost());
+//      jmdns.addServiceListener("_itql._tcp.local", new ServerServiceListener());
+//    } catch (Exception e) {
+//      logger.warn("Couldn't start ZeroConf peer", e);
+//    }
   }
 
+
   /**
    * Obtain a {@link SessionFactory} instance.  Assumes that this is being used
    * locally - within the same JVM.
@@ -133,75 +127,64 @@
       boolean isRemote) throws SessionFactoryFinderException, NonRemoteSessionException {
 
     // If no serverURI was specified, search the LAN for a local server
-    if (serverURI == null) {
-      serverURI = findServerURI();
-    }
+    if (serverURI == null) serverURI = findServerURI();
     assert serverURI != null;
 
+    String scheme = serverURI.getScheme();
+
     // Obtain the classname for the SessionFactory
     String className;
 
     // Handle RMI schemes differently.
-    if (serverURI.getScheme().equals("rmi")) {
+    if (scheme.equals("rmi")) {
       logger.debug("Attempting to connect via RMI");
       // First attempt to connect via RMI.
       try {
-        Hashtable environment = new Hashtable();
-        environment.put("java.naming.factory.initial",
-            "com.sun.jndi.rmi.registry.RegistryContextFactory");
-        environment.put("java.naming.provider.url",
-            "rmi://" + serverURI.getRawAuthority());
+        Hashtable<String,String> environment = new Hashtable<String,String>();
+        environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
+        environment.put(Context.PROVIDER_URL, "rmi://" + serverURI.getRawAuthority());
         Context rmiRegistryContext = new InitialContext(environment);
-        rmiRegistryContext.lookup(serverURI.getPath()
-          .substring(1));
+        rmiRegistryContext.lookup(serverURI.getPath().substring(1));
 
         // If the lookup is successful connect using RMI.
-        className = (String) schemeMap.get(serverURI.getScheme());
+        className = (String)schemeMap.get(scheme);
       } catch (NamingException ne) {
         logger.debug("Failed to connect via RMI", ne);
 
         // If there is an exception connect locally.
         if (!isRemote) {
           logger.debug("Attempting to fallback to local", ne);
-          className = (String) schemeMap.get("local");
+          className = (String)schemeMap.get("local");
+        } else {
+          throw new SessionFactoryFinderException("Cannot find server " + serverURI, ne);
         }
-        else {
-          throw new SessionFactoryFinderException(
-              "Cannot find server " + serverURI, ne);
-        }
       }
+    } else {
+      className = (String)schemeMap.get(scheme);
     }
-    else {
-      className = (String) schemeMap.get(serverURI.getScheme());
-    }
 
     if (className == null) {
-      throw new SessionFactoryFinderException(
-          serverURI + " has unsupported scheme (" + serverURI.getScheme() + ")"
-      );
+      throw new SessionFactoryFinderException(serverURI + " has unsupported scheme (" + scheme + ")");
     }
     assert className != null;
 
     // Use reflection to create the SessionFactory
     try {
       try {
-        return (SessionFactory) Class.forName(className).
-            getConstructor(new Class[] { URI.class }).newInstance(new Object[] {
-            serverURI});
-      } catch (java.lang.reflect.InvocationTargetException ie) {
+        return (SessionFactory)Reflect.newInstance(Class.forName(className), serverURI);
+      } catch (RuntimeException ie) {
+        Throwable originalEx = ie.getCause();
         // check if the exception thrown indicates we should retry
-        Throwable e = ie.getCause();
+        Throwable e = originalEx.getCause();
         if (!(e instanceof NonRemoteSessionException)) {
           throw new SessionFactoryFinderException("Couldn't create session factory for " + serverURI, e);
         }
         // tell the calling code
-        throw (NonRemoteSessionException)e;
+        throw (NonRemoteSessionException)originalEx;
       }
 
     } catch (Exception e) {
-      throw new SessionFactoryFinderException(
-          "Couldn't create session factory for " + serverURI, e
-      );
+      throw new SessionFactoryFinderException("Couldn't create session factory for " + serverURI, e);
     }
   }
 
@@ -209,10 +192,10 @@
    * Find a server.
    *
    * This currently only tries for a Java RMI server on the local host.
+   * Consider falling back to other hosts seen when asking for a session factory.
    *
-   * @return a Java RMI server {@link URI} for the local host, never
-   *   <code>null</code>
-   * @throws SessionFactoryFinderException  if the server URI can't be composed
+   * @return a Java RMI server {@link URI} for the local host, never <code>null</code>
+   * @throws SessionFactoryFinderException if the server URI can't be composed
    */
   public static URI findServerURI() throws SessionFactoryFinderException {
     // Look for an RMI server named "server1" on the local host
@@ -220,56 +203,34 @@
       return new URI(
           "rmi", // Java RMI protocol
           InetAddress.getLocalHost().getCanonicalHostName(), // host
-          "/server1", // default RMI server
+          "/" + getServiceName(),
           null // no fragment means this is a server, not a model
       );
+    } catch (UnknownHostException e) {
+      throw new SessionFactoryFinderException("Couldn't determine local host name", e);
+    } catch (URISyntaxException e) {
+      throw new SessionFactoryFinderException("Invalid local server URI", e);
     }
-    catch (UnknownHostException e) {
-      throw new SessionFactoryFinderException(
-          "Couldn't determine local host name", e
-      );
-    }
-    catch (URISyntaxException e) {
-      throw new SessionFactoryFinderException(
-          "Invalid local server URI", e
-      );
-    }
-
-    /*
-         throw new SessionFactoryFinderException(
-      "Null \"serverURI\" parameter - LAN search not yet implemented"
-         );
-     */
   }
 
+
   /**
-   * Method to ask the ServerInfo for the local database session.
-   * This will return null if ServerInfo is not available -
-   * ie. being run on a host which has no local database, such an an iTQL client.
-   *
-   * @throws SessionFactoryFinderException If ServerInfo can't be called.  This
-   *         should only happen on a client, which should not have asked for a local session
-   *         anyway.
+   * Lookup the local registry for any registered names.
+   * @return The first name registered with the local RMI server, or the default name if this cannot be found.
    */
-  private static SessionFactory getLocalSessionFactory() throws SessionFactoryFinderException {
-    Object factory = null;
+  private static String getServiceName() {
     try {
-      Class<?> rsf = Class.forName("org.mulgara.server.ServerInfo");
-      java.lang.reflect.Method getLocalSessionFactory = rsf.getMethod("getLocalSessionFactory", (Class<?>[])null);
-      factory = getLocalSessionFactory.invoke(null, (Object[])null);
-    } catch (Exception e) {
-      throw new SessionFactoryFinderException(
-          "Couldn't obtain a local session factory.  Unexpected problem.", e
-      );
-    }
-    if (factory == null) {
-      throw new SessionFactoryFinderException(
-          "Couldn't obtain a local session factory.  Server has no access to database."
-      );
-    }
-    return (SessionFactory)factory;
+      Context rmiRegistryContext = new InitialContext(localContextEnv);
+      // get the list of names for the default context
+      NamingEnumeration<NameClassPair> ne = rmiRegistryContext.list(rmiRegistryContext.getNameInNamespace());
+      // return the first name
+      if (ne.hasMore()) return ne.next().getName(); 
+    } catch (NamingException e) { /* fall back to the default */ }
+    
+    // error or no name found, so return the default name.
+    return SessionFactoryFactory.DEFAULT_SERVER_NAME;
   }
-
+  
   /**
    * Listens for notification via ZeroConf of servers appearing on the LAN.
    */




More information about the Mulgara-svn mailing list