001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *
019: */
020: package org.apache.mina.transport.socket.nio;
021:
022: import java.io.IOException;
023: import java.nio.channels.ByteChannel;
024: import java.nio.channels.SelectableChannel;
025: import java.nio.channels.SelectionKey;
026: import java.nio.channels.Selector;
027: import java.util.Iterator;
028: import java.util.Set;
029: import java.util.concurrent.Executor;
030:
031: import org.apache.mina.common.AbstractPollingIoProcessor;
032: import org.apache.mina.common.FileRegion;
033: import org.apache.mina.common.IoBuffer;
034: import org.apache.mina.common.RuntimeIoException;
035:
036: /**
037: *
038: * @author Apache MINA Project (dev@mina.apache.org)
039: * @version $Rev: 618575 $, $Date: 2008-02-05 01:35:28 -0700 (Tue, 05 Feb 2008) $
040: */
041: public final class NioProcessor extends
042: AbstractPollingIoProcessor<NioSession> {
043:
044: private static Selector newSelector() {
045: try {
046: return Selector.open();
047: } catch (IOException e) {
048: throw new RuntimeIoException("Failed to open a selector.",
049: e);
050: }
051: }
052:
053: private final Selector selector;
054:
055: public NioProcessor(Executor executor) {
056: super (executor);
057: this .selector = newSelector();
058: }
059:
060: @Override
061: protected void dispose0() throws Exception {
062: selector.close();
063: }
064:
065: @Override
066: protected boolean select(int timeout) throws Exception {
067: return selector.select(timeout) > 0;
068: }
069:
070: @Override
071: protected void wakeup() {
072: selector.wakeup();
073: }
074:
075: @Override
076: protected Iterator<NioSession> allSessions() {
077: return new IoSessionIterator(selector.keys());
078: }
079:
080: @Override
081: protected Iterator<NioSession> selectedSessions() {
082: return new IoSessionIterator(selector.selectedKeys());
083: }
084:
085: @Override
086: protected void init(NioSession session) throws Exception {
087: SelectableChannel ch = (SelectableChannel) session.getChannel();
088: ch.configureBlocking(false);
089: session.setSelectionKey(ch.register(selector,
090: SelectionKey.OP_READ, session));
091: }
092:
093: @Override
094: protected void destroy(NioSession session) throws Exception {
095: ByteChannel ch = session.getChannel();
096: SelectionKey key = session.getSelectionKey();
097: if (key != null) {
098: key.cancel();
099: }
100: ch.close();
101: }
102:
103: @Override
104: protected SessionState state(NioSession session) {
105: SelectionKey key = session.getSelectionKey();
106: if (key == null) {
107: return SessionState.PREPARING;
108: }
109:
110: return key.isValid() ? SessionState.OPEN : SessionState.CLOSED;
111: }
112:
113: @Override
114: protected boolean isReadable(NioSession session) {
115: SelectionKey key = session.getSelectionKey();
116: return key.isValid() && key.isReadable();
117: }
118:
119: @Override
120: protected boolean isWritable(NioSession session) {
121: SelectionKey key = session.getSelectionKey();
122: return key.isValid() && key.isWritable();
123: }
124:
125: @Override
126: protected boolean isInterestedInRead(NioSession session) {
127: SelectionKey key = session.getSelectionKey();
128: return key.isValid()
129: && (key.interestOps() & SelectionKey.OP_READ) != 0;
130: }
131:
132: @Override
133: protected boolean isInterestedInWrite(NioSession session) {
134: SelectionKey key = session.getSelectionKey();
135: return key.isValid()
136: && (key.interestOps() & SelectionKey.OP_WRITE) != 0;
137: }
138:
139: @Override
140: protected void setInterestedInRead(NioSession session, boolean value)
141: throws Exception {
142: SelectionKey key = session.getSelectionKey();
143: if (value) {
144: key.interestOps(key.interestOps() | SelectionKey.OP_READ);
145: } else {
146: key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
147: }
148: }
149:
150: @Override
151: protected void setInterestedInWrite(NioSession session,
152: boolean value) throws Exception {
153: SelectionKey key = session.getSelectionKey();
154: if (value) {
155: key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
156: } else {
157: key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
158: }
159: }
160:
161: @Override
162: protected int read(NioSession session, IoBuffer buf)
163: throws Exception {
164: return session.getChannel().read(buf.buf());
165: }
166:
167: @Override
168: protected int write(NioSession session, IoBuffer buf, int length)
169: throws Exception {
170: if (buf.remaining() <= length) {
171: return session.getChannel().write(buf.buf());
172: } else {
173: int oldLimit = buf.limit();
174: buf.limit(buf.position() + length);
175: try {
176: return session.getChannel().write(buf.buf());
177: } finally {
178: buf.limit(oldLimit);
179: }
180: }
181: }
182:
183: @Override
184: protected int transferFile(NioSession session, FileRegion region,
185: int length) throws Exception {
186: try {
187: return (int) region.getFileChannel().transferTo(
188: region.getPosition(), length, session.getChannel());
189: } catch (IOException e) {
190: // Check to see if the IOException is being thrown due to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5103988
191: if (e.getMessage().contains(
192: "Resource temporarily unavailable")) {
193: return 0;
194: } else {
195: throw e;
196: }
197: }
198: }
199:
200: protected static class IoSessionIterator implements
201: Iterator<NioSession> {
202: private final Iterator<SelectionKey> i;
203:
204: private IoSessionIterator(Set<SelectionKey> keys) {
205: i = keys.iterator();
206: }
207:
208: public boolean hasNext() {
209: return i.hasNext();
210: }
211:
212: public NioSession next() {
213: SelectionKey key = i.next();
214: return (NioSession) key.attachment();
215: }
216:
217: public void remove() {
218: i.remove();
219: }
220: }
221: }
|