001: /*
002: * <copyright>
003: *
004: * Copyright 1997-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.agent.service.community;
028:
029: import java.util.ArrayList;
030: import java.util.Collections;
031: import java.util.List;
032: import org.cougaar.core.mts.MessageAddress;
033: import org.cougaar.core.component.ComponentSupport;
034: import org.cougaar.core.service.AgentIdentificationService;
035: import org.cougaar.core.service.LoggingService;
036: import org.cougaar.core.service.community.CommunityResponse;
037: import org.cougaar.core.service.community.CommunityResponseListener;
038: import org.cougaar.core.service.community.CommunityService;
039: import org.cougaar.util.Arguments;
040:
041: /**
042: * This component makes it easy for an agent to join one or more
043: * communities at startup and leave those communities on shutdown.
044: * <p>
045: * Usage is:<pre>
046: * <component
047: * class="org.cougaar.core.agent.service.community.JoinCommunity">
048: * <argument name="community" value="X, Y, X">
049: * </componnent>
050: * </pre>
051: */
052: public class JoinCommunity extends ComponentSupport {
053:
054: private Arguments args = Arguments.EMPTY_INSTANCE;
055: private List communities = Collections.EMPTY_LIST;
056:
057: private LoggingService log;
058: private String localAgent;
059: private CommunityService cs;
060:
061: public void setParameter(Object o) {
062: args = new Arguments(o);
063: }
064:
065: public void setLoggingService(LoggingService log) {
066: this .log = log;
067: }
068:
069: public void setAgentIdentificationService(
070: AgentIdentificationService ais) {
071: MessageAddress addr = (ais == null ? null : ais
072: .getMessageAddress());
073: this .localAgent = (addr == null ? null : addr.getAddress());
074: }
075:
076: public void setCommunityService(CommunityService cs) {
077: this .cs = cs;
078: }
079:
080: public void load() {
081: super .load();
082:
083: // parse our comma-separated "community" argument, e.g.
084: // <argument name="community" value="a, b"/>
085: //
086: // TODO use
087: // getParameterValues("community")
088: // which is line-separated, e.g.
089: // <argument name="community" value="a"/>
090: // <argument name="community" value="b"/>
091: // this would require the update of our Arguments class to match
092: // org.cougaar.core.qos.metrics.ParameterizedPlugin
093: String s = args.getString("community");
094: if (s == null)
095: return;
096: String[] sa = s.split("\\s*,\\s*");
097: communities = new ArrayList(sa.length);
098: for (int i = 0; i < sa.length; i++) {
099: String si = sa[i].trim();
100: if (si.length() <= 0)
101: continue;
102: if (communities.contains(si))
103: continue;
104: communities.add(si);
105: }
106: }
107:
108: public void start() {
109: super .start();
110:
111: joinAll(communities);
112: }
113:
114: public void stop() {
115: super .stop();
116:
117: // it's not clear if we want to remove our entries if we're moving.
118: //
119: // The downside is that it'll look like a leave-then-join, which might
120: // cause unnecessary ABA relaying due to the (false) transient changes
121: // to the membership lists.
122: //
123: // However, if we keep our entries, then they'll never be removed from the
124: // membership list, even if our moved agent dies or is cleanly unloaded.
125: //
126: // So, we'll do the safe thing and remove our entries.
127: //
128: // Odds are that the caching built into the community service will hide
129: // the fact that we're doing this, so this issue is arguably moot.
130: leaveAll(communities);
131: }
132:
133: private void joinAll(List l) {
134: for (int i = 0, n = l.size(); i < n; i++) {
135: String ci = (String) l.get(i);
136: join(ci);
137: }
138: }
139:
140: private void join(String community) {
141: if (log.isInfoEnabled()) {
142: log.info("Joining community " + community);
143: }
144: cs.joinCommunity(community, localAgent, CommunityService.AGENT,
145: null, true, null, new ListenerImpl("Join", community));
146: }
147:
148: private void leaveAll(List l) {
149: for (int i = 0, n = l.size(); i < n; i++) {
150: String ci = (String) l.get(i);
151: leave(ci);
152: }
153: }
154:
155: private void leave(String community) {
156: CommunityResponseListener crl = null;
157: if (log.isInfoEnabled()) {
158: log.info("Leaving" + community);
159: }
160: cs.leaveCommunity(community, localAgent, new ListenerImpl(
161: "Leave", community));
162: }
163:
164: private class ListenerImpl implements CommunityResponseListener {
165: private final String action;
166: private final String community;
167:
168: public ListenerImpl(String action, String community) {
169: this .action = action;
170: this .community = community;
171: }
172:
173: public void getResponse(CommunityResponse res) {
174: if (log.isInfoEnabled()) {
175: String s = (res == null ? null : res
176: .getStatusAsString());
177: log.info(action + " response for community "
178: + community + " is " + s);
179: }
180: }
181: }
182: }
|