KickJava   Java API By Example, From Geeks To Geeks.

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


1 // $Id: ByteBufferParser.java 1333 2007-06-15 16:19:26Z 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 import java.io.IOException JavaDoc;
25 import java.net.InetAddress JavaDoc;
26 import java.net.InetSocketAddress JavaDoc;
27 import java.net.Socket JavaDoc;
28 import java.nio.ByteBuffer JavaDoc;
29 import java.nio.channels.SocketChannel JavaDoc;
30 import java.rmi.server.UID JavaDoc;
31 import java.util.LinkedList JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.Random JavaDoc;
34 import java.util.Timer JavaDoc;
35 import java.util.Map.Entry;
36 import java.util.concurrent.atomic.AtomicInteger JavaDoc;
37 import java.util.logging.Level JavaDoc;
38 import java.util.logging.Logger JavaDoc;
39
40 import javax.net.ssl.SSLContext;
41
42 import org.xsocket.stream.io.spi.IAcceptor;
43 import org.xsocket.stream.io.spi.IAcceptorCallback;
44 import org.xsocket.stream.io.spi.IClientIoProvider;
45 import org.xsocket.stream.io.spi.IIoHandler;
46 import org.xsocket.stream.io.spi.IIoHandlerContext;
47 import org.xsocket.stream.io.spi.IServerIoProvider;
48
49
50
51
52 /**
53  * Server and Client IoProvider<br><br>
54  *
55  * This class is a default implementation of the {@link org.xsocket.stream.io.spi} and shouldn't be used
56  * outside this context. <br>
57  * The readbuffer preallocation size and direct/non-direct mode should be set by System.properties. Please
58  * note that current vm implementations (Juli/2007) could have problems by managing direct buffers. In this
59  * case non-direct buffer should be used.
60  * <pre>
61  * ...
62  * System.setProperty("org.xsocket.stream.ReadBufferPreallocationsizeServer", "32768");
63  *
64  * IMultithreadedServer server = new MultithreadedServer(new Handler());
65  * StreamUtils.start(server);
66  *
67  *
68  * ...
69  * System.setProperty("org.xsocket.stream.ReadBufferPreallocationsizeClient", "4096");
70  *
71  * IBlockingConnection connection = new BlockingConnection(server.getLocalAddress(), server.getLocalPort());
72  * connection.write(...);
73  * </pre>
74  *
75  * @author grro@xsocket.org
76  */

