package org.plenix.jsp.language.java;

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

import sun.tools.javac.Main;

import org.plenix.jsp.*;
import org.plenix.jsp.language.*;

public class JavaProcessor extends LanguageProcessorImpl
{
  private static JspClassLoader classLoader;

  public JavaProcessor()
  {
    super();
  }

  // Program instance services
  public void init(String path)
    throws LanguageException
  {
    // Instantiate class loader
    try
    {
      classLoader = new JspClassLoader(new File(ResourceManager.getStageDirectory()));
    }
    catch (JspException e)
    {
      throw new LanguageException(e.getMessage());
    }
  }

  public void compile(String baseName, String path)
    throws LanguageException
  {
    // Invoke sun compiler
    String sourceFileName = path + File.separator + baseName + ".java";

    String[] compilerArgs =
    {
        "-classpath", path + File.pathSeparator + System.getProperty("java.class.path"),
        "-d", path,
        "-deprecation",
        // "-verbose",
        sourceFileName,
    };

    Main compiler = new Main(System.err, "javac");

    if (!compiler.compile(compilerArgs))
    {
      throw new LanguageException("Error compiling '" + sourceFileName + "'");
    }
  }

  public Object load(String baseName, String path)
    throws LanguageException
  {
    // Load servlet
    try
    {
      String className = baseName.replace(File.separatorChar, '.');

      Class servletClass = classLoader.loadClass(className, true);

      if (servletClass == null)
      {
        throw new LanguageException("Unable to load class '" + className + "'");
      }

      HttpServlet servletInstance = (HttpServlet) servletClass.newInstance();

      servletInstance.init (
        new ServletConfig()
	{
          public ServletContext getServletContext()
	  {
            return JspServlet.getServlet().getServletContext();
          }
          public String getInitParameter(String name)
	  {
            return null;
          }
          public Enumeration getInitParameterNames()
	  {
            return (new Vector()).elements();
          }
	}
      );

      return servletInstance;
    }
    catch (Exception e)
    {
      throw new LanguageException(e.getMessage() + "\n" + e.getClass().getName());
    }
  }

  public void unload(Object program)
    throws LanguageException
  {
    // Destroy servlet
    HttpServlet servlet = (HttpServlet) program;

    servlet.destroy();

    try
    {
      classLoader = new JspClassLoader(new File(ResourceManager.getStageDirectory()));
    }
    catch (JspException e)
    {
      throw new LanguageException(e.getMessage());
    }
  }

  public void execute(Object program, HttpServletRequest request, HttpServletResponse response)
    throws LanguageException
  {
    // Call servlet service method
    HttpServlet servlet = (HttpServlet) program;

    try
    {
      servlet.service(request, response);
    }
    catch (IOException e)
    {
      throw new LanguageException("IO error executing servlet: " + e.getMessage());
    }
    catch (ServletException e)
    {
      throw new LanguageException("Servlet error executing servlet: " + e.getMessage());
    }
  }
}
