1
2
3
4
5
6
7 package org.mule.registry;
8
9 import org.mule.api.MuleContext;
10 import org.mule.api.MuleException;
11 import org.mule.api.agent.Agent;
12 import org.mule.api.endpoint.ImmutableEndpoint;
13 import org.mule.api.lifecycle.Disposable;
14 import org.mule.api.lifecycle.InitialisationException;
15 import org.mule.api.model.Model;
16 import org.mule.api.registry.InjectProcessor;
17 import org.mule.api.registry.MuleRegistry;
18 import org.mule.api.registry.ObjectProcessor;
19 import org.mule.api.registry.PreInitProcessor;
20 import org.mule.api.registry.RegistrationException;
21 import org.mule.api.service.Service;
22 import org.mule.api.transformer.Transformer;
23 import org.mule.api.transport.Connector;
24 import org.mule.config.i18n.MessageFactory;
25 import org.mule.lifecycle.phases.NotInLifecyclePhase;
26 import org.mule.util.CollectionUtils;
27 import org.mule.util.StringUtils;
28
29 import java.util.Collection;
30 import java.util.HashMap;
31 import java.util.Map;
32 import java.util.Map.Entry;
33 import java.util.Set;
34 import java.util.concurrent.locks.Lock;
35 import java.util.concurrent.locks.ReadWriteLock;
36 import java.util.concurrent.locks.ReentrantReadWriteLock;
37
38 import org.apache.commons.collections.Predicate;
39 import org.apache.commons.collections.functors.InstanceofPredicate;
40 import org.apache.commons.logging.Log;
41
42
43
44
45
46 public class TransientRegistry extends AbstractRegistry
47 {
48 public static final String REGISTRY_ID = "org.mule.Registry.Transient";
49
50 private final RegistryMap registryMap = new RegistryMap(logger);
51
52 public TransientRegistry(MuleContext muleContext)
53 {
54 this(REGISTRY_ID, muleContext);
55 }
56
57 public TransientRegistry(String id, MuleContext muleContext)
58 {
59 super(id, muleContext);
60 putDefaultEntriesIntoRegistry();
61 }
62
63 private void putDefaultEntriesIntoRegistry()
64 {
65 Map<String, Object> processors = new HashMap<String, Object>();
66 processors.put("_muleContextProcessor", new MuleContextProcessor(muleContext));
67
68 processors.put("_muleExpressionEvaluatorProcessor", new ExpressionEvaluatorProcessor(muleContext));
69 processors.put("_muleExpressionEnricherProcessor", new ExpressionEnricherProcessor(muleContext));
70 processors.put("_muleLifecycleStateInjectorProcessor", new LifecycleStateInjectorProcessor(getLifecycleManager().getState()));
71 processors.put("_muleLifecycleManager", getLifecycleManager());
72 registryMap.putAll(processors);
73 }
74
75 @Override
76 protected void doInitialise() throws InitialisationException
77 {
78 applyProcessors(lookupObjects(Connector.class), null);
79 applyProcessors(lookupObjects(Transformer.class), null);
80 applyProcessors(lookupObjects(ImmutableEndpoint.class), null);
81 applyProcessors(lookupObjects(Agent.class), null);
82 applyProcessors(lookupObjects(Model.class), null);
83 applyProcessors(lookupObjects(Service.class), null);
84 applyProcessors(lookupObjects(Object.class), null);
85 }
86
87 @Override
88 protected void doDispose()
89 {
90 registryMap.clear();
91 }
92
93 protected Map<String, Object> applyProcessors(Map<String, Object> objects)
94 {
95 if (objects == null)
96 {
97 return null;
98 }
99
100 Map<String, Object> results = new HashMap<String, Object>();
101 for (Map.Entry<String, Object> entry : objects.entrySet())
102 {
103
104 Collection<ObjectProcessor> processors = lookupObjects(ObjectProcessor.class);
105 for (ObjectProcessor processor : processors)
106 {
107 Object result = processor.process(entry.getValue());
108 if (result != null)
109 {
110 results.put(entry.getKey(), result);
111 }
112 }
113 }
114 return results;
115 }
116
117
118 public void registerObjects(Map<String, Object> objects) throws RegistrationException
119 {
120 if (objects == null)
121 {
122 return;
123 }
124
125 for (Map.Entry<String, Object> entry : objects.entrySet())
126 {
127 registerObject(entry.getKey(), entry.getValue());
128 }
129 }
130
131 @SuppressWarnings("unchecked")
132 public <T> Map<String, T> lookupByType(Class<T> type)
133 {
134 final Map<String, T> results = new HashMap<String, T>();
135 try
136 {
137 registryMap.lockForReading();
138
139 for (Map.Entry<String, Object> entry : registryMap.entrySet())
140 {
141 final Class<?> clazz = entry.getValue().getClass();
142 if (type.isAssignableFrom(clazz))
143 {
144 results.put(entry.getKey(), (T) entry.getValue());
145 }
146 }
147 }
148 finally
149 {
150 registryMap.unlockForReading();
151 }
152
153 return results;
154 }
155
156 public <T> T lookupObject(String key)
157 {
158 return registryMap.<T>get(key);
159 }
160
161 @SuppressWarnings("unchecked")
162 public <T> Collection<T> lookupObjects(Class<T> returntype)
163 {
164 return (Collection<T>) registryMap.select(new InstanceofPredicate(returntype));
165 }
166
167
168
169
170
171
172
173
174
175
176 Object applyLifecycle(Object object) throws MuleException
177 {
178 getLifecycleManager().applyCompletedPhases(object);
179 return object;
180 }
181
182 Object applyLifecycle(Object object, String phase) throws MuleException
183 {
184 getLifecycleManager().applyPhase(object, NotInLifecyclePhase.PHASE_NAME, phase);
185 return object;
186 }
187
188 Object applyProcessors(Object object, Object metadata)
189 {
190 Object theObject = object;
191
192 if(!hasFlag(metadata, MuleRegistry.INJECT_PROCESSORS_BYPASS_FLAG))
193 {
194
195 Collection<InjectProcessor> injectProcessors = lookupObjects(InjectProcessor.class);
196 for (InjectProcessor processor : injectProcessors)
197 {
198 theObject = processor.process(theObject);
199 }
200 }
201
202 if(!hasFlag(metadata, MuleRegistry.PRE_INIT_PROCESSORS_BYPASS_FLAG))
203 {
204
205 Collection<PreInitProcessor> processors = lookupObjects(PreInitProcessor.class);
206 for (PreInitProcessor processor : processors)
207 {
208 theObject = processor.process(theObject);
209 if(theObject==null)
210 {
211 return null;
212 }
213 }
214 }
215 return theObject;
216 }
217
218
219
220
221
222
223
224 public void registerObject(String key, Object value) throws RegistrationException
225 {
226 registerObject(key, value, Object.class);
227 }
228
229
230
231
232 public void registerObject(String key, Object object, Object metadata) throws RegistrationException
233 {
234 checkDisposed();
235 if (StringUtils.isBlank(key))
236 {
237 throw new RegistrationException(MessageFactory.createStaticMessage("Attempt to register object with no key"));
238 }
239
240 if (logger.isDebugEnabled())
241 {
242 logger.debug(String.format("registering key/object %s/%s", key, object));
243 }
244
245 logger.debug("applying processors");
246 object = applyProcessors(object, metadata);
247 if (object == null)
248 {
249 return;
250 }
251
252 registryMap.putAndLogWarningIfDuplicate(key, object);
253
254 try
255 {
256 if (!hasFlag(metadata, MuleRegistry.LIFECYCLE_BYPASS_FLAG))
257 {
258 if(logger.isDebugEnabled())
259 {
260 logger.debug("applying lifecycle to object: " + object);
261 }
262 getLifecycleManager().applyCompletedPhases(object);
263 }
264 }
265 catch (MuleException e)
266 {
267 throw new RegistrationException(e);
268 }
269 }
270
271 protected void checkDisposed() throws RegistrationException
272 {
273 if(getLifecycleManager().isPhaseComplete(Disposable.PHASE_NAME))
274 {
275 throw new RegistrationException(MessageFactory.createStaticMessage("Cannot register objects on the registry as the context is disposed"));
276 }
277 }
278
279 protected boolean hasFlag(Object metaData, int flag)
280 {
281 return !(metaData == null || !(metaData instanceof Integer)) && ((Integer) metaData & flag) != 0;
282 }
283
284
285
286
287
288
289
290
291
292
293 public void unregisterObject(String key, Object metadata) throws RegistrationException
294 {
295 Object obj = registryMap.remove(key);
296
297 try
298 {
299 if (!hasFlag(metadata, MuleRegistry.LIFECYCLE_BYPASS_FLAG))
300 {
301 getLifecycleManager().applyPhase(obj, lifecycleManager.getCurrentPhase(), Disposable.PHASE_NAME);
302 }
303 }
304 catch (MuleException e)
305 {
306 throw new RegistrationException(e);
307 }
308
309 }
310
311 public void unregisterObject(String key) throws RegistrationException
312 {
313 unregisterObject(key, Object.class);
314 }
315
316
317
318
319
320 public boolean isReadOnly()
321 {
322 return false;
323 }
324
325 public boolean isRemote()
326 {
327 return false;
328 }
329
330
331
332
333
334
335 private static class RegistryMap
336 {
337 private final Map<String, Object> registry = new HashMap<String, Object>();
338 private final ReadWriteLock registryLock = new ReentrantReadWriteLock();
339
340 private Log logger;
341
342 public RegistryMap(Log log)
343 {
344 super();
345 logger = log;
346 }
347
348 public Collection<?> select(Predicate predicate)
349 {
350 Lock readLock = registryLock.readLock();
351 try
352 {
353 readLock.lock();
354 return CollectionUtils.select(registry.values(), predicate);
355 }
356 finally
357 {
358 readLock.unlock();
359 }
360 }
361
362 public void clear()
363 {
364 Lock writeLock = registryLock.writeLock();
365 try
366 {
367 writeLock.lock();
368 registry.clear();
369 }
370 finally
371 {
372 writeLock.unlock();
373 }
374 }
375
376 public void putAndLogWarningIfDuplicate(String key, Object object)
377 {
378 Lock writeLock = registryLock.writeLock();
379 try
380 {
381 writeLock.lock();
382
383 if (registry.containsKey(key))
384 {
385
386
387
388 logger.warn("TransientRegistry already contains an object named '" + key + "'. The previous object will be overwritten.");
389 }
390 registry.put(key, object);
391 }
392 finally
393 {
394 writeLock.unlock();
395 }
396 }
397
398 public void putAll(Map<String, Object> map)
399 {
400 Lock writeLock = registryLock.writeLock();
401 try
402 {
403 writeLock.lock();
404 registry.putAll(map);
405 }
406 finally
407 {
408 writeLock.unlock();
409 }
410 }
411
412 @SuppressWarnings("unchecked")
413 public <T> T get(String key)
414 {
415 Lock readLock = registryLock.readLock();
416 try
417 {
418 readLock.lock();
419 return (T) registry.get(key);
420 }
421 finally
422 {
423 readLock.unlock();
424 }
425 }
426
427 public Object remove(String key)
428 {
429 Lock writeLock = registryLock.writeLock();
430 try
431 {
432 writeLock.lock();
433 return registry.remove(key);
434 }
435 finally
436 {
437 writeLock.unlock();
438 }
439 }
440
441 public Set<Entry<String, Object>> entrySet()
442 {
443 return registry.entrySet();
444 }
445
446 public void lockForReading()
447 {
448 registryLock.readLock().lock();
449 }
450
451 public void unlockForReading()
452 {
453 registryLock.readLock().unlock();
454 }
455 }
456 }