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("-Djetty.home=" + baseHome.getHome());
490 cmd.addRawArg("-Djetty.base=" + baseHome.getBase());
491
492
493 for (String propKey : systemPropertyKeys)
494 {
495 String value = System.getProperty(propKey);
496 cmd.addEqualsArg("-D" + propKey,value);
497 }
498
499 cmd.addRawArg("-cp");
500 cmd.addRawArg(classpath.toString());
501 cmd.addRawArg(getMainClassname());
502 }
503
504
505 ensureSystemPropertySet("STOP.PORT");
506 ensureSystemPropertySet("STOP.KEY");
507 ensureSystemPropertySet("STOP.WAIT");
508
509
510 if (properties.size() > 0)
511 {
512 File prop_file = File.createTempFile("start",".properties");
513 if (!dryRun)
514 {
515 prop_file.deleteOnExit();
516 }
517 try (FileOutputStream out = new FileOutputStream(prop_file))
518 {
519 properties.store(out,"start.jar properties");
520 }
521 cmd.addRawArg(prop_file.getAbsolutePath());
522 }
523
524 for (Path xml : xmls)
525 {
526 cmd.addRawArg(xml.toAbsolutePath().toString());
527 }
528
529 for (Path propertyFile : propertyFiles)
530 {
531 cmd.addRawArg(propertyFile.toAbsolutePath().toString());
532 }
533
534 return cmd;
535 }
536
537 public String getMainClassname()
538 {
539 String mainclass = System.getProperty("jetty.server",SERVER_MAIN);
540 return System.getProperty("main.class",mainclass);
541 }
542
543 public String getModuleGraphFilename()
544 {
545 return moduleGraphFilename;
546 }
547
548 public Props getProperties()
549 {
550 return properties;
551 }
552
553 public List<String> getSources(String module)
554 {
555 return sources.get(module);
556 }
557
558 public List<Path> getXmlFiles()
559 {
560 return xmls;
561 }
562
563 public boolean hasJvmArgs()
564 {
565 return jvmArgs.size() > 0;
566 }
567
568 public boolean hasSystemProperties()
569 {
570 for (String key : systemPropertyKeys)
571 {
572
573 if ("jetty.home".equals(key) || "jetty.base".equals(key))
574 {
575
576 continue;
577 }
578 return true;
579 }
580 return false;
581 }
582
583 public boolean isDownload()
584 {
585 return download;
586 }
587
588 public boolean isDryRun()
589 {
590 return dryRun;
591 }
592
593 public boolean isExec()
594 {
595 return exec;
596 }
597
598 public boolean isHelp()
599 {
600 return help;
601 }
602
603 public boolean isListClasspath()
604 {
605 return listClasspath;
606 }
607
608 public boolean isListConfig()
609 {
610 return listConfig;
611 }
612
613 public boolean isListModules()
614 {
615 return listModules;
616 }
617
618 public boolean isRun()
619 {
620 return run;
621 }
622
623 public boolean isStopCommand()
624 {
625 return stopCommand;
626 }
627
628 public boolean isVersion()
629 {
630 return version;
631 }
632
633 public void parse(ConfigSources sources)
634 {
635 ListIterator<ConfigSource> iter = sources.reverseListIterator();
636 while (iter.hasPrevious())
637 {
638 ConfigSource source = iter.previous();
639 for (String arg : source.getArgs())
640 {
641 parse(arg,source.getId());
642 }
643 }
644 }
645
646 public void parse(final String rawarg, String source)
647 {
648 if (rawarg == null)
649 {
650 return;
651 }
652
653 final String arg = rawarg.trim();
654
655 if (arg.length() <= 0)
656 {
657 return;
658 }
659
660 if (arg.startsWith("#"))
661 {
662 return;
663 }
664
665 if ("--help".equals(arg) || "-?".equals(arg))
666 {
667 help = true;
668 run = false;
669 return;
670 }
671
672 if ("--debug".equals(arg) || arg.startsWith("--start-log-file"))
673 {
674
675 return;
676 }
677
678 if (arg.startsWith("--include-jetty-dir="))
679 {
680
681 return;
682 }
683
684 if ("--stop".equals(arg))
685 {
686 stopCommand = true;
687 run = false;
688 return;
689 }
690
691 if (arg.startsWith("--download="))
692 {
693 addFile(Props.getValue(arg));
694 run = false;
695 download = true;
696 return;
697 }
698
699 if (arg.equals("--create-files"))
700 {
701 run = false;
702 download = true;
703 return;
704 }
705
706 if ("--list-classpath".equals(arg) || "--version".equals(arg) || "-v".equals(arg) || "--info".equals(arg))
707 {
708 listClasspath = true;
709 run = false;
710 return;
711 }
712
713 if ("--list-config".equals(arg))
714 {
715 listConfig = true;
716 run = false;
717 return;
718 }
719
720 if ("--dry-run".equals(arg) || "--exec-print".equals(arg))
721 {
722 dryRun = true;
723 run = false;
724 return;
725 }
726
727
728 if ("--exec".equals(arg))
729 {
730 exec = true;
731 return;
732 }
733
734
735 if (arg.startsWith("--lib="))
736 {
737 String cp = Props.getValue(arg);
738
739 if (cp != null)
740 {
741 StringTokenizer t = new StringTokenizer(cp,File.pathSeparator);
742 while (t.hasMoreTokens())
743 {
744 rawLibs.add(t.nextToken());
745 }
746 }
747 return;
748 }
749
750
751 if ("--list-modules".equals(arg))
752 {
753 listModules = true;
754 run = false;
755 return;
756 }
757
758
759 if (arg.startsWith("--add-to-startd="))
760 {
761 addToStartdIni.addAll(Props.getValues(arg));
762 run = false;
763 download = true;
764 return;
765 }
766
767
768 if (arg.startsWith("--add-to-start="))
769 {
770 addToStartIni.addAll(Props.getValues(arg));
771 run = false;
772 download = true;
773 return;
774 }
775
776
777 if (arg.startsWith("--module="))
778 {
779 for (String moduleName : Props.getValues(arg))
780 {
781 modules.add(moduleName);
782 List<String> list = sources.get(moduleName);
783 if (list == null)
784 {
785 list = new ArrayList<String>();
786 sources.put(moduleName,list);
787 }
788 list.add(source);
789 }
790 return;
791 }
792
793
794 if (arg.startsWith("--write-module-graph="))
795 {
796 this.moduleGraphFilename = Props.getValue(arg);
797 run = false;
798 return;
799 }
800
801
802 if (arg.startsWith("-D"))
803 {
804 String[] assign = arg.substring(2).split("=",2);
805 systemPropertyKeys.add(assign[0]);
806 switch (assign.length)
807 {
808 case 2:
809 System.setProperty(assign[0],assign[1]);
810 setProperty(assign[0],assign[1],source);
811 break;
812 case 1:
813 System.setProperty(assign[0],"");
814 setProperty(assign[0],"",source);
815 break;
816 default:
817 break;
818 }
819 return;
820 }
821
822
823 if (arg.startsWith("-"))
824 {
825
826 if (!jvmArgs.contains(arg))
827 {
828 jvmArgs.add(arg);
829 }
830 return;
831 }
832
833
834 int idx = arg.indexOf('=');
835 if (idx >= 0)
836 {
837 String key = arg.substring(0,idx);
838 String value = arg.substring(idx + 1);
839
840 if (propertySource.containsKey(key))
841 {
842 StartLog.warn("Property %s in %s already set in %s",key,source,propertySource.get(key));
843 }
844 propertySource.put(key,source);
845
846 if ("OPTION".equals(key) || "OPTIONS".equals(key))
847 {
848 StringBuilder warn = new StringBuilder();
849 warn.append("The behavior of the argument ");
850 warn.append(arg).append(" (seen in ").append(source);
851 warn.append(") has changed, and is now considered a normal property. ");
852 warn.append(key).append(" no longer controls what libraries are on your classpath,");
853 warn.append(" use --module instead. See --help for details.");
854 StartLog.warn(warn.toString());
855 }
856
857 setProperty(key,value,source);
858 return;
859 }
860
861
862 if (FS.isXml(arg))
863 {
864
865 if (!xmlRefs.contains(arg))
866 {
867 xmlRefs.add(arg);
868 }
869 return;
870 }
871
872 if (FS.isPropertyFile(arg))
873 {
874
875 if (!propertyFileRefs.contains(arg))
876 {
877 propertyFileRefs.add(arg);
878 }
879 return;
880 }
881
882
883 throw new UsageException(ERR_BAD_ARG,"Unrecognized argument: \"%s\" in %s",arg,source);
884 }
885
886 public void resolveExtraXmls(BaseHome baseHome) throws IOException
887 {
888
889 for (String xmlRef : xmlRefs)
890 {
891
892 Path xmlfile = baseHome.getPath(xmlRef);
893 if (!FS.exists(xmlfile))
894 {
895 xmlfile = baseHome.getPath("etc/" + xmlRef);
896 }
897 addUniqueXmlFile(xmlRef,xmlfile);
898 }
899 }
900
901 public void resolvePropertyFiles(BaseHome baseHome) throws IOException
902 {
903
904 for (String propertyFileRef : propertyFileRefs)
905 {
906
907 Path propertyFile = baseHome.getPath(propertyFileRef);
908 if (!FS.exists(propertyFile))
909 {
910 propertyFile = baseHome.getPath("etc/" + propertyFileRef);
911 }
912 addUniquePropertyFile(propertyFileRef,propertyFile);
913 }
914 }
915
916 public void setAllModules(Modules allModules)
917 {
918 this.allModules = allModules;
919 }
920
921 private void setProperty(String key, String value, String source)
922 {
923
924 if (key.equals("jetty.home"))
925 {
926 properties.setProperty("jetty.home",System.getProperty("jetty.home"),source);
927 return;
928 }
929
930
931 if (key.equals("jetty.base"))
932 {
933 properties.setProperty("jetty.base",System.getProperty("jetty.base"),source);
934 return;
935 }
936
937
938 properties.setProperty(key,value,source);
939 }
940
941 public void setRun(boolean run)
942 {
943 this.run = run;
944 }
945
946 @Override
947 public String toString()
948 {
949 StringBuilder builder = new StringBuilder();
950 builder.append("StartArgs [enabledModules=");
951 builder.append(modules);
952 builder.append(", xmlRefs=");
953 builder.append(xmlRefs);
954 builder.append(", properties=");
955 builder.append(properties);
956 builder.append(", jvmArgs=");
957 builder.append(jvmArgs);
958 builder.append("]");
959 return builder.toString();
960 }
961 }