![JAR search and dependency download from the Maven repository](/logo.png)
net.sf.jasperreports.chrome.ResourceManager Maven / Gradle / Ivy
The newest version!
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2023 Cloud Software Group, Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
package net.sf.jasperreports.chrome;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.collections4.map.AbstractReferenceMap.ReferenceStrength;
import org.apache.commons.collections4.map.ReferenceIdentityMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.jasperreports.annotations.properties.Property;
import net.sf.jasperreports.annotations.properties.PropertyScope;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRPropertiesUtil;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.engine.SimpleJasperReportsContext;
import net.sf.jasperreports.engine.util.ConcurrentMapping;
import net.sf.jasperreports.properties.PropertyConstants;
import net.sf.jasperreports.repo.RepositoryContext;
import net.sf.jasperreports.repo.RepositoryUtil;
import net.sf.jasperreports.repo.SimpleRepositoryContext;
/**
* @author Lucian Chirita ([email protected])
*/
public class ResourceManager
{
private static final Log log = LogFactory.getLog(ResourceManager.class);
@Property(
category = PropertyConstants.CATEGORY_CHROME,
scopes = {PropertyScope.CONTEXT},
sinceVersion = PropertyConstants.VERSION_6_11_0,
defaultValue = "System.getProperty(\"java.io.tmpdir\")"
)
public static final String PROPERTY_TEMPDIR_PATH = Chrome.PROPERTY_PREFIX + "tempdir.path";
private static final String TEMP_FILE_PREFIX = "jr_res_";
private static final int COPY_BUFFER_SIZE = 0x4000;
private static final ResourceManager INSTANCE = new ResourceManager();
public static ResourceManager instance()
{
return INSTANCE;
}
private final Map contextMappings;
public ResourceManager()
{
//TODO schedule a repeating job to purge contexts
this.contextMappings = new ReferenceIdentityMap<>(ReferenceStrength.WEAK, ReferenceStrength.HARD);
}
//TODO use java.nio?
public File getTempFolder(JasperReportsContext jasperReportsContext)
{
ContextMappings mappings = contextMappings(jasperReportsContext);
return mappings.tempFolder;
}
protected ContextMappings contextMappings(JasperReportsContext jasperReportsContext)
{
ContextMappings mappings;
synchronized (contextMappings)
{
//TODO lucianc use safer keys (classloader)
mappings = contextMappings.get(jasperReportsContext);
if (mappings == null)
{
mappings = new ContextMappings(jasperReportsContext);
contextMappings.put(jasperReportsContext, mappings);
}
}
return mappings;
}
public String getResourceLocation(String resourceLocation, JasperReportsContext jasperReportsContext)
{
return getResourceLocation(resourceLocation, SimpleRepositoryContext.of(jasperReportsContext));
}
public String getResourceLocation(String resourceLocation, RepositoryContext repositoryContext)
{
File resourceMapping = resourceMapping(resourceLocation, repositoryContext);
if (resourceMapping == null)
{
throw new JRRuntimeException(RepositoryUtil.EXCEPTION_MESSAGE_KEY_INPUT_STREAM_NOT_FOUND,
new Object[]{resourceLocation});
}
return resourceMapping.toURI().toString();
}
public String copyDataResource(String resourceName, JasperReportsContext jasperReportsContext,
InputStream data)
{
ContextMappings mappings = contextMappings(jasperReportsContext);
File resourceFile = mappings.dataResourceMapping(resourceName, data, jasperReportsContext);
return resourceFile.toURI().toString();
}
public String getDataResourceLocation(String resourceName, JasperReportsContext jasperReportsContext)
{
ContextMappings mappings = contextMappings(jasperReportsContext);
File resourceFile = mappings.dataResourceMapping(resourceName, jasperReportsContext);
if (resourceFile == null)
{
throw new JRRuntimeException(RepositoryUtil.EXCEPTION_MESSAGE_KEY_INPUT_STREAM_NOT_FOUND,
new Object[]{resourceName});
}
return resourceFile.toURI().toString();
}
protected File resourceMapping(String resourceLocation, RepositoryContext repositoryContext)
{
JasperReportsContext jasperReportsContext = repositoryContext.getJasperReportsContext();
if (jasperReportsContext instanceof SimpleJasperReportsContext)
{
JasperReportsContext parentContext = ((SimpleJasperReportsContext) jasperReportsContext).getParent();
if (parentContext != null)
{
//looking first in the parent so that contexts that share a parent would also share the mappings
SimpleRepositoryContext parentRepositoryContext = SimpleRepositoryContext.of(
parentContext, repositoryContext.getResourceContext());
File parentMapping = resourceMapping(resourceLocation, parentRepositoryContext);
if (parentMapping != null)
{
return parentMapping;
}
}
}
ContextMappings mappings = contextMappings(jasperReportsContext);
File resourceFile = mappings.resourceMapping(resourceLocation, repositoryContext);
return resourceFile;
}
protected File copyResource(String resourceLocation, RepositoryContext repositoryContext, File tempFolder)
{
try(InputStream input = RepositoryUtil.getInstance(repositoryContext).getInputStreamFromLocation(resourceLocation))
{
File file = createTempFile(resourceLocation, tempFolder);
copyToFile(resourceLocation, input, file);
return file;
}
catch (JRException | IOException e)
{
throw new JRRuntimeException(e);
}
}
protected File createTempFile(String resourceLocation, File tempFolder)
{
try
{
String resourceName = getResourceName(resourceLocation);
File file = File.createTempFile(TEMP_FILE_PREFIX, "_" + resourceName, tempFolder);
file.deleteOnExit();//TODO lucianc leak
return file;
}
catch (IOException e)
{
throw new JRRuntimeException(e);
}
}
protected void copyToFile(String resourceLocation, InputStream data, File file)
{
try
{
if (log.isDebugEnabled())
{
log.debug("copying " + resourceLocation + " to " + file);
}
byte[] buf = new byte[COPY_BUFFER_SIZE];
try (OutputStream output = new BufferedOutputStream(new FileOutputStream(file)))
{
int read = 0;
while ((read = data.read(buf)) > 0)
{
output.write(buf, 0, read);
}
}
}
catch (IOException e)
{
throw new JRRuntimeException(e);
}
}
protected String getResourceName(String resourceLocation)
{
// location can be both classpath resource and file path
int slashIndex = resourceLocation.lastIndexOf('/');
int separatorIndex = resourceLocation.lastIndexOf(File.separator);
int nameIndex = Math.max(slashIndex, separatorIndex);
return nameIndex >= 0 ? resourceLocation.substring(nameIndex + 1) : resourceLocation;
}
protected class ContextMappings
{
private final ConcurrentMapping resourceFiles;
private final ConcurrentMapping dataResourceFiles;
protected final File tempFolder;
public ContextMappings(JasperReportsContext jasperReportsContext)
{
String tempPath = JRPropertiesUtil.getInstance(jasperReportsContext).getProperty(PROPERTY_TEMPDIR_PATH);
if (tempPath == null)
{
tempPath = System.getProperty("java.io.tmpdir");
}
this.tempFolder = new File(tempPath);
if (this.tempFolder.exists() && this.tempFolder.isDirectory())
{
log.info("Resources temp folder is " + tempPath);
}
else
{
log.error("The resources temp folder " + tempPath + " does not exist.");
}
this.resourceFiles = new ConcurrentMapping<>((key, context)
-> copyResource(key, context, tempFolder));
this.dataResourceFiles = new ConcurrentMapping<>((resourceName, context)
-> createTempFile(resourceName, tempFolder));
}
public File resourceMapping(String resourceLocation, RepositoryContext repositoryContext)
{
try
{
return resourceFiles.get(resourceLocation, repositoryContext);
}
catch (JRRuntimeException e)
{
if (e.getCause() instanceof JRException
&& RepositoryUtil.EXCEPTION_MESSAGE_KEY_INPUT_STREAM_NOT_FOUND.equals(
((JRException) e.getCause()).getMessageKey()))
{
return null;
}
throw e;
}
}
public File dataResourceMapping(String resourceName, InputStream data, JasperReportsContext jasperReportsContext)
{
File resourceFile = dataResourceFiles.get(resourceName, jasperReportsContext);
synchronized (resourceFile)
{
if (resourceFile.length() == 0)
{
copyToFile(resourceName, data, resourceFile);
}
else
{
if (log.isDebugEnabled())
{
log.debug("file " + resourceFile + " already written for " + resourceName);
}
}
}
return resourceFile;
}
public File dataResourceMapping(String resourceName, JasperReportsContext jasperReportsContext)
{
return dataResourceFiles.get(resourceName, jasperReportsContext);
}
@Override
protected void finalize()
{
for (Iterator fileIt = resourceFiles.currentValues(); fileIt.hasNext();)
{
File file = fileIt.next();
boolean deleted = file.delete();
if (log.isDebugEnabled())
{
log.debug("deleted " + file + ": " + deleted);
}
}
resourceFiles.clear();
for (Iterator fileIt = dataResourceFiles.currentValues(); fileIt.hasNext();)
{
File file = fileIt.next();
boolean deleted = file.delete();
if (log.isDebugEnabled())
{
log.debug("deleted " + file + ": " + deleted);
}
}
dataResourceFiles.clear();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy