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