/******************************************************************************* * Copyright (c) 2007, 2014 Massimiliano Ziccardi * * 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 it.jnrpe.utils; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.WeakHashMap; /** * This class stores the already loaded plugin class so that no attempts will be * performed to load the same class twice. * * @author Massimiliano Ziccardi * * @version $Revision: 1.0 $ */ @SuppressWarnings("rawtypes") final class LoadedClassCache { /** * Private constructor to avoid instantiations. */ private LoadedClassCache() { } /** * Stores data about each created class loader. */ private static final Map<ClassLoader, ClassesData> LOADED_PLUGINS = new WeakHashMap<ClassLoader, ClassesData>(); /** * This class stores data about all the classes loaded by a classloader. * * @author Massimiliano Ziccardi * */ private static final class ClassesData { /** * Maps classname with corresponding Class object. */ private final Map<String, Class> loadedClasses = new HashMap<String, Class>(); /** * @param name * the class name * @return the cached class object (if any) */ public Class getClass(final String name) { return loadedClasses.get(name); } /** * Adds a class to the cache. * * @param clazz * the class to be added */ public void addClass(final Class clazz) { loadedClasses.put(clazz.getName(), clazz); } /** * Method toString. * @return String */ @Override public String toString() { final int maxLen = 10; return "ClassesData [loadedClasses=" + (loadedClasses != null ? toString(loadedClasses.entrySet(), maxLen) : null) + "]"; } /** * Method toString. * @param collection Collection<?> * @param maxLen int * @return String */ private String toString(Collection<?> collection, int maxLen) { StringBuilder builder = new StringBuilder(); builder.append('['); int i = 0; for (Iterator<?> iterator = collection.iterator(); iterator.hasNext() && i < maxLen; i++) { if (i > 0) { builder.append(", "); } builder.append(iterator.next()); } builder.append(']'); return builder.toString(); } } /** * Stores a class in the cache. * * @param cl * The classloader * @param c * the class to be stored */ private static void saveClass(final ClassLoader cl, final Class c) { if (LOADED_PLUGINS.get(cl) == null) { LOADED_PLUGINS.put(cl, new ClassesData()); } ClassesData cd = LOADED_PLUGINS.get(cl); cd.addClass(c); } /** * Returns a class object. If the class is new, a new Class object is * created, otherwise the cached object is returned. * * @param cl * the classloader * @param className * the class name * @return the class object associated to the given class name * @throws ClassNotFoundException * if the class can't be loaded */ public static Class getClass(final ClassLoader cl, final String className) throws ClassNotFoundException { if (LOADED_PLUGINS.get(cl) == null) { LOADED_PLUGINS.put(cl, new ClassesData()); } ClassesData cd = LOADED_PLUGINS.get(cl); Class clazz = cd.getClass(className); if (clazz == null) { clazz = cl.loadClass(className); saveClass(cl, clazz); } return clazz; } }