001: /*
002: * Copyright 2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.ws.transport.support;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.util.ArrayList;
022: import java.util.Collections;
023: import java.util.List;
024: import java.util.Properties;
025: import javax.servlet.ServletContext;
026:
027: import org.springframework.beans.BeanUtils;
028: import org.springframework.beans.BeansException;
029: import org.springframework.beans.factory.BeanCreationException;
030: import org.springframework.beans.factory.BeanFactory;
031: import org.springframework.beans.factory.BeanFactoryAware;
032: import org.springframework.beans.factory.BeanInitializationException;
033: import org.springframework.beans.factory.BeanNameAware;
034: import org.springframework.beans.factory.InitializingBean;
035: import org.springframework.context.ApplicationContext;
036: import org.springframework.context.ApplicationContextAware;
037: import org.springframework.context.ApplicationEventPublisherAware;
038: import org.springframework.context.MessageSourceAware;
039: import org.springframework.context.ResourceLoaderAware;
040: import org.springframework.core.OrderComparator;
041: import org.springframework.core.io.Resource;
042: import org.springframework.util.Assert;
043: import org.springframework.util.ClassUtils;
044: import org.springframework.util.StringUtils;
045: import org.springframework.web.context.ServletContextAware;
046: import org.springframework.web.context.WebApplicationContext;
047:
048: /**
049: * Helper class for for loading default implementations of an interface. Encapsulates a properties object, which
050: * contains strategy interface names as keys, and comma-separated class names as values.
051: * <p/>
052: * Simulates the {@link BeanFactory normal lifecycle} for beans, by calling {@link
053: * BeanFactoryAware#setBeanFactory(BeanFactory)}, {@link ApplicationContextAware#setApplicationContext(ApplicationContext)},
054: * etc.
055: *
056: * @author Arjen Poutsma
057: * @since 1.0.0
058: */
059: public class DefaultStrategiesHelper {
060:
061: /** Keys are strategy interface names, values are implementation class names. */
062: private Properties defaultStrategies;
063:
064: /** Initializes a new instance of the <code>DefaultStrategiesHelper</code> based on the given set of properties. */
065: public DefaultStrategiesHelper(Properties defaultStrategies) {
066: Assert.notNull(defaultStrategies,
067: "defaultStrategies must not be null");
068: this .defaultStrategies = defaultStrategies;
069: }
070:
071: /** Initializes a new instance of the <code>DefaultStrategiesHelper</code> based on the given resource. */
072: public DefaultStrategiesHelper(Resource resource)
073: throws IllegalStateException {
074: try {
075: InputStream is = resource.getInputStream();
076: defaultStrategies = new Properties();
077: try {
078: defaultStrategies.load(is);
079: } finally {
080: is.close();
081: }
082: } catch (IOException ex) {
083: throw new IllegalStateException("Could not load '"
084: + resource + "': " + ex.getMessage());
085: }
086: }
087:
088: /**
089: * Create a list of strategy objects for the given strategy interface. Strategies are retrieved from the
090: * <code>Properties</code> object given at construction-time.
091: *
092: * @param strategyInterface the strategy interface
093: * @return a list of corresponding strategy objects
094: * @throws BeansException if initialization failed
095: */
096: public List getDefaultStrategies(Class strategyInterface)
097: throws BeanInitializationException {
098: return getDefaultStrategies(strategyInterface, null);
099: }
100:
101: /**
102: * Create a list of strategy objects for the given strategy interface. Strategies are retrieved from the
103: * <code>Properties</code> object given at construction-time. It instantiates the strategy objects and satisifies
104: * <code>ApplicationContextAware</code> with the supplied context if necessary.
105: *
106: * @param strategyInterface the strategy interface
107: * @param applicationContext used to satisfy strategies that are application context aware, may be
108: * <code>null</code>
109: * @return a list of corresponding strategy objects
110: * @throws BeansException if initialization failed
111: */
112: public List getDefaultStrategies(Class strategyInterface,
113: ApplicationContext applicationContext)
114: throws BeanInitializationException {
115: String key = strategyInterface.getName();
116: try {
117: List result = null;
118: String value = defaultStrategies.getProperty(key);
119: if (value != null) {
120: String[] classNames = StringUtils
121: .commaDelimitedListToStringArray(value);
122: result = new ArrayList(classNames.length);
123: for (int i = 0; i < classNames.length; i++) {
124: Class clazz = ClassUtils.forName(classNames[i]);
125: Object strategy = instantiateBean(clazz,
126: applicationContext);
127: result.add(strategy);
128: }
129: } else {
130: result = Collections.EMPTY_LIST;
131: }
132: Collections.sort(result, new OrderComparator());
133: return result;
134: } catch (ClassNotFoundException ex) {
135: throw new BeanInitializationException(
136: "Could not find default strategy class for interface ["
137: + key + "]", ex);
138: }
139: }
140:
141: /** Instantiates the given bean, simulating the standard bean lifecycle. */
142: private Object instantiateBean(Class clazz,
143: ApplicationContext applicationContext) {
144: Object strategy = BeanUtils.instantiateClass(clazz);
145: if (strategy instanceof BeanNameAware) {
146: BeanNameAware beanNameAware = (BeanNameAware) strategy;
147: beanNameAware.setBeanName(clazz.getName());
148: }
149: if (applicationContext != null) {
150: if (strategy instanceof BeanFactoryAware) {
151: ((BeanFactoryAware) strategy)
152: .setBeanFactory(applicationContext);
153: }
154: if (strategy instanceof ResourceLoaderAware) {
155: ((ResourceLoaderAware) strategy)
156: .setResourceLoader(applicationContext);
157: }
158: if (strategy instanceof ApplicationEventPublisherAware) {
159: ((ApplicationEventPublisherAware) strategy)
160: .setApplicationEventPublisher(applicationContext);
161: }
162: if (strategy instanceof MessageSourceAware) {
163: ((MessageSourceAware) strategy)
164: .setMessageSource(applicationContext);
165: }
166: if (strategy instanceof ApplicationContextAware) {
167: ApplicationContextAware applicationContextAware = (ApplicationContextAware) strategy;
168: applicationContextAware
169: .setApplicationContext(applicationContext);
170: }
171: if (applicationContext instanceof WebApplicationContext
172: && strategy instanceof ServletContextAware) {
173: ServletContext servletContext = ((WebApplicationContext) applicationContext)
174: .getServletContext();
175: ((ServletContextAware) strategy)
176: .setServletContext(servletContext);
177: }
178: }
179: if (strategy instanceof InitializingBean) {
180: InitializingBean initializingBean = (InitializingBean) strategy;
181: try {
182: initializingBean.afterPropertiesSet();
183: } catch (Throwable ex) {
184: throw new BeanCreationException(
185: "Invocation of init method failed", ex);
186: }
187: }
188: return strategy;
189: }
190:
191: /**
192: * Return the default strategy object for the given strategy interface.
193: *
194: * @param strategyInterface the strategy interface
195: * @return the corresponding strategy object
196: * @throws BeansException if initialization failed
197: * @see #getDefaultStrategies
198: */
199: public Object getDefaultStrategy(Class strategyInterface)
200: throws BeanInitializationException {
201: return getDefaultStrategy(strategyInterface, null);
202: }
203:
204: /**
205: * Return the default strategy object for the given strategy interface.
206: * <p/>
207: * Delegates to {@link #getDefaultStrategies(Class,ApplicationContext)}, expecting a single object in the list.
208: *
209: * @param strategyInterface the strategy interface
210: * @param applicationContext used to satisfy strategies that are application context aware, may be
211: * <code>null</code>
212: * @return the corresponding strategy object
213: * @throws BeansException if initialization failed
214: */
215: public Object getDefaultStrategy(Class strategyInterface,
216: ApplicationContext applicationContext)
217: throws BeanInitializationException {
218: List result = getDefaultStrategies(strategyInterface,
219: applicationContext);
220: if (result.size() != 1) {
221: throw new BeanInitializationException(
222: "Could not find exactly 1 strategy for interface ["
223: + strategyInterface.getName() + "]");
224: }
225: return result.get(0);
226: }
227:
228: }
|