001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/metaobj/tags/sakai_2-4-1/metaobj-api/api/src/java/org/sakaiproject/metaobj/utils/ioc/FieldRetrievingFactoryBean.java $
003: * $Id: FieldRetrievingFactoryBean.java 9469 2006-05-15 14:52:05Z chmaurer@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.metaobj.utils.ioc;
021:
022: import java.lang.reflect.Field;
023:
024: import org.springframework.beans.factory.BeanNameAware;
025: import org.springframework.beans.factory.FactoryBean;
026: import org.springframework.beans.factory.InitializingBean;
027: import org.springframework.util.ClassUtils;
028:
029: /**
030: * FactoryBean which retrieves a static or non-static field value.
031: * Typically used for retrieving public static final constants.
032: * <p/>
033: * <p>Usage example:
034: * <p/>
035: * <pre>
036: * // standard definition for exposing a static field, specifying the "staticField" property
037: * <bean id="myField" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
038: * <property name="staticField"><value>java.sql.Connection.TRANSACTION_SERIALIZABLE</value></property>
039: * </bean>
040: * <p/>
041: * // convenience version that specifies a static field pattern as bean name
042: * <bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/></pre>
043: * </pre>
044: *
045: * @author Juergen Hoeller
046: * @see #setStaticField
047: * @since 1.1
048: */
049: public class FieldRetrievingFactoryBean implements FactoryBean,
050: BeanNameAware, InitializingBean {
051:
052: private Class targetClass;
053:
054: private Object targetObject;
055:
056: private String targetField;
057:
058: private String staticField;
059:
060: private String beanName;
061:
062: // the field we will retrieve
063: private Field fieldObject;
064:
065: /**
066: * Set the target class on which the field is defined.
067: * Only necessary when the target field is static; else,
068: * a target object needs to be specified anyway.
069: *
070: * @see #setTargetObject
071: * @see #setTargetField
072: */
073: public void setTargetClass(Class targetClass) {
074: this .targetClass = targetClass;
075: }
076:
077: /**
078: * Return the target class on which the field is defined.
079: */
080: public Class getTargetClass() {
081: return targetClass;
082: }
083:
084: /**
085: * Set the target object on which the field is defined.
086: * Only necessary when the target field is not static;
087: * else, a target class is sufficient.
088: *
089: * @see #setTargetClass
090: * @see #setTargetField
091: */
092: public void setTargetObject(Object targetObject) {
093: this .targetObject = targetObject;
094: }
095:
096: /**
097: * Return the target object on which the field is defined.
098: */
099: public Object getTargetObject() {
100: return targetObject;
101: }
102:
103: /**
104: * Set the name of the field to be retrieved.
105: * Refers to either a static field or a non-static field,
106: * depending on a target object being set.
107: *
108: * @see #setTargetClass
109: * @see #setTargetObject
110: */
111: public void setTargetField(String targetField) {
112: this .targetField = targetField;
113: }
114:
115: /**
116: * Return the name of the field to be retrieved.
117: */
118: public String getTargetField() {
119: return targetField;
120: }
121:
122: /**
123: * Set a fully qualified static field name to retrieve,
124: * e.g. "example.MyExampleClass.MY_EXAMPLE_FIELD".
125: * Convenient alternative to specifying targetClass and targetField.
126: *
127: * @see #setTargetClass
128: * @see #setTargetField
129: */
130: public void setStaticField(String staticField) {
131: this .staticField = staticField;
132: }
133:
134: /**
135: * The bean name of this FieldRetrievingFactoryBean will be interpreted
136: * as "staticField" pattern, if neither "targetClass" nor "targetObject"
137: * nor "targetField" have been specified.
138: * This allows for concise bean definitions with just an id/name.
139: */
140: public void setBeanName(String beanName) {
141: this .beanName = beanName;
142: }
143:
144: public void afterPropertiesSet() throws ClassNotFoundException,
145: NoSuchFieldException {
146: if (this .targetClass != null && this .targetObject != null) {
147: throw new IllegalArgumentException(
148: "Specify either targetClass or targetObject, not both");
149: }
150:
151: if (this .targetClass == null && this .targetObject == null) {
152: if (this .targetField != null) {
153: throw new IllegalArgumentException(
154: "Specify targetClass or targetObject in combination with targetField");
155: }
156:
157: // If no other property specified, consider bean name as static field expression.
158: if (this .staticField == null) {
159: this .staticField = this .beanName;
160: }
161:
162: // try to parse static field into class and field
163: int lastDotIndex = this .staticField.lastIndexOf('.');
164: if (lastDotIndex == -1
165: || lastDotIndex == this .staticField.length()) {
166: throw new IllegalArgumentException(
167: "staticField must be a fully qualified class plus method name: "
168: + "e.g. 'example.MyExampleClass.MY_EXAMPLE_FIELD'");
169: }
170: String className = this .staticField.substring(0,
171: lastDotIndex);
172: String fieldName = this .staticField
173: .substring(lastDotIndex + 1);
174: this .targetClass = ClassUtils.forName(className);
175: this .targetField = fieldName;
176: }
177:
178: else if (this .targetField == null) {
179: // either targetClass or targetObject specified
180: throw new IllegalArgumentException(
181: "targetField is required");
182: }
183:
184: // try to get the exact method first
185: Class targetClass = (this .targetObject != null) ? this .targetObject
186: .getClass()
187: : this .targetClass;
188: this .fieldObject = targetClass.getField(this .targetField);
189: }
190:
191: public Object getObject() throws IllegalAccessException {
192: if (this .targetObject != null) {
193: // instance field
194: return this .fieldObject.get(this .targetObject);
195: } else {
196: // class field
197: return this .fieldObject.get(null);
198: }
199: }
200:
201: public Class getObjectType() {
202: return this .fieldObject.getType();
203: }
204:
205: public boolean isSingleton() {
206: return true;
207: }
208:
209: }
|