001: /*
002: * $Id: SpringBeanLocator.java 462072 2006-09-03 18:03:16Z ivaynberg $
003: * $Revision: 462072 $
004: * $Date: 2006-09-03 20:03:16 +0200 (Sun, 03 Sep 2006) $
005: *
006: * ==============================================================================
007: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
008: * use this file except in compliance with the License. You may obtain a copy of
009: * the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
015: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
016: * License for the specific language governing permissions and limitations under
017: * the License.
018: */
019: package wicket.spring;
020:
021: import java.util.Map;
022:
023: import org.springframework.beans.factory.BeanFactoryUtils;
024: import org.springframework.beans.factory.NoSuchBeanDefinitionException;
025: import org.springframework.context.ApplicationContext;
026:
027: import wicket.proxy.IProxyTargetLocator;
028: import wicket.util.lang.Objects;
029:
030: /**
031: * Implementation of {@link IProxyTargetLocator} that can locate beans within a
032: * spring application context. Beans are looked up by the combination of name
033: * and type, if name is omitted only type is used.
034: *
035: * @author Igor Vaynberg (ivaynberg)
036: *
037: */
038: public class SpringBeanLocator implements IProxyTargetLocator {
039: private transient Class beanTypeCache;
040:
041: private String beanTypeName;
042:
043: private String beanName;
044:
045: private ISpringContextLocator springContextLocator;
046:
047: /**
048: * Constructor
049: *
050: * @param beanType
051: * bean class
052: * @param locator
053: * spring context locator
054: */
055: public SpringBeanLocator(Class beanType,
056: ISpringContextLocator locator) {
057: this (null, beanType, locator);
058: }
059:
060: /**
061: * Constructor
062: *
063: * @param beanName
064: * bean name
065: * @param beanType
066: * bean class
067: * @param locator
068: * spring context locator
069: */
070: public SpringBeanLocator(String beanName, Class beanType,
071: ISpringContextLocator locator) {
072: if (locator == null) {
073: throw new IllegalArgumentException(
074: "[locator] argument cannot be null");
075: }
076: if (beanType == null) {
077: throw new IllegalArgumentException(
078: "[beanType] argument cannot be null");
079: }
080:
081: this .beanTypeCache = beanType;
082: this .beanTypeName = beanType.getName();
083: this .beanName = beanName;
084: this .springContextLocator = locator;
085: }
086:
087: /**
088: * @return bean class this locator is configured with
089: */
090: public Class getBeanType() {
091: if (beanTypeCache == null) {
092: try {
093: beanTypeCache = Class.forName(beanTypeName, true,
094: Thread.currentThread().getContextClassLoader());
095: } catch (ClassNotFoundException e) {
096: throw new RuntimeException(
097: "SpringBeanLocator could not find class ["
098: + beanTypeName
099: + "] needed to locate the ["
100: + ((beanName != null) ? (beanName)
101: : ("bean name not specified"))
102: + "] bean", e);
103: }
104: }
105: return beanTypeCache;
106: }
107:
108: /**
109: * @see wicket.proxy.IProxyTargetLocator#locateProxyTarget()
110: */
111: public Object locateProxyTarget() {
112: final ApplicationContext context = springContextLocator
113: .getSpringContext();
114:
115: if (context == null) {
116: throw new IllegalStateException(
117: "spring application context locator returned null");
118: }
119:
120: if (beanName != null && beanName.length() > 0) {
121: return lookupSpringBean(context, beanName, getBeanType());
122: } else {
123: return lookupSpringBean(context, getBeanType());
124: }
125: }
126:
127: /**
128: * @return bean name this locator is configured with
129: */
130: public final String getBeanName() {
131: return beanName;
132: }
133:
134: /**
135: * @return context locator this locator is configured with
136: */
137: public final ISpringContextLocator getSpringContextLocator() {
138: return springContextLocator;
139: }
140:
141: /**
142: * Looks up a bean by its class. Throws IllegalState exception if none or
143: * more then one beans are found.
144: *
145: * @param ctx
146: * spring application context
147: *
148: * @param clazz
149: * bean class
150: * @throws IllegalStateException
151: * @return found bean
152: */
153: private final Object lookupSpringBean(ApplicationContext ctx,
154: Class clazz) {
155: Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx,
156: clazz);
157: if (beans.size() == 0) {
158: throw new IllegalStateException("bean of type ["
159: + clazz.getName() + "] not found");
160: }
161: if (beans.size() > 1) {
162: throw new IllegalStateException(
163: "more then one bean of type ["
164: + clazz.getName()
165: + "] found, you have to specify the name of the bean (@SpringBean(name=\"foo\")) in order to resolve this conflict");
166: }
167: return beans.values().iterator().next();
168: }
169:
170: /**
171: * Looks up a bean by its name and class. Throws IllegalState exception if
172: * bean not found.
173: *
174: * @param ctx
175: * spring application context
176: *
177: * @param name
178: * bean name
179: * @param clazz
180: * bean class
181: * @throws IllegalStateException
182: * @return found bean
183: */
184: private static Object lookupSpringBean(ApplicationContext ctx,
185: String name, Class clazz) {
186: try {
187: return ctx.getBean(name, clazz);
188: } catch (NoSuchBeanDefinitionException e) {
189: throw new IllegalStateException("bean with name [" + name
190: + "] and class [" + clazz.getName() + "] not found");
191: }
192: }
193:
194: /**
195: * @see java.lang.Object#equals(java.lang.Object)
196: */
197: public boolean equals(Object obj) {
198: if (obj instanceof SpringBeanLocator) {
199: SpringBeanLocator other = (SpringBeanLocator) obj;
200: return beanTypeName.equals(other.beanTypeName)
201: && Objects.equal(beanName, other.beanName);
202: }
203: return false;
204: }
205:
206: /**
207: * @see java.lang.Object#hashCode()
208: */
209: public int hashCode() {
210: int hashcode = beanTypeName.hashCode();
211: if (beanName != null) {
212: hashcode = hashcode + (127 * beanName.hashCode());
213: }
214: return hashcode;
215: }
216: }
|