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.lib.web.micro.mts;
028:
029: import java.io.UnsupportedEncodingException;
030: import java.net.BindException;
031: import java.net.URI;
032: import java.net.URLEncoder;
033: import java.util.Collections;
034: import java.util.Map;
035: import javax.servlet.Servlet;
036: import javax.servlet.ServletException;
037:
038: import org.cougaar.bootstrap.SystemProperties;
039: import org.cougaar.core.agent.service.MessageSwitchService;
040: import org.cougaar.core.component.Component;
041: import org.cougaar.core.component.ServiceBroker;
042: import org.cougaar.core.component.ServiceProvider;
043: import org.cougaar.core.mts.MessageAddress;
044: import org.cougaar.core.node.NodeIdentificationService;
045: import org.cougaar.core.service.LoggingService;
046: import org.cougaar.core.service.ThreadService;
047: import org.cougaar.lib.web.engine.ServletEngineRegistryService;
048: import org.cougaar.lib.web.engine.ServletEngineService;
049: import org.cougaar.lib.web.micro.base.ServletEngine;
050: import org.cougaar.lib.web.micro.base.ServletEngineImpl;
051: import org.cougaar.util.Arguments;
052: import org.cougaar.util.GenericStateModelAdapter;
053:
054: /**
055: * This component loads a message-transport-backed servlet engine that
056: * listens for incoming {@link MessagingTunnel} servlet requests.
057: *
058: * @property org.cougaar.lib.web.micro.mts.engine.nagle=1000
059: * MTS-backed servlet engine response OutputStream buffering delay.
060: * See {@link OutputPipe}.
061: */
062: public class MessagingServletEngine extends GenericStateModelAdapter
063: implements Component {
064:
065: private ServiceBroker sb;
066:
067: private LoggingService log;
068: private ThreadService threadService;
069: private MessageSwitchService messageSwitch;
070:
071: private ServletEngineService ses;
072: private ServletEngineRegistryService sers;
073: private ServiceProvider ses_sp;
074:
075: private Arguments args = Arguments.EMPTY_INSTANCE;
076:
077: private ServletEngine engine;
078:
079: public void setServiceBroker(ServiceBroker sb) {
080: this .sb = sb;
081: }
082:
083: public void setParameter(Object o) {
084: args = new Arguments(o);
085: }
086:
087: public void load() {
088: super .load();
089:
090: // parse args
091: String prefix = "org.cougaar.lib.web.micro.mts.engine.";
092: long nagle = args.getLong("nagle", SystemProperties.getLong(
093: prefix + ".nagle", 1000));
094:
095: // obtain services
096: log = (LoggingService) sb.getService(this ,
097: LoggingService.class, null);
098: threadService = (ThreadService) sb.getService(this ,
099: ThreadService.class, null);
100: messageSwitch = (MessageSwitchService) sb.getService(this ,
101: MessageSwitchService.class, null);
102:
103: // figure out which node we're in
104: String localNode = null;
105: NodeIdentificationService nis = (NodeIdentificationService) sb
106: .getService(this , NodeIdentificationService.class, null);
107: if (nis != null) {
108: localNode = nis.getMessageAddress().getAddress();
109: sb.releaseService(this , NodeIdentificationService.class,
110: nis);
111: }
112:
113: // create naming entries
114: String encNode = (localNode == null ? null : encode(localNode));
115: final Map namingEntries = (encNode == null ? null : Collections
116: .singletonMap("mts_tunnel", URI.create("node:///"
117: + encNode)));
118:
119: // create mts listener
120: MessagingServerFactory server_factory = new MessagingServerFactory(
121: log, threadService, messageSwitch, nagle);
122: server_factory.start();
123:
124: // create engine
125: engine = new ServletEngineImpl(server_factory);
126: engine.configure(-1, -1, null);
127: try {
128: engine.start();
129: } catch (Exception e) {
130: throw new RuntimeException(
131: "Unable to start servlet engine", e);
132: }
133:
134: if (log.isInfoEnabled()) {
135: log.info("Started MTS servlet engine");
136: }
137:
138: // create and advertise our service
139: ses = new ServletEngineService() {
140: public void setGateway(Servlet s) throws ServletException {
141: engine.setGateway(s);
142: }
143:
144: public Map getNamingEntries() {
145: return namingEntries;
146: }
147: };
148: sers = (ServletEngineRegistryService) sb.getService(this ,
149: ServletEngineRegistryService.class, null);
150: if (sers != null) {
151: // share registry
152: sers.add(ses);
153: } else {
154: // just us
155: final Class cl = ServletEngineService.class;
156: ses_sp = new ServiceProvider() {
157: public Object getService(ServiceBroker sb, Object req,
158: Class scl) {
159: return (cl.isAssignableFrom(scl) ? ses : null);
160: }
161:
162: public void releaseService(ServiceBroker sb,
163: Object req, Class scl, Object svc) {
164: }
165: };
166: sb.addService(cl, ses_sp);
167: }
168: }
169:
170: public void unload() {
171: // remove/revoke our service
172: if (ses != null) {
173: if (sers != null) {
174: sers.remove(ses);
175: sers = null;
176: } else if (ses_sp != null) {
177: sb.revokeService(ServletEngineService.class, ses_sp);
178: ses_sp = null;
179: }
180: ses = null;
181: }
182:
183: // stop engine
184: if (engine != null) {
185: try {
186: engine.stop();
187: } catch (Exception e) {
188: throw new RuntimeException("Unable to stop server", e);
189: }
190: engine = null;
191: }
192:
193: // release services
194: if (messageSwitch != null) {
195: sb.releaseService(this , MessageSwitchService.class,
196: messageSwitch);
197: messageSwitch = null;
198: }
199: if (threadService != null) {
200: sb.releaseService(this , ThreadService.class, threadService);
201: threadService = null;
202: }
203: if (log != null) {
204: sb.releaseService(this , LoggingService.class, log);
205: log = null;
206: }
207:
208: super .unload();
209: }
210:
211: private static final String encode(String raw) {
212: try {
213: return URLEncoder.encode(raw, "UTF-8");
214: } catch (UnsupportedEncodingException uee) {
215: throw new RuntimeException("Invalid name: " + raw, uee);
216: }
217: }
218: }
|