/*******************************************************************************
 * Copyright (c) 2003, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.ws.internal.axis.consumption.core.command;


import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

import org.apache.axis.AxisEngine;
import org.apache.axis.server.AxisServer;
import org.apache.axis.tools.ant.axis.AdminClientTask;
import org.apache.axis.utils.ClassUtils;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Target;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jst.ws.internal.axis.consumption.core.AxisConsumptionCoreMessages;
import org.eclipse.jst.ws.internal.axis.consumption.core.common.JavaWSDLParameter;
import org.eclipse.jst.ws.internal.common.J2EEUtils;
import org.eclipse.jst.ws.internal.common.ResourceUtils;
import org.eclipse.wst.command.internal.env.core.common.ProgressUtils;
import org.eclipse.wst.command.internal.env.core.common.StatusUtils;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.environment.IEnvironment;
import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelOperation;

/**
 * Commands are executable, undoable, redoable objects. Every Command has a name and a description.
 */

public class GeronimoAxisDeployCommand extends AbstractDataModelOperation
{

  private JavaWSDLParameter javaWSDLParam;

  private String projectName_;
  private static final String AXIS_SERVER_CONFIG_FILE = "axis.ServerConfigFile";
  
  IFolder outputRoot;
  
  /**
   * Constructor for GeronimoAxisDeployCommand.
 * @param String projectName
   * 
   */
  public GeronimoAxisDeployCommand(String projectName)
  {
  }
  
  public IStatus execute( IProgressMonitor monitor, IAdaptable adaptable )
  {
	IEnvironment environment = getEnvironment();
    if (javaWSDLParam == null)
    {
      return StatusUtils.errorStatus(AxisConsumptionCoreMessages.MSG_ERROR_JAVA_WSDL_PARAM_NOT_SET);
    }

    if (javaWSDLParam.getProjectURL() == null || javaWSDLParam.getProjectURL().equals(""))
    { //$NON-NLS-1$
      return StatusUtils.errorStatus(AxisConsumptionCoreMessages.MSG_ERROR_PROJECT_URL_PARAM_NOT_SET);
    }

    if (javaWSDLParam.getDeploymentFiles() == null || javaWSDLParam.getDeploymentFiles().length == 0)
    {
      return StatusUtils.errorStatus(
      AxisConsumptionCoreMessages.MSG_ERROR_DEPLOY_FILE_PARAM_NOT_SET);
    }

    ProgressUtils.report(monitor, AxisConsumptionCoreMessages.MSG_AXIS_DEPLOY);

    IStatus status = executeAdminTask();
    if (status.getSeverity() == Status.ERROR)
    {
        environment.getStatusHandler().reportError(status);
    }    
    
    status = executeAntTask();
    if (status.getSeverity() == Status.ERROR)
    {
        environment.getStatusHandler().reportError(status);
    }    
    return status;
  }
  
  protected IStatus executeAntTask()
  {
    final class DeployTask extends AdminClientTask
    {
      public DeployTask()
      {
        super.setProject(new Project());
		super.getProject().init();
		super.setTaskType("axis"); //$NON-NLS-1$
		super.setTaskName("axis-admin"); //$NON-NLS-1$
		super.setOwningTarget(new Target());
      }
    }

    DeployTask adminClient = new DeployTask();
    String url = javaWSDLParam.getProjectURL() + AxisDeployCommand.SERVICE_EXT;
    adminClient.setUrl(url);
    adminClient.setXmlFile(new File(javaWSDLParam.getDeploymentFiles()[0]));

    // Since the admin server may not be available right away we will try
    // several times to execute it.
    try
    {
      BuildException lastException = null;
      
      for( int index = 0; index < 20; index++ )
      {
        try
        {
          lastException = null;
          adminClient.execute();
        }
        catch( BuildException exc )
        {
          lastException = exc;
          
          try
          {
            Thread.sleep( 200 );
          }
          catch( InterruptedException threadException  )
          {
          }
        }
        
        // If no exception occured then we should break out of the loop.
        if( lastException == null ) break;
      }
      
      // If after many tries we still get an exception, then we will re throw it.
      if( lastException != null ) throw lastException;
    }
    catch (BuildException e)
    {
      e.printStackTrace();
      String message = e.getMessage();
      if (e.getCause() != null)
      {
        message = e.getCause().toString();
      }
      
      IStatus[] childStatus = new Status[1];
      childStatus[0] = StatusUtils.errorStatus( message);
      return StatusUtils.multiStatus(AxisConsumptionCoreMessages.MSG_ERROR_AXIS_DEPLOY, childStatus);
    }
    return Status.OK_STATUS; 

  }
  
  protected IStatus executeAdminTask(){
    
    IStatus status = Status.OK_STATUS;
    // check if server-config.wsdd exists
    IVirtualComponent component = J2EEUtils.getVirtualComponent( projectName_ );
    outputRoot = J2EEUtils.getOutputContainerRoot( component );
    IPath path = new Path( "WEB-INF" ).append( "server-config.wsdd" );    
    IFile descriptorFile = outputRoot.getFile( path );
    
    if (!descriptorFile.exists()){
      status = createServerConfigFile();
      if (status.getSeverity()==Status.ERROR)
        return status;
    }
    
    // check if deploy.wsdd exists
    String deployWSDD = javaWSDLParam.getDeploymentFiles()[0];
    File deployFile = new File(deployWSDD);
    if (deployFile==null || !deployFile.exists()){
      return status;
    }
    
    try {
      // get Classpath
      String jarsCP = new String();
      // classes dir
      IPath classesPath = new Path("WEB-INF").append("classes");
      IFile classesDir = outputRoot.getFile(classesPath);
      jarsCP = "\""+classesDir.getRawLocation().toOSString()+"\"";
      
      // lib JARs
      IPath libPath = new Path("WEB-INF").append("lib");
      IFile libEntry = outputRoot.getFile(libPath);
      IFolder libFolder = (IFolder)ResourceUtils.findResource(libEntry.getFullPath());
      IResource[] JARfiles = libFolder.members();
      for (int i=0;i<JARfiles.length;i++){
        IResource res = JARfiles[i];
        if (res.getFileExtension().equals("jar")){
          jarsCP = jarsCP + ";\""+ res.getRawLocation().toOSString()+"\"";
        }
      }

      // form and run utils.Admin command
      String adminCommand = new String("java -Daxis.ServerConfigFile="+ descriptorFile.getRawLocation().toOSString() 
          +" -cp "+jarsCP+" org.apache.axis.utils.Admin server "+deployFile.getCanonicalPath());
      Runtime.getRuntime().exec(adminCommand);

    }
    catch(Exception e){
      System.setProperty(AXIS_SERVER_CONFIG_FILE,"server-conifg.wsdd");      
      e.printStackTrace();
      String message = e.getMessage();
      if (e.getCause() != null)
      {
        message = e.getCause().toString();
      }
      
      IStatus[] childStatus = new Status[1];
      childStatus[0] = StatusUtils.errorStatus( message);
      return StatusUtils.multiStatus(AxisConsumptionCoreMessages.MSG_ERROR_AXIS_DEPLOY, childStatus);
    }
    
    return status;
  }
  
  /**t
   * Creates the initial server-config.wsdd file from a template in Axis
   * @return
   */
  private IStatus createServerConfigFile(){
    try{

      // server-config.wsdd file
      IPath             path           = new Path( "WEB-INF" ).append( "server-config.wsdd" );    
      IFile             descriptorFile = outputRoot.getFile( path );      

      // create the initial server-config.wsdd file
      AxisEngine preEngine = new AxisServer();
      InputStream is = ClassUtils.getResourceAsStream(preEngine.getClass(), "server-config.wsdd");
      FileOutputStream fos = new FileOutputStream(descriptorFile.getRawLocation().toOSString());
      ResourceUtils.copyStream(is, fos);
      fos.close();
      
      return Status.OK_STATUS;
    }
    catch(Exception e){
      e.printStackTrace();
      String message = e.getMessage();
      if (e.getCause() != null)
      {
        message = e.getCause().toString();
      }

      IStatus[] childStatus = new Status[1];
      childStatus[0] = StatusUtils.errorStatus( message);
      return StatusUtils.multiStatus(AxisConsumptionCoreMessages.MSG_ERROR_AXIS_DEPLOY, childStatus);

    }
  }

  /**
   * @param javaWSDLParam The javaWSDLParam to set.
   */
  public void setJavaWSDLParam(JavaWSDLParameter javaWSDLParam)
  {
    this.javaWSDLParam = javaWSDLParam;
  }

}
