package helpers;

/**
 * Cette classe facilite l'initialisation d'un registre RMI directement depuis
 * votre propre code. Il n'est donc pas necessaire de lancer le registre
 * separemment depuis la ligne de commande.
 * 
 * Par contre, cela implique que le serveur RMI et son registre soient situees
 * sur la mme machine.
 * 
 * Ils partagent donc le meme classpath (car meme JVM) et toutes les classes
 * visibles par le serveur sont aussi visibles par l'annuaire. Il n'y a donc pas
 * de configuration fastidieuse du classpath de l'annuaire a effectuer.
 * 
 * @author pierre
 * 
 */
public class RegistryHelper {

	protected final static int DEFAULT_REGISTRY_PORT = 1099;

	/**
	 * settings of the registry
	 */
	protected int registryPortNumber = DEFAULT_REGISTRY_PORT;
	protected boolean shouldCreateRegistry = true;
	protected boolean registryChecked;

	public RegistryHelper() {
	}

	public int getRegistryPortNumber() {
		return registryPortNumber;
	}

	public void setRegistryPortNumber(int v) {
		registryPortNumber = v;
		registryChecked = false;
	}

	public boolean shouldCreateRegistry() {
		return shouldCreateRegistry;
	}

	public void setShouldCreateRegistry(boolean v) {
		shouldCreateRegistry = v;
	}

	/**
	 * Methode principale qui permet d'initialiser le registre RMI pour
	 * l'enregistrement d'objets serveurs.
	 * 
	 * @throws java.rmi.RemoteException
	 */
	public synchronized void initializeRegistry()
			throws java.rmi.RemoteException {
		if (!shouldCreateRegistry)
			return; // don't bother
		if (registryChecked)
			return; // already done for this VM
		getOrCreateRegistry(registryPortNumber);
		registryChecked = true;
	}

	private static java.rmi.registry.Registry createRegistry(int port)
			throws java.rmi.RemoteException {
		return java.rmi.registry.LocateRegistry.createRegistry(port);
	}

	private static java.rmi.registry.Registry detectRegistry(int port) {
		java.rmi.registry.Registry registry = null;
		try {
			// whether an effective registry exists or not we should get a
			// reference
			registry = java.rmi.registry.LocateRegistry.getRegistry(port);
			if (registry == null)
				return null;
			// doing a lookup should produce ConnectException if registry
			// doesn't exist
			// and no exception or NotBoundException if the registry does exist.
			java.rmi.Remote r = registry.lookup("blah!");
			System.out.println("Detected an existing RMI Registry on port "
					+ port);
			return registry;
		} catch (java.rmi.NotBoundException e) {
			System.out.println("Detected an existing RMI Registry on port "
					+ port);
			return registry;
		} catch (java.rmi.RemoteException e) {
			return null;
		}
	}

	private static java.rmi.registry.Registry getOrCreateRegistry(int port)
			throws java.rmi.RemoteException {
		java.rmi.registry.Registry registry = detectRegistry(port);
		if (registry != null)
			return registry;
		// no registry created
		try {
			registry = createRegistry(port);
			System.out.println("Created a new registry on port " + port);
			return registry;
		} catch (java.rmi.RemoteException e) {
			// problem to bind the registry : may be somebody created one in the
			// meantime
			// try to find the rmi registry one more time
			registry = detectRegistry(port);
			if (registry != null)
				return registry;
			System.out
					.println("Cannot detect an existing RMI Registry on port "
							+ port + " nor create one e=" + e);
			throw e;
		}
	}

}

