1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codehaus.mojo.castor;
17
18 import java.io.File;
19 import java.io.FileNotFoundException;
20 import java.io.IOException;
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.Set;
26
27 import org.apache.maven.model.Resource;
28 import org.apache.maven.plugin.AbstractMojo;
29 import org.apache.maven.plugin.MojoExecutionException;
30 import org.apache.maven.plugins.annotations.LifecyclePhase;
31 import org.apache.maven.plugins.annotations.Mojo;
32 import org.apache.maven.plugins.annotations.Parameter;
33 import org.apache.maven.project.MavenProject;
34 import org.codehaus.plexus.compiler.util.scan.InclusionScanException;
35 import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
36 import org.codehaus.plexus.compiler.util.scan.StaleSourceScanner;
37 import org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping;
38 import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping;
39 import org.codehaus.plexus.util.FileUtils;
40 import org.exolab.castor.builder.conflictresolution.WarningViaDialogClassNameCRStrategy;
41 import org.exolab.castor.util.Version;
42
43
44
45
46
47
48
49
50 @Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
51 public class GenerateMojo extends AbstractMojo
52 {
53
54
55
56
57 private static final String DISABLE_DESCRIPTORS_MSG = "Disabling generation of Class descriptors";
58
59
60
61
62 private static final String DISABLE_MARSHALL_MSG =
63 "Disabling generation of Marshalling framework methods (marshall, unmarshall, validate).";
64
65
66
67
68 private static final String DEFAULT_PROPERTY_FILE_LOCATION = "src/main/castor/castorbuilder.properties";
69
70
71
72
73 @Parameter(property = "bindingFile", defaultValue = "${basedir}/src/main/castor/bindings.xml")
74 private File bindingfile;
75
76
77
78
79 @Parameter(property = "schema")
80 private File schema;
81
82
83
84
85 @Parameter(property = "schemaDirectory", defaultValue = "${basedir}/src/main/castor")
86 private File schemaDirectory;
87
88
89
90
91
92
93 @Parameter(property = "dest", defaultValue = "${project.build.directory}/generated-sources/castor")
94 private File dest;
95
96
97
98
99
100
101
102 @Parameter(property = "tstamp", defaultValue = "${project.build.directory}/xsds")
103 private File tstamp;
104
105
106
107
108 @Parameter(property = "staleMillis", defaultValue = "0")
109 private int staleMillis = 0;
110
111
112
113
114
115
116
117 @Parameter(property = "types", defaultValue = "arraylist")
118 private String types = "arraylist";
119
120
121
122
123 @Parameter(property = "descriptors", defaultValue = "true")
124 private boolean descriptors = true;
125
126
127
128
129 @Parameter(property = "verbose", defaultValue = "false")
130 private boolean verbose = false;
131
132
133
134
135 @Parameter(property = "warnings", defaultValue = "false")
136 private boolean warnings = false;
137
138
139
140
141 @Parameter(property = "marshal", defaultValue = "true")
142 private boolean marshal = true;
143
144
145
146
147
148
149 @Parameter(property = "lineSeparator")
150 private String lineSeparator;
151
152
153
154
155 @Parameter(property = "properties", defaultValue = "${basedir}/src/main/castor/castorbuilder.properties")
156 private File properties;
157
158
159
160
161 @Parameter(property = "packaging")
162 private String packaging;
163
164
165
166
167
168 @Parameter(property = "nameConflictStrategy", defaultValue = WarningViaDialogClassNameCRStrategy.NAME)
169 private String nameConflictStrategy = WarningViaDialogClassNameCRStrategy.NAME;
170
171
172
173
174 @Parameter(property = "generateImportedSchemas", defaultValue = "false")
175 private boolean generateImportedSchemas = false;
176
177
178
179
180
181 @Parameter(property = "generateMappings", defaultValue = "false")
182 private boolean generateMappings = false;
183
184
185
186
187
188
189 @Parameter(property = "classGenerationMode", defaultValue = "standard")
190 private String classGenerationMode = "standard";
191
192
193
194
195 @Parameter(property = "resourceDestination", defaultValue = "${project.build.directory}/generated-sources/castor")
196 private File resourceDestination;
197
198
199
200
201 @Parameter(property = "createJdoDescriptors", defaultValue = "false")
202 private boolean createJdoDescriptors = false;
203
204
205
206
207
208
209 @Parameter(property = "project", defaultValue = "${project}", required = true)
210 private MavenProject project;
211
212
213
214
215
216
217 private CastorSourceGenerator sgen;
218
219
220
221
222
223
224 public void execute()
225 throws MojoExecutionException
226 {
227
228 if ( !dest.exists() )
229 {
230 FileUtils.mkdir( dest.getAbsolutePath() );
231 }
232
233 if ( !resourceDestination.exists() )
234 {
235 FileUtils.mkdir( resourceDestination.getAbsolutePath() );
236 }
237
238 Set<File> staleXSDs = computeStaleXSDs();
239
240 if ( staleXSDs.isEmpty() )
241 {
242 getLog().info( "Nothing to process - all xsds are up to date" );
243
244
245 project.addCompileSourceRoot( dest.getAbsolutePath() );
246
247
248 getLog().info( "Adding resource " + getResourceDestination().getAbsolutePath() + " ... " );
249 Resource resource = new Resource();
250 resource.setDirectory( getResourceDestination().getAbsolutePath() );
251 resource.addInclude( "**/*.cdr" );
252 resource.addExclude( "**/*.java" );
253 project.addResource( resource );
254
255 return;
256 }
257
258 config();
259
260 for ( Iterator<File> i = staleXSDs.iterator(); i.hasNext(); )
261 {
262 File xsd = (File) i.next();
263
264 try
265 {
266
267 processFile( xsd.getCanonicalPath() );
268
269
270 File timeStampDir = getTimeStampDirectory();
271
272
273 FileUtils.copyFileToDirectory( xsd, timeStampDir );
274 }
275 catch ( Exception e )
276 {
277 throw new MojoExecutionException( "Castor execution failed", e );
278 }
279 catch ( Throwable t )
280 {
281 throw new MojoExecutionException( "Castor execution failed", t );
282 }
283 }
284
285 if ( project != null )
286 {
287 project.addCompileSourceRoot( dest.getAbsolutePath() );
288
289
290 getLog().info( "Adding resource " + getResourceDestination().getAbsolutePath() + " ... " );
291 Resource resource = new Resource();
292 resource.setDirectory( getResourceDestination().getAbsolutePath() );
293 resource.addInclude( "**/*.cdr" );
294 resource.addExclude( "**/*.java" );
295 project.addResource( resource );
296 }
297
298 }
299
300
301
302
303
304
305
306 private Set<File> computeStaleXSDs()
307 throws MojoExecutionException
308 {
309 Set<File> staleSources = new HashSet<File>();
310
311 if ( schema != null && schema.exists() )
312 {
313 File sourceFile = schema;
314 File targetFile = new File( getTimeStampDirectory(), sourceFile.getName() );
315 if ( !targetFile.exists() || ( targetFile.lastModified() + staleMillis < sourceFile.lastModified() ) )
316 {
317 getLog().debug( "Finding XSDs - adding schema " + targetFile );
318 staleSources.add( sourceFile );
319 }
320 else
321 {
322 getLog().debug( "Finding XSDs - adding schema " + targetFile );
323 }
324 }
325 else
326 {
327 SourceMapping mapping = new SuffixMapping( ".xsd", ".xsd" );
328
329 File tstampDir = getTimeStampDirectory();
330
331 File schemaDir = schemaDirectory;
332
333 SourceInclusionScanner scanner = getSourceInclusionScanner();
334
335 scanner.addSourceMapping( mapping );
336
337 try
338 {
339 getLog().debug(
340 "Finding XSDs - adding scanned XSDs from schemaDir " + schemaDir + " tstampDir "
341 + tstampDir );
342 staleSources.addAll( scanner.getIncludedSources( schemaDir, tstampDir ) );
343 }
344 catch ( InclusionScanException e )
345 {
346 throw new MojoExecutionException( "Error scanning source root: \'" + schemaDir
347 + "\' for stale xsds to reprocess.", e );
348 }
349 }
350
351 return staleSources;
352 }
353
354
355
356
357
358
359 private SourceInclusionScanner getSourceInclusionScanner()
360 {
361 return new StaleSourceScanner( staleMillis );
362 }
363
364
365
366
367
368
369 private File getTimeStampDirectory()
370 {
371 return tstamp;
372 }
373
374
375
376
377
378
379 private void config()
380 throws MojoExecutionException
381 {
382 sgen = CastorSourceGenerator.createSourceGenerator( types );
383
384 if ( getLog().isInfoEnabled() )
385 {
386 getLog().info(
387 "Successfully created an instance of the Castor XML source generator, release "
388 + Version.VERSION );
389 }
390
391 sgen.setLog( getLog() );
392
393 sgen.setLineSeparatorStyle( lineSeparator );
394
395 sgen.setDestDir( dest.getAbsolutePath() );
396
397 callSetterMethodUsingReflection( "setResourceDestination", String.class,
398 getResourceDestination().getAbsolutePath() );
399
400 if ( bindingfile != null && bindingfile.exists() )
401 {
402 sgen.setBindingFile( bindingfile );
403 }
404
405 sgen.setVerbose( verbose );
406
407 sgen.setSuppressNonFatalWarnings( !warnings );
408
409 sgen.setDescriptorCreation( descriptors );
410 if ( !descriptors )
411 {
412 log( DISABLE_DESCRIPTORS_MSG );
413 }
414
415 sgen.setCreateMarshalMethods( marshal );
416 if ( !marshal )
417 {
418 log( DISABLE_MARSHALL_MSG );
419 }
420
421 if ( properties != null && properties.exists() )
422 {
423 sgen.setBuilderProperties( properties );
424 }
425 else
426 {
427 File defaultPropertyFile = new File( getProject().getBasedir(), DEFAULT_PROPERTY_FILE_LOCATION );
428 if ( properties != null && !properties.equals( defaultPropertyFile ) )
429 {
430 getLog().warn( "Cannot find custom builder property file " + properties.getAbsolutePath() );
431 throw new MojoExecutionException( "Cannot find custom builder property file "
432 + properties.getAbsolutePath() );
433 }
434 else if ( properties != null )
435 {
436 getLog().info(
437 "There is no custom builder property file at " + "the default location at "
438 + properties.getAbsolutePath() + ". Continuing code generation without." );
439 }
440 }
441
442 if ( createJdoDescriptors == true )
443 {
444 callSetterMethodUsingReflection( "setJdoDescriptorCreation", boolean.class,
445 new Boolean( createJdoDescriptors ) );
446 }
447
448 if ( isGenerateImportedSchemas() == true )
449 {
450 sgen.setGenerateImportedSchemas( true );
451 }
452
453 if ( generateMapping() == true )
454 {
455 sgen.setGenerateMappingFile( this.generateMappings );
456 sgen.setDescriptorCreation( false );
457 }
458
459 if ( !getClassGenerationMode().equals( "standard" ) )
460 {
461 callSetterMethodUsingReflection( "setJClassPrinterType", String.class, getClassGenerationMode() );
462 }
463
464 sgen.setNameConflictStrategy( this.nameConflictStrategy );
465
466 }
467
468
469
470
471
472
473
474
475
476 private void callSetterMethodUsingReflection( final String methodName, final Class<?> parameterType,
477 final Object parameterValue )
478 throws MojoExecutionException
479 {
480 getLog().info(
481 "About to invoke method >" + methodName
482 + "< on Castor's SourceGenerator class using reflection." );
483 try
484 {
485 Method method = sgen.getClass().getMethod( methodName, new Class[] { parameterType } );
486 method.invoke( sgen, new Object[] { parameterValue } );
487 }
488 catch ( NoSuchMethodException e )
489 {
490 getLog().info( "Specified method " + methodName + " not available on class SourceGenerator." );
491
492 }
493 catch ( IllegalArgumentException e )
494 {
495 throw new MojoExecutionException( "Problem calling SourceGenerator." + methodName + ": ", e );
496 }
497 catch ( IllegalAccessException e )
498 {
499 throw new MojoExecutionException( "Problem calling SourceGenerator." + methodName + ": ", e );
500 }
501 catch ( InvocationTargetException e )
502 {
503 throw new MojoExecutionException( "Problem calling SourceGenerator." + methodName + ": ", e );
504 }
505 }
506
507
508
509
510
511
512
513 private void processFile( String filePath )
514 throws MojoExecutionException
515 {
516 log( "Processing " + filePath );
517 try
518 {
519 sgen.generateSource( filePath, packaging );
520 }
521 catch ( FileNotFoundException e )
522 {
523 String message = "XML Schema file \"" + filePath + "\" not found.";
524 log( message );
525 throw new MojoExecutionException( message );
526 }
527 catch ( IOException iox )
528 {
529 throw new MojoExecutionException( "An IOException occurred processing " + filePath, iox );
530 }
531 catch ( Exception e )
532 {
533 throw new MojoExecutionException( "An Exception occurred processing " + filePath, e );
534 }
535 }
536
537
538
539
540
541
542 private void log( final String msg )
543 {
544 getLog().info( msg );
545 }
546
547
548
549
550
551
552 public File getDest()
553 {
554 return dest;
555 }
556
557
558
559
560
561
562 public File getResourceDestination()
563 {
564 return this.resourceDestination;
565 }
566
567
568
569
570
571
572 public void setDest( final File dest )
573 {
574 this.dest = dest;
575 }
576
577
578
579
580
581
582 public void setResourceDestination( final File resourceDestination )
583 {
584 this.resourceDestination = resourceDestination;
585 }
586
587
588
589
590
591
592 public File getTstamp()
593 {
594 return tstamp;
595 }
596
597
598
599
600
601
602 public void setTstamp( final File tstamp )
603 {
604 this.tstamp = tstamp;
605 }
606
607
608
609
610
611
612 public String getPackaging()
613 {
614 return packaging;
615 }
616
617
618
619
620
621
622 public void setPackaging( final String packaging )
623 {
624 this.packaging = packaging;
625 }
626
627
628
629
630
631
632 public String getNameConflictStrategy()
633 {
634 return nameConflictStrategy;
635 }
636
637
638
639
640
641
642 public void setNameConflictStrategy( final String nameConflictStrategy )
643 {
644 this.nameConflictStrategy = nameConflictStrategy;
645 }
646
647
648
649
650
651
652 public File getSchema()
653 {
654 return schema;
655 }
656
657
658
659
660
661
662 public void setSchema( final File schema )
663 {
664 this.schema = schema;
665 }
666
667
668
669
670
671
672 public String getTypes()
673 {
674 return types;
675 }
676
677
678
679
680
681
682 public void setTypes( final String types )
683 {
684 this.types = types;
685 }
686
687
688
689
690
691
692 public void setBindingfile( final File bindingfile )
693 {
694 this.bindingfile = bindingfile;
695 }
696
697
698
699
700
701
702 public void setProperties( final File properties )
703 {
704 this.properties = properties;
705 }
706
707
708
709
710
711
712 public boolean getMarshal()
713 {
714 return marshal;
715 }
716
717
718
719
720
721
722 public void setMarshal( final boolean marshal )
723 {
724 this.marshal = marshal;
725 }
726
727
728
729
730
731
732 public boolean isGenerateImportedSchemas()
733 {
734 return generateImportedSchemas;
735 }
736
737
738
739
740
741
742 public void setGenerateImportedSchemas( final boolean generateImportedSchemas )
743 {
744 this.generateImportedSchemas = generateImportedSchemas;
745 }
746
747
748
749
750
751
752 public MavenProject getProject()
753 {
754 return project;
755 }
756
757
758
759
760
761
762 public void setProject( MavenProject project )
763 {
764 this.project = project;
765 }
766
767
768
769
770
771
772 public final boolean getCreateJdoDescriptors()
773 {
774 return createJdoDescriptors;
775 }
776
777
778
779
780
781
782 public final void setCreateJdoDescriptors( final boolean newCreateJdoDescriptors )
783 {
784 this.createJdoDescriptors = newCreateJdoDescriptors;
785 }
786
787
788
789
790
791
792 private boolean generateMapping()
793 {
794 return this.generateMappings;
795 }
796
797
798
799
800
801
802 public final void setGenerateMappings( final boolean generateMappings )
803 {
804 this.generateMappings = generateMappings;
805 }
806
807
808
809
810
811
812 public String getClassGenerationMode()
813 {
814 return this.classGenerationMode;
815 }
816
817
818
819
820
821
822 public void setClassGenerationMode( final String classPrinterMethod )
823 {
824 this.classGenerationMode = classPrinterMethod;
825 }
826
827 }