001: /*
002: * ============================================================================
003: * GNU Lesser General Public License
004: * ============================================================================
005: *
006: * JasperReports - Free Java report-generating library.
007: * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * JasperSoft Corporation
024: * 303 Second Street, Suite 450 North
025: * San Francisco, CA 94107
026: * http://www.jaspersoft.com
027: */
028:
029: /*
030: * Contributors:
031: * Henri Chen - henrichen@users.sourceforge.net
032: * Kees Kuip - keeskuip@users.sourceforge.net
033: */
034: package net.sf.jasperreports.ant;
035:
036: import java.io.File;
037: import java.util.Collection;
038: import java.util.HashMap;
039: import java.util.Iterator;
040: import java.util.Map;
041:
042: import net.sf.jasperreports.engine.JRException;
043: import net.sf.jasperreports.engine.JasperCompileManager;
044: import net.sf.jasperreports.engine.util.JRProperties;
045:
046: import org.apache.tools.ant.AntClassLoader;
047: import org.apache.tools.ant.BuildException;
048: import org.apache.tools.ant.DirectoryScanner;
049: import org.apache.tools.ant.taskdefs.MatchingTask;
050: import org.apache.tools.ant.types.Path;
051: import org.apache.tools.ant.util.RegexpPatternMapper;
052: import org.apache.tools.ant.util.SourceFileScanner;
053:
054: /**
055: * Ant task for batch-compiling XML report design files.
056: * Works like the built-in <code>javac</code> Ant task.
057: * <p>
058: * This task can take the following arguments:
059: * <ul>
060: * <li>src
061: * <li>destdir
062: * <li>compiler
063: * <li>classpath
064: * <li>tempdir
065: * <li>keepjava
066: * <li>xmlvalidation
067: * </ul>
068: * Of these arguments, the <code>src</code> and <code>destdir</code> are required.
069: * When this task executes, it will recursively scan the <code>src</code> and
070: * <code>destdir</code> looking for XML report design files to compile.
071: * This task makes its compile decision based on timestamp and only XML files
072: * that have no corresponding .jasper file or where the compiled report design file
073: * is older than the XML file will be compiled.
074: *
075: * @author Teodor Danciu (teodord@users.sourceforge.net)
076: * @version $Id: JRAntCompileTask.java 1606 2007-02-28 08:21:12Z lucianc $
077: */
078: public class JRAntCompileTask extends MatchingTask {
079:
080: /**
081: *
082: */
083: private Path src = null;
084: private File destdir = null;
085: private File tempdir = null;
086: private boolean keepjava = false;
087: private String compiler = null;
088: private Path classpath = null;
089: private boolean xmlvalidation = true;
090:
091: private Map reportFilesMap = null;
092:
093: /**
094: * Sets the source directories to find the XML report design files.
095: *
096: * @param srcdir source path
097: */
098: public void setSrcdir(Path srcdir) {
099: if (src == null) {
100: src = srcdir;
101: } else {
102: src.append(srcdir);
103: }
104: }
105:
106: /**
107: * Adds a path for source compilation.
108: *
109: * @return source path
110: */
111: public Path createSrc() {
112: if (src == null) {
113: src = new Path(getProject());
114: }
115:
116: return src.createPath();
117: }
118:
119: /**
120: * Sets the destination directory into which the XML report design files should be compiled.
121: *
122: * @param destdir destination directory
123: */
124: public void setDestdir(File destdir) {
125: this .destdir = destdir;
126: }
127:
128: /**
129: * Sets the temporary working directory into which to store the temporary files
130: * generated during XML report design file compilation. This is only used by the
131: * Java bytecode report compilers that need to have the Java source files stored
132: * on disk in order to compile them.
133: * <p>
134: * If not set, the temporary working directory will be the current working directory,
135: * as specified by the <code>user.dir</code> system property.
136: *
137: * @param tempdir temporary working directory
138: */
139: public void setTempdir(File tempdir) {
140: this .tempdir = tempdir;
141: }
142:
143: /**
144: * Sets a boolean flag that will instruct the Java bytecode report compilers
145: * to avoid deletion of the Java source files generated in the temporary working
146: * directory during report generation. This is useful when debugging.
147: *
148: * @param keepjava flag for preventing the deletion of generated Java source files
149: */
150: public void setKeepjava(boolean keepjava) {
151: this .keepjava = keepjava;
152: }
153:
154: /**
155: * Sets the name of the report compiler class to use when compiling the XML
156: * report design files.
157: * <p>
158: * The specified class should be an implementation of the
159: * {@link net.sf.jasperreports.engine.design.JRCompiler} interface.
160: * When specified, this value will temporarily override the value of the
161: * <code>jasper.reports.compiler.class</code> system property which in turn
162: * is used by the {@link net.sf.jasperreports.engine.design.JRDefaultCompiler}.
163: *
164: * @param compiler report compiler class name
165: */
166: public void setCompiler(String compiler) {
167: this .compiler = compiler;
168: }
169:
170: /**
171: * Adds a path to the classpath.
172: *
173: * @return classpath to use when compiling the report associated Java expressions class
174: */
175: public Path createClasspath() {
176: if (classpath == null) {
177: classpath = new Path(getProject());
178: }
179:
180: return classpath.createPath();
181: }
182:
183: /**
184: * Instructs the XML parser to validate the XML report design file during compilation.
185: *
186: * @param xmlvalidation flag for enabling/disabling the validation feature of the XML parser
187: */
188: public void setXmlvalidation(boolean xmlvalidation) {
189: this .xmlvalidation = xmlvalidation;
190: }
191:
192: /**
193: * Executes the task.
194: */
195: public void execute() throws BuildException {
196: checkParameters();
197:
198: reportFilesMap = new HashMap();
199:
200: JRProperties.backupProperties();
201:
202: try {
203: if (tempdir != null) {
204: JRProperties.setProperty(
205: JRProperties.COMPILER_TEMP_DIR, String
206: .valueOf(tempdir));
207: }
208:
209: JRProperties.setProperty(
210: JRProperties.COMPILER_KEEP_JAVA_FILE, keepjava);
211:
212: if (compiler != null) {
213: JRProperties.setProperty(JRProperties.COMPILER_CLASS,
214: compiler);
215: }
216:
217: JRProperties
218: .setProperty(JRProperties.COMPILER_XML_VALIDATION,
219: xmlvalidation);
220:
221: AntClassLoader classLoader = null;
222: if (classpath != null) {
223: JRProperties.setProperty(
224: JRProperties.COMPILER_CLASSPATH, String
225: .valueOf(classpath));
226:
227: ClassLoader parentClassLoader = getClass()
228: .getClassLoader();
229: classLoader = new AntClassLoader(parentClassLoader,
230: getProject(), classpath, true);
231: classLoader.setThreadContextLoader();
232: }
233:
234: try {
235: /* */
236: scanSrc();
237: /* */
238: compile();
239: } finally {
240: if (classLoader != null) {
241: classLoader.resetThreadContextLoader();
242: }
243: }
244: } finally {
245: JRProperties.restoreProperties();
246: }
247: }
248:
249: /**
250: * Checks that all required attributes have been set and that the supplied values are valid.
251: */
252: protected void checkParameters() throws BuildException {
253: if (src == null || src.size() == 0) {
254: throw new BuildException(
255: "The srcdir attribute must be set.", location);
256: }
257:
258: if (destdir != null && !destdir.isDirectory()) {
259: throw new BuildException("The destination directory \""
260: + destdir + "\" does not exist "
261: + "or is not a directory.", location);
262: }
263:
264: if (tempdir != null && !tempdir.isDirectory()) {
265: throw new BuildException("The temporary directory \""
266: + tempdir + "\" does not exist "
267: + "or is not a directory.", location);
268: }
269: }
270:
271: /**
272: * Scans the source directories looking for source files to be compiled.
273: */
274: protected void scanSrc() throws BuildException {
275: String[] list = src.list();
276: for (int i = 0; i < list.length; i++) {
277: File srcdir = project.resolveFile(list[i]);
278: if (!srcdir.exists()) {
279: throw new BuildException("The srcdir \""
280: + srcdir.getPath() + "\" does not exist.",
281: location);
282: }
283:
284: if (srcdir.isDirectory()) {
285: DirectoryScanner ds = getDirectoryScanner(srcdir);
286: String[] files = ds.getIncludedFiles();
287:
288: scanDir(srcdir, destdir != null ? destdir : srcdir,
289: files);
290: } else {
291: String[] files = new String[] { srcdir.getName() };
292:
293: scanDir(srcdir.getParentFile(),
294: destdir != null ? destdir : srcdir
295: .getParentFile(), files);
296: }
297: }
298: }
299:
300: /**
301: * Scans the directory looking for source files to be compiled.
302: * The results are returned in the instance variable <code>reportFilesMap</code>.
303: *
304: * @param srcdir source directory
305: * @param destdir destination directory
306: * @param files included file names
307: */
308: protected void scanDir(File srcdir, File destdir, String[] files) {
309: RegexpPatternMapper mapper = new RegexpPatternMapper();
310: mapper.setFrom("^(.*)\\.(.*)$");
311: mapper.setTo("\\1.jasper");
312:
313: SourceFileScanner scanner = new SourceFileScanner(this );
314: String[] newFiles = scanner.restrict(files, srcdir, destdir,
315: mapper);
316:
317: if (newFiles != null && newFiles.length > 0) {
318: for (int i = 0; i < newFiles.length; i++) {
319: reportFilesMap.put((new File(srcdir, newFiles[i]))
320: .getAbsolutePath(), (new File(destdir, mapper
321: .mapFileName(newFiles[i])[0]))
322: .getAbsolutePath());
323: }
324: }
325: }
326:
327: /**
328: * Performs the compilation of the selected report design files.
329: */
330: protected void compile() throws BuildException {
331: Collection files = reportFilesMap.keySet();
332:
333: if (files != null && files.size() > 0) {
334: boolean isError = false;
335:
336: System.out.println("Compiling " + files.size()
337: + " report design files.");
338:
339: String srcFileName = null;
340: String destFileName = null;
341: File destFileParent = null;
342:
343: for (Iterator it = files.iterator(); it.hasNext();) {
344: srcFileName = (String) it.next();
345: destFileName = (String) reportFilesMap.get(srcFileName);
346: destFileParent = new File(destFileName).getParentFile();
347: if (!destFileParent.exists()) {
348: destFileParent.mkdirs();
349: }
350:
351: try {
352: System.out.print("File : " + srcFileName + " ... ");
353: JasperCompileManager.compileReportToFile(
354: srcFileName, destFileName);
355: System.out.println("OK.");
356: } catch (JRException e) {
357: System.out.println("FAILED.");
358: System.out
359: .println("Error compiling report design : "
360: + srcFileName);
361: e.printStackTrace(System.out);
362: isError = true;
363: }
364: }
365:
366: if (isError) {
367: throw new BuildException(
368: "Errors were encountered when compiling report designs.");
369: }
370: }
371: }
372:
373: }
|