Browse Source

what started as an innocent minor performance improvement of antClassLoader lead to an infinite recursion and thus to a testcase for VectorSet.

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@699377 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 16 years ago
parent
commit
430b0251e5
3 changed files with 230 additions and 21 deletions
  1. +3
    -8
      src/main/org/apache/tools/ant/AntClassLoader.java
  2. +44
    -13
      src/main/org/apache/tools/ant/util/VectorSet.java
  3. +183
    -0
      src/tests/junit/org/apache/tools/ant/util/VectorSetTest.java

+ 3
- 8
src/main/org/apache/tools/ant/AntClassLoader.java View File

@@ -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);
}

/**


+ 44
- 13
src/main/org/apache/tools/ant/util/VectorSet.java View File

@@ -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;


+ 183
- 0
src/tests/junit/org/apache/tools/ant/util/VectorSetTest.java View File

@@ -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());
}
}

Loading…
Cancel
Save