/* $Id: ResourceLoader.java 18319 2010-04-20 23:50:51Z euluis $
*****************************************************************************
* Copyright (c) 2009 Contributors - see below
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* tfmorris
*****************************************************************************
*
* Some portions of this file was previously release using the BSD License:
*/
// Copyright (c) 1996-2006 The Regents of the University of California. All
// Rights Reserved. Permission to use, copy, modify, and distribute this
// software and its documentation without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph appear in all copies. This software program and
// documentation are copyrighted by The Regents of the University of
// California. The software program and documentation are supplied "AS
// IS", without any accompanying services from The Regents. The Regents
// does not warrant that the operation of the program will be
// uninterrupted or error-free. The end-user understands that the program
// was developed for research purposes and is advised not to rely
// exclusively on the program for any reason. IN NO EVENT SHALL THE
// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
package org.argouml.application.helpers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.swing.Icon;
import javax.swing.ImageIcon;
/**
* This class manages the resource locations needed within the application.
* Already loaded resources are cached. The resources can be searched in
* different locations.
* <p>
* Derived from org.tigris.gef.util.ResourceLoader with formatting and
* variable naming changed to conform to ArgoUML coding standard.
* <p>
* We use a local copy to reduce coupling to GEF and so that GEF isn't trying
* to do uplevel accesses to the application resources (which won't work in
* environments that enforce strict partitioning between projects eg Eclipse).
*
* @author Original Author: Thorsten Sturm
*/
// NOTE: This is package scope to force callers to use ResourceLoaderWrapper
class ResourceLoader {
private static HashMap<String, Icon> resourceCache =
new HashMap<String, Icon>();
private static List<String> resourceLocations = new ArrayList<String>();
private static List<String> resourceExtensions = new ArrayList<String>();
public static ImageIcon lookupIconResource(String resource) {
return lookupIconResource(resource, resource);
}
public static ImageIcon lookupIconResource(String resource, String desc) {
return lookupIconResource(resource, desc, null);
}
public static ImageIcon lookupIconResource(String resource,
ClassLoader loader) {
return lookupIconResource(resource, resource, loader);
}
/**
* This method tries to find an ImageIcon for the given name in all known
* locations. The file extension of the used image file can be any of the
* known extensions.
*
* @param resource
* Name of the image to be looked after.
* @param desc
* A description for the ImageIcon.
* @param loader
* The class loader that should be used for loading the resource.
* @return ImageIcon for the given name, null if no image could be found.
*/
public static ImageIcon lookupIconResource(String resource, String desc,
ClassLoader loader) {
resource = toJavaIdentifier(resource);
if (isInCache(resource)) {
return (ImageIcon) resourceCache.get(resource);
}
ImageIcon res = null;
java.net.URL imgURL = lookupIconUrl(resource, loader);
if (imgURL != null) {
res = new ImageIcon(imgURL, desc);
synchronized (resourceCache) {
resourceCache.put(resource, res);
}
}
return res;
}
/**
* Search for the given resource with one of the registered extensions, in
* one of the registered locations. The URL of the first found is returned.
*
* @param resource
* base name of resource to search for
* @param loader
* class loader to use
* @return URL representing first location the resource was found or null if
* it was not found in any of the registered locations.
*/
static java.net.URL lookupIconUrl(String resource,
ClassLoader loader) {
java.net.URL imgURL = null;
for (Iterator extensions = resourceExtensions.iterator();
extensions.hasNext();) {
String tmpExt = (String) extensions.next();
for (Iterator locations = resourceLocations.iterator();
locations.hasNext();) {
String imageName =
locations.next() + "/" + resource + "." + tmpExt;
// System.out.println("[ResourceLoader] try loading " + imageName);
if (loader == null) {
imgURL = ResourceLoader.class.getResource(imageName);
} else {
imgURL = loader.getResource(imageName);
}
if (imgURL != null) {
break;
}
}
if (imgURL != null) {
break;
}
}
return imgURL;
}
/**
* Adds a location (path) to the list of known locations. Locations are
* searched in the order they are added, so for best performance add the
* most likely locations first.
*
* @param location
* String representation of the new location.
*/
public static void addResourceLocation(String location) {
if (!containsLocation(location)) {
resourceLocations.add(location);
}
}
/**
* Add an extension to the list of known extensions. Extensions are searched
* in the order they are added, so for best performance add the most likely
* extensions first.
*
* @param extension
* String representation of the new extension.
*/
public static void addResourceExtension(String extension) {
if (!containsExtension(extension)) {
resourceExtensions.add(extension);
}
}
/**
* This method removes a location from the list of known locations.
*
* @param location
* String representation of the location to be removed.
*/
public static void removeResourceLocation(String location) {
for (Iterator iter = resourceLocations.iterator(); iter.hasNext();) {
String loc = (String) iter.next();
if (loc.equals(location)) {
resourceLocations.remove(loc);
break;
}
}
}
/**
* This method removes a extension from the list of known extensions.
*
* @param extension String representation of the extension to be removed.
*/
public static void removeResourceExtension(String extension) {
for (Iterator iter = resourceExtensions.iterator(); iter.hasNext();) {
String ext = (String) iter.next();
if (ext.equals(extension)) {
resourceExtensions.remove(ext);
break;
}
}
}
public static boolean containsExtension(String extension) {
return resourceExtensions.contains(extension);
}
public static boolean containsLocation(String location) {
return resourceLocations.contains(location);
}
public static boolean isInCache(String resource) {
return resourceCache.containsKey(resource);
}
/*
* Strip all characters out of <var>s</var> that could not be part of a
* valid Java identifier. Return either the given string (if all characters
* were valid), or a new string with all invalid characters stripped out.
* This allows automatic conversion of strings containing punctuation and
* spaces to a resource name that can be looked up.
*/
public static final String toJavaIdentifier(String s) {
int len = s.length();
int pos = 0;
for (int i = 0; i < len; i++, pos++) {
if (!Character.isJavaIdentifierPart(s.charAt(i))) break;
}
if (pos == len) {
return s;
}
StringBuffer buf = new StringBuffer(len);
buf.append(s.substring(0, pos));
// skip pos, we know it's not a valid char from above
for (int i = pos + 1; i < len; i++) {
char c = s.charAt(i);
if (Character.isJavaIdentifierPart(c)) {
buf.append(c);
}
}
return buf.toString();
}
} /* end class ResourceLoader */