Skip to content

Commit 1e0c6e9

Browse files
committed
GROOVY-11871: Support Maven Resolver based version of Grapes
1 parent 7d8349c commit 1e0c6e9

19 files changed

Lines changed: 1337 additions & 175 deletions

File tree

build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ dependencies {
9898
grapesImplementation "org.apache.ivy:ivy:${versions.ivy}", {
9999
transitive = false
100100
}
101+
// grapesImplementation "org.apache.maven:maven-resolver-provider:${versions.mavenResolverProvider}"
102+
// grapesImplementation "org.apache.maven.resolver:maven-resolver-supplier-mvn4:${versions.mavenResolverSupplier}"
103+
// grapesImplementation "org.slf4j:slf4j-simple:${versions.slf4j}"
101104

102105
loggingImplementation "org.jline:jansi:${versions.jline}"
103106

gradle/verification-metadata.xml

Lines changed: 277 additions & 0 deletions
Large diffs are not rendered by default.

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def subprojects = [
5656
'groovy-datetime',
5757
'groovy-dateutil',
5858
'groovy-docgenerator',
59+
'groovy-grape-maven',
5960
'groovy-groovydoc',
6061
'groovy-groovysh',
6162
'groovy-jmx',

src/main/groovy/groovy/grape/GrapeIvy.groovy

Lines changed: 33 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ import groovy.transform.CompileStatic
2424
import groovy.transform.EqualsAndHashCode
2525
import groovy.transform.NamedParam
2626
import groovy.transform.NamedParams
27-
import org.apache.groovy.plugin.GroovyRunner
28-
import org.apache.groovy.plugin.GroovyRunnerRegistry
2927
import org.apache.ivy.Ivy
3028
import org.apache.ivy.core.IvyContext
3129
import org.apache.ivy.core.event.download.PrepareDownloadEvent
@@ -49,29 +47,19 @@ import org.apache.ivy.plugins.resolver.IBiblioResolver
4947
import org.apache.ivy.plugins.resolver.ResolverSettings
5048
import org.apache.ivy.util.DefaultMessageLogger
5149
import org.apache.ivy.util.Message
52-
import org.codehaus.groovy.reflection.CachedClass
53-
import org.codehaus.groovy.reflection.ClassInfo
5450
import org.codehaus.groovy.reflection.ReflectionUtils
55-
import org.codehaus.groovy.runtime.m12n.ExtensionModuleScanner
56-
import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl
5751
import org.w3c.dom.Element
5852

5953
import javax.xml.parsers.DocumentBuilderFactory
6054
import java.text.ParseException
61-
import java.util.jar.JarFile
6255
import java.util.regex.Pattern
63-
import java.util.zip.ZipEntry
64-
import java.util.zip.ZipException
65-
import java.util.zip.ZipFile
6656

6757
/**
6858
* Implementation supporting {@code @Grape} and {@code @Grab} annotations based on Ivy.
6959
*/
7060
@AutoFinal @CompileStatic
7161
class GrapeIvy implements GrapeEngine {
7262

73-
private static final String METAINF_PREFIX = 'META-INF/services/'
74-
private static final String RUNNER_PROVIDER_CONFIG = GroovyRunner.getName()
7563
private static final List<String> DEFAULT_CONF = Collections.singletonList('default')
7664
private static final Map<String, Set<String>> MUTUALLY_EXCLUSIVE_KEYS = processGrabArgs([
7765
['group', 'groupId', 'organisation', 'organization', 'org'],
@@ -287,20 +275,20 @@ class GrapeIvy implements GrapeEngine {
287275

288276
URI[] uris = resolve(loader, args, dependencies)
289277
for (URI uri : uris) {
290-
addURL(loader, uri)
278+
GrapeUtil.addURL(loader, uri)
291279
}
292280
boolean runnerServicesFound = false
293281
for (URI uri : uris) {
294282
// TODO: check artifact type, jar vs library, etc.
295283
File file = new File(uri)
296-
processCategoryMethods(loader, file)
297-
Collection<String> services = processMetaInfServices(loader, file)
284+
GrapeUtil.processCategoryMethods(loader, file)
285+
Collection<String> services = GrapeUtil.processMetaInfServices(loader, file)
298286
if (!runnerServicesFound) {
299-
runnerServicesFound = services.contains(RUNNER_PROVIDER_CONFIG)
287+
runnerServicesFound = GrapeUtil.checkForRunner(services)
300288
}
301289
}
302290
if (runnerServicesFound) {
303-
GroovyRunnerRegistry.getInstance().load(loader)
291+
GrapeUtil.registryLoad(loader)
304292
}
305293
} catch (Exception e) {
306294
// clean-up the state first
@@ -316,112 +304,8 @@ class GrapeIvy implements GrapeEngine {
316304
null
317305
}
318306

319-
@CompileDynamic
320-
private void addURL(ClassLoader loader, URI uri) {
321-
loader.addURL(uri.toURL())
322-
}
323-
324-
private processCategoryMethods(ClassLoader loader, File file) {
325-
// register extension methods if jar
326-
if (file.getName().toLowerCase().endsWith('.jar')) {
327-
def mcRegistry = GroovySystem.getMetaClassRegistry()
328-
if (mcRegistry instanceof MetaClassRegistryImpl) {
329-
try (JarFile jar = new JarFile(file)) {
330-
ZipEntry entry = jar.getEntry(ExtensionModuleScanner.MODULE_META_INF_FILE)
331-
if (!entry) {
332-
entry = jar.getEntry(ExtensionModuleScanner.LEGACY_MODULE_META_INF_FILE)
333-
}
334-
if (entry) {
335-
Properties props = new Properties()
336-
337-
try (InputStream is = jar.getInputStream(entry)) {
338-
props.load(is)
339-
}
340-
341-
Map<CachedClass, List<MetaMethod>> metaMethods = [:]
342-
mcRegistry.registerExtensionModuleFromProperties(props, loader, metaMethods)
343-
// add old methods to the map
344-
metaMethods.each { CachedClass c, List<MetaMethod> methods ->
345-
// GROOVY-5543: if a module was loaded using grab, there are chances that subclasses
346-
// have their own ClassInfo, and we must change them as well!
347-
Set<CachedClass> classesToBeUpdated = [c].toSet()
348-
ClassInfo.onAllClassInfo { ClassInfo info ->
349-
if (c.getTheClass().isAssignableFrom(info.getCachedClass().getTheClass())) {
350-
classesToBeUpdated << info.getCachedClass()
351-
}
352-
}
353-
classesToBeUpdated*.addNewMopMethods(methods)
354-
}
355-
}
356-
} catch (ZipException e) {
357-
throw new RuntimeException("Grape could not load jar '$file'", e)
358-
}
359-
}
360-
}
361-
}
362-
363307
void processOtherServices(ClassLoader loader, File f) {
364-
processMetaInfServices(loader, f) // ignore result
365-
}
366-
367-
/**
368-
* Searches the given File for known service provider
369-
* configuration files to process.
370-
*
371-
* @param loader used to locate service provider files
372-
* @param f ZipFile in which to search for services
373-
* @return a collection of service provider files that were found
374-
*/
375-
private Collection<String> processMetaInfServices(ClassLoader loader, File f) {
376-
List<String> services = []
377-
try (ZipFile zf = new ZipFile(f)) {
378-
String providerConfig = 'org.codehaus.groovy.runtime.SerializedCategoryMethods'
379-
ZipEntry serializedCategoryMethods = zf.getEntry(METAINF_PREFIX + providerConfig)
380-
if (serializedCategoryMethods != null) {
381-
services.add(providerConfig)
382-
383-
try (InputStream is = zf.getInputStream(serializedCategoryMethods)) {
384-
processSerializedCategoryMethods(is)
385-
}
386-
}
387-
// TODO: remove in a future release (replaced by GroovyRunnerRegistry)
388-
providerConfig = 'org.codehaus.groovy.plugins.Runners'
389-
ZipEntry pluginRunners = zf.getEntry(METAINF_PREFIX + providerConfig)
390-
if (pluginRunners != null) {
391-
services.add(providerConfig)
392-
393-
try (InputStream is = zf.getInputStream(pluginRunners)) {
394-
processRunners(is, f.getName(), loader)
395-
}
396-
}
397-
// GroovyRunners are loaded per ClassLoader using a ServiceLoader so here
398-
// it only needs to be indicated that the service provider file was found
399-
if (zf.getEntry(METAINF_PREFIX + RUNNER_PROVIDER_CONFIG) != null) {
400-
services.add(RUNNER_PROVIDER_CONFIG)
401-
}
402-
} catch (ZipException ignore) {
403-
// ignore files we can't process, e.g. non-jar/zip artifacts
404-
// TODO: log a warning
405-
}
406-
services
407-
}
408-
409-
void processSerializedCategoryMethods(InputStream is) {
410-
is.getText().readLines().each {
411-
System.err.println(it.trim()) // TODO: implement this or delete it
412-
}
413-
}
414-
415-
void processRunners(InputStream is, String name, ClassLoader loader) {
416-
GroovyRunnerRegistry registry = GroovyRunnerRegistry.getInstance()
417-
is.getText().readLines()*.trim().each { String line ->
418-
if (!line.isEmpty() && line[0] != '#')
419-
try {
420-
registry[name] = (GroovyRunner) loader.loadClass(line).getDeclaredConstructor().newInstance()
421-
} catch (Exception e) {
422-
throw new IllegalStateException("Error registering runner class '$line'", e)
423-
}
424-
}
308+
GrapeUtil.processMetaInfServices(loader, f) // ignore result
425309
}
426310

427311
ResolveReport getDependencies(Map args, IvyGrabRecord... grabRecords) {
@@ -730,6 +614,33 @@ class GrapeIvy implements GrapeEngine {
730614
resolvedDependencies = []
731615
downloadedArtifacts = []
732616
}
617+
618+
@Override
619+
void setLoggingLevel(int level) {
620+
// Map numeric level to Ivy logging level
621+
// 0=quiet/errors only, 1=warn, 2=info, 3=verbose, 4=debug
622+
int ivyLevel
623+
switch (level) {
624+
case 0:
625+
ivyLevel = Message.MSG_ERR
626+
break
627+
case 1:
628+
ivyLevel = Message.MSG_WARN
629+
break
630+
case 2:
631+
ivyLevel = Message.MSG_INFO
632+
break
633+
case 3:
634+
ivyLevel = Message.MSG_VERBOSE
635+
break
636+
case 4:
637+
ivyLevel = Message.MSG_DEBUG
638+
break
639+
default:
640+
ivyLevel = Message.MSG_INFO
641+
}
642+
Message.setDefaultLogger(new DefaultMessageLogger(ivyLevel))
643+
}
733644
}
734645

735646
@CompileStatic

0 commit comments

Comments
 (0)