Code Search for Developers
 
 
  

ResourcePathClassLoader.java from Magellan-Client at Krugle


Show ResourcePathClassLoader.java syntax highlighted

/*
 *  Copyright (C) 2000-2004 Roger Butenuth, Andreas Gampe,
 *                          Stefan Goetz, Sebastian Pappert,
 *                          Klaas Prause, Enno Rehling,
 *                          Sebastian Tusk, Ulrich Kuester,
 *                          Ilja Pavkovic
 *
 * This file is part of the Eressea Java Code Base, see the
 * file LICENSING for the licensing information applying to
 * this file.
 *
 */

package com.eressea.resource;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import com.eressea.util.CollectionFactory;
import com.eressea.util.IteratorEnumeration;
import com.eressea.util.PropertiesHelper;
import com.eressea.util.logging.Logger;

/**
 * Loads classes and resources from a configurable set of places. Well-known local directories
 * and/or contents of the executed jar file are used as fall-back resourcePaths.
 */
public class ResourcePathClassLoader extends ClassLoader {
	private static final Logger log = Logger.getInstance(ResourcePathClassLoader.class);
	private static Collection staticResourcePaths = CollectionFactory.createLinkedList();
	private Collection resourcePaths = CollectionFactory.createLinkedList();

	/**
	 * Creates a new class loader initializing itself with the specified settings.
	 *
	 * @param settings TODO: DOCUMENT ME!
	 */
	public ResourcePathClassLoader(Properties settings) {
		this.resourcePaths = loadResourcePaths(settings);
	}

	/**
	 * Initializes this class loader for static access.
	 *
	 * @param settings TODO: DOCUMENT ME!
	 */
	public static void init(Properties settings) {
		staticResourcePaths = loadResourcePaths(settings);
	}

	/**
	 * Returns the resource paths this loader operates on.
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public Collection getPaths() {
		return CollectionFactory.unmodifiableCollection(this.resourcePaths);
	}

	/**
	 * Tells this loader which resource paths to search for classes and resources.
	 *
	 * @param paths TODO: DOCUMENT ME!
	 */
	public void setPaths(Collection paths) {
		if(paths == null) {
			this.resourcePaths = CollectionFactory.createLinkedList();
		} else {
			this.resourcePaths = paths;
		}
	}

	/**
	 * Returns the resource paths the static methods of this class operate on.
	 *
	 * @see com.eressea.util.ResourcePathClassLoader#init(java.util.Properties)
	 */
	public static Collection getStaticPaths() {
		return CollectionFactory.unmodifiableCollection(staticResourcePaths);
	}

	/**
	 * Tells this loader which resource paths to search for classes and resources when operating
	 * statically.
	 *
	 * @param paths TODO: DOCUMENT ME!
	 */
	public static void setStaticPaths(Collection paths) {
		if(paths == null) {
			staticResourcePaths = CollectionFactory.createLinkedList();
		} else {
			staticResourcePaths = paths;
		}
	}

	/**
	 * Finds the specified class.
	 *
	 * @param name the name of the class.
	 *
	 * @return the resulting <tt>Class</tt> object.
	 *
	 * @throws ClassNotFoundException if the class could not be found.
	 */
	protected Class findClass(String name) throws ClassNotFoundException {
		URL url = null;
		String fileName = name.replace('.', '/').concat(".class");

		url = getResourceFromPaths(fileName, this.resourcePaths);

		if(url == null) {
			url = getResourceFromCurrentDir(fileName);
		}

		if(url != null) {
			try {
				InputStream is = url.openStream();
				List buffer = CollectionFactory.createLinkedList();
				int read = is.read();

				while(read != -1) {
					buffer.add(new Byte((byte) read));
					read = is.read();
				}

				is.close();

				byte buf[] = new byte[buffer.size()];

				for(int i = 0; i < buffer.size(); i++) {
					buf[i] = ((Byte) buffer.get(i)).byteValue();
				}

				return defineClass(name, buf, 0, buf.length);
			} catch(Exception e) {
				throw new ClassNotFoundException(e.toString());
			}
		} else {
			return findSystemClass(name);
		}
	}

	/**
	 * Finds the resource with the given name.
	 *
	 * @param name the resource name
	 *
	 * @return a URL for reading the resource, or <code>null</code> if the resource could not be
	 * 		   found
	 */
	protected URL findResource(String name) {
		return getResourceStatically(name, this.resourcePaths);
	}

	/**
	 * Finds the resource with the given name.
	 *
	 * @param name the resource name
	 *
	 * @return a URL for reading the resource, or <code>null</code> if the resource could not be
	 * 		   found
	 */
	public static URL getResourceStatically(String name) {
		return getResourceStatically(name, staticResourcePaths);
	}

	/**
	 * Finds the resource with the given name in the given resource paths.
	 *
	 * @param aName The resource name, a relative path!
	 * @param resourcePaths Additional resource paths to find the resource in
	 * 
	 * @return A URL for reading the resource, or <code>null</code> if the resource could not be
	 * 		   found
	 */
	public static URL getResourceStatically(String aName, Collection resourcePaths) {
		URL url = null;
		log.debug("trying to find \""+aName+"\"");

		//String name = Umlaut.replace(aName," ","\\ ");
		String name=aName;
		
		url = getResourceFromPaths(name, resourcePaths);

		if(url == null) {
			url = getResourceFromCurrentDir(name);
		}

		// try to get the resource from the class path
		if(url == null) {
			url = getSystemClassLoader().getResource(name);
		}

		// try to get the resource from the jar
		if(url == null) {
			// FFTest...do not use \ but / (Fiete)
			String myName = name.replace("\\".charAt(0), "/".charAt(0));
			url = getSystemClassLoader().getResource("res/" + myName);
		}

		if(url != null) {
			// do some ugly tests here because of jvm specification bugs with spaces
			// in filenames inside OR outside a jar file
			if(canOpenURLResource(url) == null) {
				URL decoded = canOpenURLResource(URLDecoder.decode(url.toString()));
				if(decoded != null) {
					url = decoded;
				} else {
					URL encoded = canOpenURLResource(URLEncoder.encode(url.toString()));
					if(encoded != null) {
						url = encoded;
					}
				}
			}
		}
		return url;
	}
	
	private static URL canOpenURLResource(String aUrl) {
		try {
			return canOpenURLResource(new URL(aUrl));
		}  catch (MalformedURLException e) {
			return null;
		}
	}

	private static URL canOpenURLResource(URL url) {
		if(url == null) return null;
		try {
			url.openStream().close();
			return url;
		} catch (IOException e) {
			return null;
		}	
	}

	/**
	 * Searches the available resource paths for a resource with the specified name and returns the
	 * first match.
	 *
	 * @param name The resource name, a relative path!
	 * @param resourcePaths The collection of resource paths.
	 *
	 * @return a URL for reading the resource, or <code>null</code> if the resource could not be
	 * 		   found
	 */
	private static URL getResourceFromPaths(String name, Collection resourcePaths) {
		URL url = null;

		for(Iterator iter = resourcePaths.iterator(); iter.hasNext() && (url == null);) {
			url = verifyResource((URL) iter.next(), name);
		}

		return url;
	}

	/**
	 * Searches the available resource paths for all resources with the specified name.
	 *
	 * @param name The resource name, a relative path!
	 * @param resourcePaths The collection of resource paths.
	 *
	 * @return A Collection of all the URLs found for reading the resource, an empty collection if the resource could not be
	 * 		   found
	 */
	private static Collection getResourcesFromPaths(String name, Collection resourcePaths) {
		Collection urls = CollectionFactory.createLinkedList();

		for(Iterator iter = resourcePaths.iterator(); iter.hasNext();) {
			URL url = verifyResource((URL) iter.next(), name);

			if(url != null) {
				urls.add(url);
			}
		}

		return urls;
	}

	/**
	 * Searches the available resource paths for the resources with the specified names until at
	 * least one is found.
	 *
	 * @param names A Collection of resource names
	 * @param resourcePaths The collection of resource paths.
	 *
	 * @return A Collection of the URLs for reading the resource found at the first location, an empty collection if the resource could not be
	 * 		   found
	 */
	private static Collection getResourcesFromPaths(Collection names, Collection resourcePaths) {
		Collection urls = CollectionFactory.createLinkedList();

		for(Iterator iter = resourcePaths.iterator(); iter.hasNext() && (urls.size() == 0);) {
			URL path = (URL) iter.next();

			for(Iterator nameIter = names.iterator(); nameIter.hasNext();) {
				String name = (String) nameIter.next();
				URL url = verifyResource(path, name);

				if(url != null) {
					urls.add(url);
				}
			}
		}

		return urls;
	}

	/**
	 * Searches the current directory for a resource with the specified name.
	 *
	 * @param name The resource name, a relative path!
	 *
	 * @return a URL for reading the resource, or <code>null</code> if the resource could not be
	 * 		   found
	 */
	private static URL getResourceFromCurrentDir(String name) {
		URL url = null;

		try {
			File currentDirectory = new File(".");
			URL baseLocation = new URL(currentDirectory.toURL(), "res/");
			url = verifyResource(baseLocation, name);
		} catch(Exception e) {
			log.error(e);
		}

		return url;
	}

	/**
	 * Searches the current directory for the resources with the specified names.
	 *
	 * @param names A Collection of resource names.
	 *
	 * @return A Collection of URLs for reading the resource, empty if the resource could not be
	 * 		   found.
	 */
	private static Collection getResourcesFromCurrentDir(Collection names) {
		Collection urls = CollectionFactory.createLinkedList();

		try {
			File currentDirectory = new File(".");
			URL baseLocation = new URL(currentDirectory.toURL(), "res/");

			for(Iterator iter = names.iterator(); iter.hasNext();) {
				String name = (String) iter.next();
				URL url = verifyResource(baseLocation, name);

				if(url != null) {
					urls.add(url);
				}
			}
		} catch(Exception e) {
			log.error(e);
		}

		return urls;
	}

	/**
	 * Checks if the object specified by the base location and the name exists. If it does, a valid
	 * URL pointing to is returned else null.
	 *
	 * @param location TODO: DOCUMENT ME!
	 * @param name TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	private static URL verifyResource(URL location, String name) {
		URL url = null;

		try {
			url = new URL(location, name);

			InputStream istream = url.openStream();
			istream.close();
		} catch(Exception ex) {
			url = null;
		}

		return url;
	}

	/**
	 * Returns an Enumeration of URLs representing all the resources with the given name.
	 *
	 * @param name the resource name
	 *
	 * @return an Enumeration of URLs for the resources
	 *
	 * @throws IOException if I/O errors occur
	 */
	protected Enumeration findResources(String name) throws IOException {
		Collection urls = CollectionFactory.createLinkedList();

		urls.addAll(getResourcesFromPaths(name, resourcePaths));

		URL url = getResourceFromCurrentDir(name);

		if(url != null) {
			urls.add(url);
		}

		// try to get the resource from the class path
		url = getSystemClassLoader().getResource(name);

		if(url != null) {
			urls.add(url);
		}

		// try to get the resource from the jar
		//		 FFTest...do not use \ but / (Fiete)
		String myName = name.replace("\\".charAt(0), "/".charAt(0));
		url = getSystemClassLoader().getResource("res/" + myName);

		if(url != null) {
			urls.add(url);
		}

		return new IteratorEnumeration(urls.iterator());
	}

	/**
	 * Tries to find the specified bunch of resources. As soon as one of the resources is found in
	 * a location no other location is searched but it is attempted to find as many of the other
	 * specified resources in the same location.
	 *
	 * @param names the resource names
	 * @param resourcePaths additional resource paths to find the resources in
	 *
	 * @return the URLs the found resources can be read from
	 */
	private static Collection getResourcesStatically(Collection names, Collection resourcePaths) {
		Collection urls = getResourcesFromPaths(names, resourcePaths);

		if(urls.size() == 0) {
			urls = getResourcesFromCurrentDir(names);
		}

		// try to get the resource from the class path
		if(urls.size() == 0) {
			for(Iterator iter = names.iterator(); iter.hasNext();) {
				String name = (String) iter.next();
				URL url = getSystemClassLoader().getResource(name);

				if(url != null) {
					urls.add(url);
				}
			}
		}

		// try to get the resource from the jar
		if(urls.size() == 0) {
			for(Iterator iter = names.iterator(); iter.hasNext();) {
				String name = (String) iter.next();
				// FFTest...do not use \ but / (Fiete)
				String myName = name.replace("\\".charAt(0), "/".charAt(0));
				URL url = getSystemClassLoader().getResource("res/" + myName);

				if(url != null) {
					urls.add(url);
				}
			}
		}

		return urls;
	}

	/**
	 * Tries to find the specified bunch of resources. As soon as one of the resources is found in
	 * a location no further locations are scanned for the resources, but it is attempted to find
	 * as many of the other specified resources in the same location.
	 *
	 * @param names the resource names
	 *
	 * @return the URLs the found resources can be read from
	 */
	public static Collection getResourcesStatically(Collection names) {
		return getResourcesStatically(names, staticResourcePaths);
	}

	/**
	 * Tries to find the given resource in all resource paths including working directory and
	 * source jar. It will return all found URLs.
	 *
	 * @param name TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public static Collection getResourceFromAllPaths(String name) {
		Collection col = CollectionFactory.createLinkedList();

		URL url = getSystemClassLoader().getResource(name);

		if(url != null) {
			col.add(url);
		}

		url = getResourceFromCurrentDir(name);

		if(url != null) {
			col.add(url);
		}

		for(Iterator iter = staticResourcePaths.iterator(); iter.hasNext();) {
			url = verifyResource((URL) iter.next(), name);

			if(url != null) {
				col.add(url);
			}
		}

		if(col.size() == 0) {
			col = null;
		}

		return col;
	}

	/**
	 * Loads the resource paths from the specified settings.
	 *
	 * @param settings TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	private static Collection loadResourcePaths(Properties settings) {
		Collection properties = PropertiesHelper.getList(settings, "Resources.preferredPathList");

		Collection resourcePaths = CollectionFactory.createArrayList(properties.size());

		for(Iterator iter = properties.iterator(); iter.hasNext();) {
			String location = (String) iter.next();

			try {
				resourcePaths.add(new URL(location));
			} catch(MalformedURLException e) {
				log.error(e);
			}
		}

		return resourcePaths;
	}

	/**
	 * Stores the specified resource paths to the specified settings.
	 *
	 * @param resourcePaths TODO: DOCUMENT ME!
	 * @param settings TODO: DOCUMENT ME!
	 */
	public static void storePaths(Collection resourcePaths, Properties settings) {
		if(resourcePaths == null) {
			resourcePaths = CollectionFactory.createLinkedList();
		}

		PropertiesHelper.setList(settings, "Resources.preferredPathList", resourcePaths);
	}
}




See more files for this project here

Magellan-Client

The Magellan Client is basicly a GUI for the pbem game eressea but can be used for other pbems based on \"atlantis\" too.

Project homepage: http://sourceforge.net/projects/magellan-client
Programming language(s): Java
License: other

  ResourcePathClassLoader.java
  ResourceSettings.java
  ResourceSettingsFactory.java