/*
 * 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.jetty.Server;
import org.mortbay.jetty.handler.ResourceHandler;
import org.mortbay.jetty.servlet.Context;

/*
 * WOJettyRunner
 * 
 * Configures and starts a Jetty HTTP server for Servlet execution.
 */
public class WOJettyRunner extends Object {

  protected final Log log = LogFactory.getLog("WOJettyRunner");
  Server 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 Server(_port);
    this.log.info("application started on HTTP port: " + _port);
    
    /* create a context */

    Context root = new Context(this.server, "/",
        Context.NO_SESSIONS | Context.NO_SECURITY);

    // TODO: this is done differently with Tomcat, possibly we need to set the
    //       value using a different method (init parameters)
    root.setAttribute("WOAppName", _appName);
    this.log.debug("  set appname in context: " + _appName);
    
    /* add a Servlet to the container */
    
    root.addServlet("org.mortbay.servlet.Dump", "/Dump/*");
    
    // TODO: fix appname
    String shortAppName = _appName;
    int    idx          = _appName.lastIndexOf('.');
    if (idx != -1) shortAppName = _appName.substring(idx + 1);

    root.addServlet("org.opengroupware.jope.servlets.WOServletAdaptor",
                    "/" + shortAppName + "/*" /* Path Spec */);
    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()) {
      ResourceHandler rh = new ResourceHandler();
      rh.setResourceBase(home.getAbsolutePath());
      this.server.addHandler(rh);
    }
    
    /* 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();
  }
}