77 public final class IoProvider implements IClientIoProvider, IServerIoProvider {
78
79     private static final Logger JavaDoc LOG = Logger.getLogger(IoProvider.class.getName());
80
81
82     private static final Timer JavaDoc TIMER = new Timer JavaDoc("xIoTimer", true);
83     private static IoSocketDispatcher globalDispatcher = null;
84
85     // memory management
86
public static final int DEFAULT_READ_BUFFER_PREALLOCATION_SIZE = 65536;
87     public static final boolean DEFAULT_USE_DIRECT_BUFFER = true;
88     public static final String JavaDoc USE_DIRECT_READ_BUFFER_CLIENT_KEY = "org.xsocket.stream.UseDirectReadBufferClient";
89     public static final String JavaDoc READ_BUFFER_PREALLOCATIONSIZE_CLIENT_KEY = "org.xsocket.stream.ReadBufferPreallocationsizeClient";
90     public static final String JavaDoc USE_DIRECT_READ_BUFFER_SERVER_KEY = "org.xsocket.stream.UseDirectReadBufferServer";
91     public static final String JavaDoc READ_BUFFER_PREALLOCATIONSIZE_SERVER_KEY = "org.xsocket.stream.ReadBufferPreallocationsizeServer";
92     private static Boolean JavaDoc useDirectReadBufferClient = null;
93     private static int readBufferPreallocationsizeClient = DEFAULT_READ_BUFFER_PREALLOCATION_SIZE;
94     private static Boolean JavaDoc useDirectReadBufferServer = null;
95     private static int readBufferPreallocationsizeServer = DEFAULT_READ_BUFFER_PREALLOCATION_SIZE;
96
97     private final IMemoryManager sslMemoryManagerServer = new SynchronizedMemoryManager(readBufferPreallocationsizeServer, useDirectReadBufferServer);
98     private final IMemoryManager sslMemoryManagerClient = new SynchronizedMemoryManager(readBufferPreallocationsizeClient, useDirectReadBufferClient);
99
100
101     ////////////////////////////////////////////////
102
// use direct buffer or non-direct buffer?
103
//
104
// current vm implementations (Juli/2007) seems to have
105
// problems by gc direct buffers. mina therefore decided
106
// to use non-direct allocated buffer by default with V2
107
//
108
// links
109
// * [Java bugdatabase] http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=94d5403110224b692e5354bd87a92:WuuT?bug_id=6210541
110
// * [forum thread] http://forums.java.net/jive/thread.jspa?messageID=223706&tstart=0
111
// * [mina] https://issues.apache.org/jira/browse/DIRMINA-391
112
//
113
////////////////////////////////////////////////
114

115
116
117     // id
118
private final AtomicInteger JavaDoc nextId = new AtomicInteger JavaDoc();
119     private static String JavaDoc idPrefix = null;
120
121
122     static {
123
124         // Memory properties
125
try {
126             useDirectReadBufferClient = new Boolean JavaDoc(System.getProperty(IoProvider.USE_DIRECT_READ_BUFFER_CLIENT_KEY, Boolean.toString(DEFAULT_USE_DIRECT_BUFFER)));
127         } catch (Exception JavaDoc e) {
128             LOG.warning("invalid value for system property " + IoProvider.USE_DIRECT_READ_BUFFER_CLIENT_KEY + ": "
129                     + System.getProperty(IoProvider.USE_DIRECT_READ_BUFFER_CLIENT_KEY) + " (valid is true|false)"
130                     + " using direct buffer");
131             useDirectReadBufferClient = Boolean.TRUE;
132         }
133
134         try {
135             useDirectReadBufferServer = new Boolean JavaDoc(System.getProperty(IoProvider.USE_DIRECT_READ_BUFFER_SERVER_KEY, Boolean.toString(DEFAULT_USE_DIRECT_BUFFER)));
136         } catch (Exception JavaDoc e) {
137             LOG.warning("invalid value for system property " + IoProvider.USE_DIRECT_READ_BUFFER_SERVER_KEY + ": "
138                     + System.getProperty(IoProvider.USE_DIRECT_READ_BUFFER_SERVER_KEY) + " (valid is true|false)"
139                     + " using direct buffer");
140             useDirectReadBufferServer = Boolean.TRUE;
141         }
142
143         try {
144             readBufferPreallocationsizeClient = Integer.parseInt(System.getProperty(IoProvider.READ_BUFFER_PREALLOCATIONSIZE_CLIENT_KEY, Integer.toString(DEFAULT_READ_BUFFER_PREALLOCATION_SIZE)));
145         } catch (Exception JavaDoc e) {
146             LOG.warning("invalid value for system property " + IoProvider.READ_BUFFER_PREALLOCATIONSIZE_CLIENT_KEY + ": "
147                     + System.getProperty(IoProvider.READ_BUFFER_PREALLOCATIONSIZE_CLIENT_KEY)
148                     + " using default size " + DEFAULT_READ_BUFFER_PREALLOCATION_SIZE);
149             readBufferPreallocationsizeClient = DEFAULT_READ_BUFFER_PREALLOCATION_SIZE;
150         }
151
152         try {
153             readBufferPreallocationsizeServer = Integer.parseInt(System.getProperty(IoProvider.READ_BUFFER_PREALLOCATIONSIZE_SERVER_KEY, Integer.toString(DEFAULT_READ_BUFFER_PREALLOCATION_SIZE)));
154         } catch (Exception JavaDoc e) {
155             LOG.warning("invalid value for system property " + IoProvider.READ_BUFFER_PREALLOCATIONSIZE_SERVER_KEY + ": "
156                     + System.getProperty(IoProvider.READ_BUFFER_PREALLOCATIONSIZE_SERVER_KEY)
157                     + " using default size " + DEFAULT_READ_BUFFER_PREALLOCATION_SIZE);
158             readBufferPreallocationsizeServer = DEFAULT_READ_BUFFER_PREALLOCATION_SIZE;
159         }
160
161
162         // prepare id prefix
163
String JavaDoc base = null;
164         try {
165             base = InetAddress.getLocalHost().getCanonicalHostName();
166         } catch (Exception JavaDoc e) {
167             base = new UID JavaDoc().toString();
168         }
169
170         int random = 0;
171         Random JavaDoc rand = new Random JavaDoc();
172         do {
173             random = rand.nextInt();
174         } while (random < 0);
175         idPrefix = Integer.toHexString(base.hashCode()) + "." + Long.toHexString(System.currentTimeMillis()) + "." + Integer.toHexString(random);
176     }
177
178
179     /**
180      * {@inheritDoc}
181      */

182     public IAcceptor createAcceptor(IAcceptorCallback callback, IIoHandlerContext handlerContext, InetSocketAddress JavaDoc address, int backlog, Map JavaDoc<String JavaDoc, Object JavaDoc> options) throws IOException JavaDoc {
183         Acceptor acceptor = new Acceptor(callback, handlerContext, address, backlog);
184         for (Entry<String JavaDoc, Object JavaDoc> entry : options.entrySet()) {
185             acceptor.setOption(entry.getKey(), entry.getValue());
186         }
187
188         return acceptor;
189     }
190
191
192     /**
193      * {@inheritDoc}
194      */

195     public IAcceptor create(IAcceptorCallback callback, IIoHandlerContext handlerContext, InetSocketAddress JavaDoc address, int backlog, Map JavaDoc<String JavaDoc, Object JavaDoc> options, SSLContext sslContext, boolean sslOn) throws IOException JavaDoc {
196         Acceptor acceptor = new Acceptor(callback, handlerContext, address, backlog, sslContext, sslOn);
197         for (Entry<String JavaDoc, Object JavaDoc> entry : options.entrySet()) {
198             acceptor.setOption(entry.getKey(), entry.getValue());
199         }
200
201         return acceptor;
202     }
203
204
205     /**
206      * {@inheritDoc}
207      */

208     public IIoHandler createClientIoHandler(IIoHandlerContext ctx, InetSocketAddress JavaDoc remoteAddress, Map JavaDoc<String JavaDoc ,Object JavaDoc> options) throws IOException JavaDoc {
209         return createIoHandler(ctx, true, getClientDispatcher(), openSocket(remoteAddress, options), null, false);
210     }
211
212
213     /**
214      * {@inheritDoc}
215      */

216     public IIoHandler createSSLClientIoHandler(IIoHandlerContext ctx, InetSocketAddress JavaDoc remoteAddress, Map JavaDoc<String JavaDoc ,Object JavaDoc> options, SSLContext sslContext, boolean sslOn) throws IOException JavaDoc {
217         return createIoHandler(ctx, true, getClientDispatcher(), openSocket(remoteAddress, options), sslContext, sslOn);
218     }
219
220
221     /**
222      * {@inheritDoc}
223      */

224     IIoHandler createIoHandler(IIoHandlerContext ctx, boolean isClient, IoSocketDispatcher dispatcher, SocketChannel JavaDoc channel, SSLContext sslContext, boolean sslOn) throws IOException JavaDoc {
225
226         String JavaDoc connectionId = null;
227
228         if (isClient) {
229             connectionId = idPrefix + ".c." + nextId.incrementAndGet();
230         } else {
231             connectionId = idPrefix + ".s." + nextId.incrementAndGet();
232         }
233
234         ChainableIoHandler ioHandler = new IoSocketHandler(channel, dispatcher, ctx, connectionId);
235
236         // ssl connection?
237
if (sslContext != null) {
238
239             IMemoryManager mm = null;
240             if (isClient) {
241                 mm = sslMemoryManagerClient;
242             } else {
243                 mm = sslMemoryManagerServer;
244             }
245
246             if (sslOn) {
247                 ioHandler = new IoSSLHandler(ioHandler, sslContext, isClient, mm);
248             } else {
249                 ioHandler = new IoActivateableSSLHandler(ioHandler, sslContext, isClient, mm);
250             }
251         }
252
253         // supports multithread?
254
if (ctx.isMultithreaded()) {
255             ioHandler = new IoMultithreadedHandler(ioHandler, ctx);
256         }
257
258         return ioHandler;
259     }
260
261
262     /**
263      * {@inheritDoc}
264      */

265     public IIoHandler setWriteTransferRate(IIoHandler ioHandler, int bytesPerSecond) throws IOException JavaDoc {
266
267         // unlimited? remove throttling handler if exists
268
if (bytesPerSecond == UNLIMITED) {
269             IoThrottledWriteHandler delayWriter = (IoThrottledWriteHandler) getHandler((ChainableIoHandler) ioHandler, IoThrottledWriteHandler.class);
270             if (delayWriter != null) {
271                 delayWriter.flushOutgoing();
272                 ChainableIoHandler successor = delayWriter.getSuccessor();
273                 return successor;
274             } else {
275                 return ioHandler;
276             }
277
278         // ...no -> add throttling handler if not exists and set rate
279
} else {
280             IoThrottledWriteHandler delayWriter = (IoThrottledWriteHandler) getHandler((ChainableIoHandler) ioHandler, IoThrottledWriteHandler.class);
281             if (delayWriter == null) {
282                 delayWriter = new IoThrottledWriteHandler((ChainableIoHandler) ioHandler);
283             }
284
285             delayWriter.setWriteRateSec(bytesPerSecond);
286             return delayWriter;
287         }
288     }
289
290
291
292     public boolean preStartSecuredMode(IIoHandler ioHandler) throws IOException JavaDoc {
293         try {
294             IoActivateableSSLHandler activateableHandler = (IoActivateableSSLHandler) getHandler((ChainableIoHandler) ioHandler, IoActivateableSSLHandler.class);
295             if (activateableHandler != null) {
296                 return activateableHandler.preStartSecuredMode();
297             } else {
298                 LOG.warning("connection is not SSL activatable (non IoActivateableHandler in chain");
299                 return false;
300             }
301         } catch (ClassCastException JavaDoc cce) {
302             throw new IOException JavaDoc("only ioHandler of tpye " + ChainableIoHandler.class.getName() + " are supported");
303         }
304     }
305
306     public void startSecuredMode(IIoHandler ioHandler, LinkedList JavaDoc<ByteBuffer JavaDoc> buffers) throws IOException JavaDoc {
307         try {
308             ((ChainableIoHandler) ioHandler).flushOutgoing();
309         } catch (ClassCastException JavaDoc cce) {
310             throw new IOException JavaDoc("only ioHandler of tpye " + ChainableIoHandler.class.getName() + " are supported");
311         }
312
313         IoActivateableSSLHandler activateableHandler = (IoActivateableSSLHandler) getHandler((ChainableIoHandler) ioHandler, IoActivateableSSLHandler.class);
314         if (activateableHandler != null) {
315             activateableHandler.startSecuredMode(buffers);
316         } else {
317             LOG.warning("connection is not SSL activatable (non IoActivateableHandler in chain");
318         }
319     }
320
321
322
323     static Timer JavaDoc getTimer() {
324         return TIMER;
325     }
326
327     static boolean isUseDirectReadBufferServer() {
328         return useDirectReadBufferServer;
329     }
330
331
332     static int getReadBufferPreallocationsizeServer() {
333         return readBufferPreallocationsizeServer;
334     }
335
336
337     private static SocketChannel JavaDoc openSocket(InetSocketAddress JavaDoc remoteAddress, Map JavaDoc<String JavaDoc ,Object JavaDoc> options) throws IOException JavaDoc {
338         SocketChannel JavaDoc channel = SocketChannel.open();
339
340         for (Entry<String JavaDoc, Object JavaDoc> entry : options.entrySet()) {
341             setOption(channel.socket(), entry.getKey(), entry.getValue());
342         }
343
344
345         try {
346             channel.socket().connect(remoteAddress);
347         } catch (IOException JavaDoc ioe) {
348             if (LOG.isLoggable(Level.FINE)) {
349                 LOG.fine("error occured by bindung socket to remote address " + remoteAddress + " " + ioe.toString());
350             }
351             throw ioe;
352         }
353
354         return channel;
355     }
356
357
358
359
360     private static void setOption(Socket JavaDoc socket, String JavaDoc name, Object JavaDoc value) throws IOException JavaDoc {
361
362         if (name.equals(IClientIoProvider.SO_RCVBUF)) {
363             socket.setReceiveBufferSize((Integer JavaDoc) value);
364
365         } else if (name.equals(IClientIoProvider.SO_REUSEADDR)) {
366             socket.setReuseAddress((Boolean JavaDoc) value);
367
368         } else if (name.equals(IClientIoProvider.SO_SNDBUF)) {
369             socket.setSendBufferSize((Integer JavaDoc) value);
370
371         } else if (name.equals(IClientIoProvider.SO_KEEPALIVE)) {
372             socket.setKeepAlive((Boolean JavaDoc) value);
373
374         } else if (name.equals(IClientIoProvider.TCP_NODELAY)) {
375             socket.setTcpNoDelay((Boolean JavaDoc) value);
376
377         } else if (name.equals(IClientIoProvider.SO_LINGER)) {
378             if (value instanceof Integer JavaDoc) {
379                 socket.setSoLinger(true, (Integer JavaDoc) value);
380             } else if (value instanceof Boolean JavaDoc) {
381                 if (((Boolean JavaDoc) value).equals(Boolean.FALSE)) {
382                     socket.setSoLinger(Boolean.FALSE, 0);
383                 }
384             }
385
386         } else {
387             LOG.warning("option " + name + " is not supported");
388         }
389     }
390
391
392
393     private ChainableIoHandler getHandler(ChainableIoHandler head, Class JavaDoc clazz) {
394         ChainableIoHandler handler = head;
395         do {
396             if (handler.getClass() == clazz) {
397                 return handler;
398             }
399
400             handler = handler.getSuccessor();
401         } while (handler != null);
402
403         return null;
404     }
405
406
407     private static synchronized IoSocketDispatcher getClientDispatcher() {
408         if (globalDispatcher == null) {
409             globalDispatcher = new IoSocketDispatcher( new UnsynchronizedMemoryManager(readBufferPreallocationsizeClient, useDirectReadBufferClient));
410             Thread JavaDoc t = new Thread JavaDoc(globalDispatcher);
411             t.setName(IoSocketDispatcher.DISPATCHER_PREFIX + "#" + "CLIENT");
412             t.setDaemon(true);
413             t.start();
414
415             if (LOG.isLoggable(Level.FINE)) {
416                 LOG.fine("client dispatcher created (readbuffer preallocation size=" + readBufferPreallocationsizeClient + ", useDirectBuffer=" + useDirectReadBufferClient + ")");
417             }
418         }
419         return globalDispatcher;
420     }
421 }
Popular Tags