View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections.collection;
18  
19  import java.io.Serializable;
20  import java.util.Collection;
21  import java.util.Iterator;
22  
23  /**
24   * Decorates another {@link Collection} to synchronize its behaviour
25   * for a multi-threaded environment.
26   * <p>
27   * Iterators must be manually synchronized:
28   * <pre>
29   * synchronized (coll) {
30   *   Iterator it = coll.iterator();
31   *   // do stuff with iterator
32   * }
33   * </pre>
34   * <p>
35   * This class is Serializable from Commons Collections 3.1.
36   *
37   * @param <E> the type of the elements in the collection
38   * @since 3.0
39   * @version $Id: SynchronizedCollection.java 1443602 2013-02-07 17:00:23Z tn $
40   */
41  public class SynchronizedCollection<E> implements Collection<E>, Serializable {
42  
43      /** Serialization version */
44      private static final long serialVersionUID = 2412805092710877986L;
45  
46      /** The collection to decorate */
47      protected final Collection<E> collection;
48      /** The object to lock on, needed for List/SortedSet views */
49      protected final Object lock;
50  
51      /**
52       * Factory method to create a synchronized collection.
53       * 
54       * @param <T> the type of the elements in the collection
55       * @param coll  the collection to decorate, must not be null
56       * @return a new synchronized collection
57       * @throws IllegalArgumentException if collection is null
58       */
59      public static <T> SynchronizedCollection<T> synchronizedCollection(final Collection<T> coll) {
60          return new SynchronizedCollection<T>(coll);
61      }
62  
63      //-----------------------------------------------------------------------
64      /**
65       * Constructor that wraps (not copies).
66       * 
67       * @param collection  the collection to decorate, must not be null
68       * @throws IllegalArgumentException if the collection is null
69       */
70      protected SynchronizedCollection(final Collection<E> collection) {
71          if (collection == null) {
72              throw new IllegalArgumentException("Collection must not be null");
73          }
74          this.collection = collection;
75          this.lock = this;
76      }
77  
78      /**
79       * Constructor that wraps (not copies).
80       * 
81       * @param collection  the collection to decorate, must not be null
82       * @param lock  the lock object to use, must not be null
83       * @throws IllegalArgumentException if the collection is null
84       */
85      protected SynchronizedCollection(final Collection<E> collection, final Object lock) {
86          if (collection == null) {
87              throw new IllegalArgumentException("Collection must not be null");
88          }
89          this.collection = collection;
90          this.lock = lock;
91      }
92  
93      /**
94       * Gets the collection being decorated.
95       * 
96       * @return the decorated collection
97       */
98      protected Collection<E> decorated() {
99          return collection;
100     }
101 
102     //-----------------------------------------------------------------------
103     
104     public boolean add(final E object) {
105         synchronized (lock) {
106             return decorated().add(object);
107         }
108     }
109 
110     public boolean addAll(final Collection<? extends E> coll) {
111         synchronized (lock) {
112             return decorated().addAll(coll);
113         }
114     }
115 
116     public void clear() {
117         synchronized (lock) {
118             decorated().clear();
119         }
120     }
121 
122     public boolean contains(final Object object) {
123         synchronized (lock) {
124             return decorated().contains(object);
125         }
126     }
127 
128     public boolean containsAll(final Collection<?> coll) {
129         synchronized (lock) {
130             return decorated().containsAll(coll);
131         }
132     }
133 
134     public boolean isEmpty() {
135         synchronized (lock) {
136             return decorated().isEmpty();
137         }
138     }
139 
140     /**
141      * Iterators must be manually synchronized.
142      * <pre>
143      * synchronized (coll) {
144      *   Iterator it = coll.iterator();
145      *   // do stuff with iterator
146      * }
147      * 
148      * @return an iterator that must be manually synchronized on the collection
149      */
150     public Iterator<E> iterator() {
151         return decorated().iterator();
152     }
153 
154     public Object[] toArray() {
155         synchronized (lock) {
156             return decorated().toArray();
157         }
158     }
159 
160     public <T> T[] toArray(final T[] object) {
161         synchronized (lock) {
162             return decorated().toArray(object);
163         }
164     }
165 
166     public boolean remove(final Object object) {
167         synchronized (lock) {
168             return decorated().remove(object);
169         }
170     }
171 
172     public boolean removeAll(final Collection<?> coll) {
173         synchronized (lock) {
174             return decorated().removeAll(coll);
175         }
176     }
177 
178     public boolean retainAll(final Collection<?> coll) {
179         synchronized (lock) {
180             return decorated().retainAll(coll);
181         }
182     }
183 
184     public int size() {
185         synchronized (lock) {
186             return decorated().size();
187         }
188     }
189 
190     @Override
191     public boolean equals(final Object object) {
192         synchronized (lock) {
193             if (object == this) {
194                 return true;
195             }
196             return object == this || decorated().equals(object);
197         }
198     }
199 
200     @Override
201     public int hashCode() {
202         synchronized (lock) {
203             return decorated().hashCode();
204         }
205     }
206 
207     @Override
208     public String toString() {
209         synchronized (lock) {
210             return decorated().toString();
211         }
212     }
213 
214 }