001: /*
002: * <copyright>
003: *
004: * Copyright 1997-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.agent;
028:
029: import java.lang.reflect.Method;
030: import java.net.URL;
031: import java.util.ArrayList;
032: import java.util.Arrays;
033: import java.util.Collection;
034: import java.util.Collections;
035: import java.util.LinkedList;
036: import java.util.List;
037: import org.cougaar.core.component.Component;
038: import org.cougaar.core.component.ComponentDescription;
039: import org.cougaar.core.component.ComponentDescriptions;
040: import org.cougaar.core.component.Service;
041: import org.cougaar.core.component.ServiceBroker;
042: import org.cougaar.core.component.ServiceProvider;
043: import org.cougaar.core.mts.MessageAddress;
044: import org.cougaar.core.service.AgentContainmentService;
045: import org.cougaar.core.service.AgentIdentificationService;
046: import org.cougaar.core.util.Reflection;
047: import org.cougaar.util.GenericStateModel;
048:
049: /**
050: * AgentImpl is the base class for all agents.
051: * <p>
052: * An agent starts with a single "bootstrap" component that uses
053: * the AgentBootstrapService to specify the subsequent agent
054: * components.
055: */
056: public class AgentImpl extends Agent {
057:
058: private static final String DEFAULT_BOOTSTRAP_CLASSNAME = "org.cougaar.core.agent.Bootstrap";
059:
060: // from "setParameter(..)", cleared in "load()"
061: private List params;
062:
063: private String agentName;
064:
065: /** Alias for getMessageAddress, required by Agent superclass */
066: public MessageAddress getAgentIdentifier() {
067: return MessageAddress.getMessageAddress(agentName);
068: }
069:
070: /**
071: * Required parameter, minimally our agent name.
072: */
073: public void setParameter(Object param) {
074: Object o = param;
075: if (o instanceof Object[]) {
076: o = Arrays.asList((Object[]) o);
077: }
078: if (o != null && !(o instanceof List)) {
079: o = Collections.singletonList(o);
080: }
081: params = (List) o;
082: }
083:
084: // disable super load sequence
085: protected void loadHighPriorityComponents() {
086: }
087:
088: protected void loadInternalPriorityComponents() {
089: }
090:
091: protected void loadBinderPriorityComponents() {
092: }
093:
094: protected void loadComponentPriorityComponents() {
095: }
096:
097: protected void loadLowPriorityComponents() {
098: }
099:
100: protected ComponentDescriptions findInitialComponentDescriptions() {
101: return null;
102: }
103:
104: protected ComponentDescriptions findExternalComponentDescriptions() {
105: return null;
106: }
107:
108: public Object getState() {
109: return null;
110: }
111:
112: public void setState(Object o) {
113: }
114:
115: public void load() {
116: // can't call super.load()!
117: transitState("load()", UNLOADED, LOADED);
118:
119: // take parameters
120: List p = params;
121: params = null;
122: int pn = (p == null ? 0 : p.size());
123:
124: // first parameter is our bootstrap (typically just our agent name)
125: ComponentDescription bootstrap_desc = (pn > 0 ? getBootstrapDescription(p
126: .get(0))
127: : null);
128:
129: // the remaining parameters are external components
130: List ext = (pn > 1 ? p.subList(1, pn) : null);
131:
132: add_agent_state_model_service();
133: add_agent_containment_service();
134: add_agent_component_model_service();
135:
136: List l = new LinkedList();
137:
138: ServiceProvider sp = add_agent_bootstrap_service(l);
139:
140: add_external_components(ext);
141:
142: // start with a bootstrap component, which must use our
143: // AgentBootstrapService to add more components that we
144: // will load
145: l.add(bootstrap_desc);
146:
147: while (!l.isEmpty()) {
148: Object o = l.get(0);
149: l.remove(0);
150: if (o != null) {
151: // add component, may change our list!
152: add(o);
153: }
154: }
155:
156: // done loading
157: revoke_agent_bootstrap_service(sp);
158:
159: // get our agent's name for our deprecated "getAgentIdentifier()" method
160: record_agent_name(bootstrap_desc);
161: }
162:
163: private List parse_external_components(Object obj) {
164: Object o = obj;
165: if (o instanceof Object[]) {
166: o = Arrays.asList((Object[]) o);
167: }
168: if (o != null && !(o instanceof List)) {
169: o = Collections.singletonList(o);
170: }
171: return (List) o;
172: }
173:
174: private ComponentDescription getBootstrapDescription(Object o) {
175: if (o instanceof ComponentDescription) {
176: // explicit comp-desc
177: return (ComponentDescription) o;
178: }
179:
180: // parse bootstrap classname and parameters
181: String name = extractAgentName(o);
182: String classname = DEFAULT_BOOTSTRAP_CLASSNAME;
183: List parameters = Collections.singletonList(name);
184: if (o instanceof List && ((List) o).size() > 1) {
185: List l = (List) o;
186: classname = (String) l.get(1);
187: if (l.size() > 2) {
188: parameters = new ArrayList(l.size());
189: parameters.add(name);
190: parameters.addAll(l.subList(2, l.size()));
191: parameters = Collections.unmodifiableList(parameters);
192: }
193: }
194:
195: // create bootstrap descriptor
196: return new ComponentDescription(classname,
197: "Node.AgentManager.Agent.Component", classname, null, //codebase
198: parameters, null, //certificate
199: null, //lease
200: null, //policy
201: ComponentDescription.PRIORITY_HIGH);
202: }
203:
204: private static String extractAgentName(Object obj) {
205: Object o = obj;
206: if (o instanceof List) {
207: List l = (List) o;
208: if (!l.isEmpty()) {
209: o = l.get(0);
210: }
211: }
212: if (o instanceof String) {
213: return (String) o;
214: } else if (o instanceof MessageAddress) {
215: return ((MessageAddress) o).getAddress();
216: } else {
217: return null;
218: }
219: }
220:
221: private ServiceProvider add_agent_state_model_service() {
222: final GenericStateModel agentModel = this ;
223: Class clazz = AgentStateModelService.class;
224: Service service = new AgentStateModelService() {
225: // forward all agent state transitions
226: public void initialize() {
227: agentModel.initialize();
228: }
229:
230: public void load() {
231: agentModel.load();
232: }
233:
234: public void start() {
235: agentModel.start();
236: }
237:
238: public void suspend() {
239: agentModel.suspend();
240: }
241:
242: public void resume() {
243: agentModel.resume();
244: }
245:
246: public void stop() {
247: agentModel.stop();
248: }
249:
250: public void halt() {
251: agentModel.halt();
252: }
253:
254: public void unload() {
255: agentModel.unload();
256: }
257:
258: public int getModelState() {
259: return agentModel.getModelState();
260: }
261: };
262: return add_service(clazz, service);
263: }
264:
265: private ServiceProvider add_agent_containment_service() {
266: final Collection agent = this ;
267: Class clazz = AgentContainmentService.class;
268: Service service = new AgentContainmentService() {
269: // forward all operations
270: public boolean add(ComponentDescription desc) {
271: return agent.add(desc);
272: }
273:
274: public boolean remove(ComponentDescription desc) {
275: return agent.remove(desc);
276: }
277:
278: public boolean contains(ComponentDescription desc) {
279: return agent.contains(desc);
280: }
281: };
282: return add_service(clazz, service);
283: }
284:
285: private ServiceProvider add_agent_component_model_service() {
286: final AgentImpl agent = this ;
287: Class clazz = AgentComponentModelService.class;
288: Service service = new AgentComponentModelService() {
289: public ComponentDescriptions getComponentDescriptions() {
290: return agent.captureState();
291: }
292: };
293: return add_service(clazz, service);
294: }
295:
296: private ServiceProvider add_agent_bootstrap_service(final List l) {
297: Class clazz = AgentBootstrapService.class;
298: Service service = new AgentBootstrapService() {
299: public void overrideComponentList(List newlist) {
300: l.clear();
301: if (newlist != null) {
302: l.addAll(newlist);
303: }
304: }
305: };
306: return add_service(clazz, service);
307: }
308:
309: private void revoke_agent_bootstrap_service(ServiceProvider sp) {
310: Class clazz = AgentBootstrapService.class;
311: revoke_service(clazz, sp);
312: }
313:
314: private void record_agent_name(ComponentDescription bootstrap_desc) {
315: ServiceBroker csb = getChildServiceBroker();
316: AgentIdentificationService ais = (AgentIdentificationService) csb
317: .getService(this , AgentIdentificationService.class,
318: null);
319: if (ais == null) {
320: this .agentName = extractAgentName(bootstrap_desc);
321: } else {
322: this .agentName = ais.getMessageAddress().getAddress();
323: csb.releaseService(this , AgentIdentificationService.class,
324: ais);
325: }
326: }
327:
328: //
329: private void add_external_components(List l) {
330: int n = (l == null ? 0 : l.size());
331: for (int i = 0; i < n; i++) {
332: Object oi = l.get(i);
333: try {
334: add_external_component(oi);
335: } catch (Exception e) {
336: throw new RuntimeException(
337: "Unable to add_external_component [" + i
338: + " / " + n + "]", e);
339: }
340: }
341: }
342:
343: //
344: private void add_external_component(Object o) throws Exception {
345: // cast parameter as list
346: List args;
347: if (o instanceof List) {
348: args = (List) o;
349: } else if (o instanceof Object[]) {
350: args = Arrays.asList((Object[]) o);
351: } else if (o instanceof String) {
352: // ignore strings
353: return;
354: } else {
355: // support comp-desc?
356: throw new RuntimeException(
357: "Expecting a List, Object[], or String, not "
358: + (o == null ? "null" : o.getClass()
359: .getName()));
360: }
361:
362: int n = (args == null ? 0 : args.size());
363: if (n < 3) {
364: throw new RuntimeException(
365: "Invalid external component definition, expecting:\n"
366: + "\n insertionPoint, priority, classname, [arg0, ..]");
367: }
368:
369: // for now, only support agent-level HIGH external components
370: Object ip = args.get(0);
371: if (!"Node.AgentManager.Agent.Component".equals(ip)) {
372: throw new RuntimeException(
373: "External component InsertionPoint must be "
374: + "Node.AgentManager.Agent.Component"
375: + ", not " + ip);
376: }
377: Object pr = args.get(1);
378: if (!"HIGH".equals(pr)) {
379: throw new RuntimeException(
380: "External component Priority must be " + "HIGH"
381: + ", not " + pr);
382: }
383:
384: Object c = args.get(2);
385: if (c instanceof String) {
386: c = Class.forName((String) c);
387: }
388: if (c instanceof Class) {
389: c = ((Class) c).newInstance();
390: }
391: if (!(c instanceof Component)) {
392: c = Reflection.makeProxy(c, Component.class);
393: }
394:
395: if (n > 2) {
396: List l = new ArrayList(args.subList(3, n));
397: Class cl = c.getClass();
398: Method m = cl.getMethod("setParameter",
399: new Class[] { Object.class });
400: m.invoke(c, new Object[] { l });
401: }
402:
403: addComponent(c, null);
404: }
405:
406: private ServiceProvider add_service(Class clazz, Service service) {
407: ServiceBroker csb = getChildServiceBroker();
408: ServiceProvider sp = new SimpleServiceProvider(clazz, service);
409: csb.addService(clazz, sp);
410: return sp;
411: }
412:
413: private void revoke_service(Class clazz, ServiceProvider sp) {
414: if (sp != null) {
415: ServiceBroker csb = getChildServiceBroker();
416: csb.revokeService(clazz, sp);
417: }
418: }
419:
420: private static final class SimpleServiceProvider implements
421: ServiceProvider {
422: private final Class clazz;
423: private final Service service;
424:
425: public SimpleServiceProvider(Class clazz, Service service) {
426: this .clazz = clazz;
427: this .service = service;
428: }
429:
430: public Object getService(ServiceBroker sb, Object requestor,
431: Class serviceClass) {
432: if (clazz.isAssignableFrom(serviceClass)) {
433: return service;
434: } else {
435: return null;
436: }
437: }
438:
439: public void releaseService(ServiceBroker sb, Object requestor,
440: Class serviceClass, Object service) {
441: }
442: }
443: }
|