001: /*
002: * Copyright (c) xsocket.org, 2006 - 2008. All rights reserved.
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
019: * The latest copy of this software may be found on http://www.xsocket.org/
020: */
021: package org.xsocket.connection;
022:
023: import java.io.IOException;
024: import java.net.InetAddress;
025: import java.net.InetSocketAddress;
026: import java.net.UnknownHostException;
027: import java.util.ArrayList;
028: import java.util.HashMap;
029: import java.util.Map;
030: import java.util.concurrent.Executor;
031: import java.util.concurrent.ExecutorService;
032: import java.util.concurrent.Executors;
033: import java.util.concurrent.ThreadFactory;
034: import java.util.concurrent.atomic.AtomicInteger;
035: import java.util.logging.Level;
036: import java.util.logging.Logger;
037:
038: import javax.net.ssl.SSLContext;
039:
040: import org.xsocket.connection.IConnection.FlushMode;
041: import org.xsocket.connection.spi.DefaultIoProvider;
042: import org.xsocket.connection.spi.IAcceptor;
043: import org.xsocket.connection.spi.IAcceptorCallback;
044: import org.xsocket.connection.spi.IIoHandler;
045: import org.xsocket.connection.spi.IServerIoProvider;
046:
047: /**
048: * Implementation of a server. For more information see
049: * {@link IServer}
050: *
051: * @author grro@xsocket.org
052: */
053: public class Server implements IServer {
054:
055: private static final Logger LOG = Logger.getLogger(Server.class
056: .getName());
057:
058: public static final int SIZE_DEFAULT_WORKER_POOL = 40;
059: private static String implementationVersion = null;
060:
061: private FlushMode flushMode = IConnection.DEFAULT_FLUSH_MODE;
062: private boolean autoflush = IConnection.DEFAULT_AUTOFLUSH;
063: private Integer writeRate = null;
064: private Integer readRate = null;
065:
066: // is open flag
067: private boolean isOpen = false;
068:
069: // name
070: private String name = "server";
071:
072: // acceptor
073: private boolean isSsslOn = false;
074: private static IServerIoProvider serverIoProvider = null;
075: private IAcceptor acceptor = null;
076:
077: // workerpool
078: private ExecutorService defaultWorkerPool = Executors
079: .newFixedThreadPool(SIZE_DEFAULT_WORKER_POOL,
080: new DefaultThreadFactory());
081: private Executor workerpool = defaultWorkerPool;
082:
083: // app handler
084: private HandlerProxy handlerProxyPrototype = HandlerProxy
085: .newPrototype(null, null);
086:
087: // timeouts
088: private long idleTimeoutMillis = IConnection.MAX_TIMEOUT_MILLIS;
089: private long connectionTimeoutMillis = IConnection.MAX_TIMEOUT_MILLIS;
090:
091: // server listeners
092: private final ArrayList<IServerListener> listeners = new ArrayList<IServerListener>();
093:
094: // modules
095: private String startUpLogMessage = null;
096:
097: /**
098: * constructor <br><br>
099: *
100: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
101: * @throws IOException If some other I/O error occurs
102: * @throws UnknownHostException if the local host cannot determined
103: */
104: public Server(IHandler handler) throws UnknownHostException,
105: IOException {
106: this (new InetSocketAddress(InetAddress
107: .getByName(DEFAULT_HOST_ADDRESS), 0),
108: new HashMap<String, Object>(), handler, null, false, 0);
109: }
110:
111: /**
112: * constructor <br><br>
113: *
114: * @param options the socket options
115: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
116: * @throws IOException If some other I/O error occurs
117: * @throws UnknownHostException if the local host cannot determined
118: */
119: public Server(Map<String, Object> options, IHandler handler)
120: throws UnknownHostException, IOException {
121: this (InetAddress.getByName(DEFAULT_HOST_ADDRESS), 0, options,
122: handler, null, false, 0);
123: }
124:
125: /**
126: * constructor <br><br>
127: *
128: *
129: * @param port the local port
130: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
131: * @throws UnknownHostException if the local host cannot determined
132: * @throws IOException If some other I/O error occurs
133: */
134: public Server(int port, IHandler handler)
135: throws UnknownHostException, IOException {
136: this (new InetSocketAddress(InetAddress
137: .getByName(DEFAULT_HOST_ADDRESS), port),
138: new HashMap<String, Object>(), handler, null, false, 0);
139: }
140:
141: /**
142: * constructor <br><br>
143: *
144: *
145: * @param port the local port
146: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
147: * @param backlog The maximum number number of pending connections. If has the value 0, or a negative value, then an implementation specific default is used.
148: * @throws UnknownHostException if the local host cannot determined
149: * @throws IOException If some other I/O error occurs
150: */
151: public Server(int port, IHandler handler, int backlog)
152: throws UnknownHostException, IOException {
153: this (new InetSocketAddress(InetAddress
154: .getByName(DEFAULT_HOST_ADDRESS), port),
155: new HashMap<String, Object>(), handler, null, false,
156: backlog);
157: }
158:
159: /**
160: * constructor <br><br>
161: *
162: * @param port the local port
163: * @param options the acceptor socket options
164: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
165: * @throws UnknownHostException if the local host cannot determined
166: * @throws IOException If some other I/O error occurs
167: */
168: public Server(int port, Map<String, Object> options,
169: IHandler handler) throws UnknownHostException, IOException {
170: this (InetAddress.getByName(DEFAULT_HOST_ADDRESS), port,
171: options, handler, null, false, 0);
172: }
173:
174: /**
175: * constructor <br><br>
176: *
177: * @param address the local address
178: * @param port the local port
179: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
180: * @throws UnknownHostException if the local host cannot determined
181: * @throws IOException If some other I/O error occurs
182: */
183: public Server(InetAddress address, int port, IHandler handler)
184: throws UnknownHostException, IOException {
185: this (address, port, new HashMap<String, Object>(), handler,
186: null, false, 0);
187: }
188:
189: /**
190: * constructor <br><br>
191: *
192: * @param ipAddress the local ip address
193: * @param port the local port
194: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
195: * @throws UnknownHostException if the local host cannot determined
196: * @throws IOException If some other I/O error occurs
197: */
198: public Server(String ipAddress, int port, IHandler handler)
199: throws UnknownHostException, IOException {
200: this (InetAddress.getByName(ipAddress), port,
201: new HashMap<String, Object>(), handler, null, false, 0);
202: }
203:
204: /**
205: * constructor <br><br>
206: *
207: *
208: * @param ipAddress the local ip address
209: * @param port the local port
210: * @param options the socket options
211: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
212: * @throws UnknownHostException if the local host cannot determined
213: * @throws IOException If some other I/O error occurs
214: */
215: public Server(String ipAddress, int port,
216: Map<String, Object> options, IHandler handler)
217: throws UnknownHostException, IOException {
218: this (InetAddress.getByName(ipAddress), port, options, handler,
219: null, false, 0);
220: }
221:
222: /**
223: * constructor <br><br>
224: *
225: * @param port local port
226: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
227: * @param sslOn true, is SSL should be activated
228: * @param sslContext the ssl context to use
229: * @throws UnknownHostException if the local host cannot determined
230: * @throws IOException If some other I/O error occurs
231: */
232: public Server(int port, IHandler handler, SSLContext sslContext,
233: boolean sslOn) throws UnknownHostException, IOException {
234: this (InetAddress.getByName(DEFAULT_HOST_ADDRESS), port,
235: new HashMap<String, Object>(), handler, sslContext,
236: sslOn, 0);
237: }
238:
239: /**
240: * constructor <br><br>
241: *
242: * @param port local port
243: * @param options the acceptor socket options
244: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
245: * @param sslOn true, is SSL should be activated
246: * @param sslContext the ssl context to use
247: * @throws UnknownHostException if the local host cannot determined
248: * @throws IOException If some other I/O error occurs
249: */
250: public Server(int port, Map<String, Object> options,
251: IHandler handler, SSLContext sslContext, boolean sslOn)
252: throws UnknownHostException, IOException {
253: this (InetAddress.getByName(DEFAULT_HOST_ADDRESS), port,
254: options, handler, sslContext, sslOn, 0);
255: }
256:
257: /**
258: * constructor <br><br>
259: *
260: * @param ipAddress local ip address
261: * @param port local port
262: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
263: * @param sslOn true, is SSL should be activated
264: * @param sslContext the ssl context to use
265: * @throws UnknownHostException if the local host cannot determined
266: * @throws IOException If some other I/O error occurs
267: */
268: public Server(String ipAddress, int port, IHandler handler,
269: SSLContext sslContext, boolean sslOn)
270: throws UnknownHostException, IOException {
271: this (InetAddress.getByName(ipAddress), port,
272: new HashMap<String, Object>(), handler, sslContext,
273: sslOn, 0);
274: }
275:
276: /**
277: * constructor <br><br>
278: *
279: * @param ipAddress local ip address
280: * @param port local port
281: * @param options the acceptor socket options
282: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
283: * @param sslOn true, is SSL should be activated
284: * @param sslContext the ssl context to use
285: * @throws UnknownHostException if the local host cannot determined
286: * @throws IOException If some other I/O error occurs
287: */
288: public Server(String ipAddress, int port,
289: Map<String, Object> options, IHandler handler,
290: SSLContext sslContext, boolean sslOn)
291: throws UnknownHostException, IOException {
292: this (InetAddress.getByName(ipAddress), port, options, handler,
293: sslContext, sslOn, 0);
294: }
295:
296: /**
297: * constructor <br><br>
298: *
299: * @param address local address
300: * @param port local port
301: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
302: * @param sslOn true, is SSL should be activated
303: * @param sslContext the ssl context to use
304: * @throws UnknownHostException if the local host cannot determined
305: * @throws IOException If some other I/O error occurs
306: */
307: public Server(InetAddress address, int port, IHandler handler,
308: SSLContext sslContext, boolean sslOn)
309: throws UnknownHostException, IOException {
310: this (address, port, new HashMap<String, Object>(), handler,
311: sslContext, sslOn, 0);
312: }
313:
314: /**
315: * constructor <br><br>
316: *
317: * @param address local address
318: * @param port local port
319: * @param options the socket options
320: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
321: * @param sslOn true, is SSL should be activated
322: * @param sslContext the ssl context to use
323: * @throws UnknownHostException if the local host cannot determined
324: * @throws IOException If some other I/O error occurs
325: */
326: public Server(InetAddress address, int port,
327: Map<String, Object> options, IHandler handler,
328: SSLContext sslContext, boolean sslOn)
329: throws UnknownHostException, IOException {
330: this (new InetSocketAddress(address, port), options, handler,
331: sslContext, sslOn, 0);
332: }
333:
334: /**
335: * constructor <br><br>
336: *
337: * @param address local address
338: * @param port local port
339: * @param options the socket options
340: * @param handler the handler to use (supported: IConnectHandler, IDisconnectHandler, IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler, IConnectionScoped, ILifeCycle)
341: * @param sslOn true, is SSL should be activated
342: * @param sslContext the ssl context to use
343: * @param backlog The maximum number number of pending connections. If has the value 0, or a negative value, then an implementation specific default is used.
344: * @throws UnknownHostException if the local host cannot determined
345: * @throws IOException If some other I/O error occurs
346: */
347: public Server(InetAddress address, int port,
348: Map<String, Object> options, IHandler handler,
349: SSLContext sslContext, boolean sslOn, int backlog)
350: throws UnknownHostException, IOException {
351: this (new InetSocketAddress(address, port), options, handler,
352: sslContext, sslOn, backlog);
353: }
354:
355: protected Server(InetSocketAddress address,
356: Map<String, Object> options, IHandler appHandler,
357: SSLContext sslContext, boolean sslOn, int backlog)
358: throws UnknownHostException, IOException {
359:
360: if (sslContext != null) {
361: isSsslOn = true;
362: acceptor = new DefaultIoProvider().create(
363: new AcceptorCallback(), address, backlog, options,
364: sslContext, sslOn);
365:
366: } else {
367: isSsslOn = false;
368: acceptor = getServerIoProvider().createAcceptor(
369: new AcceptorCallback(), address, backlog, options);
370: }
371:
372: setHandler(appHandler);
373: }
374:
375: private void setHandler(IHandler handler) {
376: if (isOpen) {
377: destroyCurrentHandler();
378: }
379:
380: handlerProxyPrototype = HandlerProxy
381: .newPrototype(handler, this );
382:
383: if (isOpen) {
384: initCurrentHandler();
385: }
386: }
387:
388: private void initCurrentHandler() {
389: handlerProxyPrototype.onInit();
390: }
391:
392: private void destroyCurrentHandler() {
393: handlerProxyPrototype.onDestroy();
394: }
395:
396: IServerIoProvider getIoProvider() {
397: return serverIoProvider;
398: }
399:
400: /**
401: * the the server name. The server name will be used to print out the start log message.<br>
402: *
403: * E.g.
404: * <pre>
405: * IServer cacheServer = new Server(port, new CacheHandler());
406: * ConnectionUtils.start(server);
407: * server.setServerName("CacheServer");
408: *
409: *
410: * // prints out
411: * // 01::52::42,756 10 INFO [Server$AcceptorCallback#onConnected] CacheServer listening on 172.25.34.33/172.25.34.33:9921 (xSocket 2.0)
412: * </pre>
413: *
414: * @param name the server name
415: */
416: public final void setServerName(String name) {
417: this .name = name;
418: }
419:
420: /**
421: * return the server name
422: *
423: * @return the server name
424: */
425: public final String getServerName() {
426: return name;
427: }
428:
429: /**
430: * {@inheritDoc}
431: */
432: public String getStartUpLogMessage() {
433: return startUpLogMessage;
434: }
435:
436: /**
437: * {@inheritDoc}
438: */
439: public void setStartUpLogMessage(String message) {
440: this .startUpLogMessage = message;
441: }
442:
443: @SuppressWarnings("unchecked")
444: private static IServerIoProvider getServerIoProvider() {
445:
446: if (serverIoProvider == null) {
447: String serverIoProviderClassname = System
448: .getProperty(IServerIoProvider.PROVIDER_CLASSNAME_KEY);
449: if (serverIoProviderClassname != null) {
450: try {
451: Class serverIoProviderClass = Class.forName(
452: serverIoProviderClassname, true, Thread
453: .currentThread()
454: .getContextClassLoader());
455: serverIoProvider = (IServerIoProvider) serverIoProviderClass
456: .newInstance();
457: } catch (Exception e) {
458: LOG
459: .warning("error occured by creating ServerIoProivder "
460: + serverIoProviderClassname
461: + ": "
462: + e.toString());
463: LOG.info("using default ServerIoProvider");
464:
465: }
466: }
467:
468: if (serverIoProvider == null) {
469: serverIoProvider = new DefaultIoProvider();
470: }
471: }
472:
473: return serverIoProvider;
474: }
475:
476: /**
477: * {@inheritDoc}
478: */
479: @SuppressWarnings("unchecked")
480: public final void run() {
481:
482: try {
483: if (getHandler() == null) {
484: LOG
485: .warning("no handler has been set. Call setHandler-method to set an assigned handler");
486: }
487:
488: Runtime.getRuntime().addShutdownHook(new Thread() {
489: @Override
490: public void run() {
491: close();
492: }
493: });
494:
495: // start listening
496: acceptor.listen();
497:
498: } catch (Exception e) {
499: throw new RuntimeException(e.toString());
500: }
501: }
502:
503: /**
504: * {@inheritDoc}
505: */
506: public final Object getOption(String name) throws IOException {
507: return acceptor.getOption(name);
508: }
509:
510: public IHandler getHandler() {
511: return handlerProxyPrototype.getHandler();
512: }
513:
514: /**
515: * {@inheritDoc}
516: */
517: @SuppressWarnings("unchecked")
518: public final Map<String, Class> getOptions() {
519: return acceptor.getOptions();
520: }
521:
522: /**
523: * {@inheritDoc}
524: */
525: @SuppressWarnings("unchecked")
526: public final void close() {
527: if (isOpen) {
528: isOpen = false;
529:
530: try {
531: acceptor.close(); // closing of dispatcher will be initiated by acceptor
532: } catch (IOException ignore) {
533: }
534:
535: if (defaultWorkerPool != null) {
536: defaultWorkerPool.shutdownNow();
537: }
538: }
539: }
540:
541: IAcceptor getAcceptor() {
542: return acceptor;
543: }
544:
545: /**
546: * {@inheritDoc}
547: */
548: public final void addListener(IServerListener listener) {
549: listeners.add(listener);
550: }
551:
552: /**
553: * {@inheritDoc}
554: */
555: public final boolean removeListener(IServerListener listener) {
556: boolean result = listeners.remove(listener);
557: return result;
558: }
559:
560: /**
561: * {@inheritDoc}
562: */
563: public final Executor getWorkerpool() {
564: return workerpool;
565: }
566:
567: /**
568: * {@inheritDoc}
569: */
570: public final void setWorkerpool(Executor executor) {
571: if (executor == null) {
572: throw new NullPointerException("executor has to be set");
573: }
574:
575: if (isOpen) {
576: LOG.warning("server is already running");
577: }
578:
579: workerpool = executor;
580:
581: if (defaultWorkerPool != null) {
582: defaultWorkerPool.shutdown();
583: defaultWorkerPool = null;
584: }
585: }
586:
587: /**
588: * {@inheritDoc}
589: */
590: public final boolean isOpen() {
591: return isOpen;
592: }
593:
594: /**
595: * {@inheritDoc}
596: */
597: public final int getLocalPort() {
598: return acceptor.getLocalPort();
599: }
600:
601: /**
602: * {@inheritDoc}
603: */
604: public final InetAddress getLocalAddress() {
605: return acceptor.getLocalAddress();
606: }
607:
608: /**
609: * {@inheritDoc}
610: */
611: public final int getNumberOfOpenConnections() {
612: return acceptor.getNumberOfOpenConnections();
613: }
614:
615: /**
616: * {@inheritDoc}
617: */
618: public final FlushMode getFlushMode() {
619: return flushMode;
620: }
621:
622: /**
623: * {@inheritDoc}
624: */
625: public final void setFlushMode(FlushMode flusmode) {
626: this .flushMode = flusmode;
627: }
628:
629: /**
630: * {@inheritDoc}
631: */
632: public final void setAutoflush(boolean autoflush) {
633: this .autoflush = autoflush;
634: }
635:
636: /**
637: * {@inheritDoc}
638: */
639: public final boolean getAutoflush() {
640: return autoflush;
641: }
642:
643: /**
644: * {@inheritDoc}
645: */
646: public final void setConnectionTimeoutMillis(long timeoutMillis) {
647: this .connectionTimeoutMillis = timeoutMillis;
648: }
649:
650: /**
651: * {@inheritDoc}
652: */
653: public void setWriteTransferRate(int bytesPerSecond)
654: throws IOException {
655: this .writeRate = bytesPerSecond;
656: }
657:
658: /**
659: * {@inheritDoc}
660: */
661: public void setReadTransferRate(int bytesPerSecond)
662: throws IOException {
663: this .readRate = bytesPerSecond;
664: }
665:
666: /**
667: * {@inheritDoc}
668: */
669: public void setIdleTimeoutMillis(long timeoutMillis) {
670: this .idleTimeoutMillis = timeoutMillis;
671: }
672:
673: /**
674: * {@inheritDoc}
675: */
676: public final long getConnectionTimeoutMillis() {
677: return connectionTimeoutMillis;
678: }
679:
680: /**
681: * {@inheritDoc}
682: */
683: public final long getIdleTimeoutMillis() {
684: return idleTimeoutMillis;
685: }
686:
687: public final String getVersion() {
688: if (implementationVersion == null) {
689: implementationVersion = ConnectionUtils.getVersionInfo();
690: }
691:
692: return implementationVersion;
693: }
694:
695: private final class AcceptorCallback implements IAcceptorCallback {
696:
697: @SuppressWarnings("unchecked")
698: public void onConnected() {
699:
700: isOpen = true;
701:
702: startUpLogMessage = getVersion();
703: if (startUpLogMessage.length() > 0) {
704: startUpLogMessage = "xSocket " + startUpLogMessage;
705: }
706:
707: if (!(serverIoProvider instanceof DefaultIoProvider)) {
708: String verInfo = getServerIoProvider()
709: .getImplementationVersion();
710: if (verInfo.length() > 0) {
711: startUpLogMessage = startUpLogMessage
712: + "/"
713: + getServerIoProvider().getClass()
714: .getSimpleName() + " " + verInfo;
715: }
716: }
717:
718: // init app handler
719: initCurrentHandler();
720:
721: // notify listeners
722: for (IServerListener listener : (ArrayList<IServerListener>) listeners
723: .clone()) {
724: listener.onInit();
725: }
726:
727: // print out the startUp log message
728: if (isSsslOn) {
729: LOG.info(name + " listening on "
730: + acceptor.getLocalAddress().getHostName()
731: + ":" + acceptor.getLocalPort()
732: + " - SSL mode (" + startUpLogMessage + ")");
733: } else {
734: LOG.info(name + " listening on "
735: + acceptor.getLocalAddress().getHostName()
736: + ":" + acceptor.getLocalPort() + " ("
737: + startUpLogMessage + ")");
738: }
739: }
740:
741: @SuppressWarnings("unchecked")
742: public void onDisconnected() {
743:
744: destroyCurrentHandler();
745:
746: for (IServerListener listener : (ArrayList<IServerListener>) listeners
747: .clone()) {
748: try {
749: listener.onDestroy();
750: } catch (IOException ioe) {
751: if (LOG.isLoggable(Level.FINE)) {
752: LOG.fine("exception occured by destroying "
753: + listener + " " + ioe.toString());
754: }
755: }
756: }
757:
758: LOG.info("server has been shutdown");
759: }
760:
761: public void onConnectionAccepted(IIoHandler ioHandler)
762: throws IOException {
763:
764: // create a new connection
765: NonBlockingConnection connection = new NonBlockingConnection();
766:
767: // set default flush properties
768: connection.setAutoflush(autoflush);
769: connection.setFlushmode(flushMode);
770:
771: // initialize the connection
772: connection.init(ioHandler, getServerIoProvider(),
773: handlerProxyPrototype.newProxy(connection),
774: workerpool);
775:
776: // set timeouts (requires that connection is already initialized)
777: connection.setIdleTimeoutMillis(idleTimeoutMillis);
778: connection
779: .setConnectionTimeoutMillis(connectionTimeoutMillis);
780:
781: // set transfer rates
782: if (writeRate != null) {
783: connection.setWriteTransferRate(writeRate);
784: }
785: /* if (readRate != null) {
786: connection.setReadTransferRate(readRate);
787: }*/
788: }
789: }
790:
791: private static class DefaultThreadFactory implements ThreadFactory {
792: private static final AtomicInteger poolNumber = new AtomicInteger(
793: 1);
794: private final ThreadGroup group;
795: private final AtomicInteger threadNumber = new AtomicInteger(1);
796: private final String namePrefix;
797:
798: DefaultThreadFactory() {
799: SecurityManager s = System.getSecurityManager();
800: group = (s != null) ? s.getThreadGroup() : Thread
801: .currentThread().getThreadGroup();
802: namePrefix = "xServerPool-" + poolNumber.getAndIncrement()
803: + "-thread-";
804: }
805:
806: public Thread newThread(Runnable r) {
807: Thread t = new Thread(group, r, namePrefix
808: + threadNumber.getAndIncrement(), 0);
809: if (t.isDaemon()) {
810: t.setDaemon(false);
811: }
812: if (t.getPriority() != Thread.NORM_PRIORITY) {
813: t.setPriority(Thread.NORM_PRIORITY);
814: }
815: return t;
816: }
817: }
818: }
|