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 static org.eclipse.jetty.start.UsageException.*;
22
23 import java.io.File;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.nio.file.Path;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.ListIterator;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.StringTokenizer;
36
37 import org.eclipse.jetty.start.Props.Prop;
38 import org.eclipse.jetty.start.config.ConfigSource;
39 import org.eclipse.jetty.start.config.ConfigSources;
40 import org.eclipse.jetty.start.config.DirConfigSource;
41
42
43
44
45 public class StartArgs
46 {
47 public static final String VERSION;
48
49 static
50 {
51 String ver = System.getProperty("jetty.version",null);
52
53 if (ver == null)
54 {
55 Package pkg = StartArgs.class.getPackage();
56 if ((pkg != null) && "Eclipse.org - Jetty".equals(pkg.getImplementationVendor()) && (pkg.getImplementationVersion() != null))
57 {
58 ver = pkg.getImplementationVersion();
59 }
60 }
61
62 if (ver == null)
63 {
64 ver = "TEST";
65 }
66
67 VERSION = ver;
68 System.setProperty("jetty.version",VERSION);
69 }
70
71 private static final String SERVER_MAIN = "org.eclipse.jetty.xml.XmlConfiguration";
72
73
74 private Set<String> modules = new HashSet<>();
75
76 private Map<String, List<String>> sources = new HashMap<>();
77
78 private Map<String, String> propertySource = new HashMap<>();
79
80 private List<FileArg> files = new ArrayList<>();
81
82 private Classpath classpath;
83
84 private List<Path> xmls = new ArrayList<>();
85
86 private List<String> jvmArgs = new ArrayList<>();
87
88
89 private List<String> xmlRefs = new ArrayList<>();
90
91
92 private List<String> propertyFileRefs = new ArrayList<>();
93
94
95 private List<Path> propertyFiles = new ArrayList<>();
96
97 private Props properties = new Props();
98 private Set<String> systemPropertyKeys = new HashSet<>();
99 private List<String> rawLibs = new ArrayList<>();
100
101
102
103 private List<String> addToStartdIni = new ArrayList<>();
104
105 private List<String> addToStartIni = new ArrayList<>();
106
107
108
109 private String moduleGraphFilename;
110
111
112 private Modules allModules;
113
114 private boolean run = true;
115 private boolean download = false;
116 private boolean help = false;
117 private boolean stopCommand = false;
118 private boolean listModules = false;
119 private boolean listClasspath = false;
120 private boolean listConfig = false;
121 private boolean version = false;
122 private boolean dryRun = false;
123
124 private boolean exec = false;
125
126 public StartArgs()
127 {
128 classpath = new Classpath();
129 }
130
131 private void addFile(String uriLocation)
132 {
133 FileArg arg = new FileArg(uriLocation);
134 if (!files.contains(arg))
135 {
136 files.add(arg);
137 }
138 }
139
140 public void addSystemProperty(String key, String value)
141 {
142 this.systemPropertyKeys.add(key);
143 System.setProperty(key,value);
144 }
145
146 private void addUniqueXmlFile(String xmlRef, Path xmlfile) throws IOException
147 {
148 if (!FS.canReadFile(xmlfile))
149 {
150 throw new IOException("Cannot read file: " + xmlRef);
151 }
152 xmlfile = FS.toRealPath(xmlfile);
153 if (!xmls.contains(xmlfile))
154 {
155 xmls.add(xmlfile);
156 }
157 }
158
159 private void addUniquePropertyFile(String propertyFileRef, Path propertyFile) throws IOException
160 {
161 if (!FS.canReadFile(propertyFile))
162 {
163 throw new IOException("Cannot read file: " + propertyFileRef);
164 }
165 propertyFile = FS.toRealPath(propertyFile);
166 if (!propertyFiles.contains(propertyFile))
167 {
168 propertyFiles.add(propertyFile);
169 }
170 }
171
172 public void dumpActiveXmls(BaseHome baseHome)
173 {
174 System.out.println();
175 System.out.println("Jetty Active XMLs:");
176 System.out.println("------------------");
177 if (xmls.isEmpty())
178 {
179 System.out.println(" (no xml files specified)");
180 return;
181 }
182
183 for (Path xml : xmls)
184 {
185 System.out.printf(" %s%n",baseHome.toShortForm(xml.toAbsolutePath()));
186 }
187 }
188
189 public void dumpEnvironment(BaseHome baseHome)
190 {
191
192 System.out.println();
193 System.out.println("Java Environment:");
194 System.out.println("-----------------");
195 dumpSystemProperty("java.home");
196 dumpSystemProperty("java.vm.vendor");
197 dumpSystemProperty("java.vm.version");
198 dumpSystemProperty("java.vm.name");
199 dumpSystemProperty("java.vm.info");
200 dumpSystemProperty("java.runtime.name");
201 dumpSystemProperty("java.runtime.version");
202 dumpSystemProperty("java.io.tmpdir");
203 dumpSystemProperty("user.dir");
204 dumpSystemProperty("user.language");
205 dumpSystemProperty("user.country");
206
207
208 System.out.println();
209 System.out.println("Jetty Environment:");
210 System.out.println("-----------------");
211 dumpProperty("jetty.version");
212 dumpProperty("jetty.home");
213 dumpProperty("jetty.base");
214
215
216 System.out.println();
217 System.out.println("Config Search Order:");
218 System.out.println("--------------------");
219 for (ConfigSource config : baseHome.getConfigSources())
220 {
221 System.out.printf(" %s",config.getId());
222 if (config instanceof DirConfigSource)
223 {
224 DirConfigSource dirsource = (DirConfigSource)config;
225 if (dirsource.isPropertyBased())
226 {
227 System.out.printf(" -> %s",dirsource.getDir());
228 }
229 }
230 System.out.println();
231 }
232
233
234 System.out.println();
235 }
236
237 public void dumpJvmArgs()
238 {
239 System.out.println();
240 System.out.println("JVM Arguments:");
241 System.out.println("--------------");
242 if (jvmArgs.isEmpty())
243 {
244 System.out.println(" (no jvm args specified)");
245 return;
246 }
247
248 for (String jvmArgKey : jvmArgs)
249 {
250 String value = System.getProperty(jvmArgKey);
251 if (value != null)
252 {
253 System.out.printf(" %s = %s%n",jvmArgKey,value);
254 }
255 else
256 {
257 System.out.printf(" %s%n",jvmArgKey);
258 }
259 }
260 }
261
262 public void dumpProperties()
263 {
264 System.out.println();
265 System.out.println("Properties:");
266 System.out.println("-----------");
267
268 List<String> sortedKeys = new ArrayList<>();
269 for (Prop prop : properties)
270 {
271 if (prop.origin.equals(Props.ORIGIN_SYSPROP))
272 {
273 continue;
274 }
275 sortedKeys.add(prop.key);
276 }
277
278 if (sortedKeys.isEmpty())
279 {
280 System.out.println(" (no properties specified)");
281 return;
282 }
283
284 Collections.sort(sortedKeys);
285
286 for (String key : sortedKeys)
287 {
288 dumpProperty(key);
289 }
290 }
291
292 private void dumpProperty(String key)
293 {
294 Prop prop = properties.getProp(key);
295 if (prop == null)
296 {
297 System.out.printf(" %s (not defined)%n",key);
298 }
299 else
300 {
301 System.out.printf(" %s = %s%n",key,properties.expand(prop.value));
302 if (StartLog.isDebugEnabled())
303 {
304 System.out.printf(" origin: %s%n",prop.origin);
305 while (prop.overrides != null)
306 {
307 prop = prop.overrides;
308 System.out.printf(" (overrides)%n");
309 System.out.printf(" %s = %s%n",key,properties.expand(prop.value));
310 System.out.printf(" origin: %s%n",prop.origin);
311 }
312 }
313 }
314 }
315
316 public void dumpSystemProperties()
317 {
318 System.out.println();
319 System.out.println("System Properties:");
320 System.out.println("------------------");
321
322 if (systemPropertyKeys.isEmpty())
323 {
324 System.out.println(" (no system properties specified)");
325 return;
326 }
327
328 List<String> sortedKeys = new ArrayList<>();
329 sortedKeys.addAll(systemPropertyKeys);
330 Collections.sort(sortedKeys);
331
332 for (String key : sortedKeys)
333 {
334 String value = System.getProperty(key);
335 System.out.printf(" %s = %s%n",key,properties.expand(value));
336 }
337 }
338
339 private void dumpSystemProperty(String key)
340 {
341 System.out.printf(" %s = %s%n",key,System.getProperty(key));
342 }
343
344
345
346
347
348
349
350 private void ensureSystemPropertySet(String key)
351 {
352 if (systemPropertyKeys.contains(key))
353 {
354 return;
355 }
356
357 if (properties.containsKey(key))
358 {
359 String val = properties.expand(properties.getString(key));
360 if (val == null)
361 {
362 return;
363 }
364
365 systemPropertyKeys.add(key);
366 System.setProperty(key,val);
367 }
368 }
369
370
371
372
373
374
375
376 public void expandLibs(BaseHome baseHome) throws IOException
377 {
378 for (String rawlibref : rawLibs)
379 {
380 StartLog.debug("rawlibref = " + rawlibref);
381 String libref = properties.expand(rawlibref);
382 StartLog.debug("expanded = " + libref);
383
384
385 libref = libref.replaceAll("\\\\([^\\\\])","\\\\\\\\$1");
386
387 for (Path libpath : baseHome.getPaths(libref))
388 {
389 classpath.addComponent(libpath.toFile());
390 }
391 }
392 }
393
394
395
396
397
398
399
400
401 public void expandModules(BaseHome baseHome, List<Module> activeModules) throws IOException
402 {
403 for (Module module : activeModules)
404 {
405
406 for (String rawlibref : module.getLibs())
407 {
408 StartLog.debug("rawlibref = " + rawlibref);
409 String libref = properties.expand(rawlibref);
410 StartLog.debug("expanded = " + libref);
411
412 for (Path libpath : baseHome.getPaths(libref))
413 {
414 classpath.addComponent(libpath.toFile());
415 }
416 }
417
418 for (String jvmArg : module.getJvmArgs())
419 {
420 exec = true;
421 jvmArgs.add(jvmArg);
422 }
423
424
425 for (String xmlRef : module.getXmls())
426 {
427
428 Path xmlfile = baseHome.getPath(xmlRef);
429 addUniqueXmlFile(xmlRef,xmlfile);
430 }
431
432
433 for (String file : module.getFiles())
434 {
435 StartLog.debug("Adding module specified file: %s",file);
436 addFile(file);
437 }
438 }
439 }
440
441 public List<String> getAddToStartdIni()
442 {
443 return addToStartdIni;
444 }
445
446 public List<String> getAddToStartIni()
447 {
448 return addToStartIni;
449 }
450
451 public Modules getAllModules()
452 {
453 return allModules;
454 }
455
456 public Classpath getClasspath()
457 {
458 return classpath;
459 }
460
461 public Set<String> getEnabledModules()
462 {
463 return this.modules;
464 }
465
466 public List<FileArg> getFiles()
467 {
468 return files;
469 }
470
471 public List<String> getJvmArgs()
472 {
473 return jvmArgs;
474 }
475
476 public CommandLineBuilder getMainArgs(BaseHome baseHome, boolean addJavaInit) throws IOException
477 {
478 CommandLineBuilder cmd = new CommandLineBuilder();
479
480 if (addJavaInit)
481 {
482 cmd.addRawArg(CommandLineBuilder.findJavaBin());
483
484 for (String x : jvmArgs)
485 {
486 cmd.addRawArg(x);
487 }
488
489 cmd.addRawArg("-Djava.io.tmpdir=" + System.getProperty("java.io.tmpdir"));
490 cmd.addRawArg("-Djetty.home=" + baseHome.getHome());
491 cmd.addRawArg("-Djetty.base=" + baseHome.getBase());
492
493
494 for (String propKey : systemPropertyKeys)
495 {
496 String value = System.getProperty(propKey);
497 cmd.addEqualsArg("-D" + propKey,value);
498 }
499
500 cmd.addRawArg("-cp");
501 cmd.addRawArg(classpath.toString());
502 cmd.addRawArg(getMainClassname());
503 }
504
505
506 ensureSystemPropertySet("STOP.PORT");
507 ensureSystemPropertySet("STOP.KEY");
508 ensureSystemPropertySet("STOP.WAIT");
509
510
511 if (dryRun || isExec())
512 {
513 for (Prop p : properties)
514 cmd.addRawArg(CommandLineBuilder.quote(p.key)+"="+CommandLineBuilder.quote(p.value));
515 }
516 else if (properties.size() > 0)
517 {
518 File prop_file = File.createTempFile("start",".properties");
519 prop_file.deleteOnExit();
520 try (FileOutputStream out = new FileOutputStream(prop_file))
521 {
522 properties.store(out,"start.jar properties");
523 }
524 cmd.addRawArg(prop_file.getAbsolutePath());
525 }
526
527 for (Path xml : xmls)
528 {
529 cmd.addRawArg(xml.toAbsolutePath().toString());
530 }
531
532 for (Path propertyFile : propertyFiles)
533 {
534 cmd.addRawArg(propertyFile.toAbsolutePath().toString());
535 }
536
537 return cmd;
538 }
539
540 public String getMainClassname()
541 {
542 String mainclass = System.getProperty("jetty.server",SERVER_MAIN);
543 return System.getProperty("main.class",mainclass);
544 }
545
546 public String getModuleGraphFilename()
547 {
548 return moduleGraphFilename;
549 }
550
551 public Props getProperties()
552 {
553 return properties;
554 }
555
556 public List<String> getSources(String module)
557 {
558 return sources.get(module);
559 }
560
561 public List<Path> getXmlFiles()
562 {
563 return xmls;
564 }
565
566 public boolean hasJvmArgs()
567 {
568 return jvmArgs.size() > 0;
569 }
570
571 public boolean hasSystemProperties()
572 {
573 for (String key : systemPropertyKeys)
574 {
575
576 if ("jetty.home".equals(key) || "jetty.base".equals(key))
577 {
578
579 continue;
580 }
581 return true;
582 }
583 return false;
584 }
585
586 public boolean isDownload()
587 {
588 return download;
589 }
590
591 public boolean isDryRun()
592 {
593 return dryRun;
594 }
595
596 public boolean isExec()
597 {
598 return exec;
599 }
600
601 public boolean isHelp()
602 {
603 return help;
604 }
605
606 public boolean isListClasspath()
607 {
608 return listClasspath;
609 }
610
611 public boolean isListConfig()
612 {
613 return listConfig;
614 }
615
616 public boolean isListModules()
617 {
618 return listModules;
619 }
620
621 public boolean isRun()
622 {
623 return run;
624 }
625
626 public boolean isStopCommand()
627 {
628 return stopCommand;
629 }
630
631 public boolean isVersion()
632 {
633 return version;
634 }
635
636 public void parse(ConfigSources sources)
637 {
638 ListIterator<ConfigSource> iter = sources.reverseListIterator();
639 while (iter.hasPrevious())
640 {
641 ConfigSource source = iter.previous();
642 for (RawArgs.Entry arg : source.getArgs())
643 {
644 parse(arg.getLine(),arg.getOrigin());
645 }
646 }
647 }
648
649 public void parse(final String rawarg, String source)
650 {
651 if (rawarg == null)
652 {
653 return;
654 }
655
656 final String arg = rawarg.trim();
657
658 if (arg.length() <= 0)
659 {
660 return;
661 }
662
663 if (arg.startsWith("#"))
664 {
665 return;
666 }
667
668 if ("--help".equals(arg) || "-?".equals(arg))
669 {
670 help = true;
671 run = false;
672 return;
673 }
674
675 if ("--debug".equals(arg) || arg.startsWith("--start-log-file"))
676 {
677
678 return;
679 }
680
681 if (arg.startsWith("--include-jetty-dir="))
682 {
683
684 return;
685 }
686
687 if ("--stop".equals(arg))
688 {
689 stopCommand = true;
690 run = false;
691 return;
692 }
693
694 if (arg.startsWith("--download="))
695 {
696 addFile(Props.getValue(arg));
697 run = false;
698 download = true;
699 return;
700 }
701
702 if (arg.equals("--create-files"))
703 {
704 run = false;
705 download = true;
706 return;
707 }
708
709 if ("--list-classpath".equals(arg) || "--version".equals(arg) || "-v".equals(arg) || "--info".equals(arg))
710 {
711 listClasspath = true;
712 run = false;
713 return;
714 }
715
716 if ("--list-config".equals(arg))
717 {
718 listConfig = true;
719 run = false;
720 return;
721 }
722
723 if ("--dry-run".equals(arg) || "--exec-print".equals(arg))
724 {
725 dryRun = true;
726 run = false;
727 return;
728 }
729
730
731 if ("--exec".equals(arg))
732 {
733 exec = true;
734 return;
735 }
736
737
738 if (arg.startsWith("--lib="))
739 {
740 String cp = Props.getValue(arg);
741
742 if (cp != null)
743 {
744 StringTokenizer t = new StringTokenizer(cp,File.pathSeparator);
745 while (t.hasMoreTokens())
746 {
747 rawLibs.add(t.nextToken());
748 }
749 }
750 return;
751 }
752
753
754 if ("--list-modules".equals(arg))
755 {
756 listModules = true;
757 run = false;
758 return;
759 }
760
761
762 if (arg.startsWith("--add-to-startd="))
763 {
764 addToStartdIni.addAll(Props.getValues(arg));
765 run = false;
766 download = true;
767 return;
768 }
769
770
771 if (arg.startsWith("--add-to-start="))
772 {
773 addToStartIni.addAll(Props.getValues(arg));
774 run = false;
775 download = true;
776 return;
777 }
778
779
780 if (arg.startsWith("--module="))
781 {
782 for (String moduleName : Props.getValues(arg))
783 {
784 modules.add(moduleName);
785 List<String> list = sources.get(moduleName);
786 if (list == null)
787 {
788 list = new ArrayList<String>();
789 sources.put(moduleName,list);
790 }
791 list.add(source);
792 }
793 return;
794 }
795
796
797 if (arg.startsWith("--write-module-graph="))
798 {
799 this.moduleGraphFilename = Props.getValue(arg);
800 run = false;
801 return;
802 }
803
804
805 if (arg.startsWith("-D"))
806 {
807 String[] assign = arg.substring(2).split("=",2);
808 systemPropertyKeys.add(assign[0]);
809 switch (assign.length)
810 {
811 case 2:
812 System.setProperty(assign[0],assign[1]);
813 setProperty(assign[0],assign[1],source);
814 break;
815 case 1:
816 System.setProperty(assign[0],"");
817 setProperty(assign[0],"",source);
818 break;
819 default:
820 break;
821 }
822 return;
823 }
824
825
826 if (arg.startsWith("-"))
827 {
828
829 if (!jvmArgs.contains(arg))
830 {
831 jvmArgs.add(arg);
832 }
833 return;
834 }
835
836
837 int idx = arg.indexOf('=');
838 if (idx >= 0)
839 {
840 String key = arg.substring(0,idx);
841 String value = arg.substring(idx + 1);
842
843 if (propertySource.containsKey(key))
844 {
845 StartLog.warn("Property %s in %s already set in %s",key,source,propertySource.get(key));
846 }
847 propertySource.put(key,source);
848
849 if ("OPTION".equals(key) || "OPTIONS".equals(key))
850 {
851 StringBuilder warn = new StringBuilder();
852 warn.append("The behavior of the argument ");
853 warn.append(arg).append(" (seen in ").append(source);
854 warn.append(") has changed, and is now considered a normal property. ");
855 warn.append(key).append(" no longer controls what libraries are on your classpath,");
856 warn.append(" use --module instead. See --help for details.");
857 StartLog.warn(warn.toString());
858 }
859
860 setProperty(key,value,source);
861 return;
862 }
863
864
865 if (FS.isXml(arg))
866 {
867
868 if (!xmlRefs.contains(arg))
869 {
870 xmlRefs.add(arg);
871 }
872 return;
873 }
874
875 if (FS.isPropertyFile(arg))
876 {
877
878 if (!propertyFileRefs.contains(arg))
879 {
880 propertyFileRefs.add(arg);
881 }
882 return;
883 }
884
885
886 throw new UsageException(ERR_BAD_ARG,"Unrecognized argument: \"%s\" in %s",arg,source);
887 }
888
889 public void resolveExtraXmls(BaseHome baseHome) throws IOException
890 {
891
892 for (String xmlRef : xmlRefs)
893 {
894
895 Path xmlfile = baseHome.getPath(xmlRef);
896 if (!FS.exists(xmlfile))
897 {
898 xmlfile = baseHome.getPath("etc/" + xmlRef);
899 }
900 addUniqueXmlFile(xmlRef,xmlfile);
901 }
902 }
903
904 public void resolvePropertyFiles(BaseHome baseHome) throws IOException
905 {
906
907 for (String propertyFileRef : propertyFileRefs)
908 {
909
910 Path propertyFile = baseHome.getPath(propertyFileRef);
911 if (!FS.exists(propertyFile))
912 {
913 propertyFile = baseHome.getPath("etc/" + propertyFileRef);
914 }
915 addUniquePropertyFile(propertyFileRef,propertyFile);
916 }
917 }
918
919 public void setAllModules(Modules allModules)
920 {
921 this.allModules = allModules;
922 }
923
924 private void setProperty(String key, String value, String source)
925 {
926
927 if (key.equals("jetty.home"))
928 {
929 properties.setProperty("jetty.home",System.getProperty("jetty.home"),source);
930 return;
931 }
932
933
934 if (key.equals("jetty.base"))
935 {
936 properties.setProperty("jetty.base",System.getProperty("jetty.base"),source);
937 return;
938 }
939
940
941 properties.setProperty(key,value,source);
942 }
943
944 public void setRun(boolean run)
945 {
946 this.run = run;
947 }
948
949 @Override
950 public String toString()
951 {
952 StringBuilder builder = new StringBuilder();
953 builder.append("StartArgs [enabledModules=");
954 builder.append(modules);
955 builder.append(", xmlRefs=");
956 builder.append(xmlRefs);
957 builder.append(", properties=");
958 builder.append(properties);
959 builder.append(", jvmArgs=");
960 builder.append(jvmArgs);
961 builder.append("]");
962 return builder.toString();
963 }
964 }