View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.impl.nio.reactor;
29  
30  import java.io.IOException;
31  
32  import org.apache.http.annotation.Immutable;
33  import org.apache.http.nio.reactor.IOEventDispatch;
34  import org.apache.http.nio.reactor.IOSession;
35  import org.apache.http.nio.reactor.ssl.SSLIOSession;
36  import org.apache.http.util.Asserts;
37  
38  /**
39   * Abstract {@link IOEventDispatch} implementation that supports both plain (non-encrypted)
40   * and SSL encrypted HTTP connections.
41   *
42   * @param <T> the connection type.
43   * @since 4.2
44   */
45  @Immutable // provided injected dependencies are immutable
46  public abstract class AbstractIODispatch<T> implements IOEventDispatch {
47  
48      protected abstract T createConnection(IOSession session);
49  
50      protected abstract void onConnected(T conn);
51  
52      protected abstract void onClosed(T conn);
53  
54      protected abstract void onException(T conn, IOException ex);
55  
56      protected abstract void onInputReady(T conn);
57  
58      protected abstract void onOutputReady(T conn);
59  
60      protected abstract void onTimeout(T conn);
61  
62      private void ensureNotNull(final T conn) {
63          Asserts.notNull(conn, "HTTP connection");
64      }
65  
66      @Override
67      public void connected(final IOSession session) {
68          @SuppressWarnings("unchecked")
69          T conn = (T) session.getAttribute(IOEventDispatch.CONNECTION_KEY);
70          try {
71              if (conn == null) {
72                  conn = createConnection(session);
73                  session.setAttribute(IOEventDispatch.CONNECTION_KEY, conn);
74              }
75              onConnected(conn);
76              final SSLIOSession ssliosession = (SSLIOSession) session.getAttribute(
77                      SSLIOSession.SESSION_KEY);
78              if (ssliosession != null) {
79                  try {
80                      synchronized (ssliosession) {
81                          if (!ssliosession.isInitialized()) {
82                              ssliosession.initialize();
83                          }
84                      }
85                  } catch (final IOException ex) {
86                      onException(conn, ex);
87                      ssliosession.shutdown();
88                  }
89              }
90          } catch (final RuntimeException ex) {
91              session.shutdown();
92              throw ex;
93          }
94      }
95  
96      @Override
97      public void disconnected(final IOSession session) {
98          @SuppressWarnings("unchecked")
99          final
100         T conn = (T) session.getAttribute(IOEventDispatch.CONNECTION_KEY);
101         if (conn != null) {
102             onClosed(conn);
103         }
104     }
105 
106     @Override
107     public void inputReady(final IOSession session) {
108         @SuppressWarnings("unchecked")
109         final
110         T conn = (T) session.getAttribute(IOEventDispatch.CONNECTION_KEY);
111         try {
112             ensureNotNull(conn);
113             final SSLIOSession ssliosession = (SSLIOSession) session.getAttribute(
114                     SSLIOSession.SESSION_KEY);
115             if (ssliosession == null) {
116                 onInputReady(conn);
117             } else {
118                 try {
119                     if (!ssliosession.isInitialized()) {
120                         ssliosession.initialize();
121                     }
122                     if (ssliosession.isAppInputReady()) {
123                         onInputReady(conn);
124                     }
125                     ssliosession.inboundTransport();
126                 } catch (final IOException ex) {
127                     onException(conn, ex);
128                     ssliosession.shutdown();
129                 }
130             }
131         } catch (final RuntimeException ex) {
132             session.shutdown();
133             throw ex;
134         }
135     }
136 
137     @Override
138     public void outputReady(final IOSession session) {
139         @SuppressWarnings("unchecked")
140         final
141         T conn = (T) session.getAttribute(IOEventDispatch.CONNECTION_KEY);
142         try {
143             ensureNotNull(conn);
144             final SSLIOSession ssliosession = (SSLIOSession) session.getAttribute(
145                     SSLIOSession.SESSION_KEY);
146             if (ssliosession == null) {
147                 onOutputReady(conn);
148             } else {
149                 try {
150                     if (!ssliosession.isInitialized()) {
151                         ssliosession.initialize();
152                     }
153                     if (ssliosession.isAppOutputReady()) {
154                         onOutputReady(conn);
155                     }
156                     ssliosession.outboundTransport();
157                 } catch (final IOException ex) {
158                     onException(conn, ex);
159                     ssliosession.shutdown();
160                 }
161             }
162         } catch (final RuntimeException ex) {
163             session.shutdown();
164             throw ex;
165         }
166     }
167 
168     @Override
169     public void timeout(final IOSession session) {
170         @SuppressWarnings("unchecked")
171         final
172         T conn = (T) session.getAttribute(IOEventDispatch.CONNECTION_KEY);
173         try {
174             final SSLIOSession ssliosession = (SSLIOSession) session.getAttribute(
175                     SSLIOSession.SESSION_KEY);
176             ensureNotNull(conn);
177             onTimeout(conn);
178             if (ssliosession != null) {
179                 synchronized (ssliosession) {
180                     if (ssliosession.isOutboundDone() && !ssliosession.isInboundDone()) {
181                         // The session failed to terminate cleanly
182                         ssliosession.shutdown();
183                     }
184                 }
185             }
186         } catch (final RuntimeException ex) {
187             session.shutdown();
188             throw ex;
189         }
190     }
191 
192 }