/** * Squidy Interaction Library is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * Squidy Interaction Library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Squidy Interaction Library. If not, see * <http://www.gnu.org/licenses/>. * * 2009 Human-Computer Interaction Group, University of Konstanz. * <http://hci.uni-konstanz.de> * * Please contact info@squidy-lib.de or visit our website * <http://www.squidy-lib.de> for further information. */ package org.squidy.manager.scanner; import java.io.File; import java.lang.annotation.Annotation; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * <code>AnnotationScanner</code>. * <p/> * Date: Feb 8, 2008 * Time: 11:33:13 AM * <p/> * @author Roman Rädle, <a href="mailto:Roman.Raedle@uni-konstanz.de">Roman.Raedle@uni-konstanz.de</a>,, University of Konstanz * @version $Id: AnnotationScanner.java 772 2011-09-16 15:39:44Z raedle $$ * */ public final class AnnotationScanner extends ClasspathScanner { // private static final Log LOG = LogFactory.getLog(AnnotationsScanner.class); public AnnotationScanner() { } public Map<Class, List<String>> getAnnotations(final Class<? extends Annotation> annotation, final Set<String> locationFilters, final Set<String> packageFilters) { setLocationFilters(locationFilters != null ? locationFilters : Collections.EMPTY_SET); setPackageFilters(packageFilters != null ? packageFilters : new HashSet<String>(Arrays .asList(DEFAULT_PACKAGE_FILTER))); Map<Class, List<String>> class2Annotation = new HashMap(); Set<String> locationPatterns = new HashSet<String>(); for (String locationFilter : getLocationFilters()) { locationPatterns.add(locationFilter.replace("*", "")); } Set<String> packagePatterns = new HashSet<String>(); for (String packageFilter : getPackageFilters()) { packagePatterns.add(packageFilter.replace("*", "").replace(".", File.separator)); } ClassLoader loader = getClasspath().getClassLoader(); // If it's not a URLClassLoader, we can't deal with it! if (!(loader instanceof URLClassLoader)) { // LOG.error("The current ClassLoader is not castable to a URLClassLoader. ClassLoader is of type [" // + loader.getClass().getName() + "]. Cannot scan ClassLoader for annotations of " // + annotation.getClass().getName() + "."); } else { URLClassLoader urlLoader = (URLClassLoader) loader; URL[] urls = urlLoader.getURLs(); for (URL url : urls) { String path = url.getFile(); File location = new File(path); // Only process the URL if it matches one of our filter strings if (matchesAny(path, locationPatterns)) { // LOG.trace("Checking URL '" + url + "' for annotation of " + annotation); if (location.isDirectory()) { class2Annotation.putAll(getAnnotationsInDirectory(loader, annotation, null, location, packagePatterns)); } } } } return class2Annotation; } private Map<Class, List<String>> getAnnotationsInDirectory(final ClassLoader loader, final Class<? extends Annotation> annotation, final String parent, final File location, final Set<String> packagePatterns) { Map<Class, List<String>> class2Annotation = new HashMap(); File[] files = location.listFiles(); StringBuilder builder = null; for (File file : files) { builder = new StringBuilder(100); builder.append(parent).append(File.separator).append(file.getName()); String packageOrClass = (parent == null ? file.getName() : builder.toString()); if (file.isDirectory()) { class2Annotation.putAll(getAnnotationsInDirectory(loader, annotation, packageOrClass, file, packagePatterns)); } else if (file.getName().endsWith(".class")) { if (matchesAny(packageOrClass, packagePatterns)) { addIfAnnotationPresent(loader, class2Annotation, annotation, packageOrClass); } } } return class2Annotation; } private void addIfAnnotationPresent(final ClassLoader loader, final Map<Class, List<String>> impls, final Class<? extends Annotation> iface, final String name) { try { // LOG.trace("Checking to see if class '" + name + "' has annotation " + iface); String externalName = name.substring(0, name.indexOf('.')).replace(File.separatorChar, '.'); Class type = loadClass(loader, externalName); boolean matched = checkAllMatchers(type); if (type.isAnnotationPresent(iface) || matched) { // LOG.trace("Found: " + type); Annotation annotation = type.getAnnotation(iface); List<String> permissions = impls.get(type); if (permissions == null) { permissions = new ArrayList(); impls.put(type, permissions); } String permission = null; // if we have an annotation use the given path otherwise the // package name // if (annotation instanceof Authorized) { // permission = ((Authorized) annotation).permission(); // } else { // permission = type.getPackage().getName(); // } // // if (permission != null && permission.length() > 0) { // permissions.add(permission); // } } } catch (Throwable t) { // LOG.warn("Could not examine class '" + name + "'. Reason: " + t.getMessage()); } } }