//----------------------------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.willow.deploy;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.Set;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.huihoo.willow.Context;
import org.huihoo.willow.ContextDeployer;
import org.huihoo.willow.LifecycleException;
import org.huihoo.willow.Logger;
import org.huihoo.willow.core.StandardService;
import org.huihoo.willow.realm.UserDatabaseRealm;
import org.huihoo.willow.startup.Embedded;
import org.huihoo.workflow.WorkflowException;

/*  

	<context-param>    
		<param-name>WILLOW_PLUGIN</param-name>
		<param-value>plugin.xml</param-value>
	</context-param> 	
	<context-param>    
		<param-name>WILLOW_WORKDIR</param-name>
		<param-value>/temp</param-value>
	</context-param> 				   
	<servlet>
		<servlet-name>WillowServlet</servlet-name>
		<servlet-class>org.huihoo.willow.deploy.WillowServlet</servlet-class>
		<init-param>
			<param-name>WILLOW_PLUGIN</param-name>
			<param-value>plugin.xml</param-value>
		</init-param>
		<init-param>
			<param-name>WILLOW_WORKDIR</param-name>
			<param-value>/temp</param-value>
		</init-param>		
		<load-on-startup>1</load-on-startup>
	</servlet>

	The servlet init-parameter values will override those of the
	context-parameters.
*/

public class WillowServlet extends HttpServlet
{
	private Embedded embedded;

