001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.collections.collection;
018
019 import java.io.Serializable;
020 import java.util.Collection;
021 import java.util.Iterator;
022
023 /**
024 * Decorates another <code>Collection</code> to synchronize its behaviour
025 * for a multi-threaded environment.
026 * <p>
027 * Iterators must be manually synchronized:
028 * <pre>
029 * synchronized (coll) {
030 * Iterator it = coll.iterator();
031 * // do stuff with iterator
032 * }
033 * </pre>
034 * <p>
035 * This class is Serializable from Commons Collections 3.1.
036 *
037 * @since Commons Collections 3.0
038 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
039 *
040 * @author Stephen Colebourne
041 */
042 public class SynchronizedCollection implements Collection, Serializable {
043
044 /** Serialization version */
045 private static final long serialVersionUID = 2412805092710877986L;
046
047 /** The collection to decorate */
048 protected final Collection collection;
049 /** The object to lock on, needed for List/SortedSet views */
050 protected final Object lock;
051
052 /**
053 * Factory method to create a synchronized collection.
054 *
055 * @param coll the collection to decorate, must not be null
056 * @return a new synchronized collection
057 * @throws IllegalArgumentException if collection is null
058 */
059 public static Collection decorate(Collection coll) {
060 return new SynchronizedCollection(coll);
061 }
062
063 //-----------------------------------------------------------------------
064 /**
065 * Constructor that wraps (not copies).
066 *
067 * @param collection the collection to decorate, must not be null
068 * @throws IllegalArgumentException if the collection is null
069 */
070 protected SynchronizedCollection(Collection collection) {
071 if (collection == null) {
072 throw new IllegalArgumentException("Collection must not be null");
073 }
074 this.collection = collection;
075 this.lock = this;
076 }
077
078 /**
079 * Constructor that wraps (not copies).
080 *
081 * @param collection the collection to decorate, must not be null
082 * @param lock the lock object to use, must not be null
083 * @throws IllegalArgumentException if the collection is null
084 */
085 protected SynchronizedCollection(Collection collection, Object lock) {
086 if (collection == null) {
087 throw new IllegalArgumentException("Collection must not be null");
088 }
089 this.collection = collection;
090 this.lock = lock;
091 }
092
093 //-----------------------------------------------------------------------
094 public boolean add(Object object) {
095 synchronized (lock) {
096 return collection.add(object);
097 }
098 }
099
100 public boolean addAll(Collection coll) {
101 synchronized (lock) {
102 return collection.addAll(coll);
103 }
104 }
105
106 public void clear() {
107 synchronized (lock) {
108 collection.clear();
109 }
110 }
111
112 public boolean contains(Object object) {
113 synchronized (lock) {
114 return collection.contains(object);
115 }
116 }
117
118 public boolean containsAll(Collection coll) {
119 synchronized (lock) {
120 return collection.containsAll(coll);
121 }
122 }
123
124 public boolean isEmpty() {
125 synchronized (lock) {
126 return collection.isEmpty();
127 }
128 }
129
130 /**
131 * Iterators must be manually synchronized.
132 * <pre>
133 * synchronized (coll) {
134 * Iterator it = coll.iterator();
135 * // do stuff with iterator
136 * }
137 *
138 * @return an iterator that must be manually synchronized on the collection
139 */
140 public Iterator iterator() {
141 return collection.iterator();
142 }
143
144 public Object[] toArray() {
145 synchronized (lock) {
146 return collection.toArray();
147 }
148 }
149
150 public Object[] toArray(Object[] object) {
151 synchronized (lock) {
152 return collection.toArray(object);
153 }
154 }
155
156 public boolean remove(Object object) {
157 synchronized (lock) {
158 return collection.remove(object);
159 }
160 }
161
162 public boolean removeAll(Collection coll) {
163 synchronized (lock) {
164 return collection.removeAll(coll);
165 }
166 }
167
168 public boolean retainAll(Collection coll) {
169 synchronized (lock) {
170 return collection.retainAll(coll);
171 }
172 }
173
174 public int size() {
175 synchronized (lock) {
176 return collection.size();
177 }
178 }
179
180 public boolean equals(Object object) {
181 synchronized (lock) {
182 if (object == this) {
183 return true;
184 }
185 return collection.equals(object);
186 }
187 }
188
189 public int hashCode() {
190 synchronized (lock) {
191 return collection.hashCode();
192 }
193 }
194
195 public String toString() {
196 synchronized (lock) {
197 return collection.toString();
198 }
199 }
200
201 }