From 689573c90d33198e90c3d04259302ca1d5ff9d0c Mon Sep 17 00:00:00 2001
From: Diego Ruiz <12065321+d-ruiz@users.noreply.github.com>
Date: Wed, 12 Jun 2024 12:51:58 +0200
Subject: [PATCH] =?UTF-8?q?IDEMPIERE-6165=20-=20Custom=20name=20is=20not?=
=?UTF-8?q?=20taken=20when=20running=20a=20core=20report=20=E2=80=A6=20(#2?=
=?UTF-8?q?386)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* IDEMPIERE-6165 - Custom name is not taken when running a core report programatically
* IDEMPIERE-6165 - Add unit test
* IDEMPIERE-6165 - Peer review changes
* IDEMPIERE-6165 - Modified condition to avoid potential NPE
* IDEMPIERE-6165 - Changed Unit Test to be thread safe
* IDEMPIERE-6165 - Create file in a thread-safe way respecting folder name if existing
* IDEMPIERE-6165 - Updated Unit test
* IDEMPIERE-6165 - Updated Unit test
* IDEMPIERE-6165 - Code refactor to remove code duplication in different classes
* IDEMPIERE-6165 - Improved Javadoc
---
.../src/org/compiere/print/ReportEngine.java | 24 ++----
.../org/compiere/print/ServerReportCtl.java | 2 +
.../src/org/compiere/tools/FileUtil.java | 70 +++++++++++++++--
.../report/jasper/ReportStarter.java | 25 ++----
.../org/idempiere/test/base/ReportTest.java | 76 +++++++++++++++++++
5 files changed, 154 insertions(+), 43 deletions(-)
create mode 100644 org.idempiere.test/src/org/idempiere/test/base/ReportTest.java
diff --git a/org.adempiere.base/src/org/compiere/print/ReportEngine.java b/org.adempiere.base/src/org/compiere/print/ReportEngine.java
index 3168acee80..232075d855 100644
--- a/org.adempiere.base/src/org/compiere/print/ReportEngine.java
+++ b/org.adempiere.base/src/org/compiere/print/ReportEngine.java
@@ -857,7 +857,8 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount)
try
{
if (file == null)
- file = FileUtil.createTempFile (makePrefix(getName()), ".pdf");
+ file = (m_pi != null && !Util.isEmpty(m_pi.getPDFFileName(),true)) ? FileUtil.createFile(m_pi.getPDFFileName()) :
+ FileUtil.createTempFile (FileUtil.makePrefix(getName()), ".pdf");
}
catch (IOException e)
{
@@ -888,7 +889,7 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount)
try
{
if (file == null)
- file = FileUtil.createTempFile (makePrefix(getName()), ".html");
+ file = FileUtil.createTempFile (FileUtil.makePrefix(getName()), ".html");
}
catch (IOException e)
{
@@ -919,7 +920,7 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount)
try
{
if (file == null)
- file = FileUtil.createTempFile (makePrefix(getName()), ".csv");
+ file = FileUtil.createTempFile (FileUtil.makePrefix(getName()), ".csv");
}
catch (IOException e)
{
@@ -950,7 +951,7 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount)
try
{
if (file == null)
- file = FileUtil.createTempFile (makePrefix(getName()), ".xls");
+ file = FileUtil.createTempFile (FileUtil.makePrefix(getName()), ".xls");
}
catch (IOException e)
{
@@ -988,7 +989,7 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount)
try
{
if (file == null)
- file = FileUtil.createTempFile (makePrefix(getName()), ".xlsx");
+ file = FileUtil.createTempFile (FileUtil.makePrefix(getName()), ".xlsx");
}
catch (IOException e)
{
@@ -1064,19 +1065,6 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount)
return file2.exists();
} // createPDF
- private String makePrefix(String name) {
- StringBuilder prefix = new StringBuilder();
- char[] nameArray = name.toCharArray();
- for (char ch : nameArray) {
- if (Character.isLetterOrDigit(ch)) {
- prefix.append(ch);
- } else {
- prefix.append("_");
- }
- }
- return prefix.toString();
- }
-
/**
* Create PDF as Data array
* @return pdf data
diff --git a/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java b/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java
index 87a1f7ac03..1ade000110 100644
--- a/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java
+++ b/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java
@@ -94,6 +94,7 @@ public class ServerReportCtl {
{
if (pi != null && pi.isBatch() && pi.isPrintPreview())
{
+ re.setProcessInfo(pi);
if ("HTML".equals(pi.getReportType()))
{
pi.setExport(true);
@@ -163,6 +164,7 @@ public class ServerReportCtl {
if (pi != null) {
jasperProcessInfo.setPrintPreview(pi.isPrintPreview());
jasperProcessInfo.setIsBatch(pi.isBatch());
+ jasperProcessInfo.setPDFFileName(pi.getPDFFileName());
} else {
jasperProcessInfo.setPrintPreview( !IsDirectPrint );
}
diff --git a/org.adempiere.base/src/org/compiere/tools/FileUtil.java b/org.adempiere.base/src/org/compiere/tools/FileUtil.java
index f60aceeafd..17cd380c67 100644
--- a/org.adempiere.base/src/org/compiere/tools/FileUtil.java
+++ b/org.adempiere.base/src/org/compiere/tools/FileUtil.java
@@ -475,12 +475,7 @@ public class FileUtil
if (suffix == null)
suffix = ".tmp";
- Calendar cal = Calendar.getInstance();
- SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
- String dt = sdf.format(cal.getTime());
- String tmpdirname = (directory != null) ? directory.getCanonicalPath() : System.getProperty("java.io.tmpdir");
- tmpdirname += System.getProperty("file.separator") + "rpttmp_" + dt + "_" + Env.getContext(Env.getCtx(), Env.AD_SESSION_ID) + System.getProperty("file.separator");
-
+ String tmpdirname = getTempFolderName(directory);
File tmpdir = new File(tmpdirname);
tmpdir.mkdirs();
@@ -490,11 +485,74 @@ public class FileUtil
return f;
}
+
+ /**
+ * Generates a unique temporary folder name based on the current timestamp and session ID.
+ * The folder name is either within the specified directory or the default temporary directory.
+ *
+ * @param directory the base directory where the temporary folder will be created;
+ * if null, the system's default temporary directory is used
+ * @return a string representing the path to the unique temporary folder
+ * @throws IOException
+ */
+ public static String getTempFolderName(File directory) throws IOException {
+ Calendar cal = Calendar.getInstance();
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+ String dt = sdf.format(cal.getTime());
+ String tmpdirname = (directory != null) ? directory.getCanonicalPath() : System.getProperty("java.io.tmpdir");
+ tmpdirname += System.getProperty("file.separator") + "rpttmp_" + dt + "_" + Env.getContext(Env.getCtx(), Env.AD_SESSION_ID) + System.getProperty("file.separator");
+
+ return tmpdirname;
+ }
public static File createTempFile(String prefix, String suffix) throws IOException
{
return createTempFile(prefix, suffix, null);
}
+
+ /**
+ * Creates a file with the given filename.
+ * If the filename includes the path, the file is created as requested.
+ * If it only includes the name, the file is created in a thread-safe temporary folder.
+ * @param fileName
+ * @return file
+ * @throws IOException
+ */
+ public static File createFile(String fileName) throws IOException {
+ if (Util.isEmpty(fileName))
+ throw new IllegalArgumentException("Name is required");
+
+ File file = null;
+ if (fileName.contains(System.getProperty("file.separator"))) {
+ file = new File(fileName);
+ } else {
+ String tmpdirname = getTempFolderName(null);
+ File tmpdir = new File(tmpdirname);
+ tmpdir.mkdirs();
+
+ file = new File(tmpdirname, fileName);
+ }
+
+ return file;
+ }
+
+ /**
+ * Creates a valid file name prefix from "name"
+ * @param name
+ * @return file name prefix
+ */
+ public static String makePrefix(String name) {
+ StringBuilder prefix = new StringBuilder();
+ char[] nameArray = name.toCharArray();
+ for (char ch : nameArray) {
+ if (Character.isLetterOrDigit(ch)) {
+ prefix.append(ch);
+ } else {
+ prefix.append("_");
+ }
+ }
+ return prefix.toString();
+ }
/**
*
diff --git a/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java b/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java
index 34f0644f51..94b40863aa 100644
--- a/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java
+++ b/org.adempiere.report.jasper/src/org/adempiere/report/jasper/ReportStarter.java
@@ -492,7 +492,7 @@ public class ReportStarter implements ProcessCall, ClientProcess
processInfo.setPDFReport(batchPDFExportList.get(0));
} else {
try {
- File pdfFile = File.createTempFile(makePrefix(processInfo.getTitle()), ".pdf");
+ File pdfFile = File.createTempFile(FileUtil.makePrefix(processInfo.getTitle()), ".pdf");
Util.mergePdf(batchPDFExportList, pdfFile);
processInfo.setPDFReport(pdfFile);
} catch (Exception e) {
@@ -542,7 +542,7 @@ public class ReportStarter implements ProcessCall, ClientProcess
}
private File createMultiFileArchive(List exportFileList) throws Exception {
- File archiveFile = File.createTempFile(makePrefix(processInfo.getTitle()), ".zip");
+ File archiveFile = File.createTempFile(FileUtil.makePrefix(processInfo.getTitle()), ".zip");
try (FileOutputStream out = new FileOutputStream(archiveFile)) {
try (ZipOutputStream zip = new ZipOutputStream(out);) {
zip.setMethod(ZipOutputStream.DEFLATED);
@@ -575,9 +575,9 @@ public class ReportStarter implements ProcessCall, ClientProcess
{
File pdfFile = null;
if (processInfo.getPDFFileName() != null) {
- pdfFile = new File(processInfo.getPDFFileName());
+ pdfFile = FileUtil.createFile(processInfo.getPDFFileName());
} else {
- pdfFile = File.createTempFile(makePrefix(jasperPrint.getName()), ".pdf");
+ pdfFile = File.createTempFile(FileUtil.makePrefix(jasperPrint.getName()), ".pdf");
}
JRPdfExporter exporter = new JRPdfExporter(jasperReportContext);
@@ -637,7 +637,7 @@ public class ReportStarter implements ProcessCall, ClientProcess
else
newQueryText = originalQueryText + " WHERE " + query.toString();
- File jrxmlFile = File.createTempFile(makePrefix(jasperReport.getName()), ".jrxml");
+ File jrxmlFile = File.createTempFile(FileUtil.makePrefix(jasperReport.getName()), ".jrxml");
JRXmlWriter.writeReport(jasperReport, new FileOutputStream(jrxmlFile), "UTF-8");
JasperDesign jasperDesign = JRXmlLoader.load(jrxmlFile);
@@ -706,7 +706,7 @@ public class ReportStarter implements ProcessCall, ClientProcess
if (ext == null)
ext = "pdf";
try {
- File exportFile = File.createTempFile(makePrefix(jasperPrint.getName()), "." + ext);
+ File exportFile = File.createTempFile(FileUtil.makePrefix(jasperPrint.getName()), "." + ext);
try (FileOutputStream outputStream = new FileOutputStream(exportFile);) {
@@ -826,19 +826,6 @@ public class ReportStarter implements ProcessCall, ClientProcess
return viewerLauncher;
}
- private String makePrefix(String name) {
- StringBuilder prefix = new StringBuilder();
- char[] nameArray = name.toCharArray();
- for (char ch : nameArray) {
- if (Character.isLetterOrDigit(ch)) {
- prefix.append(ch);
- } else {
- prefix.append("_");
- }
- }
- return prefix.toString();
- }
-
private WebResourceLoader getWebResourceLoader() {
if (webResourceLoader == null)
webResourceLoader = new WebResourceLoader(getLocalDownloadFolder());
diff --git a/org.idempiere.test/src/org/idempiere/test/base/ReportTest.java b/org.idempiere.test/src/org/idempiere/test/base/ReportTest.java
new file mode 100644
index 0000000000..eab18899e8
--- /dev/null
+++ b/org.idempiere.test/src/org/idempiere/test/base/ReportTest.java
@@ -0,0 +1,76 @@
+/***********************************************************************
+ * 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: *
+ * - Carlos Ruiz - globalqss *
+ **********************************************************************/
+package org.idempiere.test.base;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.File;
+
+import org.compiere.model.MOrder;
+import org.compiere.model.MPInstance;
+import org.compiere.model.MProcess;
+import org.compiere.process.ProcessInfo;
+import org.compiere.process.ServerProcessCtl;
+import org.compiere.util.Env;
+import org.idempiere.test.AbstractTestCase;
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author Diego Ruiz - BX Service GmbH
+ */
+public class ReportTest extends AbstractTestCase {
+
+ public ReportTest() {
+ }
+
+ private static final int Order_Print_Process = 110;
+
+ /**
+ * https://idempiere.atlassian.net/browse/IDEMPIERE-6165
+ */
+ @Test
+ public void testPDFFileName() {
+ MProcess orderReport = MProcess.get(Env.getCtx(), Order_Print_Process);
+ MOrder order = new MOrder(Env.getCtx(), 108, getTrxName()); // Garden Order 60000
+
+ String fileName = order.getDocumentNo() + ".pdf";
+
+ ProcessInfo pi = new ProcessInfo(orderReport.getName(), orderReport.getAD_Process_ID());
+ pi.setRecord_ID(order.getC_Order_ID());
+ pi.setAD_Client_ID(Env.getAD_Client_ID(Env.getCtx()));
+ pi.setTable_ID(order.get_Table_ID());
+ pi.setPrintPreview(true);
+ pi.setIsBatch(true);
+ pi.setPDFFileName(fileName);
+ pi.setReportType("PDF");
+ MPInstance instance = new MPInstance(orderReport, order.get_Table_ID(), order.getC_Order_ID(), order.getC_Order_UU());
+ instance.saveEx();
+ ServerProcessCtl.process(pi, null);
+ File file = pi.getPDFReport();
+
+ assertEquals(file.getName(), fileName);
+
+ }
+}