001: /*
002: * Copyright 2005-2007 Noelios Consulting.
003: *
004: * The contents of this file are subject to the terms of the Common Development
005: * and Distribution License (the "License"). You may not use this file except in
006: * compliance with the License.
007: *
008: * You can obtain a copy of the license at
009: * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
010: * language governing permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL HEADER in each file and
013: * include the License file at http://www.opensource.org/licenses/cddl1.txt If
014: * applicable, add the following below this CDDL HEADER, with the fields
015: * enclosed by brackets "[]" replaced with your own identifying information:
016: * Portions Copyright [yyyy] [name of copyright owner]
017: */
018:
019: package com.noelios.restlet.http;
020:
021: import java.io.IOException;
022: import java.net.InetSocketAddress;
023: import java.net.ServerSocket;
024: import java.net.Socket;
025: import java.net.SocketAddress;
026: import java.util.concurrent.ExecutorService;
027: import java.util.concurrent.Executors;
028: import java.util.logging.Level;
029:
030: import org.restlet.Server;
031: import org.restlet.data.Protocol;
032:
033: /**
034: * HTTP server helper based on BIO sockets.
035: *
036: * @author Jerome Louvel (contact@noelios.com)
037: */
038: public class StreamServerHelper extends HttpServerHelper {
039: /**
040: * Connection that handles the socket.
041: */
042: class Connection implements Runnable {
043: private StreamServerHelper helper;
044:
045: private final Socket socket;
046:
047: Connection(StreamServerHelper helper, Socket socket) {
048: this .helper = helper;
049: this .socket = socket;
050: }
051:
052: public void run() {
053: try {
054: this .helper.handle(new StreamServerCall(this .helper
055: .getServer(), this .socket.getInputStream(),
056: this .socket.getOutputStream()));
057: this .socket.getOutputStream().close();
058: this .socket.close();
059: } catch (IOException ioe) {
060: getLogger().log(Level.WARNING,
061: "Unexpected error while handle a call", ioe);
062: }
063: }
064: }
065:
066: /**
067: * Listener thread that accepts incoming requests.
068: */
069: class Listener extends Thread {
070: private StreamServerHelper helper;
071:
072: Listener(StreamServerHelper helper) {
073: this .helper = helper;
074: }
075:
076: public void run() {
077: try {
078: if (socketAddress == null) {
079: socketAddress = createSocketAddress();
080: }
081:
082: executorService = Executors.newFixedThreadPool(10);
083: serverSocket = createSocket();
084:
085: if (socketAddress != null) {
086: serverSocket.bind(socketAddress);
087: }
088:
089: for (;;) {
090: executorService.execute(new Connection(helper,
091: serverSocket.accept()));
092: }
093: } catch (IOException ioe) {
094: try {
095: this .helper.stop();
096: } catch (Exception e) {
097: getLogger()
098: .log(
099: Level.WARNING,
100: "Unexpected error while stopping the connector",
101: e);
102: }
103: }
104: }
105: }
106:
107: /** The server socket to listen on. */
108: private ServerSocket serverSocket;
109:
110: /** The server socket address. */
111: private SocketAddress socketAddress;
112:
113: /** The executor service (thread pool). */
114: private ExecutorService executorService;
115:
116: /**
117: * Constructor.
118: *
119: * @param server
120: * The server to help.
121: */
122: public StreamServerHelper(Server server) {
123: super (server);
124: getProtocols().add(Protocol.HTTP);
125: }
126:
127: /**
128: * Creates a server socket to listen on.
129: *
130: * @return The created server socket.
131: * @throws IOException
132: */
133: public ServerSocket createSocket() throws IOException {
134: ServerSocket serverSocket = new ServerSocket();
135: return serverSocket;
136: }
137:
138: /**
139: * Creates a socket address to listen on.
140: *
141: * @return The created socket address.
142: * @throws IOException
143: */
144: public SocketAddress createSocketAddress() throws IOException {
145: if (getServer().getAddress() == null) {
146: return new InetSocketAddress(getServer().getPort());
147: } else {
148: return new InetSocketAddress(getServer().getAddress(),
149: getServer().getPort());
150: }
151: }
152:
153: @Override
154: public void start() throws Exception {
155: super .start();
156: getLogger().info("Starting the internal HTTP server");
157: new Listener(this ).start();
158: }
159:
160: @Override
161: public void stop() throws Exception {
162: super .stop();
163: getLogger().info("Stopping the internal HTTP server");
164: if (this.serverSocket.isBound()) {
165: this.serverSocket.close();
166: this.serverSocket = null;
167: }
168:
169: if (this.executorService != null) {
170: this.executorService.shutdown();
171: }
172: }
173: }
|