Skip to content

Commit

Permalink
Fix #21 Remove class field from exception types
Browse files Browse the repository at this point in the history
  • Loading branch information
ljacqu committed Jul 16, 2016
1 parent 02bb68c commit 982bc39
Show file tree
Hide file tree
Showing 22 changed files with 109 additions and 158 deletions.
6 changes: 3 additions & 3 deletions src/main/java/ch/jalu/injector/InjectorBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public InjectorBuilder() {
* @since 0.1
*/
public static List<Handler> createDefaultHandlers(String rootPackage) {
InjectorUtils.checkNotNull(rootPackage, "root package may not be null", String.class);
InjectorUtils.checkNotNull(rootPackage, "root package may not be null");
return new ArrayList<>(Arrays.asList(
// PreConstruct
new PreConstructPackageValidator(rootPackage),
Expand Down Expand Up @@ -158,8 +158,8 @@ public void process(Handler handler) {
foundSubtype |= addHandler(subtype, handler);
}
if (!foundSubtype) {
throw new InjectorException(
"Unknown Handler type. Handlers must implement a known subtype", handler.getClass());
throw new InjectorException(String.format("Class '%s' must extend a known Handler subtype",
handler.getClass().getName()));
}
}

Expand Down
15 changes: 7 additions & 8 deletions src/main/java/ch/jalu/injector/InjectorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ public <T> T getSingleton(Class<T> clazz) {
@Override
public <T> void register(Class<? super T> clazz, T object) {
if (objects.containsKey(clazz)) {
throw new InjectorException("There is already an object present for " + clazz, clazz);
throw new InjectorException("There is already an object present for " + clazz);
}
InjectorUtils.checkNotNull(object, clazz);
InjectorUtils.checkNotNull(object);
objects.put(clazz, object);
}

@Override
public void provide(Class<? extends Annotation> clazz, Object object) {
checkNotNull(clazz, "Provided annotation may not be null", Annotation.class);
checkNotNull(clazz, "Provided annotation may not be null");
for (AnnotationValueHandler annotationValueHandler : config.getAnnotationValueHandlers()) {
try {
annotationValueHandler.processProvided(clazz, object);
Expand Down Expand Up @@ -116,7 +116,7 @@ private <T> T get(Class<T> clazz, Set<Class<?>> traversedClasses) {
}

if (!InjectorUtils.canInstantiate(mappedClass)) {
throw new InjectorException("Class " + clazz.getSimpleName() + " cannot be instantiated", clazz);
throw new InjectorException("Class " + clazz.getSimpleName() + " cannot be instantiated");
}

// Add the clazz to the list of traversed classes in a new Set, so each path we take has its own Set.
Expand Down Expand Up @@ -162,13 +162,12 @@ private <T> Instantiation<T> getInstantiation(Class<T> clazz) {
}

if (config.getInstantiationProviders().isEmpty()) {
throw new InjectorException("You did not register any instantiation methods!",
InstantiationProvider.class);
throw new InjectorException("You did not register any instantiation methods!");
}
throw new InjectorException("Did not find instantiation method for '" + clazz + "'. Make sure your class "
+ "conforms to one of the registered instantiations. If default: make sure you have "
+ "a constructor with @Inject or fields with @Inject. Fields with @Inject require "
+ "the default constructor", clazz);
+ "the default constructor");
}

/**
Expand Down Expand Up @@ -235,7 +234,7 @@ private static void validateInjectionHasNoCircularDependencies(List<? extends De
Class<?> clazz = dependency.getType();
if (traversedClasses.contains(clazz)) {
throw new InjectorException("Found cyclic dependency - already traversed '" + clazz
+ "' (full traversal list: " + traversedClasses + ")", clazz);
+ "' (full traversal list: " + traversedClasses + ")");
}
}
}
Expand Down
16 changes: 2 additions & 14 deletions src/main/java/ch/jalu/injector/exceptions/InjectorException.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,12 @@
*/
public class InjectorException extends RuntimeException {

private final Class<?> clazz;

public InjectorException(String message, Class<?> clazz) {
public InjectorException(String message) {
super(message);
this.clazz = clazz;
}

public InjectorException(String message, Throwable cause, Class<?> clazz) {
public InjectorException(String message, Throwable cause) {
super(message, cause);
this.clazz = clazz;
}

/**
* Returns the class an operation was being run for that caused the exception.
*
* @return the class
*/
public Class<?> getClazz() {
return clazz;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package ch.jalu.injector.exceptions;

import java.lang.reflect.Member;

/**
* Exception while trying to perform a reflection operation.
*/
public class InjectorReflectionException extends InjectorException {

public InjectorReflectionException(String message, ReflectiveOperationException cause, Member member) {
super(message, cause, member.getDeclaringClass());
public InjectorReflectionException(String message, ReflectiveOperationException cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ public Class<AllInstances> getAnnotationType() {

@Override
public Object resolveValueSafely(Injector injector, AllInstances annotation,
DependencyDescription dependencyDescription) {
DependencyDescription dependencyDescription) {
// The raw type, e.g. List or array
final Class<?> rawType = dependencyDescription.getType();
// The type of the collection, e.g. String for List<String> or String[]
final Class<?> genericType = ReflectionUtils.getGenericClass(rawType, dependencyDescription.getGenericType());

if (genericType == null) {
throw new InjectorException("Unsupported dependency of type '" + rawType
+ "' annotated with @AllInstances. (Or did you forget the generic type?)", rawType);
+ "' annotated with @AllInstances. (Or did you forget the generic type?)");
}

// TODO: Implement detection of cyclic dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public Class<AllTypes> getAnnotationType() {
@Override
public Object resolveValueSafely(Injector injector, AllTypes annotation,
DependencyDescription dependencyDescription) {
InjectorUtils.checkNotNull(annotation.value(), "Annotation value may not be null", AllTypes.class);
InjectorUtils.checkNotNull(annotation.value(), "Annotation value may not be null");
Set<?> subTypes = reflections.getSubTypesOf(annotation.value());

Class<?> rawType = dependencyDescription.getType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ public Object resolveValue(Injector injector, DependencyDescription dependencyDe

@Override
public void processProvided(Class<? extends Annotation> annotation, Object object) {
InjectorUtils.checkNotNull(annotation, "Annotation may not be null", null);
InjectorUtils.checkNotNull(object, "Object may not be null", annotation);
InjectorUtils.checkNotNull(object, "Object may not be null");
if (storedValues.containsKey(annotation)) {
throw new InjectorException("Value already registered for @" + annotation.getSimpleName(), annotation);
throw new InjectorException("Value already registered for @" + annotation.getSimpleName());
}
storedValues.put(annotation, object);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public List<DependencyDescription> getDependencies() {

@Override
public T instantiateWith(Object... values) {
InjectorUtils.checkNotNull(values, constructor.getDeclaringClass());
InjectorUtils.checkNoNullValues(values);
return ReflectionUtils.newInstance(constructor, values);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ private static <T> Constructor<T> getInjectionConstructor(Class<T> clazz) {
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
if (constructor.isAnnotationPresent(Inject.class)) {
constructor.setAccessible(true);
return (Constructor<T>) constructor;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.util.Collection;
import java.util.List;

import static ch.jalu.injector.utils.InjectorUtils.getDeclarer;

/**
* Functionality for field injection.
*/
Expand All @@ -34,12 +36,12 @@ public List<DependencyDescription> getDependencies() {

@Override
public T instantiateWith(Object... values) {
InjectorUtils.checkArgument(values.length == fields.length,
"The number of values must be equal to the number of fields", defaultConstructor.getDeclaringClass());
InjectorUtils.checkNoNullValues(values);
InjectorUtils.checkArgument(values.length == fields.length, "The number of values must be equal to the "
+ "number of fields (class " + getDeclarer(defaultConstructor) + ")");

T instance = ReflectionUtils.newInstance(defaultConstructor);
for (int i = 0; i < fields.length; ++i) {
InjectorUtils.checkNotNull(values[i], defaultConstructor.getDeclaringClass());
ReflectionUtils.setField(fields[i], instance, values[i]);
}
return instance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ private static List<Field> getInjectionFields(Class<?> clazz) {
if (field.isAnnotationPresent(Inject.class)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new InjectorException(String.format("Field '%s' in class '%s' is static but "
+ "annotated with @Inject", field.getName(), clazz.getSimpleName()), clazz);
+ "annotated with @Inject", field.getName(), clazz.getSimpleName()));
}
field.setAccessible(true);
fields.add(field);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.util.ArrayList;
import java.util.List;

import static ch.jalu.injector.utils.InjectorUtils.getDeclarer;

/**
* Fallback instantiation method for classes with an accessible no-args constructor
* and no elements whatsoever annotated with {@link Inject} or {@link PostConstruct}.
Expand All @@ -29,7 +31,7 @@ public List<DependencyDescription> getDependencies() {
@Override
public T instantiateWith(Object... values) {
InjectorUtils.checkArgument(values == null || values.length == 0,
"Instantiation fallback cannot have parameters", constructor.getDeclaringClass());
"Instantiation fallback cannot have parameters. Values passed for " + getDeclarer(constructor));
return ReflectionUtils.newInstance(constructor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ private static Method getAndValidatePostConstructMethod(Class<?> clazz) {
for (Method method : ReflectionUtils.safeGetDeclaredMethods(clazz)) {
if (method.isAnnotationPresent(PostConstruct.class)) {
if (postConstructMethod != null) {
throw new InjectorException("Multiple methods with @PostConstruct on " + clazz, clazz);
throw new InjectorException("Multiple methods with @PostConstruct on " + clazz);
} else if (method.getParameterTypes().length > 0 || Modifier.isStatic(method.getModifiers())) {
throw new InjectorException("@PostConstruct method may not be static or have any parameters. "
+ "Invalid method in " + clazz, clazz);
+ "Invalid method in " + clazz);
} else if (method.getReturnType() != void.class) {
throw new InjectorException("@PostConstruct method must have return type void. "
+ "Offending class: " + clazz, clazz);
+ "Offending class: " + clazz);
} else {
postConstructMethod = method;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ public PreConstructPackageValidator(String rootPackage) {
@Override
public void process(Class<?> clazz) {
if (clazz.getPackage() == null) {
throw new InjectorException("Primitive types must be provided explicitly (or use an annotation).", clazz);
throw new InjectorException("Cannot instantiate '" + clazz + "'. Primitive types must be provided"
+ " explicitly (or use an annotation).");
}
String packageName = clazz.getPackage().getName();
if (!packageName.startsWith(rootPackage)) {
throw new InjectorException("Class " + clazz + " with package " + packageName + " is outside of the "
+ "allowed packages. It must be provided explicitly or the package must be passed to the constructor.",
clazz);
throw new InjectorException("Class '" + clazz + "' with package '" + packageName + "' is outside of the "
+ "allowed packages. It must be provided explicitly or the package must be passed to the constructor.");
}
}

Expand Down
35 changes: 17 additions & 18 deletions src/main/java/ch/jalu/injector/utils/InjectorUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ch.jalu.injector.exceptions.InjectorException;

import javax.annotation.Nullable;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;

/**
Expand All @@ -13,40 +14,34 @@ public final class InjectorUtils {
private InjectorUtils() {
}

public static void checkNotNull(Object o, Class<?> clazz) {
checkNotNull(o, "Object may not be null", clazz);
public static void checkNotNull(Object o) {
checkNotNull(o, "Object may not be null");
}

public static void checkNotNull(Iterable<?> collection, Class<?> clazz) {
checkNotNull((Object) collection, clazz);
for (Object o : collection) {
checkNotNull(o, clazz);
public static void checkNotNull(Object o, String errorMessage) {
if (o == null) {
throw new InjectorException(errorMessage);
}
}

public static <T> void checkNotNull(T[] arr, Class<?> clazz) {
checkNotNull((Object) arr, clazz);
@SafeVarargs
public static <T> void checkNoNullValues(T... arr) {
checkNotNull(arr);
for (Object o : arr) {
checkNotNull(o, clazz);
}
}

public static void checkNotNull(Object o, String errorMessage, Class<?> clazz) {
if (o == null) {
throw new InjectorException(errorMessage, clazz);
checkNotNull(o);
}
}

public static void checkArgument(boolean expression, String errorMessage, Class<?> clazz) {
public static void checkArgument(boolean expression, String errorMessage) {
if (!expression) {
throw new InjectorException(errorMessage, clazz);
throw new InjectorException(errorMessage);
}
}

public static void rethrowException(Exception e) throws InjectorException {
throw (e instanceof InjectorException)
? (InjectorException) e
: new InjectorException("An error occurred (see cause)", e, null);
: new InjectorException("An error occurred (see cause)", e);
}

@Nullable
Expand All @@ -63,4 +58,8 @@ public static <T> T firstNotNull(T... objects) {
public static boolean canInstantiate(Class<?> clazz) {
return !clazz.isEnum() && !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers());
}

public static String getDeclarer(@Nullable Member member) {
return member == null ? "null" : member.getDeclaringClass().getName();
}
}
11 changes: 6 additions & 5 deletions src/main/java/ch/jalu/injector/utils/ReflectionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static Object getFieldValue(Field field, Object instance) {
return field.get(instance);
} catch (IllegalAccessException e) {
throw new InjectorReflectionException(
"Could not get value of field '" + field.getName() + "' for " + instance, e, field);
"Could not get value of field '" + field.getName() + "' for " + instance, e);
}
}

Expand All @@ -55,7 +55,7 @@ public static void setField(Field field, Object instance, Object value) {
field.set(instance, value);
} catch (IllegalAccessException e) {
throw new InjectorReflectionException(
"Could not set field '" + field.getName() + "' for " + instance, e, field);
"Could not set field '" + field.getName() + "' for " + instance, e);
}
}

Expand All @@ -73,7 +73,7 @@ public static Object invokeMethod(Method method, Object instance, Object... para
return method.invoke(instance, parameters);
} catch (InvocationTargetException | IllegalAccessException e) {
throw new InjectorReflectionException(
"Could not invoke method '" + method.getName() + "' for " + instance, e, method);
"Could not invoke method '" + method.getName() + "' for " + instance, e);
}
}

Expand All @@ -86,11 +86,12 @@ public static Object invokeMethod(Method method, Object instance, Object... para
* @return the instantiated object
*/
public static <T> T newInstance(Constructor<T> constructor, Object... parameters) {
constructor.setAccessible(true);
try {
return constructor.newInstance(parameters);
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new InjectorReflectionException("Could not invoke constructor of class '"
+ constructor.getDeclaringClass() + "'", e, constructor);
+ constructor.getDeclaringClass() + "'", e);
}
}

Expand Down Expand Up @@ -125,7 +126,7 @@ public static <T> Object toSuitableCollectionType(Class<?> rawType, Set<T> resul
return new ArrayList<>(result);
}
throw new InjectorException("Cannot convert @AllTypes result to '" + rawType + "'. "
+ "Supported: Set, List, or any subtype thereof, and array", rawType);
+ "Supported: Set, List, or any subtype thereof, and array");
}

/**
Expand Down
Loading

0 comments on commit 982bc39

Please sign in to comment.