net.sf.jasperreports.ant.JRAntApiWriteTask Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jasperreports Show documentation
Show all versions of jasperreports Show documentation
Free Java Reporting Library
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2023 Cloud Software Group, Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
package net.sf.jasperreports.ant;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.util.RegexpPatternMapper;
import org.apache.tools.ant.util.SourceFileScanner;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRReport;
import net.sf.jasperreports.engine.design.JRCompiler;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.util.JRApiWriter;
import net.sf.jasperreports.engine.util.JRClassLoader;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.engine.util.ReportCreator;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import net.sf.jasperreports.engine.xml.JRXmlWriter;
/**
* Ant task for batch-generating the Java source file that uses the JR API to create the report design,
* from compiled report template files or from source JRXML files.
* Works like the built-in javac
Ant task.
*
* This task can take the following arguments:
*
* - src
*
- destdir
*
* Of these arguments, the src
and destdir
are required.
* When this task executes, it will recursively scan the src
and
* destdir
looking for compiled report template files or for source
* JRXML report template files and it will recreate the Java source file for each of them.
* This task makes its file creation decision based on timestamp and only input files
* that have no corresponding file in the target directory or where the destination Java file
* is older than the input file will be processed.
*
* @author Teodor Danciu ([email protected])
*/
public class JRAntApiWriteTask extends JRBaseAntTask
{
/**
*
*/
private Path src;
private File destdir;
private Path classpath;
private boolean runApi;
private Map reportFilesMap;
/**
* Sets the source directories to find the source files.
*
* @param srcdir source path
*/
public void setSrcdir(Path srcdir)
{
if (src == null)
{
src = srcdir;
}
else
{
src.append(srcdir);
}
}
/**
* Adds a path for source report templates.
*
* @return source path
*/
public Path createSrc()
{
if (src == null)
{
src = new Path(getProject());
}
return src.createPath();
}
/**
* Sets the destination directory into which the Java report design files should be generated.
*
* @param destdir destination directory
*/
public void setDestdir(File destdir)
{
this.destdir = destdir;
}
/**
* Adds a path to the classpath.
*
* @return classpath to use when updating the report
*/
public Path createClasspath()
{
if (classpath == null)
{
classpath = new Path(getProject());
}
return classpath.createPath();
}
/**
* If set to true, the task will run the API writer generated classes and produce JRXML source files.
*/
public void setRunApi(boolean runApi)
{
this.runApi = runApi;
}
/**
* Executes the task.
*/
@Override
public void execute() throws BuildException
{
checkParameters();
reportFilesMap = new HashMap<>();
AntClassLoader classLoader = null;
if (classpath != null)
{
jasperReportsContext.setProperty(JRCompiler.COMPILER_CLASSPATH, String.valueOf(classpath));
ClassLoader parentClassLoader = getClass().getClassLoader();
classLoader = new AntClassLoader(parentClassLoader, getProject(), classpath, true);
classLoader.setThreadContextLoader();
}
try
{
/* */
scanSrc();
if (runApi)
{
/* */
runApi();
}
else
{
/* */
writeApi();
}
}
finally
{
if (classLoader != null)
{
classLoader.resetThreadContextLoader();
}
}
}
/**
* Checks that all required attributes have been set and that the supplied values are valid.
*/
protected void checkParameters() throws BuildException
{
if (src == null || src.size() == 0)
{
throw
new BuildException(
"The srcdir attribute must be set.",
getLocation()
);
}
if (destdir != null && !destdir.isDirectory())
{
throw
new BuildException(
"The destination directory \""
+ destdir
+ "\" does not exist "
+ "or is not a directory.",
getLocation()
);
}
}
/**
* Scans the source directories looking for source report design files to be processed.
*/
protected void scanSrc() throws BuildException
{
for(Iterator it = src.iterator(); it.hasNext();)
{
Resource resource = it.next();
FileResource fileResource = resource instanceof FileResource ? (FileResource)resource : null;
if (fileResource != null)
{
File file = fileResource.getFile();
if (file.isDirectory())
{
DirectoryScanner ds = getDirectoryScanner(file);
String[] files = ds.getIncludedFiles();
scanDir(file, destdir != null ? destdir : file, files);
}
else
{
String[] files = new String[]{fileResource.getName()};
scanDir(fileResource.getBaseDir(), destdir != null ? destdir : fileResource.getBaseDir(), files);
}
}
// else
// {
// //FIXME what to do?
// }
}
}
/**
* Scans the directory looking for source report design files to be processed.
* The results are returned in the instance variable reportFilesMap
.
*
* @param srcdir source directory
* @param destdir destination directory
* @param files included file names
*/
protected void scanDir(File srcdir, File destdir, String[] files)
{
RegexpPatternMapper mapper = new RegexpPatternMapper();
if (runApi)
{
mapper.setFrom("^(.*)\\.(.*)$");
mapper.setTo("\\1.api.jrxml");
}
else
{
mapper.setFrom("^(.*)\\.(.*)$");
mapper.setTo("\\1.java");
}
SourceFileScanner scanner = new SourceFileScanner(this);
String[] newFiles = scanner.restrict(files, srcdir, destdir, mapper);
if (newFiles != null && newFiles.length > 0)
{
for (int i = 0; i < newFiles.length; i++)
{
reportFilesMap.put(
(new File(srcdir, newFiles[i])).getAbsolutePath(),
(new File(destdir, mapper.mapFileName(newFiles[i])[0])).getAbsolutePath()
);
}
}
}
/**
* Performs the API code generation for the selected report design files.
*/
protected void writeApi() throws BuildException
{
Collection files = reportFilesMap.keySet();
if (files != null && files.size() > 0)
{
boolean isError = false;
System.out.println("Processing " + files.size() + " report design files.");
for (Iterator it = files.iterator(); it.hasNext();)
{
String srcFileName = it.next();
String destFileName = reportFilesMap.get(srcFileName);
File destFileParent = new File(destFileName).getParentFile();
if(!destFileParent.exists())
{
destFileParent.mkdirs();
}
String srcFileExtension = null;
int srcFileExtensionStart = srcFileName.lastIndexOf('.');
if (srcFileExtensionStart >= 0)
{
srcFileExtension = srcFileName.substring(srcFileExtensionStart);
}
try
{
System.out.print("File : " + srcFileName + " ... ");
JRReport report = null;
if ("jrxml".equalsIgnoreCase(srcFileExtension))
{
report = JRXmlLoader.load(srcFileName);
}
else if ("jasper".equalsIgnoreCase(srcFileExtension))
{
report = (JRReport)JRLoader.loadObjectFromFile(srcFileName);
}
else
{
try
{
report = (JRReport)JRLoader.loadObjectFromFile(srcFileName);
}
catch (JRException e)
{
report = JRXmlLoader.load(srcFileName);
}
}
new JRApiWriter(jasperReportsContext).write(report, destFileName);
System.out.println("OK.");
}
catch(JRException e)
{
System.out.println("FAILED.");
System.out.println("Error generating API report design : " + srcFileName);
e.printStackTrace(System.out);
isError = true;
}
}
if(isError)
{
throw new BuildException("Errors were encountered when generating API report designs.");
}
}
}
/**
* Runs the generated code and produces the JRXML image of the report.
*/
protected void runApi() throws BuildException
{
Collection files = reportFilesMap.keySet();
if (files != null && files.size() > 0)
{
boolean isError = false;
System.out.println("Running " + files.size() + " API report design files.");
for (Iterator it = files.iterator(); it.hasNext();)
{
String srcFileName = it.next();
String destFileName = reportFilesMap.get(srcFileName);
File destFileParent = new File(destFileName).getParentFile();
if(!destFileParent.exists())
{
destFileParent.mkdirs();
}
try
{
System.out.print("File : " + srcFileName + " ... ");
Class reportCreatorClass = JRClassLoader.loadClassFromFile(null, new File(srcFileName));
ReportCreator reportCreator = (ReportCreator)reportCreatorClass.getDeclaredConstructor().newInstance();
JasperDesign jasperDesign = reportCreator.create();
new JRXmlWriter(jasperReportsContext).write(jasperDesign, destFileName, "UTF-8");
System.out.println("OK.");
}
catch (JRException | IOException | NoSuchMethodException | InvocationTargetException | IllegalAccessException | InstantiationException e)
{
System.out.println("FAILED.");
System.out.println("Error running API report design class : " + srcFileName);
e.printStackTrace(System.out);
isError = true;
}
}
if(isError)
{
throw new BuildException("Errors were encountered when running API report designs classes.");
}
}
}
}