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