/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 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 Lesser General Public License for more details. * * Copyright 2006 - 2009 Pentaho Corporation. All rights reserved. * */ package org.pentaho.platform.plugin.action.jfreereport.helper; 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.io.Serializable; import java.net.URL; import java.net.URLClassLoader; import java.util.HashMap; import java.util.Map; import org.jfree.io.IOUtils; import org.pentaho.platform.api.engine.IActionSequenceResource; import org.pentaho.platform.api.engine.IApplicationContext; import org.pentaho.platform.api.engine.IPentahoSession; import org.pentaho.platform.api.repository.ISolutionRepository; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.plugin.action.messages.Messages; /** * Creation-Date: 07.07.2006, 15:49:35 * * @author Thomas Morgner */ public class ReportUtils { private static class ClassLoaderEntry implements Serializable { private static final long serialVersionUID = 8925334939030498948L; private transient ClassLoader entry; public ClassLoaderEntry(final ClassLoader entry) { this.entry = entry; } public ClassLoader getEntry() { return entry; } } private ReportUtils() { } public static synchronized File getTempDirectory(final IPentahoSession session) { IApplicationContext ctx = PentahoSystem.getApplicationContext(); if (ctx != null) { final String fileOutputPath = ctx.getFileOutputPath("system/tmp/"); //$NON-NLS-1$ final File tempDir = new File(fileOutputPath); final String id = session.getId(); final File userTempDir; if (id == null) { // typical sloopy programming! Someone forgot to check null values. userTempDir = tempDir; } else { userTempDir = new File(tempDir, id); } // this operation silently fails if the dir already exists. userTempDir.mkdir(); return userTempDir; } throw new IllegalStateException(Messages.getInstance().getString("ReportUtils.ERROR_0036_PENTAHO_SYSTEM_NOT_OK")); //$NON-NLS-1$ } public static ClassLoader createJarLoader(final IPentahoSession session, final IActionSequenceResource resource) { // todo: We cant clean the temp directory ... // session.addListener (,..) is needed synchronized (session) { try { final URL url = ReportUtils.getURL(session, resource, true); if (url == null) { return null; } final Map cache = ReportUtils.getClassLoaderCache(session); ClassLoaderEntry entry = (ClassLoaderEntry) cache.get(url); if (entry != null) { if (entry.getEntry() != null) { return entry.getEntry(); } } // now wrap the beast into a jar URL ... final URL jarURL = new URL("jar:" + url.toExternalForm() + "!/"); //$NON-NLS-1$ //$NON-NLS-2$ final URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[] { jarURL }); cache.put(url, new ClassLoaderEntry(urlClassLoader)); return urlClassLoader; } catch (IOException e) { // something went wrong .. return null; } } } private static Map getClassLoaderCache(final IPentahoSession session) { synchronized (session) { Object maybeMap = session.getAttribute("-x-pentaho-classloaders"); //$NON-NLS-1$ if (maybeMap instanceof Map) { return (Map) maybeMap; } Map map = new HashMap(); session.setAttribute("-x-pentaho-classloaders", map); //$NON-NLS-1$ return map; } } private static URL getURL(final IPentahoSession session, final IActionSequenceResource resource, final boolean create) throws IOException { if (resource.getSourceType() == IActionSequenceResource.URL_RESOURCE) { return new URL(resource.getAddress()); } if (resource.getSourceType() == IActionSequenceResource.FILE_RESOURCE) { File file = new File(resource.getAddress()); if (file.exists() && file.canRead()) { return file.toURL(); } } if (resource.getSourceType() == IActionSequenceResource.SOLUTION_FILE_RESOURCE) { String reportJarPath = PentahoSystem.getApplicationContext().getSolutionPath(resource.getAddress()); File file = new File(reportJarPath); if (file.exists() && file.canRead()) { return file.toURL(); } } if (create) { // ok, fall back to copy the file into the temp dir and to load it from // there... File temp = ReportUtils.getTempDirectory(session); File tempFile = PentahoSystem.getApplicationContext().createTempFile(session, "loaded-jar-", ".jar", temp, true); //$NON-NLS-1$ //$NON-NLS-2$ // if that fails, we dont have to waste our time on copying the stuff .. final URL url = tempFile.toURL(); final ISolutionRepository solutionRepository = PentahoSystem.get(ISolutionRepository.class, session); final InputStream in = solutionRepository.getResourceInputStream(resource, true, ISolutionRepository.ACTION_EXECUTE); final OutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile)); try { IOUtils.getInstance().copyStreams(in, out); } finally { in.close(); out.close(); } return url; } else { return null; } } public static URL getURL(final IPentahoSession session, final IActionSequenceResource resource) throws IOException { return ReportUtils.getURL(session, resource, false); } }