001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019 020package icy.plugin.classloader; 021 022import icy.file.FileUtil; 023import icy.network.NetworkUtil; 024import icy.plugin.classloader.exception.JclException; 025import icy.plugin.classloader.exception.ResourceNotFoundException; 026import icy.system.IcyExceptionHandler; 027 028import java.io.File; 029import java.io.IOException; 030import java.net.URISyntaxException; 031import java.net.URL; 032import java.util.logging.Level; 033import java.util.logging.Logger; 034 035/** 036 * Class that builds a local classpath by loading resources from different 037 * files/paths 038 * 039 * @author Kamran Zafar 040 * @author Stephane Dallongeville 041 */ 042public class ClasspathResources extends JarResources 043{ 044 private static Logger logger = Logger.getLogger(ClasspathResources.class.getName()); 045 private boolean ignoreMissingResources; 046 047 public ClasspathResources() 048 { 049 super(); 050 ignoreMissingResources = Configuration.suppressMissingResourceException(); 051 } 052 053 /** 054 * Attempts to load a remote resource (jars, properties files, etc) 055 * 056 * @param url 057 */ 058 protected void loadRemoteResource(URL url) 059 { 060 if (logger.isLoggable(Level.FINEST)) 061 logger.finest("Attempting to load a remote resource."); 062 063 if (url.toString().toLowerCase().endsWith(".jar")) 064 { 065 try 066 { 067 loadJar(url); 068 } 069 catch (IOException e) 070 { 071 System.err.println("JarResources.loadJar(" + url + ") error:"); 072 IcyExceptionHandler.showErrorMessage(e, false, true); 073 } 074 return; 075 } 076 077 if (entryUrls.containsKey(url.toString())) 078 { 079 if (!collisionAllowed) 080 throw new JclException("Resource " + url.toString() + " already loaded"); 081 082 if (logger.isLoggable(Level.FINEST)) 083 logger.finest("Resource " + url.toString() + " already loaded; ignoring entry..."); 084 return; 085 } 086 087 if (logger.isLoggable(Level.FINEST)) 088 logger.finest("Loading remote resource."); 089 090 entryUrls.put(url.toString(), url); 091 } 092 093 /** 094 * Loads and returns content the remote resource (jars, properties files, etc) 095 * 096 * @throws IOException 097 */ 098 protected byte[] loadRemoteResourceContent(URL url) throws IOException 099 { 100 final byte[] result = NetworkUtil.download(url.openStream()); 101 102 if (result != null) 103 loadedSize += result.length; 104 105 return result; 106 } 107 108 /** 109 * Reads local and remote resources 110 * 111 * @param url 112 */ 113 protected void loadResource(URL url) 114 { 115 try 116 { 117 final File file = new File(url.toURI()); 118 // Is Local 119 loadResource(file, FileUtil.getGenericPath(file.getAbsolutePath())); 120 } 121 catch (IllegalArgumentException iae) 122 { 123 // Is Remote 124 loadRemoteResource(url); 125 } 126 catch (URISyntaxException e) 127 { 128 throw new JclException("URISyntaxException", e); 129 } 130 } 131 132 /** 133 * Reads local resources from - Jar files - Class folders - Jar Library 134 * folders 135 * 136 * @param path 137 */ 138 protected void loadResource(String path) 139 { 140 if (logger.isLoggable(Level.FINEST)) 141 logger.finest("Resource: " + path); 142 143 File fp = new File(path); 144 145 if (!fp.exists() && !ignoreMissingResources) 146 throw new JclException("File/Path does not exist"); 147 148 loadResource(fp, FileUtil.getGenericPath(path)); 149 } 150 151 /** 152 * Reads local resources from - Jar files - Class folders - Jar Library 153 * folders 154 * 155 * @param fol 156 * @param packName 157 */ 158 protected void loadResource(File fol, String packName) 159 { 160 // FILE 161 if (fol.isFile()) 162 { 163 if (fol.getName().toLowerCase().endsWith(".jar")) 164 { 165 try 166 { 167 loadJar(fol.toURI().toURL()); 168 } 169 catch (IOException e) 170 { 171 System.err.println("JarResources.loadJar(" + fol.getAbsolutePath() + ") error:"); 172 IcyExceptionHandler.showErrorMessage(e, false, true); 173 } 174 } 175 else 176 loadResourceInternal(fol, packName); 177 } 178 // DIRECTORY 179 else 180 { 181 if (fol.list() != null) 182 { 183 for (String f : fol.list()) 184 { 185 File fl = new File(fol.getAbsolutePath() + "/" + f); 186 187 String pn = packName; 188 189 if (fl.isDirectory()) 190 { 191 192 if (!pn.equals("")) 193 pn = pn + "/"; 194 195 pn = pn + fl.getName(); 196 } 197 198 loadResource(fl, pn); 199 } 200 } 201 } 202 } 203 204 /** 205 * Loads the local resource. 206 */ 207 protected void loadResourceInternal(File file, String pack) 208 { 209 String entryName = ""; 210 211 if (pack.length() > 0) 212 entryName = pack + "/"; 213 entryName += file.getName(); 214 215 if (entryUrls.containsKey(entryName)) 216 { 217 if (!collisionAllowed) 218 throw new JclException("Resource " + entryName + " already loaded"); 219 220 if (logger.isLoggable(Level.WARNING)) 221 logger.finest("Resource " + entryName + " already loaded; ignoring entry..."); 222 return; 223 } 224 225 if (logger.isLoggable(Level.FINEST)) 226 logger.finest("Loading resource: " + entryName); 227 228 try 229 { 230 entryUrls.put(entryName, file.toURI().toURL()); 231 } 232 catch (Exception e) 233 { 234 if (logger.isLoggable(Level.SEVERE)) 235 logger.finest("Error while loading: " + entryName); 236 237 System.err.println("JarResources.loadResourceInternal(" + file.getAbsolutePath() + ") error:"); 238 IcyExceptionHandler.showErrorMessage(e, false, true); 239 } 240 } 241 242 @Override 243 protected void loadContent(String name, URL url) throws IOException 244 { 245 // JAR protocol 246 if (url.getProtocol().equalsIgnoreCase(("jar"))) 247 super.loadContent(name, url); 248 // FILE protocol 249 else if (url.getProtocol().equalsIgnoreCase(("file"))) 250 { 251 final byte[] content = loadResourceContent(url); 252 setResourceContent(name, content); 253 } 254 // try remote loading 255 else 256 { 257 final byte content[] = loadRemoteResourceContent(url); 258 setResourceContent(name, content); 259 } 260 } 261 262 /** 263 * Loads and returns the local resource content. 264 * 265 * @throws IOException 266 */ 267 protected byte[] loadResourceContent(URL url) throws IOException 268 { 269 final byte[] result = NetworkUtil.download(url.openStream()); 270 271 if (result != null) 272 loadedSize += result.length; 273 274 return result; 275 } 276 277 /** 278 * Removes the loaded resource 279 * 280 * @param resource 281 */ 282 public void unload(String resource) 283 { 284 if (entryContents.containsKey(resource)) 285 { 286 if (logger.isLoggable(Level.FINEST)) 287 logger.finest("Removing resource " + resource); 288 entryContents.remove(resource); 289 } 290 else 291 throw new ResourceNotFoundException(resource, "Resource not found in local ClasspathResources"); 292 } 293 294 public boolean isCollisionAllowed() 295 { 296 return collisionAllowed; 297 } 298 299 public void setCollisionAllowed(boolean collisionAllowed) 300 { 301 this.collisionAllowed = collisionAllowed; 302 } 303 304 public boolean isIgnoreMissingResources() 305 { 306 return ignoreMissingResources; 307 } 308 309 public void setIgnoreMissingResources(boolean ignoreMissingResources) 310 { 311 this.ignoreMissingResources = ignoreMissingResources; 312 } 313}