001: /*
002: * <copyright>
003: *
004: * Copyright 2000-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.core.component;
027:
028: import java.util.ArrayList;
029: import java.util.Iterator;
030:
031: /** A service broker which implements not just a local SB, but also
032: * a pass-through to another (presumably higher-level) SB.
033: **/
034:
035: public class PropagatingServiceBroker extends ServiceBrokerSupport {
036: public PropagatingServiceBroker(BindingSite bs) {
037: this (bs.getServiceBroker());
038: }
039:
040: public PropagatingServiceBroker(ServiceBroker delegate) {
041: if (delegate == null) {
042: throw new IllegalArgumentException(
043: "Delegate must be non-null");
044: }
045:
046: this .delegate = delegate;
047: connectToDelegate(delegate);
048: }
049:
050: private ServiceBroker delegate;
051: private ServiceAvailableListener availableListener;
052: private ServiceRevokedListener revokedListener;
053:
054: /**
055: * Disconnect this propagating service broker from its parent.
056: * <p>
057: * This method removes the revokation listeners, which allows
058: * the broker to be garbage-collected.
059: * <p>
060: * The expected usage is for the Container to have a private
061: * static inner-class that is a subclass of this class. The
062: * subclass should has an added method, "void myDestroy()",
063: * which simply calls "destroy()":
064: * private static class MyPropSB
065: * extends PropagatingServiceBroker {
066: * public MyPropSB(BindingSite sb) { super(sb); }
067: * private void myDestroy() { super.destroy(); }
068: * }
069: * This allows the container to call "myDestroy()" during its
070: * "unload()", but still hide this method from the child
071: * components (due to the private class access).
072: */
073: protected void destroy() {
074: disconnectFromDelegate(delegate);
075: }
076:
077: protected ServiceBroker getDelegate() {
078: return delegate;
079: }
080:
081: protected void connectToDelegate(ServiceBroker d) {
082: // listen to the delegating service and relay events to our clients.
083: if (availableListener == null) {
084: availableListener = new ServiceAvailableListener() {
085: public void serviceAvailable(ServiceAvailableEvent ae) {
086: applyListeners(new ServiceAvailableEvent(
087: PropagatingServiceBroker.this , ae
088: .getService()));
089: }
090: };
091: d.addServiceListener(availableListener);
092: }
093: if (revokedListener == null) {
094: revokedListener = new ServiceRevokedListener() {
095: public void serviceRevoked(ServiceRevokedEvent ae) {
096: applyListeners(new ServiceRevokedEvent(
097: PropagatingServiceBroker.this , ae
098: .getService()));
099: }
100: };
101: d.addServiceListener(revokedListener);
102: }
103: }
104:
105: protected void disconnectFromDelegate(ServiceBroker d) {
106: // remove our delegating listeners
107: if (availableListener != null) {
108: d.removeServiceListener(availableListener);
109: availableListener = null;
110: }
111: if (revokedListener != null) {
112: d.removeServiceListener(revokedListener);
113: revokedListener = null;
114: }
115: }
116:
117: /** is the service currently available in this broker or in the Delegate? **/
118: public boolean hasService(Class serviceClass) {
119: boolean localp = super .hasService(serviceClass);
120: return localp || delegate.hasService(serviceClass);
121: }
122:
123: /** gets the currently available services for this context.
124: * This version copies the keyset to keep the iterator safe, so don't be doing this
125: * too often.
126: **/
127: public Iterator getCurrentServiceClasses() {
128: ArrayList l = new ArrayList(); // ugh!
129: // get the local services
130: {
131: Iterator i = super .getCurrentServiceClasses();
132: while (i.hasNext()) {
133: l.add(i.next());
134: }
135: }
136: // get the delegated services
137: {
138: Iterator i = delegate.getCurrentServiceClasses();
139: while (i.hasNext()) {
140: l.add(i.next());
141: }
142: }
143: return l.iterator();
144: }
145:
146: /** get an instance of the requested service from a service provider associated
147: * with this context.
148: **/
149: public ServiceResult getService(int requestorId,
150: ComponentDescription requestorDesc, Object requestor,
151: Class serviceClass, ServiceRevokedListener srl,
152: boolean recordInView) {
153: ServiceResult sr = getServiceAllowNull(requestorId,
154: requestorDesc, requestor, serviceClass, srl,
155: recordInView);
156: Object service = (sr == null ? null : sr.getService());
157: if (service != null) {
158: if (service instanceof NullService) {
159: // blocked
160: sr = new ServiceResult(sr.getProviderId(), sr
161: .getProviderComponentDescription(), null);
162: }
163: } else {
164: // propagate
165: if (delegate instanceof ExtendedServiceBroker) {
166: ExtendedServiceBroker esb = (ExtendedServiceBroker) delegate;
167: sr = esb.getService(requestorId, requestorDesc,
168: requestor, serviceClass, srl, false); // propagation sets recordInView to false!
169: } else {
170: service = delegate.getService(requestor, serviceClass,
171: srl);
172: sr = new ServiceResult(0, null, service);
173: }
174: }
175: return sr;
176: }
177:
178: public void releaseService(int requestorId,
179: ComponentDescription requestorDesc, Object requestor,
180: Class serviceClass, Object service, boolean recordInView) {
181: synchronized (servicesLock) {
182: if (super .hasService(serviceClass)) {
183: super .releaseService(requestorId, requestorDesc,
184: requestor, serviceClass, service, recordInView);
185: return;
186: }
187: }
188: // else propagate
189: if (delegate instanceof ExtendedServiceBroker) {
190: ExtendedServiceBroker esb = (ExtendedServiceBroker) delegate;
191: esb.releaseService(requestorId, requestorDesc, requestor,
192: serviceClass, service, false); // propagation stops recordInView!
193: } else {
194: delegate.releaseService(requestor, serviceClass, service);
195: }
196: }
197:
198: public void revokeService(Class serviceClass,
199: ServiceProvider serviceProvider) {
200: synchronized (servicesLock) {
201: if (super .hasService(serviceClass)) {
202: super .revokeService(serviceClass, serviceProvider);
203: return;
204: }
205: }
206: // else propagate
207: //
208: // FIXME looks like a bug; we didn't propagate the advertisement,
209: // so why are we propagating the revocation?
210: delegate.revokeService(serviceClass, serviceProvider);
211: }
212:
213: }
|