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.IOException;
22 import java.net.URI;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import org.eclipse.jetty.start.builders.StartDirBuilder;
29 import org.eclipse.jetty.start.builders.StartIniBuilder;
30 import org.eclipse.jetty.start.fileinits.MavenLocalRepoFileInitializer;
31 import org.eclipse.jetty.start.fileinits.TestFileInitializer;
32 import org.eclipse.jetty.start.fileinits.UriFileInitializer;
33 import org.eclipse.jetty.start.graph.CriteriaSetPredicate;
34 import org.eclipse.jetty.start.graph.UniqueCriteriaPredicate;
35 import org.eclipse.jetty.start.graph.Predicate;
36 import org.eclipse.jetty.start.graph.Selection;
37
38
39
40
41
42 public class BaseBuilder
43 {
44 public static interface Config
45 {
46
47
48
49
50
51
52
53
54
55 public boolean addModule(Module module) throws IOException;
56 }
57
58 private static final String EXITING_LICENSE_NOT_ACKNOWLEDGED = "Exiting: license not acknowledged!";
59
60 private final BaseHome baseHome;
61 private final List<FileInitializer> fileInitializers;
62 private final StartArgs startArgs;
63
64 public BaseBuilder(BaseHome baseHome, StartArgs args)
65 {
66 this.baseHome = baseHome;
67 this.startArgs = args;
68 this.fileInitializers = new ArrayList<>();
69
70
71 if (args.isTestingModeEnabled())
72 {
73
74 fileInitializers.add(new TestFileInitializer());
75 }
76 else if (args.isDownload())
77 {
78
79
80 Path localRepoDir = args.getMavenLocalRepoDir();
81 if (localRepoDir != null)
82 {
83
84 fileInitializers.add(new MavenLocalRepoFileInitializer(baseHome,localRepoDir));
85 }
86 else
87 {
88
89 fileInitializers.add(new MavenLocalRepoFileInitializer(baseHome));
90 }
91
92
93 fileInitializers.add(new UriFileInitializer(baseHome));
94 }
95 }
96
97 private void ackLicenses() throws IOException
98 {
99 if (startArgs.isLicenseCheckRequired())
100 {
101 if (startArgs.isApproveAllLicenses())
102 {
103 StartLog.info("All Licenses Approved via Command Line Option");
104 }
105 else
106 {
107 Licensing licensing = new Licensing();
108 for (Module module : startArgs.getAllModules().getSelected())
109 {
110 if (!module.hasFiles(baseHome,startArgs.getProperties()))
111 {
112 licensing.addModule(module);
113 }
114 }
115
116 if (licensing.hasLicenses())
117 {
118 StartLog.debug("Requesting License Acknowledgement");
119 if (!licensing.acknowledgeLicenses())
120 {
121 StartLog.warn(EXITING_LICENSE_NOT_ACKNOWLEDGED);
122 System.exit(1);
123 }
124 }
125 }
126 }
127 }
128
129
130
131
132
133
134
135 public boolean build() throws IOException
136 {
137 Modules modules = startArgs.getAllModules();
138 boolean dirty = false;
139
140 String dirCriteria = "<add-to-startd>";
141 String iniCriteria = "<add-to-start-ini>";
142 Selection startDirSelection = new Selection(dirCriteria);
143 Selection startIniSelection = new Selection(iniCriteria);
144
145 List<String> startDNames = new ArrayList<>();
146 startDNames.addAll(startArgs.getAddToStartdIni());
147 List<String> startIniNames = new ArrayList<>();
148 startIniNames.addAll(startArgs.getAddToStartIni());
149
150 int count = 0;
151 count += modules.selectNodes(startDNames,startDirSelection);
152 count += modules.selectNodes(startIniNames,startIniSelection);
153
154
155 Predicate ambiguousPredicate = new CriteriaSetPredicate(dirCriteria,iniCriteria);
156 List<Module> ambiguous = modules.getMatching(ambiguousPredicate);
157
158 if (ambiguous.size() > 0)
159 {
160 StringBuilder warn = new StringBuilder();
161 warn.append("Ambiguous module locations detected, defaulting to --add-to-start for the following module selections:");
162 warn.append(" [");
163
164 for (int i = 0; i < ambiguous.size(); i++)
165 {
166 if (i > 0)
167 {
168 warn.append(", ");
169 }
170 warn.append(ambiguous.get(i).getName());
171 }
172 warn.append(']');
173 StartLog.warn(warn.toString());
174 }
175
176 StartLog.debug("Adding %s new module(s)",count);
177
178
179 ackLicenses();
180
181
182
183 Predicate startDMatcher = new UniqueCriteriaPredicate(dirCriteria);
184 Predicate startIniMatcher = new UniqueCriteriaPredicate(iniCriteria);
185
186 List<Module> startDModules = modules.getMatching(startDMatcher);
187 List<Module> startIniModules = modules.getMatching(startIniMatcher);
188
189 List<FileArg> files = new ArrayList<FileArg>();
190
191 if (!startDModules.isEmpty())
192 {
193 StartDirBuilder builder = new StartDirBuilder(this);
194 for (Module mod : startDModules)
195 {
196 if (ambiguous.contains(mod))
197 {
198
199 continue;
200 }
201
202 if (mod.isSkipFilesValidation())
203 {
204 StartLog.debug("Skipping [files] validation on %s",mod.getName());
205 }
206 else
207 {
208 dirty |= builder.addModule(mod);
209 for (String file : mod.getFiles())
210 {
211 files.add(new FileArg(mod,startArgs.getProperties().expand(file)));
212 }
213 }
214 }
215 }
216
217 if (!startIniModules.isEmpty())
218 {
219 StartIniBuilder builder = new StartIniBuilder(this);
220 for (Module mod : startIniModules)
221 {
222 if (mod.isSkipFilesValidation())
223 {
224 StartLog.debug("Skipping [files] validation on %s",mod.getName());
225 }
226 else
227 {
228 dirty |= builder.addModule(mod);
229 for (String file : mod.getFiles())
230 {
231 files.add(new FileArg(mod,startArgs.getProperties().expand(file)));
232 }
233 }
234 }
235 }
236
237
238 files.addAll(startArgs.getFiles());
239 dirty |= processFileResources(files);
240
241 return dirty;
242 }
243
244 public BaseHome getBaseHome()
245 {
246 return baseHome;
247 }
248
249 public StartArgs getStartArgs()
250 {
251 return startArgs;
252 }
253
254
255
256
257
258
259
260
261
262
263
264
265 private boolean processFileResource(FileArg arg, Path file) throws IOException
266 {
267 if (startArgs.isDownload() && (arg.uri != null))
268 {
269
270 if (!file.startsWith(baseHome.getBasePath()))
271 {
272 throw new IOException("For security reasons, Jetty start is unable to process maven file resource not in ${jetty.base} - " + file);
273 }
274
275
276 FS.ensureDirectoryExists(file.getParent());
277
278 URI uri = URI.create(arg.uri);
279
280
281 for (FileInitializer finit : fileInitializers)
282 {
283 if (finit.init(uri,file,arg.location))
284 {
285
286 return true;
287 }
288 }
289
290 return false;
291 }
292 else
293 {
294
295 boolean isDir = arg.location.endsWith("/");
296
297 if (FS.exists(file))
298 {
299
300 if (isDir)
301 {
302 if (!Files.isDirectory(file))
303 {
304 throw new IOException("Invalid: path should be a directory (but isn't): " + file);
305 }
306 if (!FS.canReadDirectory(file))
307 {
308 throw new IOException("Unable to read directory: " + file);
309 }
310 }
311 else
312 {
313 if (!FS.canReadFile(file))
314 {
315 throw new IOException("Unable to read file: " + file);
316 }
317 }
318
319 return false;
320 }
321
322 if (isDir)
323 {
324
325 StartLog.log("MKDIR",baseHome.toShortForm(file));
326 return FS.ensureDirectoryExists(file);
327 }
328 else
329 {
330
331 String shortRef = baseHome.toShortForm(file);
332 if (startArgs.isTestingModeEnabled())
333 {
334 StartLog.log("TESTING MODE","Skipping required file check on: %s",shortRef);
335 return true;
336 }
337
338 StartLog.warn("Missing Required File: %s",baseHome.toShortForm(file));
339 startArgs.setRun(false);
340 if (arg.uri != null)
341 {
342 StartLog.warn(" Can be downloaded From: %s",arg.uri);
343 StartLog.warn(" Run start.jar --create-files to download");
344 }
345
346 return true;
347 }
348 }
349 }
350
351
352
353
354
355
356
357
358
359 private boolean processFileResources(List<FileArg> files) throws IOException
360 {
361 if ((files == null) || (files.isEmpty()))
362 {
363 return false;
364 }
365
366 boolean dirty = false;
367
368 List<String> failures = new ArrayList<String>();
369
370 for (FileArg arg : files)
371 {
372 Path file = baseHome.getBasePath(arg.location);
373 try
374 {
375 dirty |= processFileResource(arg,file);
376 }
377 catch (Throwable t)
378 {
379 StartLog.warn(t);
380 failures.add(String.format("[%s] %s - %s",t.getClass().getSimpleName(),t.getMessage(),file.toAbsolutePath().toString()));
381 }
382 }
383
384 if (!failures.isEmpty())
385 {
386 StringBuilder err = new StringBuilder();
387 err.append("Failed to process all file resources.");
388 for (String failure : failures)
389 {
390 err.append(System.lineSeparator()).append(" - ").append(failure);
391 }
392 StartLog.warn(err.toString());
393
394 throw new RuntimeException(err.toString());
395 }
396
397 return dirty;
398 }
399 }