org.zeromq.jms.util.ClassUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jeromq-jms Show documentation
Show all versions of jeromq-jms Show documentation
ZeroMQ implementation of the JMS API
package org.zeromq.jms.util;
/*
* Copyright (c) 2015 Jeremy Miller
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.zeromq.jms.annotation.ZmqUriParameter;
/**
* Helper class to assist in finding classes with a specified annotation.
*/
public class ClassUtils {
private static final Logger LOGGER = Logger.getLogger(ClassUtils.class.getCanonicalName());
/**
* Stop construction of utility class.
*/
private ClassUtils() {
};
/**
* Return the class from a list of classes that contain the specified annotation attribute and value. Duplicates
* will cause an IllegalstateException. If non can be found the class short name will be check a possible name.
* @param possibleClasses the list of possible class
* @param annotation the annotation class
* @param name the annotation method name to check when annotation exists
* @param value the query value too match against annotation method value or class name
* @return return the found class, or null when not found
* @throws IllegalAccessException can throw illegal access exception
* @throws IllegalArgumentException can throw illegal argument exception
* @throws InvocationTargetException can throw invocation target exception
*/
public static Class> getClass(final List> possibleClasses, final Class extends Annotation> annotation, final String name,
final String value) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class> clazz = null;
for (Class> possibleClass : possibleClasses) {
if (possibleClass.isAnnotationPresent(annotation)) {
final Annotation annotationClass = possibleClass.getAnnotation(annotation);
final Class extends Annotation> type = annotationClass.annotationType();
for (Method method : type.getDeclaredMethods()) {
if (method.getName().equals(name) && method.getParameterTypes().length == 0) {
Object attributeValue = method.invoke(annotationClass);
if (attributeValue != null && attributeValue.equals(value)) {
if (clazz != null) {
throw new IllegalStateException("Conflict with value (" + name + "=" + value + " ) between classes: "
+ clazz.getCanonicalName() + ", " + possibleClass.getCanonicalName());
}
clazz = possibleClass;
}
}
}
}
if (possibleClass.getSimpleName().equals(value)) {
if (clazz != null) {
throw new IllegalStateException("Conflict with value (" + name + "=" + value + " ) between classes: " + clazz.getCanonicalName()
+ ", " + possibleClass.getCanonicalName());
}
clazz = possibleClass;
}
}
// One last try, may been value is a class?
if (clazz == null && value.contains(".")) {
// CHECKSTYLE:OFF: Empty Block
try {
clazz = Class.forName(value);
} catch (ClassNotFoundException ex) {
}
// CHECKSTYLE:ON: Empty Block
}
return clazz;
}
/**
* Return the setter method using the specified annotation attribute and value. Duplicates
* will cause an IllegalstateException. If non can be found the method name will be check as
* possible match.
* @param clazz the class to investigate
* @param annotation the annotation class
* @param name the annotation method name to check when annotation exists
* @param value the query value too match against annotation method value or class name
* @return return the found method, or null when not found
* @throws IllegalAccessException can throw illegal access exception
* @throws IllegalArgumentException can throw illegal argument exception
* @throws InvocationTargetException can throw invocation target exception
*/
public static Method getSetterMethod(final Class> clazz, final Class extends Annotation> annotation, final String name, final String value)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method setterMethod = null;
for (Method possibleMethod : clazz.getMethods()) {
if (possibleMethod.isAnnotationPresent(annotation)) {
Annotation[] methodAnnotations = possibleMethod.getDeclaredAnnotations();
for (Annotation methodAnnotation : methodAnnotations) {
if (annotation.isInstance(methodAnnotation)) {
final Class extends Annotation> type = methodAnnotation.annotationType();
for (Method annotationMethod : type.getDeclaredMethods()) {
if (annotationMethod.getName().equals(name) && annotationMethod.getParameterTypes().length == 0) {
Object attributeValue = annotationMethod.invoke(methodAnnotation);
if (attributeValue != null && attributeValue.equals(value)) {
if (setterMethod != null) {
throw new IllegalStateException("Conflict with value (" + name + "=" + value + " ) between methods: "
+ setterMethod.getName() + ", " + possibleMethod.getName());
}
setterMethod = possibleMethod;
}
}
}
}
}
}
// check name is not the same
if (possibleMethod.getParameterTypes().length == 1) {
final String methodName = possibleMethod.getName();
if (methodName.equalsIgnoreCase(value) || methodName.equalsIgnoreCase("set" + value)) {
if (setterMethod != null) {
throw new IllegalStateException("Conflict with value (" + name + "=" + value + " ) between methods: "
+ setterMethod.getName() + ", " + possibleMethod.getName());
}
setterMethod = possibleMethod;
}
}
}
return setterMethod;
}
/**
* Return all method(s) of a specified class that contain the specified annotation.
* @param clazz the class to interrogate
* @param annotation the annotation to find
* @return return the list of methods found (an empty list is possible)
*/
public static List getMethods(final Class> clazz, final Class extends Annotation> annotation) {
final List annotatedMethods = new LinkedList();
for (Method method : clazz.getMethods()) {
if (method.isAnnotationPresent(annotation)) {
annotatedMethods.add(method);
}
}
return annotatedMethods;
}
/**
* Return all classes below the package root that have the specified annotation.
* @param packageName the starting package to search.
* @param annotation the annotation to find
* @return return a list of classes found (an empty list is possible)
* @throws ClassNotFoundException throws class not found
* @throws IOException throws I/O exception in searching package structures
*/
public static List> getClasses(final String packageName, final Class extends Annotation> annotation) throws ClassNotFoundException,
IOException {
final List> classes = getClasses(packageName);
final List> annotatedClasses = new LinkedList>();
for (Class> clazz : classes) {
if (clazz.isAnnotationPresent(annotation)) {
annotatedClasses.add(clazz);
}
}
return annotatedClasses;
}
/**
* Check weather a package within the class path and that it can be read.
* @param packageName the name of the package
* @return return true of existing, otherwise false
*/
public static boolean packageExists(final String packageName) {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
final String path = packageName.replace('.', '/');
try {
Enumeration resources = classLoader.getResources(path);
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
if (resource == null) {
LOGGER.warning("Unable to retrieve resources from the package: " + packageName);
return false;
}
}
} catch (IOException ex) {
LOGGER.warning("Unable to locate package: " + packageName);
return false;
}
return true;
}
/**
* Scans all classes accessible from the context class loader which belong to the given package and sub-packages.
* @param basePackageName the base package
* @return return the classes foundThe classes
* @throws ClassNotFoundException throws class not found exception
* @throws IOException throws I/O exception
*/
public static List> getClasses(final String basePackageName) throws ClassNotFoundException, IOException {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
final String path = basePackageName.replace('.', '/');
final Enumeration resources = classLoader.getResources(path);
final Set dirs = new HashSet();
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
dirs.add(new File(resource.getFile()));
}
final List> classes = new LinkedList>();
for (File directory : dirs) {
classes.addAll(findClasses(directory, basePackageName));
}
return classes;
}
/**
* Recursive method used to find all classes in a given directory and sub-directories.
* @param directory the base directory
* @param packageName the package name for classes found inside the base directory
* @return return the found classes
* @throws ClassNotFoundException throws class not found exception
*/
private static List> findClasses(final File directory, final String packageName) throws ClassNotFoundException {
final List> classes = new LinkedList>();
if (!directory.exists()) {
return classes;
}
final File[] files = directory.listFiles();
for (File file : files) {
if (file.isDirectory()) {
classes.addAll(findClasses(file, packageName + "." + file.getName()));
} else if (file.getName().endsWith(".class")) {
try {
classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
} catch (UnsupportedClassVersionError ex) {
LOGGER.log(Level.WARNING, "Unable to loader class " + file.getName() + " due to JVM version conflict: " + ex.getMessage());
}
}
}
return classes;
}
/**
* Set the values of any matching parameters to class setter values, that have URI parameter.
* @param parameters the map of name/values pairs
* @param config the instantiated class
* @throws ReflectiveOperationException throws reflective operation exception
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void setMethods(final Map> parameters, final Object config) throws ReflectiveOperationException {
final List methods = getMethods(config.getClass(), ZmqUriParameter.class);
for (Method method : methods) {
final ZmqUriParameter attribute = (ZmqUriParameter) method.getAnnotation(ZmqUriParameter.class);
final String paramName = attribute.value();
final List paramValues = parameters.get(paramName);
final String paramValue = (paramValues == null || paramValues.size() == 0) ? null : paramValues.get(0);
// Found a valid value to set
if (paramValue != null) {
Object value = null;
final Class>[] paramTypes = method.getParameterTypes();
// check for at setter value only
if (paramTypes != null && paramTypes.length == 1) {
final Class> paramType = paramTypes[0];
if (paramType == int.class || paramType.isAssignableFrom(Integer.class)) {
value = Integer.parseInt(paramValue);
} else if (paramType == long.class || paramType.isAssignableFrom(Long.class)) {
value = Long.parseLong(paramValue);
} else if (paramType == short.class || paramType.isAssignableFrom(Short.class)) {
value = Short.decode(paramValue);
} else if (paramType == double.class || paramType.isAssignableFrom(Double.class)) {
value = Double.parseDouble(paramValue);
} else if (paramType == float.class || paramType.isAssignableFrom(Float.class)) {
value = Float.parseFloat(paramValue);
} else if (paramType == boolean.class || paramType.isAssignableFrom(Boolean.class)) {
value = Boolean.parseBoolean(paramValue);
} else if (paramType.isAssignableFrom(byte[].class)) {
value = paramValue.getBytes();
} else if (paramType.isAssignableFrom(String.class)) {
value = paramValue;
} else if (paramType.isEnum()) {
value = Enum.valueOf((Class) paramType, paramValue);
} else if (paramType.isArray()) {
String[] values = new String[paramValues.size()];
paramValues.toArray(values);
value = values;
} else {
throw new UnsupportedOperationException("Unable to map parameter [" + paramName + "] with value ["
+ paramValue + "] to required type: " + paramType);
}
}
if (value != null) {
try {
LOGGER.info("Setting configuration parameter " + paramName + "=" + paramValue + " on: " + config);
method.invoke(config, value);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
LOGGER.log(Level.SEVERE, "Unable to invoke setter method: " + method.getName() + "(" + value + ")", ex);
throw ex;
}
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy