View Javadoc

1   /*
2    * Copyright 2002-2009 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.support;
18  
19  import java.io.IOException;
20  import java.util.ArrayList;
21  import java.util.Collections;
22  import java.util.List;
23  import java.util.Properties;
24  import javax.servlet.ServletContext;
25  
26  import org.springframework.beans.BeanUtils;
27  import org.springframework.beans.BeansException;
28  import org.springframework.beans.factory.BeanClassLoaderAware;
29  import org.springframework.beans.factory.BeanCreationException;
30  import org.springframework.beans.factory.BeanFactory;
31  import org.springframework.beans.factory.BeanFactoryAware;
32  import org.springframework.beans.factory.BeanInitializationException;
33  import org.springframework.beans.factory.BeanNameAware;
34  import org.springframework.beans.factory.InitializingBean;
35  import org.springframework.context.ApplicationContext;
36  import org.springframework.context.ApplicationContextAware;
37  import org.springframework.context.ApplicationEventPublisherAware;
38  import org.springframework.context.MessageSourceAware;
39  import org.springframework.context.ResourceLoaderAware;
40  import org.springframework.core.OrderComparator;
41  import org.springframework.core.io.Resource;
42  import org.springframework.core.io.support.PropertiesLoaderUtils;
43  import org.springframework.util.Assert;
44  import org.springframework.util.ClassUtils;
45  import org.springframework.util.StringUtils;
46  import org.springframework.web.context.ServletContextAware;
47  import org.springframework.web.context.WebApplicationContext;
48  
49  /**
50   * Helper class for for loading default implementations of an interface. Encapsulates a properties object, which
51   * contains strategy interface names as keys, and comma-separated class names as values.
52   * <p/>
53   * Simulates the {@link BeanFactory normal lifecycle} for beans, by calling {@link
54   * BeanFactoryAware#setBeanFactory(BeanFactory)}, {@link ApplicationContextAware#setApplicationContext(ApplicationContext)},
55   * etc.
56   *
57   * @author Arjen Poutsma
58   * @since 1.0.0
59   */
60  public class DefaultStrategiesHelper {
61  
62      /** Keys are strategy interface names, values are implementation class names. */
63      private Properties defaultStrategies;
64  
65      /** Initializes a new instance of the <code>DefaultStrategiesHelper</code> based on the given set of properties. */
66      public DefaultStrategiesHelper(Properties defaultStrategies) {
67          Assert.notNull(defaultStrategies, "defaultStrategies must not be null");
68          this.defaultStrategies = defaultStrategies;
69      }
70  
71      /** Initializes a new instance of the <code>DefaultStrategiesHelper</code> based on the given resource. */
72      public DefaultStrategiesHelper(Resource resource) throws IllegalStateException {
73          try {
74              defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
75          }
76          catch (IOException ex) {
77              throw new IllegalStateException("Could not load '" + resource + "': " + ex.getMessage());
78          }
79      }
80  
81      /**
82       * Create a list of strategy objects for the given strategy interface. Strategies are retrieved from the
83       * <code>Properties</code> object given at construction-time.
84       *
85       * @param strategyInterface the strategy interface
86       * @return a list of corresponding strategy objects
87       * @throws BeansException if initialization failed
88       */
89      public List getDefaultStrategies(Class strategyInterface) throws BeanInitializationException {
90          return getDefaultStrategies(strategyInterface, null);
91      }
92  
93      /**
94       * Create a list of strategy objects for the given strategy interface. Strategies are retrieved from the
95       * <code>Properties</code> object given at construction-time. It instantiates the strategy objects and satisfies
96       * <code>ApplicationContextAware</code> with the supplied context if necessary.
97       *
98       * @param strategyInterface  the strategy interface
99       * @param applicationContext used to satisfy strategies that are application context aware, may be
100      *                           <code>null</code>
101      * @return a list of corresponding strategy objects
102      * @throws BeansException if initialization failed
103      */
104     public List getDefaultStrategies(Class strategyInterface, ApplicationContext applicationContext)
105             throws BeanInitializationException {
106         String key = strategyInterface.getName();
107         try {
108             List result;
109             String value = defaultStrategies.getProperty(key);
110             if (value != null) {
111                 String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
112                 result = new ArrayList(classNames.length);
113                 for (int i = 0; i < classNames.length; i++) {
114                     Class clazz = ClassUtils.forName(classNames[i]);
115                     Object strategy = instantiateBean(clazz, applicationContext);
116                     result.add(strategy);
117                 }
118             }
119             else {
120                 result = Collections.EMPTY_LIST;
121             }
122             Collections.sort(result, new OrderComparator());
123             return result;
124         }
125         catch (ClassNotFoundException ex) {
126             throw new BeanInitializationException("Could not find default strategy class for interface [" + key + "]",
127                     ex);
128         }
129     }
130 
131     /** Instantiates the given bean, simulating the standard bean lifecycle. */
132     private Object instantiateBean(Class clazz, ApplicationContext applicationContext) {
133         Object strategy = BeanUtils.instantiateClass(clazz);
134         if (strategy instanceof BeanNameAware) {
135             BeanNameAware beanNameAware = (BeanNameAware) strategy;
136             beanNameAware.setBeanName(clazz.getName());
137         }
138         if (applicationContext != null) {
139             if (strategy instanceof BeanClassLoaderAware) {
140                 ((BeanClassLoaderAware) strategy).setBeanClassLoader(applicationContext.getClassLoader());
141             }
142             if (strategy instanceof BeanFactoryAware) {
143                 ((BeanFactoryAware) strategy).setBeanFactory(applicationContext);
144             }
145             if (strategy instanceof ResourceLoaderAware) {
146                 ((ResourceLoaderAware) strategy).setResourceLoader(applicationContext);
147             }
148             if (strategy instanceof ApplicationEventPublisherAware) {
149                 ((ApplicationEventPublisherAware) strategy).setApplicationEventPublisher(applicationContext);
150             }
151             if (strategy instanceof MessageSourceAware) {
152                 ((MessageSourceAware) strategy).setMessageSource(applicationContext);
153             }
154             if (strategy instanceof ApplicationContextAware) {
155                 ApplicationContextAware applicationContextAware = (ApplicationContextAware) strategy;
156                 applicationContextAware.setApplicationContext(applicationContext);
157             }
158             if (applicationContext instanceof WebApplicationContext && strategy instanceof ServletContextAware) {
159                 ServletContext servletContext = ((WebApplicationContext) applicationContext).getServletContext();
160                 ((ServletContextAware) strategy).setServletContext(servletContext);
161             }
162         }
163         if (strategy instanceof InitializingBean) {
164             InitializingBean initializingBean = (InitializingBean) strategy;
165             try {
166                 initializingBean.afterPropertiesSet();
167             }
168             catch (Throwable ex) {
169                 throw new BeanCreationException("Invocation of init method failed", ex);
170             }
171         }
172         return strategy;
173     }
174 
175     /**
176      * Return the default strategy object for the given strategy interface.
177      *
178      * @param strategyInterface the strategy interface
179      * @return the corresponding strategy object
180      * @throws BeansException if initialization failed
181      * @see #getDefaultStrategies
182      */
183     public Object getDefaultStrategy(Class strategyInterface) throws BeanInitializationException {
184         return getDefaultStrategy(strategyInterface, null);
185     }
186 
187     /**
188      * Return the default strategy object for the given strategy interface.
189      * <p/>
190      * Delegates to {@link #getDefaultStrategies(Class,ApplicationContext)}, expecting a single object in the list.
191      *
192      * @param strategyInterface  the strategy interface
193      * @param applicationContext used to satisfy strategies that are application context aware, may be
194      *                           <code>null</code>
195      * @return the corresponding strategy object
196      * @throws BeansException if initialization failed
197      */
198     public Object getDefaultStrategy(Class strategyInterface, ApplicationContext applicationContext)
199             throws BeanInitializationException {
200         List result = getDefaultStrategies(strategyInterface, applicationContext);
201         if (result.size() != 1) {
202             throw new BeanInitializationException(
203                     "Could not find exactly 1 strategy for interface [" + strategyInterface.getName() + "]");
204         }
205         return result.get(0);
206     }
207 
208 }