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

import java.lang.reflect.Constructor;

import org.apache.commons.digester.Digester;
import org.apache.commons.digester.Rule;
import org.apache.commons.digester.RuleSetBase;
import org.huihoo.willow.Container;
import org.huihoo.willow.Loader;
import org.xml.sax.Attributes;

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

	// ----------------------------------------------------- Instance Variables

	/**
	 * The matching pattern prefix to use for recognizing our elements.
	 */
	protected String prefix = null;

	// ------------------------------------------------------------ Constructor

	/**
	 * Construct an instance of this <code>RuleSet</code> with the default
	 * matching pattern prefix.
	 */
	public ContextRuleSet()
	{

		this("");

	}

	/**
	 * Construct an instance of this <code>RuleSet</code> with the specified
	 * matching pattern prefix.
	 *
	 * @param prefix Prefix for matching pattern rules (including the
	 *  trailing slash character)
	 */
	public ContextRuleSet(String prefix)
	{

		super();
		this.namespaceURI = null;
		this.prefix = prefix;

	}

	// --------------------------------------------------------- Public Methods

	/**
	 * <p>Add the set of Rule instances defined in this RuleSet to the
	 * specified <code>Digester</code> instance, associating them with
	 * our namespace URI (if any).  This method should only be called
	 * by a Digester instance.</p>
	 *
	 * @param digester Digester instance to which the new Rule instances
	 *  should be added.
	 */
	public void addRuleInstances(Digester digester)
	{

		digester.addObjectCreate(
				prefix + "Context",
				"org.huihoo.willow.core.StandardContext",
				"className");
		digester.addSetProperties(prefix + "Context");

			digester.addRule(prefix + "Context", new CopyParentClassLoaderRule(digester));
			digester.addRule(
				prefix + "Context",
				new LifecycleListenerRule(
					digester,
					"org.huihoo.willow.startup.ContextConfig",
					"configClass"));
			digester.addRule(prefix + "Context", new SetAppBaseRule(digester));
			digester.addSetNext(prefix + "Context", "addChild", "org.huihoo.willow.Container");



		digester.addObjectCreate(prefix + "Context/Listener", null, // MUST be specified in the element
		"className");
		digester.addSetProperties(prefix + "Context/Listener");
		digester.addSetNext(
			prefix + "Context/Listener",
			"addLifecycleListener",
			"org.huihoo.willow.LifecycleListener");

		digester.addRule(
			prefix + "Context/Loader",
			new CreateLoaderRule(digester, "org.huihoo.willow.loader.WebappLoader", "className"));
		digester.addSetProperties(prefix + "Context/Loader");
		digester.addSetNext(prefix + "Context/Loader", "setLoader", "org.huihoo.willow.Loader");

		digester.addObjectCreate(prefix + "Context/Logger", null, // MUST be specified in the element
		"className");
		digester.addSetProperties(prefix + "Context/Logger");
		digester.addSetNext(prefix + "Context/Logger", "setLogger", "org.huihoo.willow.Logger");

	}

}

// ----------------------------------------------------------- Private Classes

/**
 * Rule that creates a new <code>Loader</code> instance, with the parent
 * class loader associated with the top object on the stack (which must be
 * a <code>Container</code>), and pushes it on to the stack.
 */

final class CreateLoaderRule extends Rule
{

	public CreateLoaderRule(Digester digester, String loaderClass, String attributeName)
	{

		super(digester);
		this.loaderClass = loaderClass;
		this.attributeName = attributeName;

	}

	private String attributeName;

	private String loaderClass;

	public void begin(Attributes attributes) throws Exception
	{

		// Look up the required parent class loader
		ClassLoader parentClassLoader = null;
		Object ojb = digester.peek();
		if (ojb instanceof Container)
		{
			parentClassLoader = ((Container) ojb).getParentClassLoader();
		}

		// Instantiate a new Loader implementation object
		String className = loaderClass;
		if (attributeName != null)
		{
			String value = attributes.getValue(attributeName);
			if (value != null)
				className = value;
		}
		Class clazz = Class.forName(className);
		Class types[] = { ClassLoader.class };
		Object args[] = { parentClassLoader };
		Constructor constructor = clazz.getDeclaredConstructor(types);
		Loader loader = (Loader) constructor.newInstance(args);

		// Push the new loader onto the stack
		digester.push(loader);
		if (digester.getDebug() >= 1)
			digester.log("new " + loader.getClass().getName());

	}

	public void end() throws Exception
	{

		Loader loader = (Loader) digester.pop();
		if (digester.getDebug() >= 1)
			digester.log("pop " + loader.getClass().getName());

	}

}