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 }