View Javadoc

1   /*
2    * $Id$
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.registry;
12  
13  import org.mule.api.MuleContext;
14  import org.mule.api.MuleException;
15  import org.mule.api.NamedObject;
16  import org.mule.api.agent.Agent;
17  import org.mule.api.config.MuleProperties;
18  import org.mule.api.endpoint.EndpointBuilder;
19  import org.mule.api.endpoint.EndpointFactory;
20  import org.mule.api.endpoint.ImmutableEndpoint;
21  import org.mule.api.lifecycle.Disposable;
22  import org.mule.api.lifecycle.Initialisable;
23  import org.mule.api.lifecycle.InitialisationException;
24  import org.mule.api.lifecycle.LifecycleException;
25  import org.mule.api.model.Model;
26  import org.mule.api.registry.AbstractServiceDescriptor;
27  import org.mule.api.registry.MuleRegistry;
28  import org.mule.api.registry.RegistrationException;
29  import org.mule.api.registry.ResolverException;
30  import org.mule.api.registry.ServiceDescriptor;
31  import org.mule.api.registry.ServiceDescriptorFactory;
32  import org.mule.api.registry.ServiceException;
33  import org.mule.api.registry.ServiceType;
34  import org.mule.api.registry.TransformerResolver;
35  import org.mule.api.service.Service;
36  import org.mule.api.transformer.DataType;
37  import org.mule.api.transformer.DiscoverableTransformer;
38  import org.mule.api.transformer.Transformer;
39  import org.mule.api.transformer.TransformerException;
40  import org.mule.api.transport.Connector;
41  import org.mule.config.i18n.CoreMessages;
42  import org.mule.transformer.types.SimpleDataType;
43  import org.mule.util.SpiUtils;
44  import org.mule.util.StringUtils;
45  import org.mule.util.UUID;
46  
47  import java.util.ArrayList;
48  import java.util.Collection;
49  import java.util.Collections;
50  import java.util.Comparator;
51  import java.util.Iterator;
52  import java.util.List;
53  import java.util.Map;
54  import java.util.Properties;
55  
56  import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
57  
58  import org.apache.commons.logging.Log;
59  import org.apache.commons.logging.LogFactory;
60  
61  /**
62   * Adds lookup/register/unregister methods for Mule-specific entities to the standard
63   * Registry interface.
64   */
65  public class MuleRegistryHelper implements MuleRegistry
66  {
67      protected transient Log logger = LogFactory.getLog(MuleRegistryHelper.class);
68  
69      /**
70       * A reference to Mule's internal registry
71       */
72      private DefaultRegistryBroker registry;
73  
74      /**
75       * We cache transformer searches so that we only search once
76       */
77      protected Map<String, List<Transformer>> transformerListCache = new ConcurrentHashMap/*<String, List<Transformer>>*/(8);
78  
79      private MuleContext muleContext;
80  
81      public MuleRegistryHelper(DefaultRegistryBroker registry, MuleContext muleContext)
82      {
83          this.registry = registry;
84          this.muleContext = muleContext;
85      }
86  
87      /**
88       * {@inheritDoc}
89       */
90      public void initialise() throws InitialisationException
91      {
92          //no-op
93  
94          //This is called when the MuleContext starts up, and should only do initialisation for any state on this class, the lifecycle
95          //for the registries will be handled by the LifecycleManager on the registry that this class wraps
96      }
97  
98      /**
99       * {@inheritDoc}
100      */
101     public void dispose()
102     {
103         transformerListCache.clear();
104     }
105 
106     public void fireLifecycle(String phase) throws LifecycleException
107     {
108         if(Initialisable.PHASE_NAME.equals(phase))
109         {
110             registry.initialise();
111         }
112         else if(Disposable.PHASE_NAME.equals(phase))
113         {
114             registry.dispose();
115         }
116         else
117         {
118             registry.fireLifecycle(phase);
119         }
120     }
121 
122     /**
123      * {@inheritDoc}
124      */
125     public Connector lookupConnector(String name)
126     {
127         return (Connector) registry.lookupObject(name);
128     }
129 
130     /**
131      * Removed this method from {@link Registry} API as it should only be used
132      * internally and may confuse users. The {@link EndpointFactory} should be used
133      * for creating endpoints.<br/><br/> Looks up an returns endpoints registered in the
134      * registry by their identifier (currently endpoint name)<br/><br/ <b>NOTE:
135      * This method does not create new endpoint instances, but rather returns
136      * existing endpoint instances that have been registered. This lookup method
137      * should be avoided and the intelligent, role specific endpoint lookup methods
138      * should be used instead.<br/><br/>
139      *
140      * @param name the idendtifer/name used to register endpoint in registry
141      * @return foo
142      */
143     /*public ImmutableEndpoint lookupEndpoint(String name)
144     {
145         Object obj = registry.lookupObject(name);
146         if (obj instanceof ImmutableEndpoint)
147         {
148             return (ImmutableEndpoint) obj;
149         }
150         else
151         {
152             logger.debug("No endpoint with the name: "
153                     + name
154                     + "found.  If "
155                     + name
156                     + " is a global endpoint you should use the EndpointFactory to create endpoint instances from global endpoints.");
157             return null;
158         }
159     }*/
160 
161     /**
162      * {@inheritDoc}
163      */
164     public EndpointBuilder lookupEndpointBuilder(String name)
165     {
166         Object o = registry.lookupObject(name);
167         if (o instanceof EndpointBuilder)
168         {
169             logger.debug("Global endpoint EndpointBuilder for name: " + name + " found");
170             return (EndpointBuilder) o;
171         }
172         else
173         {
174             logger.debug("No endpoint builder with the name: " + name + " found.");
175             return null;
176         }
177     }
178 
179     /**
180      * {@inheritDoc}
181      */
182     public EndpointFactory lookupEndpointFactory()
183     {
184         return (EndpointFactory) registry.lookupObject(MuleProperties.OBJECT_MULE_ENDPOINT_FACTORY);
185     }
186 
187     /**
188      * {@inheritDoc}
189      */
190     public Transformer lookupTransformer(String name)
191     {
192         return (Transformer) registry.lookupObject(name);
193     }
194 
195     /**
196      * {@inheritDoc}
197      *
198      * @deprecated use {@link #lookupTransformer(org.mule.api.transformer.DataType, org.mule.api.transformer.DataType)} instead.  This
199      * method should only be used internally to discover transformers, typically a user does not need ot do this
200      * directly
201      */
202     @Deprecated
203     public Transformer lookupTransformer(Class inputType, Class outputType) throws TransformerException
204     {
205         return lookupTransformer(new SimpleDataType(inputType), new SimpleDataType(outputType));
206     }
207 
208     /**
209      * {@inheritDoc}
210      *
211      * @deprecated use {@link #lookupTransformer(org.mule.api.transformer.DataType, org.mule.api.transformer.DataType)} instead.  This
212      * method should only be used internally to discover transformers, typically a user does not need ot do this
213      * directly
214      */
215     @Deprecated
216     public List<Transformer> lookupTransformers(Class input, Class output)
217     {
218         return lookupTransformers(new SimpleDataType(input), new SimpleDataType(output));
219     }
220 
221     /**
222      * {@inheritDoc}
223      */
224     public Transformer lookupTransformer(DataType source, DataType result) throws TransformerException
225     {
226 
227         Transformer trans;
228         List<TransformerResolver> resolvers = (List<TransformerResolver>) lookupObjects(TransformerResolver.class);
229         Collections.sort(resolvers, new TransformerResolverComparator());
230         for (TransformerResolver resolver : resolvers)
231         {
232             try
233             {
234                 trans = resolver.resolve(source, result);
235                 if (trans != null)
236                 {
237                     return trans;
238                 }
239             }
240             catch (ResolverException e)
241             {
242                 throw new TransformerException(CoreMessages.noTransformerFoundForMessage(source, result), e);
243             }
244         }
245         throw new TransformerException(CoreMessages.noTransformerFoundForMessage(source, result));
246     }
247 
248     /**
249      * {@inheritDoc}
250      */
251     public List<Transformer> lookupTransformers(DataType source, DataType result)
252     {
253         List<Transformer> results = transformerListCache.get(source.toString() + result.toString());
254         if (results != null)
255         {
256             return results;
257         }
258 
259         results = new ArrayList<Transformer>(2);
260         Collection<Transformer> transformers = getTransformers();
261         for (Transformer t : transformers)
262         {
263             //The transformer must have the DiscoveryTransformer interface if we are going to
264             //find it here
265             if (!(t instanceof DiscoverableTransformer))
266             {
267                 continue;
268             }
269             DataType dt = t.getReturnDataType();
270             if (result.isCompatibleWith(dt) && t.isSourceDataTypeSupported(source))
271             {
272                 results.add(t);
273             }
274         }
275 
276         transformerListCache.put(source.toString() + result.toString(), results);
277         return results;
278     }
279 
280     /**
281      * {@inheritDoc}
282      */
283     public Model lookupModel(String name)
284     {
285         return (Model) registry.lookupObject(name);
286     }
287 
288     /**
289      * {@inheritDoc}
290      */
291     public Model lookupSystemModel()
292     {
293         return lookupModel(MuleProperties.OBJECT_SYSTEM_MODEL);
294     }
295 
296     /**
297      * {@inheritDoc}
298      */
299     public Collection<Model> getModels()
300     {
301         return registry.lookupObjects(Model.class);
302     }
303 
304     /**
305      * {@inheritDoc}
306      */
307     public Collection<Connector> getConnectors()
308     {
309         return registry.lookupObjects(Connector.class);
310     }
311 
312     /**
313      * {@inheritDoc}
314      */
315     public Collection<Agent> getAgents()
316     {
317         return registry.lookupObjects(Agent.class);
318     }
319 
320     /**
321      * {@inheritDoc}
322      */
323     public Collection<ImmutableEndpoint> getEndpoints()
324     {
325         return registry.lookupObjects(ImmutableEndpoint.class);
326     }
327 
328     /**
329      * {@inheritDoc}
330      */
331     public Collection<Transformer> getTransformers()
332     {
333         return registry.lookupObjects(Transformer.class);
334     }
335 
336     /**
337      * {@inheritDoc}
338      */
339     public Agent lookupAgent(String name)
340     {
341         return (Agent) registry.lookupObject(name);
342     }
343 
344     /**
345      * {@inheritDoc}
346      */
347     public Service lookupService(String name)
348     {
349         return (Service) registry.lookupObject(name);
350     }
351 
352     /**
353      * {@inheritDoc}
354      */
355     public Collection<Service> lookupServices()
356     {
357         return lookupObjects(Service.class);
358     }
359 
360     /**
361      * {@inheritDoc}
362      */
363     public Collection<Service> lookupServices(String model)
364     {
365         Collection<Service> services = lookupServices();
366         List<Service> modelServices = new ArrayList<Service>();
367         Iterator it = services.iterator();
368         Service service;
369         while (it.hasNext())
370         {
371             service = (Service) it.next();
372             if (model.equals(service.getModel().getName()))
373             {
374                 modelServices.add(service);
375             }
376         }
377         return modelServices;
378     }
379 
380     /**
381      * {@inheritDoc}
382      */
383     public final void registerTransformer(Transformer transformer) throws MuleException
384     {
385         registry.registerObject(getName(transformer), transformer, Transformer.class);
386         notifyTransformerResolvers(transformer, TransformerResolver.RegistryAction.ADDED);
387     }
388 
389     protected void notifyTransformerResolvers(Transformer t, TransformerResolver.RegistryAction action)
390     {
391         if (t instanceof DiscoverableTransformer)
392         {
393             Collection<TransformerResolver> resolvers = lookupObjects(TransformerResolver.class);
394             for (TransformerResolver resolver : resolvers)
395             {
396                 resolver.transformerChange(t, action);
397             }
398             transformerListCache.clear();
399         }
400     }
401 
402     /**
403      * Looks up the service descriptor from a singleton cache and creates a new one if not found.
404      */
405     public ServiceDescriptor lookupServiceDescriptor(ServiceType type, String name, Properties overrides) throws ServiceException
406     {
407         String key = new AbstractServiceDescriptor.Key(name, overrides).getKey();
408         // TODO If we want these descriptors loaded form Spring we need to change the key mechanism
409         // and the scope, and then deal with circular reference issues.
410         ServiceDescriptor sd = (ServiceDescriptor) registry.lookupObject(key);
411 
412         synchronized (this)
413         {
414             if (sd == null)
415             {
416                 sd = createServiceDescriptor(type, name, overrides);
417                 try
418                 {
419                     registry.registerObject(key, sd, ServiceDescriptor.class);
420                 }
421                 catch (RegistrationException e)
422                 {
423                     throw new ServiceException(e.getI18nMessage(), e);
424                 }
425             }
426         }
427         return sd;
428     }
429 
430     protected ServiceDescriptor createServiceDescriptor(ServiceType type, String name, Properties overrides) throws ServiceException
431     {
432         //Stripe off and use the meta-scheme if present
433         String scheme = name;
434         if (name.contains(":"))
435         {
436             scheme = name.substring(0, name.indexOf(":"));
437         }
438 
439         Properties props = SpiUtils.findServiceDescriptor(type, scheme);
440         if (props == null)
441         {
442             throw new ServiceException(CoreMessages.failedToLoad(type + " " + scheme));
443         }
444 
445         return ServiceDescriptorFactory.create(type, name, props, overrides, muleContext, null);
446     }
447 
448     /**
449      * {@inheritDoc}
450      */
451     public void registerAgent(Agent agent) throws MuleException
452     {
453         registry.registerObject(getName(agent), agent, Agent.class);
454     }
455 
456     /**
457      * {@inheritDoc}
458      */
459     public void registerConnector(Connector connector) throws MuleException
460     {
461         registry.registerObject(getName(connector), connector, Connector.class);
462     }
463 
464     /**
465      * {@inheritDoc}
466      */
467     public void registerEndpoint(ImmutableEndpoint endpoint) throws MuleException
468     {
469         registry.registerObject(getName(endpoint), endpoint, ImmutableEndpoint.class);
470     }
471 
472     /**
473      * {@inheritDoc}
474      */
475     public void registerEndpointBuilder(String name, EndpointBuilder builder) throws MuleException
476     {
477         registry.registerObject(name, builder, EndpointBuilder.class);
478     }
479 
480     /**
481      * {@inheritDoc}
482      */
483     public void registerModel(Model model) throws MuleException
484     {
485         registry.registerObject(getName(model), model, Model.class);
486     }
487 
488     /**
489      * {@inheritDoc}
490      */
491     public void registerService(Service service) throws MuleException
492     {
493         registry.registerObject(getName(service), service, Service.class);
494     }
495 
496     /**
497      * {@inheritDoc}
498      */
499     public void unregisterService(String serviceName) throws MuleException
500     {
501         registry.unregisterObject(serviceName, Service.class);
502     }
503 
504     /**
505      * {@inheritDoc}
506      */
507     public void unregisterAgent(String agentName) throws MuleException
508     {
509         registry.unregisterObject(agentName, Agent.class);
510     }
511 
512     /**
513      * {@inheritDoc}
514      */
515     public void unregisterConnector(String connectorName) throws MuleException
516     {
517         registry.unregisterObject(connectorName, Connector.class);
518     }
519 
520     /**
521      * {@inheritDoc}
522      */
523     public void unregisterEndpoint(String endpointName) throws MuleException
524     {
525         registry.unregisterObject(endpointName, ImmutableEndpoint.class);
526     }
527 
528     /**
529      * {@inheritDoc}
530      */
531     public void unregisterModel(String modelName) throws MuleException
532     {
533         registry.unregisterObject(modelName, Model.class);
534     }
535 
536     /**
537      * {@inheritDoc}
538      */
539     public void unregisterTransformer(String transformerName) throws MuleException
540     {
541         Transformer transformer = lookupTransformer(transformerName);
542         notifyTransformerResolvers(transformer, TransformerResolver.RegistryAction.REMOVED);
543         registry.unregisterObject(transformerName, Transformer.class);
544 
545     }
546 
547     /**
548      * {@inheritDoc}
549      */
550     public Object applyProcessorsAndLifecycle(Object object) throws MuleException
551     {
552         object = applyProcessors(object);
553         object = applyLifecycle(object);
554         return object;
555     }
556 
557     /**
558      * {@inheritDoc}
559      */
560     public Object applyProcessors(Object object) throws MuleException
561     {
562         return registry.getTransientRegistry().applyProcessors(object, null);
563     }
564 
565     /**
566      * {@inheritDoc}
567      */
568     public Object applyProcessors(Object object, int flags) throws MuleException
569     {
570         return registry.getTransientRegistry().applyProcessors(object, flags);
571     }
572 
573     /**
574      * {@inheritDoc}
575      */
576     public Object applyLifecycle(Object object) throws MuleException
577     {
578         return registry.getTransientRegistry().applyLifecycle(object);
579     }
580 
581     public Object applyLifecycle(Object object, String phase) throws MuleException
582     {
583         return registry.getTransientRegistry().applyLifecycle(object, phase);        
584     }
585 
586     ////////////////////////////////////////////////////////////////////////////
587     // Delegate to internal registry
588     ////////////////////////////////////////////////////////////////////////////
589 
590     /**
591      * {@inheritDoc}
592      */
593     public <T> T lookupObject(Class<T> type) throws RegistrationException
594     {
595         return registry.lookupObject(type);
596     }
597 
598     @SuppressWarnings("unchecked")
599     public <T> T lookupObject(String key)
600     {
601         return (T) registry.lookupObject(key);
602     }
603 
604     /**
605      * {@inheritDoc}
606      */
607     public <T> Collection<T> lookupObjects(Class<T> type)
608     {
609         return registry.lookupObjects(type);
610     }
611 
612     @SuppressWarnings("unchecked")
613     public <T> T get(String key)
614     {
615         return (T)registry.get(key);
616     }
617 
618     public <T> Map<String, T> lookupByType(Class<T> type)
619     {
620         return registry.lookupByType(type);
621     }
622 
623     /**
624      * {@inheritDoc}
625      */
626     public void registerObject(String key, Object value, Object metadata) throws RegistrationException
627     {
628         registry.registerObject(key, value, metadata);
629     }
630 
631     /**
632      * {@inheritDoc}
633      */
634     public void registerObject(String key, Object value) throws RegistrationException
635     {
636         registry.registerObject(key, value);
637     }
638 
639     /**
640      * {@inheritDoc}
641      */
642     public void registerObjects(Map objects) throws RegistrationException
643     {
644         registry.registerObjects(objects);
645     }
646 
647     /**
648      * {@inheritDoc}
649      */
650     public void unregisterObject(String key, Object metadata) throws RegistrationException
651     {
652         registry.unregisterObject(key, metadata);
653     }
654 
655     /**
656      * {@inheritDoc}
657      */
658     public void unregisterObject(String key) throws RegistrationException
659     {
660         registry.unregisterObject(key);
661     }
662 
663     /**
664      * Returns the name for the object passed in.  If the object implements {@link org.mule.api.NamedObject}, then
665      * {@link org.mule.api.NamedObject#getName()} will be returned, otherwise a name is generated using the class name
666      * and a generated UUID.
667      * @param obj the object to inspect
668      * @return the name for this object
669      */
670     protected String getName(Object obj)
671     {
672         String name = null;
673         if (obj instanceof NamedObject)
674         {
675             name = ((NamedObject) obj).getName();
676         }
677         if (StringUtils.isBlank(name))
678         {
679             name = obj.getClass().getName() + ":" + UUID.getUUID();
680         }
681         return name;
682     }
683 
684     ////////////////////////////////////////////////////////////////////////////
685     // Registry Metadata
686     ////////////////////////////////////////////////////////////////////////////
687 
688     /**
689      * {@inheritDoc}
690      */
691     public String getRegistryId()
692     {
693         return this.toString();
694     }
695 
696     /**
697      * {@inheritDoc}
698      */
699     public boolean isReadOnly()
700     {
701         return false;
702     }
703 
704     /**
705      * {@inheritDoc}
706      */
707     public boolean isRemote()
708     {
709         return false;
710     }
711 
712 
713     private class TransformerResolverComparator implements Comparator<TransformerResolver>
714     {
715         public int compare(TransformerResolver transformerResolver, TransformerResolver transformerResolver1)
716         {
717             if (transformerResolver.getClass().equals(TypeBasedTransformerResolver.class))
718             {
719                 return 1;
720             }
721 
722             if (transformerResolver1.getClass().equals(TypeBasedTransformerResolver.class))
723             {
724                 return -1;
725             }
726             return 0;
727         }
728     }
729 }
730 
731