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 java.io.BufferedReader;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.nio.charset.StandardCharsets;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.text.CollationKey;
28 import java.text.Collator;
29 import java.util.ArrayList;
30 import java.util.Comparator;
31 import java.util.List;
32 import java.util.Locale;
33 import java.util.regex.Matcher;
34 import java.util.regex.Pattern;
35
36 import org.eclipse.jetty.start.graph.Node;
37
38
39
40
41 public class Module extends Node<Module>
42 {
43 private static final String VERSION_UNSPECIFIED = "9.2";
44
45 public static class NameComparator implements Comparator<Module>
46 {
47 private Collator collator = Collator.getInstance();
48
49 @Override
50 public int compare(Module o1, Module o2)
51 {
52
53 CollationKey k1 = collator.getCollationKey(o1.fileRef);
54 CollationKey k2 = collator.getCollationKey(o2.fileRef);
55 return k1.compareTo(k2);
56 }
57 }
58
59
60 private Path file;
61
62
63 private String fileRef;
64
65
66 private Version version;
67
68
69 private List<String> xmls;
70
71
72 private List<String> iniTemplate;
73 private boolean hasIniTemplate = false;
74
75
76 private List<String> defaultConfig;
77 private boolean hasDefaultConfig = false;
78
79
80 private List<String> libs;
81
82
83 private List<String> files;
84
85 private boolean skipFilesValidation = false;
86
87
88 private List<String> jvmArgs;
89
90
91 private List<String> license;
92
93 public Module(BaseHome basehome, Path file) throws FileNotFoundException, IOException
94 {
95 super();
96 this.file = file;
97
98
99 this.fileRef = Pattern.compile(".mod$",Pattern.CASE_INSENSITIVE).matcher(file.getFileName().toString()).replaceFirst("");
100 this.setName(fileRef);
101
102 init(basehome);
103 process(basehome);
104 }
105
106 @Override
107 public boolean equals(Object obj)
108 {
109 if (this == obj)
110 {
111 return true;
112 }
113 if (obj == null)
114 {
115 return false;
116 }
117 if (getClass() != obj.getClass())
118 {
119 return false;
120 }
121 Module other = (Module)obj;
122 if (fileRef == null)
123 {
124 if (other.fileRef != null)
125 {
126 return false;
127 }
128 }
129 else if (!fileRef.equals(other.fileRef))
130 {
131 return false;
132 }
133 return true;
134 }
135
136 public void expandProperties(Props props)
137 {
138
139 List<String> parents = new ArrayList<>();
140 for (String parent : getParentNames())
141 {
142 parents.add(props.expand(parent));
143 }
144 setParentNames(parents);
145 }
146
147 public List<String> getDefaultConfig()
148 {
149 return defaultConfig;
150 }
151
152 public List<String> getIniTemplate()
153 {
154 return iniTemplate;
155 }
156
157 public List<String> getFiles()
158 {
159 return files;
160 }
161
162 public boolean isSkipFilesValidation()
163 {
164 return skipFilesValidation;
165 }
166
167 public String getFilesystemRef()
168 {
169 return fileRef;
170 }
171
172 public List<String> getJvmArgs()
173 {
174 return jvmArgs;
175 }
176
177 public List<String> getLibs()
178 {
179 return libs;
180 }
181
182 public List<String> getLicense()
183 {
184 return license;
185 }
186
187 public List<String> getXmls()
188 {
189 return xmls;
190 }
191
192 public Version getVersion()
193 {
194 return version;
195 }
196
197 public boolean hasDefaultConfig()
198 {
199 return hasDefaultConfig;
200 }
201
202 public boolean hasIniTemplate()
203 {
204 return hasIniTemplate;
205 }
206
207 @Override
208 public int hashCode()
209 {
210 final int prime = 31;
211 int result = 1;
212 result = (prime * result) + ((fileRef == null)?0:fileRef.hashCode());
213 return result;
214 }
215
216 public boolean hasLicense()
217 {
218 return (license != null) && (license.size() > 0);
219 }
220
221 private void init(BaseHome basehome)
222 {
223 xmls = new ArrayList<>();
224 defaultConfig = new ArrayList<>();
225 iniTemplate = new ArrayList<>();
226 libs = new ArrayList<>();
227 files = new ArrayList<>();
228 jvmArgs = new ArrayList<>();
229 license = new ArrayList<>();
230
231 String name = basehome.toShortForm(file);
232
233
234 Pattern pat = Pattern.compile("^.*[/\\\\]{1}modules[/\\\\]{1}(.*).mod$",Pattern.CASE_INSENSITIVE);
235 Matcher mat = pat.matcher(name);
236 if (!mat.find())
237 {
238 throw new RuntimeException("Invalid Module location (must be located under /modules/ directory): " + name);
239 }
240 this.fileRef = mat.group(1).replace('\\','/');
241 setName(this.fileRef);
242 }
243
244
245
246
247
248
249 public boolean isDynamic()
250 {
251 return !getName().equals(fileRef);
252 }
253
254 public boolean hasFiles(BaseHome baseHome, Props props)
255 {
256 for (String ref : getFiles())
257 {
258 FileArg farg = new FileArg(this,props.expand(ref));
259 Path refPath = baseHome.getBasePath(farg.location);
260 if (!Files.exists(refPath))
261 {
262 return false;
263 }
264 }
265 return true;
266 }
267
268 public void process(BaseHome basehome) throws FileNotFoundException, IOException
269 {
270 Pattern section = Pattern.compile("\\s*\\[([^]]*)\\]\\s*");
271
272 if (!FS.canReadFile(file))
273 {
274 StartLog.debug("Skipping read of missing file: %s",basehome.toShortForm(file));
275 return;
276 }
277
278 try (BufferedReader buf = Files.newBufferedReader(file,StandardCharsets.UTF_8))
279 {
280 String sectionType = "";
281 String line;
282 while ((line = buf.readLine()) != null)
283 {
284 line = line.trim();
285
286 Matcher sectionMatcher = section.matcher(line);
287
288 if (sectionMatcher.matches())
289 {
290 sectionType = sectionMatcher.group(1).trim().toUpperCase(Locale.ENGLISH);
291 }
292 else
293 {
294
295 if ((line.length() == 0) || line.startsWith("#"))
296 {
297
298
299 if ("INI-TEMPLATE".equals(sectionType))
300 {
301 iniTemplate.add(line);
302 hasIniTemplate = true;
303 }
304 }
305 else
306 {
307 switch (sectionType)
308 {
309 case "":
310
311 break;
312 case "DEPEND":
313 addParentName(line);
314 break;
315 case "FILES":
316 files.add(line);
317 break;
318 case "DEFAULTS":
319 case "INI":
320 defaultConfig.add(line);
321 hasDefaultConfig = true;
322 break;
323 case "INI-TEMPLATE":
324 iniTemplate.add(line);
325 hasIniTemplate = true;
326 break;
327 case "LIB":
328 libs.add(line);
329 break;
330 case "LICENSE":
331 case "LICENCE":
332 license.add(line);
333 break;
334 case "NAME":
335 setName(line);
336 break;
337 case "OPTIONAL":
338 addOptionalParentName(line);
339 break;
340 case "EXEC":
341 jvmArgs.add(line);
342 break;
343 case "VERSION":
344 if (version != null)
345 {
346 throw new IOException("[version] already specified");
347 }
348 version = new Version(line);
349 break;
350 case "XML":
351 xmls.add(line);
352 break;
353 default:
354 throw new IOException("Unrecognized Module section: [" + sectionType + "]");
355 }
356 }
357 }
358 }
359 }
360
361 if (version == null)
362 {
363 version = new Version(VERSION_UNSPECIFIED);
364 }
365 }
366
367 public void setEnabled(boolean enabled)
368 {
369 throw new RuntimeException("Don't enable directly");
370 }
371
372 public void setSkipFilesValidation(boolean skipFilesValidation)
373 {
374 this.skipFilesValidation = skipFilesValidation;
375 }
376
377 @Override
378 public String toString()
379 {
380 StringBuilder str = new StringBuilder();
381 str.append("Module[").append(getName());
382 if (isDynamic())
383 {
384 str.append(",file=").append(fileRef);
385 }
386 if (isSelected())
387 {
388 str.append(",selected");
389 }
390 str.append(']');
391 return str.toString();
392 }
393 }