refs #2357: Remove reflections dependency from document-store-lib
https://support.d4science.org/issues/2357 git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-publishing/document-store-lib@124712 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
7bbaa4ed20
commit
77d911861b
2
pom.xml
2
pom.xml
|
@ -38,11 +38,13 @@
|
|||
<version>1.7.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>0.9.10</version>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<!-- Test Dependency -->
|
||||
<dependency>
|
||||
|
|
|
@ -47,6 +47,10 @@ public abstract class PersistenceBackendFactory {
|
|||
fallbackLastCheck = new HashMap<String, Long>();
|
||||
}
|
||||
|
||||
public static void setDefaultAggregationPackage(Package packageObj){
|
||||
|
||||
}
|
||||
|
||||
private static File file(File file) throws IllegalArgumentException {
|
||||
if(!file.isDirectory()){
|
||||
file = file.getParentFile();
|
||||
|
|
|
@ -7,10 +7,12 @@ import java.io.Serializable;
|
|||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.reflections.Reflections;
|
||||
//import org.reflections.Reflections;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -27,11 +29,82 @@ public class RecordUtility {
|
|||
private final static String KEY_VALUE_PAIR_SEPARATOR = ",";
|
||||
private final static String KEY_VALUE_LINKER = "=";
|
||||
|
||||
private RecordUtility(){}
|
||||
|
||||
protected static Set<Package> recordPackages;
|
||||
protected static Map<String, Class<? extends Record>> recordClassesFound;
|
||||
|
||||
protected static Map<String, Class<? extends AggregatedRecord>> aggregatedRecordClassesFound;
|
||||
protected static Map<Class<? extends Record>, Class<? extends AggregatedRecord>> recordAggregationMapping;
|
||||
|
||||
private RecordUtility(){}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void addRecordPackage(Package packageObject) {
|
||||
if(recordPackages.contains(packageObject)){
|
||||
logger.trace("Package ({}) already scanned", packageObject.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
List<Class<?>> classes = ReflectionUtility.getClassesForPackage(packageObject);
|
||||
for(Class<?> clz : classes){
|
||||
if(Record.class.isAssignableFrom(clz)){
|
||||
addRecordClass((Class<? extends Record>) clz);
|
||||
}
|
||||
if(AggregatedRecord.class.isAssignableFrom(clz)){
|
||||
addAggregatedRecordClass((Class<? extends AggregatedRecord>) clz);
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.error("Error discovering classes inside package {}", packageObject.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void addRecordClass(Class<? extends Record> cls){
|
||||
if(Modifier.isAbstract(cls.getModifiers())){
|
||||
return;
|
||||
}
|
||||
|
||||
String discoveredRecordType;
|
||||
try {
|
||||
Record record = cls.newInstance();
|
||||
if(record instanceof AggregatedRecord){
|
||||
return;
|
||||
}
|
||||
discoveredRecordType = record.getRecordType();
|
||||
|
||||
if(!recordClassesFound.containsKey(discoveredRecordType)){
|
||||
recordClassesFound.put(discoveredRecordType, cls);
|
||||
}
|
||||
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
logger.error("Unable to instantiate found {} class ({})",
|
||||
Record.class.getSimpleName(), cls.getSimpleName(), e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected static void addAggregatedRecordClass(Class<? extends AggregatedRecord> cls){
|
||||
if(Modifier.isAbstract(cls.getModifiers())){
|
||||
return;
|
||||
}
|
||||
|
||||
String discoveredRecordType;
|
||||
try {
|
||||
AggregatedRecord instance = cls.newInstance();
|
||||
discoveredRecordType = instance.getRecordType();
|
||||
if(!aggregatedRecordClassesFound.containsKey(discoveredRecordType)){
|
||||
aggregatedRecordClassesFound.put(discoveredRecordType, cls);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Record> recordClass = instance.getAggregable();
|
||||
recordAggregationMapping.put(recordClass, cls);
|
||||
}
|
||||
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
logger.error("Unable to instantiate found {} class ({})",
|
||||
AggregatedRecord.class.getSimpleName(), cls.getSimpleName(), e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the recordClassesFound
|
||||
|
@ -48,54 +121,28 @@ public class RecordUtility {
|
|||
}
|
||||
|
||||
static {
|
||||
recordPackages = new HashSet<>();
|
||||
|
||||
recordClassesFound = new HashMap<>();
|
||||
aggregatedRecordClassesFound = new HashMap<>();
|
||||
|
||||
recordAggregationMapping = new HashMap<>();
|
||||
|
||||
/* Old code using Reflections
|
||||
Reflections recordClassesReflections = new Reflections();
|
||||
Set<Class<? extends Record>> recordClasses = recordClassesReflections.getSubTypesOf(Record.class);
|
||||
for(Class<? extends Record> cls : recordClasses){
|
||||
if(Modifier.isAbstract(cls.getModifiers())){
|
||||
continue;
|
||||
}
|
||||
|
||||
String discoveredRecordType;
|
||||
try {
|
||||
Record record = cls.newInstance();
|
||||
if(record instanceof AggregatedRecord){
|
||||
continue;
|
||||
}
|
||||
discoveredRecordType = record.getRecordType();
|
||||
|
||||
if(!recordClassesFound.containsKey(discoveredRecordType)){
|
||||
recordClassesFound.put(discoveredRecordType, cls);
|
||||
}
|
||||
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
continue;
|
||||
}
|
||||
addRecordClass(cls)
|
||||
}
|
||||
|
||||
aggregatedRecordClassesFound = new HashMap<>();
|
||||
Reflections aggregatedRecordReflections = new Reflections();
|
||||
Set<Class<? extends AggregatedRecord>> aggregatedRecordClasses = aggregatedRecordReflections.getSubTypesOf(AggregatedRecord.class);
|
||||
for(Class<? extends AggregatedRecord> cls : aggregatedRecordClasses){
|
||||
if(Modifier.isAbstract(cls.getModifiers())){
|
||||
continue;
|
||||
}
|
||||
|
||||
String discoveredRecordType;
|
||||
try {
|
||||
discoveredRecordType = cls.newInstance().getRecordType();
|
||||
if(!aggregatedRecordClassesFound.containsKey(discoveredRecordType)){
|
||||
aggregatedRecordClassesFound.put(discoveredRecordType, cls);
|
||||
}
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
logger.error("Unable to instantiate found {} class ({})",
|
||||
AggregatedRecord.class.getSimpleName(), cls.getSimpleName(), e);
|
||||
continue;
|
||||
}
|
||||
addAggregatedRecordClass(cls);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
public static Class<? extends AggregatedRecord> getAggregatedRecordClass(String recordType) throws ClassNotFoundException {
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
/**
|
||||
*
|
||||
*/
|
||||
package org.gcube.documentstore.records;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
* Got from
|
||||
* http://stackoverflow.com/questions/520328/can-you-find-all-classes-in-a-package-using-reflection#answer-22462785
|
||||
*
|
||||
* The method first gets the current ClassLoader. It then fetches all resources
|
||||
* that contain said package and iterates of these URLs. It then creates a
|
||||
* URLConnection and determines what type of URL we have. It can either be a
|
||||
* directory (FileURLConnection) or a directory inside a jar or zip file
|
||||
* (JarURLConnection). Depending on what type of connection we have two
|
||||
* different methods will be called.
|
||||
*
|
||||
* First lets see what happens if it is a FileURLConnection.
|
||||
*
|
||||
* It first checks if the passed File exists and is a directory. If that's the
|
||||
* case it checks if it is a class file. If so a Class object will be created
|
||||
* and put in the List. If it is not a class file but is a directory, we
|
||||
* simply iterate into it and do the same thing. All other cases/files will be
|
||||
* ignored.
|
||||
*
|
||||
* If the URLConnection is a JarURLConnection the other private helper method
|
||||
* will be called. This method iterates over all Entries in the zip/jar
|
||||
* archive. If one entry is a class file and is inside of the package a Class
|
||||
* object will be created and stored in the ArrayList.
|
||||
*
|
||||
* After all resources have been parsed it (the main method) returns the
|
||||
* ArrayList containing all classes in the given package, that the current
|
||||
* ClassLoader knows about.
|
||||
*
|
||||
* If the process fails at any point a ClassNotFoundException will be thrown
|
||||
* containing detailed information about the exact cause.
|
||||
*
|
||||
*/
|
||||
public class ReflectionUtility {
|
||||
|
||||
/**
|
||||
* Private helper method
|
||||
*
|
||||
* @param directory
|
||||
* The directory to start with
|
||||
* @param pckgname
|
||||
* The package name to search for. Will be needed for getting the
|
||||
* Class object.
|
||||
* @param classes
|
||||
* if a file isn't loaded but still is in the directory
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
private static void checkDirectory(File directory, String pckgname,
|
||||
List<Class<?>> classes) throws ClassNotFoundException {
|
||||
File tmpDirectory;
|
||||
|
||||
if (directory.exists() && directory.isDirectory()) {
|
||||
final String[] files = directory.list();
|
||||
|
||||
for (final String file : files) {
|
||||
if (file.endsWith(".class")) {
|
||||
try {
|
||||
classes.add(Class.forName(pckgname + '.'
|
||||
+ file.substring(0, file.length() - 6)));
|
||||
} catch (final NoClassDefFoundError e) {
|
||||
// do nothing. this class hasn't been found by the
|
||||
// loader, and we don't care.
|
||||
}
|
||||
} else if ((tmpDirectory = new File(directory, file))
|
||||
.isDirectory()) {
|
||||
checkDirectory(tmpDirectory, pckgname + "." + file, classes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method.
|
||||
*
|
||||
* @param connection
|
||||
* the connection to the jar
|
||||
* @param pckgname
|
||||
* the package name to search for
|
||||
* @param classes
|
||||
* the current ArrayList of all classes. This method will simply
|
||||
* add new classes.
|
||||
* @throws ClassNotFoundException
|
||||
* if a file isn't loaded but still is in the jar file
|
||||
* @throws IOException
|
||||
* if it can't correctly read from the jar file.
|
||||
*/
|
||||
private static void checkJarFile(JarURLConnection connection,
|
||||
String pckgname, List<Class<?>> classes)
|
||||
throws ClassNotFoundException, IOException {
|
||||
final JarFile jarFile = connection.getJarFile();
|
||||
final Enumeration<JarEntry> entries = jarFile.entries();
|
||||
String name;
|
||||
|
||||
for (JarEntry jarEntry = null; entries.hasMoreElements()
|
||||
&& ((jarEntry = entries.nextElement()) != null);) {
|
||||
name = jarEntry.getName();
|
||||
|
||||
if (name.contains(".class")) {
|
||||
name = name.substring(0, name.length() - 6).replace('/', '.');
|
||||
|
||||
if (name.contains(pckgname)) {
|
||||
classes.add(Class.forName(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Class<?>> getClassesForPackage(Package packageObject)
|
||||
throws ClassNotFoundException {
|
||||
return getClassesForPackage(packageObject.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to list all the classes in the specified package as determined
|
||||
* by the context class loader
|
||||
*
|
||||
* @param pckgname
|
||||
* the package name to search
|
||||
* @return a list of classes that exist within that package
|
||||
* @throws ClassNotFoundException
|
||||
* if something went wrong
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public static List<Class<?>> getClassesForPackage(String pckgname)
|
||||
throws ClassNotFoundException {
|
||||
final List<Class<?>> classes = new ArrayList<Class<?>>();
|
||||
|
||||
try {
|
||||
final ClassLoader cld = Thread.currentThread()
|
||||
.getContextClassLoader();
|
||||
|
||||
if (cld == null)
|
||||
throw new ClassNotFoundException("Can't get class loader.");
|
||||
|
||||
final Enumeration<URL> resources = cld.getResources(pckgname
|
||||
.replace('.', '/'));
|
||||
URLConnection connection;
|
||||
|
||||
for (URL url = null; resources.hasMoreElements()
|
||||
&& ((url = resources.nextElement()) != null);) {
|
||||
try {
|
||||
connection = url.openConnection();
|
||||
|
||||
if (connection instanceof JarURLConnection) {
|
||||
checkJarFile((JarURLConnection) connection, pckgname,
|
||||
classes);
|
||||
} else if (connection instanceof sun.net.www.protocol.file.FileURLConnection) {
|
||||
try {
|
||||
checkDirectory(
|
||||
new File(URLDecoder.decode(url.getPath(),
|
||||
"UTF-8")), pckgname, classes);
|
||||
} catch (final UnsupportedEncodingException ex) {
|
||||
throw new ClassNotFoundException(
|
||||
pckgname
|
||||
+ " does not appear to be a valid package (Unsupported encoding)",
|
||||
ex);
|
||||
}
|
||||
} else
|
||||
throw new ClassNotFoundException(pckgname + " ("
|
||||
+ url.getPath()
|
||||
+ ") does not appear to be a valid package");
|
||||
} catch (final IOException ioex) {
|
||||
throw new ClassNotFoundException(
|
||||
"IOException was thrown when trying to get all resources for "
|
||||
+ pckgname, ioex);
|
||||
}
|
||||
}
|
||||
} catch (final NullPointerException ex) {
|
||||
throw new ClassNotFoundException(
|
||||
pckgname
|
||||
+ " does not appear to be a valid package (Null pointer exception)",
|
||||
ex);
|
||||
} catch (final IOException ioex) {
|
||||
throw new ClassNotFoundException(
|
||||
"IOException was thrown when trying to get all resources for "
|
||||
+ pckgname, ioex);
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue