/* 
 * ========================================================================
 * 
 * Copyright 2003 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * ========================================================================
 */
package org.apache.cactus.integration.ant.container.weblogic;

import java.io.File;
import java.io.IOException;

import org.apache.cactus.integration.ant.container.AbstractJavaContainer;
import org.apache.cactus.integration.ant.util.ResourceUtils;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.Jar;
import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.types.FilterChain;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.ZipFileSet;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.types.Environment.Variable;

/**
 * Special container support for the Bea WebLogic 8.1 application server.
 * 
 * @version $$
 */
public class WebLogic81Container extends AbstractJavaContainer
{
	private final String TEMP_DOMAIN_DIRNAME = "testDomain";

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

	/**
	 * The Bea home directory.
	 */
	private File beaHome;

	/**
	 * The WebLogic 8.1 installation directory. For example:
	 * "c:\bea\weblogic814".
	 */
	private File dir;

	/**
	 * The port to which the container should be bound.
	 */
	private int port = 7001;

	/**
	 * A user-specific <code>config.xml</code> WebLogic configuration file. If
	 * this variable is not set, the file in the domain will be used.
	 */
	private File configXml = null;

	/**
	 * The temporary directory from which the container will be started.
	 */
	private File tmpDir;

	/**
	 * The admin username for the WebLogic domain.
	 */
	private String username = "weblogic";

	/**
	 * The admin password for the WebLogic domain.
	 */
	private String password = "password";

	/**
	 * The WLS server name that is being run, defaults to 'myserver'.
	 */
	private String servername = "myserver";

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

	/**
	 * Sets the Bea home directory.
	 * 
	 * @param theBeaHome
	 *            The BEA home directory
	 */
	public final void setBeaHome(File theBeaHome)
	{
		this.beaHome = theBeaHome;
	}

	/**
	 * Sets the WebLogic 8.1 installation directory.
	 * 
	 * @param theDir
	 *            The directory to set
	 */
	public final void setDir(File theDir)
	{
		this.dir = theDir;
	}

	/**
	 * Sets the port to which the container should listen.
	 * 
	 * @param thePort
	 *            The port to set
	 */
	public final void setPort(int thePort)
	{
		this.port = thePort;
	}

	/**
	 * Sets the configuration file to use for the test installation of WebLogic.
	 * 
	 * @param theConfigXml
	 *            The custom <code>config.xml</code> file
	 */
	public final void setConfigXml(File theConfigXml)
	{
		this.configXml = theConfigXml;
	}

	/**
	 * Sets the temporary installation directory.
	 * 
	 * @param theTmpDir
	 *            The temporary directory to set
	 */
	public final void setTmpDir(File theTmpDir)
	{
		this.tmpDir = theTmpDir;
	}

	// AbstractContainer Implementation ----------------------------------------

	/**
	 * @see org.apache.cactus.integration.ant.container.Container#getName
	 */
	public final String getName()
	{
		return "WebLogic 8.1";
	}

	/**
	 * Returns the port to which the container should listen.
	 * 
	 * @return The port
	 */
	public final int getPort()
	{
		return this.port;
	}


	/**
	 * Sets the WebLogic server name.
	 * 
	 * @param theServername
	 *            The servername to set
	 */
	public final void setServername(String theServername)
	{
		this.servername = theServername;
	}

	/**
	 * @see org.apache.cactus.integration.ant.container.Container#init
	 */
	public final void init()
	{
		if (!this.dir.isDirectory())
			throw new BuildException(this.dir + " is not a directory");

		// If the beaHome attribute is not set, guess the bea home
		// directory using the parent directory of this.dir
		if (this.beaHome == null)
		{
			getLog().debug("Extrapolating beaHome to be ["
					+ this.dir.getParentFile() + "]");
			this.beaHome = this.dir.getParentFile();
		}
	}

