001: //========================================================================
002: //$Id: Injection.java 1448 2006-12-29 20:46:57Z janb $
003: //Copyright 2006 Mort Bay Consulting Pty. Ltd.
004: //------------------------------------------------------------------------
005: //Licensed under the Apache License, Version 2.0 (the "License");
006: //you may not use this file except in compliance with the License.
007: //You may obtain a copy of the License at
008: //http://www.apache.org/licenses/LICENSE-2.0
009: //Unless required by applicable law or agreed to in writing, software
010: //distributed under the License is distributed on an "AS IS" BASIS,
011: //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: //See the License for the specific language governing permissions and
013: //limitations under the License.
014: //========================================================================
015:
016: package org.mortbay.jetty.plus.annotation;
017:
018: import java.lang.reflect.Field;
019: import java.lang.reflect.Member;
020: import java.lang.reflect.Method;
021:
022: import javax.naming.InitialContext;
023:
024: import org.mortbay.log.Log;
025: import org.mortbay.util.IntrospectionUtil;
026:
027: /**
028: * Injection
029: *
030: * Represents the injection of a resource into a target (method or field).
031: * The injection is performed by doing an ENC lookup using the jndi
032: * name provided, and setting the object obtained on the target.
033: *
034: */
035: public class Injection {
036: private String _className;
037: private String _jndiName;
038: private String _mappingName;
039: private Member _target;
040:
041: public Injection() {
042: }
043:
044: /**
045: * @return the _className
046: */
047: public String getClassName() {
048: return _className;
049: }
050:
051: /**
052: * @param name the _className to set
053: */
054: public void setClassName(String name) {
055: _className = name;
056: }
057:
058: /**
059: * @return the jndiName
060: */
061: public String getJndiName() {
062: return _jndiName;
063: }
064:
065: /**
066: * @param jndiName the jndiName to set
067: */
068: public void setJndiName(String jndiName) {
069: this ._jndiName = jndiName;
070: }
071:
072: /**
073: * @return the mappingName
074: */
075: public String getMappingName() {
076: return _mappingName;
077: }
078:
079: /**
080: * @param mappingName the mappingName to set
081: */
082: public void setMappingName(String mappingName) {
083: this ._mappingName = mappingName;
084: }
085:
086: /**
087: * @return the target
088: */
089: public Member getTarget() {
090: return _target;
091: }
092:
093: /**
094: * @param target the target to set
095: */
096: public void setTarget(Member target) {
097: this ._target = target;
098: }
099:
100: public void setTarget(Class clazz, String targetName,
101: Class targetType) {
102: //first look for a javabeans style setter matching the targetName
103: String setter = "set"
104: + targetName.substring(0, 1).toUpperCase()
105: + targetName.substring(1);
106: try {
107: Log.debug("Looking for method for setter: " + setter
108: + " with arg " + targetType);
109: _target = IntrospectionUtil.findMethod(clazz, setter,
110: new Class[] { targetType }, true, false);
111: _className = clazz.getName();
112: } catch (NoSuchMethodException me) {
113: //try as a field
114: try {
115: _target = IntrospectionUtil.findField(clazz,
116: targetName, targetType, true, false);
117: _className = clazz.getName();
118: } catch (NoSuchFieldException fe) {
119: throw new IllegalArgumentException(
120: "No such field or method " + targetName
121: + " on class " + _className);
122: }
123: }
124: }
125:
126: /**
127: * Inject a value for a Resource from JNDI into an object
128: * @param injectable
129: * @throws Exception
130: */
131: public void inject(Object injectable) throws Exception {
132: Member theTarget = getTarget();
133: if (theTarget instanceof Field) {
134: injectField((Field) theTarget, injectable);
135: } else if (theTarget instanceof Method) {
136: injectMethod((Method) theTarget, injectable);
137: }
138: }
139:
140: /**
141: * The Resource must already exist in the ENC of this webapp.
142: * @return
143: * @throws Exception
144: */
145: public Object lookupInjectedValue() throws Exception {
146: InitialContext context = new InitialContext();
147: return context.lookup("java:comp/env/" + getJndiName());
148: }
149:
150: /**
151: * Inject value from jndi into a field of an instance
152: * @param field
153: * @param injectable
154: * @throws Exception
155: */
156: public void injectField(Field field, Object injectable)
157: throws Exception {
158: //validateInjection(field, injectable);
159: boolean accessibility = field.isAccessible();
160: field.setAccessible(true);
161: field.set(injectable, lookupInjectedValue());
162: field.setAccessible(accessibility);
163: }
164:
165: /**
166: * Inject value from jndi into a setter method of an instance
167: * @param method
168: * @param injectable
169: * @throws Exception
170: */
171: public void injectMethod(Method method, Object injectable)
172: throws Exception {
173: //validateInjection(method, injectable);
174: boolean accessibility = method.isAccessible();
175: method.setAccessible(true);
176: method.invoke(injectable,
177: new Object[] { lookupInjectedValue() });
178: method.setAccessible(accessibility);
179: }
180:
181: private void validateInjection(Method method, Object injectable)
182: throws NoSuchMethodException {
183: if ((injectable == null) || (method == null))
184: return;
185: //check the injection target actually has a matching method
186: //TODO: think about this, they have to be assignable
187: injectable.getClass().getMethod(method.getName(),
188: method.getParameterTypes());
189: }
190:
191: private void validateInjection(Field field, Object injectable)
192: throws NoSuchFieldException {
193: if ((field == null) || (injectable == null))
194: return;
195:
196: Field f = injectable.getClass().getField(field.getName());
197: if (!f.getType().isAssignableFrom(field.getType()))
198: throw new NoSuchFieldException(
199: "Mismatching type of field: "
200: + f.getType().getName() + " v "
201: + field.getType().getName());
202: }
203: }
|