diff --git a/src/main/org/apache/tools/ant/AntClassLoader.java b/src/main/org/apache/tools/ant/AntClassLoader.java index 05f39a3b3..b7545346d 100644 --- a/src/main/org/apache/tools/ant/AntClassLoader.java +++ b/src/main/org/apache/tools/ant/AntClassLoader.java @@ -46,6 +46,7 @@ import org.apache.tools.ant.util.CollectionUtils; import org.apache.tools.ant.util.FileUtils; import org.apache.tools.ant.util.JavaEnvUtils; import org.apache.tools.ant.util.LoaderUtils; +import org.apache.tools.ant.util.VectorSet; import org.apache.tools.ant.launch.Locator; /** @@ -166,7 +167,7 @@ public class AntClassLoader extends ClassLoader implements SubBuildListener { * The components of the classpath that the classloader searches * for classes. */ - private Vector pathComponents = new Vector(); + private Vector pathComponents = new VectorSet(); /** * The project to which this class loader belongs. @@ -1260,13 +1261,7 @@ public class AntClassLoader extends ClassLoader implements SubBuildListener { * @return true if the file is in the class path */ protected boolean isInPath(File component) { - for (Enumeration e = pathComponents.elements(); e.hasMoreElements();) { - File pathComponent = (File) e.nextElement(); - if (pathComponent.equals(component)) { - return true; - } - } - return false; + return pathComponents.contains(component); } /** diff --git a/src/main/org/apache/tools/ant/util/VectorSet.java b/src/main/org/apache/tools/ant/util/VectorSet.java index 9a9448dfb..ee5102f98 100644 --- a/src/main/org/apache/tools/ant/util/VectorSet.java +++ b/src/main/org/apache/tools/ant/util/VectorSet.java @@ -20,6 +20,7 @@ package org.apache.tools.ant.util; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.Vector; /** @@ -50,9 +51,22 @@ public class VectorSet extends Vector { * This implementation may not add the element at the given index * if it is already contained in the collection. */ - public synchronized void add(int index, Object o) { + public void add(int index, Object o) { + doAdd(index, o); + } + + private synchronized void doAdd(int index, Object o) { + // Vector.add seems to delegate to insertElementAt, but this + // is not documented so we may better implement it ourselves if (set.add(o)) { - super.add(index, o); + ensureCapacity(size() + 1); + Object[] elems = new Object[elementData.length]; + System.arraycopy(elementData, 0, elems, 0, index); + elems[index] = o; + System.arraycopy(elementData, index, elems, index + 1, + size() - index); + elementData = elems; + elementCount++; } } @@ -105,18 +119,28 @@ public class VectorSet extends Vector { } public void insertElementAt(Object o, int index) { - add(index, o); + doAdd(index, o); } public synchronized Object remove(int index) { - Object o = super.remove(index); - set.remove(o); + Object o = get(index); + remove(o); return o; } - public synchronized boolean remove(Object o) { + public boolean remove(Object o) { + return doRemove(o); + } + + private synchronized boolean doRemove(Object o) { + // again, remove seems to delegate to removeElement, but we + // shouldn't trust it if (set.remove(o)) { - return super.remove(o); + int index = indexOf(o); + System.arraycopy(elementData, index + 1, elementData, index, + size() - index); + elementCount--; + return true; } return false; } @@ -129,12 +153,13 @@ public class VectorSet extends Vector { return changed; } - public void removeAllElements() { - clear(); + public synchronized void removeAllElements() { + set.clear(); + super.removeAllElements(); } public boolean removeElement(Object o) { - return remove(o); + return doRemove(o); } public synchronized void removeElementAt(int index) { @@ -148,9 +173,15 @@ public class VectorSet extends Vector { } public synchronized boolean retainAll(Collection c) { - if (super.retainAll(c)) { - clear(); - addAll(c); + LinkedList l = new LinkedList(); + for (Iterator i = iterator(); i.hasNext(); ) { + Object o = i.next(); + if (!c.contains(o)) { + l.addLast(o); + } + } + if (!l.isEmpty()) { + removeAll(l); return true; } return false; diff --git a/src/tests/junit/org/apache/tools/ant/util/VectorSetTest.java b/src/tests/junit/org/apache/tools/ant/util/VectorSetTest.java new file mode 100644 index 000000000..5aac05000 --- /dev/null +++ b/src/tests/junit/org/apache/tools/ant/util/VectorSetTest.java @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.tools.ant.util; + +import java.util.Arrays; + +import junit.framework.TestCase; + +public class VectorSetTest extends TestCase { + + private static final Object O = new Object(); + private VectorSet v = new VectorSet(); + + public void testAdd() { + assertTrue(v.add(O)); + assertFalse(v.add(O)); + assertEquals(1, v.size()); + } + + public void testAdd2() { + v.add(0, O); + v.add(1, O); + assertEquals(1, v.size()); + } + + public void testAddElement() { + v.addElement(O); + v.addElement(O); + assertEquals(1, v.size()); + } + + public void testAddAll() { + assertTrue(v.addAll(Arrays.asList(new Object[] {O, O}))); + assertEquals(1, v.size()); + } + + public void testAddAll2() { + assertTrue(v.addAll(0, Arrays.asList(new Object[] {O, O}))); + assertEquals(1, v.size()); + } + + public void testClear() { + v.add(O); + v.clear(); + assertEquals(0, v.size()); + } + + public void testClone() { + v.add(O); + Object o = v.clone(); + assertTrue(o instanceof VectorSet); + VectorSet vs = (VectorSet) o; + assertEquals(1, vs.size()); + assertTrue(vs.contains(O)); + } + + public void testContains() { + assertFalse(v.contains(O)); + v.add(O); + assertTrue(v.contains(O)); + assertFalse(v.contains(null)); + } + + public void testContainsAll() { + assertFalse(v.containsAll(Arrays.asList(new Object[] {O, O}))); + v.add(O); + assertTrue(v.containsAll(Arrays.asList(new Object[] {O, O}))); + assertFalse(v.containsAll(Arrays.asList(new Object[] {O, null}))); + } + + public void testInsertElementAt() { + v.insertElementAt(O, 0); + v.insertElementAt(O, 1); + assertEquals(1, v.size()); + } + + public void testRemoveIndex() { + v.add(O); + assertSame(O, v.remove(0)); + assertEquals(0, v.size()); + try { + v.remove(0); + fail("expected an AIOBE"); + } catch (ArrayIndexOutOfBoundsException e) { + // expected + } + } + + public void testRemoveObject() { + v.add(O); + assertTrue(v.remove(O)); + assertEquals(0, v.size()); + assertFalse(v.remove(O)); + } + + public void testRemoveAll() { + v.add(O); + assertTrue(v.removeAll(Arrays.asList(new Object[] {O, O}))); + assertEquals(0, v.size()); + assertFalse(v.removeAll(Arrays.asList(new Object[] {O, O}))); + } + + public void testRemoveAllElements() { + v.add(O); + v.removeAllElements(); + assertEquals(0, v.size()); + } + + public void testRemoveElement() { + v.add(O); + assertTrue(v.removeElement(O)); + assertEquals(0, v.size()); + assertFalse(v.removeElement(O)); + } + + public void testRemoveElementAt() { + v.add(O); + v.removeElementAt(0); + assertEquals(0, v.size()); + try { + v.removeElementAt(0); + fail("expected an AIOBE"); + } catch (ArrayIndexOutOfBoundsException e) { + // expected + } + } + + public void testRemoveRange() { + Object a = new Object(); + Object b = new Object(); + Object c = new Object(); + v.addAll(Arrays.asList(new Object[] {O, a, b, c})); + v.removeRange(1, 3); + assertEquals(2, v.size()); + assertTrue(v.contains(O)); + assertTrue(v.contains(c)); + } + + public void testRetainAll() { + Object a = new Object(); + Object b = new Object(); + Object c = new Object(); + v.addAll(Arrays.asList(new Object[] {O, a, b, c})); + assertEquals(0, v.indexOf(O)); + v.retainAll(Arrays.asList(new Object[] {c, O})); + assertEquals(2, v.size()); + assertTrue(v.contains(O)); + assertTrue(v.contains(c)); + assertEquals(0, v.indexOf(O)); + } + + public void testSet() { + v.add(O); + Object a = new Object(); + assertSame(O, v.set(0, a)); + assertSame(a, v.get(0)); + assertEquals(1, v.size()); + } + + public void testSetElementAt() { + v.add(O); + Object a = new Object(); + v.setElementAt(a, 0); + assertSame(a, v.get(0)); + assertEquals(1, v.size()); + } +} \ No newline at end of file