//----------------------------BEGIN LICENSE----------------------------
/* 
 * Willow : the Open Source WorkFlow Project
 * Distributable under GNU LGPL license by gun.org
 *
 * Copyright (C) 2004-2010 huihoo.org 
 * Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com> 
 * 
 * ====================================================================
 * Project Homepage : http://www.huihoo.org/willow
 * Source Forge     : http://sourceforge.net/projects/huihoo
 * Mailing list     : willow@lists.sourceforge.net 
 */
//----------------------------END  LICENSE----------------------------
package org.huihoo.workflow.desktop.helpers;


import java.util.Hashtable;

import org.huihoo.workflow.WorkflowException;
import org.huihoo.workflow.desktop.NoInitialDeskopException;
import org.huihoo.workflow.desktop.WorkflowDesktop;
import org.huihoo.workflow.desktop.WorkflowDesktopFactory;

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

	NamingManager()
	{
	}

	// should be protected and package private
	static final PropertyUtils helper = PropertyUtils.getUtils();

	//------------ Initial Desktop Factory Stuff
	private static ClassLoader initctx_class_loader = null;

	/**
		* Creates an initial context using the specified environment 
		* properties. 
		*<p>
		* If an LocalClientFactoryBuilder has been installed, 
		* it is used to create the factory for creating the initial context.
		* Otherwise, the class specified in the 
		* <tt>Desktop.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 ClientNotFoundException If the
		*		<tt>Desktop.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 , WorkflowNamingException If some other naming exception was encountered.
		*/
	public static WorkflowDesktop getInitialDesktop(Hashtable env) throws WorkflowException
	{
		WorkflowDesktopFactory factory;

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

		try
		{
			factory = (WorkflowDesktopFactory) getInitialClassLoader().loadClass(className).newInstance();
		}
		catch (Exception e)
		{
			NoInitialDeskopException ne = new NoInitialDeskopException("Cannot instantiate class: " + className);
			ne.initCause(e);
			throw ne;
		}

		return factory.getInitialDesktop(env);
	}


	/**
		* Sets the InitialClassLoader 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 loader The InitialClassLoader to install. If null,
		*                no loader is set.
		* @exception IllegalStateException If a loader was previous installed.
		*/
	public static synchronized void setInitialClassLoader(ClassLoader loader)
	{
		if (initctx_class_loader != null)
		{
			throw new IllegalStateException("InitialClassLoader already set");
		}

		initctx_class_loader = loader;
	}

	/**
		* Determines whether an InitialClassLoader has
		* been set.
		* @return true ifInitialClassLoader has
		*		 been set; false otherwise.
		*/
	public static boolean hasInitialClassLoader()
	{
		return (getInitialClassLoader() != null);
	}


	/**
		* Use this method for accessing initctx_class_loader while
		* inside an unsynchronized method.
		*/
	private static synchronized ClassLoader getInitialClassLoader()
	{
		if (initctx_class_loader != null)
		{
			return initctx_class_loader;
		}
		
		return Thread.currentThread().getContextClassLoader();
	}

}