001: /*
002: * <copyright>
003: * Copyright 1997-2001 Networks Associates Technology, Inc.
004: * under sponsorship of the Defense Advanced Research Projects Agency (DARPA).
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the Cougaar Open Source License as published by
008: * DARPA on the Cougaar Open Source Website (www.cougaar.org).
009: *
010: * THE COUGAAR SOFTWARE AND ANY DERIVATIVE SUPPLIED BY LICENSOR IS
011: * PROVIDED 'AS IS' WITHOUT WARRANTIES OF ANY KIND, WHETHER EXPRESS OR
012: * IMPLIED, INCLUDING (BUT NOT LIMITED TO) ALL IMPLIED WARRANTIES OF
013: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND WITHOUT
014: * ANY WARRANTIES AS TO NON-INFRINGEMENT. IN NO EVENT SHALL COPYRIGHT
015: * HOLDER BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT OR CONSEQUENTIAL
016: * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE OF DATA OR PROFITS,
017: * TORTIOUS CONDUCT, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
018: * PERFORMANCE OF THE COUGAAR SOFTWARE.
019: * </copyright>
020: * Created on September 12, 2001, 10:55 AM
021: */
022:
023: package org.cougaar.core.qos.ca;
024:
025: import org.cougaar.util.UnaryPredicate;
026: import org.cougaar.util.log.Logger;
027: import org.cougaar.util.log.Logging;
028: import org.cougaar.core.mts.MessageAddress;
029: import org.cougaar.core.service.community.Community;
030: import org.cougaar.core.service.community.CommunityResponse;
031: import org.cougaar.core.service.community.CommunityResponseListener;
032: import org.cougaar.core.service.community.CommunityService;
033: import org.cougaar.core.service.community.CommunityChangeListener;
034: import org.cougaar.core.service.community.CommunityChangeEvent;
035: import org.cougaar.core.service.community.Entity;
036:
037: import java.util.Collection;
038: import java.util.Iterator;
039: import java.util.Map;
040: import java.util.Observable;
041: import javax.naming.directory.Attribute;
042: import javax.naming.directory.Attributes;
043:
044: /**
045: * This utility class helps simplify Community lookup. For now it
046: * comes in two variants, which are inner class extensions.
047: */
048: abstract public class CommunityFinder extends Observable implements
049: CommunityResponseListener, CommunityChangeListener
050:
051: {
052: private String community_name;
053: private Community community;
054:
055: protected String filter;
056: protected UnaryPredicate predicate;
057: protected CommunityService svc;
058: protected Logger logger;
059:
060: public CommunityFinder(CommunityService svc, String filter,
061: UnaryPredicate predicate) {
062: this .svc = svc;
063: this .filter = filter;
064: this .predicate = predicate;
065: logger = Logging
066: .getLogger("org.cougaar.core.qos.ca.CommunityFinder");
067: }
068:
069: abstract public void postQuery();
070:
071: protected void go() {
072: svc.addListener(this );
073: }
074:
075: public synchronized void communityChanged(CommunityChangeEvent e) {
076: if (logger.isDebugEnabled())
077: logger.debug("CommunityChangeEvent " + e);
078: boolean repost; // only notify observers once
079: repost = this .community_name == null;
080: if (repost)
081: postQuery();
082: }
083:
084: private void getCommunity(String community_name, Community community) {
085: if (community != null) {
086: this .community = community;
087: return;
088: }
089:
090: CommunityResponseListener crl = new CommunityResponseListener() {
091: public void getResponse(CommunityResponse response) {
092: Object xxx = response.getContent();
093: if (xxx instanceof Community) {
094: CommunityFinder.this .community = (Community) xxx;
095: }
096: }
097: };
098: this .community = svc.getCommunity(community_name, crl);
099: }
100:
101: private boolean shouldNotify(Community community) {
102: return predicate == null || predicate.execute(community);
103: }
104:
105: private synchronized boolean foundCommunity(String community_name,
106: Community community) {
107: if (logger.isDebugEnabled())
108: logger.debug("Community = " + community_name);
109:
110: if (this .community_name == null) {
111: getCommunity(community_name, community);
112: if (!shouldNotify(this .community)) {
113: this .community = null;
114: return false;
115: }
116:
117: this .community_name = community_name;
118: setChanged();
119: notifyObservers(community_name);
120: clearChanged();
121: if (logger.isDebugEnabled())
122: logger.debug(countObservers()
123: + " observers notified that community="
124: + community_name);
125: }
126: return true;
127:
128: }
129:
130: protected void handleResponse(Object candidate) {
131: if (logger.isDebugEnabled())
132: logger.debug("Response was candidate " + candidate);
133: boolean remove = false;
134: if (candidate instanceof Community) {
135: Community comm = (Community) candidate;
136: remove = foundCommunity(comm.getName(), comm);
137: } else if (candidate instanceof String) {
138: remove = foundCommunity((String) candidate, null);
139: } else {
140: if (logger.isErrorEnabled())
141: logger.error("Response was " + candidate + " of class "
142: + candidate.getClass());
143: }
144: if (remove)
145: svc.removeListener(this );
146:
147: }
148:
149: protected void handleCollectionResponse(Collection result) {
150: Iterator itr = result.iterator();
151: while (itr.hasNext())
152: handleResponse(itr.next());
153: }
154:
155: public void getResponse(CommunityResponse response) {
156: if (logger.isDebugEnabled())
157: logger.debug("CommunityResponse callback "
158: + response.getStatus());
159: if (response.getStatus() == CommunityResponse.SUCCESS) {
160: Collection result = (Collection) response.getContent();
161: handleCollectionResponse(result);
162: }
163:
164: }
165:
166: public String getCommunityName() {
167: if (logger.isDebugEnabled())
168: logger.debug("getCommunityName() -> " + community_name);
169: return community_name;
170: }
171:
172: public Community getCommunity() {
173: return community;
174: }
175:
176: /**
177: * This variant of CommunityFinder is useful for finding
178: * Communities without assuming any particular Agent is a member.
179: * A filter supplied as a constructor parameter describes the
180: * community.
181: */
182: public static class ForAny extends CommunityFinder {
183: public ForAny(CommunityService svc, String filter,
184: UnaryPredicate predicate) {
185: super (svc, filter, predicate);
186: go();
187: }
188:
189: public void postQuery() {
190: if (logger.isDebugEnabled())
191: logger.debug("Posted Manager Subscription filter="
192: + filter);
193: Collection results = svc.searchCommunity(null, filter,
194: true, Community.COMMUNITIES_ONLY, this );
195: if (results != null) {
196: handleCollectionResponse(results);
197: }
198: }
199: }
200:
201: /**
202: * This variant of CommunityFinder is useful for finding
203: * Communities of which a given Agent is a member. A filter
204: * supplied as a constructor parameter describes the community.
205: */
206: public static class ForAgent extends CommunityFinder {
207: private MessageAddress agentID;
208:
209: public ForAgent(CommunityService svc, String filter,
210: UnaryPredicate predicate, MessageAddress agentID) {
211: super (svc, filter, predicate);
212: this .agentID = agentID;
213: go();
214: }
215:
216: public void postQuery() {
217: if (logger.isDebugEnabled())
218: logger.debug("Posted Member Subscription filter="
219: + filter);
220: Collection results = svc.listParentCommunities(agentID
221: .getAddress(), filter);
222: if (results != null) {
223: handleCollectionResponse(results);
224: }
225: }
226:
227: }
228:
229: /**
230: * Constructs a filter that matches one Community attribute.
231: */
232: public static String makeFilter(String attribute, String value) {
233: return "(" + attribute + "=" + value + ")";
234: }
235:
236: /**
237: * Constructs a filter that matches two Community attributes.
238: */
239: public static String makeFilter(String attribute1, String value1,
240: String attribute2, String value2) {
241: return "(&(" + attribute1 + "=" + value1 + ")(" + attribute2
242: + "=" + value2 + "))";
243: }
244:
245: /**
246: * Constructs a filter that matches N Community attributes.
247: */
248: public static String makeFilter(Map attributes) {
249: StringBuffer buff = new StringBuffer();
250: buff.append("(&");
251: Iterator itr = attributes.entrySet().iterator();
252: while (itr.hasNext()) {
253: Map.Entry entry = (Map.Entry) itr.next();
254: buff.append("(");
255: buff.append(entry.getKey());
256: buff.append("=");
257: buff.append(entry.getValue());
258: buff.append(")");
259: }
260: buff.append(")");
261: return buff.toString();
262: }
263:
264: private static class MemberHasRoleP implements UnaryPredicate {
265: String entity_name;
266: String role;
267:
268: MemberHasRoleP(String entity_name, String role) {
269: this .entity_name = entity_name;
270: this .role = role;
271: }
272:
273: public boolean execute(Object comm) {
274: Community community = (Community) comm;
275: Logger log = Logging
276: .getLogger("org.cougaar.core.qos.ca.CommunityFinder");
277: if (log.isInfoEnabled())
278: log.info("Searching for member " + entity_name
279: + " of community " + community.getName()
280: + " with role " + role);
281:
282: Entity entity = community.getEntity(entity_name);
283: boolean result = false;
284: if (entity != null) {
285: Attributes attrs = entity.getAttributes();
286: Attribute attr = attrs.get("Role");
287: result = (attr != null && attr.contains(role));
288: }
289:
290: if (log.isInfoEnabled()) {
291: log.info(result ? "Succeeded" : "Failed");
292: }
293:
294: return result;
295: }
296:
297: }
298:
299: public static UnaryPredicate memberHasRole(String entity,
300: String role) {
301: return new MemberHasRoleP(entity, role);
302: }
303:
304: }
|