/* The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * http://www.sun.com/cddl/cddl.html or * install_dir/legal/LICENSE * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at install_dir/legal/LICENSE. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * $Id$ * * Copyright 2005-2009 Sun Microsystems Inc. All Rights Reserved */ package com.sun.faban.common; import java.rmi.RMISecurityManager; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.server.UnicastRemoteObject; import java.util.HashMap; import java.util.Iterator; import java.util.logging.Logger; import java.util.logging.Level; /** * This class implements the Registry interface * The Registry is the single remote object that runs on the master * machine and with which all other instances of remote servers reregister. * A remote reference to any remote service is obtained by the GUI as * well as the Engine through the registry. There is only one remote * server object (the Registry) that is known by rmiregistry running * on the master machine. Once a reference to the Registry is obtained * by the client, it should use the 'getReference' method to obtain a * reference to any type of remote server.<p> * * Although the Registry implementation uses rmi underneath, the rmi registry * is fully encapsulated inside the Registry and RegistryLocator to avoid any * confusion in the agent programs and other programs accessing the registry. * * @author Shanti Subramanyam */ public class RegistryImpl extends UnicastRemoteObject implements Registry { // This field is a legal requirement and serves no other purpose. static final String COPYRIGHT = "Copyright \251 2006-2009 Sun Microsystems, Inc., 4150 Network " + "Circle, Santa Clara, California 95054, U.S.A. All rights " + "reserved.\nU.S. Government Rights - Commercial software. " + "Government users are subject to the Sun Microsystems, Inc. " + "standard license agreement and applicable provisions of the FAR " + "and its supplements.\n" + "Use is subject to license terms.\n" + "This distribution may include materials developed by third " + "parties.\n" + "Sun, Sun Microsystems, the Sun logo and Java are trademarks " + "or registered trademarks of Sun Microsystems, Inc. in the U.S. " + "and other countries.\n" + "Apache is a trademark of The Apache Software Foundation, and is " + "used with permission.\n" + "This product is covered and controlled by U.S. Export Control " + "laws and may be subject to the export or import laws in other " + "countries. Nuclear, missile, chemical biological weapons or " + "nuclear maritime end uses or end users, whether direct or " + "indirect, are strictly prohibited. Export or reexport to " + "countries subject to U.S. embargo or to entities identified on " + "U.S. export exclusion lists, including, but not limited to, the " + "denied persons and specially designated nationals lists is " + "strictly prohibited.\n" + "\n" + "Copyright \251 2006-2009 Sun Microsystems, Inc., 4150 Network " + "Circle, Santa Clara, California 95054, Etats-Unis. Tous droits " + "r\351serv\351s.\n" + "L'utilisation est soumise aux termes de la Licence.\n" + "Cette distribution peut comprendre des composants " + "d\351velopp\351s par des tierces parties.\n" + "Sun, Sun Microsystems, le logo Sun et Java sont des marques " + "de fabrique ou des marques d\351pos\351es de " + "Sun Microsystems, Inc. aux Etats-Unis et dans d'autres pays.\n" + "Apache est une marque d\264Apache Software Foundation, utilis\351e " + "avec leur permission.\n" + "Ce produit est soumis \340 la l\351gislation am\351ricaine " + "en mati\350re de contr\364le des exportations et peut \352tre " + "soumis \340 la r\350glementation en vigueur dans d'autres pays " + "dans le domaine des exportations et importations. Les " + "utilisations, ou utilisateurs finaux, pour des armes " + "nucl\351aires, des missiles, des armes biologiques et chimiques " + "ou du nucl\351aire maritime, directement ou indirectement, sont " + "strictement interdites. Les exportations ou r\351exportations " + "vers les pays sous embargo am\351ricain, ou vers des entit\351s " + "figurant sur les listes d'exclusion d'exportation " + "am\351ricaines, y compris, mais de mani\350re non exhaustive, " + "la liste de personnes qui font objet d'un ordre de ne pas " + "participer, d'une fa\347on directe ou indirecte, aux " + "exportations des produits ou des services qui sont r\351gis par " + "la l\351gislation am\351ricaine en mati\350re de contr\364le " + "des exportations et la liste de ressortissants sp\351cifiquement " + "d\351sign\351s, sont rigoureusement interdites.\n"; private static final long serialVersionUID = 20070523L; static int rmiPort = RegistryLocator.DEFAULT_PORT; private HashMap<String, Remote> servicesTable = new HashMap<String, Remote>(); private HashMap<String, HashMap<String, Remote>> servicesTypeTable = new HashMap<String, HashMap<String, Remote>>(); // private String className; private static Logger logger = Logger.getLogger(RegistryImpl.class.getName()); private RegistryImpl() throws RemoteException { super(); } /** * Registers service with Registry. * The service driverName is of the form <driverName>@<host> * For example, a CmdAgent will reregister itself as CmdAgent@<host> * so all CmdAgents on different machines can be uniquely * identified by driverName. * * @param name public driverName of service * @param service Remote reference to service * @return true if registration succeeded, false if there is already * an object registered by this name. */ public synchronized boolean register(String name, Remote service) { if (servicesTable.get(name) == null) { logger.info("Registering " + name + " on " + getCaller()); servicesTable.put(name, service); return true; } else { logger.warning("Failed registering. Service " + name + " already exists"); return false; } } /** * Registers service with Registry. * The service driverName is of the form <driverName>@<host> * For example, a CmdAgent will reregister itself as CmdAgent@<host> * so all CmdAgents on different machines can be uniquely * identified by driverName. * * @param type of service * @param name of service * @param service Remote reference to service * @return true if registration succeeded, false if there is already * an object registered by this name. */ public synchronized boolean register(String type, String name, Remote service) { if (service == null) throw new NullPointerException("Type: " + type + ", Name: " + name + "| Service reference is null"); // First check if the type of service exists HashMap<String, Remote> h = servicesTypeTable.get(type); if (h == null) { h = new HashMap<String, Remote>(); servicesTypeTable.put(type, h); } else if (h.get(name) != null) { logger.warning("Failed registering. Service " + name + " already exists"); return false; } logger.info("Registering " + name + " (type: " + type + ") on " + getCaller()); h.put(name, service); return true; } /** * Re-registers service with Registry, replacing old entry if exists. * The service driverName is of the form <driverName>@<host> * For example, a CmdAgent will reregister itself as CmdAgent@<host> * so all CmdAgents on different machiens can be uniquely * identified by driverName. * @param name public driverName of service * @param service Remote reference to service */ public synchronized void reregister(String name, Remote service) { logger.info("Registering " + name + " on " + getCaller()); servicesTable.put(name, service); } /** * Re-registers service with Registry, replacing old entry if exists. * The service driverName is of the form <driverName>@<host> * For example, a CmdAgent will reregister itself as CmdAgent@<host> * so all CmdAgents on different machiens can be uniquely * identified by driverName. * @param type of service * @param name of service * @param service Remote reference to service */ public synchronized void reregister(String type, String name, Remote service) { if (service == null) throw new NullPointerException("Type: " + type + ", Name: " + name + "| Service reference is null"); // First check if the type of service exists HashMap<String, Remote> h = servicesTypeTable.get(type); if (h == null) { h = new HashMap<String, Remote>(); servicesTypeTable.put(type, h); } logger.info("Registering " + name + " (type: " + type + ") on " + getCaller()); h.put(name, service); } /** * unregister service from Registry * The registry removes this service from its list and clients * can no longer access it. This method is typically called when * the service exits. * @param name public driverName of service */ public synchronized void unregister(String name) { logger.info("Unregistering " + name); servicesTable.remove(name); } /** * unregister service from Registry * The registry removes this service from its list and clients * can no longer access it. This method is typically called when * the service exits. * @param type of service * @param name public driverName of service */ public synchronized void unregister(String type, String name) { // First check if the type of service exists HashMap<String, Remote> h = servicesTypeTable.get(type); if (h == null) { logger.warning("Registry.unregister : " + "Cannot find Service type : " + type); } else { logger.info("Unregistering " + name + "(type: " + type + ")"); h.remove(name); } } /** * get reference to service from Registry * The registry searches in its list of registered services * and returns a remote reference to the requested one. * The service driverName is of the form <driverName>@<host> * @param name public driverName of service * @return remote reference */ public synchronized Remote getService(String name) { logger.info("Get service by name: " + name); return servicesTable.get(name); } /** * get reference to service from Registry * The registry searches in its list of registered services * and returns a remote reference to the requested one. * The service driverName is of the form <driverName>@<host> * @param type of service * @param name public driverName of service * @return remote reference */ public synchronized Remote getService(String type, String name) { logger.info("Get service by name: " + name + ", type: " + type); Remote r = null; // First check if the type of service exists HashMap<String, Remote> h = servicesTypeTable.get(type); if (h == null) { logger.warning("Registry.getService : " + "Cannot find Service type : " + type); } else { r = h.get(name); } return r; } /** * get all references to a type of services from Registry * The registry searches in its list of registered services * and returns all remote references to the requested type. * The service driverName is of the form <driverName>@<host> * @param type of service * @return remote references */ public synchronized Remote[] getServices(String type) { logger.info("Get services by type: " + type); Remote[] r = null; // First check if the type of service exists HashMap<String, Remote> h = servicesTypeTable.get(type); if (h == null) { logger.warning("Registry.getServices : " + "Cannot find Service type : " + type); } else { r = new Remote[h.size()]; r = h.values().toArray(r); } return r; } /** * Get the number of registered Services of a type. * @param type of service * @return int number of registered services */ public synchronized int getNumServices(String type) { // First check if the type of service exists HashMap<String, Remote> h = servicesTypeTable.get(type); int i = 0; if (h == null) { logger.warning("Registry.getNumServices : " + "Cannot find Service type : " + type); } else { i = h.size(); } return i; } // Get the caller private String getCaller() { String s = null; try { s = getClientHost(); } catch (Exception e) { logger.log(Level.SEVERE, e.getMessage(), e); } return s; } /** * Kill is called to exit the RMI registry and Registry. */ public void kill() { logger.info("Unregistering Services"); for (Iterator<String> iter = servicesTable.keySet().iterator(); iter.hasNext();) { logger.fine("Unregistering " + iter.next()); iter.remove(); } for (Iterator<String> iter = servicesTypeTable.keySet().iterator(); iter.hasNext();) { logger.fine("Unregistering " + iter.next()); iter.remove(); } // *** This is to gracefully return from this method. // *** The Agent will exit after 5 seconds // *** If the System.exit(0) is called in this method // *** the Service will get a RemoteException Thread exitThread = new Thread() { public void run() { try { Thread.sleep(5000); System.exit(0); } catch(Exception e) {} } }; exitThread.start(); logger.info("Registry will exit in 5 secs"); } /** * Registration for RMI serving. * * @param args Command line arguments, not used */ public static void main(String[] args) { String portString = System.getProperty("faban.registry.port"); if (portString != null) try { rmiPort = Integer.parseInt(portString); } catch (NumberFormatException e) { System.err.println("Property faban.registry.port " + e.getMessage()); e.printStackTrace(); System.exit(-1); } java.rmi.registry.Registry rmiRegistry = null; try { rmiRegistry = LocateRegistry.createRegistry(rmiPort); logger.fine("Registry listening on port " + rmiPort + "."); } catch (Exception e) { logger.log(Level.SEVERE, "Exception starting registry.", e); System.exit(-1); } System.setSecurityManager (new RMISecurityManager()); try { Registry registry = new RegistryImpl(); rmiRegistry.bind(RegistryLocator.BIND_NAME, registry); // debug.println(3, "Binding registry to " + s); // If the debug level is set to too high and if this is not // printed driver will hang !!!! logger.info("Registry started."); } catch (Exception e) { e.printStackTrace(); try { rmiRegistry.unbind(RegistryLocator.BIND_NAME); } catch (Exception ei) { } System.exit(-1); } } }