KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > buffer > BoundedBuffer


1 /*
2  * Copyright 2005-2006 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.collections.buffer;
17
18 import java.io.PrintWriter JavaDoc;
19 import java.io.StringWriter JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.Iterator JavaDoc;
22
23 import org.apache.commons.collections.BoundedCollection;
24 import org.apache.commons.collections.Buffer;
25 import org.apache.commons.collections.BufferOverflowException;
26 import org.apache.commons.collections.BufferUnderflowException;
27 import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
28
29 /**
30  * Decorates another <code>Buffer</code> to ensure a fixed maximum size.
31  * <p>
32  * Note: This class should only be used if you need to add bounded
33  * behaviour to another buffer. If you just want a bounded buffer then
34  * you should use {@link BoundedFifoBuffer} or {@link CircularFifoBuffer}.
35  * <p>
36  * The decoration methods allow you to specify a timeout value.
37  * This alters the behaviour of the add methods when the buffer is full.
38  * Normally, when the buffer is full, the add method will throw an exception.
39  * With a timeout, the add methods will wait for up to the timeout period
40  * to try and add the elements.
41  *
42  * @author James Carman
43  * @author Stephen Colebourne
44  * @version $Revision: 405927 $ $Date: 2006-05-12 23:57:03 +0100 (Fri, 12 May 2006) $
45  * @since Commons Collections 3.2
46  */

47 public class BoundedBuffer extends SynchronizedBuffer implements BoundedCollection {
48
49     /** The serialization version. */
50     private static final long serialVersionUID = 1536432911093974264L;
51
52     /** The maximum size. */
53     private final int maximumSize;
54     /** The timeout milliseconds. */
55     private final long timeout;
56
57     /**
58      * Factory method to create a bounded buffer.
59      * <p>
60      * When the buffer is full, it will immediately throw a
61      * <code>BufferOverflowException</code> on calling <code>add()</code>.
62      *
63      * @param buffer the buffer to decorate, must not be null
64      * @param maximumSize the maximum size, must be size one or greater
65      * @return a new bounded buffer
66      * @throws IllegalArgumentException if the buffer is null
67      * @throws IllegalArgumentException if the maximum size is zero or less
68      */

69     public static BoundedBuffer decorate(Buffer buffer, int maximumSize) {
70         return new BoundedBuffer(buffer, maximumSize, 0L);
71     }
72
73     /**
74      * Factory method to create a bounded buffer that blocks for a maximum
75      * amount of time.
76      *
77      * @param buffer the buffer to decorate, must not be null
78      * @param maximumSize the maximum size, must be size one or greater
79      * @param timeout the maximum amount of time to wait in milliseconds
80      * @return a new bounded buffer
81      * @throws IllegalArgumentException if the buffer is null
82      * @throws IllegalArgumentException if the maximum size is zero or less
83      */

84     public static BoundedBuffer decorate(Buffer buffer, int maximumSize, long timeout) {
85         return new BoundedBuffer(buffer, maximumSize, timeout);
86     }
87
88     //-----------------------------------------------------------------------
89
/**
90      * Constructor that wraps (not copies) another buffer, making it bounded
91      * waiting only up to a maximum amount of time.
92      *
93      * @param buffer the buffer to wrap, must not be null
94      * @param maximumSize the maximum size, must be size one or greater
95      * @param timeout the maximum amount of time to wait
96      * @throws IllegalArgumentException if the buffer is null
97      * @throws IllegalArgumentException if the maximum size is zero or less
98      */

99     protected BoundedBuffer(Buffer buffer, int maximumSize, long timeout) {
100         super(buffer);
101         if (maximumSize < 1) {
102             throw new IllegalArgumentException JavaDoc();
103         }
104         this.maximumSize = maximumSize;
105         this.timeout = timeout;
106     }
107
108     //-----------------------------------------------------------------------
109
public Object JavaDoc remove() {
110         synchronized (lock) {
111             Object JavaDoc returnValue = getBuffer().remove();
112             lock.notifyAll();
113             return returnValue;
114         }
115     }
116
117     public boolean add(Object JavaDoc o) {
118         synchronized (lock) {
119             timeoutWait(1);
120             return getBuffer().add(o);
121         }
122     }
123
124     public boolean addAll(final Collection JavaDoc c) {
125         synchronized (lock) {
126             timeoutWait(c.size());
127             return getBuffer().addAll(c);
128         }
129     }
130
131     public Iterator JavaDoc iterator() {
132         return new NotifyingIterator(collection.iterator());
133     }
134
135     private void timeoutWait(final int nAdditions) {
136         // method synchronized by callers
137
if (nAdditions > maximumSize) {
138             throw new BufferOverflowException(
139                     "Buffer size cannot exceed " + maximumSize);
140         }
141         if (timeout <= 0) {
142             // no wait period (immediate timeout)
143
if (getBuffer().size() + nAdditions > maximumSize) {
144                 throw new BufferOverflowException(
145                         "Buffer size cannot exceed " + maximumSize);
146             }
147             return;
148         }
149         final long expiration = System.currentTimeMillis() + timeout;
150         long timeLeft = expiration - System.currentTimeMillis();
151         while (timeLeft > 0 && getBuffer().size() + nAdditions > maximumSize) {
152             try {
153                 lock.wait(timeLeft);
154                 timeLeft = expiration - System.currentTimeMillis();
155             } catch (InterruptedException JavaDoc ex) {
156                 PrintWriter JavaDoc out = new PrintWriter JavaDoc(new StringWriter JavaDoc());
157                 ex.printStackTrace(out);
158                 throw new BufferUnderflowException(
159                     "Caused by InterruptedException: " + out.toString());
160             }
161         }
162         if (getBuffer().size() + nAdditions > maximumSize) {
163             throw new BufferOverflowException("Timeout expired");
164         }
165     }
166
167     public boolean isFull() {
168         // size() is synchronized
169
return (size() == maxSize());
170     }
171
172     public int maxSize() {
173         return maximumSize;
174     }
175
176     //-----------------------------------------------------------------------
177
/**
178      * BoundedBuffer iterator.
179      */

180     private class NotifyingIterator extends AbstractIteratorDecorator {
181
182         public NotifyingIterator(Iterator JavaDoc it) {
183             super(it);
184         }
185
186         public void remove() {
187             synchronized (lock) {
188                 iterator.remove();
189                 lock.notifyAll();
190             }
191         }
192     }
193 }
194
Popular Tags