001: /* tjws - SelectorAcceptor.java
002: * Copyright (C) 1999-2007 Dmitriy Rogatkin. All rights reserved.
003: * Redistribution and use in source and binary forms, with or without
004: * modification, are permitted provided that the following conditions
005: * are met:
006: * 1. Redistributions of source code must retain the above copyright
007: * notice, this list of conditions and the following disclaimer.
008: * 2. Redistributions in binary form must reproduce the above copyright
009: * notice, this list of conditions and the following disclaimer in the
010: * documentation and/or other materials provided with the distribution.
011: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
012: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
013: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
014: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
015: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
016: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
017: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
018: * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
019: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
020: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
021: * SUCH DAMAGE.
022: *
023: * Visit http://tjws.sourceforge.net to get the latest information
024: * about Rogatkin's products.
025: * $Id: SelectorAcceptor.java,v 1.8 2008/01/18 10:05:23 dmitriy Exp $
026: * Created on Feb 21, 2007
027: * @author dmitriy
028: */
029: package Acme.Serve;
030:
031: import java.io.IOException;
032: import java.net.InetSocketAddress;
033: import java.net.ServerSocket;
034: import java.net.Socket;
035: import java.net.InetAddress;
036: import java.nio.channels.SelectionKey;
037: import java.nio.channels.Selector;
038: import java.nio.channels.ServerSocketChannel;
039: import java.util.Iterator;
040: import java.util.Map;
041:
042: import Acme.Serve.Serve.Acceptor;
043:
044: public class SelectorAcceptor implements Acceptor {
045: private ServerSocketChannel channel;
046:
047: private Selector selector;
048:
049: private Iterator readyItor;
050:
051: public Socket accept() throws IOException {
052: do {
053: if (readyItor == null) {
054: if (selector.select() > 0)
055: readyItor = selector.selectedKeys().iterator();
056: else
057: throw new IOException();
058: }
059:
060: if (readyItor.hasNext()) {
061:
062: // Get key from set
063: SelectionKey key = (SelectionKey) readyItor.next();
064:
065: // Remove current entry
066: readyItor.remove();
067: // TODO add processing CancelledKeyException
068: if (key.isValid() && key.isAcceptable()) {
069: // Get channel
070: ServerSocketChannel keyChannel = (ServerSocketChannel) key
071: .channel();
072:
073: // Get server socket
074: ServerSocket serverSocket = keyChannel.socket();
075:
076: // Accept request
077: return serverSocket.accept();
078: }
079: } else
080: readyItor = null;
081: } while (true);
082: }
083:
084: public void destroy() throws IOException {
085: String exceptions = "";
086: try {
087: channel.close();
088: } catch (IOException e) {
089: exceptions += e.toString();
090: }
091: try {
092: selector.close();
093: } catch (IOException e) {
094: exceptions += e.toString();
095: }
096: if (exceptions.length() > 0)
097: throw new IOException(exceptions);
098: }
099:
100: public void init(Map inProperties, Map outProperties)
101: throws IOException {
102: selector = Selector.open();
103:
104: channel = ServerSocketChannel.open();
105: channel.configureBlocking(false);
106: int port = inProperties.get(Serve.ARG_PORT) != null ? ((Integer) inProperties
107: .get(Serve.ARG_PORT)).intValue()
108: : Serve.DEF_PORT;
109: InetSocketAddress isa = null;
110: if (inProperties.get(Serve.ARG_BINDADDRESS) != null)
111: try {
112: isa = new InetSocketAddress((String) inProperties
113: .get(Serve.ARG_BINDADDRESS), port);
114: } catch (Exception e) {
115: }
116: if (isa == null)
117: isa = new InetSocketAddress(port);
118: // TODO add ARG_BACKLOG
119: channel.socket().bind(isa);
120:
121: // Register interest in when connection
122: channel.register(selector, SelectionKey.OP_ACCEPT);
123: if (outProperties != null) {
124: if (channel.socket().isBound())
125: outProperties.put(Serve.ARG_BINDADDRESS, channel
126: .socket().getInetAddress().getHostName());
127: else
128: outProperties.put(Serve.ARG_BINDADDRESS, InetAddress
129: .getLocalHost().getHostName());
130: }
131: }
132:
133: public String toString() {
134: return "SelectorAcceptor - "
135: + (channel == null ? "unset" : "" + channel.socket());
136: }
137: }
|