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.DirectoryStream;
25  import java.nio.file.Files;
26  import java.nio.file.Path;
27  import java.nio.file.PathMatcher;
28  import java.util.ArrayList;
29  import java.util.Collections;
30  import java.util.List;
31  
32  import org.eclipse.jetty.start.FS;
33  import org.eclipse.jetty.start.NaturalSort;
34  import org.eclipse.jetty.start.PathMatchers;
35  import org.eclipse.jetty.start.Props;
36  import org.eclipse.jetty.start.RawArgs;
37  import org.eclipse.jetty.start.UsageException;
38  import org.eclipse.jetty.start.Props.Prop;
39  import org.eclipse.jetty.start.StartIni;
40  import org.eclipse.jetty.start.StartLog;
41  
42  /**
43   * A Directory based {@link ConfigSource}.
44   * <p>
45   * Such as <code>${jetty.base}</code> or and <code>--include-jetty-dir=[path]</code> sources.
46   */
47  public class DirConfigSource implements ConfigSource
48  {
49      private static final List<String> BANNED_ARGS;
50  
51      static
52      {
53          // Arguments that are not allowed to be in start.ini or start.d/{name}.ini files
54          BANNED_ARGS = new ArrayList<>();
55          BANNED_ARGS.add("--help");
56          BANNED_ARGS.add("-?");
57          BANNED_ARGS.add("--stop");
58          BANNED_ARGS.add("--dry-run");
59          BANNED_ARGS.add("--exec-print");
60          BANNED_ARGS.add("--list-config");
61          BANNED_ARGS.add("--list-classpath");
62          BANNED_ARGS.add("--list-modules");
63          BANNED_ARGS.add("--write-module-graph");
64          BANNED_ARGS.add("--version");
65          BANNED_ARGS.add("-v");
66          BANNED_ARGS.add("--download");
67          BANNED_ARGS.add("--create-files");
68          BANNED_ARGS.add("--add-to-startd");
69          BANNED_ARGS.add("--add-to-start");
70      }
71  
72      private final String id;
73      private final Path dir;
74      private final int weight;
75      private final RawArgs args;
76      private final Props props;
77  
78      /**
79       * Create DirConfigSource with specified identifier and directory.
80       * 
81       * @param id
82       *            the identifier for this {@link ConfigSource}
83       * @param dir
84       *            the directory for this {@link ConfigSource}
85       * @param weight
86       *            the configuration weight (used for search order)
87       * @param canHaveArgs
88       *            true if this directory can have start.ini or start.d entries. (false for directories like ${jetty.home}, for example)
89       * @throws IOException
90       *             if unable to load the configuration args
91       */
92      public DirConfigSource(String id, Path dir, int weight, boolean canHaveArgs) throws IOException
93      {
94          this.id = id;
95          this.dir = dir.toAbsolutePath();
96          this.weight = weight;
97          this.props = new Props();
98  
99          this.args = new RawArgs();
100 
101         if (canHaveArgs)
102         {
103             Path iniFile = dir.resolve("start.ini");
104             if (FS.canReadFile(iniFile))
105             {
106                 StartIni ini = new StartIni(iniFile);
107                 args.addAll(ini.getLines(),iniFile);
108                 parseAllArgs(ini.getLines(),iniFile.toString());
109             }
110 
111             Path startDdir = dir.resolve("start.d");
112 
113             if (FS.canReadDirectory(startDdir))
114             {
115                 DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>()
116                 {
117                     PathMatcher iniMatcher = PathMatchers.getMatcher("glob:**/start.d/*.ini");
118 
119                     @Override
120                     public boolean accept(Path entry) throws IOException
121                     {
122                         return iniMatcher.matches(entry);
123                     }
124                 };
125 
126                 List<Path> paths = new ArrayList<>();
127 
128                 for (Path diniFile : Files.newDirectoryStream(startDdir,filter))
129                 {
130                     if (FS.canReadFile(diniFile))
131                     {
132                         paths.add(diniFile);
133                     }
134                 }
135 
136                 Collections.sort(paths,new NaturalSort.Paths());
137 
138                 for (Path diniFile : paths)
139                 {
140                     StartLog.debug("Reading %s/start.d/%s - %s",id,diniFile.getFileName(),diniFile);
141                     StartIni ini = new StartIni(diniFile);
142                     args.addAll(ini.getLines(),diniFile);
143                     parseAllArgs(ini.getLines(),diniFile.toString());
144                 }
145             }
146         }
147     }
148 
149     private void parseAllArgs(List<String> lines, String origin)
150     {
151         for (String line : lines)
152         {
153             String arg = line;
154             int idx = line.indexOf('=');
155             if (idx > 0)
156             {
157                 arg = line.substring(0,idx);
158             }
159             if (BANNED_ARGS.contains(arg))
160             {
161                 throw new UsageException(ERR_BAD_ARG,"%s not allowed in %s",arg,origin);
162             }
163             this.props.addPossibleProperty(line,origin);
164         }
165     }
166 
167     @Override
168     public boolean equals(Object obj)
169     {
170         if (this == obj)
171         {
172             return true;
173         }
174         if (obj == null)
175         {
176             return false;
177         }
178         if (getClass() != obj.getClass())
179         {
180             return false;
181         }
182         DirConfigSource other = (DirConfigSource)obj;
183         if (dir == null)
184         {
185             if (other.dir != null)
186             {
187                 return false;
188             }
189         }
190         else if (!dir.equals(other.dir))
191         {
192             return false;
193         }
194         return true;
195     }
196 
197     @Override
198     public RawArgs getArgs()
199     {
200         return args;
201     }
202 
203     public Path getDir()
204     {
205         return dir;
206     }
207 
208     @Override
209     public String getId()
210     {
211         return id;
212     }
213 
214     @Override
215     public String getProperty(String key)
216     {
217         Prop prop = props.getProp(key,false);
218         if (prop == null)
219         {
220             return null;
221         }
222         return prop.value;
223     }
224 
225     @Override
226     public Props getProps()
227     {
228         return props;
229     }
230 
231     @Override
232     public int getWeight()
233     {
234         return weight;
235     }
236 
237     @Override
238     public int hashCode()
239     {
240         final int prime = 31;
241         int result = 1;
242         result = (prime * result) + ((dir == null)?0:dir.hashCode());
243         return result;
244     }
245 
246     public boolean isPropertyBased()
247     {
248         return id.contains("${");
249     }
250 
251     @Override
252     public String toString()
253     {
254         return String.format("%s[%s,%s,args.length=%d]",this.getClass().getSimpleName(),id,dir,getArgs().size());
255     }
256 }