View Javadoc

1   /*
2    * $Id: SpringRegistry.java 22409 2011-07-14 05:14:27Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.config.spring;
12  
13  import org.mule.api.MuleContext;
14  import org.mule.api.MuleRuntimeException;
15  import org.mule.api.lifecycle.InitialisationException;
16  import org.mule.api.registry.RegistrationException;
17  import org.mule.config.i18n.MessageFactory;
18  import org.mule.lifecycle.RegistryLifecycleManager;
19  import org.mule.registry.AbstractRegistry;
20  import org.mule.util.StringUtils;
21  
22  import java.util.Collection;
23  import java.util.Collections;
24  import java.util.Map;
25  import java.util.concurrent.atomic.AtomicBoolean;
26  
27  import org.springframework.beans.FatalBeanException;
28  import org.springframework.beans.factory.NoSuchBeanDefinitionException;
29  import org.springframework.context.ApplicationContext;
30  import org.springframework.context.ConfigurableApplicationContext;
31  
32  public class SpringRegistry extends AbstractRegistry
33  {
34      public static final String REGISTRY_ID = "org.mule.Registry.Spring";
35  
36      /**
37       * Key used to lookup Spring Application Context from SpringRegistry via Mule's
38       * Registry interface.
39       */
40      public static final String SPRING_APPLICATION_CONTEXT = "springApplicationContext";
41  
42      protected ApplicationContext applicationContext;
43  
44      //This is used to track the Spring context lifecycle since there is no way to confirm the
45      //lifecycle phase from the application context
46      protected AtomicBoolean springContextInitialised = new AtomicBoolean(false);
47  
48      public SpringRegistry(MuleContext muleContext)
49      {
50          super(REGISTRY_ID, muleContext);
51      }
52  
53      public SpringRegistry(String id, MuleContext muleContext)
54      {
55          super(id, muleContext);
56      }
57  
58      public SpringRegistry(ApplicationContext applicationContext, MuleContext muleContext)
59      {
60          super(REGISTRY_ID, muleContext);
61          this.applicationContext = applicationContext;
62      }
63  
64      public SpringRegistry(String id, ApplicationContext applicationContext, MuleContext muleContext)
65      {
66          super(id, muleContext);
67          this.applicationContext = applicationContext;
68      }
69  
70      public SpringRegistry(ConfigurableApplicationContext applicationContext, ApplicationContext parentContext, MuleContext muleContext)
71      {
72          super(REGISTRY_ID, muleContext);
73          applicationContext.setParent(parentContext);
74          this.applicationContext = applicationContext;
75      }
76  
77      public SpringRegistry(String id, ConfigurableApplicationContext applicationContext, ApplicationContext parentContext, MuleContext muleContext)
78      {
79          super(id, muleContext);
80          applicationContext.setParent(parentContext);
81          this.applicationContext = applicationContext;
82      }
83  
84      @Override
85      protected void doInitialise() throws InitialisationException
86      {
87          if (applicationContext instanceof ConfigurableApplicationContext)
88          {
89              ((ConfigurableApplicationContext) applicationContext).refresh();
90          }
91          //This is used to track the Spring context lifecycle since there is no way to confirm the lifecycle phase from the application context
92          springContextInitialised.set(true);
93      }
94  
95      @Override
96      public void doDispose()
97      {
98          // check we aren't trying to close a context which has never been started,
99          // spring's appContext.isActive() isn't working for this case
100         if (!this.springContextInitialised.get())
101         {
102             return;
103         }
104 
105         if (applicationContext instanceof ConfigurableApplicationContext
106                 && ((ConfigurableApplicationContext) applicationContext).isActive())
107         {
108             ((ConfigurableApplicationContext) applicationContext).close();
109         }
110 
111         // release the circular implicit ref to MuleContext
112         applicationContext = null;
113 
114         this.springContextInitialised.set(false);
115     }
116 
117     @Override
118     protected RegistryLifecycleManager createLifecycleManager()
119     {
120         return new SpringRegistryLifecycleManager(getRegistryId(), this, muleContext);
121     }
122 
123     @SuppressWarnings("unchecked")
124     @Override
125     public Object lookupObject(String key)
126     {
127         if (StringUtils.isBlank(key))
128         {
129             logger.warn(
130                     MessageFactory.createStaticMessage("Detected a lookup attempt with an empty or null key"),
131                     new Throwable().fillInStackTrace());
132             return null;
133         }
134 
135         if (key.equals(SPRING_APPLICATION_CONTEXT) && applicationContext != null)
136         {
137             return applicationContext;
138         }
139         else
140         {
141             try
142             {
143                 return applicationContext.getBean(key);
144             }
145             catch (NoSuchBeanDefinitionException e)
146             {
147                 logger.debug(e);
148                 return null;
149             }
150         }
151     }
152 
153     @Override
154     public <T> Collection<T> lookupObjects(Class<T> type)
155     {
156         return lookupByType(type).values();
157     }
158 
159     /**
160      * For lifecycle we only want spring to return singleton objects from it's application context
161      */
162     @Override
163     public <T> Collection<T> lookupObjectsForLifecycle(Class<T> type)
164     {
165         return internalLookupByType(type, false, false).values();
166     }
167 
168     @Override
169     public <T> Map<String, T> lookupByType(Class<T> type)
170     {
171         return internalLookupByType(type, true, true);
172     }
173 
174     protected <T> Map<String, T> internalLookupByType(Class<T> type, boolean nonSingletons, boolean eagerInit)
175     {
176         try
177         {
178             return applicationContext.getBeansOfType(type, nonSingletons, eagerInit);
179         }
180         catch (FatalBeanException fbex)
181         {
182             // FBE is a result of a broken config, propagate it (see MULE-3297 for more details)
183             String message = String.format("Failed to lookup beans of type %s from the Spring registry", type);
184             throw new MuleRuntimeException(MessageFactory.createStaticMessage(message), fbex);
185         }
186         catch (Exception e)
187         {
188             logger.debug(e);
189             return Collections.emptyMap();
190         }
191     }
192 
193 
194     ////////////////////////////////////////////////////////////////////////////////////
195     // Registry is read-only
196     ////////////////////////////////////////////////////////////////////////////////////
197 
198     @Override
199     public void registerObject(String key, Object value) throws RegistrationException
200     {
201         throw new UnsupportedOperationException("Registry is read-only so objects cannot be registered or unregistered.");
202     }
203 
204     @Override
205     public void registerObject(String key, Object value, Object metadata) throws RegistrationException
206     {
207         throw new UnsupportedOperationException("Registry is read-only so objects cannot be registered or unregistered.");
208     }
209 
210     @Override
211     public void registerObjects(Map<String, Object> objects) throws RegistrationException
212     {
213         throw new UnsupportedOperationException("Registry is read-only so objects cannot be registered or unregistered.");
214     }
215 
216     @Override
217     public void unregisterObject(String key)
218     {
219         throw new UnsupportedOperationException("Registry is read-only so objects cannot be registered or unregistered.");
220     }
221 
222     @Override
223     public void unregisterObject(String key, Object metadata) throws RegistrationException
224     {
225         throw new UnsupportedOperationException("Registry is read-only so objects cannot be registered or unregistered.");
226     }
227 
228     ////////////////////////////////////////////////////////////////////////////////////
229     // Registry meta-data
230     ////////////////////////////////////////////////////////////////////////////////////
231 
232     @Override
233     public boolean isReadOnly()
234     {
235         return true;
236     }
237 
238     @Override
239     public boolean isRemote()
240     {
241         return false;
242     }
243 
244 }