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  import java.net.SocketAddress;
32  import java.nio.channels.Channel;
33  import java.nio.channels.SelectionKey;
34  
35  import org.apache.http.annotation.ThreadSafe;
36  import org.apache.http.nio.reactor.IOSession;
37  import org.apache.http.nio.reactor.SessionRequest;
38  import org.apache.http.nio.reactor.SessionRequestCallback;
39  import org.apache.http.util.Args;
40  
41  /**
42   * Default implementation of {@link SessionRequest}.
43   *
44   * @since 4.0
45   */
46  @ThreadSafe
47  public class SessionRequestImpl implements SessionRequest {
48  
49      private volatile boolean completed;
50      private volatile SelectionKey key;
51  
52      private final SocketAddress remoteAddress;
53      private final SocketAddress localAddress;
54      private final Object attachment;
55      private final SessionRequestCallback callback;
56  
57      private volatile int connectTimeout;
58      private volatile IOSession session = null;
59      private volatile IOException exception = null;
60  
61      public SessionRequestImpl(
62              final SocketAddress remoteAddress,
63              final SocketAddress localAddress,
64              final Object attachment,
65              final SessionRequestCallback callback) {
66          super();
67          Args.notNull(remoteAddress, "Remote address");
68          this.remoteAddress = remoteAddress;
69          this.localAddress = localAddress;
70          this.attachment = attachment;
71          this.callback = callback;
72          this.connectTimeout = 0;
73      }
74  
75      public SocketAddress getRemoteAddress() {
76          return this.remoteAddress;
77      }
78  
79      public SocketAddress getLocalAddress() {
80          return this.localAddress;
81      }
82  
83      public Object getAttachment() {
84          return this.attachment;
85      }
86  
87      public boolean isCompleted() {
88          return this.completed;
89      }
90  
91      protected void setKey(final SelectionKey key) {
92          this.key = key;
93      }
94  
95      public void waitFor() throws InterruptedException {
96          if (this.completed) {
97              return;
98          }
99          synchronized (this) {
100             while (!this.completed) {
101                 wait();
102             }
103         }
104     }
105 
106     public IOSession getSession() {
107         synchronized (this) {
108             return this.session;
109         }
110     }
111 
112     public IOException getException() {
113         synchronized (this) {
114             return this.exception;
115         }
116     }
117 
118     public void completed(final IOSession session) {
119         Args.notNull(session, "Session");
120         if (this.completed) {
121             return;
122         }
123         this.completed = true;
124         synchronized (this) {
125             this.session = session;
126             if (this.callback != null) {
127                 this.callback.completed(this);
128             }
129             notifyAll();
130         }
131     }
132 
133     public void failed(final IOException exception) {
134         if (exception == null) {
135             return;
136         }
137         if (this.completed) {
138             return;
139         }
140         this.completed = true;
141         final SelectionKey key = this.key;
142         if (key != null) {
143             key.cancel();
144             final Channel channel = key.channel();
145             if (channel.isOpen()) {
146                 try {
147                     channel.close();
148                 } catch (final IOException ignore) {}
149             }
150         }
151         synchronized (this) {
152             this.exception = exception;
153             if (this.callback != null) {
154                 this.callback.failed(this);
155             }
156             notifyAll();
157         }
158     }
159 
160     public void timeout() {
161         if (this.completed) {
162             return;
163         }
164         this.completed = true;
165         final SelectionKey key = this.key;
166         if (key != null) {
167             key.cancel();
168             final Channel channel = key.channel();
169             if (channel.isOpen()) {
170                 try {
171                     channel.close();
172                 } catch (final IOException ignore) {}
173             }
174         }
175         synchronized (this) {
176             if (this.callback != null) {
177                 this.callback.timeout(this);
178             }
179         }
180     }
181 
182     public int getConnectTimeout() {
183         return this.connectTimeout;
184     }
185 
186     public void setConnectTimeout(final int timeout) {
187         if (this.connectTimeout != timeout) {
188             this.connectTimeout = timeout;
189             final SelectionKey key = this.key;
190             if (key != null) {
191                 key.selector().wakeup();
192             }
193         }
194     }
195 
196     public void cancel() {
197         if (this.completed) {
198             return;
199         }
200         this.completed = true;
201         final SelectionKey key = this.key;
202         if (key != null) {
203             key.cancel();
204             final Channel channel = key.channel();
205             if (channel.isOpen()) {
206                 try {
207                     channel.close();
208                 } catch (final IOException ignore) {}
209             }
210         }
211         synchronized (this) {
212             if (this.callback != null) {
213                 this.callback.cancelled(this);
214             }
215             notifyAll();
216         }
217     }
218 
219 }