Source Code Cross Referenced for CommunityServiceProvider.java in  » Science » Cougaar12_4 » org » cougaar » core » agent » service » community » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Science » Cougaar12_4 » org.cougaar.core.agent.service.community 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.net.URI;
030:        import java.util.ArrayList;
031:        import java.util.Collection;
032:        import java.util.Collections;
033:        import java.util.Iterator;
034:        import java.util.LinkedHashMap;
035:        import java.util.LinkedHashSet;
036:        import java.util.List;
037:        import java.util.Map;
038:        import java.util.Set;
039:        import javax.naming.directory.Attributes;
040:        import javax.naming.directory.ModificationItem;
041:        import org.cougaar.core.component.ComponentSupport;
042:        import org.cougaar.core.component.ServiceBroker;
043:        import org.cougaar.core.component.ServiceProvider;
044:        import org.cougaar.core.mts.MessageAddress;
045:        import org.cougaar.core.node.NodeControlService;
046:        import org.cougaar.core.service.LoggingService;
047:        import org.cougaar.core.service.ThreadService;
048:        import org.cougaar.core.service.community.Community;
049:        import org.cougaar.core.service.community.CommunityChangeEvent;
050:        import org.cougaar.core.service.community.CommunityChangeListener;
051:        import org.cougaar.core.service.community.CommunityResponse;
052:        import org.cougaar.core.service.community.CommunityResponseListener;
053:        import org.cougaar.core.service.community.CommunityService;
054:        import org.cougaar.core.service.community.Entity;
055:        import org.cougaar.core.service.community.FindCommunityCallback;
056:        import org.cougaar.core.service.wp.AddressEntry;
057:        import org.cougaar.core.service.wp.Callback;
058:        import org.cougaar.core.service.wp.Request;
059:        import org.cougaar.core.service.wp.Response;
060:        import org.cougaar.core.service.wp.WhitePagesService;
061:        import org.cougaar.core.thread.Schedulable;
062:        import org.cougaar.util.Arguments;
063:
064:        /**
065:         * This component advertises a {@link CommunityService} implementation that
066:         * uses the {@link WhitePagesService} to supports basic join, leave, and
067:         * search operations.
068:         * <p>
069:         * This implementation is sufficient to support {@link AttributeBasedAddress}
070:         * (ABA) relay targets.  Hierarchical communities are not supported.
071:         * Community members must explicitly join their community at startup, as
072:         * illustrated in the {@link JoinCommunity} helper plugin.
073:         */
074:        public class CommunityServiceProvider extends ComponentSupport {
075:
076:            // the wp is cached, so we poll at a relatively fast rate.
077:            private static final long DEFAULT_REFRESH_PERIOD = 11000;
078:
079:            // FIXME "search" can't return null on a cache miss, so we wait
080:            // a short while to help avoid false "empty" results
081:            private static final long DEFAULT_WP_TIMEOUT = 2000;
082:
083:            // our marker key for listing community names, as opposed to members
084:            private static final String ALL = "*";
085:
086:            private static final String WP_SUFFIX = ".communities";
087:            private static final String WP_TYPE = "community";
088:
089:            // our marker entry for in-progress lookups
090:            private static final Set PENDING = Collections.singleton("PENDING");
091:
092:            private Arguments args = Arguments.EMPTY_INSTANCE;
093:            private long refreshPeriod;
094:            private long wpTimeout;
095:
096:            private LoggingService log;
097:            private ThreadService threadService;
098:            private WhitePagesService wp;
099:
100:            private ServiceBroker rootsb;
101:            private ServiceProvider sp;
102:            private Schedulable thread;
103:
104:            private final Object lock = new Object();
105:            private final Map cache = new LinkedHashMap();
106:            private final List listeners = new ArrayList();
107:
108:            public void setParameter(Object o) {
109:                args = new Arguments(o);
110:            }
111:
112:            public void setLoggingService(LoggingService log) {
113:                this .log = log;
114:            }
115:
116:            public void setThreadService(ThreadService threadService) {
117:                this .threadService = threadService;
118:            }
119:
120:            public void setWhitePagesService(WhitePagesService wp) {
121:                this .wp = wp;
122:            }
123:
124:            public void load() {
125:                super .load();
126:
127:                refreshPeriod = args.getLong("refreshPeriod",
128:                        DEFAULT_REFRESH_PERIOD);
129:                wpTimeout = args.getLong("wpTimeout", DEFAULT_WP_TIMEOUT);
130:
131:                ServiceBroker sb = getServiceBroker();
132:
133:                // optional root-level sb
134:                NodeControlService ncs = (NodeControlService) sb.getService(
135:                        this , NodeControlService.class, null);
136:                if (ncs != null) {
137:                    rootsb = ncs.getRootServiceBroker();
138:                    sb.releaseService(this , NodeControlService.class, ncs);
139:                }
140:
141:                // advertise our service
142:                sp = new TrivialServiceProvider(new CommunityServiceImpl());
143:                ServiceBroker the_sb = (rootsb == null ? sb : rootsb);
144:                the_sb.addService(CommunityService.class, sp);
145:            }
146:
147:            public void start() {
148:                super .start();
149:
150:                // start our refresh thread
151:                Runnable runner = new Runnable() {
152:                    public void run() {
153:                        refresh();
154:                    }
155:                };
156:                thread = threadService.getThread(this , runner,
157:                        "CommunityService refresh poller");
158:                thread.schedule(refreshPeriod);
159:            }
160:
161:            public void stop() {
162:                super .stop();
163:
164:                // stop our refresh thread
165:                if (thread != null) {
166:                    thread.cancel();
167:                    thread = null;
168:                }
169:            }
170:
171:            public void unload() {
172:                super .unload();
173:
174:                // revoke our service
175:                if (sp != null) {
176:                    ServiceBroker the_sb = (rootsb == null ? getServiceBroker()
177:                            : rootsb);
178:                    the_sb.revokeService(CommunityService.class, sp);
179:                    sp = null;
180:                }
181:            }
182:
183:            //
184:            // the following methods are called by our CommunityServiceImpl
185:            //
186:
187:            private void add(CommunityChangeListener ccl) {
188:                synchronized (lock) {
189:                    // wrap to ensure that it's well behaved
190:                    CommunityChangeListener l = new ListenerImpl(ccl);
191:                    if (listeners.contains(l))
192:                        return;
193:                    if (log.isDebugEnabled()) {
194:                        log.debug("Add listener " + l);
195:                    }
196:                    listeners.add(l);
197:                }
198:            }
199:
200:            private void remove(CommunityChangeListener ccl) {
201:                synchronized (lock) {
202:                    CommunityChangeListener l = new ListenerImpl(ccl);
203:                    if (!listeners.contains(l))
204:                        return;
205:                    if (log.isDebugEnabled()) {
206:                        log.debug("Remove listener " + l);
207:                    }
208:                    listeners.remove(l);
209:                }
210:            }
211:
212:            // called by periodic thread
213:            private void refresh() {
214:                // get list of community names that we should refresh (null means all)
215:                Set names;
216:                synchronized (lock) {
217:                    if (listeners.isEmpty()) {
218:                        names = Collections.EMPTY_SET;
219:                    } else {
220:                        names = null;
221:                        for (int i = 0; i < listeners.size(); i++) {
222:                            CommunityChangeListener li = (CommunityChangeListener) listeners
223:                                    .get(i);
224:                            String ci = li.getCommunityName();
225:                            ci = fix(ci);
226:                            if (ci.length() == 0) {
227:                                // all
228:                                names = null;
229:                                break;
230:                            }
231:                            if (names == null) {
232:                                names = new LinkedHashSet();
233:                            }
234:                            names.add(ci);
235:                        }
236:                    }
237:
238:                    if (names != null) {
239:                        // not all
240:                        for (Iterator iter = cache.entrySet().iterator(); iter
241:                                .hasNext();) {
242:                            Map.Entry me = (Map.Entry) iter.next();
243:                            String ci = (String) me.getKey();
244:                            // remove entries we're not listening to (and are not pending)
245:                            if (!names.contains(ci)
246:                                    && (me.getValue() != PENDING)) {
247:                                iter.remove();
248:                            }
249:                        }
250:                    }
251:                }
252:
253:                if (names == null) {
254:                    // get all, force lookup
255:                    names = list(ALL, false, null);
256:                    if (names == null) {
257:                        // cache miss, we'll get it next time
258:                        names = Collections.EMPTY_SET;
259:                    }
260:                }
261:
262:                // force lookup
263:                for (Iterator iter = names.iterator(); iter.hasNext();) {
264:                    String ci = (String) iter.next();
265:                    list(ci, false, null);
266:                }
267:
268:                // wake again later
269:                if (thread != null) {
270:                    thread.schedule(refreshPeriod);
271:                }
272:            }
273:
274:            /**
275:             * @param community either ALL or a non-null, non-empty String
276:             * @return a Set of Strings if ALL, otherwise a Set of MessageAddresses
277:             *   if not ALL.  This set can be null if !useCache.
278:             */
279:            private Set list(final String community, boolean useCache,
280:                    final CommunityResponseListener crl) {
281:                // check cache
282:                Set oldC;
283:                synchronized (lock) {
284:                    oldC = (Set) cache.get(community);
285:                    if (oldC == null) {
286:                        // new lookup
287:                        cache.put(community, PENDING);
288:                    }
289:                }
290:                if (oldC != null) {
291:                    if (oldC == PENDING) {
292:                        // already in progress
293:                        return (useCache ? Collections.EMPTY_SET : null); // FIXME see below.
294:                    } else if (useCache) {
295:                        // in cache
296:                        return oldC;
297:                    } else {
298:                        // do refresh, but don't replace our cached value with PENDING
299:                    }
300:                }
301:
302:                if (log.isDebugEnabled()) {
303:                    log.debug((useCache ? "Looking up" : "Refreshing") + " "
304:                            + community);
305:                }
306:
307:                // initiate lookup
308:                String ext = WP_SUFFIX;
309:                if (community != ALL) {
310:                    ext = "." + community + WP_SUFFIX;
311:                }
312:                Callback cb = new Callback() {
313:                    public void execute(Response res) {
314:                        Set members = extractNames(res, community);
315:                        handleSearchResult(community, members, crl);
316:                    }
317:                };
318:                Response res = wp.submit(new Request.List(Request.NONE, ext),
319:                        cb);
320:
321:                // check for immediate response (i.e. in local wp cache)
322:                Set ret = extractNames(res, community);
323:                if (ret != null)
324:                    return ret;
325:
326:                if (!useCache) {
327:                    // return the stale value (null or non-PENDING)
328:                    return oldC;
329:                }
330:
331:                // FIXME the CommunityService API should return null if there's a cache
332:                // miss, otherwise the caller can't distinguish between a cache miss and
333:                // an empty/non-existent community!
334:                //
335:                // However, the CommunityService is currently defined to return an empty
336:                // set on a cache miss, and the Blackboard "lookupABA(...)" method expects
337:                // a non-null return value.
338:                //
339:                // So, for now, we must return a non-null value.
340:                if (wpTimeout > 0) {
341:                    try {
342:                        res.waitForIsAvailable(wpTimeout);
343:                    } catch (InterruptedException ie) {
344:                    }
345:                    ret = extractNames(res, community);
346:                    if (ret != null)
347:                        return ret;
348:                }
349:                return Collections.EMPTY_SET; // should be null!
350:            }
351:
352:            // convert "[A.MyComm.communities, B.MyComm.communities]" into "[A, B]"
353:            //
354:            // also works for "[.MyComm.communities]" --> "[MyComm]"
355:            private static final Set extractNames(Response res, String community) {
356:                if (!res.isSuccess())
357:                    return null;
358:                Set set = ((Response.List) res).getNames();
359:                if (set == null)
360:                    return null;
361:                if (set.isEmpty())
362:                    return Collections.EMPTY_SET;
363:                String ext = WP_SUFFIX;
364:                if (community != ALL) {
365:                    ext = "." + community + WP_SUFFIX;
366:                }
367:                Set ret = new LinkedHashSet();
368:                for (Iterator iter = set.iterator(); iter.hasNext();) {
369:                    String s = (String) iter.next();
370:                    if (!s.endsWith(ext))
371:                        continue;
372:                    s = s.substring(0, s.length() - ext.length());
373:                    Object o;
374:                    if (community == ALL) {
375:                        if (s.length() <= 1 || s.charAt(0) != '.')
376:                            continue;
377:                        s = s.substring(1);
378:                        o = s;
379:                    } else {
380:                        o = MessageAddress.getMessageAddress(s);
381:                    }
382:                    ret.add(o);
383:                }
384:                return Collections.unmodifiableSet(ret);
385:            }
386:
387:            private void handleSearchResult(String community, Set members,
388:                    CommunityResponseListener crl) {
389:
390:                // gather change listeners
391:                List l = Collections.EMPTY_LIST;
392:
393:                if (members == null) {
394:                    // lookup failed
395:                    if (log.isDebugEnabled()) {
396:                        log.debug("Lookup for " + community + " failed");
397:                    }
398:                } else {
399:                    synchronized (lock) {
400:                        Set oldC = (Set) cache.get(community);
401:
402:                        boolean changed = (oldC == PENDING || !members
403:                                .equals(oldC));
404:                        if (changed) {
405:                            // modify cache
406:                            cache.put(community, members);
407:                            if (community != ALL) {
408:                                // find interested change listeners
409:                                for (int i = 0; i < listeners.size(); i++) {
410:                                    CommunityChangeListener li = (CommunityChangeListener) listeners
411:                                            .get(i);
412:                                    String ci = li.getCommunityName();
413:                                    ci = fix(ci);
414:                                    if (ci.length() == 0
415:                                            || ci.equals(community)) {
416:                                        if (l.isEmpty()) {
417:                                            l = new ArrayList();
418:                                        }
419:                                        l.add(li);
420:                                    }
421:                                }
422:                            }
423:                        }
424:
425:                        if (log.isDebugEnabled()) {
426:                            log
427:                                    .debug("Lookup for "
428:                                            + community
429:                                            + " found "
430:                                            + (!changed ? "no change"
431:                                                    : (((oldC == null || oldC == PENDING) ? "initial"
432:                                                            : "modified")
433:                                                            + " membership list["
434:                                                            + members.size()
435:                                                            + "]:\n  "
436:                                                            + members + (community == ALL ? ""
437:                                                            : ("\nTelling "
438:                                                                    + l.size()
439:                                                                    + " listener" + (l
440:                                                                    .size() == 1 ? ""
441:                                                                    : "s"))))));
442:                        }
443:                    }
444:                }
445:
446:                // tell search listener
447:                if (crl != null) {
448:                    crl.getResponse(new CommunityResponseImpl(
449:                            (members != null), community));
450:                }
451:
452:                if (l.isEmpty()) {
453:                    // no change listeners
454:                    return;
455:                }
456:
457:                // create event
458:                CommunityChangeEvent cce = new CommunityChangeEvent(
459:                        new CommunityImpl(community), -1, null);
460:
461:                // invoke listeners
462:                //
463:                // our listeners should be well behaved.  Minimally the Blackboard
464:                // does the right thing: it kicks off a pooled thread.
465:                for (int i = 0; i < l.size(); i++) {
466:                    CommunityChangeListener li = (CommunityChangeListener) l
467:                            .get(i);
468:                    try {
469:                        li.communityChanged(cce);
470:                    } catch (Exception e) {
471:                        log.error("Removing listener " + li
472:                                + " that failed on callback for " + cce, e);
473:                        synchronized (lock) {
474:                            listeners.remove(li);
475:                        }
476:                    }
477:                }
478:            }
479:
480:            private void modify(final boolean isJoin, final String community,
481:                    final String agent, final CommunityResponseListener crl) {
482:                // define wp entry
483:                //
484:                // RFE use the uri to specify meta-data about this agent, e.g.:
485:                //   "?type=blah"
486:                // and/or, since we don't have a manager, about its community, e.g.:
487:                //   "?parent=Foo"
488:                String name = agent + "." + community + WP_SUFFIX;
489:                URI uri = URI.create("role://member");
490:                AddressEntry ae = AddressEntry.getAddressEntry(name, WP_TYPE,
491:                        uri);
492:
493:                if (log.isDebugEnabled()) {
494:                    log.debug((isJoin ? "Adding" : "Removing") + " agent "
495:                            + agent + " " + (isJoin ? "to" : "from")
496:                            + " community " + community);
497:                }
498:
499:                // make wp callback wrapper
500:                Callback cb = new Callback() {
501:                    public void execute(Response res) {
502:                        boolean isSuccess = (isJoin ? ((Response.Bind) res)
503:                                .didBind() : ((Response.Unbind) res)
504:                                .didUnbind());
505:                        handleModifyResult(isJoin, community, agent, crl,
506:                                isSuccess);
507:                    }
508:                };
509:
510:                if (isJoin) {
511:                    wp.rebind(ae, cb);
512:                } else {
513:                    wp.unbind(ae, cb);
514:                }
515:            }
516:
517:            private void handleModifyResult(boolean isJoin,
518:                    final String community, String agent,
519:                    CommunityResponseListener crl, final boolean isSuccess) {
520:
521:                if (log.isDebugEnabled()) {
522:                    log.debug((isSuccess ? (isJoin ? "Added" : "Removed")
523:                            : ("Unable to " + (isJoin ? "add" : "remove")))
524:                            + " agent "
525:                            + agent
526:                            + " "
527:                            + (isJoin ? "to" : "from")
528:                            + " community "
529:                            + community);
530:                }
531:
532:                // update the cache
533:                if (isSuccess) {
534:                    synchronized (lock) {
535:                        Set oldC = (Set) cache.get(community);
536:                        if (oldC != null && oldC != PENDING
537:                                && (isJoin != oldC.contains(agent))) {
538:                            // it's safer to decache then to alter the cache entry.  We want our
539:                            // cache to match whatevers in the wp, not our half-baked view of the
540:                            // world.
541:                            if (log.isDebugEnabled()) {
542:                                log.debug("Decaching " + community);
543:                            }
544:                            cache.remove(community);
545:                        }
546:                    }
547:                }
548:
549:                // tell optional listener
550:                if (crl != null) {
551:                    crl.getResponse(new CommunityResponseImpl(isSuccess,
552:                            community));
553:                }
554:            }
555:
556:            private static final String fix(String s) {
557:                String ret = s;
558:                if (ret == null || ret.equals("*")) {
559:                    ret = "";
560:                } else {
561:                    ret = ret.trim();
562:                }
563:                return ret;
564:            }
565:
566:            /**
567:             * Our service implementation.
568:             */
569:            private class CommunityServiceImpl implements  CommunityService {
570:
571:                public void addListener(CommunityChangeListener l) {
572:                    if (l == null) {
573:                        throw new IllegalArgumentException("Null listener");
574:                    }
575:                    add(l);
576:                }
577:
578:                public void removeListener(CommunityChangeListener l) {
579:                    if (l == null) {
580:                        throw new IllegalArgumentException("Null listener");
581:                    }
582:                    remove(l);
583:                }
584:
585:                public Collection search(String communityName, String filter) {
586:                    return searchCommunity(communityName, filter, false,
587:                            Community.AGENTS_ONLY, null);
588:                }
589:
590:                public Collection searchCommunity(String communityName,
591:                        String searchFilter, boolean recursiveSearch,
592:                        int resultQualifier, CommunityResponseListener crl) {
593:                    // filter must be "(Role=Member)"
594:                    if (searchFilter != null
595:                            && !searchFilter.equals("(Role=Member)")) {
596:                        throw new UnsupportedOperationException(
597:                                "Only supports null or \"(Role=Member)\" search filter, not "
598:                                        + searchFilter);
599:                    }
600:                    // trim community name
601:                    String c = fix(communityName);
602:                    if (c.length() == 0) {
603:                        throw new IllegalArgumentException(
604:                                "Invalid community name: " + communityName);
605:                    }
606:                    // ignore "recursiveSearch", since our "join" forces all communities to
607:                    // be non-hierarchical anyways  i.e. no recursion necessary)
608:                    //
609:                    // our namespace is flat, so there are no children communities
610:                    if (resultQualifier == Community.COMMUNITIES_ONLY) {
611:                        return Collections.EMPTY_SET;
612:                    }
613:                    if (resultQualifier != Community.AGENTS_ONLY
614:                            && resultQualifier != Community.ALL_ENTITIES) {
615:                        throw new IllegalArgumentException(
616:                                "Invalid result qualifier: " + resultQualifier);
617:                    }
618:                    return list(c, true, crl);
619:                }
620:
621:                /** @deprecated */
622:                public Collection listAllCommunities() {
623:                    return list(ALL, true, null);
624:                }
625:
626:                public void listAllCommunities(CommunityResponseListener crl) {
627:                    list(ALL, true, crl);
628:                }
629:
630:                public void joinCommunity(String communityName,
631:                        String entityName, int entityType,
632:                        Attributes entityAttrs, boolean createIfNotFound,
633:                        Attributes newCommunityAttrs,
634:                        CommunityResponseListener crl) {
635:                    // trim community name
636:                    String c = fix(communityName);
637:                    if (c.length() == 0) {
638:                        throw new IllegalArgumentException(
639:                                "Invalid community name: " + communityName);
640:                    }
641:                    // trim agent name
642:                    String a = fix(entityName);
643:                    if (a.length() == 0) {
644:                        throw new IllegalArgumentException(
645:                                "Invalid agent name: " + entityName);
646:                    }
647:                    // must be of type AGENT
648:                    if (entityType != AGENT) {
649:                        throw new UnsupportedOperationException(
650:                                "Only supports AGENT (" + AGENT
651:                                        + ") entities, not " + entityType);
652:                    }
653:                    // must be createIfNotFound
654:                    if (!createIfNotFound) {
655:                        throw new UnsupportedOperationException(
656:                                "Only supports createIfNotFound=true");
657:                    }
658:                    // no attrs
659:                    if (entityAttrs != null && entityAttrs.size() > 0) {
660:                        throw new UnsupportedOperationException(
661:                                "Only supports null or empty agent attributes, not "
662:                                        + entityAttrs);
663:                    }
664:                    if (newCommunityAttrs != null
665:                            && newCommunityAttrs.size() > 0) {
666:                        throw new UnsupportedOperationException(
667:                                "Only supports null or empty agent attributes, not "
668:                                        + newCommunityAttrs);
669:                    }
670:
671:                    modify(true, c, a, crl);
672:                }
673:
674:                public void leaveCommunity(String communityName,
675:                        String entityName, CommunityResponseListener crl) {
676:                    // trim community name
677:                    String c = fix(communityName);
678:                    if (c.length() == 0) {
679:                        throw new IllegalArgumentException(
680:                                "Invalid community name: " + communityName);
681:                    }
682:                    // trim agent name
683:                    String a = fix(entityName);
684:                    if (a.length() == 0) {
685:                        throw new IllegalArgumentException(
686:                                "Invalid agent name: " + entityName);
687:                    }
688:
689:                    modify(false, c, a, crl);
690:                }
691:
692:                //
693:                // The rest are not supported!
694:                //
695:                // We could support some of the "search" methods below, e.g.:
696:                //   getCommunity
697:                //   findCommunity
698:                //
699:                // Create/modify don't quite make sense, since we don't have a community
700:                // manager or a wp "metadata" entry that describes the overall community.
701:                //
702:                // We currently don't support hierarchical communities, so no "parents"
703:                // for now.  This could be added by having every child community entry
704:                // specify its parent, e.g.
705:                //   AgentX.MyChildComm.communities is role://member?parent=MyParentComm
706:                // However, this makes it expensive to find children.
707:                //
708:
709:                /** @deprecated */
710:                public void createCommunity(String communityName,
711:                        Attributes attrs, CommunityResponseListener crl) {
712:                    die();
713:                }
714:
715:                public Community getCommunity(String communityName,
716:                        CommunityResponseListener crl) {
717:                    die();
718:                    return null;
719:                }
720:
721:                public void modifyAttributes(String communityName,
722:                        String entityName, ModificationItem[] mods,
723:                        CommunityResponseListener crl) {
724:                    die();
725:                }
726:
727:                public Collection listParentCommunities(String member,
728:                        CommunityResponseListener crl) {
729:                    die();
730:                    return null;
731:                }
732:
733:                public Collection listParentCommunities(String member,
734:                        String filter, CommunityResponseListener crl) {
735:                    die();
736:                    return null;
737:                }
738:
739:                public void findCommunity(String communityName,
740:                        FindCommunityCallback fccb, long timeout) {
741:                    die();
742:                }
743:
744:                /** @deprecated */
745:                public String[] getParentCommunities(boolean allLevels) {
746:                    die();
747:                    return null;
748:                }
749:
750:                /** @deprecated */
751:                public Collection listParentCommunities(String member) {
752:                    die();
753:                    return null;
754:                }
755:
756:                /** @deprecated */
757:                public Collection listParentCommunities(String member,
758:                        String filter) {
759:                    die();
760:                    return null;
761:                }
762:
763:                private void die() {
764:                    throw new UnsupportedOperationException();
765:                }
766:            }
767:
768:            /**
769:             * A trivial service provider implementation, for where we want to return the
770:             * same service instance to all clients.
771:             */
772:            private static final class TrivialServiceProvider implements 
773:                    ServiceProvider {
774:                private final Object svc;
775:
776:                public TrivialServiceProvider(Object svc) {
777:                    this .svc = svc;
778:                }
779:
780:                public Object getService(ServiceBroker sb, Object requestor,
781:                        Class serviceClass) {
782:                    return svc;
783:                }
784:
785:                public void releaseService(ServiceBroker sb, Object requestor,
786:                        Class serviceClass, Object service) {
787:                }
788:            }
789:
790:            /**
791:             * A minimal {@link Community} implementation, required because the
792:             * {@link CommunityChangeEvent} constructor calls "community.getName()".
793:             */
794:            private static final class CommunityImpl implements  Community {
795:                private final String name;
796:
797:                public CommunityImpl(String name) {
798:                    this .name = name;
799:                }
800:
801:                public String getName() {
802:                    return name;
803:                }
804:
805:                // the rest are not supported:
806:                public void setName(String name) {
807:                    die();
808:                }
809:
810:                public void setAttributes(Attributes attrs) {
811:                    die();
812:                }
813:
814:                public Attributes getAttributes() {
815:                    die();
816:                    return null;
817:                }
818:
819:                public String toXml() {
820:                    die();
821:                    return null;
822:                }
823:
824:                public String toXml(String indent) {
825:                    die();
826:                    return null;
827:                }
828:
829:                public String attrsToString() {
830:                    die();
831:                    return null;
832:                }
833:
834:                //
835:                public Collection getEntities() {
836:                    die();
837:                    return null;
838:                }
839:
840:                public Entity getEntity(String name) {
841:                    die();
842:                    return null;
843:                }
844:
845:                public boolean hasEntity(String name) {
846:                    die();
847:                    return false;
848:                }
849:
850:                public void addEntity(Entity entity) {
851:                    die();
852:                }
853:
854:                public void removeEntity(String entityName) {
855:                    die();
856:                }
857:
858:                public Set search(String filter, int qualifier) {
859:                    die();
860:                    return null;
861:                }
862:
863:                public String qualifierToString(int qualifier) {
864:                    die();
865:                    return null;
866:                }
867:
868:                //
869:                private void die() {
870:                    throw new UnsupportedOperationException();
871:                }
872:            }
873:
874:            private static final class CommunityResponseImpl implements 
875:                    CommunityResponse {
876:                private final boolean isSuccess;
877:                private final String community;
878:
879:                public CommunityResponseImpl(boolean isSuccess, String community) {
880:                    this .isSuccess = isSuccess;
881:                    this .community = community;
882:                }
883:
884:                public int getStatus() {
885:                    return (isSuccess ? SUCCESS : FAIL);
886:                }
887:
888:                public String getStatusAsString() {
889:                    return (isSuccess ? "SUCCESS" : "FAIL");
890:                }
891:
892:                public Object getContent() {
893:                    return new CommunityImpl(community);
894:                }
895:            }
896:
897:            /**
898:             * This is a paraniod wrapper around the listener callback, to make
899:             * sure that "getCommunityName()" is well behaved.
900:             */
901:            private static final class ListenerImpl implements 
902:                    CommunityChangeListener {
903:                private final String s;
904:                private final CommunityChangeListener l;
905:
906:                public ListenerImpl(CommunityChangeListener l) {
907:                    this .l = l;
908:                    this .s = fix(l.getCommunityName());
909:                }
910:
911:                public String getCommunityName() {
912:                    return s;
913:                }
914:
915:                public void communityChanged(CommunityChangeEvent event) {
916:                    l.communityChanged(event);
917:                }
918:
919:                public int hashCode() {
920:                    return System.identityHashCode(l);
921:                }
922:
923:                public boolean equals(Object o) {
924:                    if (o == this )
925:                        return true;
926:                    if (!(o instanceof  ListenerImpl))
927:                        return false;
928:                    return l == ((ListenerImpl) o).l;
929:                }
930:
931:                public String toString() {
932:                    return "(listener for community "
933:                            + (s.length() == 0 ? "*" : s) + ")";
934:                }
935:            }
936:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.