View Javadoc

1   /*
2    * $Id: TransientRegistry.java 12269 2008-07-10 04:19:03Z dfeist $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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  package org.mule.registry;
11  
12  import org.mule.MuleServer;
13  import org.mule.RegistryContext;
14  import org.mule.api.MuleContext;
15  import org.mule.api.MuleException;
16  import org.mule.api.agent.Agent;
17  import org.mule.api.endpoint.EndpointBuilder;
18  import org.mule.api.endpoint.ImmutableEndpoint;
19  import org.mule.api.lifecycle.InitialisationException;
20  import org.mule.api.lifecycle.LifecycleManager;
21  import org.mule.api.lifecycle.LifecyclePhase;
22  import org.mule.api.lifecycle.Stoppable;
23  import org.mule.api.model.Model;
24  import org.mule.api.registry.AbstractServiceDescriptor;
25  import org.mule.api.registry.ObjectProcessor;
26  import org.mule.api.registry.RegistrationException;
27  import org.mule.api.registry.Registry;
28  import org.mule.api.registry.ServiceDescriptor;
29  import org.mule.api.registry.ServiceDescriptorFactory;
30  import org.mule.api.registry.ServiceException;
31  import org.mule.api.service.Service;
32  import org.mule.api.transformer.DiscoverableTransformer;
33  import org.mule.api.transformer.Transformer;
34  import org.mule.api.transport.Connector;
35  import org.mule.config.i18n.CoreMessages;
36  import org.mule.lifecycle.GenericLifecycleManager;
37  import org.mule.lifecycle.phases.TransientRegistryDisposePhase;
38  import org.mule.lifecycle.phases.TransientRegistryInitialisePhase;
39  import org.mule.util.BeanUtils;
40  import org.mule.util.ClassUtils;
41  import org.mule.util.SpiUtils;
42  
43  import java.util.Collection;
44  import java.util.HashMap;
45  import java.util.Iterator;
46  import java.util.Map;
47  import java.util.Properties;
48  
49  import org.apache.commons.logging.Log;
50  import org.apache.commons.logging.LogFactory;
51  
52  public class TransientRegistry extends AbstractRegistry
53  {
54      /** logger used by this class */
55      protected transient final Log logger = LogFactory.getLog(TransientRegistry.class);
56      public static final String REGISTRY_ID = "org.mule.Registry.Transient";
57  
58      /** Map of Maps registry */
59      private Map registry;
60  
61      public TransientRegistry()
62      {
63          super(REGISTRY_ID);
64          init();
65      }
66  
67      public TransientRegistry(Registry parent)
68      {
69          super(REGISTRY_ID, parent);
70          init();
71      }
72  
73      private void init()
74      {
75          registry = new HashMap(8);
76  
77          getObjectTypeMap(ObjectProcessor.class).put("_muleExpressionEvaluatorProcessor",
78                  new ExpressionEvaluatorProcessor());
79  
80          RegistryContext.setRegistry(this);
81          try
82          {
83              initialise();
84          }
85          catch (InitialisationException e)
86          {
87              logger.error(e);
88          }
89  
90      }
91  
92      protected LifecycleManager createLifecycleManager()
93      {
94          GenericLifecycleManager lcm = new GenericLifecycleManager();
95          LifecyclePhase initPhase = new TransientRegistryInitialisePhase();
96          initPhase.setRegistryScope(Registry.SCOPE_IMMEDIATE);
97          lcm.registerLifecycle(initPhase);
98          LifecyclePhase disposePhase = new TransientRegistryDisposePhase();
99          disposePhase.setRegistryScope(Registry.SCOPE_IMMEDIATE);
100         lcm.registerLifecycle(disposePhase);
101         return lcm;
102     }
103 
104     //@java.lang.Override
105     protected void doInitialise() throws InitialisationException
106     {
107         int oldScope = getDefaultScope();
108         setDefaultScope(Registry.SCOPE_IMMEDIATE);
109         try
110         {
111             applyProcessors(getConnectors());
112             applyProcessors(getTransformers());
113             applyProcessors(getEndpoints());
114             applyProcessors(getAgents());
115             applyProcessors(getModels());
116             applyProcessors(lookupServices());
117             applyProcessors(lookupObjects(Object.class));
118         }
119         finally
120         {
121             setDefaultScope(oldScope);
122         }
123 
124     }
125 
126     protected void applyProcessors(Map objects)
127     {
128         if (objects == null)
129         {
130             return;
131         }
132         for (Iterator iterator = objects.values().iterator(); iterator.hasNext();)
133         {
134             Object o = iterator.next();
135             Collection processors = lookupObjects(ObjectProcessor.class);
136             for (Iterator iterator2 = processors.iterator(); iterator2.hasNext();)
137             {
138                 ObjectProcessor op = (ObjectProcessor) iterator2.next();
139                 op.process(o);
140             }
141         }
142     }
143 
144 
145     public void registerObjects(Map objects) throws RegistrationException
146     {
147         if (objects == null)
148         {
149             return;
150         }
151 
152         for (Iterator iterator = objects.entrySet().iterator(); iterator.hasNext();)
153         {
154             Map.Entry entry = (Map.Entry) iterator.next();
155             registerObject(entry.getKey().toString(), entry.getValue());
156         }
157     }
158 
159     protected Object doLookupObject(String key)
160     {
161         Object o = null;
162         if (key != null)
163         {
164             Map map;
165             for (Iterator it = registry.values().iterator(); it.hasNext();)
166             {
167                 map = (Map) it.next();
168                 o = map.get(key);
169                 if (o != null)
170                 {
171                     return o;
172                 }
173             }
174         }
175         return o;
176     }
177 
178     public Collection doLookupObjects(Class returntype)
179     {
180         Map map = (Map) registry.get(returntype);
181         if (map != null)
182         {
183             return map.values();
184         }
185         else
186         {
187             return null;
188         }
189     }
190 
191     /** Looks up the service descriptor from a singleton cache and creates a new one if not found. */
192     public ServiceDescriptor lookupServiceDescriptor(String type, String name, Properties overrides) throws ServiceException
193     {
194         String key = new AbstractServiceDescriptor.Key(name, overrides).getKey();
195         //TODO If we want these descriptors loaded form Spring we need to checnge the key mechanism
196         //and the scope, and then deal with circular reference issues.
197         ServiceDescriptor sd = (ServiceDescriptor) lookupObject(key);
198 
199         synchronized (this)
200         {
201             if (sd == null)
202             {
203                 sd = createServiceDescriptor(type, name, overrides);
204                 try
205                 {
206                     registerObject(key, sd, ServiceDescriptor.class);
207                 }
208                 catch (RegistrationException e)
209                 {
210                     throw new ServiceException(e.getI18nMessage(), e);
211                 }
212             }
213         }
214         return sd;
215     }
216 
217     // TODO ServiceDescriptors will be created upon bundle startup for OSGi. 
218     protected ServiceDescriptor createServiceDescriptor(String type, String name, Properties overrides) throws ServiceException
219     {
220         Properties props = SpiUtils.findServiceDescriptor(type, name);
221         if (props == null)
222         {
223             throw new ServiceException(CoreMessages.failedToLoad(type + " " + name));
224         }
225         return ServiceDescriptorFactory.create(type, name, props, overrides, this);
226     }
227 
228     protected Map getObjectTypeMap(Object o)
229     {
230         if (o == null)
231         {
232             o = Object.class;
233         }
234 
235         Object key;
236         if (o instanceof Class)
237         {
238             key = o;
239         }
240         else if (o instanceof String)
241         {
242             key = o;
243         }
244         else
245         {
246             key = o.getClass();
247         }
248         Map objects = (Map) registry.get(key);
249         if (objects == null)
250         {
251             objects = new HashMap(8);
252             registry.put(key, objects);
253         }
254         return objects;
255     }
256 
257     protected Object applyProcessors(Object object)
258     {
259         Object theObject = object;
260         // this may be an incorrect hack.  the problem is that if we try to lookup objects in spring before
261         // it is initialised, we end up triggering object creation.  that causes circular dependencies because
262         // this may have originally been called while creating objects in spring...  so we prevent that by
263         // only doing the full lookup once everything is stable.  ac.
264         Collection processors = 
265                 lookupObjects(ObjectProcessor.class,
266                         (null != getParent() && getParent().isInitialised()) ? getDefaultScope() : SCOPE_IMMEDIATE);
267         for (Iterator iterator = processors.iterator(); iterator.hasNext();)
268         {
269             ObjectProcessor o = (ObjectProcessor) iterator.next();
270             theObject = o.process(theObject);
271         }
272         return theObject;
273     }
274 
275     /**
276      * Allows for arbitary registration of transient objects
277      *
278      * @param key
279      * @param value
280      */
281     protected void doRegisterObject(String key, Object value) throws RegistrationException
282     {
283         doRegisterObject(key, value, Object.class);
284     }
285 
286     /**
287      * Allows for arbitary registration of transient objects
288      *
289      * @param key
290      * @param value
291      */
292     protected void doRegisterObject(String key, Object object, Object metadata) throws RegistrationException
293     {
294         logger.debug("registering object");
295         if (isInitialised() || isInitialising())
296         {
297             logger.debug("applying processors");
298             object = applyProcessors(object);
299         }
300 
301         Map objectMap = getObjectTypeMap(metadata);
302         if (objectMap != null)
303         {
304             if (objectMap.containsKey(key))
305             {
306                 // objectMap.put(key, value) would overwrite a previous entity with the same name.  Is this really what we want?
307                 // Not sure whether to throw an exception or log a warning here.
308                 //throw new RegistrationException("TransientRegistry already contains an object named '" + key + "'.  The previous object would be overwritten.");
309                 logger.warn("TransientRegistry already contains an object named '" + key + "'.  The previous object will be overwritten.");
310             }
311             objectMap.put(key, object);
312             try
313             {
314                 MuleContext mc = MuleServer.getMuleContext();
315                 logger.debug("context: " + mc);
316                 if (mc != null)
317                 {
318                     logger.debug("applying lifecycle");
319                     mc.applyLifecycle(object);
320                 }
321                 else
322                 {
323                     throw new RegistrationException("Unable to register object (\""
324                             + key + ":" + ClassUtils.getSimpleName(object.getClass())
325                             + "\") because MuleContext has not yet been created.");
326                 }
327             }
328             catch (MuleException e)
329             {
330                 throw new RegistrationException(e);
331             }
332         }
333         else
334         {
335             throw new RegistrationException("No object map exists for type " + metadata);
336         }
337     }
338 
339     //@java.lang.Override
340     public void registerAgent(Agent agent) throws MuleException
341     {
342         registerObject(agent.getName(), agent, Agent.class);
343     }
344 
345     //@java.lang.Override
346     public void registerConnector(Connector connector) throws MuleException
347     {
348         registerObject(connector.getName(), connector, Connector.class);
349     }
350 
351     //@java.lang.Override
352     public void registerEndpoint(ImmutableEndpoint endpoint) throws MuleException
353     {
354         registerObject(endpoint.getName(), endpoint, ImmutableEndpoint.class);
355     }
356 
357     public void registerEndpointBuilder(String name, EndpointBuilder builder) throws MuleException
358     {
359         registerObject(name, builder, EndpointBuilder.class);
360     }
361 
362     //@java.lang.Override
363     public void registerModel(Model model) throws MuleException
364     {
365         registerObject(model.getName(), model, Model.class);
366     }
367 
368     //@java.lang.Override
369     protected void doRegisterTransformer(Transformer transformer) throws MuleException
370     {
371         //TODO should we always throw an exception if an object already exists
372         if (lookupTransformer(transformer.getName()) != null)
373         {
374             throw new RegistrationException(CoreMessages.objectAlreadyRegistered("transformer: " +
375                     transformer.getName(), lookupTransformer(transformer.getName()), transformer).getMessage());
376         }
377         registerObject(transformer.getName(), transformer, Transformer.class);
378     }
379 
380     //@java.lang.Override
381     public void registerService(Service service) throws MuleException
382     {
383         registerObject(service.getName(), service, Service.class);
384     }
385 
386     protected void unregisterObject(String key, Object metadata) throws MuleException
387     {
388         Object obj = getObjectTypeMap(metadata).remove(key);
389         if (obj instanceof Stoppable)
390         {
391             ((Stoppable) obj).stop();
392         }
393     }
394 
395     public void unregisterObject(String key) throws MuleException
396     {
397         unregisterObject(key, Object.class);
398     }
399 
400     //@java.lang.Override
401     public void unregisterService(String serviceName) throws MuleException
402     {
403         unregisterObject(serviceName, Service.class);
404     }
405 
406 
407     //@java.lang.Override
408     public void unregisterAgent(String agentName) throws MuleException
409     {
410         unregisterObject(agentName, Agent.class);
411     }
412 
413     //@java.lang.Override
414     public void unregisterConnector(String connectorName) throws MuleException
415     {
416         unregisterObject(connectorName, Connector.class);
417     }
418 
419     //@java.lang.Override
420     public void unregisterEndpoint(String endpointName) throws MuleException
421     {
422         unregisterObject(endpointName, ImmutableEndpoint.class);
423     }
424 
425     //@java.lang.Override
426     public void unregisterModel(String modelName) throws MuleException
427     {
428         unregisterObject(modelName, Model.class);
429     }
430 
431     //@java.lang.Override
432     public void unregisterTransformer(String transformerName) throws MuleException
433     {
434         Transformer transformer = lookupTransformer(transformerName);
435         if (transformer instanceof DiscoverableTransformer)
436         {
437             exactTransformerCache.clear();
438             transformerListCache.clear();
439         }
440         unregisterObject(transformerName, Transformer.class);
441     }
442 
443     //@java.lang.Override
444     public Transformer lookupTransformer(String name)
445     {
446         Transformer transformer = super.lookupTransformer(name);
447         if (transformer != null)
448         {
449             try
450             {
451                 if (transformer.getEndpoint() != null)
452                 {
453                     throw new IllegalStateException("Endpoint cannot be set");
454                 }
455 //                Map props = BeanUtils.describe(transformer);
456 //                props.remove("endpoint");
457 //                props.remove("strategy");
458 //                transformer = (Transformer)ClassUtils.instanciateClass(transformer.getClass(), ClassUtils.NO_ARGS);
459                 //TODO: friggin' cloning
460                 transformer = (Transformer) BeanUtils.cloneBean(transformer);
461             }
462             catch (Exception e)
463             {
464                 //TODO MULE-3532
465                 e.printStackTrace();
466             }
467         }
468         return transformer;
469     }
470 
471     public boolean isReadOnly()
472     {
473         return false;
474     }
475 
476     public boolean isRemote()
477     {
478         return false;
479     }
480 
481 }