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.bootstrap.rmi;
028:
029: import java.net.URI;
030: import java.rmi.registry.Registry;
031: import java.rmi.server.RMISocketFactory;
032: import java.util.Map;
033: import org.cougaar.core.component.ServiceBroker;
034: import org.cougaar.core.component.ServiceRevokedListener;
035: import org.cougaar.core.mts.MessageAddress;
036: import org.cougaar.core.service.LoggingService;
037: import org.cougaar.core.service.SocketFactoryService;
038: import org.cougaar.core.service.wp.AddressEntry;
039: import org.cougaar.core.wp.bootstrap.AdvertiseBase;
040: import org.cougaar.core.wp.bootstrap.Bundle;
041: import org.cougaar.core.wp.bootstrap.ConfigService;
042: import org.cougaar.core.wp.bootstrap.Util;
043:
044: /**
045: * This component advertises bundles through an RMI registry stub.
046: * <p>
047: * It looks in the {@link ConfigService} for config entries of type
048: * "-RMI_REG" and scheme "rmi", e.g.<pre>
049: * X={-RMI_REG=rmi://test.com:8888/Y}
050: * </pre>
051: * and if the localhost is "test.com" and the local agent is "Y"
052: * (or this path is "*") then this component attempts to create
053: * the RMI registry and bind "COUGAAR_NAMING/X" in it. The bound
054: * {@link RMIAccess} stub responds to "getBundles()" with the bundles
055: * tracked by the {@link
056: * org.cougaar.core.wp.bootstrap.AdvertiseService} (i.e. locally bound
057: * leases). These bundles are filtered for just agent "Y" (or no
058: * filtering if this path is "*").
059: */
060: public class RMIAdvertise extends AdvertiseBase {
061:
062: private ConfigService configService;
063:
064: private final ConfigService.Client configClient = new ConfigService.Client() {
065: public void add(Bundle b) {
066: addAdvertiser(getBootEntry(b));
067: }
068:
069: public void change(Bundle b) {
070: add(b);
071: }
072:
073: public void remove(Bundle b) {
074: removeAdvertiser(getBootEntry(b));
075: }
076: };
077:
078: private SocketFactoryService socFacService;
079:
080: private final Object socFacLock = new Object();
081: private RMISocketFactory socFac;
082:
083: public void setSocketFactoryService(
084: SocketFactoryService socFacService) {
085: this .socFacService = socFacService;
086: }
087:
088: public void load() {
089: super .load();
090:
091: configService = (ConfigService) sb.getService(configClient,
092: ConfigService.class, null);
093: if (configService == null) {
094: throw new RuntimeException("Unable to obtain ConfigService");
095: }
096: }
097:
098: public void unload() {
099: if (configService != null) {
100: sb.releaseService(configClient, ConfigService.class,
101: configService);
102: configService = null;
103: }
104:
105: super .unload();
106: }
107:
108: protected RMISocketFactory getRMISocketFactory() {
109: synchronized (socFacLock) {
110: if (socFac == null) {
111: socFac = RMIUtil.getRMISocketFactory(socFacService);
112: }
113: return socFac;
114: }
115: }
116:
117: private AddressEntry getBootEntry(Bundle b) {
118: AddressEntry ae = RMIUtil.getBootEntry(b);
119: if (ae == null) {
120: return null;
121: }
122: URI uri = ae.getURI();
123: String host = (uri == null ? null : uri.getHost());
124: if (!Util.isLocalHost(host)) {
125: return null;
126: }
127: String filter = RMIUtil.getFilter(ae, agentId, log);
128: if (!agentName.equals(filter)) {
129: return null;
130: }
131: return ae;
132: }
133:
134: protected Advertiser createAdvertiser(Object bootObj) {
135: return new RMIAdvertiser(bootObj);
136: }
137:
138: private class RMIAdvertiser extends Advertiser {
139:
140: private final AddressEntry bootEntry;
141:
142: private final String filter;
143:
144: // this is the active RMI RemoteObject that was found
145: // in the RMI registry upon successful lookup.
146: private RMIAccess rmiAccess;
147:
148: public RMIAdvertiser(Object bootObj) {
149: super (bootObj);
150:
151: bootEntry = (AddressEntry) bootObj;
152:
153: filter = RMIUtil.getFilter(bootEntry, agentId, log);
154: }
155:
156: public void start() {
157: String name = bootEntry.getName();
158: URI uri = bootEntry.getURI();
159: int port = uri.getPort();
160:
161: // assert Util.isLocalHost(uri.getHost());
162:
163: // create registry
164: RMISocketFactory rsf = getRMISocketFactory();
165: Registry r = RMIUtil.createRegistry(rsf, port, log);
166: if (r == null) {
167: // try again later?
168: return;
169: }
170:
171: // bind rmi object
172: BundlesProvider bp = new BundlesProvider() {
173: public Map getBundles() {
174: // serve remote caller
175: return RMIAdvertiser.this .getBundles();
176: }
177: };
178: RMIAccess newAccess = RMIUtil.bindAccess(rsf, r, name, bp,
179: log);
180: if (newAccess == null) {
181: // try again later?
182: return;
183: }
184:
185: // save
186: rmiAccess = newAccess;
187:
188: // okay, listening for calls to "getBundles()"
189:
190: // wake periodically to make sure we're still registered?
191: }
192:
193: private Map getBundles() {
194: // serve remote caller
195: Map ret = RMIAdvertise.this .getBundles();
196: // filter for specific agent
197: ret = RMIUtil.filterBundles(ret, filter, log);
198: if (log.isDebugEnabled()) {
199: log.debug("Serving bundles: " + ret);
200: }
201: return ret;
202: }
203:
204: public void update(String name, Bundle bundle) {
205: // do nothing, since we server bundles (as opposed to posting
206: // them at external server)
207: }
208:
209: public void stop() {
210: // not implemented yet
211: //unbind from registry
212: }
213:
214: public String toString() {
215: return "(rmi_bootstrap " + super .toString()
216: + ", rmiAccess=" + rmiAccess + ")";
217: }
218: }
219: }
|