1
2
3
4
5
6
7
8
9
10
11 package org.mule.registry;
12
13 import org.mule.MuleServer;
14 import org.mule.RegistryContext;
15 import org.mule.api.MuleException;
16 import org.mule.api.MuleRuntimeException;
17 import org.mule.api.agent.Agent;
18 import org.mule.api.config.MuleProperties;
19 import org.mule.api.context.MuleContextAware;
20 import org.mule.api.endpoint.EndpointBuilder;
21 import org.mule.api.endpoint.EndpointFactory;
22 import org.mule.api.endpoint.ImmutableEndpoint;
23 import org.mule.api.lifecycle.Disposable;
24 import org.mule.api.lifecycle.Initialisable;
25 import org.mule.api.lifecycle.InitialisationException;
26 import org.mule.api.lifecycle.LifecycleManager;
27 import org.mule.api.model.Model;
28 import org.mule.api.registry.RegistrationException;
29 import org.mule.api.registry.Registry;
30 import org.mule.api.service.Service;
31 import org.mule.api.transformer.DiscoverableTransformer;
32 import org.mule.api.transformer.Transformer;
33 import org.mule.api.transformer.TransformerException;
34 import org.mule.api.transport.Connector;
35 import org.mule.config.i18n.CoreMessages;
36 import org.mule.transformer.TransformerCollection;
37 import org.mule.transformer.TransformerWeighting;
38 import org.mule.transformer.simple.ObjectToByteArray;
39 import org.mule.transformer.simple.ObjectToString;
40 import org.mule.util.CollectionUtils;
41 import org.mule.util.UUID;
42 import org.mule.util.expression.ExpressionEvaluatorManager;
43
44 import java.util.ArrayList;
45 import java.util.Collection;
46 import java.util.Iterator;
47 import java.util.List;
48 import java.util.Map;
49
50 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
51
52 import org.apache.commons.logging.Log;
53 import org.apache.commons.logging.LogFactory;
54
55
56 public abstract class AbstractRegistry implements Registry
57 {
58 private static final ObjectToString objectToString = new ObjectToString();
59 private static final ObjectToByteArray objectToByteArray = new ObjectToByteArray();
60
61 private Registry parent;
62
63 private String id;
64
65 private int defaultScope = DEFAULT_SCOPE;
66
67 protected transient Log logger = LogFactory.getLog(getClass());
68
69 protected LifecycleManager lifecycleManager;
70 protected Map transformerListCache = new ConcurrentHashMap(8);
71 protected Map exactTransformerCache = new ConcurrentHashMap(8);
72
73
74 protected AbstractRegistry(String id)
75 {
76 if (id == null)
77 {
78 throw new MuleRuntimeException(CoreMessages.objectIsNull("RegistryID"));
79 }
80 this.id = id;
81 lifecycleManager = createLifecycleManager();
82 }
83
84 protected AbstractRegistry(String id, Registry parent)
85 {
86 this(id);
87 setParent(parent);
88 }
89
90 protected abstract LifecycleManager createLifecycleManager();
91
92 protected LifecycleManager getLifecycleManager()
93 {
94 return lifecycleManager;
95 }
96
97 public final synchronized void dispose()
98 {
99
100
101 if (isDisposed())
102 {
103 return;
104 }
105
106 try
107 {
108 exactTransformerCache.clear();
109 transformerListCache.clear();
110
111 doDispose();
112 lifecycleManager.firePhase(MuleServer.getMuleContext(), Disposable.PHASE_NAME);
113 if (getParent() != null)
114 {
115 parent.dispose();
116 }
117 else
118 {
119
120 RegistryContext.setRegistry(null);
121 ExpressionEvaluatorManager.clearEvaluators();
122 }
123 }
124 catch (MuleException e)
125 {
126
127 logger.error("Failed to cleanly dispose: " + e.getMessage(), e);
128 }
129 }
130
131 protected void doDispose()
132 {
133
134 }
135
136 public boolean isDisposed()
137 {
138 return lifecycleManager.isPhaseComplete(Disposable.PHASE_NAME);
139 }
140
141 public boolean isDisposing()
142 {
143 return Disposable.PHASE_NAME.equals(lifecycleManager.getExecutingPhase());
144 }
145
146 public boolean isInitialised()
147 {
148 return lifecycleManager.isPhaseComplete(Initialisable.PHASE_NAME);
149 }
150
151 public boolean isInitialising()
152 {
153 return Initialisable.PHASE_NAME.equals(lifecycleManager.getExecutingPhase());
154 }
155
156 public final void initialise() throws InitialisationException
157 {
158 lifecycleManager.checkPhase(Initialisable.PHASE_NAME);
159
160
161
162
163
164
165
166
167
168
169
170
171
172 if (id == null)
173 {
174 logger.warn("No unique id has been set on this registry");
175 id = UUID.getUUID();
176 }
177 try
178 {
179 doInitialise();
180 lifecycleManager.firePhase(MuleServer.getMuleContext(), Initialisable.PHASE_NAME);
181 }
182 catch (InitialisationException e)
183 {
184 throw e;
185 }
186 catch (Exception e)
187 {
188 throw new InitialisationException(e, this);
189 }
190 }
191
192 protected void doInitialise() throws InitialisationException
193 {
194
195 }
196
197
198 public Connector lookupConnector(String name)
199 {
200 return (Connector) lookupObject(name);
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 public ImmutableEndpoint lookupEndpoint(String name)
218 {
219 Object obj = lookupObject(name);
220 if (obj instanceof ImmutableEndpoint)
221 {
222 return (ImmutableEndpoint) obj;
223 }
224 else
225 {
226 logger.debug("No endpoint with the name: "
227 + name
228 + "found. If "
229 + name
230 + " is a global endpoint you should use the EndpointFactory to create endpoint instances from global endpoints.");
231 return null;
232 }
233 }
234
235 public EndpointBuilder lookupEndpointBuilder(String name)
236 {
237 Object o = lookupObject(name);
238 if (o instanceof EndpointBuilder)
239 {
240 logger.debug("Global endpoint EndpointBuilder for name: " + name + " found");
241 return (EndpointBuilder) o;
242 }
243 else
244 {
245 logger.debug("No endpoint builder with the name: " + name + " found.");
246 return null;
247 }
248 }
249
250 public EndpointFactory lookupEndpointFactory()
251 {
252 return (EndpointFactory) lookupObject(MuleProperties.OBJECT_MULE_ENDPOINT_FACTORY);
253 }
254
255 public Transformer lookupTransformer(String name)
256 {
257 return (Transformer) lookupObject(name);
258 }
259
260
261 public Transformer lookupTransformer(Class inputType, Class outputType) throws TransformerException
262 {
263 Transformer result = (Transformer) exactTransformerCache.get(inputType.getName() + outputType.getName());
264 if (result != null)
265 {
266 return result;
267 }
268 List trans = lookupTransformers(inputType, outputType);
269
270 result = getNearestTransformerMatch(trans, inputType, outputType);
271
272
273 Transformer secondPass = null;
274
275 if (result == null)
276 {
277
278
279 if (outputType.equals(String.class))
280 {
281 secondPass = objectToString;
282 }
283 else if (outputType.equals(byte[].class))
284 {
285 secondPass = objectToByteArray;
286 }
287 else
288 {
289 throw new TransformerException(CoreMessages.noTransformerFoundForMessage(inputType, outputType));
290 }
291
292 trans = lookupTransformers(inputType, Object.class);
293
294 result = getNearestTransformerMatch(trans, inputType, outputType);
295 if (result != null)
296 {
297 result = new TransformerCollection(new Transformer[]{result, secondPass});
298 }
299 }
300
301 if (result != null)
302 {
303 exactTransformerCache.put(inputType.getName() + outputType.getName(), result);
304 }
305 return result;
306 }
307
308 protected Transformer getNearestTransformerMatch(List trans, Class input, Class output) throws TransformerException
309 {
310 if (trans.size() > 1)
311 {
312 TransformerWeighting weighting = null;
313 for (Iterator iterator = trans.iterator(); iterator.hasNext();)
314 {
315 Transformer transformer = (Transformer) iterator.next();
316 TransformerWeighting current = new TransformerWeighting(input, output, transformer);
317 if (weighting == null)
318 {
319 weighting = current;
320 }
321 else
322 {
323 int compare = current.compareTo(weighting);
324 if (compare == 1)
325 {
326 weighting = current;
327 }
328 else if (compare == 0)
329 {
330
331 if (!weighting.getTransformer().getClass().equals(current.getTransformer().getClass()))
332 {
333 throw new TransformerException(CoreMessages.transformHasMultipleMatches(input, output,
334 current.getTransformer(), weighting.getTransformer()));
335 }
336 }
337 }
338 }
339 return weighting.getTransformer();
340 }
341 else if (trans.size() == 0)
342 {
343 return null;
344 }
345 else
346 {
347 return (Transformer) trans.get(0);
348 }
349 }
350
351
352 public List lookupTransformers(Class input, Class output)
353 {
354 List results = (List) transformerListCache.get(input.getName() + output.getName());
355 if (results != null)
356 {
357 return results;
358 }
359
360 results = new ArrayList(2);
361 Collection transformers = getTransformers();
362 for (Iterator itr = transformers.iterator(); itr.hasNext();)
363 {
364 Transformer t = (Transformer) itr.next();
365
366
367 if (!(t instanceof DiscoverableTransformer))
368 {
369 continue;
370 }
371 Class c = t.getReturnClass();
372
373 if (c == null)
374 {
375 c = Object.class;
376 }
377 if (output.isAssignableFrom(c)
378 && t.isSourceTypeSupported(input))
379 {
380 results.add(t);
381 }
382 }
383
384 transformerListCache.put(input.getName() + output.getName(), results);
385 return results;
386 }
387
388 public Model lookupModel(String name)
389 {
390 return (Model) lookupObject(name);
391 }
392
393 public Model lookupSystemModel()
394 {
395 return lookupModel(MuleProperties.OBJECT_SYSTEM_MODEL);
396 }
397
398 public Collection getModels()
399 {
400 return lookupObjects(Model.class);
401 }
402
403 public Collection getConnectors()
404 {
405 return lookupObjects(Connector.class);
406 }
407
408 public Collection getAgents()
409 {
410 return lookupObjects(Agent.class);
411 }
412
413 public Collection getEndpoints()
414 {
415 return lookupObjects(ImmutableEndpoint.class);
416 }
417
418 public Collection getTransformers()
419 {
420 return lookupObjects(Transformer.class);
421 }
422
423 public Agent lookupAgent(String name)
424 {
425 return (Agent) lookupObject(name);
426 }
427
428 public Service lookupService(String name)
429 {
430 return (Service) lookupObject(name);
431 }
432
433 public Collection
434 {
435 return lookupObjects(Service.class);
436 }
437
438 public Collection
439 {
440 Collection
441 List modelComponents = new ArrayList();
442 Iterator it = components.iterator();
443 Service service;
444 while (it.hasNext())
445 {
446 service = (Service) it.next();
447
448 if (model.equals(service.getModel().getName()))
449 {
450 modelComponents.add(service);
451 }
452 }
453 return modelComponents;
454 }
455
456 public final Object lookupObject(String key, int scope)
457 {
458 logger.debug("lookupObject: key=" + key + " scope=" + scope);
459 Object o = doLookupObject(key);
460
461 if (o == null)
462 {
463 if (logger.isDebugEnabled())
464 {
465 logger.debug("Failed to find object in Registry ID: " + getRegistryId());
466 }
467 if (getParent() != null && scope > SCOPE_IMMEDIATE)
468 {
469 if (getParent().isRemote() && scope == SCOPE_REMOTE)
470 {
471 o = getParent().lookupObject(key);
472 }
473 else if (!getParent().isRemote() && scope >= SCOPE_LOCAL)
474 {
475 o = getParent().lookupObject(key);
476 }
477 }
478 }
479 return o;
480 }
481
482 public final Object lookupObject(Class type) throws RegistrationException
483 {
484 return lookupObject(type, getDefaultScope());
485 }
486
487
488
489
490
491
492 public final Object lookupObject(Class type, int scope) throws RegistrationException
493 {
494 Collection collection = lookupObjects(type, scope);
495 if (collection == null || collection.size() < 1)
496 {
497 return null;
498 }
499 else if (collection.size() > 1)
500 {
501 throw new RegistrationException("More than one object of type " + type + " was found in registry, but only 1 was expected.");
502 }
503 else
504 {
505 return collection.iterator().next();
506 }
507 }
508
509 public final Collection lookupObjects(Class type)
510 {
511 return lookupObjects(type, getDefaultScope());
512 }
513
514 public final Collection lookupObjects(Class type, int scope)
515 {
516 logger.debug("lookupObjects: type=" + type + " scope=" + scope);
517 Collection collection = doLookupObjects(type);
518 if (collection == null)
519 {
520 collection = new ArrayList();
521 }
522
523 if (getParent() != null && scope > SCOPE_IMMEDIATE)
524 {
525 if (getParent().isRemote() && scope == SCOPE_REMOTE)
526 {
527 Collection collection2 = getParent().lookupObjects(type);
528 if (collection2 != null)
529 {
530 collection.addAll(collection2);
531 }
532 }
533 else if (!getParent().isRemote() && scope >= SCOPE_LOCAL)
534 {
535 Collection collection2 = getParent().lookupObjects(type);
536 if (collection2 != null)
537 {
538 collection = CollectionUtils.union(collection, collection2);
539 }
540 }
541 }
542
543 return collection;
544 }
545
546 protected abstract Collection doLookupObjects(Class type);
547
548 public Object lookupObject(String key)
549 {
550 return lookupObject(key, getDefaultScope());
551 }
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628 protected abstract Object doLookupObject(String key);
629
630 protected void unsupportedOperation(String operation, Object o) throws UnsupportedOperationException
631 {
632 throw new UnsupportedOperationException(
633 "Registry: "
634 + getRegistryId()
635 + " is read-only so objects cannot be registered or unregistered. Failed to execute operation "
636 + operation + " on object: " + o);
637 }
638
639 public final void registerObject(String key, Object value) throws RegistrationException
640 {
641 registerObject(key, value, null);
642 }
643
644 public final void registerObject(String key,
645 Object value,
646 Object metadata) throws RegistrationException
647 {
648
649 logger.debug("registerObject: key=" + key + " value=" + value + " metadata=" + metadata);
650 if (value instanceof MuleContextAware)
651 {
652 ((MuleContextAware) value).setMuleContext(MuleServer.getMuleContext());
653 }
654 doRegisterObject(key, value, metadata);
655 }
656
657 protected abstract void doRegisterObject(String key,
658 Object value,
659 Object metadata) throws RegistrationException;
660
661 public final void registerTransformer(Transformer transformer) throws MuleException
662 {
663 if (transformer instanceof DiscoverableTransformer)
664 {
665 exactTransformerCache.clear();
666 transformerListCache.clear();
667 }
668 doRegisterTransformer(transformer);
669
670 }
671
672 protected abstract void doRegisterTransformer(Transformer transformer) throws MuleException;
673
674
675
676
677
678 public final String getRegistryId()
679 {
680 return id;
681 }
682
683 public Registry getParent()
684 {
685 return parent;
686 }
687
688 public void setParent(Registry registry)
689 {
690 this.parent = registry;
691 }
692
693 public int getDefaultScope()
694 {
695 return defaultScope;
696 }
697
698 public void setDefaultScope(int scope)
699 {
700 if (scope < SCOPE_IMMEDIATE || scope > SCOPE_REMOTE)
701 {
702 throw new IllegalArgumentException("Invalid value for scope: " + scope);
703 }
704 defaultScope = scope;
705 }
706 }