1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.transport.socket.nio;
21
22 import java.io.IOException;
23 import java.nio.channels.ByteChannel;
24 import java.nio.channels.SelectableChannel;
25 import java.nio.channels.SelectionKey;
26 import java.nio.channels.Selector;
27 import java.util.Iterator;
28 import java.util.Set;
29 import java.util.concurrent.Executor;
30
31 import org.apache.mina.common.AbstractPollingIoProcessor;
32 import org.apache.mina.common.FileRegion;
33 import org.apache.mina.common.IoBuffer;
34 import org.apache.mina.common.RuntimeIoException;
35
36
37
38
39
40
41 public final class NioProcessor extends AbstractPollingIoProcessor<NioSession> {
42
43 private static Selector newSelector() {
44 try {
45 return Selector.open();
46 } catch (IOException e) {
47 throw new RuntimeIoException("Failed to open a selector.", e);
48 }
49 }
50
51 private final Selector selector;
52
53 public NioProcessor(Executor executor) {
54 super(executor);
55 this.selector = newSelector();
56 }
57
58 @Override
59 protected void dispose0() throws Exception {
60 selector.close();
61 }
62
63 @Override
64 protected boolean select(int timeout) throws Exception {
65 return selector.select(timeout) > 0;
66 }
67
68 @Override
69 protected void wakeup() {
70 selector.wakeup();
71 }
72
73 @Override
74 protected Iterator<NioSession> allSessions() {
75 return new IoSessionIterator(selector.keys());
76 }
77
78 @Override
79 protected Iterator<NioSession> selectedSessions() {
80 return new IoSessionIterator(selector.selectedKeys());
81 }
82
83 @Override
84 protected void init(NioSession session) throws Exception {
85 SelectableChannel ch = (SelectableChannel) session.getChannel();
86 ch.configureBlocking(false);
87 session.setSelectionKey(ch.register(selector, SelectionKey.OP_READ, session));
88 }
89
90 @Override
91 protected void destroy(NioSession session) throws Exception {
92 ByteChannel ch = session.getChannel();
93 SelectionKey key = session.getSelectionKey();
94 if (key != null) {
95 key.cancel();
96 }
97 ch.close();
98 }
99
100 @Override
101 protected SessionState state(NioSession session) {
102 SelectionKey key = session.getSelectionKey();
103 if (key == null) {
104 return SessionState.PREPARING;
105 }
106
107 return key.isValid()? SessionState.OPEN : SessionState.CLOSED;
108 }
109
110 @Override
111 protected boolean isReadable(NioSession session) {
112 SelectionKey key = session.getSelectionKey();
113 return key.isValid() && key.isReadable();
114 }
115
116 @Override
117 protected boolean isWritable(NioSession session) {
118 SelectionKey key = session.getSelectionKey();
119 return key.isValid() && key.isWritable();
120 }
121
122 @Override
123 protected boolean isInterestedInRead(NioSession session) {
124 SelectionKey key = session.getSelectionKey();
125 return key.isValid() && (key.interestOps() & SelectionKey.OP_READ) != 0;
126 }
127
128 @Override
129 protected boolean isInterestedInWrite(NioSession session) {
130 SelectionKey key = session.getSelectionKey();
131 return key.isValid() && (key.interestOps() & SelectionKey.OP_WRITE) != 0;
132 }
133
134 @Override
135 protected void setInterestedInRead(NioSession session, boolean value) throws Exception {
136 SelectionKey key = session.getSelectionKey();
137 if (value) {
138 key.interestOps(key.interestOps() | SelectionKey.OP_READ);
139 } else {
140 key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
141 }
142 }
143
144 @Override
145 protected void setInterestedInWrite(NioSession session, boolean value) throws Exception {
146 SelectionKey key = session.getSelectionKey();
147 if (value) {
148 key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
149 } else {
150 key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
151 }
152 }
153
154 @Override
155 protected int read(NioSession session, IoBuffer buf) throws Exception {
156 return session.getChannel().read(buf.buf());
157 }
158
159 @Override
160 protected int write(NioSession session, IoBuffer buf, int length) throws Exception {
161 if (buf.remaining() <= length) {
162 return session.getChannel().write(buf.buf());
163 } else {
164 int oldLimit = buf.limit();
165 buf.limit(buf.position() + length);
166 try {
167 return session.getChannel().write(buf.buf());
168 } finally {
169 buf.limit(oldLimit);
170 }
171 }
172 }
173
174 @Override
175 protected int transferFile(NioSession session, FileRegion region, int length) throws Exception {
176 try {
177 return (int) region.getFileChannel().transferTo(region.getPosition(), length, session.getChannel());
178 } catch (IOException e) {
179
180 if (e.getMessage().contains("Resource temporarily unavailable")) {
181 return 0;
182 } else {
183 throw e;
184 }
185 }
186 }
187
188 protected static class IoSessionIterator implements Iterator<NioSession> {
189 private final Iterator<SelectionKey> i;
190 private IoSessionIterator(Set<SelectionKey> keys) {
191 i = keys.iterator();
192 }
193 public boolean hasNext() {
194 return i.hasNext();
195 }
196
197 public NioSession next() {
198 SelectionKey key = i.next();
199 return (NioSession) key.attachment();
200 }
201
202 public void remove() {
203 i.remove();
204 }
205 }
206 }