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