package org.kevoree.library.javase.webserver.gitblit; /** * Created by IntelliJ IDEA. * User: duke * Date: 15/03/12 * Time: 17:23 * To change this template use File | Settings | File Templates. */ /* * Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net> * Distributed under the terms of either: * - the common development and distribution license (CDDL), v1.0; or * - the GNU Lesser General Public License, v2.1 or later */ import winstone.*; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.io.ObjectInputStream; import java.io.OutputStream; import java.lang.reflect.Constructor; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Implements the main launcher daemon thread. This is the class that gets * launched by the command line, and owns the server socket, etc. * * @author <a href="mailto:rick_knowles@hotmail.com">Rick Knowles</a> * @version $Id: Launcher.java,v 1.29 2007/04/23 02:55:35 rickknowles Exp $ */ public class KevLauncher implements Runnable { static final String HTTP_LISTENER_CLASS = "winstone.HttpListener"; static final String HTTPS_LISTENER_CLASS = "winstone.ssl.HttpsListener"; static final String AJP_LISTENER_CLASS = "winstone.ajp13.Ajp13Listener"; public static final byte SHUTDOWN_TYPE = (byte) '0'; public static final byte RELOAD_TYPE = (byte) '4'; private int CONTROL_TIMEOUT = 2000; // wait 2s for control connection private Thread controlThread; public final static WinstoneResourceBundle RESOURCES = new WinstoneResourceBundle("winstone.LocalStrings"); private int controlPort; private HostGroup hostGroup; private ObjectPool objectPool; private final List listeners = new ArrayList(); private Map args; private Cluster cluster; private JNDIManager globalJndiManager; /** * Constructor - initialises the web app, object pools, control port and the * available protocol listeners. */ public KevLauncher(Map args) throws IOException { boolean success=false; try { boolean useJNDI = false; // Set jndi resource handler if not set (workaround for JamVM bug) if (useJNDI) try { Class ctxFactoryClass = Class.forName("winstone.jndi.java.javaURLContextFactory"); if (System.getProperty("java.naming.factory.initial") == null) { System.setProperty("java.naming.factory.initial", ctxFactoryClass.getName()); } if (System.getProperty("java.naming.factory.url.pkgs") == null) { System.setProperty("java.naming.factory.url.pkgs", "winstone.jndi"); } } catch (ClassNotFoundException err) {} Logger.log(Logger.MAX, RESOURCES, "Launcher.StartupArgs", args + ""); this.args = args; // Check for java home List jars = new ArrayList(); List commonLibCLPaths = new ArrayList(); String defaultJavaHome = System.getProperty("java.home"); File javaHome = new File(defaultJavaHome); Logger.log(Logger.DEBUG, RESOURCES, "Launcher.UsingJavaHome", javaHome.getPath()); /* File toolsJar = Option.TOOLS_JAR.get(args); if (toolsJar == null) { toolsJar = new File(javaHome, "lib/tools.jar"); // first try - if it doesn't exist, try up one dir since we might have // the JRE home by mistake if (!toolsJar.exists()) { File javaHome2 = javaHome.getParentFile(); File toolsJar2 = new File(javaHome2, "lib/tools.jar"); if (toolsJar2.exists()) { javaHome = javaHome2; toolsJar = toolsJar2; } } } // Add tools jar to classloader path if (toolsJar.exists()) { jars.add(toolsJar.toURL()); commonLibCLPaths.add(toolsJar); Logger.log(Logger.DEBUG, RESOURCES, "Launcher.AddedCommonLibJar", toolsJar.getName()); }*/ // Set up common lib class loader /* File libFolder = Option.COMMON_LIB_FOLDER.get(args,new File("lib")); if (libFolder.exists() && libFolder.isDirectory()) { Logger.log(Logger.DEBUG, RESOURCES, "Launcher.UsingCommonLib", libFolder.getCanonicalPath()); File children[] = libFolder.listFiles(); for (File aChildren : children) if (aChildren.getName().endsWith(".jar") || aChildren.getName().endsWith(".zip")) { jars.add(aChildren.toURL()); commonLibCLPaths.add(aChildren); Logger.log(Logger.DEBUG, RESOURCES, "Launcher.AddedCommonLibJar", aChildren.getName()); } } else { Logger.log(Logger.DEBUG, RESOURCES, "Launcher.NoCommonLib"); } ClassLoader commonLibCL = new URLClassLoader((URL[]) jars.toArray(new URL[jars.size()]), getClass().getClassLoader());*/ ClassLoader commonLibCL = this.getClass().getClassLoader(); Logger.log(Logger.MAX, RESOURCES, "Launcher.CLClassLoader", commonLibCL.toString()); Logger.log(Logger.MAX, RESOURCES, "Launcher.CLClassLoader", commonLibCLPaths.toString()); this.objectPool = new ObjectPool(args); // If jndi is enabled, run the container wide jndi populator if (useJNDI) { try { // Build the realm Class jndiMgrClass = JNDIManager.class; Constructor jndiMgrConstr = jndiMgrClass.getConstructor(new Class[] { Map.class, List.class, ClassLoader.class }); this.globalJndiManager = (JNDIManager) jndiMgrConstr.newInstance(args, null, commonLibCL); this.globalJndiManager.setup(); } catch (Throwable err) { Logger.log(Logger.ERROR, RESOURCES, "Launcher.JNDIError", "", err); } } // Open the web apps this.hostGroup = new HostGroup(this.cluster, this.objectPool, commonLibCL, (File []) commonLibCLPaths.toArray(new File[0]), args); // Create connectors (http, https and ajp) spawnListener(HTTP_LISTENER_CLASS); spawnListener(AJP_LISTENER_CLASS); try { Class.forName("javax.net.ServerSocketFactory"); spawnListener(HTTPS_LISTENER_CLASS); } catch (ClassNotFoundException err) { Logger.log(Logger.DEBUG, RESOURCES, "Launcher.NeedsJDK14", HTTPS_LISTENER_CLASS); } this.controlThread = new Thread(this, RESOURCES.getString( "Launcher.ThreadName", "" + this.controlPort)); this.controlThread.setDaemon(false); this.controlThread.setContextClassLoader(KevLauncher.class.getClassLoader()); this.controlThread.start(); success = true; } finally { if (!success) shutdown(); } } /** * Instantiates listeners. Note that an exception thrown in the * constructor is interpreted as the listener being disabled, so * don't do anything too adventurous in the constructor, or if you do, * catch and log any errors locally before rethrowing. */ protected void spawnListener(String listenerClassName) throws IOException { try { Class listenerClass = Class.forName(listenerClassName); Constructor listenerConstructor = listenerClass .getConstructor(new Class[]{Map.class, ObjectPool.class, HostGroup.class}); Listener listener = (Listener) listenerConstructor .newInstance(args, this.objectPool, this.hostGroup); if (listener.start()) { this.listeners.add(listener); } // } catch (ClassNotFoundException err) { // Logger.log(Logger.INFO, RESOURCES, // "Launcher.ListenerNotFound", listenerClassName); } catch (Throwable err) { // Logger.log(Logger.ERROR, RESOURCES, // "Launcher.ListenerStartupError", listenerClassName, err); throw (IOException)new IOException("Failed to start a listener: "+listenerClassName).initCause(err); } } /** * The main run method. This handles the normal thread processing. */ public void run() { boolean interrupted = false; try { ServerSocket controlSocket = null; if (this.controlPort > 0) { controlSocket = new ServerSocket(this.controlPort); controlSocket.setSoTimeout(CONTROL_TIMEOUT); } // Enter the main loop while (!interrupted) { // this.objectPool.removeUnusedRequestHandlers(); // this.hostGroup.invalidateExpiredSessions(); // Check for control request Socket accepted = null; try { if (controlSocket != null) { accepted = controlSocket.accept(); if (accepted != null) { handleControlRequest(accepted); } } else { Thread.sleep(CONTROL_TIMEOUT); } } catch (InterruptedIOException err) { } catch (InterruptedException err) { interrupted = true; } catch (Throwable err) { Logger.log(Logger.ERROR, RESOURCES, "Launcher.ShutdownError", err); } finally { if (accepted != null) { try {accepted.close();} catch (IOException err) {} } if (Thread.interrupted()) { interrupted = true; } } } // Close server socket if (controlSocket != null) { controlSocket.close(); } } catch (Throwable err) { Logger.log(Logger.ERROR, RESOURCES, "Launcher.ShutdownError", err); } Logger.log(Logger.INFO, RESOURCES, "Launcher.ControlThreadShutdownOK"); } protected void handleControlRequest(Socket csAccepted) throws IOException { InputStream inSocket = null; OutputStream outSocket = null; ObjectInputStream inControl = null; try { inSocket = csAccepted.getInputStream(); int reqType = inSocket.read(); if ((byte) reqType == SHUTDOWN_TYPE) { Logger.log(Logger.INFO, RESOURCES, "Launcher.ShutdownRequestReceived"); shutdown(); } else if ((byte) reqType == RELOAD_TYPE) { inControl = new ObjectInputStream(inSocket); String host = inControl.readUTF(); String prefix = inControl.readUTF(); Logger.log(Logger.INFO, RESOURCES, "Launcher.ReloadRequestReceived", host + prefix); HostConfiguration hostConfig = this.hostGroup.getHostByName(host); hostConfig.reloadWebApp(prefix); } else if (this.cluster != null) { outSocket = csAccepted.getOutputStream(); this.cluster.clusterRequest((byte) reqType, inSocket, outSocket, csAccepted, this.hostGroup); } } finally { if (inControl != null) { try {inControl.close();} catch (IOException err) {} } if (inSocket != null) { try {inSocket.close();} catch (IOException err) {} } if (outSocket != null) { try {outSocket.close();} catch (IOException err) {} } } } public void shutdown() { // Release all listeners/pools/webapps for (Object listener : this.listeners) ((Listener) listener).destroy(); this.objectPool.destroy(); if (this.cluster != null) this.cluster.destroy(); if (this.hostGroup!=null) this.hostGroup.destroy(); if (this.globalJndiManager != null) { this.globalJndiManager.tearDown(); } if (this.controlThread != null) { this.controlThread.interrupt(); } Thread.yield(); Logger.log(Logger.INFO, RESOURCES, "Launcher.ShutdownOK"); } public boolean isRunning() { return (this.controlThread != null) && this.controlThread.isAlive(); } /* public static void initLogger(Map args) throws IOException { // Reset the log level int logLevel = WebAppConfiguration.intArg(args, "debug", Logger.INFO.intValue()); boolean showThrowingLineNo = Option.LOG_THROWING_LINE_NO.get(args); boolean showThrowingThread = Option.LOG_THROWING_THREAD.get(args); OutputStream logStream; if (args.get("logfile") != null) { logStream = new FileOutputStream((String) args.get("logfile")); } else if (WebAppConfiguration.booleanArg(args, "logToStdErr", false)) { logStream = System.err; } else { logStream = System.out; } // Logger.init(logLevel, logStream, showThrowingLineNo, showThrowingThread); // Logger.init(Level.parse(String.valueOf(logLevel)), logStream, showThrowingThread); }*/ protected static void printUsage() { // if the caller overrides the usage, use that instead. String usage = USAGE; if(usage==null) usage = RESOURCES.getString("Launcher.UsageInstructions", RESOURCES.getString("ServerVersion")); System.out.println(usage); } /** * Overridable usage screen */ public static String USAGE; }