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.relay;
028:
029: import java.io.Serializable;
030: import java.util.Collections;
031: import java.util.Set;
032:
033: import org.cougaar.core.mts.MessageAddress;
034: import org.cougaar.core.util.UID;
035:
036: /**
037: * Source-side implementation of {@link SimpleRelay}, which creates
038: * the {@link SimpleRelayTarget} on the target's blackboard.
039: * <p>
040: * Note that this class, {@link SimpleRelaySource}, and the
041: * target-side implementation, {@link SimpleRelayTarget}, could be
042: * easily merged into a single "SimpleRelayImpl" class. However,
043: * in practice this tends to cause implementation bugs in similar
044: * relays, due to aliasing and confusion over the ownership of the
045: * instance fields. In particular, developers often incorrectly
046: * attempt to share fields between the source and target, or allow the
047: * source to modify the target's "reply" field or vice versa, which
048: * leads to tricky race condition bugs. Also, note that two agents
049: * within the same node will share (alias) the same "SimpleRelayImpl"
050: * if the relay itself is used as the content and the factory is
051: * either null or simply casts the content back into the
052: * "SimpleRelayImpl". Lastly, there are known bugs for relays that
053: * implement both source and target, specificially if they use ABA
054: * targets or attempt to "chain" multiple relays together across many
055: * agents. For the purposes of this example and most relay
056: * implementations, it's best to separate the source and target relay
057: * class implementations and not implement both APIs in a single
058: * class.
059: */
060: public final class SimpleRelaySource extends SimpleRelayBase implements
061: Relay.Source {
062:
063: private Set targets;
064: private Relay.TargetFactory factory;
065:
066: // constructor:
067: public SimpleRelaySource(UID uid, MessageAddress source,
068: MessageAddress target, Object query) {
069: super (uid, source, target);
070: // set initial query value, which can be null
071: this .query = query;
072: // the relay API wants a set of targets, so we save one
073: targets = Collections.singleton(target);
074: // our factory to create the target-side instance
075: factory = new MyFactory(target);
076: }
077:
078: // prevent "setReply", since this is the source-side instance.
079: // Only "updateResponse" from the target can change the reply.
080: public void setReply(Object reply) {
081: throw new UnsupportedOperationException(
082: "Unable to modify the reply on the sender-side, "
083: + " it can only be modified at the target ("
084: + target + ")");
085: }
086:
087: // implement Relay.Source:
088: public Set getTargets() {
089: return targets;
090: }
091:
092: public Object getContent() {
093: return query;
094: }
095:
096: public Relay.TargetFactory getTargetFactory() {
097: return factory;
098: }
099:
100: public int updateResponse(MessageAddress target, Object response) {
101: this .reply = response;
102: return Relay.RESPONSE_CHANGE;
103: }
104:
105: // factory method, which creates the target-side instance:
106: private static class MyFactory implements Relay.TargetFactory,
107: Serializable {
108: private final MessageAddress target;
109:
110: public MyFactory(MessageAddress target) {
111: this .target = target;
112: }
113:
114: public Relay.Target create(UID uid, MessageAddress source,
115: Object content, Relay.Token token) {
116: Object query = content;
117: return new SimpleRelayTarget(uid, source, target, query);
118: }
119: }
120: }
|