/*
 * Created on 2004-9-5
 *
 * To change the template for this generated file go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
package workflow.client.factory;

import java.util.Hashtable;

import javax.naming.NamingException;

import workflow.WorkflowException;
import workflow.client.NoWorkflowClientException;
import workflow.client.WorkflowClient;

/**
 * @author reic
 *
 * To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
public class WorkflowNamingManager
{

	/*
	 * Disallow anyone from creating one of these.
	 * Made package private so that DirectoryManager can subclass.
	 */

	WorkflowNamingManager()
	{
	}

	// should be protected and package private
	static final VersionHelper helper = VersionHelper.getVersionHelper();

	//------------ Initial LiveClient Factory Stuff
	private static WorkflowClientFactoryBuilder initctx_factory_builder = null;

	/**
		* Use this method for accessing initctx_factory_builder while
		* inside an unsynchronized method.
		*/
	private static synchronized WorkflowClientFactoryBuilder getInitialLocalClientFactoryBuilder()
	{
		return initctx_factory_builder;
	}

	/**
		* Creates an initial context using the specified environment 
		* properties. 
		*<p>
		* If an WorkflowClientFactoryBuilder has been installed, 
		* it is used to create the factory for creating the initial context.
		* Otherwise, the class specified in the 
		* <tt>LiveClient.INITIAL_CONTEXT_FACTORY</tt> environment property is used.
		* Note that an initial wfiClient factory (an object that implements the 
		* LiveClientFactory interface) must be public and must have a 
		* public constructor that accepts no arguments.
		*
		* @param env The possibly null environment properties used when 
		* 			creating the context.
		* @return A non-null initial context.
		* @exception NoWorkflowClientException If the
		*		<tt>LiveClient.INITIAL_CONTEXT_FACTORY</tt> property
		*         is not found or names a nonexistent
		*         class or a class that cannot be instantiated,
		*		or if the initial context could not be created for some other
		*		reason.
		* @exception NamingException If some other naming exception was encountered.
		* @see javax.naming.InitialLiveClient
		* @see javax.naming.directory.InitialDirWorkflowClient
		*/
	public static WorkflowClient getInitialLocalClient(Hashtable env)
		throws WorkflowException, NamingException
	{
		WorkflowClientFactory factory;

		WorkflowClientFactoryBuilder builder = getInitialLocalClientFactoryBuilder();
		if (builder == null)
		{
			// No factory installed, use property
			// Get initial wfiClient factory class name

			String className =
				env != null ? (String) env.get(WorkflowClient.INITIAL_CLIENT_FACTORY) : null;
			if (className == null)
			{
				NoWorkflowClientException ne =
					new NoWorkflowClientException(
						"Need to specify class name in environment or system "
							+ "property, or as an applet parameter, or in an "
							+ "application resource file:  "
							+ WorkflowClient.INITIAL_CLIENT_FACTORY);
				throw ne;
			}

			try
			{
				factory = (WorkflowClientFactory) helper.loadClass(className).newInstance();
			}
			catch (Exception e)
			{
				NoWorkflowClientException ne =
					new NoWorkflowClientException("Cannot instantiate class: " + className);
				ne.initCause(e);
				throw ne;
			}
		}
		else
		{
			factory = builder.createInitialLocalClientFactory(env);
		}

		return factory.getInitialLocalClient(env);
	}

	/**
		* Sets the LiveClientFactory builder to be builder.
		*
		*<p>
		* The builder can only be installed if the executing thread is allowed by
		* the security manager to do so. Once installed, the builder cannot 
		* be replaced.
		* @param builder The initial wfiClient factory builder to install. If null,
		*                no builder is set.
		* @exception SecurityException builder cannot be installed for security
		*			reasons.
		* @exception NamingException builder cannot be installed for
		*         a non-security-related reason.
		* @exception IllegalStateException If a builder was previous installed.
		* @see #hasInitialWorkflowClientFactoryBuilder
		* @see java.lang.SecurityManager#checkSetFactory
		*/
	public static synchronized void setInitialLocalClientFactoryBuilder(WorkflowClientFactoryBuilder builder)
		throws NamingException
	{
		if (initctx_factory_builder != null)
		{
			throw new IllegalStateException("WorkflowClientFactoryBuilder already set");
		}

		SecurityManager security = System.getSecurityManager();
		if (security != null)
		{
			security.checkSetFactory();
		}
		initctx_factory_builder = builder;
	}

	/**
		* Determines whether an initial wfiClient factory builder has
		* been set.
		* @return true if an initial wfiClient factory builder has
		*		 been set; false otherwise.
		* @see #setInitialWorkflowClientFactoryBuilder
		*/
	public static boolean hasInitialLocalClientFactoryBuilder()
	{
		return (getInitialLocalClientFactoryBuilder() != null);
	}
}