/*
* Copyright 2010-2015 Institut Pasteur.
*
* This file is part of Icy.
*
* Icy 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 3 of the License, or
* (at your option) any later version.
*
* Icy 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 Icy. If not, see <http://www.gnu.org/licenses/>.
*/
package icy.plugin.classloader;
import icy.file.FileUtil;
import icy.network.NetworkUtil;
import icy.plugin.classloader.exception.JclException;
import icy.plugin.classloader.exception.ResourceNotFoundException;
import icy.system.IcyExceptionHandler;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Class that builds a local classpath by loading resources from different
* files/paths
*
* @author Kamran Zafar
* @author Stephane Dallongeville
*/
public class ClasspathResources extends JarResources
{
private static Logger logger = Logger.getLogger(ClasspathResources.class.getName());
private boolean ignoreMissingResources;
public ClasspathResources()
{
super();
ignoreMissingResources = Configuration.suppressMissingResourceException();
}
/**
* Attempts to load a remote resource (jars, properties files, etc)
*
* @param url
*/
protected void loadRemoteResource(URL url)
{
if (logger.isLoggable(Level.FINEST))
logger.finest("Attempting to load a remote resource.");
if (url.toString().toLowerCase().endsWith(".jar"))
{
try
{
loadJar(url);
}
catch (IOException e)
{
System.err.println("JarResources.loadJar(" + url + ") error:");
IcyExceptionHandler.showErrorMessage(e, false, true);
}
return;
}
if (entryUrls.containsKey(url.toString()))
{
if (!collisionAllowed)
throw new JclException("Resource " + url.toString() + " already loaded");
if (logger.isLoggable(Level.FINEST))
logger.finest("Resource " + url.toString() + " already loaded; ignoring entry...");
return;
}
if (logger.isLoggable(Level.FINEST))
logger.finest("Loading remote resource.");
entryUrls.put(url.toString(), url);
}
/**
* Loads and returns content the remote resource (jars, properties files, etc)
*
* @throws IOException
*/
protected byte[] loadRemoteResourceContent(URL url) throws IOException
{
final byte[] result = NetworkUtil.download(url.openStream());
if (result != null)
loadedSize += result.length;
return result;
}
/**
* Reads local and remote resources
*
* @param url
*/
protected void loadResource(URL url)
{
try
{
final File file = new File(url.toURI());
// Is Local
loadResource(file, FileUtil.getGenericPath(file.getAbsolutePath()));
}
catch (IllegalArgumentException iae)
{
// Is Remote
loadRemoteResource(url);
}
catch (URISyntaxException e)
{
throw new JclException("URISyntaxException", e);
}
}
/**
* Reads local resources from - Jar files - Class folders - Jar Library
* folders
*
* @param path
*/
protected void loadResource(String path)
{
if (logger.isLoggable(Level.FINEST))
logger.finest("Resource: " + path);
File fp = new File(path);
if (!fp.exists() && !ignoreMissingResources)
throw new JclException("File/Path does not exist");
loadResource(fp, FileUtil.getGenericPath(path));
}
/**
* Reads local resources from - Jar files - Class folders - Jar Library
* folders
*
* @param fol
* @param packName
*/
protected void loadResource(File fol, String packName)
{
// FILE
if (fol.isFile())
{
if (fol.getName().toLowerCase().endsWith(".jar"))
{
try
{
loadJar(fol.toURI().toURL());
}
catch (IOException e)
{
System.err.println("JarResources.loadJar(" + fol.getAbsolutePath() + ") error:");
IcyExceptionHandler.showErrorMessage(e, false, true);
}
}
else
loadResourceInternal(fol, packName);
}
// DIRECTORY
else
{
if (fol.list() != null)
{
for (String f : fol.list())
{
File fl = new File(fol.getAbsolutePath() + "/" + f);
String pn = packName;
if (fl.isDirectory())
{
if (!pn.equals(""))
pn = pn + "/";
pn = pn + fl.getName();
}
loadResource(fl, pn);
}
}
}
}
/**
* Loads the local resource.
*/
protected void loadResourceInternal(File file, String pack)
{
String entryName = "";
if (pack.length() > 0)
entryName = pack + "/";
entryName += file.getName();
if (entryUrls.containsKey(entryName))
{
if (!collisionAllowed)
throw new JclException("Resource " + entryName + " already loaded");
if (logger.isLoggable(Level.WARNING))
logger.finest("Resource " + entryName + " already loaded; ignoring entry...");
return;
}
if (logger.isLoggable(Level.FINEST))
logger.finest("Loading resource: " + entryName);
try
{
entryUrls.put(entryName, file.toURI().toURL());
}
catch (Exception e)
{
if (logger.isLoggable(Level.SEVERE))
logger.finest("Error while loading: " + entryName);
System.err.println("JarResources.loadResourceInternal(" + file.getAbsolutePath() + ") error:");
IcyExceptionHandler.showErrorMessage(e, false, true);
}
}
@Override
protected void loadContent(String name, URL url) throws IOException
{
// JAR protocol
if (url.getProtocol().equalsIgnoreCase(("jar")))
super.loadContent(name, url);
// FILE protocol
else if (url.getProtocol().equalsIgnoreCase(("file")))
{
final byte[] content = loadResourceContent(url);
setResourceContent(name, content);
}
// try remote loading
else
{
final byte content[] = loadRemoteResourceContent(url);
setResourceContent(name, content);
}
}
/**
* Loads and returns the local resource content.
*
* @throws IOException
*/
protected byte[] loadResourceContent(URL url) throws IOException
{
final byte[] result = NetworkUtil.download(url.openStream());
if (result != null)
loadedSize += result.length;
return result;
}
/**
* Removes the loaded resource
*
* @param resource
*/
public void unload(String resource)
{
if (entryContents.containsKey(resource))
{
if (logger.isLoggable(Level.FINEST))
logger.finest("Removing resource " + resource);
entryContents.remove(resource);
}
else
throw new ResourceNotFoundException(resource, "Resource not found in local ClasspathResources");
}
public boolean isCollisionAllowed()
{
return collisionAllowed;
}
public void setCollisionAllowed(boolean collisionAllowed)
{
this.collisionAllowed = collisionAllowed;
}
public boolean isIgnoreMissingResources()
{
return ignoreMissingResources;
}
public void setIgnoreMissingResources(boolean ignoreMissingResources)
{
this.ignoreMissingResources = ignoreMissingResources;
}
}