	public void init() throws ServletException
	{
		ClassLoader servletClassLoader = Thread.currentThread().getContextClassLoader();

		try
		{
			/**
			 * Make sure that we got a useful classloader; if we can not
			 * even load ourselves, then at least use the classloader that
			 * loaded us.
			 **/
			servletClassLoader.loadClass(this.getClass().getName());
		}
		catch (ClassNotFoundException e)
		{
			servletClassLoader = getClass().getClassLoader();
		}

		if (servletClassLoader == null)
		{
			/**
			 * This is needed because some containers use hashtable to store
			 * servlet attributes and therefore they can't be null.
			 * If Class.forName is passed in null as the classloader, then it
			 * seems to default to the system class loader, so this should be ok.
			 */
			servletClassLoader = ClassLoader.getSystemClassLoader();
		}

		ServletConfig servletConfig = this.getServletConfig();
		ServletContext servletContext = servletConfig.getServletContext();

		//----------------------------------------------------------------
		//  WILLOW_PLUGIN Property Setting (mandatory)
		//----------------------------------------------------------------
		URL pluginURL = null;
		String pluginPath = servletConfig.getInitParameter(Constants.WILLOW_PLUGIN);
		if (pluginPath == null)
		{
			pluginPath = servletContext.getInitParameter(Constants.WILLOW_PLUGIN);
		}

		if (pluginPath != null)
		{
			try
			{
				if (pluginPath.startsWith("/WEB-INF/"))
				{
					pluginURL = servletContext.getResource(pluginPath);
				}
				else
				{
					File pluginFile = new File(pluginPath);

					if (!pluginFile.isAbsolute())
					{
						pluginURL = servletContext.getResource("/WEB-INF/" + pluginPath);

					}
					else if (pluginFile.exists())
					{
						pluginURL = new URL("file", null,pluginFile.getCanonicalPath());
					}
				}

			}
			catch (Throwable t)
			{
				pluginURL = null;
			}

		}

		if (pluginURL == null)
		{
			try
			{
				pluginURL = servletContext.getResource(Constants.DEFAULT_WILLOW_PLUGIN);
			}
			catch (Throwable t)
			{
				pluginURL = null;
			}
		}

		if (pluginURL == null)
		{
			new ServletException("WILLOW_STORE property must be set");
		}

		InputStream istream = null;

		try
		{
			istream = pluginURL.openStream();
			PluginRepository.loadOnStartup(istream);
		}
		catch (IOException e1)
		{
			try
			{
				if (istream != null)
				{
					istream.close();
				}
			}
			catch (IOException e)
			{

			}

			new ServletException(e1);
		}

		servletContext.log("WILLOW_PLUGIN = [" + pluginURL + "]");

		//----------------------------------------------------------------
		//  WILLOW_WORK Property Setting (mandatory)
		//----------------------------------------------------------------
		String workDir = servletConfig.getInitParameter(Constants.WILLOW_WORKDIR);
		if (workDir == null)
		{
			workDir = servletContext.getInitParameter(Constants.WILLOW_WORKDIR);
		}

		if (workDir == null)
		{
			//Only for Apache/Tomcat. see org\apache\catalina\Globals.java
			File fworkDir = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
			if (fworkDir != null)
			{
				workDir = fworkDir.getAbsolutePath();
			}
		}

		if (workDir == null)
		{
			workDir = System.getProperty("java.io.tmpdir");
		}

		servletContext.log("WILLOW_WORKDIR = [" + workDir + "]");

		//----------------------------------------------------------------
		//  Startup workflow engine
		//----------------------------------------------------------------
		Logger logger = new ServletContextLogger(servletContext);
		Embedded embedded = new Embedded(logger);

		//engine.setName(contextFile.getName());
		embedded.setName("Embedded");
		embedded.setAutoDeploy(false);
		embedded.setParentClassLoader(servletClassLoader);

		if (embedded instanceof StandardService)
		{
			StandardService s_embedded = (StandardService) embedded;
			s_embedded.setWorkDir(workDir);
		}

		UserDatabaseRealm userRealm = new UserDatabaseRealm();
		embedded.setRealmDatabase(userRealm);

		Context context = null;
		boolean fileSystemBased = false;
		String contextPath = servletContext.getRealPath("/");
		if (contextPath != null)
		{
			fileSystemBased = true;
			File contextFile = new File(contextPath);
			context = embedded.createContext(contextFile.getName(), contextFile.getAbsolutePath());
		}
		else
		{
			context = embedded.createContext("Embedded", "");
		}

		context.setAutoDeploy(false);
		context.setReloadable(false);
		embedded.addChild(context);

		try
		{
			embedded.start();
		}
		catch (LifecycleException ex)
		{
			throw new ServletException(ex);
		}

		if (!fileSystemBased && (context instanceof ContextDeployer))
		{
			ContextDeployer contextDeploy = (ContextDeployer) context;
			Set xpSet = servletContext.getResourcePaths("/WEB-INF/xpdl");
			Iterator iterator = xpSet.iterator();

			URL xpURL = null;
			String xp_path = null;
			String xp_temp = null;
			while (iterator.hasNext())
			{
				xp_path = (String) iterator.next();
				try
				{
					xpURL = servletContext.getResource(xp_path);
					xp_path = xpURL.toString();
					int slash1 = xp_path.lastIndexOf("/");
					if (slash1 == -1 || !xp_path.endsWith(".xpdl"))
					{
						servletContext.log("Can't deploy XPDL " + xp_path);
					}
					else
					{
						try
						{
							contextDeploy.install(xp_path.substring(slash1 + 1), xpURL);
						}
						catch (WorkflowException e3)
						{
							servletContext.log("Can't deploy XPDL " + xp_path, e3);
						}
					}

				}
				catch (MalformedURLException e2)
				{
					servletContext.log("Can't deploy XPDL " + xp_path, e2);
				}
			}
		}
	}

	public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
	{
		res.setContentType("text/html");

		PrintWriter out = res.getWriter();

		out.println("<html><head><title>Huihoo Willow  Initializer</title></head>");
		out.println("<body><h1>Huihoo Willow  Initializer</h1>");
		out.println("<p>Sorry, I don't speak via HTTP GET/POST </p>");
		out.println("</body></html>");
	}

	public void destroy()
	{
		if (embedded != null)
		{
			try
			{
				embedded.stop();
			}
			catch (LifecycleException e)
			{
				;
			}
		}
	}
}
