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