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.util;
    21
    22  import java.io.Serializable;
    23  import java.util.Arrays;
    24
    25  /**
    26   * A unbounded stack with expiration.
    27   *
    28   * @author The Apache Directory Project (mina-dev@directory.apache.org)
    29   * @version $Rev: 555855 $, $Date: 2007-07-13 05:19:00 +0200 (Fri, 13 Jul 2007) $
    30   */
    31  public class ExpiringStack implements Serializable {
    32      private static final long serialVersionUID = 3546919169401434168L;
    33
    34      private static final int DEFAULT_CAPACITY = 4;
    35
    36      private Object[] items;
    37
    38      private long[] timestamps;
    39
    40      private int size = 0;
    41
    42      /**
    43       * Construct a new, empty stack.
    44       */
    45      public ExpiringStack() {
    46          items = new Object[DEFAULT_CAPACITY];
    47          timestamps = new long[DEFAULT_CAPACITY];
    48      }
    49
    50      /**
    51       * Clears this stack.
    52       */
    53      public void clear() {
    54          Arrays.fill(items, null);
    55          size = 0;
    56      }
    57
    58      /**
    59       * Pops from this stack.
    60       *
    61       * @return <code>null</code>, if this stack is empty or the element is
    62       *         really <code>null</code>.
    63       */
    64      public Object pop() {
    65          if (size == 0) {
    66              return null;
    67          }
    68
    69          int pos = size - 1;
    70          Object ret = items[pos];
    71          items[pos] = null;
    72          size--;
    73
    74          return ret;
    75      }
    76
    77      /**
    78       * Push into this stack.
    79       */
    80      public void push(Object obj) {
    81          if (size == items.length) {
    82              // expand queue
    83              final int oldLen = items.length;
    84              Object[] tmpItems = new Object[oldLen * 2];
    85              System.arraycopy(items, 0, tmpItems, 0, size);
    86              long[] tmpTimestamps = new long[oldLen * 2];
    87              System.arraycopy(timestamps, 0, tmpTimestamps, 0, size);
    88              items = tmpItems;
    89              timestamps = tmpTimestamps;
    90          }
    91
    92          items[size] = obj;
    93          timestamps[size] = System.currentTimeMillis();
    94          size++;
    95      }
    96
    97      public void remove(Object o) {
    98          for (int i = size - 1; i >= 0; i--) {
    99              if (items[i] == o) {
    100                 System.arraycopy(items, i + 1, items, i, size - i - 1);
    101                 System
    102                         .arraycopy(timestamps, i + 1, timestamps, i, size - i
    103                                 - 1);
    104                 items[size - 1] = null;
    105                 size--;
    106                 break;
    107             }
    108         }
    109     }
    110
    111     public void expireBefore(long time) {
    112         int i;
    113         for (i = 0; i < size; i++) {
    114             if (timestamps[i] >= time) {
    115                 break;
    116             }
    117         }
    118
    119         if (i > 0) {
    120             size -= i;
    121             System.arraycopy(items, i, items, 0, size);
    122             System.arraycopy(timestamps, i, timestamps, 0, size);
    123             Arrays.fill(items, size, items.length, null);
    124         }
    125     }
    126
    127     /**
    128      * Returns the first element of the stack.
    129      *
    130      * @return <code>null</code>, if the stack is empty, or the element is
    131      *         really <code>null</code>.
    132      */
    133     public Object first() {
    134         if (size == 0) {
    135             return null;
    136         }
    137
    138         return items[size - 1];
    139     }
    140
    141     public Object last() {
    142         if (size == 0) {
    143             return null;
    144         }
    145
    146         return items[0];
    147     }
    148
    149     /**
    150      * Returns <code>true</code> if the stack is empty.
    151      */
    152     public boolean isEmpty() {
    153         return (size == 0);
    154     }
    155
    156     /**
    157      * Returns the number of elements in the stack.
    158      */
    159     public int size() {
    160         return size;
    161     }
    162 }