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.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   * @author Apache MINA Project (dev@mina.apache.org)
39   * @version $Rev: 618575 $, $Date: 2008-02-05 01:35:28 -0700 (Tue, 05 Feb 2008) $
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             // Check to see if the IOException is being thrown due to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5103988
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 }