/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 *
 */
package org.jboss.test.deployment;

// $Id: DeploymentTestCase.java,v 1.1.2.1 2005/04/08 18:56:57 tdiesler Exp $

import org.jboss.deployment.spi.DeploymentManagerImpl;
import org.jboss.deployment.spi.DeploymentMetaData;
import org.jboss.deployment.spi.JarUtils;
import org.jboss.test.JBossTestCase;

import javax.enterprise.deploy.shared.StateType;
import javax.enterprise.deploy.shared.factories.DeploymentFactoryManager;
import javax.enterprise.deploy.spi.DeploymentManager;
import javax.enterprise.deploy.spi.Target;
import javax.enterprise.deploy.spi.factories.DeploymentFactory;
import javax.enterprise.deploy.spi.status.DeploymentStatus;
import javax.enterprise.deploy.spi.status.ProgressObject;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URL;
import java.util.jar.JarOutputStream;

/** 
 * Deployment API JSR-88 tests
 *
 * @author Thomas.Diesler@jboss.org
 * @since 25-Mar-2005
 */
public class DeploymentTestCase extends JBossTestCase
{
   private DeploymentFactory factory;

   public DeploymentTestCase(String name)
   {
      super(name);
   }

   /** Get the DeploymentManager
    */
   protected void setUp() throws Exception
   {
      super.setUp();
      DeploymentFactoryManager dfManager = DeploymentFactoryManager.getInstance();
      DeploymentFactory[] factories = dfManager.getDeploymentFactories();
      factory = factories[0];
   }

   /** Check DeploymentManager
    */
   public void testDeploymentManager() throws Exception
   {
      DeploymentManager manager = factory.getDeploymentManager(DeploymentManagerImpl.DEPLOYER_SCHEME, null, null);
      assertNotNull("No deployment manager", manager);

      Target target = manager.getTargets()[0];
      assertEquals("JBoss JMX deployment target", target.getDescription());
      assertTrue("Unexpected target name: " + target.getName(), target.getName().startsWith("jboss-deployer://"));
      assertTrue("Unexpected target name: " + target.getName(), target.getName().endsWith("/jmx/invoker/RMIAdaptor"));

      String uri = DeploymentManagerImpl.DEPLOYER_SCHEME + "://somehost/SomeAdaptor";
      manager = factory.getDeploymentManager(uri, null, null);
      assertNotNull("No deployment manager", manager);

      target = manager.getTargets()[0];
      assertEquals("JBoss JMX deployment target", target.getDescription());
      assertEquals(uri.toString(), target.getName());
   }

   /** Distribute a web app
    */
   public void testDistributeWebApp() throws Exception
   {
      // Get the deployment manager and the distribution targets
      DeploymentManager manager = factory.getDeploymentManager(DeploymentManagerImpl.DEPLOYER_SCHEME, null, null);
      Target[] targets = manager.getTargets();
      assertEquals(1, targets.length);

      // Create temp file for deployment plan
      File deploymentPlan = File.createTempFile("deploymentplan", ".zip");
      deploymentPlan.deleteOnExit();

      File jbossweb = new File(new URI(getDeployURL("../resources/deployment/WEB-INF/jboss-web.xml")));
      assertTrue(jbossweb.exists());

      JarOutputStream jos = new JarOutputStream(new FileOutputStream(deploymentPlan));
      JarUtils.addJarEntry(jos, "!/WEB-INF/jboss-web.xml", new FileInputStream(jbossweb));

      // Setup deployment plan meta data with propriatary descriptor (jboss-web.xml)
      DeploymentMetaData metaData = new DeploymentMetaData("deployment-web.war");
      metaData.addEntry("deployment-web.war", "jboss-web.xml");

      // Add the meta data to the deployment plan
      String metaStr = metaData.toXMLString();
      JarUtils.addJarEntry(jos, DeploymentMetaData.ENTRY_NAME, new ByteArrayInputStream(metaStr.getBytes()));
      jos.flush();
      jos.close();

      // Get a pointer to the plain web archive
      File moduleArchive = new File(new URI(getDeployURL("deployment-web.war")));
      assertTrue(moduleArchive.exists());

      // Deploy the test war
      ProgressObject progress = manager.distribute(targets, moduleArchive, deploymentPlan);
      DeploymentStatus status = progress.getDeploymentStatus();
      waitForCompletion(status);

      assertEquals(status.getMessage(), StateType.COMPLETED, status.getState());
      assertServletAccess("custom-context");

      // Undeploy the test war
      progress = manager.undeploy(progress.getResultTargetModuleIDs());
      status = progress.getDeploymentStatus();
      waitForCompletion(status);

      // Check the webapp is undeployed
      assertEquals(status.getMessage(), StateType.COMPLETED, status.getState());
      try
      {
         assertServletAccess("custom-context");
         fail("Test deployment not undeployed");
      }
      catch (IOException e)
      {
         // ignore
      }
   }

   private void waitForCompletion(DeploymentStatus status) throws InterruptedException
   {
      // wait for the deployment to finish
      while (StateType.RUNNING == status.getState())
         Thread.sleep(100);
   }

   private void assertServletAccess(String context) throws IOException
   {
      // Check that we can access the servlet
      URL servletURL = new URL("http://" + getServerHost() + ":8080/" + context);
      BufferedReader br = new BufferedReader(new InputStreamReader(servletURL.openStream()));
      String message = br.readLine();
      assertEquals("Hello World!", message);
   }
}