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.core.RuntimeIoException;
32 import org.apache.mina.core.buffer.IoBuffer;
33 import org.apache.mina.core.file.FileRegion;
34 import org.apache.mina.core.polling.AbstractPollingIoProcessor;
35
36
37
38
39
40
41
42 public final class NioProcessor extends AbstractPollingIoProcessor<NioSession> {
43
44 private final Selector selector;
45
46
47
48
49
50
51
52 public NioProcessor(Executor executor) {
53 super(executor);
54 try {
55
56 selector = Selector.open();
57 } catch (IOException e) {
58 throw new RuntimeIoException("Failed to open a selector.", e);
59 }
60 }
61
62 @Override
63 protected void dispose0() throws Exception {
64 selector.close();
65 }
66
67 @Override
68 protected boolean select(int timeout) throws Exception {
69 return selector.select(timeout) > 0;
70 }
71
72 @Override
73 protected boolean isSelectorEmpty() {
74 return selector.keys().isEmpty();
75 }
76
77 @Override
78 protected void wakeup() {
79 selector.wakeup();
80 }
81
82 @Override
83 protected Iterator<NioSession> allSessions() {
84 return new IoSessionIterator(selector.keys());
85 }
86
87 @Override
88 protected Iterator<NioSession> selectedSessions() {
89 return new IoSessionIterator(selector.selectedKeys());
90 }
91
92 @Override
93 protected void init(NioSession session) throws Exception {
94 SelectableChannel ch = (SelectableChannel) session.getChannel();
95 ch.configureBlocking(false);
96 session.setSelectionKey(ch.register(selector, SelectionKey.OP_READ, session));
97 }
98
99 @Override
100 protected void destroy(NioSession session) throws Exception {
101 ByteChannel ch = session.getChannel();
102 SelectionKey key = session.getSelectionKey();
103 if (key != null) {
104 key.cancel();
105 }
106 ch.close();
107 }
108
109 @Override
110 protected SessionState state(NioSession session) {
111 SelectionKey key = session.getSelectionKey();
112 if (key == null) {
113 return SessionState.PREPARING;
114 }
115
116 return key.isValid()? SessionState.OPEN : SessionState.CLOSED;
117 }
118
119 @Override
120 protected boolean isReadable(NioSession session) {
121 SelectionKey key = session.getSelectionKey();
122 return key.isValid() && key.isReadable();
123 }
124
125 @Override
126 protected boolean isWritable(NioSession session) {
127 SelectionKey key = session.getSelectionKey();
128 return key.isValid() && key.isWritable();
129 }
130
131 @Override
132 protected boolean isInterestedInRead(NioSession session) {
133 SelectionKey key = session.getSelectionKey();
134 return key.isValid() && (key.interestOps() & SelectionKey.OP_READ) != 0;
135 }
136
137 @Override
138 protected boolean isInterestedInWrite(NioSession session) {
139 SelectionKey key = session.getSelectionKey();
140 return key.isValid() && (key.interestOps() & SelectionKey.OP_WRITE) != 0;
141 }
142
143 @Override
144 protected void setInterestedInRead(NioSession session, boolean value) throws Exception {
145 SelectionKey key = session.getSelectionKey();
146 int oldInterestOps = key.interestOps();
147 int newInterestOps;
148 if (value) {
149 newInterestOps = oldInterestOps | SelectionKey.OP_READ;
150 } else {
151 newInterestOps = oldInterestOps & ~SelectionKey.OP_READ;
152 }
153 if (oldInterestOps != newInterestOps) {
154 key.interestOps(newInterestOps);
155 }
156 }
157
158 @Override
159 protected void setInterestedInWrite(NioSession session, boolean value) throws Exception {
160 SelectionKey key = session.getSelectionKey();
161 int oldInterestOps = key.interestOps();
162 int newInterestOps;
163 if (value) {
164 newInterestOps = oldInterestOps | SelectionKey.OP_WRITE;
165 } else {
166 newInterestOps = oldInterestOps & ~SelectionKey.OP_WRITE;
167 }
168 if (oldInterestOps != newInterestOps) {
169 key.interestOps(newInterestOps);
170 }
171 }
172
173 @Override
174 protected int read(NioSession session, IoBuffer buf) throws Exception {
175 return session.getChannel().read(buf.buf());
176 }
177
178 @Override
179 protected int write(NioSession session, IoBuffer buf, int length) throws Exception {
180 if (buf.remaining() <= length) {
181 return session.getChannel().write(buf.buf());
182 } else {
183 int oldLimit = buf.limit();
184 buf.limit(buf.position() + length);
185 try {
186 return session.getChannel().write(buf.buf());
187 } finally {
188 buf.limit(oldLimit);
189 }
190 }
191 }
192
193 @Override
194 protected int transferFile(NioSession session, FileRegion region, int length) throws Exception {
195 try {
196 return (int) region.getFileChannel().transferTo(region.getPosition(), length, session.getChannel());
197 } catch (IOException e) {
198
199
200 String message = e.getMessage();
201 if (message != null && message.contains("temporarily unavailable")) {
202 return 0;
203 } else {
204 throw e;
205 }
206 }
207 }
208
209 protected static class IoSessionIterator implements Iterator<NioSession> {
210 private final Iterator<SelectionKey> i;
211 private IoSessionIterator(Set<SelectionKey> keys) {
212 i = keys.iterator();
213 }
214 public boolean hasNext() {
215 return i.hasNext();
216 }
217
218 public NioSession next() {
219 SelectionKey key = i.next();
220 return (NioSession) key.attachment();
221 }
222
223 public void remove() {
224 i.remove();
225 }
226 }
227 }