IDEMPIERE-6165 - Custom name is not taken when running a core report … ()

* 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
This commit is contained in:
Diego Ruiz 2024-06-12 12:51:58 +02:00 committed by Carlos Ruiz
parent 6d9c35a365
commit 689573c90d
5 changed files with 154 additions and 43 deletions
org.adempiere.base/src/org/compiere
org.adempiere.report.jasper/src/org/adempiere/report/jasper
org.idempiere.test/src/org/idempiere/test/base

View File

@ -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

View File

@ -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 );
}

View File

@ -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. <br/>
* 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. <br/>
* If the filename includes the path, the file is created as requested. <br/>
* 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();
}
/**
*

View File

@ -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<File> 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());

View File

@ -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);
}
}