/*
 * Copyright (C) 2006 Helge Hess
 * 
 * This file is part of SOPE/J.
 * 
 * SOPE/J is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2, or (at your option) any later version.
 * 
 * SOPE/J is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with SOPE/J; see the file COPYING. If not, write to the Free Software
 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

package org.opengroupware.jope.jetty;

import java.io.File;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mortbay.http.HttpContext;
import org.mortbay.http.HttpServer;
import org.mortbay.http.SocketListener;
import org.mortbay.http.handler.ResourceHandler;
import org.mortbay.jetty.servlet.ServletHandler;

public class WOJettyRunner extends Object {

  protected final Log log = LogFactory.getLog("WOJettyRunner");
  HttpServer server;

  /* initialization */

  public WOJettyRunner(Class _appCls) {
    //this.logSystemProperties();
    
    // TODO: for unknown reasons this does not return arguments set with
    //       -DWOPort=1234
    String ps = System.getProperty("WOPort");
    if (ps == null || ps.length() == 0)
      ps = "8181";
    
    this.initWithNameAndPort(_appCls.getName(), Integer.parseInt(ps));
  }
  
  public WOJettyRunner(Class _appCls, String[] _args) {
    String appName = null;
    int port = 8181;
    
    for (String arg: _args) {
      if (arg.startsWith("-DWOPort="))
        port = Integer.parseInt(arg.substring(9));
      else if (arg.startsWith("-DWOAppName="))
        appName = arg.substring(9);
    }
    
    if (appName == null)
      appName = _appCls.getName();
    
    this.initWithNameAndPort(appName, port);
  }
  
  public WOJettyRunner(int _port, String _appName) {
    this.initWithNameAndPort(_appName, _port);
  }
  public WOJettyRunner(int _port, Class _appCls) {
    this.initWithNameAndPort(_appCls.getName(), _port);
  }
  
  public void initWithNameAndPort(String _appName, int _port) {
    this.log.debug("setting up Jetty ...");
    this.server = new HttpServer();

    /* port listener */

    SocketListener listener = new SocketListener();
    listener.setPort(_port);
    this.server.addListener(listener);
    this.log.info("application started on HTTP port: " + _port);
    
    /* create a context */

    HttpContext context = new HttpContext();
    context.setContextPath("/");
    this.server.addContext(context);

    /* create a Servlet container (aka a Servlet "context"?) */

    ServletHandler servlets = new ServletHandler();
    context.addHandler(servlets);
    
    /* setup context parameters */
    
    // TODO: this is done differently with Tomcat, possibly we need to set the
    //       value using a different method (init parameters)
    servlets.getServletContext().setAttribute("WOAppName", _appName);
    this.log.debug("  set appname in context: " + _appName);
    
    /* add a Servlet to the container */

    servlets.addServlet(
        "Dump"      /* Servlet Name */,
        "/Dump/*"   /* Path Spec */, 
        "org.mortbay.servlet.Dump" /* class */);
    
    // TODO: fix appname
    String shortAppName = _appName;
    int    idx          = _appName.lastIndexOf('.');
    if (idx != -1) shortAppName = _appName.substring(idx + 1);
    
    servlets.addServlet(
        "WOApp"                   /* Servlet Name */,
        "/" + shortAppName + "/*" /* Path Spec */,
        "org.opengroupware.jope.servlets.WOServletAdaptor");
    this.log.info("mapped application to URL: /" + shortAppName);
    
    // TODO: would be cool to initialize the app ASAP
    
    /* add resource handler */
    
    File home = new File(System.getProperty("user.dir") + "/www");
    if (home.exists()) {    
      context.setResourceBase(home.getAbsolutePath());
      context.addHandler(new ResourceHandler());
    }
    
    /* done */
    
    this.log.debug("finished setting up Servlets.");
  }
  
  public void logSystemProperties() {
    Properties props = System.getProperties();
    for (Object k: props.keySet()) {
      System.err.println(k + ": " + props.getProperty((String)k));
    }
  }

  /* runner */

  public void run() {
    try {
      this.log.debug("starting Jetty ...");
      this.server.start();
      this.log.debug("Jetty is running ...");
      
      /* execution continues in a Jetty thread ...*/
    }
    catch (Exception e) {
      this.log.error("Uncaught exception at top level", e);
    }
  }

  /* main entry point */

  public static void main(String[] args) {
    WOJettyRunner runner;

    runner = new WOJettyRunner(8181, "Application");
    runner.run();
  }
}