	/**
	 * @see org.apache.cactus.integration.ant.container.Container#startUp
	 */
	public final void startUp()
	{
		try
		{
			prepare("cactus/weblogic81");

			Java java = createJavaForStartUp();
			java.setDir(new File(this.tmpDir, this.TEMP_DOMAIN_DIRNAME));

			java.createJvmarg().setValue("-hotspot");
			java.createJvmarg().setValue("-Xms32m");
			java.createJvmarg().setValue("-Xmx200m");
			java.createJvmarg().setValue("-Xverify:none");

			File serverDir = new File(this.dir, "server");

			java.addSysproperty(createSysProperty("weblogic.Name",
					this.servername));
			java.addSysproperty(createSysProperty("bea.home", this.beaHome));
			java.addSysproperty(createSysProperty("weblogic.management.username",
							this.username));
			java.addSysproperty(createSysProperty("weblogic.management.password",
							this.password));
			java.addSysproperty(createSysProperty("java.security.policy",
					"./server/lib/weblogic.policy"));

			if (null != getSystemProperties())
			{
				Variable[] vars = getSystemProperties();
				for (int i = 0; i < vars.length; i++)
				{
					Variable v = vars[i];
					java.addSysproperty(createSysProperty(v.getKey(), v
							.getValue()));
				}
			}

			Path classpath = java.createClasspath();
			classpath.createPathElement().setLocation(new File(serverDir,
					"lib/weblogic_sp.jar"));
			classpath.createPathElement().setLocation(new File(serverDir,
					"lib/weblogic.jar"));
			classpath.createPathElement().setLocation(new File(serverDir,
					"lib/webservices.jar"));

			java.setClassname("weblogic.Server");
			java.execute();
		}
		catch (IOException ioe)
		{
			getLog().error("Failed to startup the container", ioe);
			throw new BuildException(ioe);
		}
	}

	/**
	 * @see org.apache.cactus.integration.ant.container.Container#shutDown
	 */
	public final void shutDown()
	{
		Java java = createJavaForShutDown();

		File serverDir = new File(this.dir, "server");

		Path classpath = java.createClasspath();
		classpath.createPathElement().setLocation(new File(serverDir,
				"lib/weblogic_sp.jar"));
		classpath.createPathElement().setLocation(new File(serverDir,
				"lib/weblogic.jar"));
		classpath.createPathElement().setLocation(new File(serverDir,
				"lib/webservices.jar"));

		java.setClassname("weblogic.Admin");
		java.createArg().setValue("-url");
		java.createArg().setValue("t3://" + this.getServer() + ":" + getPort());
		java.createArg().setValue("-username");
		java.createArg().setValue(this.username);
		java.createArg().setValue("-password");
		java.createArg().setValue(this.password);

		// Forcing WebLogic shutdown to speed up the shutdown process
		java.createArg().setValue("FORCESHUTDOWN");

		java.execute();
	}

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

	/**
	 * Prepares a temporary installation of the container and deploys the
	 * web-application.
	 * 
	 * @param theDirName
	 *            The name of the temporary container installation directory
	 * @throws IOException
	 *             If an I/O error occurs
	 */
	private void prepare(String theDirName) throws IOException
	{
		FileUtils fileUtils = FileUtils.newFileUtils();
		FilterChain filterChain = createFilterChain();

		this.tmpDir = setupTempDirectory(this.tmpDir, theDirName);
		cleanTempDirectory(this.tmpDir);

		File testDomainDir = createDirectory(this.tmpDir,
				this.TEMP_DOMAIN_DIRNAME);

		if (this.configXml != null)
		{
			fileUtils.copyFile(this.configXml, new File(testDomainDir,
					"config.xml"));
		}
		else
		{
			ResourceUtils.copyResource(getProject(), RESOURCE_PATH
					+ "weblogic81/config.xml", new File(testDomainDir,
					"config.xml"), filterChain);
		}
		ResourceUtils.copyResource(getProject(), RESOURCE_PATH
				+ "weblogic81/SerializedSystemIni.dat", new File(testDomainDir,
				"SerializedSystemIni.dat"));

		ResourceUtils.copyResource(getProject(),
				RESOURCE_PATH + "weblogic81/DefaultAuthenticatorInit.ldift",
				new File(testDomainDir, "DefaultAuthenticatorInit.ldift"));

		// deploy the web-app by copying the WAR file into the applications
		// directory, adding the weblogic.xml descriptor in WEB-INF
		File applicationsDir = createDirectory(testDomainDir, "applications");
		Jar jar = (Jar) createAntTask("jar");
		jar.setDestFile(new File(applicationsDir, getDeployableFile().getFile()
				.getName()));
		ZipFileSet zip = new ZipFileSet();
		zip.setSrc(getDeployableFile().getFile());
		jar.addZipfileset(zip);
		jar.execute();
	}
}
