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.handler;
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.OutputStream;
25  import java.net.SocketTimeoutException;
26  
27  import org.apache.mina.common.ByteBuffer;
28  import org.apache.mina.common.IdleStatus;
29  import org.apache.mina.common.IoHandler;
30  import org.apache.mina.common.IoHandlerAdapter;
31  import org.apache.mina.common.IoSession;
32  import org.apache.mina.handler.support.IoSessionInputStream;
33  import org.apache.mina.handler.support.IoSessionOutputStream;
34  import org.apache.mina.util.SessionLog;
35  
36  /**
37   * A {@link IoHandler} that adapts asynchronous MINA events to stream I/O.
38   * <p>
39   * Please extend this class and implement
40   * {@link #processStreamIo(IoSession, InputStream, OutputStream)} to
41   * execute your stream I/O logic; <b>please note that you must forward
42   * the process request to other thread or thread pool.</b>
43   * 
44   * @author The Apache Directory Project (mina-dev@directory.apache.org)
45   * @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (금, 13  7월 2007) $
46   */
47  public abstract class StreamIoHandler extends IoHandlerAdapter {
48      private static final String KEY_IN = StreamIoHandler.class.getName()
49              + ".in";
50  
51      private static final String KEY_OUT = StreamIoHandler.class.getName()
52              + ".out";
53  
54      private int readTimeout;
55  
56      private int writeTimeout;
57  
58      protected StreamIoHandler() {
59      }
60  
61      /**
62       * Implement this method to execute your stream I/O logic;
63       * <b>please note that you must forward the process request to other
64       * thread or thread pool.</b>
65       */
66      protected abstract void processStreamIo(IoSession session, InputStream in,
67              OutputStream out);
68  
69      /**
70       * Returns read timeout in seconds.
71       * The default value is <tt>0</tt> (disabled).
72       */
73      public int getReadTimeout() {
74          return readTimeout;
75      }
76  
77      /**
78       * Sets read timeout in seconds.
79       * The default value is <tt>0</tt> (disabled).
80       */
81      public void setReadTimeout(int readTimeout) {
82          this.readTimeout = readTimeout;
83      }
84  
85      /**
86       * Returns write timeout in seconds.
87       * The default value is <tt>0</tt> (disabled).
88       */
89      public int getWriteTimeout() {
90          return writeTimeout;
91      }
92  
93      /**
94       * Sets write timeout in seconds.
95       * The default value is <tt>0</tt> (disabled).
96       */
97      public void setWriteTimeout(int writeTimeout) {
98          this.writeTimeout = writeTimeout;
99      }
100 
101     /**
102      * Initializes streams and timeout settings.
103      */
104     public void sessionOpened(IoSession session) {
105         // Set timeouts
106         session.setWriteTimeout(writeTimeout);
107         session.setIdleTime(IdleStatus.READER_IDLE, readTimeout);
108 
109         // Create streams
110         InputStream in = new IoSessionInputStream();
111         OutputStream out = new IoSessionOutputStream(session);
112         session.setAttribute(KEY_IN, in);
113         session.setAttribute(KEY_OUT, out);
114         processStreamIo(session, in, out);
115     }
116 
117     /**
118      * Closes streams
119      */
120     public void sessionClosed(IoSession session) throws Exception {
121         final InputStream in = (InputStream) session.getAttribute(KEY_IN);
122         final OutputStream out = (OutputStream) session.getAttribute(KEY_OUT);
123         try {
124             in.close();
125         } finally {
126             out.close();
127         }
128     }
129 
130     /**
131      * Forwards read data to input stream.
132      */
133     public void messageReceived(IoSession session, Object buf) {
134         final IoSessionInputStream in = (IoSessionInputStream) session
135                 .getAttribute(KEY_IN);
136         in.write((ByteBuffer) buf);
137     }
138 
139     /**
140      * Forwards caught exceptions to input stream.
141      */
142     public void exceptionCaught(IoSession session, Throwable cause) {
143         final IoSessionInputStream in = (IoSessionInputStream) session
144                 .getAttribute(KEY_IN);
145 
146         IOException e = null;
147         if (cause instanceof StreamIoException) {
148             e = (IOException) cause.getCause();
149         } else if (cause instanceof IOException) {
150             e = (IOException) cause;
151         }
152 
153         if (e != null && in != null) {
154             in.throwException(e);
155         } else {
156             SessionLog.warn(session, "Unexpected exception.", cause);
157             session.close();
158         }
159     }
160 
161     /**
162      * Handles read timeout.
163      */
164     public void sessionIdle(IoSession session, IdleStatus status) {
165         if (status == IdleStatus.READER_IDLE) {
166             throw new StreamIoException(new SocketTimeoutException(
167                     "Read timeout"));
168         }
169     }
170 
171     private static class StreamIoException extends RuntimeException {
172         private static final long serialVersionUID = 3976736960742503222L;
173 
174         public StreamIoException(IOException cause) {
175             super(cause);
176         }
177     }
178 }