|
19 | 19 | package org.codehaus.groovy.tools; |
20 | 20 |
|
21 | 21 | import java.io.File; |
| 22 | +import java.io.IOException; |
22 | 23 | import java.net.MalformedURLException; |
| 24 | +import java.net.URISyntaxException; |
23 | 25 | import java.net.URL; |
24 | 26 | import java.net.URLClassLoader; |
25 | 27 | import java.util.HashMap; |
| 28 | +import java.util.HashSet; |
26 | 29 | import java.util.Map; |
27 | 30 | import java.util.Optional; |
| 31 | +import java.util.Set; |
28 | 32 |
|
29 | 33 | /** |
30 | 34 | * This ClassLoader should be used as root of class loaders. Any |
@@ -109,8 +113,16 @@ public RootLoader(final LoaderConfiguration lc) { |
109 | 113 |
|
110 | 114 | Thread.currentThread().setContextClassLoader(this); |
111 | 115 |
|
| 116 | + // Skip URLs already on the JVM startup (system) classpath: the launcher |
| 117 | + // puts the core groovy jar on -classpath to start GroovyStarter, and |
| 118 | + // groovy-starter.conf's "load lib/*.jar" then re-globs it. Adding the |
| 119 | + // same jar to both loaders lets each define its own copy of every core |
| 120 | + // class, and trips duplicate-resource detection. |
| 121 | + Set<File> startup = startupClasspathFiles(); |
112 | 122 | for (URL url : lc.getClassPathUrls()) { |
113 | | - addURL(url); |
| 123 | + if (!startup.contains(canonicalFile(url))) { |
| 124 | + addURL(url); |
| 125 | + } |
114 | 126 | } |
115 | 127 | // TODO M12N eventually defer this until later when we have a full Groovy |
116 | 128 | // environment and use normal Grape.grab() |
@@ -179,4 +191,33 @@ public void addURL(final URL url) { |
179 | 191 | protected Class<?> findClass(final String name) throws ClassNotFoundException { |
180 | 192 | throw new ClassNotFoundException(name); |
181 | 193 | } |
| 194 | + |
| 195 | + private static Set<File> startupClasspathFiles() { |
| 196 | + Set<File> files = new HashSet<>(); |
| 197 | + String cp = System.getProperty("java.class.path"); |
| 198 | + if (cp == null || cp.isEmpty()) return files; |
| 199 | + for (String entry : cp.split(File.pathSeparator)) { |
| 200 | + if (entry.isEmpty()) continue; |
| 201 | + File f = canonicalFile(new File(entry)); |
| 202 | + if (f != null) files.add(f); |
| 203 | + } |
| 204 | + return files; |
| 205 | + } |
| 206 | + |
| 207 | + private static File canonicalFile(URL url) { |
| 208 | + if (!"file".equals(url.getProtocol())) return null; |
| 209 | + try { |
| 210 | + return canonicalFile(new File(url.toURI())); |
| 211 | + } catch (URISyntaxException | IllegalArgumentException e) { |
| 212 | + return null; |
| 213 | + } |
| 214 | + } |
| 215 | + |
| 216 | + private static File canonicalFile(File f) { |
| 217 | + try { |
| 218 | + return f.getCanonicalFile(); |
| 219 | + } catch (IOException e) { |
| 220 | + return f.getAbsoluteFile(); |
| 221 | + } |
| 222 | + } |
182 | 223 | } |
0 commit comments