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

nz.ac.waikato.cms.locator.ClassCache Maven / Gradle / Ivy

/*
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see .
 */

/*
 * ClassCache.java
 * Copyright (C) 2010-2019 University of Waikato, Hamilton, New Zealand
 */
package nz.ac.waikato.cms.locator;

import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Pattern;

/**
 * A class that stores all classes on the classpath.
 * 
* Use "nz.ac.waikato.cms.locator.ClassCache.LOGLEVEL" with a value of * "{OFF|SEVERE|WARNING|INFO|CONFIG|FINE|FINER|FINEST}" to set custom * logging level. * * @author fracpete (fracpete at waikato dot ac dot nz) */ public class ClassCache implements Serializable { /** for serialization. */ private static final long serialVersionUID = -2973185784363491578L; /** * For listening to the class traversal and populating the caches. * * @author fracpete (fracpete at waikato dot ac dot nz) */ public static class Listener implements TraversalListener { /** for caching all classes on the class path (package-name <-> Set with classnames). */ protected Map> m_NameCache; /** caches the classnames per classpath part (path <-> Set with classnames). */ protected Map> m_ClasspathPartCache; /** the logger in use. */ protected transient Logger m_Logger; /** * Initializes the listener. */ public Listener() { m_NameCache = new HashMap<>(); m_ClasspathPartCache = new HashMap<>(); } /** * Returns the logger in use. * * @return the logger */ public synchronized Logger getLogger() { if (m_Logger == null) { m_Logger = Logger.getLogger(getClass().getName()); m_Logger.setLevel(LoggingHelper.getLevel(getClass())); } return m_Logger; } /** * Gets called when a class is being traversed. * * @param classname the current classname * @param classPathPart the current classpath part this classname is * located in */ @Override public void traversing(String classname, URL classPathPart) { String pkgname; // classname and package pkgname = ClassPathTraversal.extractPackage(classname); // add to package cache if (!m_NameCache.containsKey(pkgname)) m_NameCache.put(pkgname, new HashSet<>()); m_NameCache.get(pkgname).add(classname); // add to classpath part cache if (!m_ClasspathPartCache.containsKey(classPathPart)) m_ClasspathPartCache.put(classPathPart, new HashSet<>()); m_ClasspathPartCache.get(classPathPart).add(classname); } /** * Returns the name cache. * * @return the cache */ public Map> getNameCache() { return m_NameCache; } /** * Returns the classpath path cache. * * @return the cache */ public Map> getClasspathPartCache() { return m_ClasspathPartCache; } } /** the logger in use. */ protected transient Logger m_Logger; /** for caching all classes on the class path (package-name <-> Set with classnames). */ protected Map> m_NameCache; /** the classpath path part cache (classpath part <-> set with classnames). */ protected Map> m_ClasspathPartCache; /** * Initializes the cache. * Uses the {@link ClassPathTraversal} class. */ public ClassCache() { super(); initialize(new ClassPathTraversal()); } /** * Initializes the cache. * * @param traversal the traversal instance to use, can be null */ public ClassCache(ClassTraversal traversal) { super(); initialize((traversal == null) ? new ClassPathTraversal() : traversal); } /** * Returns whether logging is enabled. * * @return true if enabled */ public boolean isLoggingEnabled() { return true; } /** * Returns the logger in use. * * @return the logger */ public synchronized Logger getLogger() { if (m_Logger == null) { m_Logger = Logger.getLogger(getClass().getName()); m_Logger.setLevel(LoggingHelper.getLevel(getClass())); } return m_Logger; } /** * Removes the classname from the cache. * * @param classname the classname to remove * @return true if the removal changed the cache */ public boolean remove(String classname) { String pkgname; Set names; for (URL part: m_ClasspathPartCache.keySet()) m_ClasspathPartCache.get(part).remove(classname); classname = ClassPathTraversal.cleanUp(classname); pkgname = ClassPathTraversal.extractPackage(classname); names = m_NameCache.get(pkgname); if (names != null) return names.remove(classname); else return false; } /** * Returns all the stored packages. * * @return the package names */ public Iterator packages() { return m_NameCache.keySet().iterator(); } /** * Returns all the stored packages that match the provided regular expression. * * @param regexp the regular expression that the package names must match * @return the package names */ public Iterator packages(String regexp) { List result; Pattern pattern; result = new ArrayList<>(); pattern = Pattern.compile(regexp); for (String pkg: m_NameCache.keySet()) { if (pattern.matcher(pkg).matches()) result.add(pkg); } return result.iterator(); } /** * Returns all the classes for the given package. * * @param pkgname the package to get the classes for * @return the classes */ public Set getClassnames(String pkgname) { if (m_NameCache.containsKey(pkgname)) return m_NameCache.get(pkgname); else return new HashSet<>(); } /** * Returns all the stored classpath parts. * * @return the classpath parts */ public Iterator classpathParts() { return m_ClasspathPartCache.keySet().iterator(); } /** * Returns all the stored classpath parts that match the provided regular expression. * * @param regexp the regular expression that the URLs must match * @return the classpath parts */ public Iterator classpathParts(String regexp) { List result; Pattern pattern; result = new ArrayList<>(); pattern = Pattern.compile(regexp); for (URL part : m_ClasspathPartCache.keySet()) { if (pattern.matcher(part.toExternalForm()).matches()) result.add(part); } return result.iterator(); } /** * Returns all the classes for the given classpath part. * * @param part the classpath part to get the classes for * @return the classes */ public Set getClassnames(URL part) { if (m_ClasspathPartCache.containsKey(part)) return m_ClasspathPartCache.get(part); else return new HashSet<>(); } /** * Initializes the cache. */ protected void initialize(ClassTraversal traversal) { Listener listener; listener = new Listener(); traversal.traverse(listener); m_NameCache = listener.getNameCache(); m_ClasspathPartCache = listener.getClasspathPartCache(); } /** * Returns whether the cache is empty. * * @return true if empty */ public boolean isEmpty() { return (m_NameCache == null) || m_NameCache.isEmpty(); } /** * For testing only. * * @param args ignored */ public static void main(String[] args) { ClassCache cache = new ClassCache(); // packages System.out.println("--> Packages"); Iterator pkgs = cache.packages(); List pkgsSorted = new ArrayList<>(); while (pkgs.hasNext()) pkgsSorted.add(pkgs.next()); Collections.sort(pkgsSorted); for (String pkg : pkgsSorted) System.out.println(pkg + ": " + cache.getClassnames(pkg).size()); // packages (nz.*) System.out.println("--> Packages (nz.*)"); pkgs = cache.packages("nz.*"); pkgsSorted = new ArrayList<>(); while (pkgs.hasNext()) pkgsSorted.add(pkgs.next()); Collections.sort(pkgsSorted); for (String pkg : pkgsSorted) System.out.println(pkg + ": " + cache.getClassnames(pkg).size()); // packages System.out.println("--> Classpath parts"); Iterator parts = cache.classpathParts(); List partsSorted = new ArrayList<>(); while (parts.hasNext()) partsSorted.add(parts.next()); Collections.sort(partsSorted, new Comparator() { @Override public int compare(URL o1, URL o2) { return o1.toExternalForm().compareTo(o2.toExternalForm()); } }); for (URL part : partsSorted) System.out.println(part + ": " + cache.getClassnames(part).size()); // packages (.*classes.*) System.out.println("--> Classpath parts (.*classes.*)"); parts = cache.classpathParts(".*classes.*"); partsSorted = new ArrayList<>(); while (parts.hasNext()) partsSorted.add(parts.next()); Collections.sort(partsSorted, new Comparator() { @Override public int compare(URL o1, URL o2) { return o1.toExternalForm().compareTo(o2.toExternalForm()); } }); for (URL part : partsSorted) System.out.println(part + ": " + cache.getClassnames(part).size()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy