1 package org.codehaus.mojo.jasperreports;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.net.URL;
21 import java.net.URLClassLoader;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28
29 import net.sf.jasperreports.engine.JRException;
30 import net.sf.jasperreports.engine.JasperCompileManager;
31 import net.sf.jasperreports.engine.util.JRProperties;
32
33 import org.apache.maven.plugin.AbstractMojo;
34 import org.apache.maven.plugin.MojoExecutionException;
35 import org.apache.maven.plugin.MojoFailureException;
36 import org.apache.maven.project.MavenProject;
37 import org.codehaus.plexus.compiler.util.scan.InclusionScanException;
38 import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
39 import org.codehaus.plexus.compiler.util.scan.StaleSourceScanner;
40 import org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping;
41 import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class JasperReportsMojo
57 extends AbstractMojo
58 {
59
60
61
62 private MavenProject project;
63
64
65
66
67
68
69 private File javaDirectory;
70
71
72
73
74
75
76 private File outputDirectory;
77
78
79
80
81
82
83 private File sourceDirectory;
84
85
86
87
88
89
90
91 private String sourceFileExt;
92
93
94
95
96
97
98
99 private String outputFileExt;
100
101
102
103
104
105
106
107
108
109
110
111 private boolean keepJava;
112
113
114
115
116
117
118
119
120 private boolean keepSerializedObject;
121
122
123
124
125
126
127 private boolean xmlValidation;
128
129
130
131
132
133
134
135 private String compiler;
136
137
138
139
140 private List classpathElements;
141
142
143
144
145
146
147
148 private Map additionalProperties = new HashMap();
149
150
151
152
153
154
155
156 private String additionalClasspath;
157
158 public void execute()
159 throws MojoExecutionException, MojoFailureException
160 {
161 getLog().debug( "javaDir = " + javaDirectory );
162 getLog().debug( "sourceDirectory = " + sourceDirectory );
163 getLog().debug( "sourceFileExt = " + sourceFileExt );
164 getLog().debug( "targetDirectory = " + outputDirectory );
165 getLog().debug( "targetFileExt = " + outputFileExt );
166 getLog().debug( "keepJava = " + keepJava );
167
168 getLog().debug( "xmlValidation = " + xmlValidation );
169 getLog().debug( "compiler = " + compiler );
170 getLog().debug( "classpathElements = " + classpathElements );
171 getLog().debug( "additionalClasspath = " + additionalClasspath );
172
173 checkDir( javaDirectory, "Directory for generated java sources", true );
174 checkDir( sourceDirectory, "Source directory", false );
175 checkDir( outputDirectory, "Target directory", true );
176
177 SourceMapping mapping = new SuffixMapping( sourceFileExt, outputFileExt );
178
179 Set staleSources = scanSrcDir( mapping );
180 if ( staleSources.isEmpty() )
181 {
182 getLog().info( "Nothing to compile - all Jasper reports are up to date" );
183 }
184 else
185 {
186
187 compile( staleSources, mapping );
188
189 if ( keepJava )
190 {
191 project.addCompileSourceRoot( javaDirectory.getAbsolutePath() );
192 }
193 }
194 }
195
196 protected void compile( Set files, SourceMapping mapping )
197 throws MojoFailureException, MojoExecutionException
198 {
199 String classpath = buildClasspathString( classpathElements, additionalClasspath );
200 getLog().debug( "buildClasspathString() = " + classpath );
201
202 getLog().info( "Compiling " + files.size() + " report design files." );
203
204 getLog().debug( "Set classloader" );
205 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
206 Thread.currentThread().setContextClassLoader( getClassLoader( classLoader ) );
207
208 JRProperties.backupProperties();
209
210 try
211 {
212 JRProperties.setProperty( JRProperties.COMPILER_CLASSPATH, classpath );
213 JRProperties.setProperty( JRProperties.COMPILER_TEMP_DIR, javaDirectory.getAbsolutePath() );
214 JRProperties.setProperty( JRProperties.COMPILER_KEEP_JAVA_FILE, keepJava );
215 JRProperties.setProperty( JRProperties.COMPILER_CLASS, compiler );
216 JRProperties.setProperty( JRProperties.COMPILER_XML_VALIDATION, xmlValidation );
217
218 for ( Iterator i = additionalProperties.keySet().iterator(); i.hasNext(); )
219 {
220 String key = (String) i.next();
221 String value = (String) additionalProperties.get( key );
222 JRProperties.setProperty( key, value );
223 getLog().debug( "Added property: " + key + ":" + value );
224 }
225
226 Iterator it = files.iterator();
227 while ( it.hasNext() )
228 {
229 File src = (File) it.next();
230 String srcName = getPathRelativeToRoot( src );
231 try
232 {
233
234 File dest = (File) mapping.getTargetFiles( outputDirectory, srcName ).iterator().next();
235
236 File destFileParent = dest.getParentFile();
237 if ( !destFileParent.exists() )
238 {
239 if ( destFileParent.mkdirs() )
240 {
241 getLog().debug( "Created directory " + destFileParent );
242 }
243 else
244 {
245 throw new MojoExecutionException( "Could not create directory " + destFileParent );
246 }
247 }
248 getLog().info( "Compiling report file: " + srcName );
249 JasperCompileManager.compileReportToFile( src.getAbsolutePath(), dest.getAbsolutePath() );
250 }
251 catch ( JRException e )
252 {
253 throw new MojoFailureException( this, "Error compiling report design : " + src,
254 "Error compiling report design : " + src + " : " + e.getMessage() );
255 }
256 catch ( InclusionScanException e )
257 {
258 throw new MojoFailureException( this, "Error compiling report design : " + src,
259 "Error compiling report design : " + src + " : " + e.getMessage() );
260 }
261 }
262 }
263 finally
264 {
265 JRProperties.restoreProperties();
266
267 if ( classLoader != null )
268 {
269 Thread.currentThread().setContextClassLoader( classLoader );
270 }
271 }
272 getLog().info( "Compiled " + files.size() + " report design files." );
273 }
274
275
276
277
278
279
280
281
282
283 protected Set scanSrcDir( SourceMapping mapping )
284 throws MojoExecutionException
285 {
286 final int staleMillis = 0;
287
288 SourceInclusionScanner scanner = new StaleSourceScanner( staleMillis );
289 scanner.addSourceMapping( mapping );
290
291 try
292 {
293 return scanner.getIncludedSources( sourceDirectory, outputDirectory );
294 }
295 catch ( InclusionScanException e )
296 {
297 throw new MojoExecutionException( "Error scanning source root: \'" + sourceDirectory + "\' "
298 + "for stale files to recompile.", e );
299 }
300 }
301
302 private String getPathRelativeToRoot( File file )
303 throws MojoExecutionException
304 {
305 try
306 {
307 String root = this.sourceDirectory.getCanonicalPath();
308 String filePath = file.getCanonicalPath();
309 if ( !filePath.startsWith( root ) )
310 {
311 throw new MojoExecutionException( "File is not in source root ??? " + file );
312 }
313 return filePath.substring( root.length() + 1 );
314 }
315 catch ( IOException e )
316 {
317 throw new MojoExecutionException( "Could not getCanonicalPath from file " + file, e );
318 }
319 }
320
321 protected String buildClasspathString( List classpathElements, String additionalClasspath )
322 {
323 StringBuffer classpath = new StringBuffer();
324 Iterator it = classpathElements.iterator();
325 while ( it.hasNext() )
326 {
327 String cpElement = (String) it.next();
328 classpath.append( cpElement );
329 if ( it.hasNext() )
330 {
331 classpath.append( File.pathSeparator );
332 }
333 }
334 if ( additionalClasspath != null )
335 {
336 if ( classpath.length() > 0 )
337 {
338 classpath.append( File.pathSeparator );
339 }
340 classpath.append( additionalClasspath );
341
342 }
343 return classpath.toString();
344 }
345
346 private void checkDir( File dir, String desc, boolean isTarget )
347 throws MojoExecutionException
348 {
349 if ( dir.exists() && !dir.isDirectory() )
350 {
351 throw new MojoExecutionException( desc + " is not a directory : " + dir );
352 }
353 else if ( !dir.exists() && isTarget && !dir.mkdirs() )
354 {
355 throw new MojoExecutionException( desc + " could not be created : " + dir );
356 }
357
358 if ( isTarget && !dir.canWrite() )
359 {
360 throw new MojoExecutionException( desc + " is not writable : " + dir );
361 }
362 }
363
364 private ClassLoader getClassLoader( ClassLoader classLoader )
365 throws MojoExecutionException
366 {
367 List classpathURLs = new ArrayList();
368
369 for ( int i = 0; i < classpathElements.size(); i++ )
370 {
371 String element = (String) classpathElements.get( i );
372 try
373 {
374 File f = new File( element );
375 URL newURL = f.toURI().toURL();
376 classpathURLs.add( newURL );
377 getLog().debug( "Added to classpath " + element );
378 }
379 catch ( Exception e )
380 {
381 throw new MojoExecutionException( "Error parsing classparh " + element + " " + e.getMessage() );
382 }
383 }
384
385 if ( additionalClasspath != null && additionalClasspath.length() > 0 )
386 {
387 String[] elements = additionalClasspath.split( File.pathSeparator );
388 for ( int i = 0; i < elements.length; i++ )
389 {
390 String element = elements[i];
391 try
392 {
393 File f = new File( element );
394 URL newURL = f.toURI().toURL();
395 classpathURLs.add( newURL );
396 getLog().debug( "Added to classpath " + element );
397 }
398 catch ( Exception e )
399 {
400 throw new MojoExecutionException( "Error parsing classpath " + additionalClasspath + " "
401 + e.getMessage() );
402 }
403 }
404 }
405
406 URL[] urls = (URL[]) classpathURLs.toArray( new URL[classpathURLs.size()] );
407 return new URLClassLoader( urls, classLoader );
408 }
409
410 }