001: /*
002: * <copyright>
003: *
004: * Copyright 2002-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:
027: package org.cougaar.core.adaptivity;
028:
029: import org.cougaar.core.agent.service.alarm.Alarm;
030: import org.cougaar.core.component.Service;
031: import org.cougaar.core.component.ServiceBroker;
032: import org.cougaar.core.plugin.ComponentPlugin;
033: import org.cougaar.core.service.LoggingService;
034:
035: /**
036: * Convenience base class for plugins that need to acquire services
037: * that may not be immediately available when first started. Records
038: * the service classes needed and attempts acquire them on request.
039: * <p>Also provides timer services.
040: **/
041: public abstract class ServiceUserPluginBase extends ComponentPlugin {
042: private Class[] serviceClasses;
043:
044: private boolean[] serviceAcquired;
045:
046: private boolean allServicesAcquired = false;
047:
048: private Alarm timer;
049:
050: /**
051: * Everybody needs a logger, so we provide it here.
052: **/
053: protected LoggingService logger;
054:
055: /**
056: * Constructor
057: * @param serviceClasses the service classes needed for this plugin
058: * to operate.
059: **/
060: protected ServiceUserPluginBase(Class[] serviceClasses) {
061: this .serviceClasses = serviceClasses;
062: this .serviceAcquired = new boolean[serviceClasses.length];
063: }
064:
065: /**
066: * Override to get a logger on load
067: **/
068: public void load() {
069: super .load();
070: logger = (LoggingService) getServiceBroker().getService(this ,
071: LoggingService.class, null);
072: }
073:
074: /**
075: * Override to release a logger on load
076: **/
077: public void unload() {
078: if (logger != null) {
079: getServiceBroker().releaseService(this ,
080: LoggingService.class, logger);
081: logger = null;
082: }
083: super .unload();
084: }
085:
086: /**
087: * Test if all services specified in the constructor are available.
088: * Sub-classes should call this method from their setupSubscriptions
089: * and execute methods until it returns true. Once this method
090: * returns true, the services should be requested and normal
091: * operation started. Once all the services are available, this
092: * method simply returns true. See <code>haveServices()</code> in
093: * {@link ConditionServiceProvider#execute} for a typical
094: * usage pattern.
095: **/
096: protected boolean acquireServices() {
097: cancelTimer();
098: if (!allServicesAcquired) {
099: allServicesAcquired = true; // Assume we will get them all
100: ServiceBroker sb = getServiceBroker();
101: for (int i = 0; i < serviceClasses.length; i++) {
102: if (!serviceAcquired[i]) {
103: Service svc = (Service) sb.getService(this ,
104: serviceClasses[i], null);
105: if (svc == null) {
106: allServicesAcquired = false;
107: break;
108: }
109: if (logger.isDebugEnabled())
110: logger.debug(serviceClasses[i] + " acquired");
111: serviceAcquired[i] = true;
112: sb.releaseService(this , serviceClasses[i], svc);
113: }
114: }
115: if (!allServicesAcquired) {
116: startTimer(1000L);
117: }
118: }
119: return allServicesAcquired;
120: }
121:
122: /**
123: * Test if the timer has expired.
124: * @return false if the timer is not running or has not yet expired
125: * else return true.
126: **/
127: protected boolean timerExpired() {
128: return timer != null && timer.hasExpired();
129: }
130:
131: /**
132: * Schedule a update wakeup after some interval of time
133: * @param delay how long to delay before the timer expires.
134: **/
135: protected void startTimer(final long delay) {
136: if (timer != null)
137: return; // update already scheduled
138: if (logger.isDebugEnabled())
139: logger.debug("Starting timer " + delay);
140: timer = new Alarm() {
141: long expirationTime = System.currentTimeMillis() + delay;
142: boolean expired = false;
143:
144: public long getExpirationTime() {
145: return expirationTime;
146: }
147:
148: public synchronized void expire() {
149: if (!expired) {
150: expired = true;
151: org.cougaar.core.service.BlackboardService bbs = getBlackboardService();
152: if (bbs != null)
153: bbs.signalClientActivity();
154: }
155: }
156:
157: public boolean hasExpired() {
158: return expired;
159: }
160:
161: public synchronized boolean cancel() {
162: boolean was = expired;
163: expired = true;
164: return was;
165: }
166: };
167: getAlarmService().addRealTimeAlarm(timer);
168: }
169:
170: /**
171: * Cancel the timer.
172: **/
173: protected void cancelTimer() {
174: if (timer == null)
175: return;
176: if (logger.isDebugEnabled())
177: logger.debug("Cancelling timer");
178: timer.cancel();
179: timer = null;
180: }
181: }
|