1 /*
2 * Copyright 2005 The Codehaus.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.codehaus.mojo.castor;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileNotFoundException;
21 import java.io.IOException;
22 import java.util.Properties;
23
24 import org.apache.maven.plugin.MojoExecutionException;
25 import org.apache.maven.plugin.logging.Log;
26 import org.exolab.castor.builder.SourceGenerator;
27 import org.exolab.castor.builder.binding.ExtendedBinding;
28 import org.exolab.castor.builder.factory.FieldInfoFactory;
29 import org.exolab.castor.builder.info.CollectionInfo;
30
31 /**
32 * Override Castor's SourceGenerator to inject exception handling. Code based on Castor XML code generator, release
33 * 1.1-M2
34 */
35 class CastorSourceGenerator
36 extends SourceGenerator
37 {
38 /**
39 * {@link Log} instance to use for any logging.
40 */
41 private Log log;
42
43 /**
44 * {@link FieldInfoFactory} instance to be used during code generation. We need to save this in order to override
45 * its properties later since SourceGenerator doesn't give us access to this and the properties are only read during
46 * the constructor call
47 */
48 private FieldInfoFactory fieldInfoFactory;
49
50 /**
51 * Indicates whether logging should be verbose. As base class does not provide access to this variable, we intercept
52 * setting it and store its value here
53 */
54 private boolean verbose;
55
56 /**
57 * Creates a default {@link CastorSourceGenerator} instance.
58 */
59 public CastorSourceGenerator()
60 {
61 this( new FieldInfoFactory() );
62 }
63
64 /**
65 * Creates an instance of {@link CastorSourceGenerator}, configured with a field info factory.
66 *
67 * @param fieldInfoFactory {@link FieldInfoFactory} instance to be used during code generation.
68 */
69 public CastorSourceGenerator( FieldInfoFactory fieldInfoFactory )
70 {
71 super( fieldInfoFactory );
72 this.fieldInfoFactory = fieldInfoFactory;
73 }
74
75 /**
76 * Creates an instance of {@link CastorSourceGenerator}, configured with a field info factory and a binding file.
77 *
78 * @param fieldInfoFactory {@link FieldInfoFactory} instance to be used during code generation.
79 * @param extendedBinding Binding file to be used during code generation.
80 */
81 public CastorSourceGenerator( FieldInfoFactory fieldInfoFactory, ExtendedBinding extendedBinding )
82 {
83 super( fieldInfoFactory, extendedBinding );
84 this.fieldInfoFactory = fieldInfoFactory;
85 }
86
87 /**
88 * Factory method to create a {@link CastorSourceGenerator} instance, preset with default values.
89 *
90 * @param types A {@link FieldInfoFactory} type.
91 * @return a {@link CastorSourceGenerator} instance
92 * @throws MojoExecutionException To signal that an invalid type has been passed.
93 */
94 public static CastorSourceGenerator createSourceGenerator( String types )
95 throws MojoExecutionException
96 {
97 // Create Source Generator with appropriate type factory
98 CastorSourceGenerator sgen;
99 if ( types != null )
100 {
101 try
102 {
103 String typ = "j2".equals( types ) ? "arraylist" : types;
104 FieldInfoFactory factory = new FieldInfoFactory( typ );
105 sgen = new CastorSourceGenerator( factory );
106 }
107 catch ( Exception e )
108 {
109 try
110 {
111 sgen = new CastorSourceGenerator( (FieldInfoFactory) Class.forName( types ).newInstance() );
112 }
113 catch ( Exception e2 )
114 {
115 throw new MojoExecutionException( "Invalid types \"" + types + "\": " + e.getMessage() );
116 }
117 }
118 }
119 else
120 {
121 sgen = new CastorSourceGenerator(); // default
122 }
123 return sgen;
124 }
125
126 /**
127 * Sets the {@link Log} instance to use for logging.
128 *
129 * @param log The {@link Log} instance to use for logging
130 */
131 public void setLog( Log log )
132 {
133 this.log = log;
134 }
135
136 /**
137 * Returns the {@link Log} instance to use for logging.
138 *
139 * @return The {@link Log} instance to use for logging.
140 */
141 public Log getLog()
142 {
143 return log;
144 }
145
146 /**
147 * Helper method to output log statements.
148 *
149 * @param msg The log message to be output.
150 */
151 public void log( String msg )
152 {
153 getLog().info( msg );
154 }
155
156 /**
157 * Helper method to (conditionally) output a log statement.
158 *
159 * @param msg The log message to be output.
160 */
161 public void verbose( String msg )
162 {
163 if ( verbose )
164 {
165 getLog().info( msg );
166 }
167 }
168
169 /**
170 * Sets a user-specified line separator stype on the {@link CastorSourceGenerator}.
171 *
172 * @param lineSeparator A user-specified line separator style.
173 * @throws MojoExecutionException If an invalid line separator stype has been specified.
174 */
175 public void setLineSeparatorStyle( String lineSeparator )
176 throws MojoExecutionException
177 {
178 // Set Line Separator
179 String lineSep = System.getProperty( "line.separator" );
180 if ( lineSeparator != null )
181 {
182 if ( "win".equals( lineSeparator ) )
183 {
184 log( "Using Windows style line separation." );
185 lineSep = "\r\n";
186 }
187 else if ( "unix".equals( lineSeparator ) )
188 {
189 log( "Using UNIX style line separation." );
190 lineSep = "\n";
191 }
192 else if ( "mac".equals( lineSeparator ) )
193 {
194 log( "Using Macintosh style line separation." );
195 lineSep = "\r";
196 }
197 else
198 {
199 throw new MojoExecutionException( "Invalid value for lineseparator, must be win, unix, or mac." );
200 }
201 }
202 setLineSeparator( lineSep );
203 }
204
205 /**
206 * Indicates whether source generation should be 'verbose'.
207 *
208 * @param verbose True if source generation should be 'verbose'.
209 * @see org.exolab.castor.builder.SourceGenerator#setVerbose(boolean)
210 */
211 public void setVerbose( final boolean verbose )
212 {
213 this.verbose = verbose;
214 super.setVerbose( verbose );
215 }
216
217 /**
218 * Sets a user-specific binding file to be used during code generation.
219 *
220 * @param bindingFile A user-specified binding file.
221 */
222 public void setBindingFile( final File bindingFile )
223 {
224 setBinding( bindingFile.getAbsolutePath() );
225 }
226
227 /**
228 * Sets user-specific code generator properties for the code generation process.
229 *
230 * @param properties User-specific code generator properties.
231 * @throws MojoExecutionException Indicates that the user-specific properties cannot be accessed.
232 */
233 public void setBuilderProperties( File properties )
234 throws MojoExecutionException
235 {
236 // Set Builder Properties;
237 if ( properties != null )
238 {
239 String filePath = properties.getAbsolutePath();
240 Properties customProperties = new Properties();
241 try
242 {
243 customProperties.load( new FileInputStream( filePath ) );
244 }
245 catch ( FileNotFoundException e )
246 {
247 throw new MojoExecutionException( "Properties file \"" + filePath + "\" not found" );
248 }
249 catch ( IOException e )
250 {
251 throw new MojoExecutionException( "Can't read properties file \"" + filePath + "\": " + e );
252 }
253 setDefaultProperties( customProperties );
254
255 // these properties are read at contstruction time and copied into FieldInfoFactory
256 // se we set them directly in the fieldInfoFactory here.
257 if ( generateExtraCollectionMethods() )
258 {
259 verbose( "Overriding default castorbuilder.properties and setting createExtraMethods to true" );
260 fieldInfoFactory.setCreateExtraMethods( true );
261 }
262
263 String suffix = getProperty( CollectionInfo.REFERENCE_SUFFIX_PROPERTY, null );
264 if ( suffix != null )
265 {
266 verbose( "Overriding default castorbuilder.properties and " + "setting referenceSuffixProperty to "
267 + suffix );
268 }
269 fieldInfoFactory.setReferenceMethodSuffix( suffix );
270
271 if ( boundPropertiesEnabled() )
272 {
273 verbose( "Overriding default castorbuilder.properties and setting boundProperties to true" );
274 fieldInfoFactory.setBoundProperties( true );
275 }
276
277 }
278 }
279
280 }