IDEMPIERE-4873 Jasper Report Starter Refactoring (#779)
This commit is contained in:
parent
8d5cf4539d
commit
162c48ec4c
|
@ -16,16 +16,20 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package org.compiere.util;
|
package org.compiere.util;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.io.File;
|
||||||
import java.awt.font.TextAttribute;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.text.AttributedCharacterIterator;
|
import java.text.AttributedCharacterIterator;
|
||||||
import java.text.AttributedString;
|
import java.text.AttributedString;
|
||||||
import java.text.Normalizer;
|
import java.text.Normalizer;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -37,6 +41,13 @@ import javax.swing.InputMap;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
|
|
||||||
|
import com.itextpdf.text.Document;
|
||||||
|
import com.itextpdf.text.DocumentException;
|
||||||
|
import com.itextpdf.text.pdf.PdfContentByte;
|
||||||
|
import com.itextpdf.text.pdf.PdfImportedPage;
|
||||||
|
import com.itextpdf.text.pdf.PdfReader;
|
||||||
|
import com.itextpdf.text.pdf.PdfWriter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General Utilities
|
* General Utilities
|
||||||
*
|
*
|
||||||
|
@ -654,26 +665,6 @@ public class Util
|
||||||
return str;
|
return str;
|
||||||
} // trimSize
|
} // trimSize
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
* Test
|
|
||||||
* @param args args
|
|
||||||
*/
|
|
||||||
public static void main (String[] args)
|
|
||||||
{
|
|
||||||
String str = "a<EFBFBD>b<EFBFBD>c?d?e?f?g?";
|
|
||||||
System.out.println(str + " = " + str.length() + " - " + size(str));
|
|
||||||
String str1 = trimLength(str, 10);
|
|
||||||
System.out.println(str1 + " = " + str1.length() + " - " + size(str1));
|
|
||||||
String str2 = trimSize(str, 10);
|
|
||||||
System.out.println(str2 + " = " + str2.length() + " - " + size(str2));
|
|
||||||
//
|
|
||||||
AttributedString aString = new AttributedString ("test test");
|
|
||||||
aString.addAttribute(TextAttribute.FOREGROUND, Color.blue);
|
|
||||||
aString.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, 2, 4);
|
|
||||||
getIterator (aString, new AttributedCharacterIterator.Attribute[] {TextAttribute.UNDERLINE});
|
|
||||||
} // main
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String diacritics from given string
|
* String diacritics from given string
|
||||||
* @param s original string
|
* @param s original string
|
||||||
|
@ -707,4 +698,54 @@ public class Util
|
||||||
cal.set(Calendar.MILLISECOND, 0);
|
cal.set(Calendar.MILLISECOND, 0);
|
||||||
return new Timestamp(cal.getTimeInMillis());
|
return new Timestamp(cal.getTimeInMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param pdfList
|
||||||
|
* @param outFile
|
||||||
|
* @throws IOException
|
||||||
|
* @throws DocumentException
|
||||||
|
* @throws FileNotFoundException
|
||||||
|
*/
|
||||||
|
public static void mergePdf(List<File> pdfList, File outFile) throws IOException,
|
||||||
|
DocumentException, FileNotFoundException {
|
||||||
|
Document document = null;
|
||||||
|
PdfWriter copy = null;
|
||||||
|
|
||||||
|
List<PdfReader> pdfReaders = new ArrayList<PdfReader>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (File f : pdfList)
|
||||||
|
{
|
||||||
|
PdfReader reader = new PdfReader(f.getAbsolutePath());
|
||||||
|
|
||||||
|
pdfReaders.add(reader);
|
||||||
|
|
||||||
|
if (document == null)
|
||||||
|
{
|
||||||
|
document = new Document(reader.getPageSizeWithRotation(1));
|
||||||
|
copy = PdfWriter.getInstance(document, new FileOutputStream(outFile));
|
||||||
|
document.open();
|
||||||
|
}
|
||||||
|
int pages = reader.getNumberOfPages();
|
||||||
|
PdfContentByte cb = copy.getDirectContent();
|
||||||
|
for (int i = 1; i <= pages; i++) {
|
||||||
|
document.newPage();
|
||||||
|
copy.newPage();
|
||||||
|
PdfImportedPage page = copy.getImportedPage(reader, i);
|
||||||
|
cb.addTemplate(page, 0, 0);
|
||||||
|
copy.releaseTemplate(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.close();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
for(PdfReader reader:pdfReaders)
|
||||||
|
{
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} // Util
|
} // Util
|
||||||
|
|
|
@ -12,12 +12,15 @@ Import-Package: net.sourceforge.barbecue,
|
||||||
org.apache.commons.logging.impl;version="1.1.1",
|
org.apache.commons.logging.impl;version="1.1.1",
|
||||||
org.jfree.chart,
|
org.jfree.chart,
|
||||||
org.jfree.chart.plot,
|
org.jfree.chart.plot,
|
||||||
|
org.osgi.framework;version="1.10.0",
|
||||||
org.osgi.service.event
|
org.osgi.service.event
|
||||||
Require-Bundle: org.adempiere.base;bundle-version="0.0.0",
|
Require-Bundle: org.adempiere.base;bundle-version="0.0.0",
|
||||||
net.sf.jasperreports.engine;bundle-version="6.3.1"
|
net.sf.jasperreports.engine;bundle-version="6.3.1",
|
||||||
|
com.itextpdf;bundle-version="5.5.13"
|
||||||
Service-Component: OSGI-INF/*.xml
|
Service-Component: OSGI-INF/*.xml
|
||||||
Export-Package: org.adempiere.report.jasper
|
Export-Package: org.adempiere.report.jasper
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Bundle-ClassPath: .
|
Bundle-ClassPath: .
|
||||||
Automatic-Module-Name: org.adempiere.report.jasper
|
Automatic-Module-Name: org.adempiere.report.jasper
|
||||||
Bundle-Vendor: iDempiere Community
|
Bundle-Vendor: iDempiere Community
|
||||||
|
Bundle-Activator: org.adempiere.report.jasper.Activator
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.report.jasper;
|
||||||
|
|
||||||
|
import org.osgi.framework.BundleActivator;
|
||||||
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Activator implements BundleActivator {
|
||||||
|
|
||||||
|
private static BundleContext bundleContext = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(BundleContext context) throws Exception {
|
||||||
|
bundleContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop(BundleContext context) throws Exception {
|
||||||
|
bundleContext = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bundle context
|
||||||
|
*/
|
||||||
|
public static BundleContext getBundleContext() {
|
||||||
|
return bundleContext;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,191 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.report.jasper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.adempiere.exceptions.AdempiereException;
|
||||||
|
import org.compiere.model.MAttachment;
|
||||||
|
import org.compiere.model.MAttachmentEntry;
|
||||||
|
import org.compiere.model.MProcess;
|
||||||
|
import org.compiere.process.ProcessInfo;
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.compiere.util.Env;
|
||||||
|
import org.compiere.util.Language;
|
||||||
|
import org.compiere.utils.DigestOfFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load report resources from attachment to process
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AttachmentResourceLoader {
|
||||||
|
|
||||||
|
private final static CLogger log = CLogger.getCLogger(AttachmentResourceLoader.class);
|
||||||
|
|
||||||
|
private String destinationFolder;
|
||||||
|
|
||||||
|
private MAttachment attachment;
|
||||||
|
|
||||||
|
private static final String ATTACHMENT_PATH_PREFIX = "attachment:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param destinationFolder
|
||||||
|
*/
|
||||||
|
public AttachmentResourceLoader(String destinationFolder) {
|
||||||
|
this.destinationFolder = destinationFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get report file from process attachment
|
||||||
|
*
|
||||||
|
* @param reportPath must of syntax attachment:filename
|
||||||
|
* @return File
|
||||||
|
*/
|
||||||
|
public File getReportFile(ProcessInfo processInfo, String reportPath) {
|
||||||
|
File reportFile = null;
|
||||||
|
String name = reportPath.substring(ATTACHMENT_PATH_PREFIX.length()).trim();
|
||||||
|
MProcess process = new MProcess(Env.getCtx(), processInfo.getAD_Process_ID(), processInfo.getTransactionName());
|
||||||
|
attachment = process.getAttachment();
|
||||||
|
if (attachment != null) {
|
||||||
|
MAttachmentEntry[] entries = attachment.getEntries();
|
||||||
|
MAttachmentEntry entry = null;
|
||||||
|
for (int i = 0; i < entries.length; i++) {
|
||||||
|
if (entries[i].getName().equals(name)) {
|
||||||
|
entry = entries[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (entry != null) {
|
||||||
|
reportFile = getAttachmentEntryFile(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reportFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download db attachment to local file
|
||||||
|
*
|
||||||
|
* @param entry
|
||||||
|
* @return File
|
||||||
|
*/
|
||||||
|
private File getAttachmentEntryFile(MAttachmentEntry entry) {
|
||||||
|
String localFile = destinationFolder + entry.getName();
|
||||||
|
String downloadedLocalFile = destinationFolder + "TMP_" + entry.getName();
|
||||||
|
File reportFile = new File(localFile);
|
||||||
|
if (reportFile.exists()) {
|
||||||
|
String localMD5hash = DigestOfFile.getMD5Hash(reportFile);
|
||||||
|
String entryMD5hash = DigestOfFile.getMD5Hash(entry.getData());
|
||||||
|
if (localMD5hash.equals(entryMD5hash)) {
|
||||||
|
log.info(" no need to download: local report is up-to-date");
|
||||||
|
} else {
|
||||||
|
log.info(" report on server is different from local copy, download and replace");
|
||||||
|
File downloadedFile = new File(downloadedLocalFile);
|
||||||
|
entry.getFile(downloadedFile);
|
||||||
|
if (!reportFile.delete()) {
|
||||||
|
throw new AdempiereException("Cannot delete temporary file " + reportFile.toString());
|
||||||
|
}
|
||||||
|
if (!downloadedFile.renameTo(reportFile)) {
|
||||||
|
throw new AdempiereException("Cannot rename temporary file " + downloadedFile.toString() + " to "
|
||||||
|
+ reportFile.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entry.getFile(reportFile);
|
||||||
|
}
|
||||||
|
return reportFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getAttachmentEntryFile(String resname) {
|
||||||
|
File fileattach = null;
|
||||||
|
MAttachmentEntry[] entries = attachment.getEntries();
|
||||||
|
for (int i = 0; i < entries.length; i++) {
|
||||||
|
if (entries[i].getName().equals(resname)) {
|
||||||
|
fileattach = getAttachmentEntryFile(entries[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileattach;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get property resource file from process attachment
|
||||||
|
*
|
||||||
|
* @param bundleName
|
||||||
|
* @param currLang
|
||||||
|
* @return File
|
||||||
|
*/
|
||||||
|
public File getResourceBundle(String bundleName, Language currLang) {
|
||||||
|
String resname = bundleName + "_" + currLang.getLocale().getLanguage() + "_" + currLang.getLocale().getCountry()
|
||||||
|
+ ".properties";
|
||||||
|
File resFile = getAttachmentEntryFile(resname);
|
||||||
|
if (resFile == null) {
|
||||||
|
resname = bundleName + "_" + currLang.getLocale().getLanguage() + ".properties";
|
||||||
|
resFile = getAttachmentEntryFile(resname);
|
||||||
|
if (resFile == null) {
|
||||||
|
resname = bundleName + ".properties";
|
||||||
|
resFile = getAttachmentEntryFile(resname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get subreports and other resources (for e.g images) from attachment. Assume all other jasper attachment is
|
||||||
|
* subreport.
|
||||||
|
*
|
||||||
|
* @param reportPath
|
||||||
|
* @return File[] of subreports
|
||||||
|
*/
|
||||||
|
public File[] getSubreports(String reportPath) {
|
||||||
|
String name = reportPath.substring(ATTACHMENT_PATH_PREFIX.length()).trim();
|
||||||
|
ArrayList<File> subreports = new ArrayList<File>();
|
||||||
|
MAttachmentEntry[] entries = attachment.getEntries();
|
||||||
|
for (int i = 0; i < entries.length; i++) {
|
||||||
|
// @Trifon
|
||||||
|
if (!entries[i].getName().equals(name)) {
|
||||||
|
File reportFile = getAttachmentEntryFile(entries[i]);
|
||||||
|
if (reportFile != null) {
|
||||||
|
if (entries[i].getName().toLowerCase().endsWith(".jrxml")
|
||||||
|
|| entries[i].getName().toLowerCase().endsWith(".jasper")) {
|
||||||
|
subreports.add(reportFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return subreports.toArray(new File[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @return true if path starts with "attachment:"
|
||||||
|
*/
|
||||||
|
public static boolean isAttachmentResourcePath(String path) {
|
||||||
|
return path != null && path.startsWith(AttachmentResourceLoader.ATTACHMENT_PATH_PREFIX);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,229 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.report.jasper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.compiere.util.Language;
|
||||||
|
import org.compiere.utils.DigestOfFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Get report resources from fragment bundle
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class BundleResourceLoader {
|
||||||
|
|
||||||
|
private final static CLogger log = CLogger.getCLogger(BundleResourceLoader.class);
|
||||||
|
|
||||||
|
private String destinationFolder;
|
||||||
|
|
||||||
|
private String resourcePath;
|
||||||
|
|
||||||
|
private static final String BUNDLE_PATH_PREFIX = "bundle:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param destinationFolder
|
||||||
|
*/
|
||||||
|
public BundleResourceLoader(String destinationFolder) {
|
||||||
|
this.destinationFolder = destinationFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path
|
||||||
|
* @return File or URL
|
||||||
|
*/
|
||||||
|
public Object getResource(String path) {
|
||||||
|
String resourceName = path.startsWith(BUNDLE_PATH_PREFIX) ? path.substring(BUNDLE_PATH_PREFIX.length()).trim() : path.trim();
|
||||||
|
|
||||||
|
File reportFile = null;
|
||||||
|
boolean empty = true;
|
||||||
|
String parentPath = "/";
|
||||||
|
String bundleFileName = resourceName;
|
||||||
|
if (resourceName.lastIndexOf("/") > 0) {
|
||||||
|
parentPath = "/"+resourceName.substring(0, resourceName.lastIndexOf("/"));
|
||||||
|
bundleFileName = resourceName.substring(resourceName.lastIndexOf("/")+1);
|
||||||
|
}
|
||||||
|
URL url = null;
|
||||||
|
Enumeration<URL> entries = Activator.getBundleContext().getBundle().findEntries(parentPath, bundleFileName, false);
|
||||||
|
if (entries != null && entries.hasMoreElements())
|
||||||
|
url = entries.nextElement();
|
||||||
|
if (url != null) {
|
||||||
|
if (resourceName.endsWith(".jrxml")) {
|
||||||
|
File tmpOutputFile = null;
|
||||||
|
try (InputStream inputStream = url.openStream()) {
|
||||||
|
if (inputStream != null) {
|
||||||
|
String localResourceName = toLocalName(resourceName);
|
||||||
|
String localAbsoluteFileName = destinationFolder + localResourceName;
|
||||||
|
String localAbsolutePathName = localAbsoluteFileName.substring(0, localAbsoluteFileName.lastIndexOf(System.getProperty("file.separator"))+1);
|
||||||
|
Path localPath = Path.of(localAbsolutePathName);
|
||||||
|
try {
|
||||||
|
if (!Files.exists(localPath))
|
||||||
|
Files.createDirectory(localPath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
String localFileName = localAbsoluteFileName.substring(localAbsoluteFileName.lastIndexOf(System.getProperty("file.separator"))+1);
|
||||||
|
String extension = localFileName.substring(localFileName.lastIndexOf("."));
|
||||||
|
reportFile = new File(localAbsoluteFileName);
|
||||||
|
if (!reportFile.exists()) {
|
||||||
|
reportFile.createNewFile();
|
||||||
|
tmpOutputFile = reportFile;
|
||||||
|
} else {
|
||||||
|
tmpOutputFile = File.createTempFile(localFileName.substring(0, localFileName.lastIndexOf(".")), extension, localPath.toFile());
|
||||||
|
}
|
||||||
|
try (OutputStream out = new FileOutputStream(tmpOutputFile);) {
|
||||||
|
if (out != null) {
|
||||||
|
byte buf[] = new byte[1024];
|
||||||
|
int len;
|
||||||
|
while ((len = inputStream.read(buf)) > 0) {
|
||||||
|
empty = false;
|
||||||
|
out.write(buf, 0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.log(Level.SEVERE, e.getMessage(), e);
|
||||||
|
empty = true;
|
||||||
|
}
|
||||||
|
if (!empty && tmpOutputFile != reportFile) {
|
||||||
|
if (!DigestOfFile.md5HashCompare(reportFile, tmpOutputFile)) {
|
||||||
|
Path to = reportFile.toPath();
|
||||||
|
Path from = tmpOutputFile.toPath();
|
||||||
|
try {
|
||||||
|
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.log(Level.SEVERE, e.getMessage(), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Files.delete(tmpOutputFile.toPath());
|
||||||
|
} catch (IOException e) {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
empty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (url != null) {
|
||||||
|
resourcePath = url.toString();
|
||||||
|
if (resourcePath != null && resourcePath.lastIndexOf("/") > 0)
|
||||||
|
resourcePath = resourcePath.substring(0, resourcePath.lastIndexOf("/")+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reportFile != null ? reportFile : url;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toLocalName(String name) {
|
||||||
|
String localName = name;
|
||||||
|
if (localName.startsWith("/"))
|
||||||
|
localName = localName.substring(1);
|
||||||
|
if (localName.lastIndexOf("/") > 0) {
|
||||||
|
String path = localName.substring(0, localName.lastIndexOf("/"));
|
||||||
|
localName = localName.substring(localName.lastIndexOf("/")+1);
|
||||||
|
path = path.replace('/', '_');
|
||||||
|
localName = path + System.getProperty("file.separator") + localName;
|
||||||
|
}
|
||||||
|
return localName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get property resource file from resources
|
||||||
|
*
|
||||||
|
* @param bundleName
|
||||||
|
* @param currLang
|
||||||
|
* @return URL
|
||||||
|
*/
|
||||||
|
public URL getResourceBundle(String bundleName, Language currLang) {
|
||||||
|
String resname = bundleName + "_" + currLang.getLocale().getLanguage() + "_" + currLang.getLocale().getCountry()
|
||||||
|
+ ".properties";
|
||||||
|
URL resourceURL = null;
|
||||||
|
try {
|
||||||
|
resourceURL = (URL) getResource(resname);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignore exception - file couldn't exist
|
||||||
|
}
|
||||||
|
if (resourceURL == null) {
|
||||||
|
resname = bundleName + "_" + currLang.getLocale().getLanguage() + ".properties";
|
||||||
|
try {
|
||||||
|
resourceURL = (URL) getResource(resname);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignore exception - file couldn't exist
|
||||||
|
}
|
||||||
|
if (resourceURL == null) {
|
||||||
|
resname = bundleName + ".properties";
|
||||||
|
try {
|
||||||
|
resourceURL = (URL) getResource(resname);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignore exception - file couldn't exist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resourceURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path The full path to the parent report
|
||||||
|
* @return File[0];
|
||||||
|
*/
|
||||||
|
public File[] getSubreports(String path) {
|
||||||
|
return new File[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return url path to load subreports, images and resource bundle
|
||||||
|
*/
|
||||||
|
public String getRelatedResourcesPath() {
|
||||||
|
return resourcePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @return true if path is "bundle:*"
|
||||||
|
*/
|
||||||
|
public static boolean isBundleResourcePath(String path) {
|
||||||
|
return path != null && path.startsWith(BUNDLE_PATH_PREFIX);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,222 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.report.jasper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.compiere.util.Language;
|
||||||
|
import org.compiere.utils.DigestOfFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Get report resources from class path
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ClassResourceLoader {
|
||||||
|
|
||||||
|
private final static CLogger log = CLogger.getCLogger(ClassResourceLoader.class);
|
||||||
|
|
||||||
|
private String destinationFolder;
|
||||||
|
|
||||||
|
private String resourcePath;
|
||||||
|
|
||||||
|
private static final String RESOURCE_PATH_PREFIX = "resource:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param destinationFolder
|
||||||
|
*/
|
||||||
|
public ClassResourceLoader(String destinationFolder) {
|
||||||
|
this.destinationFolder = destinationFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path
|
||||||
|
* @return File or URL
|
||||||
|
*/
|
||||||
|
public Object getResource(String path) {
|
||||||
|
boolean empty = true;
|
||||||
|
URL url = null;
|
||||||
|
File reportFile = null;
|
||||||
|
String resourceName = path.startsWith(RESOURCE_PATH_PREFIX) ? path.substring(RESOURCE_PATH_PREFIX.length()).trim() : path.trim();
|
||||||
|
//only copy to tmp if reportPath is jrxml file (for compilation)
|
||||||
|
if (resourceName.endsWith(".jrxml")) {
|
||||||
|
String localResourceName = toLocalName(resourceName);
|
||||||
|
String localAbsolutePathName = destinationFolder + localResourceName;
|
||||||
|
reportFile = new File(localAbsolutePathName);
|
||||||
|
String localPathName = localAbsolutePathName.substring(0, localAbsolutePathName.lastIndexOf(System.getProperty("file.separator"))+1);
|
||||||
|
Path localAbsolutePath = Path.of(localPathName);
|
||||||
|
try {
|
||||||
|
if (!Files.exists(localAbsolutePath))
|
||||||
|
Files.createDirectory(localAbsolutePath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
String localFileName = localAbsolutePathName.substring(localAbsolutePathName.lastIndexOf(System.getProperty("file.separator"))+1);
|
||||||
|
String extension = localFileName.substring(localFileName.lastIndexOf("."));
|
||||||
|
File tmpOutputFile = null;
|
||||||
|
|
||||||
|
url = getClass().getClassLoader().getResource(resourceName);
|
||||||
|
if (url != null) {
|
||||||
|
try (InputStream inputStream = url.openStream()) {
|
||||||
|
if (inputStream != null) {
|
||||||
|
if (!reportFile.exists()) {
|
||||||
|
reportFile.createNewFile();
|
||||||
|
tmpOutputFile = reportFile;
|
||||||
|
} else {
|
||||||
|
tmpOutputFile = File.createTempFile(localFileName.substring(0, localFileName.lastIndexOf(".")), extension, localAbsolutePath.toFile());
|
||||||
|
}
|
||||||
|
try (OutputStream out = new FileOutputStream(tmpOutputFile);) {
|
||||||
|
if (out != null) {
|
||||||
|
byte buf[] = new byte[1024];
|
||||||
|
int len;
|
||||||
|
while ((len = inputStream.read(buf)) > 0) {
|
||||||
|
empty = false;
|
||||||
|
out.write(buf, 0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.log(Level.SEVERE, e.getMessage(), e);
|
||||||
|
empty = true;
|
||||||
|
}
|
||||||
|
if (!empty && tmpOutputFile != reportFile) {
|
||||||
|
if (!DigestOfFile.md5HashCompare(reportFile, tmpOutputFile)) {
|
||||||
|
Path to = reportFile.toPath();
|
||||||
|
Path from = tmpOutputFile.toPath();
|
||||||
|
try {
|
||||||
|
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.log(Level.SEVERE, e.getMessage(), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Files.delete(tmpOutputFile.toPath());
|
||||||
|
} catch (IOException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
url = getClass().getClassLoader().getResource(resourceName);
|
||||||
|
empty = (url == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (url != null) {
|
||||||
|
resourcePath = url.toString();
|
||||||
|
if (resourcePath != null && resourcePath.lastIndexOf("/") > 0)
|
||||||
|
resourcePath = resourcePath.substring(0, resourcePath.lastIndexOf("/")+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reportFile != null ? reportFile : url;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toLocalName(String name) {
|
||||||
|
String localName = name;
|
||||||
|
if (localName.startsWith("/"))
|
||||||
|
localName = localName.substring(1);
|
||||||
|
if (localName.lastIndexOf("/") > 0) {
|
||||||
|
String path = localName.substring(0, localName.lastIndexOf("/"));
|
||||||
|
localName = localName.substring(localName.lastIndexOf("/")+1);
|
||||||
|
path = path.replace('/', '_');
|
||||||
|
localName = path + System.getProperty("file.separator") + localName;
|
||||||
|
}
|
||||||
|
return localName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get property resource file from resources
|
||||||
|
*
|
||||||
|
* @param bundleName
|
||||||
|
* @param currLang
|
||||||
|
* @return URL
|
||||||
|
*/
|
||||||
|
public URL getResourceBundle(String bundleName, Language currLang) {
|
||||||
|
String resourceName = bundleName + "_" + currLang.getLocale().getLanguage() + "_" + currLang.getLocale().getCountry()
|
||||||
|
+ ".properties";
|
||||||
|
URL resourceURL = null;
|
||||||
|
try {
|
||||||
|
resourceURL = (URL) getResource(resourceName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignore exception - file couldn't exist
|
||||||
|
}
|
||||||
|
if (resourceURL == null) {
|
||||||
|
resourceName = bundleName + "_" + currLang.getLocale().getLanguage() + ".properties";
|
||||||
|
try {
|
||||||
|
resourceURL = (URL) getResource(resourceName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignore exception - file couldn't exist
|
||||||
|
}
|
||||||
|
if (resourceURL == null) {
|
||||||
|
resourceName = bundleName + ".properties";
|
||||||
|
try {
|
||||||
|
resourceURL = (URL) getResource(resourceName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignore exception - file couldn't exist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resourceURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path The full path to the parent report
|
||||||
|
* @return File[0]
|
||||||
|
*/
|
||||||
|
public File[] getSubreports(String path) {
|
||||||
|
return new File[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return url path to load subreports, images and resource bundle
|
||||||
|
*/
|
||||||
|
public String getRelatedResourcesPath() {
|
||||||
|
return resourcePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @return true if path is "resource:*"
|
||||||
|
*/
|
||||||
|
public static boolean isClassResourcePath(String path) {
|
||||||
|
return path != null && path.startsWith(RESOURCE_PATH_PREFIX);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.report.jasper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FilenameFilter;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.compiere.util.Language;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class FileResourceLoader {
|
||||||
|
|
||||||
|
private final static CLogger log = CLogger.getCLogger(FileResourceLoader.class);
|
||||||
|
|
||||||
|
private static final String FILE_PATH_PREFIX = "file:/";
|
||||||
|
|
||||||
|
public FileResourceLoader() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param reportPath
|
||||||
|
* @return File
|
||||||
|
*/
|
||||||
|
public File getReportFile(String reportPath) {
|
||||||
|
File reportFile = null;
|
||||||
|
try {
|
||||||
|
reportFile = new File(new URI(reportPath));
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
log.warning(e.getLocalizedMessage());
|
||||||
|
reportFile = null;
|
||||||
|
}
|
||||||
|
return reportFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get property resource file from file://
|
||||||
|
*
|
||||||
|
* @param resourcePath
|
||||||
|
* @param bundleName
|
||||||
|
* @param currLang
|
||||||
|
* @return File
|
||||||
|
*/
|
||||||
|
public File getResourceBundle(String resourcePath, String bundleName, Language currLang) {
|
||||||
|
String resname = bundleName + "_" + currLang.getLocale().getLanguage() + "_" + currLang.getLocale().getCountry()
|
||||||
|
+ ".properties";
|
||||||
|
File resFile = new File(resourcePath, resname);
|
||||||
|
if (!resFile.exists()) {
|
||||||
|
resname = bundleName + "_" + currLang.getLocale().getLanguage() + ".properties";
|
||||||
|
resFile = new File(resourcePath, resname);
|
||||||
|
if (!resFile.exists()) {
|
||||||
|
resname = bundleName + ".properties";
|
||||||
|
resFile = new File(resourcePath, resname);
|
||||||
|
if (!resFile.exists()) {
|
||||||
|
resFile = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param reportFile
|
||||||
|
* @param reportDir
|
||||||
|
* @return File[]
|
||||||
|
*/
|
||||||
|
public File[] getSubreports(File reportFile, File reportDir) {
|
||||||
|
return reportDir.listFiles(new FileFilter(reportFile, reportDir));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @return true if path is "file:*"
|
||||||
|
*/
|
||||||
|
public static boolean isFileResourcePath(String path) {
|
||||||
|
return path != null && path.startsWith(FILE_PATH_PREFIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FileFilter implements FilenameFilter {
|
||||||
|
private File directory;
|
||||||
|
private File reportFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param reportFile
|
||||||
|
* @param directory
|
||||||
|
*/
|
||||||
|
public FileFilter(File reportFile, File directory) {
|
||||||
|
this.reportFile = reportFile;
|
||||||
|
this.directory = directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(File file, String name) {
|
||||||
|
if (file.equals(directory)) {
|
||||||
|
if (!name.equals(reportFile.getName())) {
|
||||||
|
String lower = name.toLowerCase();
|
||||||
|
if (lower.endsWith(".jasper") || lower.endsWith(".jrxml"))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,241 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.report.jasper;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.exceptions.AdempiereException;
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.compiere.util.Language;
|
||||||
|
import org.compiere.util.Util;
|
||||||
|
import org.compiere.utils.DigestOfFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Load report resources from http or https
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class WebResourceLoader {
|
||||||
|
|
||||||
|
private final static CLogger log = CLogger.getCLogger(WebResourceLoader.class);
|
||||||
|
|
||||||
|
private String destinationFolder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param destinationFolder destination folder to download report file to
|
||||||
|
*/
|
||||||
|
public WebResourceLoader(String destinationFolder) {
|
||||||
|
this.destinationFolder = destinationFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download remote report file from web server
|
||||||
|
*
|
||||||
|
* @param reportFilePath full http path to report file
|
||||||
|
* @return downloaded File
|
||||||
|
*/
|
||||||
|
private File downloadFile(String reportFilePath) {
|
||||||
|
File reportFile = null;
|
||||||
|
File downloadedFile = null;
|
||||||
|
if (log.isLoggable(Level.INFO))
|
||||||
|
log.info(" report deployed to " + reportFilePath);
|
||||||
|
try {
|
||||||
|
String[] tmps = reportFilePath.split("/");
|
||||||
|
String fileName = tmps[tmps.length - 1];
|
||||||
|
String localFilePath = destinationFolder + fileName;
|
||||||
|
String tmpLocalFilePath = destinationFolder + "TMP_" + fileName;
|
||||||
|
|
||||||
|
reportFile = new File(localFilePath);
|
||||||
|
if (reportFile.exists()) {
|
||||||
|
String remoteMD5Hash = getRemoteMD5(reportFilePath);
|
||||||
|
if (!Util.isEmpty(remoteMD5Hash, true)) {
|
||||||
|
String localMD5hash = DigestOfFile.getMD5Hash(reportFile);
|
||||||
|
if (log.isLoggable(Level.INFO))
|
||||||
|
log.info("MD5 for local file is " + localMD5hash);
|
||||||
|
if (localMD5hash.equals(remoteMD5Hash.trim())) {
|
||||||
|
if (log.isLoggable(Level.INFO))
|
||||||
|
log.info("MD5 match: local report file is up-to-date");
|
||||||
|
return reportFile;
|
||||||
|
} else {
|
||||||
|
if (log.isLoggable(Level.INFO))
|
||||||
|
log.info("MD5 is different, download and replace");
|
||||||
|
downloadedFile = getRemoteFile(reportFilePath, tmpLocalFilePath);
|
||||||
|
if (downloadedFile != null) {
|
||||||
|
Path to = reportFile.toPath();
|
||||||
|
Path from = downloadedFile.toPath();
|
||||||
|
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
Files.delete(from);
|
||||||
|
return to.toFile();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
downloadedFile = getRemoteFile(reportFilePath, tmpLocalFilePath);
|
||||||
|
if (downloadedFile == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// compare hash of existing and downloaded
|
||||||
|
if (DigestOfFile.md5HashCompare(reportFile, downloadedFile)) {
|
||||||
|
// nothing file are identical
|
||||||
|
if (log.isLoggable(Level.INFO))
|
||||||
|
log.info("MD5 match: local report file is up-to-date");
|
||||||
|
return reportFile;
|
||||||
|
} else {
|
||||||
|
if (log.isLoggable(Level.INFO))
|
||||||
|
log.info("MD5 is different, replace with downloaded file");
|
||||||
|
Path to = reportFile.toPath();
|
||||||
|
Path from = downloadedFile.toPath();
|
||||||
|
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
Files.delete(from);
|
||||||
|
return to.toFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reportFile = getRemoteFile(reportFilePath, localFilePath);
|
||||||
|
return reportFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new AdempiereException("Unknown exception: " + e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param reportFilePath
|
||||||
|
* @return File
|
||||||
|
*/
|
||||||
|
public File getReportFile(String reportFilePath) {
|
||||||
|
return downloadFile(reportFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get property resource file from http URL
|
||||||
|
*
|
||||||
|
* @param reportPath
|
||||||
|
* @param bundleName
|
||||||
|
* @param currLang
|
||||||
|
* @return File
|
||||||
|
*/
|
||||||
|
public File getResourceBundle(String reportPath, String bundleName, Language currLang) {
|
||||||
|
String remoteDir = reportPath.substring(0, reportPath.lastIndexOf("/"));
|
||||||
|
String resname = bundleName + "_" + currLang.getLocale().getLanguage() + "_" + currLang.getLocale().getCountry()
|
||||||
|
+ ".properties";
|
||||||
|
try {
|
||||||
|
File resFile = downloadFile(remoteDir + "/" + resname);
|
||||||
|
if (resFile == null) {
|
||||||
|
resname = bundleName + "_" + currLang.getLocale().getLanguage() + ".properties";
|
||||||
|
resFile = downloadFile(remoteDir + "/" + resname);
|
||||||
|
if (resFile == null) {
|
||||||
|
resname = bundleName + ".properties";
|
||||||
|
resFile = downloadFile(remoteDir + "/" + resname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resFile;
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (log.isLoggable(Level.CONFIG))
|
||||||
|
log.log(Level.CONFIG, e.getMessage(), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRemoteMD5(String reportLocation) {
|
||||||
|
try {
|
||||||
|
String md5url = reportLocation + ".md5";
|
||||||
|
URL reportURL = new URL(md5url);
|
||||||
|
try (InputStream in = reportURL.openStream()) {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
byte buf[] = new byte[1024];
|
||||||
|
int s = 0;
|
||||||
|
while ((s = in.read(buf, 0, 1024)) > 0)
|
||||||
|
baos.write(buf, 0, s);
|
||||||
|
|
||||||
|
String hash = new String(baos.toByteArray());
|
||||||
|
int posSpace = hash.indexOf(" ");
|
||||||
|
if (posSpace > 0)
|
||||||
|
hash = hash.substring(0, posSpace);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (log.isLoggable(Level.CONFIG))
|
||||||
|
log.log(Level.CONFIG, "MD5 not available for " + reportLocation, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author rlemeill
|
||||||
|
* @param reportLocation http://applicationserver/webApp/standalone.jrxml for
|
||||||
|
* example
|
||||||
|
* @param localPath Where to put the http downloaded file
|
||||||
|
* @return abstract File which represent the downloaded file
|
||||||
|
*/
|
||||||
|
private File getRemoteFile(String reportLocation, String localPath) {
|
||||||
|
try {
|
||||||
|
URL reportURL = new URL(reportLocation);
|
||||||
|
try (InputStream in = reportURL.openStream();) {
|
||||||
|
|
||||||
|
File downloadedFile = new File(localPath);
|
||||||
|
|
||||||
|
if (downloadedFile.exists()) {
|
||||||
|
downloadedFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (FileOutputStream fout = new FileOutputStream(downloadedFile);) {
|
||||||
|
byte buf[] = new byte[1024];
|
||||||
|
int s = 0;
|
||||||
|
while ((s = in.read(buf, 0, 1024)) > 0)
|
||||||
|
fout.write(buf, 0, s);
|
||||||
|
|
||||||
|
fout.flush();
|
||||||
|
}
|
||||||
|
return downloadedFile;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new AdempiereException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @return true if path is http or https
|
||||||
|
*/
|
||||||
|
public static boolean isWebResourcePath(String path) {
|
||||||
|
return path.startsWith("http://") || path.startsWith("https://");
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,12 +19,10 @@ package org.adempiere.webui.apps;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -74,12 +72,7 @@ import org.zkoss.zk.ui.Desktop;
|
||||||
import org.zkoss.zk.ui.Execution;
|
import org.zkoss.zk.ui.Execution;
|
||||||
import org.zkoss.zk.ui.Executions;
|
import org.zkoss.zk.ui.Executions;
|
||||||
|
|
||||||
import com.itextpdf.text.Document;
|
|
||||||
import com.itextpdf.text.DocumentException;
|
import com.itextpdf.text.DocumentException;
|
||||||
import com.itextpdf.text.pdf.PdfContentByte;
|
|
||||||
import com.itextpdf.text.pdf.PdfImportedPage;
|
|
||||||
import com.itextpdf.text.pdf.PdfReader;
|
|
||||||
import com.itextpdf.text.pdf.PdfWriter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ZK Application Environment and utilities
|
* ZK Application Environment and utilities
|
||||||
|
@ -615,44 +608,7 @@ public final class AEnv
|
||||||
*/
|
*/
|
||||||
public static void mergePdf(List<File> pdfList, File outFile) throws IOException,
|
public static void mergePdf(List<File> pdfList, File outFile) throws IOException,
|
||||||
DocumentException, FileNotFoundException {
|
DocumentException, FileNotFoundException {
|
||||||
Document document = null;
|
Util.mergePdf(pdfList, outFile);
|
||||||
PdfWriter copy = null;
|
|
||||||
|
|
||||||
List<PdfReader> pdfReaders = new ArrayList<PdfReader>();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (File f : pdfList)
|
|
||||||
{
|
|
||||||
PdfReader reader = new PdfReader(f.getAbsolutePath());
|
|
||||||
|
|
||||||
pdfReaders.add(reader);
|
|
||||||
|
|
||||||
if (document == null)
|
|
||||||
{
|
|
||||||
document = new Document(reader.getPageSizeWithRotation(1));
|
|
||||||
copy = PdfWriter.getInstance(document, new FileOutputStream(outFile));
|
|
||||||
document.open();
|
|
||||||
}
|
|
||||||
int pages = reader.getNumberOfPages();
|
|
||||||
PdfContentByte cb = copy.getDirectContent();
|
|
||||||
for (int i = 1; i <= pages; i++) {
|
|
||||||
document.newPage();
|
|
||||||
copy.newPage();
|
|
||||||
PdfImportedPage page = copy.getImportedPage(reader, i);
|
|
||||||
cb.addTemplate(page, 0, 0);
|
|
||||||
copy.releaseTemplate(page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.close();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
for(PdfReader reader:pdfReaders)
|
|
||||||
{
|
|
||||||
reader.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,6 +15,7 @@ import javax.activation.FileDataSource;
|
||||||
|
|
||||||
import org.adempiere.base.upload.IUploadService;
|
import org.adempiere.base.upload.IUploadService;
|
||||||
import org.adempiere.exceptions.AdempiereException;
|
import org.adempiere.exceptions.AdempiereException;
|
||||||
|
import org.adempiere.report.jasper.ReportStarter;
|
||||||
import org.adempiere.webui.ClientInfo;
|
import org.adempiere.webui.ClientInfo;
|
||||||
import org.adempiere.webui.Extensions;
|
import org.adempiere.webui.Extensions;
|
||||||
import org.adempiere.webui.LayoutUtils;
|
import org.adempiere.webui.LayoutUtils;
|
||||||
|
@ -174,7 +175,7 @@ public class ZkJRViewer extends Window implements EventListener<Event>, ITabOnCl
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
final boolean isCanExport=MRole.getDefault().isCanExport();
|
final boolean isCanExport=MRole.getDefault().isCanExport();
|
||||||
defaultType = jasperPrint == null ? null : jasperPrint.getProperty("IDEMPIERE_REPORT_TYPE");
|
defaultType = jasperPrint == null ? null : jasperPrint.getProperty(ReportStarter.IDEMPIERE_REPORT_TYPE);
|
||||||
if (Util.isEmpty(defaultType)) {
|
if (Util.isEmpty(defaultType)) {
|
||||||
defaultType = MSysConfig.getValue(MSysConfig.ZK_REPORT_JASPER_OUTPUT_TYPE, "PDF",
|
defaultType = MSysConfig.getValue(MSysConfig.ZK_REPORT_JASPER_OUTPUT_TYPE, "PDF",
|
||||||
Env.getAD_Client_ID(Env.getCtx()), Env.getAD_Org_ID(Env.getCtx()));//It gets default Jasper output type
|
Env.getAD_Client_ID(Env.getCtx()), Env.getAD_Org_ID(Env.getCtx()));//It gets default Jasper output type
|
||||||
|
|
Loading…
Reference in New Issue