Merge pull request #71 from jentfoo/issue70

Fix ClassCastException in UnmodifiableMap as well as fix modifying unmodifiable structures through iterators
This commit is contained in:
Joshua Warner 2013-07-17 12:00:19 -07:00
commit c09f329728
2 changed files with 140 additions and 46 deletions

View File

@ -168,7 +168,7 @@ public class Collections {
}
public Iterator<T> iterator() {
return new SynchronizedIterator(lock, collection.iterator());
return new SynchronizedIterator<T>(lock, collection.iterator());
}
public boolean containsAll(Collection<?> c) {
@ -335,27 +335,27 @@ public class Collections {
}
public T set(int index, T value) {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public T remove(int index) {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public boolean add(T element) {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public void add(int index, T element) {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public Iterator<T> iterator() {
return inner.iterator();
return new UnmodifiableIterator<T>(inner.iterator());
}
public int indexOf(Object value) {
@ -371,11 +371,11 @@ public class Collections {
}
public ListIterator<T> listIterator(int index) {
return inner.listIterator(index);
return new UnmodifiableListIterator<T>(inner.listIterator(index));
}
public ListIterator<T> listIterator() {
return inner.listIterator();
return new UnmodifiableListIterator<T>(inner.listIterator());
}
public int size() {
@ -387,7 +387,7 @@ public class Collections {
}
public boolean addAll(Collection<? extends T> collection) {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public Object[] toArray() {
@ -399,15 +399,15 @@ public class Collections {
}
public void clear() {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public boolean addAll(int startIndex, Collection<? extends T> c) {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public boolean containsAll(Collection<?> c) {
@ -427,7 +427,7 @@ public class Collections {
}
public void clear() {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public boolean containsKey(Object key) {
@ -455,15 +455,15 @@ public class Collections {
}
public V put(K key, V value) {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public void putAll(Map<? extends K, ? extends V> t) {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public V remove(Object key) {
throw new UnsupportedOperationException("not supported");
throw new UnsupportedOperationException();
}
public int size() {
@ -471,64 +471,132 @@ public class Collections {
}
public Collection<V> values() {
return unmodifiableSet((Set<V>)inner.values());
return unmodifiableCollection(inner.values());
}
}
static class UnmodifiableSet<T> implements Set<T> {
private Set<T> inner;
UnmodifiableSet(Set<T> inner) {
static class UnmodifiableIterator<T> implements Iterator<T> {
private final Iterator<T> inner;
UnmodifiableIterator(Iterator<T> inner) {
this.inner = inner;
}
public boolean add(T element) {
throw new UnsupportedOperationException("not supported");
@Override
public T next() {
return inner.next();
}
public boolean addAll(Collection<? extends T> collection) {
throw new UnsupportedOperationException("not supported");
@Override
public boolean hasNext() {
return inner.hasNext();
}
public void clear() {
throw new UnsupportedOperationException("not supported");
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
static class UnmodifiableListIterator<T> extends UnmodifiableIterator<T>
implements ListIterator<T> {
private final ListIterator<T> innerListIterator;
UnmodifiableListIterator(ListIterator<T> listIterator) {
super(listIterator);
this.innerListIterator = listIterator;
}
public boolean contains(Object element) {
return inner.contains(element);
@Override
public boolean hasPrevious() {
return innerListIterator.hasPrevious();
}
public boolean isEmpty() {
return inner.isEmpty();
@Override
public T previous() {
return innerListIterator.previous();
}
}
static class UnmodifiableCollection<T> implements Collection<T> {
private final Collection<T> inner;
UnmodifiableCollection(Collection<T> inner) {
this.inner = inner;
}
@Override
public Iterator<T> iterator() {
return inner.iterator();
}
public boolean remove(Object element) {
throw new UnsupportedOperationException("not supported");
return new UnmodifiableIterator<T>(inner.iterator());
}
@Override
public int size() {
return inner.size();
}
public Object[] toArray() {
return toArray(new Object[size()]);
@Override
public boolean isEmpty() {
return inner.isEmpty();
}
public <S> S[] toArray(S[] array) {
return inner.toArray(array);
@Override
public boolean contains(Object element) {
return inner.contains(element);
}
@Override
public boolean containsAll(Collection<?> c) {
return inner.containsAll(c);
}
@Override
public boolean add(T element) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection<? extends T> collection) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object element) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException("not supported");
}
throw new UnsupportedOperationException();
}
@Override
public Object[] toArray() {
return inner.toArray();
}
@Override
public <S> S[] toArray(S[] array) {
return inner.toArray(array);
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
}
public static <T> UnmodifiableCollection<T> unmodifiableCollection(Collection<T> collection) {
return new UnmodifiableCollection<T>(collection);
}
static class UnmodifiableSet<T> extends UnmodifiableCollection<T>
implements Set<T> {
UnmodifiableSet(Set<T> inner) {
super(inner);
}
}
public static <T> Set<T> unmodifiableSet(Set<T> hs) {

26
test/Collections.java Normal file
View File

@ -0,0 +1,26 @@
import java.util.Collection;
import java.util.Map;
public class Collections {
public static void main(String[] args) {
testValues();
}
@SuppressWarnings("rawtypes")
private static void testValues() {
Map testMap = java.util.Collections.unmodifiableMap(java.util.Collections.emptyMap());
Collection values = testMap.values();
if (values == null) {
throw new NullPointerException();
}
try {
values.clear();
throw new IllegalStateException("Object should be immutable, exception should have thrown");
} catch (Exception e) {
// expected
}
}
}