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.mobility;
028:
029: import java.io.Serializable;
030: import java.net.URL;
031: import java.util.ArrayList;
032: import java.util.Collections;
033: import java.util.List;
034: import org.cougaar.core.agent.Agent; // inlined
035: import org.cougaar.core.component.ComponentDescription;
036: import org.cougaar.core.mts.MessageAddress;
037:
038: /**
039: * A ticket requesting agent creation.
040: */
041: public final class AddTicket extends AbstractTicket implements
042: java.io.Serializable {
043: private static final String DEFAULT_AGENT_CLASSNAME = "org.cougaar.core.agent.AgentImpl";
044: private static final String AGENT_INSERTION_POINT = Agent.INSERTION_POINT;
045:
046: private final Object id;
047: private final MessageAddress mobileAgent;
048: private final ComponentDescription desc;
049: private final MessageAddress destNode;
050: private Object state;
051:
052: // FIXME maybe add "timeout" here
053: // FIXME maybe add "clone" here + clone name
054: // FIXME maybe add security tags here
055:
056: /**
057: * Add an agent on a remote node.
058: *
059: * @param id ticket-id from the MobilityFactory
060: * @param mobileAgent agent to add
061: * @param destNode target node, or null for the local node
062: */
063: public AddTicket(Object id, MessageAddress mobileAgent,
064: MessageAddress destNode) {
065: this .id = id;
066: this .mobileAgent = validateAgentAddr(mobileAgent);
067: this .destNode = destNode;
068: this .desc = createAgentDesc(mobileAgent);
069: this .state = null;
070: }
071:
072: /** @deprecated */
073: public AddTicket(Object id, MessageAddress mobileAgent,
074: MessageAddress destNode, ComponentDescription desc,
075: Object state) {
076: this .id = id;
077: this .mobileAgent = validateAgentAddr(mobileAgent);
078: this .destNode = destNode;
079: this .desc = validateAgentDesc(mobileAgent, desc);
080: this .state = state;
081: }
082:
083: /**
084: * An optional identifier for this addticket instance.
085: * <p>
086: * The identifier <u>must</u> be serializable and should be
087: * immutable. A UID is a good identifier.
088: */
089: public Object getIdentifier() {
090: return id;
091: }
092:
093: /**
094: * The agent to be moved.
095: * <p>
096: * An agent can only pass a AddTicket to "dispatch(..)" if
097: * the agent <i>is</i> the one moving. Aside from this
098: * sanity check, tagging the ticket with the agent address
099: * aids debugging.
100: * <p>
101: * If the agent is null then the caller of the
102: * MobilityService is assumed.
103: */
104: public MessageAddress getMobileAgent() {
105: return mobileAgent;
106: }
107:
108: /**
109: * Destination node for the mobile agent.
110: * <p>
111: * If the destination node is null then the AgentControl status
112: * should be changed to FAILURE.
113: */
114: public MessageAddress getDestinationNode() {
115: return destNode;
116: }
117:
118: /**
119: * Get the new agent's ComponentDescription.
120: */
121: public ComponentDescription getComponentDescription() {
122: return desc;
123: }
124:
125: /**
126: * Get the new agent's optional mobile state.
127: */
128: public Object getState() {
129: return state;
130: }
131:
132: private static ComponentDescription createAgentDesc(Object param) {
133: return new ComponentDescription(DEFAULT_AGENT_CLASSNAME,
134: AGENT_INSERTION_POINT, DEFAULT_AGENT_CLASSNAME, null, // codebase
135: param, null, // certificate
136: null, // lease
137: null, // policy
138: ComponentDescription.PRIORITY_COMPONENT);
139: }
140:
141: private static MessageAddress validateAgentAddr(
142: MessageAddress mobileAgent) {
143: if (mobileAgent == null) {
144: throw new IllegalArgumentException(
145: "Must specify an agent to add");
146: }
147: return mobileAgent;
148: }
149:
150: private static ComponentDescription validateAgentDesc(
151: MessageAddress mobileAgent, ComponentDescription desc) {
152: if (desc == null) {
153: return createAgentDesc(mobileAgent);
154: }
155: // check the insertion point
156: String ip = desc.getInsertionPoint();
157: if (!ip.equals(AGENT_INSERTION_POINT)) {
158: throw new IllegalArgumentException(
159: "Insertion point must be \""
160: + AGENT_INSERTION_POINT + "\", not " + ip);
161: }
162: // check the agent id:
163: Object o = desc.getParameter();
164: MessageAddress cid = null;
165: if (o instanceof MessageAddress) {
166: cid = (MessageAddress) o;
167: } else if (o instanceof String) {
168: cid = MessageAddress.getMessageAddress((String) o);
169: } else if (o instanceof List) {
170: List parameters = (List) o;
171: if (parameters.size() > 0) {
172: Object o1 = parameters.get(0);
173: if (o1 instanceof MessageAddress) {
174: cid = (MessageAddress) o1;
175: } else if (o1 instanceof String) {
176: cid = MessageAddress.getMessageAddress((String) o1);
177: }
178: }
179: }
180: if (cid == null) {
181: throw new IllegalArgumentException(
182: "The ComponentDescription must specify the agent"
183: + " name as the first parameter (see SimpleAgent)");
184: }
185: if (!mobileAgent.equals(cid)) {
186: throw new IllegalArgumentException("New agent address "
187: + mobileAgent
188: + " must match the ComponentDescription's address "
189: + cid);
190: }
191: // let the remote node check the class type, since it
192: // may be a class that we don't have in our local jars.
193: return desc;
194: }
195:
196: public int hashCode() {
197: return (((id == null) ? 17 : id.hashCode()) ^ mobileAgent
198: .hashCode());
199: }
200:
201: public boolean equals(Object o) {
202: if (o == this ) {
203: return true;
204: } else if (!(o instanceof AddTicket)) {
205: return false;
206: } else {
207: AddTicket t = (AddTicket) o;
208: return ((id == null) ? (t.id == null) : (id.equals(t.id)))
209: && ((mobileAgent == null) ? (t.mobileAgent == null)
210: : (mobileAgent.equals(t.mobileAgent)))
211: && ((destNode == null) ? (t.destNode == null)
212: : (destNode.equals(t.destNode)))
213: && ((desc == null) ? (t.desc == null) : (desc
214: .equals(t.desc)))
215: && ((state == null) ? (t.state == null) : (state
216: .equals(t.state)));
217: }
218: }
219:
220: public String toString() {
221: // cache?
222: return "Add "
223: + (id == null ? " unidentified " : id)
224: + " of "
225: + (mobileAgent == null ? "this agent" : "agent \""
226: + mobileAgent + "\"")
227: + " to "
228: + (destNode == null ? "this node" : "node \""
229: + destNode + "\"") + " with " + desc
230: + (state == null ? " and state" : "");
231: }
232: }
|