001: /*
002: * <copyright>
003: *
004: * Copyright 2001-2007 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.node;
028:
029: import java.util.List;
030: import org.cougaar.core.component.Component;
031: import org.cougaar.core.component.ServiceAvailableEvent;
032: import org.cougaar.core.component.ServiceAvailableListener;
033: import org.cougaar.core.component.ServiceBroker;
034: import org.cougaar.core.service.LoggingService;
035: import org.cougaar.core.util.Reflection;
036: import org.cougaar.util.GenericStateModelAdapter;
037:
038: /**
039: * This component can be used to export an internal service out to an
040: * external framework.
041: * <p>
042: * For example, the {@link NodeApplet} uses this component to get the
043: * {@link NodeControlService}.
044: * <p>
045: * Two parameters are required:<br>
046: * 1) The Service class or classname, which can be {@link ServiceBroker}.<br>
047: * 2) The {@link GetServiceCallback} listener, which can be<br>
048: * specified as a class, classname, or instance.<br>
049: * A third parameter is optional:<br>
050: * 3) The service requestor, or "this" for this component, which<br>
051: * defaults to "this".<br>
052: * A fourth parameter is optional:<br>
053: * 4) Use a late-binding service listener if the service is not<br>
054: * available at load time, defaults to "true".<br>
055: * <p>
056: * Reflection is used to wrap the callback as the GetServiceCallback API, even
057: * if it doesn't implement that API. This allows an external client to
058: * specify:<pre>
059: * public class MyCallback {
060: * public void setService(Class cl, Object service) {..}
061: * }
062: * </pre>
063: * even though "MyCallback instanceof GetServiceCallback" is false. This is
064: * supported to avoid awkward compile and classloader dependencies.
065: */
066: public class GetServiceComponent extends GenericStateModelAdapter
067: implements Component {
068:
069: private ServiceBroker sb;
070: private List params;
071:
072: private LoggingService log;
073:
074: private Class cl;
075: private boolean is_sb;
076: private Object svc;
077: private GetServiceCallback cb;
078: private Object req;
079:
080: public void setServiceBroker(ServiceBroker sb) {
081: this .sb = sb;
082: }
083:
084: public void setParameter(Object o) {
085: if (!(o instanceof List)) {
086: throw new IllegalArgumentException("Expecting a List, not "
087: + (o == null ? "null" : o.getClass().getName()));
088: }
089: params = (List) o;
090: }
091:
092: public void load() {
093: super .load();
094:
095: log = (LoggingService) sb.getService(this ,
096: LoggingService.class, null);
097: if (log == null) {
098: log = LoggingService.NULL;
099: }
100:
101: try {
102: _load();
103: } catch (Exception e) {
104: throw new RuntimeException("Unable to load " + this , e);
105: }
106: }
107:
108: private void _load() throws Exception {
109: // extract parameters
110: int n = (params == null ? 0 : params.size());
111: if (n < 2 || n > 4) {
112: throw new RuntimeException(
113: "Expecting 2..4 parameters, not " + n);
114: }
115: Object cl_obj = params.get(0);
116: Object cb_obj = params.get(1);
117: Object req_obj = (n > 2 ? params.get(2) : null);
118: Object is_late_obj = (n > 3 ? params.get(3) : "true");
119:
120: // get class
121: if (cl_obj instanceof String) {
122: cl_obj = Class.forName((String) cl_obj);
123: }
124: if (!(cl_obj instanceof Class)) {
125: throw new RuntimeException(
126: "Expecting a Class or String, not " + cl_obj);
127: }
128: cl = (Class) cl_obj;
129: is_sb = ServiceBroker.class.isAssignableFrom(cl);
130:
131: // get callback
132: if (cb_obj == null) {
133: throw new RuntimeException("Null callback_object");
134: }
135: if (cb_obj instanceof String) {
136: cb_obj = Class.forName((String) cb_obj);
137: }
138: if (cb_obj instanceof Class) {
139: cb_obj = ((Class) cb_obj).newInstance();
140: }
141: if (!(cb_obj instanceof GetServiceCallback)) {
142: cb_obj = Reflection.makeProxy(cb_obj,
143: GetServiceCallback.class);
144: }
145: cb = (GetServiceCallback) cb_obj;
146:
147: // get requestor, which is typically "this"
148: if (req_obj == null || "this".equals(req_obj) || is_sb) {
149: req_obj = this ;
150: }
151: if (req_obj instanceof String) {
152: req_obj = Class.forName((String) req_obj);
153: }
154: if (req_obj instanceof Class) {
155: req_obj = ((Class) req_obj).newInstance();
156: }
157: req = req_obj;
158:
159: // get service
160: if (is_sb || sb.hasService(cl)) {
161: // found it
162: svc = (is_sb ? sb : sb.getService(req, cl, null));
163: cb.setService(cl, svc);
164: return;
165: }
166: if (!"true".equals(is_late_obj)) {
167: // fail
168: cb.setService(cl, null);
169: return;
170: }
171: // listen
172: ServiceAvailableListener sal = new ServiceAvailableListener() {
173: public void serviceAvailable(ServiceAvailableEvent ae) {
174: if (cl.isAssignableFrom(ae.getService())) {
175: svc = sb.getService(req, cl, null);
176: cb.setService(cl, svc);
177: //sb.removeServiceListener(this);
178: }
179: }
180: };
181: sb.addServiceListener(sal);
182: }
183:
184: public void unload() {
185: if (svc != null) {
186: try {
187: cb.setService(cl, null);
188: } catch (Exception e) {
189: }
190: if (!is_sb) {
191: sb.releaseService(req, cl, svc);
192: }
193: svc = null;
194: }
195:
196: cl = null;
197: cb = null;
198: req = null;
199:
200: if (log != null && log != LoggingService.NULL) {
201: sb.releaseService(this , LoggingService.class, log);
202: log = null;
203: }
204:
205: super.unload();
206: }
207: }
|