KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xsocket > stream > io > impl > Acceptor


1 // $Id: Acceptor.java 1347 2007-06-17 15:51:55Z grro $
2
/*
3  * Copyright (c) xsocket.org, 2006 - 2007. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
20  * The latest copy of this software may be found on http://www.xsocket.org/
21  */

22 package org.xsocket.stream.io.impl;
23
24
25 import java.io.IOException JavaDoc;
26 import java.net.BindException JavaDoc;
27 import java.net.InetSocketAddress JavaDoc;
28 import java.nio.channels.ServerSocketChannel JavaDoc;
29 import java.nio.channels.SocketChannel JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.Collections JavaDoc;
32 import java.util.HashMap JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.logging.Level JavaDoc;
36 import java.util.logging.Logger JavaDoc;
37
38 import javax.net.ssl.SSLContext;
39
40
41
42 import org.xsocket.IDispatcher;
43 import org.xsocket.stream.io.spi.IAcceptor;
44 import org.xsocket.stream.io.spi.IAcceptorCallback;
45 import org.xsocket.stream.io.spi.IIoHandler;
46 import org.xsocket.stream.io.spi.IIoHandlerContext;
47
48
49
50 /**
51  * The acceptor ist responsible to accept new incomming connections, and
52  * register these on the dispatcher.<br><br>
53  *
54  * This class is a default implementation of the {@link org.xsocket.stream.io.spi} and shouldn't be used
55  * outside this context. This is a framework-internal class
56  *
57  * @author grro@xsocket.org
58  */

59 final class Acceptor implements IAcceptor {
60
61     private static final Logger JavaDoc LOG = Logger.getLogger(Acceptor.class.getName());
62     
63     private static final Map JavaDoc<String JavaDoc ,Class JavaDoc> SUPPORTED_OPTIONS = new HashMap JavaDoc<String JavaDoc, Class JavaDoc>();
64     
65     static {
66         SUPPORTED_OPTIONS.put(SO_RCVBUF, Integer JavaDoc.class);
67         SUPPORTED_OPTIONS.put(SO_REUSEADDR, Boolean JavaDoc.class);
68     }
69
70
71     // io handler
72
private static final IoProvider IO_PROVIDER = new IoProvider();
73     private IAcceptorCallback callback = null;
74     private IIoHandlerContext handlerContext = null;
75     
76     // running flag
77
private boolean isRunning = true;
78         
79     
80     // Socket
81
private InetSocketAddress JavaDoc address = null;
82     private ServerSocketChannel JavaDoc serverChannel = null;
83     private int backlog = 0;
84
85     
86     // SSL
87
private boolean sslOn = false;
88     private SSLContext sslContext = null;
89
90
91     // dispatcher management
92
private final IoSocketDispatcherPool dispatcherPool = new IoSocketDispatcherPool(IoProvider.getReadBufferPreallocationsizeServer(), IoProvider.isUseDirectReadBufferServer());
93
94     // statistics
95
private long handledConnections = 0;
96
97     
98     public Acceptor(IAcceptorCallback callback, IIoHandlerContext handlerContext, InetSocketAddress JavaDoc address, int backlog) throws IOException JavaDoc {
99         this(callback, handlerContext, address, backlog, null, false);
100     }
101     
102     
103     
104     public Acceptor(IAcceptorCallback callback, IIoHandlerContext handlerContext, InetSocketAddress JavaDoc address, int backlog, SSLContext sslContext, boolean sslOn) throws IOException JavaDoc {
105         this.callback = callback;
106         this.address = address;
107         this.handlerContext = handlerContext;
108         this.backlog = backlog;
109         this.sslContext = sslContext;
110         this.sslOn = sslOn;
111         
112         
113         LOG.fine("try to bind server on " + address);
114         
115         // create a new server socket
116
serverChannel = ServerSocketChannel.open();
117         serverChannel.configureBlocking(true);
118         
119         serverChannel.socket().setReuseAddress(true); // set reuse address by default (can be override by socketConfig)
120
}
121     
122     
123     
124     /**
125      * {@inheritDoc}
126      */

127     public InetSocketAddress JavaDoc getLocalAddress() {
128         return new InetSocketAddress JavaDoc(serverChannel.socket().getInetAddress(), serverChannel.socket().getLocalPort());
129     }
130     
131
132     void setOption(String JavaDoc name, Object JavaDoc value) throws IOException JavaDoc {
133     
134         if (name.equals(IAcceptor.SO_RCVBUF)) {
135             serverChannel.socket().setReceiveBufferSize((Integer JavaDoc) value);
136             
137         } else if (name.equals(IAcceptor.SO_REUSEADDR)) {
138             serverChannel.socket().setReuseAddress((Boolean JavaDoc) value);
139                         
140         } else {
141             LOG.warning("option " + name + " is not supproted for " + this.getClass().getName());
142         }
143     }
144     
145     
146     /**
147      * {@inheritDoc}
148      */

149     public Object JavaDoc getOption(String JavaDoc name) throws IOException JavaDoc {
150
151         if (name.equals(IAcceptor.SO_RCVBUF)) {
152             return serverChannel.socket().getReceiveBufferSize();
153             
154         } else if (name.equals(IAcceptor.SO_REUSEADDR)) {
155             return serverChannel.socket().getReuseAddress();
156             
157         } else {
158             LOG.warning("option " + name + " is not supproted for " + this.getClass().getName());
159             return null;
160         }
161     }
162     
163     
164     public Map JavaDoc<String JavaDoc, Class JavaDoc> getOptions() {
165         return Collections.unmodifiableMap(SUPPORTED_OPTIONS);
166     }
167     
168         
169     /**
170      * {@inheritDoc}
171      */

172     public void listen() throws IOException JavaDoc {
173         
174         try {
175             setDispatcherPoolSize(Runtime.getRuntime().availableProcessors() + 1);
176             
177             // and bind it to the port and notify callback
178
serverChannel.socket().bind(address, backlog);
179             
180             callback.onConnected();
181             
182             // now accepting
183
accept();
184             
185         } catch (BindException JavaDoc be) {
186             if (serverChannel != null) {
187                 serverChannel.close();
188             }
189             LOG.info("error occured while binding server on on " + address + ". Reason: " + be.toString());
190             throw be;
191         }
192     }
193     
194     
195     private void accept() {
196         dispatcherPool.run();
197         
198         // acceptor loop
199
while (isRunning) {
200             try {
201             
202                 // blocking accept call
203
SocketChannel JavaDoc channel = serverChannel.accept();
204                 
205                 // create IoSocketHandler
206
IoSocketDispatcher dispatcher = dispatcherPool.nextDispatcher();
207                 IIoHandler ioHandler = IO_PROVIDER.createIoHandler(handlerContext, false, dispatcher, channel, sslContext, sslOn);
208
209                 // notify callback
210
callback.onConnectionAccepted(ioHandler);
211                 handledConnections++;
212                     
213             } catch (Throwable JavaDoc t) {
214                 if (LOG.isLoggable(Level.FINE)) {
215                     // if acceptor is running (<socket>.close() causes that any
216
// thread currently blocked in accept() will throw a SocketException)
217
if (serverChannel.isOpen()) {
218                         LOG.fine("error occured while accepting connection: " + t.toString());
219                     }
220                 }
221             }
222             
223         } // acceptor loop
224
}
225
226     
227     public void setDispatcherPoolSize(int size) {
228         dispatcherPool.setSize(size);
229     }
230
231     
232     public int getDispatcherPoolSize() {
233         return dispatcherPool.getDispatchers().size();
234     }
235     
236     
237     public int getReceiveBufferPreallocationSize() {
238         return dispatcherPool.getReceiveBufferPreallocationSize();
239     }
240
241     
242
243     public void setReceiveBufferPreallocationSize(int size) {
244         dispatcherPool.setReceiveBufferPreallocationSize(size);
245     }
246     
247
248     public List JavaDoc<String JavaDoc> getOpenConnections() {
249         List JavaDoc<String JavaDoc> result = new ArrayList JavaDoc<String JavaDoc>();
250
251         for (IDispatcher<IoSocketHandler> dispatcher : dispatcherPool.getDispatchers()) {
252             for (IoSocketHandler handler : dispatcher.getRegistered()) {
253                 result.add(handler.toString());
254             }
255         }
256             
257         return result;
258     }
259
260     
261     List JavaDoc<IDispatcher<IoSocketHandler>> getDispatchers() {
262         return dispatcherPool.getDispatchers();
263     }
264     
265     
266     /**
267      * {@inheritDoc}
268      */

269     public int getNumberOfOpenConnections() {
270         return getOpenConnections().size();
271     }
272     
273     IoSocketDispatcherPool getDispatcherPool() {
274         return dispatcherPool;
275     }
276     
277     /**
278      * {@inheritDoc}
279      */

280     public long getNumberOfHandledConnections() {
281         return handledConnections;
282     }
283     
284     
285     public long getNumberOfConnectionTimeouts() {
286         return dispatcherPool.getNumberOfConnectionTimeouts();
287     }
288     
289     public long getNumberOfIdleTimeouts() {
290         return dispatcherPool.getNumberOfIdleTimeouts();
291     }
292     
293     
294     /**
295      * {@inheritDoc}
296      */

297     public void close() throws IOException JavaDoc {
298         if (isRunning) {
299             isRunning = false;
300             
301             if (LOG.isLoggable(Level.FINE)) {
302                 LOG.fine("closing acceptor");
303             }
304             
305             try {
306                 // closes the server socket
307
serverChannel.close();
308             } catch (Exception JavaDoc ignore) { }
309             
310             try {
311                 dispatcherPool.shutdown();
312             } catch (Exception JavaDoc ignore) { }
313             
314             callback.onDisconnected();
315         }
316     }
317 }
318
Popular Tags