package textbender.a.r.desk; // Copyright 2006-2007, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Textbender Software"), to deal in the Textbender Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Textbender Software, and to permit persons to whom the Textbender Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Textbender Software. THE TEXTBENDER SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE TEXTBENDER SOFTWARE OR THE USE OR OTHER DEALINGS IN THE TEXTBENDER SOFTWARE. import java.io.*; import java.math.BigInteger; import java.net.URL; import java.rmi.*; import java.util.Random; import java.rmi.registry.*; import textbender.g.lang.*; /** Registry of services for this host. * The shared instance of the registry is bound in the RMI boot-registry * (at the {@linkplain textbender.g.rmi.RegistryX#STANDARD_REGISTRY_PORT standard port}) * and may be obtained via {@linkplain HostServiceRegistry.X#findRegistry() X.findRegistry}(). */ public interface HostServiceRegistry extends Remote { // - H o s t - S e r v i c e - R e g i s t r y ---------------------------------------- /** Returns the file path of an all-in-one textbender JAR, * suitable as a codebase for applets and applications. * This JAR is intended for use by boot applets * that would otherwise lack a local codebase, * and is available only in demo installations of the desk daemon * (in normal installations, demo texts ought to boot like any other, * with no need of this facility). * * @throws IOException if the JAR is unavailable, * or the JAR file cannot be created * * @see textbender.a.r.page.BootApplet */ public @ThreadSafe File allInOneJar() throws IOException; // FIX, remove to separate service /** Returns an instance of the specified service. * * @param serviceInterface specifying the service * * @throws AccessException if the caller is from another host. * Services are provided only to the local host. */ public @ThreadSafe S getService( Class serviceInterface ) throws RemoteException; /** Returns the next unique identifier. */ public @ThreadSafe UniqueID nextUniqueID() throws RemoteException; // FIX, remove to separate service /** Resolves and returns the URL of the desk daemon's runtime JAR. * * @see #allInOneJar() */ @Deprecated // per HostServiceRegistry1.resolveJarURL public @ThreadSafe URL resolveJarURL() throws IOException; // FIX, remove to separate service // ==================================================================================== /** Service registry utilities. */ public @ThreadSafe static final class X { private X() {} // /** Finds the shared instance of the registry, // * and returns a reference to it. // * // * @return reference to the shared instance of the registry. // * It is either a local reference, a remote reference, or null; // * depending on whether the desk daemon is found running in the same VM, // * in another VM (normal case), or none is found at all. // */ // public static HostServiceRegistry findRegistry() //throws RemoteException // { // HostServiceRegistry serviceRegistry = HostServiceRegistry1.i(); // if( serviceRegistry != null ) return serviceRegistry; // local reference, will probably provide faster service to client // // try // { // serviceRegistry = (HostServiceRegistry)LocateRegistry.getRegistry().lookup // ( HostServiceRegistry.class.getName() ); // } // catch( RuntimeException xR ) { throw xR; } // catch( Exception x ) {} // NotBoundException, RemoteException means probably no desk daemon, so return null // return serviceRegistry; // } // //////// reference to implementation pulls in too many classes, offending lean clients /** Returns a remote reference to the registry. * * @return remote reference to the registry, or null if no registry is found */ public static HostServiceRegistry findRegistry() { HostServiceRegistry serviceRegistry = null; // so far try { serviceRegistry = (HostServiceRegistry)LocateRegistry.getRegistry().lookup ( HostServiceRegistry.class.getName() ); } catch( RuntimeException xR ) { throw xR; } catch( Exception x ) {} // NotBoundException, RemoteException means probably no desk daemon, so return null return serviceRegistry; } // /** Finds the shared instance of the registry, // * and returns a reference to it. // * // * @param maxRetryDelayMilliseconds If this is greater than 0, // * and no registry is detected on the first attempt, // * a second attempt is made after a random delay // * of at most maxRetryDelayMilliseconds. // * If it too fails, null is returned. // * The client might then {@linkplain Run#start() start a new daemon}. // * The purpose of the delayed retry is to avoid // * a collision with another VM doing the same thing. // * // * @return reference to the shared instance of the registry. // * It is either a local reference, a remote reference, or null; // * depending on whether the desk daemon is found running in the same VM, // * in another VM, or none is found at all. // */ // public static HostServiceRegistry findRegistry( int maxRetryDelayMilliseconds ) throws RemoteException // { // HostServiceRegistry serviceRegistry; // if( maxRetryDelayMilliseconds > 0 ) // { // serviceRegistry = findRegistry( 0 ); // if( serviceRegistry != null ) return serviceRegistry; // // ThreadX.trySleep( new Random().nextInt( maxRetryDelayMilliseconds )); // } // // serviceRegistry = HostServiceRegistry1.i(); // if( serviceRegistry != null ) return serviceRegistry; // local reference, will probably provide faster service to client // // try // { // serviceRegistry = (HostServiceRegistry)RegistryX.ensureRegistry().lookup // ( HostServiceRegistry.class.getName() ); // } // catch( NotBoundException x ) {} // either no desk daemon, or its initial boot-registry got shut down. In either case return null: // return serviceRegistry; // } // ////// On 2nd thought, bad idea. Clients should not launch this from their own VM, even for the demo. It should run independently. But the collision-avoidance logic might be used later... } // ==================================================================================== /** An identifier, each instance of which is guaranteed to be unique * within a single run of the desk daemon. * It is probably also unique between runs, but that is not guaranteed. *

* Often used to identify a remote source of data. * Useful where the source cannot be identified by a remote reference * because it does not implement Remote. * Or because it is short lived, and so its references too are short-lived. * (Comparing a reference to remote Applet source, by equals(), * may throw an exception after page exit "Timer already cancelled".) * In these cases, a UniqueID may be used instead. *

* * @see #nextUniqueID() */ public @ThreadSafe static final class UniqueID extends BigInteger { UniqueID( byte[] val ) { super( val ); } } }