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.filter.reqres;
21  
22  import java.util.NoSuchElementException;
23  import java.util.concurrent.BlockingQueue;
24  import java.util.concurrent.LinkedBlockingQueue;
25  import java.util.concurrent.ScheduledFuture;
26  import java.util.concurrent.TimeUnit;
27  
28  /**
29   * TODO Add documentation
30   * 
31   * @author The Apache MINA Project (dev@mina.apache.org)
32   * @version $Rev: 663549 $, $Date: 2008-06-05 13:56:55 +0200 (jeu, 05 jun 2008) $
33   */
34  public class Request {
35      private final Object id;
36  
37      private final Object message;
38  
39      private final long timeoutMillis;
40  
41      private volatile Runnable timeoutTask;
42  
43      private volatile ScheduledFuture<?> timeoutFuture;
44  
45      private final BlockingQueue<Object> responses;
46  
47      private volatile boolean endOfResponses;
48  
49      public Request(Object id, Object message, long timeoutMillis) {
50          this(id, message, true, timeoutMillis);
51      }
52  
53      public Request(Object id, Object message, boolean useResponseQueue,
54                     long timeoutMillis) {
55          this(id, message, useResponseQueue, timeoutMillis,
56                  TimeUnit.MILLISECONDS);
57      }
58  
59      public Request(Object id, Object message, long timeout, TimeUnit unit) {
60          this(id, message, true, timeout, unit);
61      }
62  
63      public Request(Object id, Object message, boolean useResponseQueue,
64                     long timeout, TimeUnit unit) {
65          if (id == null) {
66              throw new NullPointerException("id");
67          }
68          if (message == null) {
69              throw new NullPointerException("message");
70          }
71          if (timeout < 0) {
72              throw new IllegalArgumentException("timeout: " + timeout
73                      + " (expected: 0+)");
74          } else if (timeout == 0) {
75              timeout = Long.MAX_VALUE;
76          }
77  
78          if (unit == null) {
79              throw new NullPointerException("unit");
80          }
81  
82          this.id = id;
83          this.message = message;
84          this.responses = useResponseQueue ? new LinkedBlockingQueue<Object>() : null;
85          this.timeoutMillis = unit.toMillis(timeout);
86      }
87  
88      public Object getId() {
89          return id;
90      }
91  
92      public Object getMessage() {
93          return message;
94      }
95  
96      public long getTimeoutMillis() {
97          return timeoutMillis;
98      }
99  
100     public boolean isUseResponseQueue() {
101         return responses != null;
102     }
103 
104     public boolean hasResponse() {
105         checkUseResponseQueue();
106         return !responses.isEmpty();
107     }
108 
109     public Response awaitResponse() throws RequestTimeoutException,
110             InterruptedException {
111         checkUseResponseQueue();
112         chechEndOfResponses();
113         return convertToResponse(responses.take());
114     }
115 
116     public Response awaitResponse(long timeout, TimeUnit unit)
117             throws RequestTimeoutException, InterruptedException {
118         checkUseResponseQueue();
119         chechEndOfResponses();
120         return convertToResponse(responses.poll(timeout, unit));
121     }
122 
123     private Response convertToResponse(Object o) {
124         if (o instanceof Response) {
125             return (Response) o;
126         }
127 
128         if (o == null) {
129             return null;
130         }
131 
132         throw (RequestTimeoutException) o;
133     }
134 
135     public Response awaitResponseUninterruptibly()
136             throws RequestTimeoutException {
137         for (; ;) {
138             try {
139                 return awaitResponse();
140             } catch (InterruptedException e) {
141             }
142         }
143     }
144 
145     private void chechEndOfResponses() {
146         if (responses != null && endOfResponses && responses.isEmpty()) {
147             throw new NoSuchElementException(
148                     "All responses has been retrieved already.");
149         }
150     }
151 
152     private void checkUseResponseQueue() {
153         if (responses == null) {
154             throw new UnsupportedOperationException(
155                     "Response queue is not available; useResponseQueue is false.");
156         }
157     }
158 
159     void signal(Response response) {
160         signal0(response);
161         if (response.getType() != ResponseType.PARTIAL) {
162             endOfResponses = true;
163         }
164     }
165 
166     void signal(RequestTimeoutException e) {
167         signal0(e);
168         endOfResponses = true;
169     }
170 
171     private void signal0(Object answer) {
172         if (responses != null) {
173             responses.add(answer);
174         }
175     }
176 
177     @Override
178     public int hashCode() {
179         return getId().hashCode();
180     }
181 
182     @Override
183     public boolean equals(Object o) {
184         if (o == this) {
185             return true;
186         }
187 
188         if (o == null) {
189             return false;
190         }
191 
192         if (!(o instanceof Request)) {
193             return false;
194         }
195 
196         Request that = (Request) o;
197         return this.getId().equals(that.getId());
198     }
199 
200     @Override
201     public String toString() {
202         String timeout = getTimeoutMillis() == Long.MAX_VALUE ? "max"
203                 : String.valueOf(getTimeoutMillis());
204 
205         return "request: { id=" + getId() + ", timeout=" + timeout
206                 + ", message=" + getMessage() + " }";
207     }
208 
209     Runnable getTimeoutTask() {
210         return timeoutTask;
211     }
212 
213     void setTimeoutTask(Runnable timeoutTask) {
214         this.timeoutTask = timeoutTask;
215     }
216 
217     ScheduledFuture<?> getTimeoutFuture() {
218         return timeoutFuture;
219     }
220 
221     void setTimeoutFuture(ScheduledFuture<?> timeoutFuture) {
222         this.timeoutFuture = timeoutFuture;
223     }
224 }