1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.jspc.plugin;
20
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.FileFilter;
24 import java.io.FileReader;
25 import java.io.FileWriter;
26 import java.io.IOException;
27 import java.io.PrintWriter;
28 import java.net.URI;
29 import java.net.URL;
30 import java.net.URLClassLoader;
31 import java.util.ArrayList;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Set;
35 import java.util.regex.Pattern;
36
37 import org.apache.jasper.JspC;
38 import org.apache.maven.artifact.Artifact;
39 import org.apache.maven.plugin.AbstractMojo;
40 import org.apache.maven.plugin.MojoExecutionException;
41 import org.apache.maven.plugin.MojoFailureException;
42 import org.apache.maven.project.MavenProject;
43 import org.codehaus.plexus.util.FileUtils;
44 import org.codehaus.plexus.util.StringUtils;
45 import org.eclipse.jetty.util.IO;
46 import org.eclipse.jetty.util.PatternMatcher;
47 import org.eclipse.jetty.util.resource.Resource;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 public class JspcMojo extends AbstractMojo
80 {
81 public static final String END_OF_WEBAPP = "</web-app>";
82
83
84
85
86
87
88
89
90
91 private boolean useProvidedScope;
92
93
94
95
96
97
98
99
100 private Set projectArtifacts;
101
102
103
104
105
106
107
108
109
110 private MavenProject project;
111
112
113
114
115
116
117
118
119
120 private List pluginArtifacts;
121
122
123
124
125
126
127
128
129 private String webXmlFragment;
130
131
132
133
134
135
136
137
138
139
140 private String insertionMarker;
141
142
143
144
145
146
147
148
149 private boolean mergeFragment;
150
151
152
153
154
155
156 private String generatedClasses;
157
158
159
160
161
162
163
164 private boolean keepSources;
165
166
167
168
169
170
171
172
173 private String webAppSourceDirectory;
174
175
176
177
178
179
180
181 private String webXml;
182
183
184
185
186
187
188
189
190 private String includes;
191
192
193
194
195
196
197 private String excludes;
198
199
200
201
202
203
204 private File classesDirectory;
205
206
207
208
209
210
211
212 private String tldJarNamePatterns;
213
214
215
216
217
218
219
220
221 private JspC jspc;
222
223
224
225
226
227 public void execute() throws MojoExecutionException, MojoFailureException
228 {
229 if (getLog().isDebugEnabled())
230 {
231
232 getLog().info("webAppSourceDirectory=" + webAppSourceDirectory);
233 getLog().info("generatedClasses=" + generatedClasses);
234 getLog().info("webXmlFragment=" + webXmlFragment);
235 getLog().info("webXml="+webXml);
236 getLog().info("insertionMarker="+ (insertionMarker == null || insertionMarker.equals("") ? END_OF_WEBAPP : insertionMarker));
237 getLog().info("keepSources=" + keepSources);
238 getLog().info("mergeFragment=" + mergeFragment);
239 }
240 try
241 {
242 prepare();
243 compile();
244 cleanupSrcs();
245 mergeWebXml();
246 }
247 catch (Exception e)
248 {
249 throw new MojoExecutionException("Failure processing jsps", e);
250 }
251 }
252
253 public void compile() throws Exception
254 {
255 ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
256
257
258 List<URL> webAppUrls = setUpWebAppClassPath();
259
260
261 String sysClassPath = setUpSysClassPath();
262
263
264 List<URL> tldJarUrls = getSystemJarsWithTlds();
265
266 for (URL u:tldJarUrls)
267 {
268 if (getLog().isDebugEnabled())
269 getLog().debug(" sys jar with tlds: "+u);
270 webAppUrls.add(u);
271 }
272
273
274
275 URLClassLoader webAppClassLoader = new URLClassLoader((URL[]) webAppUrls.toArray(new URL[0]), currentClassLoader);
276 StringBuffer webAppClassPath = new StringBuffer();
277
278 for (int i = 0; i < webAppUrls.size(); i++)
279 {
280 if (getLog().isDebugEnabled())
281 getLog().debug("webappclassloader contains: " + webAppUrls.get(i));
282 webAppClassPath.append(new File(webAppUrls.get(i).toURI()).getCanonicalPath());
283 if (getLog().isDebugEnabled())
284 getLog().debug("added to classpath: " + ((URL) webAppUrls.get(i)).getFile());
285 if (i+1<webAppUrls.size())
286 webAppClassPath.append(System.getProperty("path.separator"));
287 }
288
289 Thread.currentThread().setContextClassLoader(webAppClassLoader);
290
291 if (jspc == null)
292 jspc = new JspC();
293
294 jspc.setWebXmlFragment(webXmlFragment);
295 jspc.setUriroot(webAppSourceDirectory);
296 jspc.setOutputDir(generatedClasses);
297 jspc.setClassPath(webAppClassPath.toString());
298 jspc.setCompile(true);
299 jspc.setSystemClassPath(sysClassPath);
300
301
302
303
304 String jspFiles = getJspFiles(webAppSourceDirectory);
305 getLog().info("Compiling "+jspFiles);
306 getLog().info("Includes="+includes);
307 getLog().info("Excludes="+excludes);
308 jspc.setJspFiles(jspFiles);
309
310 getLog().info("Files selected to precompile: " + jspFiles);
311
312 jspc.execute();
313
314 Thread.currentThread().setContextClassLoader(currentClassLoader);
315 }
316
317 private String getJspFiles(String webAppSourceDirectory)
318 throws Exception
319 {
320 List fileNames = FileUtils.getFileNames(new File(webAppSourceDirectory),includes, excludes, false);
321 return StringUtils.join(fileNames.toArray(new String[0]), ",");
322
323 }
324
325
326
327
328
329
330
331 public void cleanupSrcs() throws Exception
332 {
333
334 if (!keepSources)
335 {
336 File generatedClassesDir = new File(generatedClasses);
337
338 if(generatedClassesDir.exists() && generatedClassesDir.isDirectory())
339 {
340 delete(generatedClassesDir, new FileFilter()
341 {
342 public boolean accept(File f)
343 {
344 return f.isDirectory() || f.getName().endsWith(".java");
345 }
346 });
347 }
348 }
349 }
350
351 static void delete(File dir, FileFilter filter)
352 {
353 File[] files = dir.listFiles(filter);
354 if (files != null)
355 {
356 for(File f: files)
357 {
358 if(f.isDirectory())
359 delete(f, filter);
360 else
361 f.delete();
362 }
363 }
364 }
365
366
367
368
369
370
371
372
373
374
375
376
377 public void mergeWebXml() throws Exception
378 {
379 if (mergeFragment)
380 {
381
382 File webXml = getWebXmlFile();
383
384 if (!webXml.exists())
385 {
386 getLog().info(webXml.toString() + " does not exist, cannot merge with generated fragment");
387 return;
388 }
389
390 File fragmentWebXml = new File(webXmlFragment);
391 if (!fragmentWebXml.exists())
392 {
393 getLog().info("No fragment web.xml file generated");
394 }
395 File mergedWebXml = new File(fragmentWebXml.getParentFile(),
396 "web.xml");
397 try (BufferedReader webXmlReader = new BufferedReader(new FileReader(
398 webXml));
399 PrintWriter mergedWebXmlWriter = new PrintWriter(new FileWriter(
400 mergedWebXml))) {
401
402
403
404 boolean atInsertPoint = false;
405 boolean atEOF = false;
406 String marker = (insertionMarker == null
407 || insertionMarker.equals("") ? END_OF_WEBAPP : insertionMarker);
408 while (!atInsertPoint && !atEOF)
409 {
410 String line = webXmlReader.readLine();
411 if (line == null)
412 atEOF = true;
413 else if (line.indexOf(marker) >= 0)
414 {
415 atInsertPoint = true;
416 }
417 else
418 {
419 mergedWebXmlWriter.println(line);
420 }
421 }
422
423
424 try (BufferedReader fragmentWebXmlReader = new BufferedReader(
425 new FileReader(fragmentWebXml))) {
426 IO.copy(fragmentWebXmlReader, mergedWebXmlWriter);
427
428
429 if (marker.equals(END_OF_WEBAPP))
430 mergedWebXmlWriter.println(END_OF_WEBAPP);
431
432
433 IO.copy(webXmlReader, mergedWebXmlWriter);
434 }
435 }
436 }
437 }
438
439 private void prepare() throws Exception
440 {
441
442
443 File generatedSourceDirectoryFile = new File(generatedClasses);
444 if (!generatedSourceDirectoryFile.exists())
445 generatedSourceDirectoryFile.mkdirs();
446 }
447
448
449
450
451
452
453
454
455
456
457 private List<URL> setUpWebAppClassPath() throws Exception
458 {
459
460 List<URL> urls = new ArrayList<URL>();
461 String classesDir = classesDirectory.getCanonicalPath();
462 classesDir = classesDir + (classesDir.endsWith(File.pathSeparator) ? "" : File.separator);
463 urls.add(Resource.toURL(new File(classesDir)));
464
465 if (getLog().isDebugEnabled())
466 getLog().debug("Adding to classpath classes dir: " + classesDir);
467
468
469 for (Iterator<Artifact> iter = project.getArtifacts().iterator(); iter.hasNext();)
470 {
471 Artifact artifact = (Artifact)iter.next();
472
473
474 if (!Artifact.SCOPE_TEST.equals(artifact.getScope()) && !Artifact.SCOPE_PROVIDED.equals(artifact.getScope()))
475 {
476 String filePath = artifact.getFile().getCanonicalPath();
477 if (getLog().isDebugEnabled())
478 getLog().debug("Adding to classpath dependency file: " + filePath);
479
480 urls.add(Resource.toURL(artifact.getFile()));
481 }
482 }
483 return urls;
484 }
485
486
487 private String setUpSysClassPath () throws Exception
488 {
489 StringBuffer buff = new StringBuffer();
490
491
492 for (Iterator<Artifact> iter = pluginArtifacts.iterator(); iter.hasNext(); )
493 {
494 Artifact pluginArtifact = iter.next();
495 if ("jar".equalsIgnoreCase(pluginArtifact.getType()))
496 {
497 if (getLog().isDebugEnabled()) { getLog().debug("Adding plugin artifact "+pluginArtifact);}
498 buff.append(pluginArtifact.getFile().getAbsolutePath());
499 if (iter.hasNext())
500 buff.append(File.pathSeparator);
501 }
502 }
503
504
505 if (useProvidedScope)
506 {
507 for ( Iterator<Artifact> iter = projectArtifacts.iterator(); iter.hasNext(); )
508 {
509 Artifact artifact = iter.next();
510 if (Artifact.SCOPE_PROVIDED.equals(artifact.getScope()))
511 {
512
513 String path = artifact.getFile().getAbsolutePath();
514 if (! buff.toString().contains(path))
515 {
516 if (buff.length() != 0)
517 buff.append(File.pathSeparator);
518 buff.append(path);
519 if (getLog().isDebugEnabled()) { getLog().debug("Adding provided artifact: "+artifact);}
520 }
521 else
522 {
523 if (getLog().isDebugEnabled()) { getLog().debug("Skipping provided artifact: "+artifact);}
524 }
525 }
526 }
527 }
528
529 return buff.toString();
530 }
531
532
533
534
535
536
537
538
539
540
541
542 private List<URL> getSystemJarsWithTlds() throws Exception
543 {
544 final List<URL> list = new ArrayList<URL>();
545 List<URI> artifactUris = new ArrayList<URI>();
546 Pattern pattern = Pattern.compile(tldJarNamePatterns);
547 for (Iterator<Artifact> iter = pluginArtifacts.iterator(); iter.hasNext(); )
548 {
549 Artifact pluginArtifact = iter.next();
550 artifactUris.add(Resource.newResource(pluginArtifact.getFile()).getURI());
551 }
552
553 PatternMatcher matcher = new PatternMatcher()
554 {
555 public void matched(URI uri) throws Exception
556 {
557
558 list.add(uri.toURL());
559 }
560 };
561 matcher.match(pattern, artifactUris.toArray(new URI[artifactUris.size()]), false);
562
563 return list;
564 }
565
566 private File getWebXmlFile ()
567 throws IOException
568 {
569 File file = null;
570 File baseDir = project.getBasedir().getCanonicalFile();
571 File defaultWebAppSrcDir = new File (baseDir, "src/main/webapp").getCanonicalFile();
572 File webAppSrcDir = new File (webAppSourceDirectory).getCanonicalFile();
573 File defaultWebXml = new File (defaultWebAppSrcDir, "web.xml").getCanonicalFile();
574
575
576 File webXmlFile = new File (webXml).getCanonicalFile();
577 if (webXmlFile.compareTo(defaultWebXml) != 0)
578 {
579 file = new File (webXml);
580 return file;
581 }
582
583
584
585 file = new File (webAppSrcDir, "web.xml");
586 return file;
587 }
588 }