1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.start;
20
21 import java.io.BufferedReader;
22 import java.io.Closeable;
23 import java.io.File;
24 import java.io.FileFilter;
25 import java.io.FileInputStream;
26 import java.io.FileNotFoundException;
27 import java.io.FileOutputStream;
28 import java.io.FileReader;
29 import java.io.FilenameFilter;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.InputStreamReader;
33 import java.io.LineNumberReader;
34 import java.io.OutputStream;
35 import java.io.PrintStream;
36 import java.lang.reflect.InvocationTargetException;
37 import java.lang.reflect.Method;
38 import java.net.ConnectException;
39 import java.net.InetAddress;
40 import java.net.Socket;
41 import java.net.SocketTimeoutException;
42 import java.net.URL;
43 import java.text.SimpleDateFormat;
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.Collections;
47 import java.util.Date;
48 import java.util.HashSet;
49 import java.util.List;
50 import java.util.Locale;
51 import java.util.Properties;
52 import java.util.Set;
53
54 import javax.naming.OperationNotSupportedException;
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public class Main
69 {
70 private static final String START_LOG_FILENAME = "start.log";
71 private static final SimpleDateFormat START_LOG_ROLLOVER_DATEFORMAT = new SimpleDateFormat("yyyy_MM_dd-HHmmSSSSS.'" + START_LOG_FILENAME + "'");
72
73 private static final int EXIT_USAGE = 1;
74 private static final int ERR_LOGGING = -1;
75 private static final int ERR_INVOKE_MAIN = -2;
76 private static final int ERR_NOT_STOPPED = -4;
77 private static final int ERR_UNKNOWN = -5;
78 private boolean _showUsage = false;
79 private boolean _dumpVersions = false;
80 private boolean _listConfig = false;
81 private boolean _listOptions = false;
82 private boolean _dryRun = false;
83 private boolean _exec = false;
84 private final Config _config = new Config();
85 private final Set<String> _sysProps = new HashSet<String>();
86 private final List<String> _jvmArgs = new ArrayList<String>();
87 private String _startConfig = null;
88
89 private String _jettyHome;
90
91 public static void main(String[] args)
92 {
93 try
94 {
95 Main main = new Main();
96 List<String> arguments = main.expandCommandLine(args);
97 List<String> xmls = main.processCommandLine(arguments);
98 if (xmls != null)
99 main.start(xmls);
100 }
101 catch (Throwable e)
102 {
103 usageExit(e,ERR_UNKNOWN);
104 }
105 }
106
107 Main() throws IOException
108 {
109 _jettyHome = System.getProperty("jetty.home",".");
110 _jettyHome = new File(_jettyHome).getCanonicalPath();
111 }
112
113 public List<String> expandCommandLine(String[] args) throws Exception
114 {
115 List<String> arguments = new ArrayList<String>();
116
117
118 boolean ini = false;
119 for (String arg : args)
120 {
121 if (arg.startsWith("--ini=") || arg.equals("--ini"))
122 {
123 ini = true;
124 if (arg.length() > 6)
125 {
126 arguments.addAll(loadStartIni(new File(arg.substring(6))));
127 }
128 }
129 else if (arg.startsWith("--config="))
130 {
131 _startConfig = arg.substring(9);
132 }
133 else
134 {
135 arguments.add(arg);
136 }
137 }
138
139
140 if (!ini)
141 {
142 arguments.addAll(0,parseStartIniFiles());
143 }
144
145 return arguments;
146 }
147
148 List<String> parseStartIniFiles()
149 {
150 List<String> ini_args = new ArrayList<String>();
151 File start_ini = new File(_jettyHome,"start.ini");
152 if (start_ini.exists())
153 ini_args.addAll(loadStartIni(start_ini));
154
155 return ini_args;
156 }
157
158 public List<String> processCommandLine(List<String> arguments) throws Exception
159 {
160
161 List<String> xmls = new ArrayList<String>();
162
163
164 int startup = 0;
165 for (String arg : arguments)
166 {
167 if ("--help".equals(arg) || "-?".equals(arg))
168 {
169 _showUsage = true;
170 continue;
171 }
172
173 if ("--stop".equals(arg))
174 {
175 int port = Integer.parseInt(Config.getProperty("STOP.PORT","-1"));
176 String key = Config.getProperty("STOP.KEY",null);
177 int timeout = Integer.parseInt(Config.getProperty("STOP.WAIT","0"));
178 stop(port,key,timeout);
179 return null;
180 }
181
182 if (arg.startsWith("--download="))
183 {
184 download(arg);
185 continue;
186 }
187
188 if ("--version".equals(arg) || "-v".equals(arg) || "--info".equals(arg))
189 {
190 _dumpVersions = true;
191 continue;
192 }
193
194 if ("--list-modes".equals(arg) || "--list-options".equals(arg))
195 {
196 _listOptions = true;
197 continue;
198 }
199
200 if ("--list-config".equals(arg))
201 {
202 _listConfig = true;
203 continue;
204 }
205
206 if ("--exec-print".equals(arg) || "--dry-run".equals(arg))
207 {
208 _dryRun = true;
209 continue;
210 }
211
212 if ("--exec".equals(arg))
213 {
214 _exec = true;
215 continue;
216 }
217
218
219 if ("--daemon".equals(arg))
220 {
221 File startDir = new File(System.getProperty("jetty.logs","logs"));
222 if (!startDir.exists() || !startDir.canWrite())
223 startDir = new File(".");
224
225 File startLog = new File(startDir,START_LOG_ROLLOVER_DATEFORMAT.format(new Date()));
226
227 if (!startLog.exists() && !startLog.createNewFile())
228 {
229
230 System.err.println("Unable to create: " + startLog.getAbsolutePath());
231
232 usageExit(ERR_LOGGING);
233 }
234
235 if (!startLog.canWrite())
236 {
237
238 System.err.println("Unable to write to: " + startLog.getAbsolutePath());
239
240 usageExit(ERR_LOGGING);
241 }
242 PrintStream logger = new PrintStream(new FileOutputStream(startLog,false));
243 System.setOut(logger);
244 System.setErr(logger);
245 System.out.println("Establishing " + START_LOG_FILENAME + " on " + new Date());
246 continue;
247 }
248
249 if (arg.startsWith("-D"))
250 {
251 String[] assign = arg.substring(2).split("=",2);
252 _sysProps.add(assign[0]);
253 switch (assign.length)
254 {
255 case 2:
256 System.setProperty(assign[0],assign[1]);
257 break;
258 case 1:
259 System.setProperty(assign[0],"");
260 break;
261 default:
262 break;
263 }
264 continue;
265 }
266
267 if (arg.startsWith("-"))
268 {
269 _jvmArgs.add(arg);
270 continue;
271 }
272
273
274 if (arg.indexOf('=') >= 0)
275 {
276 String[] assign = arg.split("=",2);
277
278 switch (assign.length)
279 {
280 case 2:
281 if ("OPTIONS".equals(assign[0]))
282 {
283 String opts[] = assign[1].split(",");
284 for (String opt : opts)
285 _config.addActiveOption(opt.trim());
286 }
287 else
288 {
289 this._config.setProperty(assign[0],assign[1]);
290 }
291 break;
292 case 1:
293 this._config.setProperty(assign[0],null);
294 break;
295 default:
296 break;
297 }
298
299 continue;
300 }
301
302
303 if (xmls.contains(arg))
304 {
305 System.out.println("WARN: Argument '" + arg + "' specified multiple times. Check start.ini?");
306 System.out.println("Use \"java -jar start.jar --help\" for more information.");
307 }
308 xmls.add(arg);
309 }
310
311 return xmls;
312 }
313
314 private void download(String arg)
315 {
316 try
317 {
318 String[] split = arg.split(":",3);
319 if (split.length!=3 || "http".equalsIgnoreCase(split[0]) || !split[1].startsWith("//"))
320 throw new IllegalArgumentException("Not --download=<http uri>:<location>");
321
322 String location=split[2];
323 if (File.separatorChar!='/')
324 location.replaceAll("/",File.separator);
325 File file = new File(location);
326
327 if (Config.isDebug())
328 System.err.println("Download to "+file.getAbsolutePath()+(file.exists()?" Exists!":""));
329 if (file.exists())
330 return;
331
332 URL url = new URL(split[0].substring(11)+":"+split[1]);
333
334 System.err.println("DOWNLOAD: "+url+" to "+location);
335
336 if (!file.getParentFile().exists())
337 file.getParentFile().mkdirs();
338
339 byte[] buf=new byte[8192];
340 try (InputStream in = url.openStream(); OutputStream out = new FileOutputStream(file);)
341 {
342 while(true)
343 {
344 int len = in.read(buf);
345
346 if (len>0)
347 out.write(buf,0,len);
348 if (len<0)
349 break;
350 }
351 }
352 }
353 catch(Exception e)
354 {
355 System.err.println("ERROR: processing "+arg+"\n"+e);
356 e.printStackTrace();
357 usageExit(EXIT_USAGE);
358 }
359 }
360
361 private void usage()
362 {
363 String usageResource = "org/eclipse/jetty/start/usage.txt";
364 InputStream usageStream = getClass().getClassLoader().getResourceAsStream(usageResource);
365
366 if (usageStream == null)
367 {
368 System.err.println("ERROR: detailed usage resource unavailable");
369 usageExit(EXIT_USAGE);
370 }
371
372 BufferedReader buf = null;
373 try
374 {
375 buf = new BufferedReader(new InputStreamReader(usageStream));
376 String line;
377
378 while ((line = buf.readLine()) != null)
379 {
380 if (line.endsWith("@") && line.indexOf('@') != line.lastIndexOf('@'))
381 {
382 String indent = line.substring(0,line.indexOf("@"));
383 String info = line.substring(line.indexOf('@'),line.lastIndexOf('@'));
384
385 if (info.equals("@OPTIONS"))
386 {
387 List<String> sortedOptions = new ArrayList<String>();
388 sortedOptions.addAll(_config.getSectionIds());
389 Collections.sort(sortedOptions);
390
391 for (String option : sortedOptions)
392 {
393 if ("*".equals(option) || option.trim().length() == 0)
394 continue;
395 System.out.print(indent);
396 System.out.println(option);
397 }
398 }
399 else if (info.equals("@CONFIGS"))
400 {
401 File etc = new File(System.getProperty("jetty.home","."),"etc");
402 if (!etc.exists() || !etc.isDirectory())
403 {
404 System.out.print(indent);
405 System.out.println("Unable to find/list " + etc);
406 continue;
407 }
408
409 File configs[] = etc.listFiles(new FileFilter()
410 {
411 public boolean accept(File path)
412 {
413 if (!path.isFile())
414 {
415 return false;
416 }
417
418 String name = path.getName().toLowerCase(Locale.ENGLISH);
419 return (name.startsWith("jetty") && name.endsWith(".xml"));
420 }
421 });
422
423 List<File> configFiles = new ArrayList<File>();
424 configFiles.addAll(Arrays.asList(configs));
425 Collections.sort(configFiles);
426
427 for (File configFile : configFiles)
428 {
429 System.out.print(indent);
430 System.out.print("etc/");
431 System.out.println(configFile.getName());
432 }
433 }
434 else if (info.equals("@STARTINI"))
435 {
436 List<String> ini = parseStartIniFiles();
437 if (ini != null && ini.size() > 0)
438 {
439 for (String a : ini)
440 {
441 System.out.print(indent);
442 System.out.println(a);
443 }
444 }
445 else
446 {
447 System.out.print(indent);
448 System.out.println("none");
449 }
450 }
451 }
452 else
453 {
454 System.out.println(line);
455 }
456 }
457 }
458 catch (IOException e)
459 {
460 usageExit(e,EXIT_USAGE);
461 }
462 finally
463 {
464 close(buf);
465 }
466 System.exit(EXIT_USAGE);
467 }
468
469 public void invokeMain(ClassLoader classloader, String classname, List<String> args) throws IllegalAccessException, InvocationTargetException,
470 NoSuchMethodException, ClassNotFoundException
471 {
472 Class<?> invoked_class = null;
473
474 try
475 {
476 invoked_class = classloader.loadClass(classname);
477 }
478 catch (ClassNotFoundException e)
479 {
480 e.printStackTrace();
481 }
482
483 if (Config.isDebug() || invoked_class == null)
484 {
485 if (invoked_class == null)
486 {
487 System.err.println("ClassNotFound: " + classname);
488 }
489 else
490 {
491 System.err.println(classname + " " + invoked_class.getPackage().getImplementationVersion());
492 }
493
494 if (invoked_class == null)
495 {
496 usageExit(ERR_INVOKE_MAIN);
497 return;
498 }
499 }
500
501 String argArray[] = args.toArray(new String[0]);
502
503 Class<?>[] method_param_types = new Class[]
504 { argArray.getClass() };
505
506 Method main = invoked_class.getDeclaredMethod("main",method_param_types);
507 Object[] method_params = new Object[]
508 { argArray };
509 main.invoke(null,method_params);
510 }
511
512
513 public static void close(Closeable c)
514 {
515 if (c == null)
516 {
517 return;
518 }
519 try
520 {
521 c.close();
522 }
523 catch (IOException e)
524 {
525 e.printStackTrace(System.err);
526 }
527 }
528
529
530 public void start(List<String> xmls) throws IOException, InterruptedException
531 {
532
533 List<String> configuredXmls = loadConfig(xmls);
534
535
536 if (configuredXmls.isEmpty())
537 {
538 throw new FileNotFoundException("No XML configuration files specified in start.config or command line.");
539 }
540
541
542 configuredXmls = resolveXmlConfigs(configuredXmls);
543
544
545 Classpath classpath = _config.getActiveClasspath();
546
547 System.setProperty("java.class.path",classpath.toString());
548 ClassLoader cl = classpath.getClassLoader();
549 if (Config.isDebug())
550 {
551 System.err.println("java.class.path=" + System.getProperty("java.class.path"));
552 System.err.println("jetty.home=" + System.getProperty("jetty.home"));
553 System.err.println("java.home=" + System.getProperty("java.home"));
554 System.err.println("java.io.tmpdir=" + System.getProperty("java.io.tmpdir"));
555 System.err.println("java.class.path=" + classpath);
556 System.err.println("classloader=" + cl);
557 System.err.println("classloader.parent=" + cl.getParent());
558 System.err.println("properties=" + Config.getProperties());
559 }
560
561
562 if (_showUsage)
563 {
564 usage();
565 return;
566 }
567
568
569 if (_dumpVersions)
570 {
571 showClasspathWithVersions(classpath);
572 return;
573 }
574
575
576 if (_listOptions)
577 {
578 showAllOptionsWithVersions();
579 return;
580 }
581
582 if (_listConfig)
583 {
584 listConfig();
585 return;
586 }
587
588
589 if (_dryRun)
590 {
591 CommandLineBuilder cmd = buildCommandLine(classpath,configuredXmls);
592 System.out.println(cmd.toString());
593 return;
594 }
595
596
597 if (_exec)
598 {
599 CommandLineBuilder cmd = buildCommandLine(classpath,configuredXmls);
600
601 ProcessBuilder pbuilder = new ProcessBuilder(cmd.getArgs());
602 final Process process = pbuilder.start();
603 Runtime.getRuntime().addShutdownHook(new Thread()
604 {
605 @Override
606 public void run()
607 {
608 Config.debug("Destroying " + process);
609 process.destroy();
610 }
611 });
612
613 copyInThread(process.getErrorStream(),System.err);
614 copyInThread(process.getInputStream(),System.out);
615 copyInThread(System.in,process.getOutputStream());
616 process.waitFor();
617 System.exit(0);
618 return;
619 }
620
621 if (_jvmArgs.size() > 0 || _sysProps.size() > 0)
622 {
623 System.err.println("WARNING: System properties and/or JVM args set. Consider using --dry-run or --exec");
624 }
625
626
627 Thread.currentThread().setContextClassLoader(cl);
628
629
630 try
631 {
632
633 String classname = _config.getMainClassname();
634
635
636 String mainClass = System.getProperty("jetty.server");
637 if (mainClass != null)
638 {
639 classname = mainClass;
640 }
641
642
643 mainClass = System.getProperty("main.class");
644 if (mainClass != null)
645 {
646 classname = mainClass;
647 }
648
649 Config.debug("main.class=" + classname);
650
651 invokeMain(cl,classname,configuredXmls);
652 }
653 catch (Exception e)
654 {
655 usageExit(e,ERR_INVOKE_MAIN);
656 }
657 }
658
659 private void copyInThread(final InputStream in, final OutputStream out)
660 {
661 new Thread(new Runnable()
662 {
663 public void run()
664 {
665 try
666 {
667 byte[] buf = new byte[1024];
668 int len = in.read(buf);
669 while (len > 0)
670 {
671 out.write(buf,0,len);
672 len = in.read(buf);
673 }
674 }
675 catch (IOException e)
676 {
677
678 }
679 }
680
681 }).start();
682 }
683
684 private String resolveXmlConfig(String xmlFilename) throws FileNotFoundException
685 {
686 if (!xmlFilename.toLowerCase(Locale.ENGLISH).endsWith(".xml"))
687 {
688
689 return xmlFilename;
690 }
691
692 File xml = new File(xmlFilename);
693 if (xml.exists() && xml.isFile())
694 {
695 return xml.getAbsolutePath();
696 }
697
698 xml = new File(_jettyHome,fixPath(xmlFilename));
699 if (xml.exists() && xml.isFile())
700 {
701 return xml.getAbsolutePath();
702 }
703
704 xml = new File(_jettyHome,fixPath("etc/" + xmlFilename));
705 if (xml.exists() && xml.isFile())
706 {
707 return xml.getAbsolutePath();
708 }
709
710 throw new FileNotFoundException("Unable to find XML Config: " + xmlFilename);
711 }
712
713 CommandLineBuilder buildCommandLine(Classpath classpath, List<String> xmls) throws IOException
714 {
715 CommandLineBuilder cmd = new CommandLineBuilder(findJavaBin());
716
717 for (String x : _jvmArgs)
718 {
719 cmd.addArg(x);
720 }
721 cmd.addRawArg("-Djetty.home=" + _jettyHome);
722
723
724 ensureSystemPropertySet("STOP.PORT");
725 ensureSystemPropertySet("STOP.KEY");
726
727
728 for (String p : _sysProps)
729 {
730 String v = System.getProperty(p);
731 cmd.addEqualsArg("-D" + p,v);
732 }
733
734 cmd.addArg("-cp");
735 cmd.addRawArg(classpath.toString());
736 cmd.addRawArg(_config.getMainClassname());
737
738
739 Properties properties = Config.getProperties();
740 if (properties.size() > 0)
741 {
742 File prop_file = File.createTempFile("start",".properties");
743 if (!_dryRun)
744 prop_file.deleteOnExit();
745 try (OutputStream out = new FileOutputStream(prop_file))
746 {
747 properties.store(out,"start.jar properties");
748 }
749 cmd.addArg(prop_file.getAbsolutePath());
750 }
751
752 for (String xml : xmls)
753 {
754 cmd.addRawArg(xml);
755 }
756 return cmd;
757 }
758
759
760
761
762
763
764
765
766 private void ensureSystemPropertySet(String key)
767 {
768 if (_sysProps.contains(key))
769 {
770 return;
771 }
772
773 Properties props = Config.getProperties();
774 if (props.containsKey(key))
775 {
776 String val = props.getProperty(key,null);
777 if (val == null)
778 {
779 return;
780 }
781
782 _sysProps.add(key);
783 System.setProperty(key,val);
784 }
785 }
786
787 private String findJavaBin()
788 {
789 File javaHome = new File(System.getProperty("java.home"));
790 if (!javaHome.exists())
791 {
792 return null;
793 }
794
795 File javabin = findExecutable(javaHome,"bin/java");
796 if (javabin != null)
797 {
798 return javabin.getAbsolutePath();
799 }
800
801 javabin = findExecutable(javaHome,"bin/java.exe");
802 if (javabin != null)
803 {
804 return javabin.getAbsolutePath();
805 }
806
807 return "java";
808 }
809
810 private File findExecutable(File root, String path)
811 {
812 String npath = path.replace('/',File.separatorChar);
813 File exe = new File(root,npath);
814 if (!exe.exists())
815 {
816 return null;
817 }
818 return exe;
819 }
820
821 private void showAllOptionsWithVersions()
822 {
823 Set<String> sectionIds = _config.getSectionIds();
824
825 StringBuffer msg = new StringBuffer();
826 msg.append("There ");
827 if (sectionIds.size() > 1)
828 {
829 msg.append("are ");
830 }
831 else
832 {
833 msg.append("is ");
834 }
835 msg.append(String.valueOf(sectionIds.size()));
836 msg.append(" OPTION");
837 if (sectionIds.size() > 1)
838 {
839 msg.append("s");
840 }
841 msg.append(" available to use.");
842 System.out.println(msg);
843 System.out.println("Each option is listed along with associated available classpath entries, in the order that they would appear from that mode.");
844 System.out.println("Note: If using multiple options (eg: 'Server,servlet,webapp,jms,jmx') "
845 + "then overlapping entries will not be repeated in the eventual classpath.");
846 System.out.println();
847 System.out.printf("${jetty.home} = %s%n",_jettyHome);
848 System.out.println();
849
850 for (String sectionId : sectionIds)
851 {
852 if (Config.DEFAULT_SECTION.equals(sectionId))
853 {
854 System.out.println("GLOBAL option (Prepended Entries)");
855 }
856 else if ("*".equals(sectionId))
857 {
858 System.out.println("GLOBAL option (Appended Entries) (*)");
859 }
860 else
861 {
862 System.out.printf("Option [%s]",sectionId);
863 if (Character.isUpperCase(sectionId.charAt(0)))
864 {
865 System.out.print(" (Aggregate)");
866 }
867 System.out.println();
868 }
869 System.out.println("-------------------------------------------------------------");
870
871 Classpath sectionCP = _config.getSectionClasspath(sectionId);
872
873 if (sectionCP.isEmpty())
874 {
875 System.out.println("Empty option, no classpath entries active.");
876 System.out.println();
877 continue;
878 }
879
880 int i = 0;
881 for (File element : sectionCP.getElements())
882 {
883 String elementPath = element.getAbsolutePath();
884 if (elementPath.startsWith(_jettyHome))
885 {
886 elementPath = "${jetty.home}" + elementPath.substring(_jettyHome.length());
887 }
888 System.out.printf("%2d: %20s | %s\n",i++,getVersion(element),elementPath);
889 }
890
891 System.out.println();
892 }
893 }
894
895 private void showClasspathWithVersions(Classpath classpath)
896 {
897
898
899
900 System.out.println("Active Options: " + _config.getActiveOptions());
901
902 if (classpath.count() == 0)
903 {
904 System.out.println("No version information available show.");
905 return;
906 }
907
908 System.out.println("Version Information on " + classpath.count() + " entr" + ((classpath.count() > 1)?"ies":"y") + " in the classpath.");
909 System.out.println("Note: order presented here is how they would appear on the classpath.");
910 System.out.println(" changes to the OPTIONS=[option,option,...] command line option will be reflected here.");
911
912 int i = 0;
913 for (File element : classpath.getElements())
914 {
915 String elementPath = element.getAbsolutePath();
916 if (elementPath.startsWith(_jettyHome))
917 {
918 elementPath = "${jetty.home}" + elementPath.substring(_jettyHome.length());
919 }
920 System.out.printf("%2d: %20s | %s\n",i++,getVersion(element),elementPath);
921 }
922 }
923
924 private String fixPath(String path)
925 {
926 return path.replace('/',File.separatorChar);
927 }
928
929 private String getVersion(File element)
930 {
931 if (element.isDirectory())
932 {
933 return "(dir)";
934 }
935
936 if (element.isFile())
937 {
938 String name = element.getName().toLowerCase(Locale.ENGLISH);
939 if (name.endsWith(".jar"))
940 {
941 return JarVersion.getVersion(element);
942 }
943 }
944
945 return "";
946 }
947
948 private List<String> resolveXmlConfigs(List<String> xmls) throws FileNotFoundException
949 {
950 List<String> ret = new ArrayList<String>();
951 for (String xml : xmls)
952 {
953 ret.add(resolveXmlConfig(xml));
954 }
955
956 return ret;
957 }
958
959 private void listConfig()
960 {
961 InputStream cfgstream = null;
962 try
963 {
964 cfgstream = getConfigStream();
965 byte[] buf = new byte[4096];
966
967 int len = 0;
968
969 while (len >= 0)
970 {
971 len = cfgstream.read(buf);
972 if (len > 0)
973 System.out.write(buf,0,len);
974 }
975 }
976 catch (Exception e)
977 {
978 usageExit(e,ERR_UNKNOWN);
979 }
980 finally
981 {
982 close(cfgstream);
983 }
984 }
985
986
987
988
989
990
991
992
993
994
995
996 private List<String> loadConfig(List<String> xmls)
997 {
998 InputStream cfgstream = null;
999 try
1000 {
1001
1002 _config.setArgCount(xmls.size());
1003
1004 cfgstream = getConfigStream();
1005
1006
1007 _config.parse(cfgstream);
1008
1009 _jettyHome = Config.getProperty("jetty.home",_jettyHome);
1010 if (_jettyHome != null)
1011 {
1012 _jettyHome = new File(_jettyHome).getCanonicalPath();
1013 System.setProperty("jetty.home",_jettyHome);
1014 }
1015
1016
1017 List<String> ret = new ArrayList<String>();
1018 ret.addAll(xmls);
1019 for (String xmlconfig : _config.getXmlConfigs())
1020 {
1021
1022 if (!ret.contains(xmlconfig))
1023 {
1024 ret.add(xmlconfig);
1025 }
1026 }
1027
1028 return ret;
1029 }
1030 catch (Exception e)
1031 {
1032 usageExit(e,ERR_UNKNOWN);
1033 return null;
1034 }
1035 finally
1036 {
1037 close(cfgstream);
1038 }
1039 }
1040
1041 private InputStream getConfigStream() throws FileNotFoundException
1042 {
1043 String config = _startConfig;
1044 if (config == null || config.length() == 0)
1045 {
1046 config = System.getProperty("START","org/eclipse/jetty/start/start.config");
1047 }
1048
1049 Config.debug("config=" + config);
1050
1051
1052 InputStream cfgstream = getClass().getClassLoader().getResourceAsStream(config);
1053
1054
1055 if (cfgstream == null)
1056 {
1057 cfgstream = new FileInputStream(config);
1058 }
1059
1060 return cfgstream;
1061 }
1062
1063
1064
1065
1066 public void stop(int port, String key)
1067 {
1068 stop(port,key,0);
1069 }
1070
1071 public void stop(int port, String key, int timeout)
1072 {
1073 int _port = port;
1074 String _key = key;
1075
1076 try
1077 {
1078 if (_port <= 0)
1079 {
1080 System.err.println("STOP.PORT system property must be specified");
1081 }
1082 if (_key == null)
1083 {
1084 _key = "";
1085 System.err.println("STOP.KEY system property must be specified");
1086 System.err.println("Using empty key");
1087 }
1088
1089 Socket s = new Socket(InetAddress.getByName("127.0.0.1"),_port);
1090 if (timeout > 0)
1091 s.setSoTimeout(timeout * 1000);
1092 try
1093 {
1094 OutputStream out = s.getOutputStream();
1095 out.write((_key + "\r\nstop\r\n").getBytes());
1096 out.flush();
1097
1098 if (timeout > 0)
1099 {
1100 System.err.printf("Waiting %,d seconds for jetty to stop%n",timeout);
1101 LineNumberReader lin = new LineNumberReader(new InputStreamReader(s.getInputStream()));
1102 String response;
1103 while ((response = lin.readLine()) != null)
1104 {
1105 Config.debug("Received \"" + response + "\"");
1106 if ("Stopped".equals(response))
1107 System.err.println("Server reports itself as Stopped");
1108 }
1109 }
1110 }
1111 finally
1112 {
1113 s.close();
1114 }
1115 }
1116 catch (SocketTimeoutException e)
1117 {
1118 System.err.println("Timed out waiting for stop confirmation");
1119 System.exit(ERR_UNKNOWN);
1120 }
1121 catch (ConnectException e)
1122 {
1123 usageExit(e,ERR_NOT_STOPPED);
1124 }
1125 catch (Exception e)
1126 {
1127 usageExit(e,ERR_UNKNOWN);
1128 }
1129 }
1130
1131 static void usageExit(Throwable t, int exit)
1132 {
1133 t.printStackTrace(System.err);
1134 System.err.println();
1135 System.err.println("Usage: java -jar start.jar [options] [properties] [configs]");
1136 System.err.println(" java -jar start.jar --help # for more information");
1137 System.exit(exit);
1138 }
1139
1140 static void usageExit(int exit)
1141 {
1142 System.err.println();
1143 System.err.println("Usage: java -jar start.jar [options] [properties] [configs]");
1144 System.err.println(" java -jar start.jar --help # for more information");
1145 System.exit(exit);
1146 }
1147
1148
1149
1150
1151 List<String> loadStartIni(File ini)
1152 {
1153 if (!ini.exists())
1154 {
1155 System.err.println("Warning - can't find ini file: " + ini);
1156
1157 return Collections.emptyList();
1158 }
1159
1160 List<String> args = new ArrayList<String>();
1161
1162 FileReader reader = null;
1163 BufferedReader buf = null;
1164 try
1165 {
1166 reader = new FileReader(ini);
1167 buf = new BufferedReader(reader);
1168
1169 String arg;
1170 while ((arg = buf.readLine()) != null)
1171 {
1172 arg = arg.trim();
1173 if (arg.length() == 0 || arg.startsWith("#"))
1174 {
1175 continue;
1176 }
1177
1178 if (arg.endsWith("/"))
1179 {
1180 try
1181 {
1182 File start_d = new File(arg);
1183 if (!start_d.exists() || !start_d.isDirectory())
1184 start_d = new File(_jettyHome,arg);
1185
1186 if (start_d.isDirectory())
1187 {
1188 File[] inis = start_d.listFiles(new FilenameFilter()
1189 {
1190 @Override
1191 public boolean accept(File dir, String name)
1192 {
1193 return name.toLowerCase(Locale.ENGLISH).endsWith(".ini");
1194 }
1195 });
1196 Arrays.sort(inis);
1197
1198 for (File i : inis)
1199 args.addAll(loadStartIni(i));
1200
1201 continue;
1202 }
1203 }
1204 catch(Exception e)
1205 {
1206 e.printStackTrace();
1207 }
1208 }
1209
1210 args.add(arg);
1211 }
1212 }
1213 catch (IOException e)
1214 {
1215 usageExit(e,ERR_UNKNOWN);
1216 }
1217 finally
1218 {
1219 Main.close(buf);
1220 Main.close(reader);
1221 }
1222
1223 return args;
1224 }
1225
1226 void addJvmArgs(List<String> jvmArgs)
1227 {
1228 _jvmArgs.addAll(jvmArgs);
1229 }
1230 }