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.wp;
028:
029: import java.util.Collections;
030: import java.util.HashMap;
031: import java.util.HashSet;
032: import java.util.Iterator;
033: import java.util.Map;
034: import java.util.Set;
035: import org.cougaar.core.component.Component;
036: import org.cougaar.core.component.ServiceBroker;
037: import org.cougaar.core.component.ServiceProvider;
038: import org.cougaar.core.node.NodeControlService;
039: import org.cougaar.core.service.LoggingService;
040: import org.cougaar.core.service.wp.AddressEntry;
041: import org.cougaar.core.service.wp.Request;
042: import org.cougaar.core.service.wp.Response;
043: import org.cougaar.core.service.wp.WhitePagesService;
044: import org.cougaar.util.GenericStateModelAdapter;
045:
046: /**
047: * This component is a node-local (loopback) implementation of
048: * the {@link WhitePagesService}.
049: */
050: public class LoopbackWhitePages extends GenericStateModelAdapter
051: implements Component {
052: private ServiceBroker sb;
053: private ServiceBroker rootsb;
054: private LoggingService log;
055:
056: private ServiceProvider sp;
057:
058: private final Map table = new HashMap();
059:
060: public void setServiceBroker(ServiceBroker sb) {
061: this .sb = sb;
062: }
063:
064: public void setNodeControlService(NodeControlService ncs) {
065: rootsb = (ncs == null ? null : ncs.getRootServiceBroker());
066: }
067:
068: public void setLoggingService(LoggingService log) {
069: this .log = log;
070: }
071:
072: public void load() {
073: super .load();
074:
075: if (log.isDebugEnabled()) {
076: log.debug("Loading resolver");
077: }
078:
079: sp = new MySP();
080: rootsb.addService(WhitePagesService.class, sp);
081:
082: if (log.isInfoEnabled()) {
083: log.info("Loaded white pages resolver");
084: }
085: }
086:
087: public void unload() {
088: super .unload();
089:
090: if (sp != null) {
091: rootsb.revokeService(WhitePagesService.class, sp);
092: sp = null;
093: }
094:
095: if (log != null) {
096: sb.releaseService(this , LoggingService.class, log);
097: log = null;
098: }
099: }
100:
101: private Response submit(Request req) {
102: if (log.isDetailEnabled()) {
103: log.detail("handling wp request: " + req);
104: }
105: Object ret;
106:
107: if (req instanceof Request.Bind) {
108: Request.Bind r = (Request.Bind) req;
109: AddressEntry ae = r.getAddressEntry();
110: boolean overWrite = r.isOverWrite();
111: String name = ae.getName();
112: String type = ae.getType();
113: synchronized (table) {
114: Map m = (Map) table.get(name);
115: if (overWrite || m == null || !m.containsKey(type)) {
116: // replace table entry with modified copy
117: m = (m == null ? new HashMap() : new HashMap(m));
118: m.put(type, ae);
119: m = Collections.unmodifiableMap(m);
120: table.put(name, m);
121: // return "forever"
122: ret = new Long(Long.MAX_VALUE);
123: } else {
124: // already bound, return conflict
125: ret = (AddressEntry) m.get(type);
126: }
127: }
128: } else if (req instanceof Request.Unbind) {
129: Request.Unbind r = (Request.Unbind) req;
130: AddressEntry ae = r.getAddressEntry();
131: String name = ae.getName();
132: String type = ae.getType();
133: synchronized (table) {
134: Map m = (Map) table.get(name);
135: AddressEntry m_ae = (m == null ? null
136: : (AddressEntry) m.get(type));
137: if (ae.equals(m_ae)) {
138: // replace table entry with modified copy
139: if (m.size() == 1) {
140: table.remove(name);
141: } else {
142: m = new HashMap(m);
143: m.remove(type);
144: m = Collections.unmodifiableMap(m);
145: table.put(name, m);
146: }
147: ret = Boolean.TRUE;
148: } else {
149: // unknown name or non-matching entry data
150: ret = Boolean.FALSE;
151: }
152: }
153: } else if (req instanceof Request.List) {
154: String suffix = ((Request.List) req).getSuffix();
155: int len = suffix.length();
156: if (len <= 0 || suffix.charAt(0) != '.') {
157: // invalid suffix, expecting ".*."
158: ret = null;
159: } else {
160: Set set = null;
161: synchronized (table) {
162: // return matching names, if any
163: boolean isRoot = (len == 1);
164: for (Iterator iter = table.keySet().iterator(); iter
165: .hasNext();) {
166: String s = (String) iter.next();
167: if (isRoot) {
168: int sep = s.lastIndexOf('.');
169: if (sep >= 0) {
170: s = s.substring(sep);
171: }
172: } else {
173: if ((s.length() <= len)
174: || !s.endsWith(suffix)) {
175: continue;
176: }
177: int sep = -1;
178: for (int j = s.length() - len - 1; j >= 0; j--) {
179: if (s.charAt(j) == '.') {
180: sep = j;
181: break;
182: }
183: }
184: if (sep >= 0) {
185: s = s.substring(sep);
186: }
187: }
188: if (set == null) {
189: set = new HashSet();
190: }
191: set.add(s);
192: }
193: }
194: ret = (set == null ? null : Collections
195: .unmodifiableSet(set));
196: }
197: } else {
198: String name = (req instanceof Request.Get ? ((Request.Get) req)
199: .getName()
200: : req instanceof Request.GetAll ? ((Request.GetAll) req)
201: .getName()
202: : null);
203: synchronized (table) {
204: ret = (Map) table.get(name);
205: }
206: }
207:
208: Response res = req.createResponse();
209: res.setResult(ret);
210: return res;
211: }
212:
213: private class MySP implements ServiceProvider {
214: public Object getService(ServiceBroker sb, Object requestor,
215: Class serviceClass) {
216: if (WhitePagesService.class.isAssignableFrom(serviceClass)) {
217: return new WhitePagesService() {
218: public Response submit(Request req) {
219: return LoopbackWhitePages.this .submit(req);
220: }
221: };
222: } else {
223: return null;
224: }
225: }
226:
227: public void releaseService(ServiceBroker sb, Object requestor,
228: Class serviceClass, Object service) {
229: }
230: }
231: }
|