View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
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   * The Arguments required to start Jetty.
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      /** List of enabled modules */
74      private Set<String> modules = new HashSet<>();
75      /** Map of enabled modules to the source of where that activation occurred */
76      private Map<String, List<String>> sources = new HashMap<>();
77      /** Map of properties to where that property was declared */
78      private Map<String, String> propertySource = new HashMap<>();
79      /** List of all active [files] sections from enabled modules */
80      private List<FileArg> files = new ArrayList<>();
81      /** List of all active [lib] sections from enabled modules */
82      private Classpath classpath;
83      /** List of all active [xml] sections from enabled modules */
84      private List<Path> xmls = new ArrayList<>();
85      /** JVM arguments, found via commmand line and in all active [exec] sections from enabled modules */
86      private List<String> jvmArgs = new ArrayList<>();
87  
88      /** List of all xml references found directly on command line or start.ini */
89      private List<String> xmlRefs = new ArrayList<>();
90  
91      /** List of all property references found directly on command line or start.ini */
92      private List<String> propertyFileRefs = new ArrayList<>();
93      
94      /** List of all property files */
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     // jetty.base - build out commands
102     /** --add-to-startd=[module,[module]] */
103     private List<String> addToStartdIni = new ArrayList<>();
104     /** --add-to-start=[module,[module]] */
105     private List<String> addToStartIni = new ArrayList<>();
106 
107     // module inspection commands
108     /** --write-module-graph=[filename] */
109     private String moduleGraphFilename;
110 
111     /** Collection of all modules */
112     private Modules allModules;
113     /** Should the server be run? */
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         // Java Details
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         // Jetty Environment
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         // Jetty Configuration Environment
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         // Jetty Se
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; // skip
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      * Ensure that the System Properties are set (if defined as a System property, or start.config property, or start.ini property)
348      * 
349      * @param key
350      *            the key to be sure of
351      */
352     private void ensureSystemPropertySet(String key)
353     {
354         if (systemPropertyKeys.contains(key))
355         {
356             return; // done
357         }
358 
359         if (properties.containsKey(key))
360         {
361             String val = properties.expand(properties.getString(key));
362             if (val == null)
363             {
364                 return; // no value to set
365             }
366             // setup system property
367             systemPropertyKeys.add(key);
368             System.setProperty(key,val);
369         }
370     }
371 
372     /**
373      * Expand any command line added <code>--lib</code> lib references.
374      * 
375      * @param baseHome
376      * @throws IOException
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             // perform path escaping (needed by windows)
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      * Build up the Classpath and XML file references based on enabled Module list.
399      * 
400      * @param baseHome
401      * @param activeModules
402      * @throws IOException
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             // Find and Expand Libraries
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             // Find and Expand XML files
429             for (String xmlRef : module.getXmls())
430             {
431                 // Straight Reference
432                 Path xmlfile = baseHome.getPath(xmlRef);
433                 addUniqueXmlFile(xmlRef,xmlfile);
434             }
435 
436             // Register Download operations
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             // System Properties
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         // Special Stop/Shutdown properties
510         ensureSystemPropertySet("STOP.PORT");
511         ensureSystemPropertySet("STOP.KEY");
512         ensureSystemPropertySet("STOP.WAIT");
513 
514         // pass properties as args or as a file
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             // ignored keys
580             if ("jetty.home".equals(key) || "jetty.base".equals(key) || "main.class".equals(key))
581             {
582                 // skip
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      * Parse a single line of argument.
675      * 
676      * @param rawarg the raw argument to parse
677      * @param source the origin of this line of argument
678      * @param replaceProps true if properties in this parse replace previous ones, false to not replace.
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             // valid, but handled in StartLog instead
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             // valid, but handled in ConfigSources instead
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         // Enable forked execution of Jetty server
771         if ("--exec".equals(arg))
772         {
773             exec = true;
774             return;
775         }
776 
777         // Enable forked execution of Jetty server
778         if ("--approve-all-licenses".equals(arg))
779         {
780             approveAllLicenses = true;
781             return;
782         }
783 
784         // Arbitrary Libraries
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         // Module Management
801         if ("--list-modules".equals(arg))
802         {
803             listModules = true;
804             run = false;
805             return;
806         }
807 
808         // jetty.base build-out : add to ${jetty.base}/start.d/
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         // jetty.base build-out : add to ${jetty.base}/start.ini
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         // Enable a module
829         if (arg.startsWith("--module="))
830         {
831             List<String> moduleNames = Props.getValues(arg);
832             enableModules(source,moduleNames);
833             return;
834         }
835 
836         // Create graphviz output of module graph
837         if (arg.startsWith("--write-module-graph="))
838         {
839             this.moduleGraphFilename = Props.getValue(arg);
840             run = false;
841             return;
842         }
843 
844         // Start property (syntax similar to System property)
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         // Anything else with a "-" is considered a JVM argument
866         if (arg.startsWith("-"))
867         {
868             // Only add non-duplicates
869             if (!jvmArgs.contains(arg))
870             {
871                 jvmArgs.add(arg);
872             }
873             return;
874         }
875 
876         // Is this a raw property declaration?
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         // Is this an xml file?
908         if (FS.isXml(arg))
909         {
910             // only add non-duplicates
911             if (!xmlRefs.contains(arg))
912             {
913                 xmlRefs.add(arg);
914             }
915             return;
916         }
917         
918         if (FS.isPropertyFile(arg))
919         {
920             // only add non-duplicates
921             if (!propertyFileRefs.contains(arg))
922             {
923                 propertyFileRefs.add(arg);
924             }
925                 return;
926         }
927 
928         // Anything else is unrecognized
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         // Find and Expand XML files
961         for (String xmlRef : xmlRefs)
962         {
963             // Straight Reference
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         // Find and Expand property files
976         for (String propertyFileRef : propertyFileRefs)
977         {
978             // Straight Reference
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         // Special / Prevent override from start.ini's
996         if (key.equals("jetty.home"))
997         {
998             properties.setProperty("jetty.home",System.getProperty("jetty.home"),source);
999             return;
1000         }
1001 
1002         // Special / Prevent override from start.ini's
1003         if (key.equals("jetty.base"))
1004         {
1005             properties.setProperty("jetty.base",System.getProperty("jetty.base"),source);
1006             return;
1007         }
1008 
1009         // Normal
1010         if (replaceProp)
1011         {
1012             // always override
1013             properties.setProperty(key,value,source);
1014         }
1015         else
1016         {
1017             // only set if unset
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 }