1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 package org.jomc.mojo;
34
35 import java.io.BufferedReader;
36 import java.io.File;
37 import java.io.IOException;
38 import java.io.StringReader;
39 import java.io.StringWriter;
40 import java.net.URL;
41 import java.net.URLClassLoader;
42 import java.text.MessageFormat;
43 import java.util.Collection;
44 import java.util.HashSet;
45 import java.util.Iterator;
46 import java.util.LinkedList;
47 import java.util.ResourceBundle;
48 import java.util.Set;
49 import java.util.logging.Level;
50 import javax.xml.bind.JAXBException;
51 import javax.xml.bind.Marshaller;
52 import javax.xml.transform.ErrorListener;
53 import javax.xml.transform.Transformer;
54 import javax.xml.transform.TransformerConfigurationException;
55 import javax.xml.transform.TransformerException;
56 import javax.xml.transform.TransformerFactory;
57 import javax.xml.transform.stream.StreamSource;
58 import org.apache.maven.artifact.Artifact;
59 import org.apache.maven.plugin.AbstractMojo;
60 import org.apache.maven.plugin.MojoExecutionException;
61 import org.apache.maven.plugin.MojoFailureException;
62 import org.apache.maven.project.MavenProject;
63 import org.jomc.model.DefaultModelProvider;
64 import org.jomc.model.ModelContext;
65 import org.jomc.model.ModelException;
66 import org.jomc.model.ModelValidationReport;
67 import org.jomc.model.Module;
68 import org.jomc.model.Modules;
69 import org.jomc.tools.JavaClasses;
70 import org.jomc.tools.JavaSources;
71 import org.jomc.tools.JomcTool;
72
73
74
75
76
77
78
79 public abstract class AbstractJomcMojo extends AbstractMojo
80 {
81
82
83
84
85
86
87 private String sourceEncoding;
88
89
90
91
92
93
94 private String templateEncoding;
95
96
97
98
99
100
101 private String templateProfile;
102
103
104
105
106
107
108 private String moduleLocation;
109
110
111
112
113
114
115
116 private MavenProject mavenProject;
117
118
119
120
121
122
123 private boolean verbose;
124
125
126
127
128
129
130 private boolean javaSourceProcessingEnabled;
131
132
133
134
135
136
137 private boolean javaClassProcessingEnabled;
138
139
140 private JavaSources javaSourcesTool;
141
142
143 private JavaClasses javaClassesTool;
144
145
146 private ClassLoader mainClassLoader;
147
148
149 private ClassLoader testClassLoader;
150
151 public void execute() throws MojoExecutionException, MojoFailureException
152 {
153 try
154 {
155 this.logSeparator( Level.INFO );
156 this.log( Level.INFO, this.getMessage( "title" ).format( null ), null );
157 this.logSeparator( Level.INFO );
158 this.executeTool();
159 }
160 catch ( final Exception e )
161 {
162 throw new MojoExecutionException( e.getMessage(), e );
163 }
164 }
165
166
167
168
169
170
171
172 protected abstract String getToolName() throws MojoExecutionException;
173
174
175
176
177
178
179
180
181 protected abstract ClassLoader getToolClassLoader() throws MojoExecutionException;
182
183
184
185
186
187
188 protected abstract void executeTool() throws Exception;
189
190
191
192
193
194
195
196
197 protected ModelContext getModelContext() throws MojoExecutionException
198 {
199 try
200 {
201 final ModelContext context = ModelContext.createModelContext( this.getToolClassLoader() );
202 this.setupModelContext( context );
203 return context;
204 }
205 catch ( final ModelException e )
206 {
207 throw new MojoExecutionException( e.getMessage(), e );
208 }
209 }
210
211
212
213
214
215
216
217
218 protected MavenProject getMavenProject() throws MojoExecutionException
219 {
220 return this.mavenProject;
221 }
222
223
224
225
226
227
228
229
230 protected JavaSources getJavaSourcesTool() throws MojoExecutionException
231 {
232 if ( this.javaSourcesTool == null )
233 {
234 this.javaSourcesTool = new JavaSources();
235 this.setupJomcTool( this.javaSourcesTool );
236 }
237
238 return this.javaSourcesTool;
239 }
240
241
242
243
244
245
246
247
248 protected JavaClasses getJavaClassesTool() throws MojoExecutionException
249 {
250 if ( this.javaClassesTool == null )
251 {
252 this.javaClassesTool = new JavaClasses();
253 this.setupJomcTool( this.javaClassesTool );
254 }
255
256 return this.javaClassesTool;
257 }
258
259
260
261
262
263
264
265
266 protected ClassLoader getMainClassLoader() throws MojoExecutionException
267 {
268 try
269 {
270 if ( this.mainClassLoader == null )
271 {
272 final Collection urls = new LinkedList();
273 for ( final Iterator it = this.getMainClasspathElements().iterator(); it.hasNext(); )
274 {
275 final String element = (String) it.next();
276 final URL url = new File( element ).toURI().toURL();
277 if ( !urls.contains( url ) )
278 {
279 urls.add( url );
280 this.log( Level.FINE, this.getClasspathElementMessage( url.toExternalForm() ), null );
281 }
282 }
283
284 this.mainClassLoader = new URLClassLoader( (URL[]) urls.toArray( new URL[ urls.size() ] ),
285 Thread.currentThread().getContextClassLoader() );
286
287 }
288
289 return this.mainClassLoader;
290 }
291 catch ( final IOException e )
292 {
293 throw new MojoExecutionException( e.getMessage(), e );
294 }
295 }
296
297
298
299
300
301
302
303
304 protected ClassLoader getTestClassLoader() throws MojoExecutionException
305 {
306 try
307 {
308 if ( this.testClassLoader == null )
309 {
310 final Collection urls = new LinkedList();
311 for ( final Iterator it = this.getTestClasspathElements().iterator(); it.hasNext(); )
312 {
313 final String element = (String) it.next();
314 final URL url = new File( element ).toURI().toURL();
315 if ( !urls.contains( url ) )
316 {
317 urls.add( url );
318 this.log( Level.FINE, this.getClasspathElementMessage( url.toExternalForm() ), null );
319 }
320 }
321
322 this.testClassLoader = new URLClassLoader( (URL[]) urls.toArray( new URL[ urls.size() ] ),
323 Thread.currentThread().getContextClassLoader() );
324
325 }
326
327 return this.testClassLoader;
328 }
329 catch ( final IOException e )
330 {
331 throw new MojoExecutionException( e.getMessage(), e );
332 }
333 }
334
335
336
337
338
339
340
341
342 protected Set getMainClasspathElements() throws MojoExecutionException
343 {
344 final Set elements = new HashSet();
345 elements.add( this.getMavenProject().getBuild().getOutputDirectory() );
346
347 for ( final Iterator it = this.getMavenProject().getRuntimeArtifacts().iterator(); it.hasNext(); )
348 {
349 final Artifact a = (Artifact) it.next();
350
351 if ( a.getFile() == null )
352 {
353 this.log( Level.WARNING, this.getIgnoredMessage( a.toString() ), null );
354 continue;
355 }
356
357 if ( a.getGroupId().equals( "org.jomc" ) &&
358 ( a.getArtifactId().equals( "jomc-util" ) || a.getArtifactId().equals( "jomc-model" ) ||
359 a.getArtifactId().equals( "jomc-tools" ) ) )
360 {
361 continue;
362 }
363
364 final String element = a.getFile().getAbsolutePath();
365 this.log( Level.FINE, this.getRuntimeElementMessage( element ), null );
366 elements.add( element );
367 }
368
369 for ( final Iterator it = this.getMavenProject().getCompileArtifacts().iterator(); it.hasNext(); )
370 {
371 final Artifact a = (Artifact) it.next();
372
373 if ( a.getFile() == null )
374 {
375 this.log( Level.WARNING, this.getIgnoredMessage( a.toString() ), null );
376 continue;
377 }
378
379 if ( a.getGroupId().equals( "org.jomc" ) &&
380 ( a.getArtifactId().equals( "jomc-util" ) || a.getArtifactId().equals( "jomc-model" ) ||
381 a.getArtifactId().equals( "jomc-tools" ) ) )
382 {
383 continue;
384 }
385
386 final String element = a.getFile().getAbsolutePath();
387 this.log( Level.FINE, this.getCompileElementMessage( element ), null );
388 elements.add( element );
389 }
390
391 return elements;
392 }
393
394
395
396
397
398
399
400
401 protected Set getTestClasspathElements() throws MojoExecutionException
402 {
403 final Set elements = new HashSet();
404
405 elements.add( this.getMavenProject().getBuild().getOutputDirectory() );
406 elements.add( this.getMavenProject().getBuild().getTestOutputDirectory() );
407
408 for ( final Iterator it = this.getMavenProject().getTestArtifacts().iterator(); it.hasNext(); )
409 {
410 final Artifact a = (Artifact) it.next();
411
412 if ( a.getFile() == null )
413 {
414 this.log( Level.WARNING, this.getIgnoredMessage( a.toString() ), null );
415 continue;
416 }
417
418 if ( a.getGroupId().equals( "org.jomc" ) &&
419 ( a.getArtifactId().equals( "jomc-util" ) || a.getArtifactId().equals( "jomc-model" ) ||
420 a.getArtifactId().equals( "jomc-tools" ) ) )
421 {
422 continue;
423 }
424
425 final String element = a.getFile().getAbsolutePath();
426 this.log( Level.FINE, this.getTestElementMessage( element ), null );
427 elements.add( element );
428 }
429
430 return elements;
431 }
432
433
434
435
436
437
438 protected boolean isJavaSourceProcessingEnabled()
439 {
440 return this.javaSourceProcessingEnabled;
441 }
442
443
444
445
446
447
448 protected boolean isJavaClassProcessingEnabled()
449 {
450 return this.javaClassProcessingEnabled;
451 }
452
453
454
455
456
457
458
459
460 protected String getJomcModuleName() throws MojoExecutionException
461 {
462 return this.getMavenProject().getName();
463 }
464
465
466
467
468
469
470
471
472 protected String getJomcTestModuleName() throws MojoExecutionException
473 {
474 return this.getMavenProject().getName() + " Tests";
475 }
476
477
478
479
480
481
482
483
484
485
486
487
488 protected Transformer getTransformer( final File file ) throws MojoExecutionException
489 {
490 if ( file == null )
491 {
492 throw new NullPointerException( "file" );
493 }
494
495 try
496 {
497 final TransformerFactory transformerFactory = TransformerFactory.newInstance();
498 transformerFactory.setErrorListener( new ErrorListener()
499 {
500
501 public void warning( final TransformerException exception ) throws TransformerException
502 {
503 getLog().warn( exception );
504 }
505
506 public void error( final TransformerException exception ) throws TransformerException
507 {
508 getLog().error( exception );
509 throw exception;
510 }
511
512 public void fatalError( final TransformerException exception ) throws TransformerException
513 {
514 getLog().error( exception );
515 throw exception;
516 }
517
518 } );
519
520 return transformerFactory.newTransformer( new StreamSource( file ) );
521 }
522 catch ( final TransformerConfigurationException e )
523 {
524 throw new MojoExecutionException( e.getMessage(), e );
525 }
526 }
527
528 protected Modules getToolModules() throws MojoExecutionException
529 {
530 try
531 {
532 DefaultModelProvider.setDefaultModuleLocation( this.moduleLocation );
533 final Modules modules = this.getModelContext().findModules();
534 final Module classpathModule = modules.getClasspathModule(
535 Modules.getDefaultClasspathModuleName(), this.getToolClassLoader() );
536
537 if ( classpathModule != null )
538 {
539 modules.getModule().add( classpathModule );
540 }
541
542 return modules;
543 }
544 catch ( final ModelException e )
545 {
546 throw new MojoExecutionException( e.getMessage(), e );
547 }
548 }
549
550 protected void logSeparator( final Level level ) throws MojoExecutionException
551 {
552 this.log( level, this.getMessage( "separator" ).format( null ), null );
553 }
554
555 protected void logProcessingModule( final Module module ) throws MojoExecutionException
556 {
557 this.log( Level.INFO, this.getProcessingModuleMesage( module ), null );
558 }
559
560 protected void logMissingModule( final String moduleName ) throws MojoExecutionException
561 {
562 this.log( Level.WARNING, this.getMissingModuleMesage( moduleName ), null );
563 }
564
565 protected void logToolSuccess() throws MojoExecutionException
566 {
567 this.log( Level.INFO, this.getToolSuccessMessage(), null );
568 }
569
570 protected void log( final Level level, final ModelValidationReport report ) throws MojoExecutionException
571 {
572 try
573 {
574 if ( !report.isModelValid() || !report.getDetails().isEmpty() )
575 {
576 this.logSeparator( level );
577 }
578
579 if ( !report.isModelValid() )
580 {
581 this.log( level, this.getMessage( "invalidModel" ).format( null ), null );
582 }
583
584 if ( !report.getDetails().isEmpty() )
585 {
586 final Marshaller marshaller = this.getModelContext().createMarshaller();
587
588 for ( ModelValidationReport.Detail detail : report.getDetails() )
589 {
590 this.log( detail.getLevel(), System.getProperty( "line.separator" ), null );
591 this.log( detail.getLevel(), detail.getMessage(), null );
592
593 if ( detail.getElement() != null )
594 {
595 final StringWriter stringWriter = new StringWriter();
596 marshaller.marshal( detail.getElement(), stringWriter );
597 this.log( Level.FINE, stringWriter.toString(), null );
598 }
599 }
600 }
601
602 if ( !report.isModelValid() || !report.getDetails().isEmpty() )
603 {
604 this.logSeparator( level );
605 }
606 }
607 catch ( final ModelException e )
608 {
609 throw new MojoExecutionException( e.getMessage(), e );
610 }
611 catch ( final JAXBException e )
612 {
613 throw new MojoExecutionException( e.getMessage(), e );
614 }
615 }
616
617 protected void log( final Level level, final String message, final Throwable throwable )
618 {
619 try
620 {
621 if ( level.intValue() < Level.INFO.intValue() || level.intValue() >= Level.WARNING.intValue() ||
622 this.verbose )
623 {
624 String line;
625 final BufferedReader reader = new BufferedReader( new StringReader( message ) );
626 while ( ( line = reader.readLine() ) != null )
627 {
628 final String mojoMessage = "[JOMC] " + line;
629
630 if ( ( level.equals( Level.CONFIG ) || level.equals( Level.FINE ) || level.equals( Level.FINER ) ||
631 level.equals( Level.FINEST ) ) && this.getLog().isDebugEnabled() )
632 {
633 this.getLog().debug( mojoMessage, throwable );
634 }
635 else if ( level.equals( Level.INFO ) && this.getLog().isInfoEnabled() )
636 {
637 this.getLog().info( mojoMessage, throwable );
638 }
639 else if ( level.equals( Level.SEVERE ) && this.getLog().isErrorEnabled() )
640 {
641 this.getLog().error( mojoMessage, throwable );
642 }
643 else if ( level.equals( Level.WARNING ) && this.getLog().isWarnEnabled() )
644 {
645 this.getLog().warn( mojoMessage, throwable );
646 }
647 else if ( this.getLog().isDebugEnabled() )
648 {
649 this.getLog().debug( mojoMessage, throwable );
650 }
651 }
652 }
653 }
654 catch ( final IOException e )
655 {
656 this.getLog().error( e );
657 throw new AssertionError( e );
658 }
659 }
660
661 private void setupJomcTool( final JomcTool tool ) throws MojoExecutionException
662 {
663 if ( this.verbose || this.getLog().isDebugEnabled() )
664 {
665 tool.setLogLevel( this.getLog().isDebugEnabled() ? Level.ALL : Level.INFO );
666 }
667
668 tool.getListeners().add( new JomcTool.Listener()
669 {
670
671 public void onLog( final Level level, final String message, final Throwable t )
672 {
673 log( level, message, t );
674 }
675
676 } );
677
678 tool.setTemplateEncoding( this.templateEncoding );
679 tool.setInputEncoding( this.sourceEncoding );
680 tool.setOutputEncoding( this.sourceEncoding );
681 tool.setProfile( this.templateProfile );
682 tool.setModules( this.getToolModules() );
683 }
684
685 private void setupModelContext( final ModelContext modelContext )
686 {
687 if ( this.verbose || this.getLog().isDebugEnabled() )
688 {
689 modelContext.setLogLevel( this.getLog().isDebugEnabled() ? Level.ALL : Level.INFO );
690 }
691
692 modelContext.getListeners().add( new ModelContext.Listener()
693 {
694
695 public void onLog( final Level level, final String message, final Throwable t )
696 {
697 log( level, message, t );
698 }
699
700 } );
701 }
702
703 private MessageFormat getMessage( final String key )
704 {
705 return new MessageFormat( ResourceBundle.getBundle( AbstractJomcMojo.class.getName().replace( '.', '/' ) ).
706 getString( key ) );
707
708 }
709
710 private String getIgnoredMessage( final String item )
711 {
712 return this.getMessage( "ignored" ).format( new Object[]
713 {
714 item
715 } );
716
717 }
718
719 private String getRuntimeElementMessage( final String element )
720 {
721 return this.getMessage( "runtimeElement" ).format( new Object[]
722 {
723 element
724 } );
725
726 }
727
728 private String getTestElementMessage( final String element )
729 {
730 return this.getMessage( "testElement" ).format( new Object[]
731 {
732 element
733 } );
734
735 }
736
737 private String getCompileElementMessage( final String element )
738 {
739 return this.getMessage( "compiletimeElement" ).format( new Object[]
740 {
741 element
742 } );
743
744 }
745
746 private String getClasspathElementMessage( final String element )
747 {
748 return this.getMessage( "classpathElement" ).format( new Object[]
749 {
750 element
751 } );
752
753 }
754
755 private String getProcessingModuleMesage( final Module module ) throws MojoExecutionException
756 {
757 return this.getMessage( "processingModule" ).format( new Object[]
758 {
759 this.getToolName(), module.getName()
760 } );
761
762 }
763
764 private String getToolSuccessMessage() throws MojoExecutionException
765 {
766 return this.getMessage( "toolSuccess" ).format( new Object[]
767 {
768 this.getToolName()
769 } );
770
771 }
772
773 private String getMissingModuleMesage( final String moduleName )
774 {
775 return this.getMessage( "missingModule" ).format( new Object[]
776 {
777 moduleName
778 } );
779
780 }
781
782 }