View Javadoc

1   package cz.cuni.amis.pogamut.base.utils.jmx;
2   
3   import java.io.ObjectInputStream;
4   import java.util.HashSet;
5   import java.util.Iterator;
6   import java.util.Set;
7   
8   import javax.management.Attribute;
9   import javax.management.AttributeList;
10  import javax.management.AttributeNotFoundException;
11  import javax.management.InstanceAlreadyExistsException;
12  import javax.management.InstanceNotFoundException;
13  import javax.management.IntrospectionException;
14  import javax.management.InvalidAttributeValueException;
15  import javax.management.ListenerNotFoundException;
16  import javax.management.MBeanException;
17  import javax.management.MBeanInfo;
18  import javax.management.MBeanRegistrationException;
19  import javax.management.MBeanServer;
20  import javax.management.MBeanServerFactory;
21  import javax.management.NotCompliantMBeanException;
22  import javax.management.NotificationFilter;
23  import javax.management.NotificationListener;
24  import javax.management.ObjectInstance;
25  import javax.management.ObjectName;
26  import javax.management.OperationsException;
27  import javax.management.QueryExp;
28  import javax.management.ReflectionException;
29  import javax.management.loading.ClassLoaderRepository;
30  
31  import cz.cuni.amis.utils.HashCode;
32  import cz.cuni.amis.utils.NullCheck;
33  import cz.cuni.amis.utils.SafeEquals;
34  
35  /**
36   * Wrapper of the {@link MBeanServer} interface, that is using to store references of
37   * registered mbeans and listeners allowing to unregister/register them again using
38   * {@link PogamutMBeanServer#unregisterAll()} and {@link PogamutMBeanServer#registerAll()}.
39   * 
40   * @author Jimmy
41   *
42   */
43  public class PogamutMBeanServer implements MBeanServer {
44  	
45  	private static interface RegisteredListener {
46  		public void register() throws InstanceNotFoundException;
47  		public void unregister();
48  	}
49  	
50  	private static interface RegisteredMBean {
51  		public void register() throws InstanceNotFoundException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException;
52  		public void unregister();
53  	}
54  	
55  	private class Listener1 implements RegisteredListener {
56  		
57  		private ObjectName name;
58  		private ObjectName listener;
59  		private NotificationFilter filter;
60  		private Object handback;
61  
62  		private int hashCode;
63  
64  		public Listener1(ObjectName name,
65  				ObjectName listener, NotificationFilter filter, Object handback) {
66  			this.name = name;
67  			this.listener = listener;
68  			this.filter = filter;
69  			this.handback = handback;
70  			HashCode hc = new HashCode();
71  			hc.add(name);
72  			hc.add(listener);
73  			hc.add(filter);
74  			hc.add(handback);
75  			this.hashCode = hc.getHash();
76  		}
77  		
78  		@Override
79  		public int hashCode() {
80  			return hashCode;
81  		}
82  		
83  		public boolean equals(Object o) {
84  			if (o == null) return false;
85  			if (!(o instanceof Listener1)) return false;
86  			Listener1 l = (Listener1)o;
87  			return SafeEquals.equals(name, l.name) && SafeEquals.equals(listener, l.listener) && SafeEquals.equals(filter, l.filter) && SafeEquals.equals(handback, l.handback);
88  		}
89  		
90  		@Override
91  		public void unregister() {
92  			try {
93  				innerRemoveNotificationListener(name, listener, filter, handback);
94  			} catch (Exception e) {				
95  			}
96  		}
97  		
98  		public void register() throws InstanceNotFoundException {
99  			innerAddNotificationListener(name, listener, filter, handback);
100 		}
101 		
102 		@Override
103 		public String toString() {
104 			return "Listener1[name=" + name + ", listener=" + listener + "]";
105 		}
106 
107 	}
108 	
109 	private class Listener2 implements RegisteredListener {
110 		
111 		private ObjectName name;
112 		private NotificationListener listener;
113 		private NotificationFilter filter;
114 		private Object handback;
115 
116 		private int hashCode;
117 
118 		public Listener2(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) {
119 			this.name = name;
120 			this.listener = listener;
121 			this.filter = filter;
122 			this.handback = handback;
123 			HashCode hc = new HashCode();
124 			hc.add(name);
125 			hc.add(listener);
126 			hc.add(filter);
127 			hc.add(handback);
128 			this.hashCode = hc.getHash();
129 		}
130 		
131 		@Override
132 		public int hashCode() {
133 			return hashCode;
134 		}
135 		
136 		public boolean equals(Object o) {
137 			if (o == null) return false;
138 			if (!(o instanceof Listener2)) return false;
139 			Listener2 l = (Listener2)o;
140 			return SafeEquals.equals(name, l.name) && SafeEquals.equals(listener, l.listener) && SafeEquals.equals(filter, l.filter) && SafeEquals.equals(handback, l.handback);
141 		}
142 		
143 		@Override
144 		public void unregister() {
145 			try {
146 				innerRemoveNotificationListener(name, listener, filter, handback);
147 			} catch (Exception e) {				
148 			}
149 		}
150 		
151 		public void register() throws InstanceNotFoundException {
152 			innerAddNotificationListener(name, listener, filter, handback);
153 		}
154 		
155 		@Override
156 		public String toString() {
157 			return "Listener2[name=" + name + ", listener=" + listener + "]";
158 		}
159 		
160 	}
161 	
162 	private class MBean1 implements RegisteredMBean {
163 
164 		private ObjectName name;
165 		private Object mBean;
166 		private int hashCode;
167 
168 		public MBean1(ObjectName name, Object bean) {
169 			this.name = name;
170 			this.mBean = bean;
171 			HashCode hc = new HashCode();
172 			hc.add(name);
173 			this.hashCode = hc.getHash();
174 		}
175 		
176 		@Override
177 		public int hashCode() {
178 			return hashCode;
179 		}
180 		
181 		@Override
182 		public boolean equals(Object obj) {
183 			if (obj == null) return false;
184 			if (!(obj instanceof MBean1)) return false;
185 			MBean1 mBean = (MBean1)obj;
186 			return SafeEquals.equals(name, mBean.name);
187 		}
188 		
189 		@Override
190 		public void register() throws InstanceNotFoundException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
191 			innerRegisterMBean(mBean, name);
192 		}
193 
194 		@Override
195 		public void unregister() {
196 			try {
197 				innerUnregisterMBean(name);
198 			} catch (Exception e) {				
199 			}
200 		}
201 		
202 		@Override
203 		public String toString() {
204 			return "MBean1[name=" + name + ", object=" + mBean + "]";
205 		}
206 
207 		
208 	}
209 	
210 	private MBeanServer mbs;
211 	
212 	private Set<RegisteredMBean> unregisteredMBeans = new HashSet<RegisteredMBean>(); 
213 	
214 	private Set<RegisteredMBean> mBeans = new HashSet<RegisteredMBean>();
215 	
216 	private Set<RegisteredListener> unregisteredListeners = new HashSet<RegisteredListener>();
217 	
218 	private Set<RegisteredListener> listeners = new HashSet<RegisteredListener>();
219 	
220 	private Set<Listener1> listeners1 = new HashSet<Listener1>();
221 	
222 	private Set<Listener2> listeners2 = new HashSet<Listener2>();
223 
224 	public PogamutMBeanServer() {
225 		this(MBeanServerFactory.createMBeanServer());
226 	}
227 	
228 	public PogamutMBeanServer(MBeanServer mBeanServer) {
229 		this.mbs = mBeanServer;
230 		NullCheck.check(this.mbs, "mBeanServer");
231 	}
232 	
233 	public synchronized void clearSaved() {
234 		unregisteredMBeans.clear();
235 		unregisteredListeners.clear();		
236 	}
237 	
238 	/**
239 	 * Unreagister all listeners and mbeans from the server.
240 	 */
241 	public synchronized void unregisterAll() {
242 		Iterator<RegisteredListener> iter1 = listeners.iterator();
243 		while (iter1.hasNext()) {
244 			RegisteredListener listener = iter1.next();
245 			listener.unregister();
246 			iter1.remove();
247 			unregisteredListeners.add(listener);
248 		}
249 		Iterator<RegisteredMBean> iter2 = mBeans.iterator();
250 		while (iter2.hasNext()) {
251 			RegisteredMBean mBean = iter2.next();
252 			mBean.unregister();
253 			unregisteredMBeans.add(mBean);
254 			iter2.remove();
255 		}	
256 	}
257 	
258 	public synchronized void registerAll() throws InstanceNotFoundException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
259 		Iterator<RegisteredMBean> iter1 = unregisteredMBeans.iterator();
260 		while (iter1.hasNext()) {
261 			RegisteredMBean mBean = iter1.next();
262 			mBean.register();
263 			iter1.remove();
264 			mBeans.add(mBean);
265 		}
266 		Iterator<RegisteredListener> iter2 = unregisteredListeners.iterator();
267 		while (iter2.hasNext()) {
268 			RegisteredListener listener = iter2.next();
269 			listener.register();
270 			iter2.remove();
271 			if (listener instanceof Listener1) {
272 				listeners1.add((Listener1) listener);
273 			} else {
274 				listeners2.add((Listener2) listener);
275 			}
276 		}
277 	}
278 
279 	@Override
280 	public synchronized void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter,
281 			Object handback) throws InstanceNotFoundException {		
282 		mbs.addNotificationListener(name, listener, filter, handback);
283 		Listener2 l = new Listener2(name, listener, filter, handback);
284 		listeners.add(l);
285 		listeners2.add(l);
286 	}
287 	
288 	private synchronized void innerAddNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter,
289 			Object handback) throws InstanceNotFoundException {		
290 		mbs.addNotificationListener(name, listener, filter, handback);		
291 	}
292 
293 	@Override
294 	public synchronized void addNotificationListener(ObjectName name, ObjectName listener,
295 			NotificationFilter filter, Object handback)
296 			throws InstanceNotFoundException {
297 		mbs.addNotificationListener(name, listener, filter, handback);
298 		Listener1 l = new Listener1(name, listener, filter, handback);
299 		listeners.add(l);
300 		listeners1.add(l);
301 	}
302 	
303 	private synchronized void innerAddNotificationListener(ObjectName name, ObjectName listener,
304 			NotificationFilter filter, Object handback)
305 			throws InstanceNotFoundException {
306 		mbs.addNotificationListener(name, listener, filter, handback);
307 	}
308 
309 	@Override
310 	public synchronized ObjectInstance createMBean(String className, ObjectName name)
311 			throws ReflectionException, InstanceAlreadyExistsException,
312 			MBeanRegistrationException, MBeanException,
313 			NotCompliantMBeanException {
314 		throw new UnsupportedOperationException("Not supported by PogamutMBeanServer yet...");
315 	}
316 
317 	@Override
318 	public synchronized ObjectInstance createMBean(String className, ObjectName name,
319 			ObjectName loaderName) throws ReflectionException,
320 			InstanceAlreadyExistsException, MBeanRegistrationException,
321 			MBeanException, NotCompliantMBeanException,
322 			InstanceNotFoundException {
323 		throw new UnsupportedOperationException("Not supported by PogamutMBeanServer yet...");
324 	}
325 
326 	@Override
327 	public synchronized ObjectInstance createMBean(String className, ObjectName name,
328 			Object[] params, String[] signature) throws ReflectionException,
329 			InstanceAlreadyExistsException, MBeanRegistrationException,
330 			MBeanException, NotCompliantMBeanException {
331 		throw new UnsupportedOperationException("Not supported by PogamutMBeanServer yet...");
332 	}
333 
334 	@Override
335 	public synchronized ObjectInstance createMBean(String className, ObjectName name,
336 			ObjectName loaderName, Object[] params, String[] signature)
337 			throws ReflectionException, InstanceAlreadyExistsException,
338 			MBeanRegistrationException, MBeanException,
339 			NotCompliantMBeanException, InstanceNotFoundException {
340 		throw new UnsupportedOperationException("Not supported by PogamutMBeanServer yet...");		
341 	}
342 
343 	@Deprecated
344 	@Override
345 	public ObjectInputStream deserialize(ObjectName name, byte[] data)
346 			throws InstanceNotFoundException, OperationsException {
347 		return mbs.deserialize(name, data);
348 	}
349 
350 	@Deprecated
351 	@Override
352 	public ObjectInputStream deserialize(String className, byte[] data)
353 			throws OperationsException, ReflectionException {
354 		return mbs.deserialize(className, data);
355 	}
356 
357 	@Deprecated
358 	@Override
359 	public ObjectInputStream deserialize(String className,
360 			ObjectName loaderName, byte[] data)
361 			throws InstanceNotFoundException, OperationsException,
362 			ReflectionException {
363 		return mbs.deserialize(className, loaderName, data);
364 	}
365 
366 	@Override
367 	public Object getAttribute(ObjectName name, String attribute)
368 			throws MBeanException, AttributeNotFoundException,
369 			InstanceNotFoundException, ReflectionException {
370 		return mbs.getAttribute(name, attribute);
371 	}
372 
373 	@Override
374 	public AttributeList getAttributes(ObjectName name, String[] attributes)
375 			throws InstanceNotFoundException, ReflectionException {
376 		return mbs.getAttributes(name, attributes);
377 	}
378 
379 	@Override
380 	public ClassLoader getClassLoader(ObjectName loaderName)
381 			throws InstanceNotFoundException {
382 		return mbs.getClassLoader(loaderName);
383 	}
384 
385 	@Override
386 	public ClassLoader getClassLoaderFor(ObjectName mbeanName)
387 			throws InstanceNotFoundException {
388 		return mbs.getClassLoaderFor(mbeanName);
389 	}
390 
391 	@Override
392 	public ClassLoaderRepository getClassLoaderRepository() {
393 		return mbs.getClassLoaderRepository();
394 	}
395 
396 	@Override
397 	public String getDefaultDomain() {
398 		return mbs.getDefaultDomain();
399 	}
400 
401 	@Override
402 	public String[] getDomains() {
403 		return mbs.getDomains();
404 	}
405 
406 	@Override
407 	public Integer getMBeanCount() {
408 		return mbs.getMBeanCount();
409 	}
410 
411 	@Override
412 	public MBeanInfo getMBeanInfo(ObjectName name)
413 			throws InstanceNotFoundException, IntrospectionException,
414 			ReflectionException {
415 		return mbs.getMBeanInfo(name);
416 	}
417 
418 	@Override
419 	public ObjectInstance getObjectInstance(ObjectName name)
420 			throws InstanceNotFoundException {
421 		return mbs.getObjectInstance(name);
422 	}
423 
424 	@Override
425 	public Object instantiate(String className) throws ReflectionException,
426 			MBeanException {
427 		return mbs.instantiate(className);
428 	}
429 
430 	@Override
431 	public Object instantiate(String className, ObjectName loaderName)
432 			throws ReflectionException, MBeanException,
433 			InstanceNotFoundException {
434 		return mbs.instantiate(className, loaderName);
435 	}
436 
437 	@Override
438 	public Object instantiate(String className, Object[] params,
439 			String[] signature) throws ReflectionException, MBeanException {
440 		return mbs.instantiate(className, params, signature);
441 	}
442 
443 	@Override
444 	public Object instantiate(String className, ObjectName loaderName,
445 			Object[] params, String[] signature) throws ReflectionException,
446 			MBeanException, InstanceNotFoundException {
447 		return mbs.instantiate(className, loaderName, params, signature);
448 	}
449 
450 	@Override
451 	public Object invoke(ObjectName name, String operationName,
452 			Object[] params, String[] signature)
453 			throws InstanceNotFoundException, MBeanException,
454 			ReflectionException {
455 		return mbs.invoke(name, operationName, params, signature);
456 	}
457 
458 	@Override
459 	public boolean isInstanceOf(ObjectName name, String className)
460 			throws InstanceNotFoundException {
461 		return mbs.isInstanceOf(name, className);
462 	}
463 
464 	@Override
465 	public boolean isRegistered(ObjectName name) {
466 		return mbs.isRegistered(name);
467 	}
468 
469 	@Override
470 	public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
471 		return mbs.queryMBeans(name, query);
472 	}
473 
474 	@Override
475 	public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
476 		return mbs.queryNames(name, query);
477 	}
478 
479 	@Override
480 	public synchronized ObjectInstance registerMBean(Object object, ObjectName name)
481 			throws InstanceAlreadyExistsException, MBeanRegistrationException,
482 			NotCompliantMBeanException {		
483 		ObjectInstance obj = mbs.registerMBean(object, name);
484 		mBeans.add(new MBean1(name, object));
485 		unregisteredMBeans.remove(new MBean1(name, object));
486 		return obj;
487 	}
488 	
489 	private synchronized ObjectInstance innerRegisterMBean(Object object, ObjectName name)
490 			throws InstanceAlreadyExistsException, MBeanRegistrationException,
491 			NotCompliantMBeanException {		
492 		return mbs.registerMBean(object, name);
493 	}	
494 
495 	@Override
496 	public synchronized void removeNotificationListener(ObjectName name, ObjectName listener)
497 			throws InstanceNotFoundException, ListenerNotFoundException {
498 		mbs.removeNotificationListener(name, listener);
499 
500 		// TODO: slow implementation ... but fast one takes a lot of time to do :-)
501 		Iterator<Listener1> iter = listeners1.iterator();
502 		while(iter.hasNext()) {
503 			Listener1 l = iter.next();
504 			if (SafeEquals.equals(name, l.name) && SafeEquals.equals(listener, l.listener)) {
505 				listeners.remove(l);
506 				unregisteredListeners.remove(l);
507 				iter.remove();
508 			}
509 		}		
510 	}
511 	
512 	@Override
513 	public synchronized void removeNotificationListener(ObjectName name,
514 			NotificationListener listener) throws InstanceNotFoundException,
515 			ListenerNotFoundException {		
516 		mbs.removeNotificationListener(name, listener);
517 		
518 		// TODO: slow implementation ... but fast one takes a lot of time to do :-)
519 		Iterator<Listener2> iter = listeners2.iterator();
520 		while(iter.hasNext()) {
521 			Listener2 l = iter.next();
522 			if (SafeEquals.equals(name, l.name) && SafeEquals.equals(listener, l.listener)) {
523 				listeners.remove(l);
524 				unregisteredListeners.remove(l);
525 				iter.remove();
526 			}
527 		}
528 	}
529 
530 	@Override
531 	public synchronized void removeNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback)
532 			throws InstanceNotFoundException, ListenerNotFoundException {
533 		mbs.removeNotificationListener(name, listener, filter, handback);
534 		Listener1 l = new Listener1(name, listener, filter, handback);
535 		listeners.remove(l);
536 		listeners1.remove(l);
537 		unregisteredListeners.remove(l);
538 	}
539 	
540 	private synchronized void innerRemoveNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback)
541 			throws InstanceNotFoundException, ListenerNotFoundException {
542 		mbs.removeNotificationListener(name, listener, filter, handback);
543 	}
544 
545 	@Override
546 	public synchronized void removeNotificationListener(ObjectName name,	NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException,
547 			ListenerNotFoundException {		
548 		mbs.removeNotificationListener(name, listener, filter, handback);
549 		Listener2 l = new Listener2(name, listener, filter, handback);
550 		listeners.remove(l);
551 		listeners2.remove(l);
552 		unregisteredListeners.remove(l);
553 	}
554 	
555 	private synchronized void innerRemoveNotificationListener(ObjectName name,	NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException,
556 			ListenerNotFoundException {		
557 		mbs.removeNotificationListener(name, listener, filter, handback);
558 	}
559 
560 	@Override
561 	public void setAttribute(ObjectName name, Attribute attribute)
562 			throws InstanceNotFoundException, AttributeNotFoundException,
563 			InvalidAttributeValueException, MBeanException, ReflectionException {
564 		mbs.setAttribute(name, attribute);
565 	}
566 
567 	@Override
568 	public AttributeList setAttributes(ObjectName name, AttributeList attributes)
569 			throws InstanceNotFoundException, ReflectionException {
570 		return mbs.setAttributes(name, attributes);
571 	}
572 
573 	@Override
574 	public synchronized void unregisterMBean(ObjectName name)
575 			throws InstanceNotFoundException, MBeanRegistrationException {		
576 		mbs.unregisterMBean(name);
577 		mBeans.remove(new MBean1(name, null));
578 		unregisteredMBeans.remove(new MBean1(name, null));
579 	}
580 	
581 	private synchronized void innerUnregisterMBean(ObjectName name)
582 			throws InstanceNotFoundException, MBeanRegistrationException {		
583 		mbs.unregisterMBean(name);
584 	}
585 
586 }