package com.yadda.yadda;


import org.apache.struts.action.Action;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.util.*;

import java.io.InputStream;

import java.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;


/**
 * <p><strong>MultiBundleActionServlet</strong>, has extended <code>ActionServlet</code> 
 * to allow multiple resource bundles to be loaded for the application.
 *
 * <p>The standard version of <code>MultiBundleActionServlet</code> is configured based
 * on the following servlet initialization parameters, which can be specified
 * in the web application deployment descriptor (<code>/WEB-INF/web.xml</code>)
 * for the application.</p>
 * <ul>
 * <li><strong>bundles</strong> - Java class name of a properties file which
 *     contains the identifier and classname for the resource bundles to load. 
 *         for this application. 
 * </li></ul>
 */
public class MultiBundleActionServlet
    extends ActionServlet {

	//Constants used to access mSuite-specific config parameters
	public static String            BUNDLES = "bundles";
	private String                  oldFactory;
	private MessageResourcesFactory factoryObject;

	/**
	 * Initialize all the MessageResources bundles for this application, if any.         
	 * When initialized, load the bundle in the session by bundle name.
	 *
	 * @exception ServletException if we cannot initialize these resources
	 */
	protected void initApplication()
	    throws ServletException {

		super.initApplication();

		String value = getServletConfig().getInitParameter(BUNDLES);

		if (value == null) {
			return;
		}

		if (debug >= 1) {
			log(internal.getMessage("applicationLoading", value));
		}

		Properties bundles = getProperties(value);

		if (bundles != null) {
			Enumeration enum = bundles.propertyNames();

			while (enum.hasMoreElements()) {
				String bundleKey = (String) enum.nextElement();

				try {
					MessageResources mr = getBundle(bundles.getProperty(bundleKey));

					getServletContext().setAttribute(bundleKey,
									 mr);
				} catch (UnavailableException e) {
					log("Error loading: " + bundleKey, e);
				}
			}

			resetFactory();
		} else {
			throw new UnavailableException(internal.getMessage("applicationResources",
				value));
		}
	}

	/**
	 * Load the requested resource bundle.
	 *
	 *
	 * @param bundleName A String naming the bundle to be returned
	 *
	 * @return MessageResources the messageResources bundle for the requested bundleName
	 * @exception UnavailableException if we cannot initialize these resources
	 */
	protected MessageResources getBundle(String bundleName)
	    throws UnavailableException {

		MessageResources newBundle = null;

		try {
			newBundle = getFactoryObject().createResources(bundleName);

			newBundle.setReturnNull(getNullReturn());
		} catch (Throwable e) {
			log(internal.getMessage("applicationResources", bundleName),
			    e);

			throw new UnavailableException(internal.getMessage("applicationResources",
				bundleName));
		}

		return newBundle;
	}

	/**
	 * Load the application value that indicates whether the properties resource should return null when         
	 * a requested resource is not found.
	 *
	 *
	 * @return the requested value.
	 */
	protected boolean getNullReturn() {

		String value = getServletConfig().getInitParameter("null");

		return ((value == null) || (value.equalsIgnoreCase("true"))
			|| (value.equalsIgnoreCase("yes")));
	}

	/**
	 * Load the requested properties resource.
	 *
	 *
	 * @param name
	 *
	 * @return the requested value.
	 */
	protected Properties getProperties(String name) {

		InputStream is = null;
		Properties  props = new Properties();

		// Load the specified property resource
		try {
			is = this.getClass().getClassLoader().getResourceAsStream(name);

			if (is != null) {
				props.load(is);
				is.close();
			}
		} catch (Throwable t) {
			if (is != null) {
				try {
					is.close();
				} catch (Throwable u) {}
			}
		}

		return props;
	}

	/**
	 * Return a MessageResourcesFactory based on the config value
	 *
	 *
	 * @return MessageResourcesFactory a factory for creating MessageResource bundles
	 */
	protected MessageResourcesFactory getFactoryObject() {

		if (factoryObject == null) {
			oldFactory = MessageResourcesFactory.getFactoryClass();

			String factory = getServletConfig().getInitParameter("factory");

			if (factory != null) {
				MessageResourcesFactory.setFactoryClass(factory);
			}

			factoryObject = MessageResourcesFactory.createFactory();
		}

		return factoryObject;
	}

	/**
	 * Reset the MessageResourcesFactory to it's original valaue
	 *
	 */
	protected void resetFactory() {
		MessageResourcesFactory.setFactoryClass(oldFactory);
	}
}

