Sunday, September 9, 2012

Sample code for adempiere jasperreport


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>&lt;project&gt;/.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