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.base;
028:
029: import java.io.IOException;
030: import java.net.BindException;
031: import java.net.InetAddress;
032: import java.net.Socket;
033: import java.net.ServerSocket;
034: import java.util.HashMap;
035: import java.util.Map;
036:
037: /**
038: * A standard {@link ServerSocket}-based server connection factory implementation.
039: * <p>
040: * This implementation supports subclassing to use pooled threads.
041: */
042: public class SocketServerFactory implements ServerFactory {
043:
044: public ListenerControl listen(final Map settings,
045: final AcceptCallback callback) throws BindException,
046: IOException {
047:
048: ServerSocket serverSock = bind(settings);
049:
050: listen_bg(serverSock, settings, callback);
051:
052: // TODO return object with "stop()" method, to release thread & close socket
053: return null;
054: }
055:
056: /** bind a socket */
057: protected ServerSocket bind(Map settings) throws BindException,
058: IOException {
059: int port = Integer.parseInt((String) settings.get("port"));
060: return new ServerSocket(port);
061: }
062:
063: /** listen in a background thread */
064: protected void listen_bg(final ServerSocket serverSock,
065: final Map settings, final AcceptCallback callback) {
066: // TODO use pooled thread (but note that we'll never return this thread!)
067: Runnable r = new Runnable() {
068: public void run() {
069: listen(serverSock, settings, callback);
070: }
071: };
072: Thread thread = new Thread(r, "servlet engine");
073: //thread.setDaemon(true);
074: thread.start();
075: }
076:
077: /** block in a loop, accepting clients */
078: protected void listen(ServerSocket serverSock, Map settings,
079: AcceptCallback callback) {
080: int port = Integer.parseInt((String) settings.get("port"));
081: String contextPath = "";
082: String serverURL = "http://localhost:" + port;
083:
084: while (true) {
085: final Socket clientSock;
086: try {
087: clientSock = serverSock.accept();
088: } catch (Exception e) {
089: throw new RuntimeException("Socket accept failed", e);
090: }
091:
092: final Map metaData = new HashMap();
093: metaData.put("serverURL", serverURL);
094: metaData.put("contextPath", contextPath);
095: InetAddress clientAddr = clientSock.getInetAddress();
096: if (clientAddr != null) {
097: metaData.put("clientAddr", clientAddr.getHostAddress());
098: metaData.put("clientHost", clientAddr.getHostName());
099: }
100:
101: Connection con = new Connection() {
102: private String to_string;
103:
104: public Map getMetaData() {
105: return metaData;
106: }
107:
108: public AnnotatedInputStream getInputStream()
109: throws IOException {
110: return AnnotatedInputStream
111: .toAnnotatedInputStream(clientSock
112: .getInputStream());
113: }
114:
115: public AnnotatedOutputStream getOutputStream()
116: throws IOException {
117: return AnnotatedOutputStream
118: .toAnnotatedOutputStream(clientSock
119: .getOutputStream());
120: }
121:
122: public void close() throws IOException {
123: clientSock.close();
124: }
125:
126: public String toString() {
127: if (to_string == null) {
128: String s = null;
129: try {
130: s = clientSock.toString();
131: } catch (Exception e) {
132: }
133: to_string = (s == null ? "null" : s);
134: }
135: return to_string;
136: }
137: };
138:
139: accept_bg(callback, con);
140: }
141: }
142:
143: /** call "callback.accept(con)" in a background thread */
144: protected void accept_bg(final AcceptCallback callback,
145: final Connection con) {
146: // TODO use pooled thread
147: Runnable r = new Runnable() {
148: public void run() {
149: accept(callback, con);
150: }
151: };
152: (new Thread(r)).start();
153: }
154:
155: /** call "callback.accept(con)" in the caller's thread */
156: protected void accept(AcceptCallback callback, Connection con) {
157: try {
158: callback.accept(con);
159: } catch (Exception e) {
160: e.printStackTrace();
161: }
162: }
163: }
|