package net.sf.jasperreports.engine.design; import java.io.File; import java.io.Serializable; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Random; import net.sf.jasperreports.crosstabs.JRCrosstab; import net.sf.jasperreports.crosstabs.design.JRDesignCrosstab; import net.sf.jasperreports.engine.JRDataset; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRExpressionCollector; import net.sf.jasperreports.engine.JRReport; import net.sf.jasperreports.engine.JRRuntimeException; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.fill.JREvaluator; import net.sf.jasperreports.engine.util.JRProperties; import net.sf.jasperreports.engine.util.JRSaver; import net.sf.jasperreports.engine.util.JRStringUtil; public abstract class JRAbstractCompiler implements JRCompiler { private static final int NAME_SUFFIX_RANDOM_MAX = 1000000; private static final Random random = new Random(); private final boolean needsSourceFiles; protected JRAbstractCompiler(boolean needsSourceFiles) { this.needsSourceFiles = needsSourceFiles; } public static String getUnitName(JasperReport report, JRDataset dataset) { return getUnitName((JRReport)report, dataset, report.getCompileNameSuffix()); } protected static String getUnitName(JRReport report, JRDataset dataset, String nameSuffix) { if (dataset.isMainDataset()) { className = report.getName(); } else { className = report.getName() + "_" + dataset.getName(); } String className = JRStringUtil.getLiteral(className) + nameSuffix; return className; } public static String getUnitName(JasperReport report, JRCrosstab crosstab) { return getUnitName((JRReport)report, crosstab.getId(), report.getCompileNameSuffix()); } protected static String getUnitName(JRReport report, JRCrosstab crosstab, JRExpressionCollector expressionCollector, String nameSuffix) { Integer crosstabId = expressionCollector.getCrosstabId(crosstab); if (crosstabId == null) throw new JRRuntimeException("Crosstab ID not found."); return getUnitName(report, crosstabId.intValue(), nameSuffix); } protected static String getUnitName(JRReport report, int crosstabId, String nameSuffix) { return JRStringUtil.getLiteral(report.getName()) + "_CROSSTAB" + crosstabId + nameSuffix; } public final JasperReport compileReport(JasperDesign jasperDesign) throws JRException { checkLanguage(jasperDesign.getLanguage()); JRExpressionCollector expressionCollector = JRExpressionCollector.collector((JRReport)jasperDesign); verifyDesign(jasperDesign, expressionCollector); String nameSuffix = createNameSuffix(); boolean isKeepJavaFile = JRProperties.getBooleanProperty("net.sf.jasperreports.compiler.keep.java.file"); File tempDirFile = null; if (isKeepJavaFile || this.needsSourceFiles) { String tempDirStr = JRProperties.getProperty("net.sf.jasperreports.compiler.temp.dir"); tempDirFile = new File(tempDirStr); if (!tempDirFile.exists() || !tempDirFile.isDirectory()) throw new JRException("Temporary directory not found : " + tempDirStr); } List datasets = jasperDesign.getDatasetsList(); List crosstabs = jasperDesign.getCrosstabs(); JRCompilationUnit[] units = new JRCompilationUnit[datasets.size() + crosstabs.size() + 1]; units[0] = createCompileUnit(jasperDesign, jasperDesign.getMainDesignDataset(), expressionCollector, tempDirFile, nameSuffix); int sourcesCount = 1; for (Iterator iterator = datasets.iterator(); iterator.hasNext(); sourcesCount++) { JRDesignDataset dataset = iterator.next(); units[sourcesCount] = createCompileUnit(jasperDesign, dataset, expressionCollector, tempDirFile, nameSuffix); } for (Iterator it = crosstabs.iterator(); it.hasNext(); sourcesCount++) { JRDesignCrosstab crosstab = it.next(); units[sourcesCount] = createCompileUnit(jasperDesign, crosstab, expressionCollector, tempDirFile, nameSuffix); } String classpath = JRProperties.getProperty("net.sf.jasperreports.compiler.classpath"); try { String compileErrors = compileUnits(units, classpath, tempDirFile); if (compileErrors != null) throw new JRException("Errors were encountered when compiling report expressions class file:\n" + compileErrors); JRReportCompileData reportCompileData = new JRReportCompileData(); reportCompileData.setMainDatasetCompileData(units[0].getCompileData()); for (ListIterator listIterator1 = datasets.listIterator(); listIterator1.hasNext(); ) { JRDesignDataset dataset = listIterator1.next(); reportCompileData.setDatasetCompileData((JRDataset)dataset, units[listIterator1.nextIndex()].getCompileData()); } for (ListIterator listIterator = crosstabs.listIterator(); listIterator.hasNext(); ) { JRDesignCrosstab crosstab = listIterator.next(); Integer crosstabId = expressionCollector.getCrosstabId((JRCrosstab)crosstab); reportCompileData.setCrosstabCompileData(crosstabId.intValue(), units[datasets.size() + listIterator.nextIndex()].getCompileData()); } JasperReport jasperReport = new JasperReport((JRReport)jasperDesign, getCompilerClass(), reportCompileData, expressionCollector, nameSuffix); return jasperReport; } catch (JRException e) { throw e; } catch (Exception e) { throw new JRException("Error compiling report design.", e); } finally { if (this.needsSourceFiles && !isKeepJavaFile) deleteSourceFiles(units); } } private static String createNameSuffix() { return "_" + System.currentTimeMillis() + "_" + random.nextInt(1000000); } protected String getCompilerClass() { return getClass().getName(); } private void verifyDesign(JasperDesign jasperDesign, JRExpressionCollector expressionCollector) throws JRException { Collection brokenRules = JRVerifier.verifyDesign(jasperDesign, expressionCollector); if (brokenRules != null && brokenRules.size() > 0) throw new JRValidationException(brokenRules); } private JRCompilationUnit createCompileUnit(JasperDesign jasperDesign, JRDesignDataset dataset, JRExpressionCollector expressionCollector, File saveSourceDir, String nameSuffix) throws JRException { String unitName = getUnitName((JRReport)jasperDesign, (JRDataset)dataset, nameSuffix); JRSourceCompileTask sourceTask = new JRSourceCompileTask(jasperDesign, dataset, expressionCollector, unitName); JRCompilationSourceCode sourceCode = generateSourceCode(sourceTask); File sourceFile = getSourceFile(saveSourceDir, unitName, sourceCode); return new JRCompilationUnit(unitName, sourceCode, sourceFile, expressionCollector.getExpressions((JRDataset)dataset)); } private JRCompilationUnit createCompileUnit(JasperDesign jasperDesign, JRDesignCrosstab crosstab, JRExpressionCollector expressionCollector, File saveSourceDir, String nameSuffix) throws JRException { String unitName = getUnitName((JRReport)jasperDesign, (JRCrosstab)crosstab, expressionCollector, nameSuffix); JRSourceCompileTask sourceTask = new JRSourceCompileTask(jasperDesign, crosstab, expressionCollector, unitName); JRCompilationSourceCode sourceCode = generateSourceCode(sourceTask); File sourceFile = getSourceFile(saveSourceDir, unitName, sourceCode); return new JRCompilationUnit(unitName, sourceCode, sourceFile, expressionCollector.getExpressions((JRCrosstab)crosstab)); } private File getSourceFile(File saveSourceDir, String unitName, JRCompilationSourceCode sourceCode) throws JRException { File sourceFile = null; if (saveSourceDir != null) { String fileName = getSourceFileName(unitName); sourceFile = new File(saveSourceDir, fileName); JRSaver.saveClassSource(sourceCode.getCode(), sourceFile); } return sourceFile; } private void deleteSourceFiles(JRCompilationUnit[] units) { for (int i = 0; i < units.length; i++) units[i].getSourceFile().delete(); } public JREvaluator loadEvaluator(JasperReport jasperReport) throws JRException { return loadEvaluator(jasperReport, jasperReport.getMainDataset()); } public JREvaluator loadEvaluator(JasperReport jasperReport, JRDataset dataset) throws JRException { String unitName = getUnitName(jasperReport, dataset); JRReportCompileData reportCompileData = (JRReportCompileData)jasperReport.getCompileData(); Serializable compileData = reportCompileData.getDatasetCompileData(dataset); return loadEvaluator(compileData, unitName); } public JREvaluator loadEvaluator(JasperReport jasperReport, JRCrosstab crosstab) throws JRException { String unitName = getUnitName(jasperReport, crosstab); JRReportCompileData reportCompileData = (JRReportCompileData)jasperReport.getCompileData(); Serializable compileData = reportCompileData.getCrosstabCompileData(crosstab); return loadEvaluator(compileData, unitName); } protected abstract JREvaluator loadEvaluator(Serializable paramSerializable, String paramString) throws JRException; protected abstract void checkLanguage(String paramString) throws JRException; protected abstract JRCompilationSourceCode generateSourceCode(JRSourceCompileTask paramJRSourceCompileTask) throws JRException; protected abstract String compileUnits(JRCompilationUnit[] paramArrayOfJRCompilationUnit, String paramString, File paramFile) throws JRException; protected abstract String getSourceFileName(String paramString); }