View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 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.config;
20  
21  import static org.eclipse.jetty.start.UsageException.ERR_BAD_ARG;
22  
23  import java.io.IOException;
24  import java.nio.file.Path;
25  import java.util.Collections;
26  import java.util.Comparator;
27  import java.util.Iterator;
28  import java.util.LinkedList;
29  import java.util.ListIterator;
30  import java.util.concurrent.atomic.AtomicInteger;
31  
32  import org.eclipse.jetty.start.FS;
33  import org.eclipse.jetty.start.Props;
34  import org.eclipse.jetty.start.Props.Prop;
35  import org.eclipse.jetty.start.RawArgs;
36  import org.eclipse.jetty.start.UsageException;
37  
38  /**
39   * Weighted List of ConfigSources.
40   */
41  public class ConfigSources implements Iterable<ConfigSource>
42  {
43      private static class WeightedConfigSourceComparator implements Comparator<ConfigSource>
44      {
45          @Override
46          public int compare(ConfigSource o1, ConfigSource o2)
47          {
48              return o1.getWeight() - o2.getWeight();
49          }
50      }
51  
52      private LinkedList<ConfigSource> sources = new LinkedList<>();
53      private Props props = new Props();
54      private AtomicInteger sourceWeight = new AtomicInteger(1);
55  
56      public void add(ConfigSource source) throws IOException
57      {
58          if (sources.contains(source))
59          {
60              // TODO: needs a better/more clear error message
61              throw new UsageException(ERR_BAD_ARG,"Duplicate Configuration Source Reference: " + source);
62          }
63          sources.add(source);
64  
65          Collections.sort(sources,new WeightedConfigSourceComparator());
66  
67          updateProps();
68  
69          // look for --include-jetty-dir entries
70          for (RawArgs.Entry arg : source.getArgs())
71          {
72              if (arg.startsWith("--include-jetty-dir"))
73              {
74                  String ref = getValue(arg.getLine());
75                  String dirName = props.expand(ref);
76                  Path dir = FS.toPath(dirName).normalize().toAbsolutePath();
77                  DirConfigSource dirsource = new DirConfigSource(ref,dir,sourceWeight.incrementAndGet(),true);
78                  add(dirsource);
79              }
80          }
81      }
82  
83      public CommandLineConfigSource getCommandLineSource()
84      {
85          for (ConfigSource source : sources)
86          {
87              if (source instanceof CommandLineConfigSource)
88              {
89                  return (CommandLineConfigSource)source;
90              }
91          }
92          return null;
93      }
94  
95      public Prop getProp(String key)
96      {
97          return props.getProp(key);
98      }
99  
100     public Props getProps()
101     {
102         return props;
103     }
104 
105     private String getValue(String arg)
106     {
107         int idx = arg.indexOf('=');
108         if (idx == (-1))
109         {
110             throw new UsageException(ERR_BAD_ARG,"Argument is missing a required value: %s",arg);
111         }
112         String value = arg.substring(idx + 1).trim();
113         if (value.length() <= 0)
114         {
115             throw new UsageException(ERR_BAD_ARG,"Argument is missing a required value: %s",arg);
116         }
117         return value;
118     }
119 
120     @Override
121     public Iterator<ConfigSource> iterator()
122     {
123         return sources.iterator();
124     }
125 
126     public ListIterator<ConfigSource> reverseListIterator()
127     {
128         return sources.listIterator(sources.size());
129     }
130 
131     @Override
132     public String toString()
133     {
134         StringBuilder str = new StringBuilder();
135         str.append(this.getClass().getSimpleName());
136         str.append('[');
137         boolean delim = false;
138         for (ConfigSource source : sources)
139         {
140             if (delim)
141             {
142                 str.append(',');
143             }
144             str.append(source.getId());
145             delim = true;
146         }
147         str.append(']');
148         return str.toString();
149     }
150 
151     private void updateProps()
152     {
153         props.reset();
154 
155         // add all properties from config sources (in reverse order)
156         ListIterator<ConfigSource> iter = sources.listIterator(sources.size());
157         while (iter.hasPrevious())
158         {
159             ConfigSource source = iter.previous();
160             props.addAll(source.getProps());
161         }
162     }
163 }