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