OpenmrsClassScanner.java
/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.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://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
/**
* Reflection utilities to search the classpath for classes that have a given annotation, implement
* a given interface, etc
*
* @since 1.10
*/
public class OpenmrsClassScanner {
protected final Log log = LogFactory.getLog(getClass());
private static final OpenmrsClassScanner instance = new OpenmrsClassScanner();
private final MetadataReaderFactory metadataReaderFactory;
private final ResourcePatternResolver resourceResolver;
private Map<Class<?>, List<Class<?>>> annotationToClassMap;
OpenmrsClassScanner() {
this.metadataReaderFactory = new SimpleMetadataReaderFactory(OpenmrsClassLoader.getInstance());
this.resourceResolver = new PathMatchingResourcePatternResolver(OpenmrsClassLoader.getInstance());
}
/**
* @return the instance
*/
public static OpenmrsClassScanner getInstance() {
return instance;
}
/**
* Searches for classes with a given annotation.
*
* @param annotation the annotation
* @return the list of found classes
*/
public List<Class<?>> getClassesWithAnnotation(Class annotationClass) {
if (annotationToClassMap != null) {
if (annotationToClassMap.containsKey(annotationClass)) {
return annotationToClassMap.get(annotationClass);
}
} else {
annotationToClassMap = new HashMap<Class<?>, List<Class<?>>>();
}
List<Class<?>> types = new ArrayList<Class<?>>();
String pattern = "classpath*:org/openmrs/**/*.class";
try {
Resource[] resources = resourceResolver.getResources(pattern);
TypeFilter typeFilter = new AnnotationTypeFilter(annotationClass);
for (Resource resource : resources) {
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
if (typeFilter.match(metadataReader, metadataReaderFactory)) {
String classname = metadataReader.getClassMetadata().getClassName();
try {
@SuppressWarnings("unchecked")
Class<?> metadata = (Class<?>) OpenmrsClassLoader.getInstance().loadClass(classname);
types.add(metadata);
}
catch (ClassNotFoundException e) {
throw new IOException("Class cannot be loaded: " + classname, e);
}
}
}
catch (IOException e) {
log.debug("Resource cannot be loaded: " + resource);
}
}
}
catch (IOException ex) {
log.error("Failed to look for classes with annocation" + annotationClass, ex);
}
annotationToClassMap.put(annotationClass, types);
return types;
}
}