All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.grinder.util.ClassLoaderUtilities Maven / Gradle / Ivy

There is a newer version: 3.11
Show newest version
// Copyright (C) 2011 - 2012 Philip Aston
// All rights reserved.
//
// This file is part of The Grinder software distribution. Refer to
// the file LICENSE which is part of The Grinder distribution for
// licensing details. The Grinder distribution is available on the
// Internet at http://grinder.sourceforge.net/
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

package net.grinder.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import net.grinder.engine.common.EngineException;


/**
 * Class loader related utilities.
 *
 * @author Philip Aston
 */
public class ClassLoaderUtilities {

  /**
   * Find all the resources with the given path, load them, and return their
   * contents as a list of Strings.
   *
   * 

Property file style comments can be added using "#".

* *

Lines are processed as follows: *

    *
  • Comments are removed from each line.
  • *
  • Leading and trailing white space is removed from each line.
  • *
  • Blank lines are discarded.
  • *
*

* * @param classLoader * Starting class loader to search. The parent class loaders will be * searched first - see {@link ClassLoader#getResources}. * @param resourceName * The name of the resources. Multiple resources may have the same * name if they are loaded from different class loaders. * @return The contents of the resources, line by line. * @throws IOException * If there was a problem parsing the resources. */ public static List allResourceLines(ClassLoader classLoader, String resourceName) throws IOException { final List result = new ArrayList(); final Enumeration resources = classLoader.getResources(resourceName); // See http://findbugs.sourceforge.net/bugDescriptions.html // #DMI_COLLECTION_OF_URLS. final Set seenURLs = new HashSet(); while (resources.hasMoreElements()) { final URL url = resources.nextElement(); final String urlString = url.toString(); if (seenURLs.contains(urlString)) { continue; } seenURLs.add(urlString); final InputStream in = url.openStream(); try { final BufferedReader reader = new BufferedReader(new InputStreamReader(in, "utf-8")); while (true) { String line = reader.readLine(); if (line == null) { break; } final int comment = line.indexOf('#'); if (comment >= 0) { line = line.substring(0, comment); } line = line.trim(); if (line.length() > 0) { result.add(line); } } reader.close(); } finally { in.close(); } } return result; } /** *

* Equivalent to {@code loadRegisteredImplementations(resourceName, * Object.class, classLoader)}. *

* * @param resourceName * The name of the resources to find. * @param classLoader * Classloader to use to load implementations. * @return The implementation classes. * @throws EngineException * If a class could not be loaded. * @see #loadRegisteredImplementations(String, Class, ClassLoader) */ public static List> loadRegisteredImplementations(String resourceName, ClassLoader classLoader) throws EngineException { return loadRegisteredImplementations(resourceName, Object.class, classLoader); } /** *

* Equivalent to {@code loadRegisteredImplementations(resourceName, * cls, cls.getClassLoader())}. *

* * @param resourceName * The name of the resources to find. * @param cls * Implementation classes must be assignable to this class. * @return The implementation classes. * @throws EngineException * If a class could not be loaded. * @param * Constrains type of {@code cls}. * @see #loadRegisteredImplementations(String, Class, ClassLoader) */ public static List> loadRegisteredImplementations(String resourceName, Class cls) throws EngineException { return loadRegisteredImplementations(resourceName, cls, cls.getClassLoader()); } /** * Simple mechanism for dynamically specified implementations. * *

* The classpath is searched for all resources called {@code resourceName}. * Matching resources are then parsed with {@link #allResourceLines} to obtain * a list of implementation class names. These classes are dynamically loaded, * and returned. *

* * @param resourceName * The name of the resources to find. * @param cls * Implementation classes must be assignable to this class. * @param classLoader * Classloader to use to load implementations. * @return The implementation classes. The order of the classes depends on the * classpath and the order of entries in individual resource files. We * maintain the order because the caller might want to load more * fundamental implementations first. * @throws EngineException * If a class could not be loaded. * @param * Constrains type of {@code cls}. */ @SuppressWarnings("unchecked") public static List> loadRegisteredImplementations(String resourceName, Class cls, ClassLoader classLoader) throws EngineException { final List names; try { names = allResourceLines(classLoader, resourceName); } catch (IOException e) { throw new EngineException("Failed to load implementation", e); } final Set seen = new HashSet(names.size()); final List> result = new ArrayList>(names.size()); for (String implementationName : names) { if (!seen.add(implementationName)) { continue; } try { final Class implementationClass = Class.forName(implementationName); if (cls.isAssignableFrom(implementationClass)) { result.add((Class) implementationClass); } else { throw new EngineException(implementationName + " does not implement " + cls.getName()); } } catch (ClassNotFoundException e) { throw new EngineException("Could not load '" + implementationName + "'", e); } } return result; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy