Java tutorial
package com.alexnederlof.jasperreport; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with this * work for additional information regarding copyright ownership. The ASF * licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ import java.io.File; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; import net.sf.jasperreports.engine.DefaultJasperReportsContext; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.design.JRCompiler; import net.sf.jasperreports.engine.design.JRJdtCompiler; import net.sf.jasperreports.engine.xml.JRReportSaxParserFactory; import org.apache.commons.lang.Validate; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; /** * This plugin compiles jasper source files to the target folder. While doing * so, it keeps the folder structure in tact. * * @goal jasper * @phase process-resources */ public class JasperReporter extends AbstractMojo { static final String ERROR_JRE_COMPILE_ERROR = "Some Jasper reports could not be compiled. See log above for details."; /** * This is the java compiler used * * @parameter * default-value="net.sf.jasperreports.engine.design.JRJdtCompiler" * @required */ private String compiler; /** * This is where the .jasper files are written. * * @parameter expression="${project.build.outputDirectory}/jasper" */ private File outputDirectory; /** * This is where the xml report design files should be. * * @parameter default-value="src/main/jasperreports" */ private File sourceDirectory; /** * The extension of the source files to look for. Finds files with a .jrxml * extension by default. * * @parameter default-value=".jrxml" */ private String sourceFileExt; /** * The extension of the compiled report files. Creates files with a .jasper * extension by default. * * @parameter default-value=".jasper" */ private String outputFileExt; /** * Check the source files before compiling. Default value is true. * * @parameter default-value="true" */ private boolean xmlValidation; /** * If verbose is on the plug-in will report which reports it is compiling and * which files are being skipped. * * @parameter default-value="false" */ private boolean verbose; /** * The number of threads the reporting will use. Default is 4 which is good * for a lot of reports on a hard drive (in stead of SSD). If you only have a * few, or if you have SSD, it might be faster to set it to 2. * * @parameter default-value=4 */ private int numberOfThreads; private Log log; public JasperReporter() { } @Override public void execute() throws MojoExecutionException { log = getLog(); if (outputDirectory.exists() && outputDirectory.listFiles().length > 0) { log.info("It seems the Jasper reports are already compiled. If you want to re-compile, run maven " + "with the 'clean' goal."); return; } if (verbose) { logConfiguration(log); } checkOutDirWritable(outputDirectory); configureJasper(); List<CompileTask> tasks = generateTasks(sourceDirectory, outputDirectory); if (tasks.isEmpty()) { log.info("Nothing to compile"); return; } executeTasks(tasks); } private void logConfiguration(Log log) { log.info("Generating Jasper reports"); log.info("Outputdir=" + outputDirectory.getAbsolutePath()); log.info("Sourcedir=" + sourceDirectory.getAbsolutePath()); log.info("Output ext=" + outputFileExt); log.info("Source ext=" + sourceFileExt); log.info("XML Validation=" + xmlValidation); log.info("JasperReports Compiler=" + compiler); log.info("Number of threads:" + numberOfThreads); } /** * Check if the output directory exist and is writable. If not, try to create * an output dir and see if that is writable. * * @param outputDirectory * @throws MojoExecutionException */ private void checkOutDirWritable(File outputDirectory) throws MojoExecutionException { if (outputDirectory.exists()) { if (outputDirectory.canWrite()) { return; } else { throw new MojoExecutionException("The output dir exists but was not writable. " + "Try running maven with the 'clean' goal."); } } checkIfOutpuCanBeCreated(); checkIfOutputDirIsWritable(); if (verbose) { getLog().info("Output dir check OK"); } } private void configureJasper() { DefaultJasperReportsContext jasperReportsContext = DefaultJasperReportsContext.getInstance(); jasperReportsContext.setProperty(JRReportSaxParserFactory.COMPILER_XML_VALIDATION, String.valueOf(xmlValidation)); jasperReportsContext.setProperty(JRCompiler.COMPILER_PREFIX, compiler == null ? JRJdtCompiler.class.getName() : compiler); jasperReportsContext.setProperty(JRCompiler.COMPILER_KEEP_JAVA_FILE, Boolean.FALSE.toString()); } private void checkIfOutpuCanBeCreated() throws MojoExecutionException { if (!outputDirectory.mkdirs()) { throw new MojoExecutionException(this, "Output folder could not be created", "Outputfolder " + outputDirectory.getAbsolutePath() + " is not a folder"); } } private void checkIfOutputDirIsWritable() throws MojoExecutionException { if (!outputDirectory.canWrite()) { throw new MojoExecutionException(this, "Could not write to output folder", "Could not write to output folder: " + outputDirectory.getAbsolutePath()); } } private List<CompileTask> generateTasks(File sourceDirectory, File destinationDirectory) { Validate.isTrue(sourceDirectory.isDirectory(), sourceDirectory.getName() + " is not a directory"); List<CompileTask> tasks = new LinkedList<CompileTask>(); for (File f : sourceDirectory.listFiles()) { generateTasks(destinationDirectory, tasks, f); } return tasks; } private void generateTasks(File destinationDirectory, List<CompileTask> tasks, File f) { if (f.isDirectory()) { tasks.addAll(generateTasks(f, createNewDest(f, destinationDirectory))); } else { // It is a file if (f.getName().endsWith(sourceFileExt)) { tasks.add(new CompileTask(f, destinationDirectory, sourceFileExt, outputFileExt, log, verbose)); } else if (verbose) { log.info("Skipped " + f.getName() + " because it doesnt have the extension " + sourceFileExt); } } } private File createNewDest(File origin, File destinationDirectory) { File newDest = new File(destinationDirectory, origin.getName()); newDest.mkdir(); return newDest; } private void executeTasks(List<CompileTask> tasks) throws MojoExecutionException { try { long t1 = System.currentTimeMillis(); List<Future<Void>> output = Executors.newFixedThreadPool(numberOfThreads).invokeAll(tasks); long time = (System.currentTimeMillis() - t1); getLog().info("Generated " + output.size() + " jasper reports in " + (time / 1000.0) + " seconds"); checkForExceptions(output); } catch (InterruptedException e) { log.error("Failed to compile Japser reports: Interrupted!", e); throw new MojoExecutionException("Error while compiling Jasper reports", e); } catch (ExecutionException e) { if (e.getCause() instanceof JRException) { throw new MojoExecutionException(ERROR_JRE_COMPILE_ERROR, e); } else { throw new MojoExecutionException("Error while compiling Jasper reports", e); } } } private void checkForExceptions(List<Future<Void>> output) throws InterruptedException, ExecutionException { for (Future<Void> future : output) { future.get(); } } }