1 /*
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Intalio, Inc. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Intalio, Inc. Exolab is a registered
23 * trademark of Intalio, Inc.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2004 (C) Intalio, Inc. All Rights Reserved.
42 *
43 * $Id: CastorSourceGenTask.java 6410 2006-11-17 12:06:24Z wguttmn $
44 */
45 package org.castor.anttask;
46
47 import java.io.File;
48 import java.io.FileInputStream;
49 import java.io.FileNotFoundException;
50 import java.io.IOException;
51 import java.lang.reflect.InvocationTargetException;
52 import java.lang.reflect.Method;
53 import java.util.Properties;
54 import java.util.Vector;
55
56 import org.apache.tools.ant.BuildException;
57 import org.apache.tools.ant.DirectoryScanner;
58 import org.apache.tools.ant.taskdefs.MatchingTask;
59 import org.apache.tools.ant.types.FileSet;
60 import org.castor.xml.BackwardCompatibilityContext;
61 import org.castor.xml.InternalContext;
62 import org.exolab.castor.builder.SourceGenerator;
63 import org.exolab.castor.builder.binding.ExtendedBinding;
64 import org.exolab.castor.builder.factory.FieldInfoFactory;
65 import org.exolab.castor.xml.XMLException;
66 import org.exolab.castor.xml.schema.Schema;
67 import org.exolab.castor.xml.schema.SchemaContext;
68 import org.exolab.castor.xml.schema.SchemaContextImpl;
69 import org.exolab.castor.xml.schema.reader.Sax2ComponentReader;
70 import org.exolab.castor.xml.schema.reader.SchemaUnmarshaller;
71 import org.exolab.javasource.JClass;
72 import org.xml.sax.InputSource;
73 import org.xml.sax.Parser;
74 import org.xml.sax.SAXException;
75
76 /**
77 * An <a href="http://ant.apache.org/">Ant</a> task to call the Castor
78 * Source Generator. It can be passed a file, a directory, a Fileset or all
79 * three.
80 *
81 * @author <a href="mailto:joel.farquhar@montage-dmc.com">Joel Farquhar</a>
82 * @author <a href="mailto:ferret AT frii DOT com">Bruce Snyder</a>
83 * @author <a href="mailto:wguttmn AT codehaus DOT org">Werner Guttmann</a>
84 * @version $Revision: 6543 $ $Date: 2005-03-05 06:42:06 -0700 (Sat, 05 Mar 2005) $
85 */
86 public final class CastorCodeGenTask extends MatchingTask {
87
88 /** Message indicating that the method setJdoDescriptorCreation cannot be invoked. */
89 private static final String PROBLEM_SETTING_JDO_DESC =
90 "Problem calling SourceGenerator.setJdoDescriptorCreation: ";
91
92 /** Msg indicating class descriptor generation has been disabled. */
93 private static final String DISABLE_DESCRIPTORS_MSG =
94 "Disabling generation of Class descriptors";
95
96 /** Msg indicating marshaling framework code will not be generated. */
97 private static final String DISABLE_MARSHAL_MSG =
98 "Disabling generation of Marshaling framework methods (marshal, unmarshal, validate).";
99
100 /** Msg indicating that castor-testable code will be generated. */
101 private static final String CASTOR_TESTABLE_MSG =
102 "The generated classes will implement org.exolab.castor.tests.CastorTestable";
103
104 /** Error message -- invalid line seperator. */
105 private static final String INVALID_LINESEP_MSG =
106 "Invalid value for lineseparator, must be win, unix, or mac.";
107
108 /** Error message -- no schemas to run code generator on. */
109 private static final String NO_SCHEMA_MSG =
110 "At least one of the file, url or dir attributes, or a fileset element, must be set.";
111
112 /** Castor XML context - the mother of all. */
113 private InternalContext _internalContext;
114
115 /** If processing one schema file, this lists the file. */
116 private File _schemaFile = null;
117
118 /** If processing one schema file from an URL, this lists the file. */
119 private String _schemaURL = null;
120
121 /** If processing all schemas in a directory, this lists the directory. */
122 private File _schemaDir = null;
123
124 /** If processing a fileset, this lists the fileset. */
125 private Vector < FileSet > _schemaFilesets = new Vector < FileSet > ();
126
127 // Begin Source Generator parameters
128 /** The package that generated code will belong to. */
129 private String _srcpackage;
130
131 /** The directory that code will be generated into. */
132 private String _todir;
133
134 /** The directory that resources will be generated into, if specified. */
135 private String _resourcesDirectory;
136
137 /** Binding file for the code generator. */
138 private String _bindingfile;
139
140 /** Information about how to generate collections. */
141 private String _types;
142
143 /** Line seperator to use for generated code. */
144 private String _lineseparator;
145
146 /** If true, the code generator will be verbose. */
147 private boolean _verbose;
148
149 /** If true, non-fatal warnings will be suppressed. Also, existing source
150 * files will be silently overwritten. */
151 private boolean _warnings = true;
152
153 /** If true, class descriptors will not be generated. */
154 private boolean _nodesc;
155
156 /** If true, marshaling code will not be generated. */
157 private boolean _nomarshal;
158
159 /** If true, old Java field naming conventions will be used. */
160 private boolean _useOldFieldNaming = true;
161
162 /**
163 * If true, a mapping file will be generated (additionally).
164 */
165 private boolean _generateMapping;
166
167 /** If true, Castor's CTF testable framework code will be generated. */
168 private boolean _testable;
169
170 /** Whether to generate code for imported schemas, too. */
171 private boolean _generateImportedSchemas;
172
173 /** Whether to generate SAX-1 compliant code. */
174 private boolean _sax1;
175
176 /** Whether enumerated type lookup should be performed in a case insensitive manner. */
177 private boolean _caseInsensitive;
178
179 /** CastorBuilderProperties file. */
180 private String _properties;
181
182 /** The name conflict strategy to use. */
183 private String _nameConflictStrategy = "warnViaConsoleDialog";
184
185 /** Name of the automatic clas name conflict strategy to use. */
186 private String _automaticConflictStrategy = "xpath";
187
188 /** Whether to generate JDO descriptors. */
189 private boolean _generateJdoDescriptors;
190
191 /**
192 * Mode for printing JClass instances.
193 */
194 private String _jclassPrinterType = "standard";
195
196 /** SourceGenerator instance. */
197 private SourceGenerator _sgen;
198
199 /**
200 * No-arg constructor.
201 */
202 public CastorCodeGenTask() {
203 super();
204 _internalContext = new BackwardCompatibilityContext();
205 }
206
207 /**
208 * Sets the individual schema that will have code generated for it.
209 *
210 * @param file One schema file.
211 */
212 public void setFile(final File file) {
213 _schemaFile = file;
214 }
215
216 /**
217 * Sets an URL for one individual schema that will have code generated for it.
218 *
219 * @param schemaURL URL for one schema file.
220 */
221 public void setSchemaURL(final String schemaURL) {
222 _schemaURL = schemaURL;
223 }
224
225
226 /**
227 * Sets the directory such that all schemas in this directory will have code
228 * generated for them.
229 *
230 * @param dir The directory containing schemas to process.
231 */
232 public void setDir(final File dir) {
233 _schemaDir = dir;
234 }
235
236 /**
237 * Adds a fileset to process that contains schemas to process.
238 *
239 * @param set An individual file set containing schemas.
240 */
241 public void addFileset(final FileSet set) {
242 _schemaFilesets.addElement(set);
243 }
244
245 /**
246 * Sets the package that generated code will belong to.
247 *
248 * @param pack The package that generated code will belong to.
249 */
250 public void setPackage(final String pack) {
251 _srcpackage = pack;
252 }
253
254 /**
255 * Sets the directory into which code will be generated.
256 *
257 * @param dest The directory into which code will be generated.
258 */
259 public void setTodir(final String dest) {
260 _todir = dest;
261 }
262
263 /**
264 * Sets the directory into which resources will be generated. If not
265 * specified, resources will be generated in the same location as
266 * code.
267 *
268 * @param dest The directory into which resources will be generated.
269 */
270 public void setResourcesDirectory(final String destination) {
271 _resourcesDirectory = destination;
272 }
273
274 /**
275 * Sets the binding file to be used for code generation.
276 *
277 * @param bindingfile The binding file to be used for code generation.
278 */
279 public void setBindingfile(final String bindingfile) {
280 _bindingfile = bindingfile;
281 }
282
283 /**
284 * Sets the line seperator to use for code generation.
285 *
286 * @param ls The line seperator to use for code generation.
287 */
288 public void setLineseparator(final String ls) {
289 _lineseparator = ls;
290 }
291
292 /**
293 * Sets the type factory for code generation.
294 *
295 * @param tf The type factory to use for code generation.
296 */
297 public void setTypes(final String tf) {
298 _types = (tf.equals("j2")) ? "arraylist" : tf;
299 }
300
301 /**
302 * Sets whether or not code generation gives extra information about its work.
303 *
304 * @param b If true, the code generator will be verbose.
305 */
306 public void setVerbose(final boolean b) {
307 _verbose = b;
308 }
309
310 /**
311 * Sets the name conflict strategy to use.
312 *
313 * @param nameConflictStrategy The name conflict strategy to use
314 */
315 public void setNameConflictStrategy(final String nameConflictStrategy) {
316 _nameConflictStrategy = nameConflictStrategy;
317 }
318
319 /**
320 * Sets the name conflict strategy to use.
321 *
322 * @param automaticConflictStrategy The automatic class name conflict strategy to use
323 */
324 public void setAutomaticConflictStrategy(final String automaticConflictStrategy) {
325 _automaticConflictStrategy = automaticConflictStrategy;
326 }
327
328
329 /**
330 * Sets whether or not non-fatal warnings should be suppressed.
331 *
332 * @param b If true, non-fatal warnings will be suppressed. This additionally
333 * means that existing source files will be silently overwritten.
334 */
335 public void setWarnings(final boolean b) {
336 _warnings = b;
337 }
338
339 /**
340 * Sets whether or not the old Java field naming conventions should be used.
341 *
342 * @param useOldFieldNaming If true, the old Java field naming conventions will be used.
343 */
344 public void setUseOldFieldNaming(final boolean useOldFieldNaming) {
345 _useOldFieldNaming = useOldFieldNaming;
346 }
347
348 /**
349 * Sets whether or not class descriptors are generated.
350 *
351 * @param b If true, class descriptors are generated.
352 */
353 public void setNodesc(final boolean b) {
354 _nodesc = b;
355 }
356
357 /**
358 * Sets whether or not marshaling methods are generated.
359 *
360 * @param b If true, marshaling methods are generated.
361 */
362 public void setNomarshal(final boolean b) {
363 _nomarshal = b;
364 }
365
366 /**
367 * Sets whether CTF framework code is generated.
368 *
369 * @param b If true, the generated code will be instrumented for the CTF.
370 */
371 public void setTestable(final boolean b) {
372 _testable = b;
373 }
374
375 /**
376 * Controls whether to generate code for imported schemas as well.
377 *
378 * @param generateImportedSchemas True if code should be generated for imported schemas.
379 */
380 public void setGenerateImportedSchemas(final boolean generateImportedSchemas) {
381 _generateImportedSchemas = generateImportedSchemas;
382 }
383
384 /**
385 * Controls whether to generate JDO-specific class descriptors.
386 *
387 * @param generateJdoDescriptors True if JDP class descriptors should be generated
388 */
389 public void setGenerateJdoDescriptors(final boolean generateJdoDescriptors) {
390 _generateJdoDescriptors = generateJdoDescriptors;
391 }
392
393
394 /**
395 * Controls whether to generate SAX-1 compliant code.
396 *
397 * @param sax1 True if SAX-1 compliant code should be generated.
398 */
399 public void setSAX1(final boolean sax1) {
400 _sax1 = sax1;
401 }
402
403 /**
404 * Controls whether enumerated type lookup should be performed in a case
405 * insensitive manner.
406 *
407 * @param caseInsensitive True if enumerated type lookup should be performed in a case
408 * insensitive manner
409 */
410 public void setCaseInsensitive(final boolean caseInsensitive) {
411 _caseInsensitive = caseInsensitive;
412 }
413
414 /**
415 * Sets the file to use for castor builder properties.
416 *
417 * @param properties The properties to use.
418 */
419 public void setProperties(final String properties) {
420 _properties = properties;
421 }
422
423 /**
424 * Sets the mode for printing {@link JClass} instances.
425 * @param jclassPrinterType The mode for printing {@link JClass} instances.
426 */
427 public void setJClassPrinterType(final String jclassPrinterType) {
428 _jclassPrinterType = jclassPrinterType;
429 }
430
431 /**
432 * Controls whether a mapping file should (additionally) be generated.
433
434 * @param generateMapping True if a mapping file should be generated.
435 */
436 public void setGenerateMapping(final boolean generateMapping) {
437 _generateMapping = generateMapping;
438 }
439
440 /**
441 * Configured the code generator. If anything goes wrong during configuration of the
442 * Ant task a BuildException will be thrown.
443 */
444 private void config() {
445 // Create Source Generator with appropriate type factory
446 if (_types != null) {
447 FieldInfoFactory factory;
448 try {
449 if (_useOldFieldNaming) {
450 factory = new FieldInfoFactory(_types);
451 } else {
452 factory = new FieldInfoFactory(_types, false);
453 }
454
455 _sgen = new CastorSourceGeneratorWrapper(factory);
456 } catch (Exception e) {
457 try {
458 factory = (FieldInfoFactory) Class.forName(_types).newInstance();
459 _sgen = new CastorSourceGeneratorWrapper(factory);
460 } catch (Exception e2) {
461 throw new BuildException("Invalid types \"" + _types + "\": " + e.getMessage());
462 }
463 }
464 } else {
465 // default
466 _sgen = new CastorSourceGeneratorWrapper();
467 }
468
469 // Set Line Separator
470 String lineSep = System.getProperty("line.separator");
471 if (_lineseparator != null) {
472 if ("win".equals(_lineseparator)) {
473 log("Using Windows style line separation.");
474 lineSep = "\r\n";
475 } else if ("unix".equals(_lineseparator)) {
476 log("Using UNIX style line separation.");
477 lineSep = "\n";
478 } else if ("mac".equals(_lineseparator)) {
479 log("Using Macintosh style line separation.");
480 lineSep = "\r";
481 } else {
482 throw new BuildException(INVALID_LINESEP_MSG);
483 }
484 }
485 _sgen.setLineSeparator(lineSep);
486
487 _sgen.setDestDir(_todir);
488
489 // TODO: use reflection to invoke this
490 if (_resourcesDirectory != null && _resourcesDirectory.length() > 0) {
491 _sgen.setResourceDestination(_resourcesDirectory);
492 }
493
494 if (_bindingfile != null) { _sgen.setBinding(_bindingfile); }
495
496 _sgen.setVerbose(_verbose);
497 _sgen.setSuppressNonFatalWarnings(!_warnings);
498
499 _sgen.setDescriptorCreation(!_nodesc);
500 if (_nodesc) { log(DISABLE_DESCRIPTORS_MSG); }
501
502 _sgen.setCreateMarshalMethods(!_nomarshal);
503 if (_nomarshal) { log(DISABLE_MARSHAL_MSG); }
504
505 _sgen.setGenerateImportedSchemas(_generateImportedSchemas);
506
507 _sgen.setSAX1(_sax1);
508
509 _sgen.setCaseInsensitive(_caseInsensitive);
510
511 _sgen.setNameConflictStrategy(_nameConflictStrategy);
512
513 _sgen.setClassNameConflictResolver(_automaticConflictStrategy);
514
515 _sgen.setJClassPrinterType(_jclassPrinterType);
516
517 _sgen.setGenerateMappingFile(_generateMapping);
518
519 if (_generateJdoDescriptors) {
520 callSetterMethodUsingReflection(_sgen, "setJdoDescriptorCreation",
521 boolean.class, new Boolean(_generateJdoDescriptors));
522 }
523
524 _sgen.setTestable(_testable);
525 if (this._testable) { log(CASTOR_TESTABLE_MSG); }
526
527 // Set Builder Properties;
528 if (_properties != null) {
529 String filePath = new File(_properties).getAbsolutePath();
530 Properties customProperties = new Properties();
531 try {
532 customProperties.load(new FileInputStream(filePath));
533 } catch (FileNotFoundException e) {
534 throw new BuildException("Properties file \"" + filePath + "\" not found");
535 } catch (IOException e) {
536 throw new BuildException("Can't read properties file \"" + filePath + "\": " + e);
537 }
538 _sgen.setDefaultProperties(customProperties);
539 }
540 }
541
542 /**
543 * Runs source generation. If anything goes wrong during source generation a
544 * BuildException will be thrown.
545 *
546 * @param filePath an individual Schema to generate code for.
547 */
548 private void processFile(final String filePath) {
549 log("Processing " + filePath);
550 try {
551 _sgen.generateSource(filePath, _srcpackage);
552 } catch (FileNotFoundException e) {
553 String message = "XML Schema file \"" + _schemaFile.getAbsolutePath() + "\" not found.";
554 log(message);
555 throw new BuildException(message);
556 } catch (Exception iox) {
557 throw new BuildException(iox);
558 }
559 }
560
561 /**
562 * Runs source generation on a XML schema instance pointed to by an URL. If anything
563 * goes wrong during source generation a BuildException will be thrown.
564 *
565 * @param schemaURL An URL to an individual XML schema to generate code for.
566 */
567 private void processURL(final String schemaURL) {
568 log("Processing " + schemaURL);
569 try {
570 InputSource inputSource = new InputSource(schemaURL);
571 _sgen.generateSource(inputSource, _srcpackage);
572 } catch (FileNotFoundException e) {
573 String message = "XML Schema file \"" + _schemaURL + "\" not found.";
574 log(message);
575 throw new BuildException(message);
576 } catch (Exception iox) {
577 throw new BuildException(iox);
578 }
579 }
580
581 /**
582 * Public execute method -- entry point for the Ant task. Loops over all
583 * schema that need code generated and creates needed code generators, then
584 * executes them. If anything goes wrong during execution of the Ant task a
585 * BuildException will be thrown.
586 *
587 * @see org.apache.tools.ant.Task#execute()
588 */
589 public void execute() {
590 // Must have something to run the source generator on
591 if (_schemaFile == null && _schemaDir == null && _schemaFilesets.size() == 0
592 && _schemaURL == null) {
593 throw new BuildException(NO_SCHEMA_MSG);
594 }
595
596 try {
597 config();
598
599 // Run source generator on file
600 if (_schemaFile != null) {
601 processFile(_schemaFile.getAbsolutePath());
602 }
603
604 // Run source generator on all files in directory
605 if (_schemaDir != null && _schemaDir.exists() && _schemaDir.isDirectory()) {
606 DirectoryScanner ds = this.getDirectoryScanner(_schemaDir);
607
608 String[] files = ds.getIncludedFiles();
609 for (int i = 0; i < files.length; i++) {
610 String filePath = _schemaDir.getAbsolutePath() + File.separator + files[i];
611 processFile(filePath);
612 }
613 }
614
615 // Run source generator on all files in FileSet
616 for (int i = 0; i < _schemaFilesets.size(); i++) {
617 FileSet fs = (FileSet) _schemaFilesets.elementAt(i);
618 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
619 File subdir = fs.getDir(getProject());
620
621 String[] files = ds.getIncludedFiles();
622 for (int j = 0; j < files.length; j++) {
623 String filePath = subdir.getAbsolutePath() + File.separator + files[j];
624 processFile(filePath);
625 }
626 }
627
628 // Run source generator on URL for XML schema
629 if (_schemaURL != null) {
630 processURL(_schemaURL);
631 }
632 } finally {
633 _sgen = null;
634 }
635 }
636
637 /**
638 * Override Castor's SourceGenerator to inject exception handling.
639 * Code based on castor-0.9.5.3-xml.jar.
640 */
641 private final class CastorSourceGeneratorWrapper extends SourceGenerator {
642 /**
643 * No-arg constructor.
644 */
645 public CastorSourceGeneratorWrapper() {
646 super();
647 }
648
649 /**
650 * Constructs a source generator with the provided FieldInfoFactory.
651 *
652 * @param fieldInfoFactory A FieldInfoFactory to use for collections.
653 */
654 public CastorSourceGeneratorWrapper(final FieldInfoFactory fieldInfoFactory) {
655 super(fieldInfoFactory);
656 }
657
658 /**
659 * Constructs a source generator with the provided FieldInfoFactory and
660 * binding file.
661 *
662 * @param fieldInfoFactory a FieldInfoFactory to use for collections.
663 * @param extendedBinding binding information for the code generator.
664 */
665 public CastorSourceGeneratorWrapper(
666 final FieldInfoFactory fieldInfoFactory, final ExtendedBinding extendedBinding) {
667 super(fieldInfoFactory, extendedBinding);
668 }
669
670 /**
671 * Generate source. If anything goes wrong during generation of source a
672 * BuildException will be thrown.
673 *
674 * @param source an individual schema to process.
675 * @param packageName the package name for generated code.
676 *
677 * @see org.exolab.castor.builder.SourceGenerator
678 * #generateSource(org.xml.sax.InputSource, java.lang.String)
679 */
680 public void generateSource(final InputSource source, final String packageName) {
681 Parser parser = null;
682 try {
683 parser = _internalContext.getParser();
684 } catch (RuntimeException e) {
685 throw new BuildException("Unable to create SAX parser.", e);
686 }
687 if (parser == null) {
688 throw new BuildException("Unable to create SAX parser.");
689 }
690
691 SchemaContext schemaContext = new SchemaContextImpl();
692 SchemaUnmarshaller schemaUnmarshaller = null;
693 try {
694 schemaUnmarshaller = new SchemaUnmarshaller(schemaContext);
695 } catch (XMLException e) {
696 throw new BuildException("Unable to create schema unmarshaller.", e);
697 }
698
699 Sax2ComponentReader handler = new Sax2ComponentReader(schemaUnmarshaller);
700 parser.setDocumentHandler(handler);
701 parser.setErrorHandler(handler);
702 try {
703 parser.parse(source);
704 } catch (IOException e) {
705 String msg = "Can't read input file " + source.getSystemId() + ".\n" + e;
706 throw new BuildException(msg, e);
707 } catch (SAXException e) {
708 String msg = "Can't parse input file " + source.getSystemId() + ".\n" + e;
709 throw new BuildException(msg, e);
710 }
711 Schema schema = schemaUnmarshaller.getSchema();
712 try {
713 generateSource(schema, packageName);
714 } catch (Exception iox) {
715 throw new BuildException(iox);
716 }
717 }
718 }
719
720 /**
721 * Helper method to invoke a setter method on {@link SourceGenerator} that might not
722 * be available due to a version issue.
723 *
724 * @param sgen {@link SourceGenerator} instance
725 * @param methodName Name of the method
726 * @param parameterType Type of the method parameter.
727 * @param parameterValue Actual parameter value to be used during method invocation.
728 * @throws BuildException If the method cannot be invoked.
729 */
730 private void callSetterMethodUsingReflection(final SourceGenerator sgen,
731 final String methodName, final Class parameterType,
732 final Object parameterValue) throws BuildException {
733 try {
734 Method method = sgen.getClass().getMethod(methodName,
735 new Class[] {parameterType});
736 method.invoke(sgen, new Object[] {parameterValue});
737 } catch (NoSuchMethodException e) {
738 // unable to find method to configure JDO descriptor creation.
739 } catch (IllegalArgumentException e) {
740 throw new BuildException(PROBLEM_SETTING_JDO_DESC, e);
741 } catch (IllegalAccessException e) {
742 throw new BuildException(PROBLEM_SETTING_JDO_DESC, e);
743 } catch (InvocationTargetException e) {
744 throw new BuildException(PROBLEM_SETTING_JDO_DESC, e);
745 }
746 }
747
748
749
750 }