001: package org.jacorb.notification.servant;
002:
003: /*
004: * JacORB - a free Java ORB
005: *
006: * Copyright (C) 1999-2004 Gerald Brose
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Library General Public
010: * License as published by the Free Software Foundation; either
011: * version 2 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Library General Public License for more details.
017: *
018: * You should have received a copy of the GNU Library General Public
019: * License along with this library; if not, write to the Free
020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
021: *
022: */
023:
024: import java.lang.ref.WeakReference;
025: import java.util.ArrayList;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.Map;
030:
031: import org.apache.avalon.framework.configuration.Configuration;
032: import org.apache.avalon.framework.logger.Logger;
033: import org.jacorb.notification.FilterManager;
034: import org.jacorb.notification.IContainer;
035: import org.jacorb.notification.MessageFactory;
036: import org.jacorb.notification.OfferManager;
037: import org.jacorb.notification.SubscriptionManager;
038: import org.jacorb.notification.container.PicoContainerFactory;
039: import org.jacorb.notification.interfaces.Disposable;
040: import org.jacorb.notification.interfaces.FilterStage;
041: import org.jacorb.notification.interfaces.JMXManageable;
042: import org.jacorb.notification.interfaces.ProxyEvent;
043: import org.jacorb.notification.interfaces.ProxyEventListener;
044: import org.jacorb.notification.lifecycle.IServantLifecyle;
045: import org.jacorb.notification.lifecycle.ServantLifecyleControl;
046: import org.jacorb.notification.util.DisposableManager;
047: import org.jacorb.notification.util.QoSPropertySet;
048: import org.omg.CORBA.OBJECT_NOT_EXIST;
049: import org.omg.CORBA.ORB;
050: import org.omg.CosNotification.NamedPropertyRangeSeqHolder;
051: import org.omg.CosNotification.Property;
052: import org.omg.CosNotification.QoSAdminOperations;
053: import org.omg.CosNotification.UnsupportedQoS;
054: import org.omg.CosNotifyChannelAdmin.AdminLimitExceeded;
055: import org.omg.CosNotifyChannelAdmin.EventChannel;
056: import org.omg.CosNotifyChannelAdmin.InterFilterGroupOperator;
057: import org.omg.CosNotifyChannelAdmin.ProxyNotFound;
058: import org.omg.CosNotifyFilter.Filter;
059: import org.omg.CosNotifyFilter.FilterAdminOperations;
060: import org.omg.CosNotifyFilter.FilterNotFound;
061: import org.omg.CosNotifyFilter.MappingFilter;
062: import org.omg.PortableServer.POA;
063: import org.picocontainer.MutablePicoContainer;
064:
065: import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
066: import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
067:
068: /**
069: * Abstract Baseclass for Adminobjects.
070: *
071: * @jmx.mbean
072: * @jboss.xmbean
073: *
074: * @author Alphonse Bendt
075: * @version $Id: AbstractAdmin.java,v 1.23 2006/05/23 10:40:35 alphonse.bendt Exp $
076: */
077:
078: public abstract class AbstractAdmin implements QoSAdminOperations,
079: FilterAdminOperations, FilterStage, IServantLifecyle,
080: JMXManageable {
081: private static final class ITypedAdminImpl implements ITypedAdmin {
082: private final IAdmin admin_;
083:
084: private final MutablePicoContainer container_;
085:
086: private final String supportedInterface_;
087:
088: private ITypedAdminImpl(IAdmin admin,
089: MutablePicoContainer container,
090: String supportedInterface) {
091: super ();
092:
093: admin_ = admin;
094: container_ = container;
095: supportedInterface_ = supportedInterface;
096: }
097:
098: public String getSupportedInterface() {
099: return supportedInterface_;
100: }
101:
102: public int getProxyID() {
103: return admin_.getProxyID();
104: }
105:
106: public boolean isIDPublic() {
107: return admin_.isIDPublic();
108: }
109:
110: public MutablePicoContainer getContainer() {
111: return admin_.getContainer();
112: }
113:
114: public void destroy() {
115: container_.unregisterComponent(ITypedAdmin.class);
116: admin_.destroy();
117: }
118:
119: public String getAdminMBean() {
120: return admin_.getAdminMBean();
121: }
122: }
123:
124: /**
125: * the default InterFilterGroupOperator used.
126: */
127: protected static final InterFilterGroupOperator DEFAULT_FILTER_GROUP_OPERATOR = InterFilterGroupOperator.AND_OP;
128:
129: ////////////////////////////////////////
130:
131: private final DisposableManager disposables_ = new DisposableManager();
132:
133: private final Integer id_;
134:
135: private InterFilterGroupOperator filterGroupOperator_;
136:
137: protected final MutablePicoContainer container_;
138:
139: private final FilterManager filterManager_;
140:
141: private final WeakReference eventChannelReference_;
142:
143: private final QoSPropertySet qosSettings_;
144:
145: private final MessageFactory messageFactory_;
146:
147: protected final OfferManager offerManager_;
148:
149: protected final SubscriptionManager subscriptionManager_;
150:
151: protected final Logger logger_;
152:
153: private final ORB orb_;
154:
155: private final POA poa_;
156:
157: protected final Object modifyProxiesLock_ = new Object();
158:
159: protected final Map pullServants_ = new HashMap();
160:
161: protected final Map pushServants_ = new HashMap();
162:
163: private final AtomicInteger proxyIdPool_ = new AtomicInteger(0);
164:
165: private final AtomicBoolean disposed_ = new AtomicBoolean(false);
166:
167: private final List proxyEventListener_ = new ArrayList();
168:
169: private final int channelID_;
170:
171: private final String parentMBean_;
172:
173: private JMXManageable.JMXCallback jmxCallback_;
174:
175: protected final ServantLifecyleControl servantLifecycle_;
176:
177: ////////////////////////////////////////
178:
179: protected AbstractAdmin(IEventChannel channel, ORB orb, POA poa,
180: Configuration config, MessageFactory messageFactory,
181: OfferManager offerManager,
182: SubscriptionManager subscriptionManager) {
183: parentMBean_ = channel.getChannelMBean();
184:
185: container_ = channel.getContainer();
186:
187: id_ = new Integer(channel.getAdminID());
188:
189: orb_ = orb;
190: poa_ = poa;
191: messageFactory_ = messageFactory;
192: filterManager_ = new FilterManager();
193:
194: eventChannelReference_ = new WeakReference(channel
195: .getEventChannel());
196:
197: channelID_ = channel.getChannelID();
198:
199: logger_ = ((org.jacorb.config.Configuration) config)
200: .getNamedLogger(getClass().getName());
201:
202: qosSettings_ = new QoSPropertySet(config,
203: QoSPropertySet.ADMIN_QOS);
204:
205: offerManager_ = offerManager;
206:
207: subscriptionManager_ = subscriptionManager;
208:
209: servantLifecycle_ = new ServantLifecyleControl(this , config);
210: }
211:
212: public final void registerDisposable(Disposable disposable) {
213: disposables_.addDisposable(disposable);
214: }
215:
216: public void setInterFilterGroupOperator(
217: InterFilterGroupOperator operator) {
218: filterGroupOperator_ = operator;
219: }
220:
221: public final POA getPOA() {
222: return poa_;
223: }
224:
225: protected ORB getORB() {
226: return orb_;
227: }
228:
229: protected MessageFactory getMessageFactory() {
230: return messageFactory_;
231: }
232:
233: int getProxyID() {
234: return proxyIdPool_.getAndIncrement();
235: }
236:
237: public List getFilters() {
238: return filterManager_.getFilters();
239: }
240:
241: public int add_filter(Filter aFilter) {
242: return filterManager_.add_filter(aFilter);
243: }
244:
245: public void remove_filter(int aFilterId) throws FilterNotFound {
246: filterManager_.remove_filter(aFilterId);
247: }
248:
249: public Filter get_filter(int aFilterId) throws FilterNotFound {
250: return filterManager_.get_filter(aFilterId);
251: }
252:
253: public int[] get_all_filters() {
254: return filterManager_.get_all_filters();
255: }
256:
257: public void remove_all_filters() {
258: filterManager_.remove_all_filters();
259: }
260:
261: public final InterFilterGroupOperator MyOperator() {
262: return filterGroupOperator_;
263: }
264:
265: public final EventChannel MyChannel() {
266: return (EventChannel) eventChannelReference_.get();
267: }
268:
269: public final int MyID() {
270: return getID().intValue();
271: }
272:
273: public final int getChannelID() {
274: return channelID_;
275: }
276:
277: public Property[] get_qos() {
278: return qosSettings_.get_qos();
279: }
280:
281: public void set_qos(Property[] props) throws UnsupportedQoS {
282: if (logger_.isDebugEnabled()) {
283: logger_.debug("AbstractAdmin.set_qos: " + qosSettings_);
284: }
285: qosSettings_.validate_qos(props,
286: new NamedPropertyRangeSeqHolder());
287:
288: qosSettings_.set_qos(props);
289: }
290:
291: public void validate_qos(Property[] props,
292: NamedPropertyRangeSeqHolder propertyRangeSeqHolder)
293: throws UnsupportedQoS {
294: qosSettings_.validate_qos(props, propertyRangeSeqHolder);
295: }
296:
297: /**
298: * @jmx.managed-operation description = "Destroy this Admin" impact = "ACTION"
299: */
300: public final void destroy() {
301: checkDestroyStatus();
302:
303: container_.dispose();
304:
305: List list = container_
306: .getComponentInstancesOfType(IContainer.class);
307:
308: for (Iterator i = list.iterator(); i.hasNext();) {
309: IContainer element = (IContainer) i.next();
310: element.destroy();
311: }
312: }
313:
314: private void checkDestroyStatus() throws OBJECT_NOT_EXIST {
315: if (!disposed_.compareAndSet(false, true)) {
316: throw new OBJECT_NOT_EXIST();
317: }
318: }
319:
320: public void dispose() {
321: logger_.info("destroy Admin " + MyID());
322:
323: //////////////////////////////
324:
325: deactivate();
326:
327: //////////////////////////////
328:
329: remove_all_filters();
330:
331: //////////////////////////////
332:
333: disposables_.dispose();
334:
335: proxyEventListener_.clear();
336: }
337:
338: public final org.omg.CORBA.Object activate() {
339: return servantLifecycle_.activate();
340: }
341:
342: public final void deactivate() {
343: servantLifecycle_.deactivate();
344: }
345:
346: /**
347: * @jmx.managed-attribute description="TODO"
348: * access = "read-only"
349: * currencyTimeLimit = "2147483647"
350: */
351: public Integer getID() {
352: return id_;
353: }
354:
355: public boolean isDestroyed() {
356: return disposed_.get();
357: }
358:
359: protected void fireCreateProxyRequestEvent()
360: throws AdminLimitExceeded {
361: synchronized (proxyEventListener_) {
362: final ProxyEvent _event = new ProxyEvent(this );
363: final Iterator _i = proxyEventListener_.iterator();
364:
365: while (_i.hasNext()) {
366: final ProxyEventListener _listener = (ProxyEventListener) _i
367: .next();
368: _listener.actionProxyCreationRequest(_event);
369: }
370: }
371: }
372:
373: /**
374: * admin does never have a lifetime filter
375: */
376: public boolean hasLifetimeFilter() {
377: return false;
378: }
379:
380: /**
381: * admin does never have a priority filter
382: */
383: public boolean hasPriorityFilter() {
384: return false;
385: }
386:
387: /**
388: * admin does not have a lifetime filter
389: */
390: public MappingFilter getLifetimeFilter() {
391: throw new UnsupportedOperationException();
392: }
393:
394: /**
395: * admin does not have a priority filter
396: */
397: public MappingFilter getPriorityFilter() {
398: throw new UnsupportedOperationException();
399: }
400:
401: /**
402: * @jmx.managed-attribute description="TODO"
403: * access = "read-only"
404: * currencyTimeLimit = "2147483647"
405: */
406: public String getInterFilterGroupOperator() {
407: return (filterGroupOperator_.value() == InterFilterGroupOperator._AND_OP) ? "AND_OP"
408: : "OR_OP";
409: }
410:
411: public boolean hasInterFilterGroupOperatorOR() {
412: return (filterGroupOperator_.value() == InterFilterGroupOperator._OR_OP);
413: }
414:
415: /**
416: * fetch the proxy specified by the provided id. this method will not access an event style
417: * proxy.
418: */
419: protected AbstractProxy getProxy(int id) throws ProxyNotFound {
420: final Integer _id = new Integer(id);
421:
422: AbstractProxy _servant;
423:
424: synchronized (modifyProxiesLock_) {
425: _servant = (AbstractProxy) pullServants_.get(_id);
426:
427: if (_servant == null) {
428: _servant = (AbstractProxy) pushServants_.get(_id);
429: }
430: }
431:
432: if (_servant == null) {
433: throw new ProxyNotFound("The proxy with ID=" + id
434: + " does not exist");
435: }
436:
437: if (!_servant.isIDPublic()) {
438: throw new ProxyNotFound(
439: "The proxy with ID="
440: + id
441: + " is a EventStyle proxy and therefor not accessible by ID");
442: }
443:
444: return _servant;
445: }
446:
447: /**
448: * return the ID's for all NotifyStyle proxies stored in the provided Map.
449: */
450: protected int[] get_all_notify_proxies(Map map, Object lock) {
451: final List _allIDsList = new ArrayList();
452:
453: synchronized (lock) {
454: final Iterator _i = map.entrySet().iterator();
455:
456: while (_i.hasNext()) {
457: final Map.Entry _entry = (Map.Entry) _i.next();
458:
459: if (((AbstractProxy) _entry.getValue()).isIDPublic()) {
460: _allIDsList.add(_entry.getKey());
461: }
462: }
463: }
464:
465: final int[] _allIDsArray = new int[_allIDsList.size()];
466:
467: for (int x = 0; x < _allIDsArray.length; ++x) {
468: _allIDsArray[x] = ((Integer) _allIDsList.get(x)).intValue();
469: }
470:
471: return _allIDsArray;
472: }
473:
474: /**
475: * configure initial QoS Settings for a proxy.
476: */
477: protected void configureQoS(AbstractProxy proxy)
478: throws UnsupportedQoS {
479: logger_.debug("configure new AbstractProxy with "
480: + qosSettings_);
481: proxy.set_qos(qosSettings_.get_qos());
482: }
483:
484: /**
485: * configure the InterFilterGroupOperator a proxy should use.
486: */
487: protected void configureInterFilterGroupOperator(AbstractProxy proxy) {
488: if (filterGroupOperator_.value() == InterFilterGroupOperator._OR_OP) {
489: proxy.setInterFilterGroupOperatorOR(true);
490: }
491: }
492:
493: public void addProxyEventListener(ProxyEventListener l) {
494: synchronized (proxyEventListener_) {
495: proxyEventListener_.add(l);
496: }
497: }
498:
499: public void removeProxyEventListener(ProxyEventListener listener) {
500: synchronized (proxyEventListener_) {
501: proxyEventListener_.remove(listener);
502: }
503: }
504:
505: void fireProxyRemoved(AbstractProxy proxy) {
506: synchronized (proxyEventListener_) {
507: Iterator i = proxyEventListener_.iterator();
508: ProxyEvent e = new ProxyEvent(proxy);
509:
510: while (i.hasNext()) {
511: ((ProxyEventListener) i.next()).actionProxyDisposed(e);
512: }
513: }
514: }
515:
516: private void fireProxyCreated(AbstractProxy proxy) {
517: synchronized (proxyEventListener_) {
518: Iterator i = proxyEventListener_.iterator();
519: ProxyEvent e = new ProxyEvent(proxy);
520:
521: while (i.hasNext()) {
522: ((ProxyEventListener) i.next()).actionProxyCreated(e);
523: }
524: }
525: }
526:
527: protected void addProxyToMap(final AbstractProxy proxy,
528: final Map map, final Object lock) {
529: synchronized (lock) {
530: map.put(proxy.getID(), proxy);
531: fireProxyCreated(proxy);
532: }
533:
534: // it removes proxy from map again.
535: proxy.registerDisposable(new Disposable() {
536: public void dispose() {
537: synchronized (lock) {
538: map.remove(proxy.getID());
539:
540: fireProxyRemoved(proxy);
541: }
542: }
543: });
544: }
545:
546: protected MutablePicoContainer newContainerForNotifyStyleProxy() {
547: return newContainerForProxy(true);
548: }
549:
550: protected MutablePicoContainer newContainerForEventStyleProxy() {
551: return newContainerForProxy(false);
552: }
553:
554: protected MutablePicoContainer newContainerForTypedProxy(
555: final String supportedInterface) {
556: final MutablePicoContainer _container = newContainerForNotifyStyleProxy();
557:
558: final IAdmin _admin = (IAdmin) _container
559: .getComponentInstanceOfType(IAdmin.class);
560:
561: final ITypedAdmin _typedAdmin = new ITypedAdminImpl(_admin,
562: _container, supportedInterface);
563:
564: _container.registerComponentInstance(ITypedAdmin.class,
565: _typedAdmin);
566:
567: return _container;
568: }
569:
570: private MutablePicoContainer newContainerForProxy(boolean isIDPublic) {
571: final int _proxyID = getProxyID();
572:
573: return newContainerForProxy(_proxyID, isIDPublic);
574: }
575:
576: private MutablePicoContainer newContainerForProxy(
577: final int proxyID, final boolean isIDPublic) {
578: final MutablePicoContainer _containerForProxy = PicoContainerFactory
579: .createChildContainer(container_);
580:
581: final IAdmin _admin = new IAdmin() {
582: public MutablePicoContainer getContainer() {
583: return _containerForProxy;
584: }
585:
586: public int getProxyID() {
587: return proxyID;
588: }
589:
590: public boolean isIDPublic() {
591: return isIDPublic;
592: }
593:
594: public void destroy() {
595: container_.removeChildContainer(_containerForProxy);
596: }
597:
598: public String getAdminMBean() {
599: return getJMXObjectName();
600: }
601: };
602:
603: _containerForProxy.registerComponentInstance(IAdmin.class,
604: _admin);
605:
606: return _containerForProxy;
607: }
608:
609: public final String getJMXObjectName() {
610: return parentMBean_ + ", admin=" + getMBeanName();
611: }
612:
613: public final String getMBeanName() {
614: return getMBeanType() + "-" + getID();
615: }
616:
617: abstract protected String getMBeanType();
618:
619: public String[] getJMXNotificationTypes() {
620: return new String[0];
621: }
622:
623: public final void setJMXCallback(JMXManageable.JMXCallback callback) {
624: jmxCallback_ = callback;
625: }
626:
627: protected final void sendNotification(String type, String message) {
628: if (jmxCallback_ != null) {
629: jmxCallback_.sendJMXNotification(type, message);
630: }
631: }
632: }
|