This patch replaces Jasper included to version 3 and also contains a new
ReportStarter class that accepts complex Jasper reports packed as a zip file.
Index: .project
===================================================================
--- .project (revision 5753)
+++ .project (working copy)
@@ -6,16 +6,6 @@
</projects>
<buildSpec>
<buildCommand>
- <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
- <triggers>full,incremental,</triggers>
- <arguments>
- <dictionary>
- <key>LaunchConfigHandle</key>
- <value><project>/.externalToolBuilders
/org.eclipse.wst.common.project.facet.core.builder.launch</value>
- </dictionary>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
Index: tools/lib/jfreechart-1.0.2.jar
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: tools/lib/jfreechart-1.0.3.jar
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: tools/lib/jfreechart-1.0.3.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: tools/build.xml
===================================================================
--- tools/build.xml (revision 5753)
+++ tools/build.xml (working copy)
@@ -360,7 +360,7 @@
<patternset refid="manifest.exclude"/>
</zipfileset>
<!-- JFreeChart -->
- <zipfileset src="lib/jfreechart-1.0.2.jar" >
+ <zipfileset src="lib/jfreechart-1.0.3.jar" >
<patternset refid="manifest.exclude"/>
</zipfileset>
<zipfileset src="lib/jcommon-1.0.5.jar" >
Index: .classpath
===================================================================
--- .classpath (revision 5753)
+++ .classpath (working copy)
@@ -46,7 +46,7 @@
<classpathentry exported="true" kind="lib" path="tools/lib/jgraph.jar"/>
<classpathentry exported="true" kind="lib" path="tools/lib/barbecue-1.1.jar"/>
<classpathentry exported="true" kind="lib" path="tools/lib/jcommon-1.0.5.jar"/>
- <classpathentry exported="true" kind="lib" path="tools/lib/jfreechart-1.0.2.jar"/>
+ <classpathentry exported="true" kind="lib" path="tools/lib/jfreechart-1.0.3.jar"/>
<classpathentry exported="true" kind="lib" path="tools/lib/postgresql.jar"/>
<classpathentry exported="true" kind="lib" path="posterita/src/web/WEB-INF/lib/struts.jar"/>
<classpathentry exported="true" kind="lib" path="posterita/src/web/WEB-INF/lib/barcode4j.jar"/>
@@ -70,7 +70,7 @@
<classpathentry exported="true" kind="lib" path="tools/lib/xml-apis.jar"/>
<classpathentry exported="true" kind="lib" path="tools/lib/itext-1.4.8.jar"/>
<classpathentry exported="true" kind="lib" path="tools/lib/jpedal.jar"/>
- <classpathentry exported="true" kind="lib" path="JasperReportsTools/lib/jasperreports-1.3.0.jar"/>
+ <classpathentry exported="true" kind="lib" path="JasperReportsTools/lib/jasperreports-3.0.0.jar"/>
<classpathentry exported="true" kind="lib" path="tools/lib/swingx-0.9.0.jar"/>
<classpathentry exported="true" kind="lib" path="tools/lib/bsh-2.0b5.jar"/>
<classpathentry exported="true" kind="lib" path="tools/lib/bsh-engine.jar"/>
Index: JasperReportsTools/lib/iReport.jar
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: JasperReportsTools/lib/jfreechart-1.0.3.jar
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: JasperReportsTools/lib/jfreechart-1.0.3.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: JasperReportsTools/lib/jasperreports-3.0.0.jar
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: JasperReportsTools/lib/jasperreports-3.0.0.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: JasperReports/src/org/compiere/report/FileVisitor.java
===================================================================
--- JasperReports/src/org/compiere/report/FileVisitor.java (revision 0)
+++ JasperReports/src/org/compiere/report/FileVisitor.java (revision 0)
@@ -0,0 +1,34 @@
+package org.compiere.report;
+
+
+import java.io.File;
+
+public class FileVisitor {
+ public interface Visitor
+ {
+ void visitFile(java.io.File file) throws Exception;
+ }
+ public static void visitRecursive(java.io.File dir, Visitor visitor) throws Exception
+ {
+ File[] fs=dir.listFiles();
+ if(fs!=null)
+ {
+ for(File f: fs)
+ {
+ visitor.visitFile(f);
+ visitRecursive(f, visitor);
+ }
+ }
+ }
+ public static void visit(java.io.File dir, Visitor visitor) throws Exception
+ {
+ File[] fs=dir.listFiles();
+ if(fs!=null)
+ {
+ for(File f: fs)
+ {
+ visitor.visitFile(f);
+ }
+ }
+ }
+}
Index: JasperReports/src/org/compiere/report/ReportStarter2.java
===================================================================
--- JasperReports/src/org/compiere/report/ReportStarter2.java (revision 0)
+++ JasperReports/src/org/compiere/report/ReportStarter2.java (revision 0)
@@ -0,0 +1,439 @@
+/*
+ */
+package org.compiere.report;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+
+import net.sf.jasperreports.engine.JasperExportManager;
+import net.sf.jasperreports.engine.JasperFillManager;
+import net.sf.jasperreports.engine.JasperPrint;
+import net.sf.jasperreports.engine.JasperPrintManager;
+import net.sf.jasperreports.engine.JasperReport;
+
+import org.compiere.db.ServerConnection;
+import org.compiere.process.ClientProcess;
+import org.compiere.process.ProcessCall;
+import org.compiere.process.ProcessInfo;
+import org.compiere.process.ProcessInfoParameter;
+import org.compiere.util.CLogger;
+import org.compiere.util.DB;
+import org.compiere.util.Env;
+import org.compiere.util.Ini;
+import org.compiere.util.Language;
+import org.compiere.util.Trx;
+import org.compiere.utils.DBUtils;
+
+/**
+ * @author rlemeill originaly coming from an application note from
+ * compiere.co.uk --- Modifications: Allow Jasper Reports to be able to
+ * be run on VPN profile (i.e: no direct connection to DB). Implemented
+ * ClientProcess for it to run on client.
+ * @author Ashley Ramdass
+ * @author victor.perez@e-evolution.com
+ * @see FR 1906632
+ * http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1906632&grou...
+ */
+public class ReportStarter2 implements ProcessCall, ClientProcess {
+ // logger
+ private static CLogger log = CLogger.getCLogger(ReportStarter2.class);
+
+ private static JRViewerProvider viewerProvider = new SwingJRViewerProvider();
+
+ static {
+ System.setProperty("javax.xml.parsers.SAXParserFactory",
+ "org.apache.xerces.jaxp.SAXParserFactoryImpl");
+ System.setProperty("org.xml.sax.driver",
+ "org.apache.xerces.parsers.SAXParser");
+ }
+
+ private ProcessInfo processInfo;
+
+
+ /**
+ * Returns the Server Connection if direct connection is not available (VPN,
+ * WAN, Terminal) and thus query has to be run on server only else return a
+ * direct connection to DB.
+ *
+ * Notes: Need to refactor and integrate in DB if confirmed to be working as
+ * expected.
+ *
+ * @author Ashley Ramdass
+ * @return Connection DB Connection
+ */
+ protected Connection getConnection() {
+ if (DB.isRemoteObjects()) {
+ return new ServerConnection();
+ } else {
+ return DB.getConnectionRW();
+ }
+ }
+
+ static JasperReportCache jasperReportCache;
+
+ void initCache() throws Exception {
+ if (jasperReportCache == null) {
+ jasperReportCache = new JasperReportCache();
+ }
+ }
+
+ /**
+ * Start the process. Called then pressing the Process button in R_Request.
+ * It should only return false, if the function could not be performed as
+ * this causes the process to abort.
+ *
+ * @author rlemeill
+ * @param ctx
+ * context
+ * @param pi
+ * Compiere standard process info
+ * @param trx
+ * @return true if success
+ */
+ public boolean startProcess(Properties ctx, ProcessInfo pi, Trx trx) {
+
+ processInfo = pi;
+ String Name = pi.getTitle();
+ int AD_PInstance_ID = pi.getAD_PInstance_ID();
+ int Record_ID = pi.getRecord_ID();
+ log.info("Name=" + Name + " AD_PInstance_ID=" + AD_PInstance_ID
+ + " Record_ID=" + Record_ID);
+ String trxName = null;
+ if (trx != null) {
+ trxName = trx.getTrxName();
+ }
+ try {
+ initCache();
+ ReportData reportData = getReportData(pi, trxName);
+ if (reportData == null) {
+ reportResult(AD_PInstance_ID, "Can not find report data",
+ trxName);
+ return false;
+ }
+
+ String reportPath = reportData.getReportFilePath();
+ if ((reportPath == null) || (reportPath.length() == 0)) {
+ throw new RuntimeException("Can not find report - report file name not set");
+ }
+
+ HashMap<String, Object> params = new HashMap(ctx);
+
+
+ addProcessParameters(AD_PInstance_ID, params, trxName);
+
+ addProcessInfoParameters(params, pi.getParameter());
+ JasperReportCache.FileLoadEnvironment fileLoadEnvironment=jasperReportCache.
new FileLoadEnvironment(pi, reportPath);
+ JasperReport jasperReport = fileLoadEnvironment.getRootReportFile();
+
+ if (jasperReport != null) {
+ if (Record_ID > 0)
+ params.put("RECORD_ID", new Integer(Record_ID));
+
+ // contribution from Ricardo (ralexsander)
+ // in iReports you can 'SELECT' AD_Client_ID, AD_Org_ID and
+ // AD_User_ID using only AD_PINSTANCE_ID
+ params.put("AD_PINSTANCE_ID", new Integer(AD_PInstance_ID));
+
+ Language currLang = Env.getLanguage(Env.getCtx());
+ params.put("CURRENT_LANG", currLang.getAD_Language());
+
+ fileLoadEnvironment.fillParams(params);
+ Connection conn = getConnection();
+ try {
+ JasperPrint jasperPrint = JasperFillManager.fillReport(
+ jasperReport, params, conn);
+ if (reportData.isDirectPrint()) {
+ log.info("ReportStarter.startProcess print report -"
+ + jasperPrint.getName());
+
+ // RF 1906632
+ if (!processInfo.isBatch())
+ JasperPrintManager.printReport(jasperPrint, false);
+ else {
+ // You can use JasperPrint to create PDF
+ // Used For the PH
+ try {
+ File PDF = File.createTempFile("mail", ".pdf");
+ JasperExportManager.exportReportToPdfFile(
+ jasperPrint, PDF.getAbsolutePath());
+ processInfo.setPDFReport(PDF);
+ } catch (IOException e) {
+ log
+ .severe("ReportStarter.startProcess:
Can not make PDF File - "
+ + e.getMessage());
+ }
+ }
+
+ // You can use JasperPrint to create PDF
+ // JasperExportManager.exportReportToPdfFile(jasperPrint,
+ // "BasicReport.pdf");
+ } else {
+ log.info("ReportStarter.startProcess run report -"
+ + jasperPrint.getName());
+ JRViewerProvider viewerLauncher = getReportViewerProvider();
+ viewerLauncher.openViewer(jasperPrint, pi.getTitle()
+ + " - " + reportPath);
+ }
+ } finally {
+ conn.close();
+ }
+ }
+ reportResult(AD_PInstance_ID, null, trxName);
+ } catch (Exception e) {
+ log.log(Level.SEVERE, "Jasper report process error", e);
+ reportResult(AD_PInstance_ID, e.toString(), trxName);
+ return false;
+ }
+
+ return true;
+ }
+
+
+ /**
+ * @author rlemeill
+ * @param AD_PInstance_ID
+ * @param errMsg
+ */
+ protected void reportResult(int AD_PInstance_ID, String errMsg,
+ String trxName) {
+ int result = (errMsg == null) ? 1 : 0;
+ errMsg = (errMsg == null) ? "" : errMsg;
+ String sql = "UPDATE AD_PInstance SET result=" + result
+ + ", errormsg='" + errMsg + "' " + "WHERE AD_PInstance_ID="
+ + AD_PInstance_ID;
+ Statement pstmt = null;
+ try {
+ pstmt = DB.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_UPDATABLE, trxName);
+ pstmt.executeUpdate(sql);
+ pstmt.close();
+ } catch (SQLException e) {
+ log.severe(sql + e.getMessage());
+ } finally {
+ DBUtils.close(pstmt);
+ }
+ }
+
+ protected void addProcessParameters(int AD_PInstance_ID,
+ Map<String, Object> params, String trxName) {
+ log.info("");
+ String sql = "SELECT ParameterName, " + "P_String, " + "P_String_To, "
+ + "P_Number, " + "P_Number_To, " + "P_Date, " + "P_Date_To "
+ + "FROM AD_PInstance_Para " + "WHERE AD_PInstance_ID=?";
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ pstmt = DB.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY, trxName);
+ pstmt.setInt(1, AD_PInstance_ID);
+ rs = pstmt.executeQuery();
+ while (rs.next()) {
+ String name = rs.getString(1);
+ String pStr = rs.getString(2);
+ String pStrTo = rs.getString(3);
+ // Double pNum = new Double( rs.getDouble(4));
+ // Double pNumTo = new Double( rs.getDouble(5));
+ BigDecimal pNum = rs.getBigDecimal(4);
+ BigDecimal pNumTo = rs.getBigDecimal(5);
+
+ Timestamp pDate = rs.getTimestamp(6);
+ Timestamp pDateTo = rs.getTimestamp(7);
+ if (pStr != null) {
+ if (pStrTo != null) {
+ params.put(name + "1", pStr);
+ params.put(name + "2", pStrTo);
+ } else {
+ params.put(name, pStr);
+ }
+ } else if (pDate != null) {
+ if (pDateTo != null) {
+ params.put(name + "1", pDate);
+ params.put(name + "2", pDateTo);
+ } else {
+ params.put(name, pDate);
+ }
+ } else if (pNum != null) {
+ if (rs.getBigDecimal(5) != null) {
+ params.put(name + "1", pNum);
+ params.put(name + "2", pNumTo);
+ } else {
+ params.put(name, pNum);
+ }
+ }
+ }
+ } catch (SQLException e) {
+ log.severe("Execption; sql = " + sql + "; e.getMessage() = "
+ + e.getMessage());
+ } finally {
+ DBUtils.close(rs);
+ DBUtils.close(pstmt);
+ }
+ }
+
+ private void addProcessInfoParameters(Map<String, Object> params,
+ ProcessInfoParameter[] para) {
+ if (para != null) {
+ for (int i = 0; i < para.length; i++) {
+ if (para[i].getParameter_To() == null) {
+ params.put(para[i].getParameterName(), para[i]
+ .getParameter());
+ } else {
+ params.put(para[i].getParameterName() + "1", para[i]
+ .getParameter());
+ params.put(para[i].getParameterName() + "2", para[i]
+ .getParameter_To());
+ }
+ }
+ }
+ }
+
+ /**
+ * @author rlemeill
+ * @param ProcessInfo
+ * @return ReportData
+ */
+ public ReportData getReportData(ProcessInfo pi, String trxName) {
+ log.info("");
+ String sql = "SELECT pr.JasperReport, pr.IsDirectPrint "
+ + "FROM AD_Process pr, AD_PInstance pi "
+ + "WHERE pr.AD_Process_ID = pi.AD_Process_ID "
+ + " AND pi.AD_PInstance_ID=?";
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ pstmt = DB.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY, trxName);
+ pstmt.setInt(1, pi.getAD_PInstance_ID());
+ rs = pstmt.executeQuery();
+ String path = null;
+ boolean directPrint = false;
+ boolean isPrintPreview = pi.isPrintPreview();
+ if (rs.next()) {
+ path = rs.getString(1);
+
+ if ("Y".equalsIgnoreCase(rs.getString(2))
+ && !Ini.isPropertyBool(Ini.P_PRINTPREVIEW)
+ && !isPrintPreview)
+ directPrint = true;
+ } else {
+ log.severe("data not found; sql = " + sql);
+ return null;
+ }
+
+ return new ReportData(path, directPrint);
+ } catch (SQLException e) {
+ log.severe("sql = " + sql + "; e.getMessage() = " + e.getMessage());
+ return null;
+ } finally {
+ DBUtils.close(rs);
+ DBUtils.close(pstmt);
+ }
+ }
+
+ /**
+ * Set jasper report viewer provider.
+ *
+ * @param provider
+ */
+ public static void setReportViewerProvider(JRViewerProvider provider) {
+ if (provider == null)
+ throw new IllegalArgumentException(
+ "Cannot set report viewer provider to null");
+ viewerProvider = provider;
+ }
+
+ /**
+ * Get the current jasper report viewer provider
+ *
+ * @return JRViewerProvider
+ */
+ public static JRViewerProvider getReportViewerProvider() {
+ return viewerProvider;
+ }
+
+ class ReportData {
+ private String reportFilePath;
+ private boolean directPrint;
+
+ public ReportData(String reportFilePath, boolean directPrint) {
+ this.reportFilePath = reportFilePath;
+ this.directPrint = directPrint;
+ }
+
+ public String getReportFilePath() {
+ return reportFilePath;
+ }
+
+ public boolean isDirectPrint() {
+ return directPrint;
+ }
+ }
+
+ class JasperData {
+ private JasperReport jasperReport;
+ private File reportDir;
+ private String jasperName;
+ private File jasperFile;
+
+ public JasperData(JasperReport jasperReport, File reportDir,
+ String jasperName, File jasperFile) {
+ this.jasperReport = jasperReport;
+ this.reportDir = reportDir;
+ this.jasperName = jasperName;
+ this.jasperFile = jasperFile;
+ }
+
+ public JasperReport getJasperReport() {
+ return jasperReport;
+ }
+
+ public File getReportDir() {
+ return reportDir;
+ }
+
+ public String getJasperName() {
+ return jasperName;
+ }
+
+ public File getJasperFile() {
+ return jasperFile;
+ }
+ }
+
+ class FileFilter implements FilenameFilter {
+ private String reportStart;
+ private File directory;
+ private String extension;
+
+ public FileFilter(String reportStart, File directory, String extension) {
+ this.reportStart = reportStart;
+ this.directory = directory;
+ this.extension = extension;
+ }
+
+ public boolean accept(File file, String name) {
+ if (file.equals(directory)) {
+ if (name.startsWith(reportStart)) {
+ int pos = name.lastIndexOf(extension);
+ if ((pos != -1)
+ && (pos == (name.length() - extension.length())))
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
Index: JasperReports/src/org/compiere/report/JasperReportCache.java
===================================================================
--- JasperReports/src/org/compiere/report/JasperReportCache.java (revision 0)
+++ JasperReports/src/org/compiere/report/JasperReportCache.java (revision 0)
@@ -0,0 +1,397 @@
+package org.compiere.report;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import net.sf.jasperreports.engine.JRException;
+import net.sf.jasperreports.engine.JasperCompileManager;
+import net.sf.jasperreports.engine.JasperReport;
+import net.sf.jasperreports.engine.util.FileResolver;
+import net.sf.jasperreports.engine.util.JRLoader;
+
+import org.compiere.process.ProcessInfo;
+import org.compiere.util.CLogger;
+import org.compiere.util.ZipUtil;
+import org.compiere.utils.DigestOfFile;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+/**
+ * Cache compiled jasper reports on the client. Handle several type of jasper
+ * report file source.
+ *
+ * @author schmidta
+ *
+ */
+public class JasperReportCache {
+ FileSource fileSource = new FileSource();
+
+ @Override
+ public String toString() {
+ return super.toString() + " on " + cacheDir;
+ }
+
+ public JasperReportCache() throws Exception {
+ init();
+ }
+
+ public class FileLoadEnvironment
+ {
+ ProcessInfo pi;
+ String jasperPath;
+ File jasperDir;
+ public FileLoadEnvironment(ProcessInfo pi, String jasperPath) throws
XPathExpressionException, IOException, SAXException, ParserConfigurationException, JRException {
+ super();
+ this.pi = pi;
+ this.jasperPath=jasperPath;
+ jasperDir=checkLocalCopyOfZip();
+ }
+ public JasperReport getRootReportFile() throws Exception {
+ return (JasperReport) JRLoader.loadObject(new File(jasperDir, "report.jasper"));
+ }
+ public FileResolver getFileResolver() {
+ return new FileResolver()
+ {
+ public File resolveFile(String arg0) {
+ File ret=new File(jasperDir, arg0);
+ log.info("Resolving file: "+arg0 +" to: "+ret);
+ return ret;
+ }
+ };
+ }
+ @Override
+ public String toString() {
+ return "Jasper zip: "+jasperPath;
+ }
+ public void fillParams(Map<String, Object> params) {
+ params.put(net.sf.jasperreports.engine.JRParameter.REPORT_FILE_RESOLVER,
+ getFileResolver());
+ params.put("SUBREPORT_DIR", "");
+ }
+
+ /**
+ * Check and create or refresh the local copy of a report file.
+ *
+ * @param reportPath
+ * @return
+ * @throws IOException
+ * @throws ParserConfigurationException
+ * @throws SAXException
+ * @throws XPathExpressionException
+ * @throws JRException
+ */
+ protected File checkLocalCopyOfZip() throws IOException,
+ XPathExpressionException, SAXException,
+ ParserConfigurationException, JRException {
+ try {
+ String name = getFileName(jasperPath);
+ File localFile = new File(cacheDir, name);
+ File zipDir=new File(localFile.getParentFile(),
+ localFile.getName().substring(0,
+ localFile.getName().length()-".zip".length()));
+ if (!isFresh(this, localFile, this.jasperPath)) {
+ UtilFile.deleteRec(zipDir);
+ fileSource.copyTo(this, jasperPath, localFile);
+ log.info("unzipping: "+localFile.getAbsolutePath()+" to: "+zipDir.getAbsolutePath());
+ ZipUtil.unzip(localFile,
+ zipDir);
+ compileAll(zipDir);
+ processed.add(jasperPath);
+ }
+ return zipDir;
+ } catch (Exception e) {
+ throw new RuntimeException("Error resolving "
+ + this, e);
+ }
+ }
+
+ }
+ interface IFileSource {
+ boolean handles(FileLoadEnvironment loadEnvironment,String fileName) throws Exception;
+
+ String getMd5(FileLoadEnvironment loadEnvironment, String fileName) throws Exception;
+
+ void copyTo(FileLoadEnvironment loadEnvironment, String fileName, File target) throws Exception;
+ }
+
+ class FileSource implements IFileSource {
+ List<IFileSource> types;
+
+ public FileSource() {
+ types = new ArrayList<IFileSource>();
+ types.add(new JasperFileSourceAttachment());
+ types.add(new JasperFileSourceURL());
+ types.add(new JasperFileSourceFile());
+ }
+
+ IFileSource getType(FileLoadEnvironment loadEnvironment, String reportPath) throws Exception {
+ for (IFileSource type : types) {
+ if (type.handles(loadEnvironment, reportPath)) {
+ return type;
+ }
+ }
+ throw new IOException("report file name is not handled: "
+ + reportPath);
+ }
+
+ public String getMd5(FileLoadEnvironment loadEnvironment, String fileName) throws Exception {
+ IFileSource type = getType(loadEnvironment, fileName);
+ return type.getMd5(loadEnvironment, fileName);
+ }
+
+ public void copyTo(FileLoadEnvironment loadEnvironment, String fileName, File target) throws Exception {
+ IFileSource type = getType(loadEnvironment, fileName);
+ type.copyTo(loadEnvironment, fileName, target);
+ }
+
+ public boolean handles(FileLoadEnvironment loadEnvironment, String fileName) throws Exception {
+ return getType(loadEnvironment, fileName) != null;
+ }
+ }
+
+ private static CLogger log = CLogger.getCLogger(JasperReportCache.class);
+
+ File cacheDir;
+ boolean inited = false;
+
+ void init() throws Exception {
+ if (!inited) {
+ cacheDir = File.createTempFile("jasper", "cache");
+// cacheDir=new File("/tmp/jasperCache");
+ UtilFile.deleteRec(cacheDir);
+ cacheDir.mkdir();
+ inited = true;
+ }
+ }
+
+ String getFileName(String reportPath) {
+ int idx = reportPath.lastIndexOf("/");
+ if (idx >= 0) {
+ reportPath = reportPath.substring(idx + 1);
+ }
+ idx = reportPath.lastIndexOf(File.separator);
+ if (idx >= 0) {
+ reportPath = reportPath.substring(idx + 1);
+ }
+ return reportPath;
+ }
+
+ String getFileNameWithoutExtension(String reportPath) {
+ int idx = reportPath.lastIndexOf("/");
+ if (idx >= 0) {
+ reportPath = reportPath.substring(idx + 1);
+ }
+ idx = reportPath.lastIndexOf('.');
+ if (idx >= 0) {
+ reportPath = reportPath.substring(0, idx);
+ }
+ return reportPath;
+ }
+
+ String getFilePath(String reportPath) {
+ int idx = reportPath.lastIndexOf("/");
+ if (idx >= 0) {
+ reportPath = reportPath.substring(0, idx + 1);
+ return reportPath;
+ }
+ return "";
+ }
+
+ String getFileExtension(String reportPath) {
+ int idx = reportPath.lastIndexOf(".");
+ if (idx >= 0) {
+ return reportPath.substring(idx);
+ }
+ return "";
+ }
+ /**
+ * Check and create or refresh the local copy of a report file.
+ *
+ * @param reportPath
+ * @return
+ * @throws IOException
+ * @throws ParserConfigurationException
+ * @throws SAXException
+ * @throws XPathExpressionException
+ * @throws JRException
+ */
+ private File checkLocalCopyOfFile(FileLoadEnvironment loadEnvironment, String reportPath) throws IOException,
+ XPathExpressionException, SAXException,
+ ParserConfigurationException, JRException {
+ try {
+ String name = getFileName(reportPath);
+ String path = getFilePath(reportPath);
+ String extension = getFileExtension(reportPath);
+ File localFile = new File(cacheDir, name);
+ File localJasper = new File(cacheDir,
+ getFileNameWithoutExtension(reportPath)+".jasper");
+ if (!isFresh(loadEnvironment, localFile, reportPath)) {
+ fileSource.copyTo(loadEnvironment, reportPath, localFile);
+ JasperCompileManager.compileReportToFile(localFile
+ .getAbsolutePath(), localJasper.getAbsolutePath());
+ }
+ List<String> subreps = getSubreportPaths(localFile);
+ for (String s : subreps) {
+ if (s.endsWith(".jasper")) {
+ s = s.substring(0, s.length() - ".jasper".length())
+ + extension;
+ }
+ String subReportPath = path + s;
+ checkLocalCopyOfFile(loadEnvironment, subReportPath);
+ }
+ return localJasper;
+ } catch (Exception e) {
+ throw new RuntimeException("Error resolving Jasper file: "
+ + reportPath, e);
+ }
+ }
+
+ private void compileAll(File zipDir) throws Exception {
+ FileVisitor.visitRecursive(zipDir, new FileVisitor.Visitor(){
+ public void visitFile(File file) throws Exception{
+ if(file.exists()&&file.isFile()&&file.getName().endsWith(".jrxml"))
+ {
+ File localJasper = new File(file.getParentFile(),
+ getFileNameWithoutExtension(file.getName())+".jasper");
+ JasperCompileManager.compileReportToFile(file
+ .getAbsolutePath(), localJasper.getAbsolutePath());
+ }
+ }});
+ }
+
+ /**
+ * @author rlemeill Correct the class path if loaded from java web start
+ */
+ private void JWScorrectClassPath() {
+ URL jasperreportsAbsoluteURL = Thread.currentThread()
+ .getContextClassLoader().getResource(
+ "net/sf/jasperreports/engine");
+ String jasperreportsAbsolutePath = "";
+
+ if (jasperreportsAbsoluteURL.toString().startsWith("jar:http:")
+ || jasperreportsAbsoluteURL.toString().startsWith("jar:https:")) {
+ // Jasper classes are deployed to a webserver (Java Webstart)
+ jasperreportsAbsolutePath = jasperreportsAbsoluteURL.toString()
+ .split("!")[0].split("jar:")[1];
+
+ // Download the required jasper libraries if they are not already
+ // existing
+ File reqLib = new File(System.getProperty("java.io.tmpdir"),
+ "CompiereJasperReqs.jar");
+ if (!reqLib.exists() && !(reqLib.length() > 0)) {
+ try {
+ URL reqLibURL = new URL(jasperreportsAbsolutePath);
+ InputStream in = reqLibURL.openStream();
+
+ FileOutputStream fout = new FileOutputStream(reqLib);
+
+ byte buf[] = new byte[1024];
+ int s = 0;
+
+ while ((s = in.read(buf, 0, 1024)) > 0)
+ fout.write(buf, 0, s);
+
+ in.close();
+ fout.flush();
+ fout.close();
+ } catch (FileNotFoundException e) {
+ log.warning("Required library not found " + e.getMessage());
+ reqLib.delete();
+ reqLib = null;
+ } catch (IOException e) {
+ log
+ .severe("I/O error downloading required library from server "
+ + e.getMessage());
+ reqLib.delete();
+ reqLib = null;
+ }
+ }
+
+ jasperreportsAbsolutePath = reqLib.getAbsolutePath();
+ } else {
+ // Jasper classes are locally available (Local client)
+ jasperreportsAbsolutePath = jasperreportsAbsoluteURL.toString()
+ .split("!")[0].split("file:")[1];
+ }
+
+ if (jasperreportsAbsolutePath != null
+ && !jasperreportsAbsolutePath.trim().equals("")) {
+ // Check whether the current CLASSPATH already contains our
+ // jasper libraries and dependencies or not.
+ if (System.getProperty("java.class.path").indexOf(
+ jasperreportsAbsolutePath) < 0) {
+ System.setProperty("java.class.path", System
+ .getProperty("java.class.path")
+ + System.getProperty("path.separator")
+ + jasperreportsAbsolutePath);
+ log.info("Classpath has been corrected to "
+ + System.getProperty("java.class.path"));
+ }
+ }
+ }
+
+ static List<String> getSubreportPaths(File f)
+ throws XPathExpressionException, SAXException, IOException,
+ ParserConfigurationException {
+ List<String> ret = new ArrayList<String>();
+ String expression = "//subreport/subreportExpression";
+ // Compile the expression to get a XPathExpression object.
+ Document xmlDocument = DocumentBuilderFactory.newInstance()
+ .newDocumentBuilder().parse(f);
+ XPathFactory xPathFactory = XPathFactory.newInstance();
+ // To get an instance of the XPathFactory object itself.
+
+ XPath xPath = xPathFactory.newXPath();
+ // Create an instance of XPath from the factory class.
+ XPathExpression xPathExpression = xPath.compile(expression);
+ Object result = xPathExpression.evaluate(xmlDocument,
+ XPathConstants.NODESET);
+ NodeList l = (NodeList) result;
+ XPathExpression toString = xPath.compile(".");
+ for (int i = 0; i < l.getLength(); ++i) {
+ Object item = l.item(i);
+ String s = "" + toString.evaluate(item);
+ int a = s.indexOf('\"');
+ int b = s.lastIndexOf('\"');
+ if (a >= 0 && b > a) {
+ ret.add(s.substring(a + 1, b));
+ }
+ }
+ return ret;
+ }
+ Set<String> processed=new TreeSet<String>();
+ private boolean isFresh(FileLoadEnvironment loadEnvironment, File localFile, String reportPath)
+ throws Exception {
+ if (!localFile.exists()) {
+ return false;
+ }
+ if(processed.contains(reportPath))
+ {
+ String md5local = DigestOfFile.GetLocalMD5Hash(localFile);
+ String md5remote = fileSource.getMd5(loadEnvironment, reportPath);
+ return md5local.equals(md5remote);
+ }else
+ {
+ return false;
+ }
+ }
+
+}
Index: JasperReports/src/org/compiere/report/JasperFileSourceFile.java
===================================================================
--- JasperReports/src/org/compiere/report/JasperFileSourceFile.java (revision 0)
+++ JasperReports/src/org/compiere/report/JasperFileSourceFile.java (revision 0)
@@ -0,0 +1,65 @@
+package org.compiere.report;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.compiere.report.JasperReportCache.FileLoadEnvironment;
+import org.compiere.util.Ini;
+import org.compiere.util.ZipUtil;
+import org.compiere.utils.DigestOfFile;
+
+public class JasperFileSourceFile implements JasperReportCache.IFileSource {
+ private static File REPORT_HOME = null;
+ static {
+ String reportPath = System.getProperty("org.compiere.report.path");
+ if (reportPath == null) {
+ REPORT_HOME = new File(Ini.getAdempiereHome() + File.separator
+ + "reports");
+ } else {
+ REPORT_HOME = new File(reportPath);
+ }
+ }
+
+ File getFile(FileLoadEnvironment loadEnvironment, String reportPath) throws URISyntaxException {
+ if (reportPath.startsWith("/")) {
+ return new File(reportPath);
+ } else if (reportPath.startsWith("file:/")) {
+ return new File(new URI(reportPath));
+ } else {
+ return new File(REPORT_HOME, reportPath);
+ }
+ }
+
+ public void copyTo(FileLoadEnvironment loadEnvironment, String fileName, File target) throws IOException, URISyntaxException {
+ File source=getFile(loadEnvironment, fileName);
+ copy(source,target);
+ }
+
+ void copy(File inputFile, File outputFile) throws IOException {
+ FileInputStream in = new FileInputStream(inputFile);
+ try {
+ FileOutputStream out = new FileOutputStream(outputFile);
+ try {
+ ZipUtil.copyInputStream(in, out);
+ } finally {
+ out.close();
+ }
+ } finally {
+ in.close();
+ }
+ }
+
+ public String getMd5(FileLoadEnvironment loadEnvironment, String fileName) throws IOException, URISyntaxException {
+ String md5local = DigestOfFile.GetLocalMD5Hash(getFile(loadEnvironment, fileName));
+ return md5local;
+ }
+
+ public boolean handles(FileLoadEnvironment loadEnvironment, String fileName) {
+ return true;
+ }
+
+}
Index: JasperReports/src/org/compiere/report/JasperFileSourceURL.java
===================================================================
--- JasperReports/src/org/compiere/report/JasperFileSourceURL.java (revision 0)
+++ JasperReports/src/org/compiere/report/JasperFileSourceURL.java (revision 0)
@@ -0,0 +1,69 @@
+package org.compiere.report;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.compiere.model.MAttachment;
+import org.compiere.model.MAttachmentEntry;
+import org.compiere.model.MProcess;
+import org.compiere.report.JasperReportCache.FileLoadEnvironment;
+import org.compiere.util.Env;
+import org.compiere.utils.DigestOfFile;
+
+public class JasperFileSourceURL implements JasperReportCache.IFileSource {
+
+ MAttachmentEntry getAttachment(FileLoadEnvironment loadEnvironment,
+ String fileName) throws IOException
+ {
+ String name = fileName.substring(prefix.length()).trim();
+ if(name.startsWith("//"))
+ {
+ name=name.substring(2);
+ }
+ MProcess process = new MProcess(Env.getCtx(),
+ loadEnvironment.
+ pi.getAD_Process_ID(),
+ loadEnvironment.pi.getTransactionName());
+ MAttachment attachment = process.getAttachment();
+ if (attachment != null) {
+ MAttachmentEntry[] entries = attachment.getEntries();
+ for (int i = 0; i < entries.length; i++) {
+ if (entries[i].getName().equals(name)) {
+ return entries[i];
+ }
+ }
+ }
+ throw new IOException("Process attachment does not exist: "+fileName+" on process: "+loadEnvironment.pi.getAD_Process_ID());
+ }
+ String prefix="attachment:";
+ public void copyTo(FileLoadEnvironment loadEnvironment, String fileName, File target) throws Exception {
+ MAttachmentEntry entry=getAttachment(loadEnvironment, fileName);
+ FileOutputStream fos=new FileOutputStream(target);
+ try
+ {
+ fos.write(entry.getData());
+ }finally
+ {
+ fos.close();
+ }
+ }
+
+ public String getMd5(FileLoadEnvironment loadEnvironment, String fileName) throws Exception {
+ MAttachmentEntry entry=getAttachment(loadEnvironment, fileName);
+ return DigestOfFile.getMD5Hash(entry.getData());
+ }
+
+ public boolean handles(FileLoadEnvironment loadEnvironment, String fileName) throws Exception {
+ return false;
+// java.net.URL url=new URL(fileName);
+// InputStream is=url.openStream();
+// try
+// {
+// return is!=null;
+// }finally
+// {
+// is.close();
+// }
+ }
+}
Index: JasperReports/src/org/compiere/report/UtilFile.java
===================================================================
--- JasperReports/src/org/compiere/report/UtilFile.java (revision 0)
+++ JasperReports/src/org/compiere/report/UtilFile.java (revision 0)
@@ -0,0 +1,57 @@
+package org.compiere.report;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+
+public class UtilFile {
+ public static String loadResourceAsString(Class<?> c, String res) throws IOException
+ {
+ URL url=c.getResource(res);
+ InputStream is=url.openStream();
+ try
+ {
+ StringBuilder ret=new StringBuilder();
+ InputStreamReader isr=new InputStreamReader(is,"UTF-8");
+ char[] chs=new char[1024];
+ int count;
+ while((count=isr.read(chs))>0)
+ {
+ ret.append(chs,0,count);
+ }
+ return ret.toString();
+ }finally
+ {
+ is.close();
+ }
+ }
+
+ public static void deleteRec(File toDelete) throws Exception {
+ if(!toDelete.exists())
+ {
+ return;
+ }
+ final List<File> l=new ArrayList<File>();
+ l.add(toDelete);
+ FileVisitor.visitRecursive(toDelete, new FileVisitor.Visitor()
+ {
+ public void visitFile(File file) throws Exception {
+ l.add(file);
+ }
+ });
+ Collections.reverse(l);
+ for(File f:l)
+ {
+ if(!f.delete())
+ {
+ throw new IOException("Cannot delete file: "+f);
+ }
+ }
+ }
+}
Index: JasperReports/src/org/compiere/report/JasperFileSourceAttachment.java
===================================================================
--- JasperReports/src/org/compiere/report/JasperFileSourceAttachment.java (revision 0)
+++ JasperReports/src/org/compiere/report/JasperFileSourceAttachment.java (revision 0)
@@ -0,0 +1,60 @@
+package org.compiere.report;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.compiere.model.MAttachment;
+import org.compiere.model.MAttachmentEntry;
+import org.compiere.model.MProcess;
+import org.compiere.report.JasperReportCache.FileLoadEnvironment;
+import org.compiere.util.Env;
+import org.compiere.utils.DigestOfFile;
+
+public class JasperFileSourceAttachment implements JasperReportCache.IFileSource {
+
+ MAttachmentEntry getAttachment(FileLoadEnvironment loadEnvironment,
+ String fileName) throws IOException
+ {
+ String name = fileName.substring(prefix.length()).trim();
+ if(name.startsWith("//"))
+ {
+ name=name.substring(2);
+ }
+ MProcess process = new MProcess(Env.getCtx(),
+ loadEnvironment.
+ pi.getAD_Process_ID(),
+ loadEnvironment.pi.getTransactionName());
+ MAttachment attachment = process.getAttachment();
+ if (attachment != null) {
+ MAttachmentEntry[] entries = attachment.getEntries();
+ for (int i = 0; i < entries.length; i++) {
+ if (entries[i].getName().equals(name)) {
+ return entries[i];
+ }
+ }
+ }
+ throw new IOException("Process attachment does not exist: "+fileName+" on process: "+loadEnvironment.pi.getAD_Process_ID());
+ }
+ String prefix="attachment:";
+ public void copyTo(FileLoadEnvironment loadEnvironment, String fileName, File target) throws Exception {
+ MAttachmentEntry entry=getAttachment(loadEnvironment, fileName);
+ FileOutputStream fos=new FileOutputStream(target);
+ try
+ {
+ fos.write(entry.getData());
+ }finally
+ {
+ fos.close();
+ }
+ }
+
+ public String getMd5(FileLoadEnvironment loadEnvironment, String fileName) throws Exception {
+ MAttachmentEntry entry=getAttachment(loadEnvironment, fileName);
+ return DigestOfFile.getMD5Hash(entry.getData());
+ }
+
+ public boolean handles(FileLoadEnvironment loadEnvironment, String fileName) throws Exception {
+ return fileName.startsWith(prefix);
+ }
+}
Index: JasperReports/build.xml
===================================================================
--- JasperReports/build.xml (revision 5753)
+++ JasperReports/build.xml (working copy)
@@ -64,7 +64,7 @@
<pathelement path="../lib/CSTools.jar"/>
<pathelement path="../looks/CLooks.jar"/>
<pathelement path="../lib/oracle.jar"/>
- <pathelement path="../JasperReportsTools/lib/jasperreports-1.3.0.jar"/>
+ <pathelement path="../JasperReportsTools/lib/jasperreports-3.0.0.jar"/>
<pathelement path="../JasperReportsTools/lib/commons-digester-1.7.jar"/>
<pathelement path="../tools/lib/commons-collections-3.1.jar"/>
<pathelement path="../tools/lib/commons-logging.jar"/>
@@ -124,14 +124,14 @@
</patternset>
</unjar>
<!-- futur dev jfree chart but it needs scriptlets
- <unjar src="../tools/lib/jfreechart-0.9.21.jar" dest="${needed.dir}" />
+ <unjar src="../tools/lib/jfreechart-1.0.3.jar" dest="${needed.dir}" />
-->
<jar jarfile="${dist.dir}/${needed.jar.name}.jar"
excludes="**/*.jbx"
index="yes"
duplicate="preserve">
<fileset dir="${needed.dir}"/>
- <zipfileset src="../JasperReportsTools/lib/jasperreports-1.3.0.jar" >
+ <zipfileset src="../JasperReportsTools/lib/jasperreports-3.0.0.jar" >
<patternset refid="manifest.exclude"/>
</zipfileset>
<zipfileset src="../JasperReportsTools/lib/commons-digester-1.7.jar" >
Index: base/src/org/compiere/util/ZipUtil.java
===================================================================
--- base/src/org/compiere/util/ZipUtil.java (revision 5753)
+++ base/src/org/compiere/util/ZipUtil.java (working copy)
@@ -435,5 +435,63 @@
System.err.println(ex);
}
}
+
+ public static final void copyInputStream(InputStream in, OutputStream out)
+ throws IOException {
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = in.read(buffer)) >= 0)
+ out.write(buffer, 0, len);
+
+ in.close();
+ out.close();
+ }
+
+ static CLogger log = CLogger.getCLogger(ZipUtil.class);
+
+ /**
+ * Unzip a zip file into a directory.
+ *
+ * @param zipF
+ * @param toDir
+ */
+ public static void unzip(File zipF, File toDir) {
+
+ try {
+ ZipFile zipFile = new ZipFile(zipF);
+
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ log.info("unzipping file: " + zipF.getAbsolutePath() + " todir: "
+ + toDir.getAbsolutePath());
+
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ File target = new File(toDir, entry.getName());
+ if (entry.isDirectory()) {
+ // Assume directories are stored parents first then
+ // children.
+ System.err.println("Extracting directory: "
+ + entry.getName());
+ // This is not robust, just for demonstration purposes.
+ target.mkdirs();
+ } else {
+ log.info("unzipping file to: " + target.getAbsolutePath());
+ target.getParentFile().mkdirs();
+ copyInputStream(zipFile.getInputStream(entry),
+ new BufferedOutputStream(new FileOutputStream(
+ target)));
+
+ }
+ }
+
+ zipFile.close();
+ } catch (IOException ioe) {
+ System.err.println("Unhandled exception:");
+ ioe.printStackTrace();
+ return;
+ }
+ }
+
+
} // ZipUtil
Index: client/build.xml
===================================================================
--- client/build.xml (revision 5753)
+++ client/build.xml (working copy)
@@ -28,7 +28,7 @@
<pathelement path="../lib/customization.jar"/>
<pathelement path="../lib/patches.jar"/>
<pathelement path="../lib/jcommon-1.0.5.jar"/>
- <pathelement path="../lib/jfreechart-1.0.2.jar"/>
+ <pathelement path="../lib/jfreechart-1.0.3.jar"/>
<pathelement path="../looks/CLooks.jar"/>
<pathelement path="../extend/Extend.jar"/>
<pathelement path="../tools/lib/j2ee.jar"/>
No comments:
Post a Comment