All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.start.Main Maven / Gradle / Ivy

There is a newer version: 12.1.0.alpha0
Show newest version
// ========================================================================
// Copyright (c) 2003-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.start;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import java.security.Policy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;

import org.eclipse.jetty.start.log.RedirectedStreamLogger;

/*-------------------------------------------*/
/**
 * 

* Main start class. This class is intended to be the main class listed in the MANIFEST.MF of the start.jar archive. It * allows an application to be started with the command "java -jar start.jar". *

* *

* The behaviour of Main is controlled by the parsing of the {@link Config} "org/eclipse/start/start.config" file * obtained as a resource or file. *

*/ public class Main { private boolean _showUsage = false; private boolean _dumpVersions = false; private boolean _listConfig = false; private boolean _listOptions = false; private boolean _dryRun = false; private boolean _exec = false; private boolean _secure = false; private boolean _fromDaemon = false; private final Config _config = new Config(); private Set _sysProps = new HashSet(); private List _jvmArgs = new ArrayList(); private String _startConfig = null; private String _jettyHome; public static void main(String[] args) { Main main = new Main(); try { main.parseCommandLine(args); } catch (Throwable t) { t.printStackTrace(System.err); } } public void parseCommandLine(String[] args) { try { List arguments = new ArrayList(); // add the command line args and look for start.ini args boolean ini=false; for (String arg : args) { if (arg.startsWith("--ini=")||arg.equals("--ini")) { ini=true; if (arg.length()>6) { arguments.addAll(loadStartIni(arg.substring(6))); continue; } } else if (arg.startsWith("--config=")) { _startConfig=arg.substring(9); } else arguments.add(arg); } // if no non-option inis, add the start.ini if (!ini) arguments.addAll(0,loadStartIni(null)); // The XML Configuration Files to initialize with List xmls = new ArrayList(); // Process the arguments for (String arg : arguments) { if ("--help".equals(arg) || "-?".equals(arg)) { _showUsage = true; continue; } if ("--stop".equals(arg)) { int port = Integer.parseInt(_config.getProperty("STOP.KEY",System.getProperty("STOP.PORT","-1"))); String key = _config.getProperty("STOP.KETY",System.getProperty("STOP.KEY",null)); stop(port,key); return; } if ("--version".equals(arg) || "-v".equals(arg) || "--info".equals(arg)) { _dumpVersions = true; continue; } if ("--list-modes".equals(arg) || "--list-options".equals(arg)) { _listOptions = true; continue; } if ("--list-config".equals(arg)) { _listConfig=true; continue; } if ("--exec-print".equals(arg)||"--dry-run".equals(arg)) { _dryRun = true; continue; } if ("--exec".equals(arg)) { _exec = true; continue; } // Special internal indicator that jetty was started by the jetty.sh Daemon if ("--fromDaemon".equals(arg)) { _fromDaemon = true; PrintStream logger = new PrintStream(new RedirectedStreamLogger("daemon_yyyy_mm_dd.log",false,90,TimeZone.getTimeZone("GMT"))); System.setOut(logger); System.setErr(logger); continue; } if ("--secure".equals(arg)) { _secure = true; continue; } if (arg.startsWith("-D")) { String[] assign = arg.substring(2).split("=",2); _sysProps.add(assign[0]); switch(assign.length) { case 2: System.setProperty(assign[0],assign[1]); break; case 1: System.setProperty(assign[0],""); break; default: break; } continue; } if (arg.startsWith("-")) { _jvmArgs.add(arg); continue; } // Is this a Property? if (arg.indexOf('=') >= 0) { String[] assign = arg.split("=",2); switch(assign.length) { case 2: if ("OPTIONS".equals(assign[0])) { String opts[] = assign[1].split(","); for (String opt : opts) _config.addActiveOption(opt); } else this._config.setProperty(assign[0],assign[1]); break; case 1: this._config.setProperty(assign[0],null); break; default: break; } continue; } // Anything else is considered an XML file. xmls.add(arg); } start(xmls); } catch (Throwable t) { t.printStackTrace(System.err); System.out.println("Use java -jar start.jar --help for usage information."); } } /** * If a start.ini is present in the CWD, then load it into the argument list. */ private List loadStartIni(String ini) { String jettyHome=System.getProperty("jetty.home"); File startIniFile = ini==null?((jettyHome!=null)? new File(jettyHome,"start.ini"):new File("start.ini")):new File(ini); if (!startIniFile.exists() || !startIniFile.canRead()) { if (ini!=null) System.err.println("Warning - can't find ini file: "+ini); // No start.ini found, skip load. return Collections.emptyList(); } List args = new ArrayList(); FileReader reader = null; BufferedReader buf = null; try { reader = new FileReader(startIniFile); buf = new BufferedReader(reader); String arg; while ((arg = buf.readLine()) != null) { arg=arg.trim(); if (arg.length()==0 || arg.startsWith("#")) continue; args.add(arg); } } catch (IOException e) { e.printStackTrace(); } finally { close(buf); close(reader); } return args; } private void usage() { String usageResource = "org/eclipse/jetty/start/usage.txt"; InputStream usageStream = getClass().getClassLoader().getResourceAsStream(usageResource); if (usageStream == null) { System.err.println("Usage: java -jar start.jar [options] [properties] [configs]"); System.err.println("ERROR: detailed usage resource unavailable"); System.exit(1); } BufferedReader buf = null; try { buf = new BufferedReader(new InputStreamReader(usageStream)); String line; while ((line = buf.readLine()) != null) { if (line.endsWith("@") && line.indexOf('@')!=line.lastIndexOf('@')) { String indent=line.substring(0,line.indexOf("@")); String info=line.substring(line.indexOf('@'),line.lastIndexOf('@')); if (info.equals("@OPTIONS")) { List sortedOptions = new ArrayList(); sortedOptions.addAll(_config.getSectionIds()); Collections.sort(sortedOptions); for (String option : sortedOptions) { if ("*".equals(option) || option.trim().length()==0) continue; System.out.print(indent); System.out.println(option); } } else if (info.equals("@CONFIGS")) { File etc = new File(System.getProperty("jetty.home","."),"etc"); if (!etc.exists() || !etc.isDirectory()) { System.out.print(indent); System.out.println("Unable to find/list " + etc); continue; } File configs[] = etc.listFiles(new FileFilter() { public boolean accept(File path) { if (!path.isFile()) { return false; } String name = path.getName().toLowerCase(); return (name.startsWith("jetty") && name.endsWith(".xml")); } }); List configFiles = new ArrayList(); configFiles.addAll(Arrays.asList(configs)); Collections.sort(configFiles); for (File configFile : configFiles) { System.out.print(indent); System.out.print("etc/"); System.out.println(configFile.getName()); } } else if (info.equals("@STARTINI")) { List ini = loadStartIni(null); if (ini!=null && ini.size()>0) { for (String a : ini) { System.out.print(indent); System.out.println(a); } } else { System.out.print(indent); System.out.println("none"); } } } else { System.out.println(line); } } } catch (IOException e) { e.printStackTrace(System.err); } finally { if (buf != null) { try { buf.close(); } catch (IOException ignore) { /* ignore */ } } } System.exit(1); } public void invokeMain(ClassLoader classloader, String classname, List args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { Class invoked_class = null; try { invoked_class = classloader.loadClass(classname); } catch (ClassNotFoundException e) { e.printStackTrace(); } if (Config.isDebug() || invoked_class == null) { if (invoked_class == null) System.err.println("ClassNotFound: " + classname); else System.err.println(classname + " " + invoked_class.getPackage().getImplementationVersion()); if (invoked_class == null) { System.err.println("Usage: java -jar start.jar [options] [properties] [configs]"); System.err.println(" java -jar start.jar --help # for more information"); return; } } String argArray[] = args.toArray(new String[0]); Class[] method_param_types = new Class[] { argArray.getClass() }; Method main = invoked_class.getDeclaredMethod("main",method_param_types); Object[] method_params = new Object[] { argArray }; main.invoke(null,method_params); } /* ------------------------------------------------------------ */ public static void close(Reader reader) { if (reader == null) { return; } try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } /* ------------------------------------------------------------ */ public static void close(InputStream stream) { if (stream == null) { return; } try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } /* ------------------------------------------------------------ */ public void start(List xmls) throws FileNotFoundException, IOException, InterruptedException { // Setup Start / Stop Monitoring startMonitor(); // Load potential Config (start.config) List configuredXmls = loadConfig(xmls); // No XML defined in start.config or command line. Can't execute. if (configuredXmls.isEmpty()) { throw new FileNotFoundException("No XML configuration files specified in start.config or command line."); } // Add required logging if executed via the daemon. if (_fromDaemon) { configuredXmls.add("etc/jetty-logging.xml"); } // Add mandatory options for secure mode if (_secure) { _config.addActiveOption("policy"); _config.addActiveOption("security"); } // Normalize the XML config options passed on the command line. configuredXmls = resolveXmlConfigs(configuredXmls); // Get Desired Classpath based on user provided Active Options. Classpath classpath = _config.getActiveClasspath(); System.setProperty("java.class.path",classpath.toString()); ClassLoader cl = classpath.getClassLoader(); if (Config.isDebug()) { System.err.println("java.class.path=" + System.getProperty("java.class.path")); System.err.println("jetty.home=" + System.getProperty("jetty.home")); System.err.println("java.home=" + System.getProperty("java.home")); System.err.println("java.io.tmpdir=" + System.getProperty("java.io.tmpdir")); System.err.println("java.class.path=" + classpath); System.err.println("classloader=" + cl); System.err.println("classloader.parent=" + cl.getParent()); } // Show the usage information and return if (_showUsage) { usage(); return; } // Show the version information and return if (_dumpVersions) { showClasspathWithVersions(classpath); showActiveSecurityPolicies(cl); return; } // Show all options with version information if (_listOptions) { showAllOptionsWithVersions(classpath); return; } if (_listConfig) { listConfig(); return; } // Show Command Line to execute Jetty if (_dryRun) { System.out.println(buildCommandLine(classpath,configuredXmls)); return; } // Show Command Line to execute Jetty if (_exec) { String cmd = buildCommandLine(classpath,configuredXmls); Process process = Runtime.getRuntime().exec(cmd); copyInThread(process.getErrorStream(),System.err); copyInThread(process.getInputStream(),System.out); copyInThread(System.in,process.getOutputStream()); process.waitFor(); return; } if (_jvmArgs.size()>0 || _sysProps.size()>0) System.err.println("WARNING: System properties and/or JVM args set. Consider using --dry-run or --exec"); // Set current context class loader to what is selected. Thread.currentThread().setContextClassLoader(cl); // Initialize the Security initSecurity(cl); // Invoke the Main Class try { // Get main class as defined in start.config String classname = _config.getMainClassname(); // Check for override of start class (via "jetty.server" property) String mainClass = System.getProperty("jetty.server"); if (mainClass != null) classname = mainClass; // Check for override of start class (via "main.class" property) mainClass = System.getProperty("main.class"); if (mainClass != null) classname = mainClass; Config.debug("main.class=" + classname); invokeMain(cl,classname,configuredXmls); } catch (Exception e) { e.printStackTrace(); } } private void copyInThread(final InputStream in,final OutputStream out) { new Thread(new Runnable() { public void run() { try { byte[] buf=new byte[1024]; int len=in.read(buf); while(len>0) { out.write(buf,0,len); len=in.read(buf); } } catch(IOException e) { e.printStackTrace(); } } }).start(); } private String resolveXmlConfig(String xmlFilename) throws FileNotFoundException { if (!xmlFilename.toLowerCase().endsWith(".xml")) { // Nothing to resolve. return xmlFilename; } File xml = new File(xmlFilename); if (xml.exists() && xml.isFile() && xml.isAbsolute()) { return xml.getAbsolutePath(); } xml = new File(_jettyHome,fixPath(xmlFilename)); if (xml.exists() && xml.isFile()) { return xml.getAbsolutePath(); } xml = new File(_jettyHome,fixPath("etc/" + xmlFilename)); if (xml.exists() && xml.isFile()) { return xml.getAbsolutePath(); } throw new FileNotFoundException("Unable to find XML Config: " + xmlFilename); } private String buildCommandLine(Classpath classpath, List xmls) { StringBuilder cmd = new StringBuilder(); cmd.append(findJavaBin()); for (String x:_jvmArgs) cmd.append(' ').append(x); cmd.append(" -Djetty.home=").append(_jettyHome); for (String p:_sysProps) { cmd.append(" -D").append(p); String v=System.getProperty(p); if (v!=null && v.length()>0) cmd.append('=').append(v); } cmd.append(" -cp ").append(classpath.toString()); cmd.append(" ").append(_config.getMainClassname()); for (String xml : xmls) { cmd.append(' ').append(xml); } return cmd.toString(); } private String findJavaBin() { File javaHome = new File(System.getProperty("java.home")); if (!javaHome.exists()) { return null; } File javabin = findExecutable(javaHome,"bin/java"); if (javabin != null) { return javabin.getAbsolutePath(); } javabin = findExecutable(javaHome,"bin/java.exe"); if (javabin != null) { return javabin.getAbsolutePath(); } return "java"; } private File findExecutable(File root, String path) { String npath = path.replace('/',File.separatorChar); File exe = new File(root,npath); if (!exe.exists()) { return null; } return exe; } private void showAllOptionsWithVersions(Classpath classpath) { Set sectionIds = _config.getSectionIds(); StringBuffer msg = new StringBuffer(); msg.append("There "); if (sectionIds.size() > 1) { msg.append("are "); } else { msg.append("is "); } msg.append(String.valueOf(sectionIds.size())); msg.append(" OPTION"); if (sectionIds.size() > 1) { msg.append("s"); } msg.append(" available to use."); System.out.println(msg); System.out.println("Each option is listed along with associated available classpath entries, in the order that they would appear from that mode."); System.out.println("Note: If using multiple options (eg: 'Server,servlet,webapp,jms,jmx') " + "then overlapping entries will not be repeated in the eventual classpath."); System.out.println(); System.out.printf("${jetty.home} = %s%n",_jettyHome); System.out.println(); for (String sectionId : sectionIds) { if (Config.DEFAULT_SECTION.equals(sectionId)) { System.out.println("GLOBAL option (Prepended Entries)"); } else if ("*".equals(sectionId)) { System.out.println("GLOBAL option (Appended Entries) (*)"); } else { System.out.printf("Option [%s]",sectionId); if (Character.isUpperCase(sectionId.charAt(0))) { System.out.print(" (Aggregate)"); } System.out.println(); } System.out.println("-------------------------------------------------------------"); Classpath sectionCP = _config.getSectionClasspath(sectionId); if (sectionCP.isEmpty()) { System.out.println("Empty option, no classpath entries active."); System.out.println(); continue; } int i = 0; for (File element : sectionCP.getElements()) { String elementPath = element.getAbsolutePath(); if (elementPath.startsWith(_jettyHome)) { elementPath = "${jetty.home}" + elementPath.substring(_jettyHome.length()); } System.out.printf("%2d: %20s | %s\n",i++,getVersion(element),elementPath); } System.out.println(); } } private void showClasspathWithVersions(Classpath classpath) { // Iterate through active classpath, and fetch Implementation Version from each entry (if present) // to dump to end user. System.out.println("Active Options: " + _config.getActiveOptions()); if (classpath.count() == 0) { System.out.println("No version information available show."); return; } System.out.println("Version Information on " + classpath.count() + " entr" + ((classpath.count() > 1)?"ies":"y") + " in the classpath."); System.out.println("Note: order presented here is how they would appear on the classpath."); System.out.println(" changes to the OPTIONS=[option,option,...] command line option will be reflected here."); int i = 0; for (File element : classpath.getElements()) { String elementPath = element.getAbsolutePath(); if (elementPath.startsWith(_jettyHome)) { elementPath = "${jetty.home}" + elementPath.substring(_jettyHome.length()); } System.out.printf("%2d: %20s | %s\n",i++,getVersion(element),elementPath); } } private void showActiveSecurityPolicies(ClassLoader cl) { initSecurity(cl); Policy policy = Policy.getPolicy(); if (policy != null && policy.getClass().getName().contains("JettyPolicy")) { System.out.println("Active Security Policies: "); try { Method m = policy.getClass().getMethod("dump",new Class[]{ PrintStream.class }); m.invoke(policy,new Object[] { System.out }); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private String fixPath(String path) { return path.replace('/',File.separatorChar); } private String getVersion(File element) { if (element.isDirectory()) { return "(dir)"; } if (element.isFile()) { String name = element.getName().toLowerCase(); if (name.endsWith(".jar")) { return JarVersion.getVersion(element); } if (name.endsWith(".zip")) { return getZipVersion(element); } } return ""; } private String getZipVersion(File element) { // TODO - find version in zip file. Look for META-INF/MANIFEST.MF ? return ""; } private void initSecurity(ClassLoader cl) { // Init the Security Policies try { if (_secure) { Policy.setPolicy(_config.getPolicyInstance(cl)); System.setSecurityManager(new SecurityManager()); // Policy.getPolicy().refresh(); } else { Policy policy = Policy.getPolicy(); if (policy != null) policy.refresh(); } } catch (Exception e) { e.printStackTrace(); } } private List resolveXmlConfigs(List xmls) throws FileNotFoundException { List ret = new ArrayList(); for (String xml : xmls) { ret.add(resolveXmlConfig(xml)); } return ret; } private void listConfig() { InputStream cfgstream = null; try { cfgstream=getConfigStream(); byte[] buf=new byte[4096]; int len=0; while (len>=0) { len=cfgstream.read(buf); if (len>0) System.out.write(buf,0,len); } } catch (Exception e) { e.printStackTrace(); System.exit(1); } finally { close(cfgstream); } } /** * Load Configuration. * * No specific configuration is real until a {@link Config#getCombinedClasspath(java.util.Collection)} is used to * execute the {@link Class} specified by {@link Config#getMainClassname()} is executed. * * @param xmls * the command line specified xml configuration options. * @return the list of xml configurations arriving via command line and start.config choices. */ private List loadConfig(List xmls) { InputStream cfgstream = null; try { // Pass in xmls.size into Config so that conditions based on "nargs" work. _config.setArgCount(xmls.size()); cfgstream=getConfigStream(); // parse the config _config.parse(cfgstream); _jettyHome = _config.getProperty("jetty.home"); if (_jettyHome != null) { _jettyHome = new File(_jettyHome).getCanonicalPath(); System.setProperty("jetty.home",_jettyHome); } // Collect the configured xml configurations. List ret = new ArrayList(); ret.addAll(xmls); // add command line provided xmls first. for (String xmlconfig : _config.getXmlConfigs()) { // add xmlconfigs arriving via start.config if (!ret.contains(xmlconfig)) { ret.add(xmlconfig); } } return ret; } catch (Exception e) { e.printStackTrace(); System.exit(1); return null; // never executed (just to satisfy javac compiler) } finally { close(cfgstream); } } private InputStream getConfigStream() throws FileNotFoundException { String config=_startConfig; if (config==null || config.length()==0) config=System.getProperty("START","org/eclipse/jetty/start/start.config"); Config.debug("config=" + config); // Look up config as resource first. InputStream cfgstream = getClass().getClassLoader().getResourceAsStream(config); // resource not found, try filesystem next if (cfgstream == null) cfgstream = new FileInputStream(config); return cfgstream; } private void startMonitor() { int port = Integer.parseInt(System.getProperty("STOP.PORT","-1")); String key = System.getProperty("STOP.KEY",null); Monitor.monitor(port,key); } /** * Stop a running jetty instance. */ public void stop(int port, String key) { int _port = port; String _key = key; try { if (_port <= 0) System.err.println("STOP.PORT system property must be specified"); if (_key == null) { _key = ""; System.err.println("STOP.KEY system property must be specified"); System.err.println("Using empty key"); } Socket s = new Socket(InetAddress.getByName("127.0.0.1"),_port); OutputStream out = s.getOutputStream(); out.write((_key + "\r\nstop\r\n").getBytes()); out.flush(); s.close(); } catch (ConnectException e) { System.err.println("ERROR: Not running!"); } catch (Exception e) { e.printStackTrace(); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy