/* * Copyright to the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.rioproject.loader; import edu.emory.mathcs.util.classloader.URIClassLoader; import net.jini.loader.ClassAnnotation; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.MalformedURLException; import java.util.Properties; /** * The ServiceClassLoader overrides getURLs(), ensuring all classes that need to * be annotated with specific location(s) are returned appropriately * * @author Dennis Reedy */ public class ServiceClassLoader extends URIClassLoader implements ClassAnnotation { private URI[] searchPath; /** The ClassAnnotator to use */ private ClassAnnotator annotator; /** Meta data associated with the classloader */ private Properties metaData = new Properties(); /** * Constructs a new ServiceClassLoader for the specified URLs having the * given parent. The constructor takes two sets of URLs. The first set is * where the class loader loads classes from, the second set is what it * returns when getURLs() is called. * * @param searchPath Array of URIs to search for classes * @param annotator Array of URLs to use for the codebase * @param parent Parent ClassLoader to delegate to */ public ServiceClassLoader(URI[] searchPath, ClassAnnotator annotator, ClassLoader parent) { this(searchPath, annotator, parent, null); } /** * Constructs a new ServiceClassLoader for the specified URLs having the * given parent. The constructor takes two sets of URLs. The first set is * where the class loader loads classes from, the second set is what it * returns when getURLs() is called. * * @param searchPath Array of URIs to search for classes * @param annotator Array of URLs to use for the codebase * @param parent Parent ClassLoader to delegate to * @param metaData Optional meta data associated with the classloader */ public ServiceClassLoader(URI[] searchPath, ClassAnnotator annotator, ClassLoader parent, Properties metaData) { super(searchPath, parent); if(annotator==null) throw new IllegalArgumentException("annotator is null"); this.annotator = annotator; this.searchPath = searchPath; if(metaData!=null) this.metaData.putAll(metaData); } /** * Get the {@link org.rioproject.loader.ClassAnnotator} created at construction * time * * @return The ClassAnnotator */ public ClassAnnotator getClassAnnotator() { return(annotator); } /** * Get the meta data associated with this classloader * * @return A Properties object representing any meta data associated with * this classloader. A new Properties object is created each time */ public Properties getMetaData() { return(new Properties(metaData)); } /** * Add meta data associated with the classloader * * @param metaData Properties to associate to this classloader. If the * property already exists in the managed metaData, it will be replaced. * New properties will be added. A null parameter will be ignored. */ public void addMetaData(Properties metaData) { if(metaData==null) return; this.metaData.putAll(metaData); } /** * Get the URLs to be used for class annotations as determined by the * {@link org.rioproject.loader.ClassAnnotator} */ public URL[] getURLs() { return(annotator.getURLs()); } /** * Get the search path of URLs for loading classes and resources * * @return The array of <code>URL[]</code> which corresponds to the search * path for the class loader; that is, the array elements are the locations * from which the class loader will load requested classes. * * @throws MalformedURLException If any of the URis cannot be transformed * to URLs */ public URL[] getSearchPath() throws MalformedURLException { URL[] urls; if(searchPath != null) { urls = new URL[searchPath.length]; for(int i=0; i<urls.length; i++) urls[i] = searchPath[i].toURL(); } else { urls = new URL[0]; } return (urls); } /** * Appends the specified URLs to the list of URLs to search for classes and * resources. * * @param urls The URLs to add */ public void addURLs(URL[] urls) { URI[] uris = new URI[0]; try { uris = getURIs(urls); } catch (URISyntaxException e) { e.printStackTrace(); } for (URI uri : uris) super.addURI(uri); } /** * Get the class annotations as determined by the * {@link org.rioproject.loader.ClassAnnotator} * * @see net.jini.loader.ClassAnnotation#getClassAnnotation */ public String getClassAnnotation() { return (annotator.getClassAnnotation()); } /** * Returns a String representation of this class loader. **/ public String toString() { return(ServiceClassLoader.class.getName()+" "+ "ClassPath : ["+ClassAnnotator.urisToPath(searchPath)+"] "+ "Codebase : ["+getClassAnnotation()+"]"); } /** * Convert a <code>URL[]</code> into a <code>URI[]</code> * * @param urls Array of URLs to convert * * @return Converted array of URIs * * @throws URISyntaxException If there are errors converting the URLs to * URIs */ public static URI[] getURIs(URL[] urls) throws URISyntaxException { if(urls==null) throw new IllegalArgumentException("urls array must not be null"); URI[] uris = new URI[urls.length]; for(int i=0; i<urls.length; i++) { if(urls[i].getProtocol().equals("file")) { File f = new File(urls[i].getFile()); if(f.getAbsolutePath().contains("%20") ) { String path = f.getAbsolutePath().replaceAll("%20", " "); f = new File(path); } uris[i] = f.toURI(); } else { uris[i] = urls[i].toURI(); } } return(uris); } }