
org.unidal.lookup.container.lifecycle.ComponentHandlers Maven / Gradle / Ivy
The newest version!
package org.unidal.lookup.container.lifecycle;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.unidal.converter.ConverterManager;
import org.unidal.helper.Reflects;
import org.unidal.helper.Reflects.IMemberFilter;
import org.unidal.lookup.ComponentLookupException;
import org.unidal.lookup.annotation.Inject;
import org.unidal.lookup.container.model.entity.Any;
import org.unidal.lookup.container.model.entity.ComponentModel;
import org.unidal.lookup.container.model.entity.ConfigurationModel;
import org.unidal.lookup.container.model.entity.RequirementModel;
import org.unidal.lookup.extension.Contextualizable;
import org.unidal.lookup.extension.Disposable;
import org.unidal.lookup.extension.Initializable;
import org.unidal.lookup.extension.RoleHintEnabled;
import org.unidal.lookup.logging.LogEnabled;
import org.unidal.tuple.Pair;
public enum ComponentHandlers implements LifecycleHandler {
REQUIREMENTS {
@Override
public void handleStart(LifecycleContext ctx) throws ComponentLookupException {
ComponentModel model = ctx.getComponentModel();
List requirements = model.getRequirements();
RequirementInjector injector = new RequirementInjector();
for (RequirementModel requirement : requirements) {
injector.inject(ctx, requirement);
}
}
},
CONFIGURATION {
@Override
public void handleStart(LifecycleContext ctx) throws ComponentLookupException {
ComponentModel model = ctx.getComponentModel();
ConfigurationModel configuration = model.getConfiguration();
if (configuration != null) {
List elements = configuration.getDynamicElements();
PropertyInjector injector = new PropertyInjector();
for (Any element : elements) {
String name = element.getName();
String value = element.getValue();
if (name != null && value != null) {
injector.injectProperty(ctx, name, value.trim());
}
}
}
}
},
CONTEXTUALIZABLE {
@Override
public void handleStart(final LifecycleContext ctx) throws ComponentLookupException {
Object component = ctx.getComponent();
if (component instanceof Contextualizable) {
try {
((Contextualizable) component).contextualize(ctx.getContainer().getContext());
} catch (Throwable e) {
ComponentModel model = ctx.getComponentModel();
throw new ComponentLookupException("Error when setting context of component!", model.getRole(),
model.getHint(), e);
}
}
}
},
INITIALIZABLE {
@Override
public void handleStart(final LifecycleContext ctx) throws ComponentLookupException {
Object component = ctx.getComponent();
if (component instanceof Initializable) {
try {
((Initializable) component).initialize();
} catch (Throwable e) {
ComponentModel model = ctx.getComponentModel();
throw new ComponentLookupException("Error when initializing component!", model.getRole(),
model.getHint(), e);
}
}
}
},
DISPOSABLE {
@Override
public void handleStop(final LifecycleContext ctx) {
Object component = ctx.getComponent();
if (component instanceof Disposable) {
try {
((Disposable) component).dispose();
} catch (Throwable e) {
// ignore it
e.printStackTrace();
}
}
}
},
ENABLE_LOG {
@Override
public void handleStart(LifecycleContext ctx) {
Object component = ctx.getComponent();
if (component instanceof LogEnabled) {
String role = ctx.getComponentModel().getRole();
((LogEnabled) component).enableLogging(ctx.getLogger(role));
}
}
},
ENABLE_ROLE_HINT {
@Override
public void handleStart(LifecycleContext ctx) {
Object component = ctx.getComponent();
if (component instanceof RoleHintEnabled) {
ComponentModel model = ctx.getComponentModel();
((RoleHintEnabled) component).enableRoleHint(model.getHint());
}
}
};
@Override
public void handleStart(LifecycleContext ctx) throws ComponentLookupException {
}
@Override
public void handleStop(LifecycleContext ctx) {
}
private static class PropertyInjector {
public void injectProperty(LifecycleContext ctx, String property, String value) throws ComponentLookupException {
ComponentModel model = ctx.getComponentModel();
Object component = ctx.getComponent();
Method method = Reflects.forMethod().getSetterMethod(component, property);
if (method == null) {
String setter = Reflects.forMethod().getSetMethodName(property);
String message = String.format("No setter method(%s) of class(%s) is found!", setter,
model.getImplementation());
throw new ComponentLookupException(message, model.getRole(), model.getHint());
} else {
Class> type = method.getParameterTypes()[0];
try {
Object val = ConverterManager.getInstance().convert(value, type);
method.invoke(component, val);
} catch (Throwable e) {
String setter = Reflects.forMethod().getSetMethodName(property);
String message = String.format("No setter method(%s) of class(%s) is found!", setter,
model.getImplementation());
throw new ComponentLookupException(message, model.getRole(), model.getHint(), e);
}
}
}
}
private static class RequirementInjector {
private Field findMatchedField(LifecycleContext ctx, RequirementModel requirement,
Pair> hints) throws ComponentLookupException {
String role = requirement.getRole();
if (hints.getValue().isEmpty()) { // single
final Class> type = Reflects.forClass().getClass(role);
Object component = ctx.getComponent();
List fields = Reflects.forField().getDeclaredFields(component, new IMemberFilter() {
@Override
public boolean filter(Field field) {
if (field.isAnnotationPresent(Inject.class)) { // with @Inject
return type.isAssignableFrom(field.getType());
} else { // old code without @Inject
return type == field.getType();
}
}
});
if (fields.size() == 1) {
return fields.get(0);
} else if (fields.size() == 0) {
ComponentModel model = ctx.getComponentModel();
String message = String.format("No field of class(%s) matches the type(%s)!", model.getImplementation(),
role);
throw new ComponentLookupException(message, model.getRole(), model.getHint());
} else {
StringBuilder sb = new StringBuilder(32);
for (Field field : fields) {
if (sb.length() > 0) {
sb.append(",");
}
sb.append(field.getName());
}
ComponentModel model = ctx.getComponentModel();
String message = String.format("Multiple fields(%s) of class(%s) matches the type(%s)!", sb.toString(),
model.getImplementation(), requirement.getRole());
throw new ComponentLookupException(message, model.getRole(), model.getHint());
}
} else { // multiple without fieldName
ComponentModel model = ctx.getComponentModel();
String message = String.format(
"For multiple role hints, fieldName must be specified in class(%s) to match the type(%s)!",
model.getImplementation(), role);
throw new ComponentLookupException(message, model.getRole(), model.getHint());
}
}
private Pair> getHints(RequirementModel requirement) {
String roleHint = requirement.getRoleHint();
List roleHints = new ArrayList();
for (Any element : requirement.getDynamicElements()) {
if ("role-hints".equals(element.getName())) {
for (Any any : element.getChildren()) {
roleHints.add(any.getValue());
}
}
}
return new Pair>(roleHint, roleHints);
}
public void inject(LifecycleContext ctx, RequirementModel requirement) throws ComponentLookupException {
String fieldName = requirement.getFieldName();
Pair> hints = getHints(requirement);
Field field;
if (fieldName != null && fieldName.length() > 0) {
Object component = ctx.getComponent();
field = Reflects.forField().getDeclaredField(component, fieldName);
} else {
field = findMatchedField(ctx, requirement, hints);
}
if (field != null) {
injectField(ctx, requirement, field, hints);
} else {
String role = requirement.getRole();
ComponentModel model = ctx.getComponentModel();
String implementation = model.getImplementation();
String message = String.format("No field of class(%s) matches the type(%s)!", implementation, role);
throw new ComponentLookupException(message, model.getRole(), model.getHint());
}
}
private void injectField(LifecycleContext ctx, RequirementModel requirement, Field field,
Pair> hints) throws ComponentLookupException {
String role = requirement.getRole();
Object component = ctx.getComponent();
Class> type = field.getType();
String roleHint = hints.getKey();
List roleHints = hints.getValue();
Object value;
if (type == List.class || type == Collection.class) { // List or Collection
if (roleHints.isEmpty()) {
value = new ArrayList
© 2015 - 2025 Weber Informatics LLC | Privacy Policy