/*
 * Created on 2004-7-19
 *
 * To change the template for this generated file go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
package org.huihoo.willow.tomcat;

import java.io.File;
import java.lang.reflect.Method;

import org.apache.catalina.security.SecurityClassLoad;
import org.apache.catalina.startup.ClassLoaderFactory;
import org.huihoo.willow.Globals;
import org.huihoo.willow.LifecycleException;
import org.huihoo.willow.Provider;
import org.huihoo.willow.core.ProviderBase;
import org.huihoo.willow.core.StandardServer;

/**
 * @author reic
 *
 * To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
public class TomcatProvider extends ProviderBase implements Provider
{
	private static final String info = "org.huihoo.willow.tomcat.TomcatProvider/1.0";

	/**
	 * Return descriptive information about this NamingProvider implementation.
	 */
	public String getInfo()
	{

		return (info);

	}

	// -------------------------------------------------------------- Variables

	/**
		* Debugging detail level for processing the startup.
		*/
	protected int debug = 0;

	/**
		* Daemon reference.
		*/
	private Object catalinaDaemon = null;

	private ClassLoader commonLoader = null;
	private ClassLoader catalinaLoader = null;
	private ClassLoader sharedLoader = null;

	// -------------------------------------------------------- Private Methods

	private void initClassLoaders()
	{
		try
		{
			ClassLoaderFactory.setDebug(debug);
		  
			ClassLoader willowServerLoader=null;		  
			ClassLoader willowCommonLoader=null;
			ClassLoader willowSharedLoader=null;
			
			willowServerLoader=StandardServer.class.getClassLoader();
			if(willowServerLoader!=null)
			{
				willowCommonLoader=willowServerLoader.getParent();
			}
			willowSharedLoader=container.getParentClassLoader();
			
			commonLoader =willowCommonLoader;						
			sharedLoader = willowSharedLoader;			
			catalinaLoader =willowServerLoader;
												
		}
		catch (Throwable t)
		{
			log("Class loader creation threw exception", t);
			
			t.printStackTrace(System.err);
			System.exit(1);
		}
	}

	/**
		* Initialize daemon.
		*/
	private void init() throws Exception
	{

		initClassLoaders();

		Thread.currentThread().setContextClassLoader(catalinaLoader);
		SecurityClassLoad.securityClassLoad(catalinaLoader);

		// Load our startup class and call its process() method
		if (debug >= 1)
		{
			log("Loading startup class");
		}
		
		Class startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
		
		Object startupInstance = startupClass.newInstance();

		// Set the shared extensions class loader
		if (debug >= 1)
		{
			log("Setting startup class properties");
		}

		String methodName = "setParentClassLoader";
		Class paramTypes[] = new Class[1];
		paramTypes[0] = Class.forName("java.lang.ClassLoader");
		Object paramValues[] = new Object[1];
		paramValues[0] = sharedLoader;
		Method method = startupInstance.getClass().getMethod(methodName, paramTypes);
		method.invoke(startupInstance, paramValues);

		catalinaDaemon = startupInstance;

	}
	
	// ----------------------------------------------------------- Main Program

	public TomcatProvider()
	{

	}
	
	/**
		* Start the Catalina daemon.
		*/
	public void start() throws LifecycleException
	{							
		super.start();
		
		try
		{
			if (catalinaDaemon == null)
			{
				init();
			}

			Method method = null;

			//setAwait(false)
			Class paramTypes[] = new Class[1];
			paramTypes[0] = Boolean.TYPE;
			Object paramValues[] = new Object[1];
			paramValues[0] = new Boolean(false);
			method = catalinaDaemon.getClass().getMethod("setAwait", paramTypes);
			method.invoke(catalinaDaemon, paramValues);		

			
			File configFile =
				new File(
					System.getProperty(Globals.PROPS_WILLOW_HOME),
					"conf" + File.separator + "catalina.xml");
			String configFilePath = configFile.getCanonicalPath();
			paramTypes = new Class[1];
			paramTypes[0] = configFilePath.getClass();
			paramValues = new Object[1];
			paramValues[0] = configFilePath;
			method = catalinaDaemon.getClass().getMethod("setConfigFile", paramTypes);
			method.invoke(catalinaDaemon, paramValues);
						
			method = catalinaDaemon.getClass().getMethod("start", null);
			method.invoke(catalinaDaemon, null);
		}
		catch (Exception e)
		{
			this.log("start web server ",e);
		}	
	}

	/**
		* Stop the Catalina Daemon.
		*/
	public void stop() throws LifecycleException
	{

		try
		{
			Method method = catalinaDaemon.getClass().getMethod("stop", null);
			method.invoke(catalinaDaemon, null);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
		super.stop();
	}
}
