001: /*
002: * Copyright 2005-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005: * in compliance with the License. You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software distributed under the License
010: * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011: * or implied. See the License for the specific language governing permissions and limitations under
012: * the License.
013: */
014:
015: package org.strecks.injection.internal;
016:
017: import java.beans.PropertyDescriptor;
018: import java.lang.annotation.Annotation;
019: import java.lang.reflect.Method;
020: import java.util.HashMap;
021: import java.util.Map;
022:
023: import org.strecks.controller.Injectable;
024: import org.strecks.controller.internal.ActionBeanAnnotationReader;
025: import org.strecks.exceptions.ApplicationConfigurationException;
026: import org.strecks.injection.factory.InjectionFactoryClass;
027: import org.strecks.injection.factory.InjectionHandlerFactory;
028: import org.strecks.injection.handler.InjectionHandler;
029: import org.strecks.util.BeanUtils;
030: import org.strecks.util.ReflectHelper;
031:
032: /**
033: * Collects information about the inputs in a stateful action object. Builds an
034: * <code>InjectionWrapper</code> for each property setter method which has an annotation which is
035: * itself annotated using the <code>InjectionFactoryClass</code> annotation
036: * @author Phil Zoio
037: */
038: public class InjectionAnnotationReader implements
039: ActionBeanAnnotationReader<Injectable> {
040:
041: private Map<String, InjectionWrapper> injectionMap;
042:
043: public void populateController(Injectable controller) {
044: controller.setInjectionHandlers(injectionMap);
045: }
046:
047: /**
048: * Inspects bean for annotations which themselves are annotated using the
049: * <code>InjectionFactoryClass</code> annotation. The factory class is instantiated, and used
050: * to create an <code>InjectionHandler</code> instance which is itself wrapped using an
051: * <code>InjectionWrapper</code>. Does this for each property, building a map of property
052: * names to <code>InjectionWrapper</code> instances
053: */
054: public boolean readAnnotations(Class actionClass) {
055:
056: for (Method m : actionClass.getMethods()) {
057:
058: Annotation[] annotations = m.getAnnotations();
059: boolean hasFactory = false;
060: InjectionWrapper wrapper = null;
061:
062: for (Annotation annotation : annotations) {
063:
064: Class<? extends Annotation> annotationType = annotation
065: .annotationType();
066: InjectionFactoryClass factoryClass = annotationType
067: .getAnnotation(InjectionFactoryClass.class);
068:
069: if (factoryClass != null) {
070:
071: hasFactory = true;
072: InjectionHandlerFactory factory = ReflectHelper
073: .createInstance(factoryClass.value(),
074: InjectionHandlerFactory.class);
075:
076: if (wrapper == null) {
077: InjectionSetter inputSetter = createSetter(
078: actionClass, m);
079: PropertyDescriptor propertyDescriptor = BeanUtils
080: .findPropertyForMethod(m);
081:
082: if (propertyDescriptor == null) {
083: throw new ApplicationConfigurationException(
084: "Method "
085: + m.getName()
086: + " has no valid property descriptor. Is this a valid property");
087: }
088:
089: wrapper = new InjectionWrapper(inputSetter,
090: propertyDescriptor);
091: }
092: InjectionHandler handler = factory
093: .createInjectionHandler(annotation,
094: actionClass, wrapper
095: .getPropertyDescriptor());
096: wrapper.addHandler(handler);
097:
098: }
099:
100: }
101:
102: if (hasFactory) {
103:
104: if (injectionMap == null)
105: injectionMap = new HashMap<String, InjectionWrapper>();
106:
107: injectionMap.put(wrapper.getInjectionSetter()
108: .getPropertyName(), wrapper);
109:
110: }
111:
112: }
113:
114: return injectionMap != null;
115: }
116:
117: public InjectionSetter createSetter(Class clazz, Method m) {
118:
119: Class<?>[] parameterTypes = m.getParameterTypes();
120: String methodName = ReflectHelper.checkSetterMethodName(m);
121: String propertyName = ReflectHelper.getPropertyName(methodName);
122:
123: Class type = parameterTypes[0];
124:
125: InjectionSetter setter = new InjectionSetter(clazz, methodName,
126: propertyName, type);
127:
128: return setter;
129:
130: }
131:
132: public Map<String, InjectionWrapper> getInjectionMap() {
133: return injectionMap;
134: }
135:
136: }
|