View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.transport.socket.nio;
21  
22  import java.net.InetSocketAddress;
23  import java.net.SocketAddress;
24  import java.nio.channels.SelectionKey;
25  import java.nio.channels.Selector;
26  import java.nio.channels.SocketChannel;
27  import java.util.Collection;
28  import java.util.Iterator;
29  import java.util.concurrent.Executor;
30  
31  import org.apache.mina.common.AbstractPollingIoConnector;
32  import org.apache.mina.common.IoConnector;
33  import org.apache.mina.common.IoProcessor;
34  import org.apache.mina.common.TransportMetadata;
35  import org.apache.mina.transport.socket.DefaultSocketSessionConfig;
36  import org.apache.mina.transport.socket.SocketConnector;
37  import org.apache.mina.transport.socket.SocketSessionConfig;
38  
39  /**
40   * {@link IoConnector} for socket transport (TCP/IP).
41   *
42   * @author The Apache MINA Project (dev@mina.apache.org)
43   * @version $Rev: 389042 $, $Date: 2006-03-27 07:49:41Z $
44   */
45  public final class NioSocketConnector
46          extends AbstractPollingIoConnector<NioSession, SocketChannel>
47          implements SocketConnector {
48  
49      private volatile Selector selector;
50  
51      public NioSocketConnector() {
52          super(new DefaultSocketSessionConfig(), NioProcessor.class);
53      }
54  
55      public NioSocketConnector(int processorCount) {
56          super(new DefaultSocketSessionConfig(), NioProcessor.class, processorCount);
57      }
58  
59      public NioSocketConnector(IoProcessor<NioSession> processor) {
60          super(new DefaultSocketSessionConfig(), processor);
61      }
62  
63      public NioSocketConnector(Executor executor, IoProcessor<NioSession> processor) {
64          super(new DefaultSocketSessionConfig(), executor, processor);
65      }
66      
67      @Override
68      protected void init() throws Exception {
69          this.selector = Selector.open();
70      }
71      
72      @Override
73      protected void destroy() throws Exception {
74          if (selector != null) {
75              selector.close();
76          }
77      }
78  
79      public TransportMetadata getTransportMetadata() {
80          return NioSocketSession.METADATA;
81      }
82  
83      @Override
84      public SocketSessionConfig getSessionConfig() {
85          return (SocketSessionConfig) super.getSessionConfig();
86      }
87  
88      @Override
89      public InetSocketAddress getDefaultRemoteAddress() {
90          return (InetSocketAddress) super.getDefaultRemoteAddress();
91      }
92      
93      public void setDefaultRemoteAddress(InetSocketAddress defaultRemoteAddress) {
94          super.setDefaultRemoteAddress(defaultRemoteAddress);
95      }
96  
97      @Override
98      protected Iterator<SocketChannel> allHandles() {
99          return new SocketChannelIterator(selector.keys());
100     }
101 
102     @Override
103     protected boolean connect(SocketChannel handle, SocketAddress remoteAddress)
104             throws Exception {
105         return handle.connect(remoteAddress);
106     }
107 
108     @Override
109     protected ConnectionRequest connectionRequest(SocketChannel handle) {
110         SelectionKey key = handle.keyFor(selector);
111         if (key == null) {
112             return null;
113         }
114         
115         return (ConnectionRequest) key.attachment();
116     }
117 
118     @Override
119     protected void close(SocketChannel handle) throws Exception {
120         SelectionKey key = handle.keyFor(selector);
121         if (key != null) {
122             key.cancel();
123         }
124         handle.close();
125     }
126 
127     @Override
128     protected boolean finishConnect(SocketChannel handle) throws Exception {
129         SelectionKey key = handle.keyFor(selector);
130         if (handle.finishConnect()) {
131             if (key != null) {
132                 key.cancel();
133             }
134             return true;
135         }
136         
137         return false;
138     }
139 
140     @Override
141     protected SocketChannel newHandle(SocketAddress localAddress)
142             throws Exception {
143         SocketChannel ch = SocketChannel.open();
144         ch.socket().setReuseAddress(true);
145         if (localAddress != null) {
146             ch.socket().bind(localAddress);
147         }
148         ch.configureBlocking(false);
149         return ch;
150     }
151 
152     @Override
153     protected NioSession newSession(IoProcessor<NioSession> processor, SocketChannel handle) {
154         return new NioSocketSession(this, processor, handle);
155     }
156 
157     @Override
158     protected void register(SocketChannel handle, ConnectionRequest request)
159             throws Exception {
160         handle.register(selector, SelectionKey.OP_CONNECT, request);
161     }
162 
163     @Override
164     protected boolean select(int timeout) throws Exception {
165         return selector.select(timeout) > 0;
166     }
167 
168     @Override
169     protected Iterator<SocketChannel> selectedHandles() {
170         return new SocketChannelIterator(selector.selectedKeys());
171     }
172 
173     @Override
174     protected void wakeup() {
175         selector.wakeup();
176     }
177     
178     private static class SocketChannelIterator implements Iterator<SocketChannel> {
179         
180         private final Iterator<SelectionKey> i;
181         
182         private SocketChannelIterator(Collection<SelectionKey> selectedKeys) {
183             this.i = selectedKeys.iterator();
184         }
185 
186         public boolean hasNext() {
187             return i.hasNext();
188         }
189 
190         public SocketChannel next() {
191             SelectionKey key = i.next();
192             return (SocketChannel) key.channel();
193         }
194 
195         public void remove() {
196             i.remove();
197         }
198     }
199 }