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