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