Jetty 9.4.x 2043 concurrentmodification annotation parsing (#2052)
* Issue #2043 Fix ConcurrentModificationException listing duplicate class scanning Signed-off-by: Jan Bartel <janb@webtide.com>
This commit is contained in:
parent
8660055574
commit
eebe139494
|
@ -71,7 +71,10 @@ public class AnnotationParser
|
|||
private static final Logger LOG = Log.getLogger(AnnotationParser.class);
|
||||
protected static int ASM_OPCODE_VERSION = Opcodes.ASM6; //compatibility of api
|
||||
|
||||
protected Map<String, List<String>> _parsedClassNames = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* Map of classnames scanned and the first location from which scan occurred
|
||||
*/
|
||||
protected Map<String, Resource> _parsedClassNames = new ConcurrentHashMap<>();
|
||||
private final int _javaPlatform;
|
||||
private int _asmVersion;
|
||||
|
||||
|
@ -561,17 +564,11 @@ public class AnnotationParser
|
|||
*/
|
||||
public void addParsedClass (String classname, Resource location)
|
||||
{
|
||||
List<String> list = new ArrayList<>(1);
|
||||
if (location != null)
|
||||
list.add(location.toString());
|
||||
|
||||
List<String> existing = _parsedClassNames.putIfAbsent(classname, list);
|
||||
Resource existing = _parsedClassNames.putIfAbsent(classname, location);
|
||||
if (existing != null)
|
||||
{
|
||||
existing.addAll(list);
|
||||
LOG.warn("{} scanned from multiple locations: {}", classname, existing);
|
||||
}
|
||||
LOG.warn("{} scanned from multiple locations: {}, {}", classname, existing, location);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the locations of the given classname. There may be more than one
|
||||
|
@ -579,13 +576,13 @@ public class AnnotationParser
|
|||
*
|
||||
* @param classname the name of the class
|
||||
* @return an immutable list of locations
|
||||
*
|
||||
* @deprecated List of duplicate locations no longer stored
|
||||
*/
|
||||
@Deprecated
|
||||
public List<String> getParsedLocations (String classname)
|
||||
{
|
||||
List<String> list = _parsedClassNames.get(classname);
|
||||
if (list == null)
|
||||
return Collections.emptyList();
|
||||
return Collections.unmodifiableList(list);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,7 +35,10 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.ClassInfo;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.FieldInfo;
|
||||
|
@ -71,6 +74,33 @@ public class TestAnnotationParser
|
|||
foundClasses.add(info.getClassName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class DuplicateClassScanHandler extends AnnotationParser.AbstractHandler
|
||||
{
|
||||
private Map<String, List<String>> _classMap = new ConcurrentHashMap();
|
||||
|
||||
@Override
|
||||
public void handle(ClassInfo info)
|
||||
{
|
||||
List<String> list = new CopyOnWriteArrayList<>();
|
||||
Resource r = info.getContainingResource();
|
||||
list.add((r==null?"":r.toString()));
|
||||
|
||||
List<String> existing = _classMap.putIfAbsent(info.getClassName(), list);
|
||||
if (existing != null)
|
||||
{
|
||||
existing.addAll(list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<String> getParsedList(String classname)
|
||||
{
|
||||
return _classMap.get(classname);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
|
@ -219,10 +249,11 @@ public class TestAnnotationParser
|
|||
Resource testJar = Resource.newResource(MavenTestingUtils.getTestResourceFile("tinytest.jar"));
|
||||
Resource testJar2 = Resource.newResource(MavenTestingUtils.getTestResourceFile("tinytest_copy.jar"));
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
Set<Handler> emptySet = Collections.emptySet();
|
||||
parser.parse(emptySet, testJar);
|
||||
parser.parse(emptySet, testJar2);
|
||||
List<String> locations = parser.getParsedLocations("org.acme.ClassOne");
|
||||
DuplicateClassScanHandler handler = new DuplicateClassScanHandler();
|
||||
Set<Handler> handlers = Collections.singleton(handler);
|
||||
parser.parse(handlers, testJar);
|
||||
parser.parse(handlers, testJar2);
|
||||
List<String> locations = handler.getParsedList("org.acme.ClassOne");
|
||||
Assert.assertNotNull(locations);
|
||||
Assert.assertEquals(2, locations.size());
|
||||
Assert.assertTrue(!(locations.get(0).equals(locations.get(1))));
|
||||
|
@ -235,10 +266,11 @@ public class TestAnnotationParser
|
|||
Resource testJar = Resource.newResource(MavenTestingUtils.getTestResourceFile("tinytest.jar"));
|
||||
File testClasses = new File(MavenTestingUtils.getTargetDir(), "test-classes");
|
||||
AnnotationParser parser = new AnnotationParser();
|
||||
Set<Handler> emptySet = Collections.emptySet();
|
||||
parser.parse(emptySet, testJar);
|
||||
parser.parse(emptySet, Resource.newResource(testClasses));
|
||||
List<String> locations = parser.getParsedLocations("org.acme.ClassOne");
|
||||
DuplicateClassScanHandler handler = new DuplicateClassScanHandler();
|
||||
Set<Handler> handlers = Collections.singleton(handler);
|
||||
parser.parse(handlers, testJar);
|
||||
parser.parse(handlers, Resource.newResource(testClasses));
|
||||
List<String>locations = handler.getParsedList("org.acme.ClassOne");
|
||||
Assert.assertNotNull(locations);
|
||||
Assert.assertEquals(2, locations.size());
|
||||
Assert.assertTrue(!(locations.get(0).equals(locations.get(1))));
|
||||
|
|
Loading…
Reference in New Issue