Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
*
* * Copyright 2010, Unitils.org
* *
* * Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
package org.unitils.inject;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.unitils.core.Module;
import org.unitils.core.TestListener;
import org.unitils.core.UnitilsException;
import org.unitils.core.util.ObjectToInjectHolder;
import org.unitils.inject.annotation.*;
import org.unitils.inject.util.InjectionUtils;
import org.unitils.inject.util.PropertyAccess;
import org.unitils.inject.util.Restore;
import org.unitils.inject.util.ValueToRestore;
import org.unitils.util.PropertyUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.*;
import static java.lang.reflect.Modifier.isAbstract;
import static org.unitils.util.AnnotationUtils.getFieldsAnnotatedWith;
import static org.unitils.util.ModuleUtils.getAnnotationPropertyDefaults;
import static org.unitils.util.ModuleUtils.getEnumValueReplaceDefault;
import static org.unitils.util.ReflectionUtils.*;
/**
* Module for injecting annotated objects into other objects. The intended usage is to inject mock objects, but it can
* be used for regular objects too.
*
* Both explicit injection and automatic injection by type are supported. An object annotated with {@link InjectInto} is
* explicitly injected into a target object. An object annotated with {@link InjectIntoByType} is automatically injected into a
* target property with the same type as the declared type of the annotated object.
*
* Explicit and automatic injection into static fields is also supported, by means of the {@link InjectIntoStatic} and {@link
* InjectIntoStaticByType} annotations.
*
* The target object can either be specified explicitly, or implicitly by annotating an object with {@link TestedObject}
*
* @author Filip Neven
* @author Tim Ducheyne
*/
public class InjectModule implements Module {
/* The logger instance for this class */
private static Log logger = LogFactory.getLog(InjectModule.class);
/* Property key indicating if the tested objects should automatically be created if they are not created yet */
private static final String PROPKEY_CREATE_TESTEDOBJECTS_IF_NULL_ENABLED = "InjectModule.TestedObject.createIfNull.enabled";
/* Map holding the default configuration of the inject annotations */
private Map, Map> defaultAnnotationPropertyValues;
/* List holding all values to restore after test was performed */
private List valuesToRestoreAfterTest = new ArrayList();
/* Indicates if tested object instance should be created if they are not created yet */
private boolean createTestedObjectsIfNullEnabled;
/**
* Initializes this module using the given configuration.
*
* @param configuration The configuration, not null
*/
public void init(Properties configuration) {
defaultAnnotationPropertyValues = getAnnotationPropertyDefaults(InjectModule.class, configuration, InjectInto.class, InjectIntoStatic.class, InjectIntoByType.class, InjectIntoStaticByType.class);
createTestedObjectsIfNullEnabled = PropertyUtils.getBoolean(PROPKEY_CREATE_TESTEDOBJECTS_IF_NULL_ENABLED, configuration);
}
/**
* No after initialization needed for this module
*/
public void afterInit() {
}
/**
* For all fields annotated with {@link TestedObject} that are still null after the test fixture, an object is
* created of the field's declared type and assigned to the field. If the field's declared type is an interface or
* abstract class, or if the type doesn't have a default constructor, a warning is produced.
*
* @param testObject The test instance, not null
*/
public void createTestedObjectsIfNull(Object testObject) {
Set testedObjectFields = getFieldsAnnotatedWith(testObject.getClass(), TestedObject.class);
for (Field testedObjectField : testedObjectFields) {
if (getFieldValue(testObject, testedObjectField) == null) {
createObjectForField(testObject, testedObjectField);
}
}
}
/**
* Creates an objects of the given fields' declared type and assigns it to this field on the given testObject
*
* @param testObject The test instance, not null
* @param testedObjectField The tested object field, not null
*/
protected void createObjectForField(Object testObject, Field testedObjectField) {
Class> declaredClass = testedObjectField.getType();
if (declaredClass.isInterface()) {
logger.warn("Field " + testedObjectField.getName() + " (annotated with @TestedObject) has type " + testedObjectField.getType().getSimpleName() + " which is an interface type. It is not automatically instantiated.");
} else if (isAbstract(declaredClass.getModifiers())) {
logger.warn("Field " + testedObjectField.getName() + " (annotated with @TestedObject) has type " + testedObjectField.getDeclaringClass().getSimpleName() + " which is an abstract class. It is not automatically instantiated.");
} else {
try {
declaredClass.getDeclaredConstructor();
Object instance = createInstanceOfType(declaredClass, true);
setFieldValue(testObject, testedObjectField, instance);
} catch (NoSuchMethodException e) {
logger.warn("Field " + testedObjectField.getName() + " (annotated with @TestedObject) has type " + testedObjectField.getDeclaringClass().getSimpleName() + " which has no default (parameterless) constructor. It is not automatically instantiated.");
}
}
}
/**
* Performs all supported kinds of injection on the given object's fields
*
* @param test The instance to inject into, not null
*/
public void injectObjects(Object test) {
injectAll(test);
injectAllByType(test);
injectAllStatic(test);
injectAllStaticByType(test);
}
/**
* Injects all fields that are annotated with {@link InjectInto}.
*
* @param test The instance to inject into, not null
*/
public void injectAll(Object test) {
Set fields = getFieldsAnnotatedWith(test.getClass(), InjectInto.class);
for (Field field : fields) {
inject(test, field);
}
}
/**
* Auto-injects all fields that are annotated with {@link InjectIntoByType}
*
* @param test The instance to inject into, not null
*/
public void injectAllByType(Object test) {
Set fields = getFieldsAnnotatedWith(test.getClass(), InjectIntoByType.class);
for (Field field : fields) {
injectByType(test, field);
}
}
/**
* Injects all fields that are annotated with {@link InjectIntoStatic}.
*
* @param test The instance to inject into, not null
*/
public void injectAllStatic(Object test) {
Set fields = getFieldsAnnotatedWith(test.getClass(), InjectIntoStatic.class);
for (Field field : fields) {
injectStatic(test, field);
}
}
/**
* Auto-injects all fields that are annotated with {@link InjectIntoStaticByType}
*
* @param test The instance to inject into, not null
*/
public void injectAllStaticByType(Object test) {
Set fields = getFieldsAnnotatedWith(test.getClass(), InjectIntoStaticByType.class);
for (Field field : fields) {
injectStaticByType(test, field);
}
}
/**
* Restores the values that were stored using {@link #storeValueToRestoreAfterTest(Class, String, Class, org.unitils.inject.util.PropertyAccess, Object, org.unitils.inject.util.Restore)}.
*/
public void restoreStaticInjectedObjects() {
for (ValueToRestore valueToRestore : valuesToRestoreAfterTest) {
restore(valueToRestore);
}
}
/**
* Injects the fieldToInject. The target is either an explicitly specified target field of the test, or into the
* field(s) that is/are annotated with {@link TestedObject}
*
* @param test The instance to inject into, not null
* @param fieldToInject The field from which the value is injected into the target, not null
*/
protected void inject(Object test, Field fieldToInject) {
InjectInto injectIntoAnnotation = fieldToInject.getAnnotation(InjectInto.class);
String ognlExpression = injectIntoAnnotation.property();
if (StringUtils.isEmpty(ognlExpression)) {
throw new UnitilsException(getSituatedErrorMessage(InjectInto.class, fieldToInject, "Property cannot be empty"));
}
Object objectToInject = getObjectToInject(test, fieldToInject);
List