66import java.lang.reflect.Method
77import java.security.SecureClassLoader
88import java.util.concurrent.atomic.AtomicReference
9+ import java.util.function.Predicate
910import java.util.regex.Pattern
1011import org.apache.maven.repository.internal.MavenRepositorySystemUtils
1112import org.eclipse.aether.DefaultRepositorySystemSession
@@ -74,7 +75,7 @@ class MuzzlePlugin implements Plugin<Project> {
7475 project. getLogger(). info(' No muzzle pass directives configured. Asserting pass against instrumentation compile-time dependencies' )
7576 ClassLoader userCL = createCompileDepsClassLoader(project, bootstrapProject)
7677 ClassLoader instrumentationCL = createInstrumentationClassloader(project, toolingProject)
77- Method assertionMethod = instrumentationCL. loadClass(' io.opentelemetry.javaagent.tooling.muzzle.MuzzleVersionScanPlugin ' )
78+ Method assertionMethod = instrumentationCL. loadClass(' io.opentelemetry.javaagent.tooling.muzzle.matcher.MuzzleGradlePluginUtil ' )
7879 .getMethod(' assertInstrumentationMuzzled' , ClassLoader . class, ClassLoader . class, boolean . class)
7980 assertionMethod. invoke(null , instrumentationCL, userCL, true )
8081 }
@@ -86,7 +87,7 @@ class MuzzlePlugin implements Plugin<Project> {
8687 description = " Print references created by instrumentation muzzle"
8788 doLast {
8889 ClassLoader instrumentationCL = createInstrumentationClassloader(project, toolingProject)
89- Method assertionMethod = instrumentationCL. loadClass(' io.opentelemetry.javaagent.tooling.muzzle.MuzzleVersionScanPlugin ' )
90+ Method assertionMethod = instrumentationCL. loadClass(' io.opentelemetry.javaagent.tooling.muzzle.matcher.MuzzleGradlePluginUtil ' )
9091 .getMethod(' printMuzzleReferences' , ClassLoader . class)
9192 assertionMethod. invoke(null , instrumentationCL)
9293 }
@@ -220,15 +221,9 @@ class MuzzlePlugin implements Plugin<Project> {
220221 rangeRequest. setRepositories(MUZZLE_REPOS )
221222 rangeRequest. setArtifact(directiveArtifact)
222223 VersionRangeResult rangeResult = system. resolveVersionRange(session, rangeRequest)
223- Set<Version > versions = rangeResult. versions. toSet()
224224
225- limitLargeRanges(rangeResult, versions, muzzleDirective. skipVersions)
226-
227- // println "Range Request: " + rangeRequest
228- // println "Range Result: " + rangeResult
229-
230- Set<Artifact > allVersionArtifacts = filterVersion(versions, muzzleDirective. skipVersions). collect { version ->
231- new DefaultArtifact (muzzleDirective. group, muzzleDirective. module, " jar" , version. toString())
225+ Set<Artifact > allVersionArtifacts = filterVersions(rangeResult, muzzleDirective. skipVersions). collect { version ->
226+ new DefaultArtifact (muzzleDirective. group, muzzleDirective. module, " jar" , version)
232227 }. toSet()
233228
234229 if (allVersionArtifacts. isEmpty()) {
@@ -244,47 +239,91 @@ class MuzzlePlugin implements Plugin<Project> {
244239 private static Set<MuzzleDirective > inverseOf (MuzzleDirective muzzleDirective , RepositorySystem system , RepositorySystemSession session ) {
245240 Set<MuzzleDirective > inverseDirectives = new HashSet<> ()
246241
247- Artifact allVerisonsArtifact = new DefaultArtifact (muzzleDirective. group, muzzleDirective. module, " jar" , " [,)" )
242+ Artifact allVersionsArtifact = new DefaultArtifact (muzzleDirective. group, muzzleDirective. module, " jar" , " [,)" )
248243 Artifact directiveArtifact = new DefaultArtifact (muzzleDirective. group, muzzleDirective. module, " jar" , muzzleDirective. versions)
249244
250-
251245 VersionRangeRequest allRangeRequest = new VersionRangeRequest ()
252246 allRangeRequest. setRepositories(MUZZLE_REPOS )
253- allRangeRequest. setArtifact(allVerisonsArtifact )
247+ allRangeRequest. setArtifact(allVersionsArtifact )
254248 VersionRangeResult allRangeResult = system. resolveVersionRange(session, allRangeRequest)
255249
256250 VersionRangeRequest rangeRequest = new VersionRangeRequest ()
257251 rangeRequest. setRepositories(MUZZLE_REPOS )
258252 rangeRequest. setArtifact(directiveArtifact)
259253 VersionRangeResult rangeResult = system. resolveVersionRange(session, rangeRequest)
260- Set<Version > versions = rangeResult. versions. toSet()
261-
262- filterVersion(allRangeResult. versions. toSet(), muzzleDirective. skipVersions). collect { version ->
263- if (! versions. contains(version)) {
264- MuzzleDirective inverseDirective = new MuzzleDirective ()
265- inverseDirective. group = muzzleDirective. group
266- inverseDirective. module = muzzleDirective. module
267- inverseDirective. versions = " $version "
268- inverseDirective. assertPass = ! muzzleDirective. assertPass
269- inverseDirectives. add(inverseDirective)
270- }
254+
255+ allRangeResult. getVersions(). removeAll(rangeResult. getVersions())
256+
257+ filterVersions(allRangeResult, muzzleDirective. skipVersions). each { version ->
258+ MuzzleDirective inverseDirective = new MuzzleDirective ()
259+ inverseDirective. group = muzzleDirective. group
260+ inverseDirective. module = muzzleDirective. module
261+ inverseDirective. versions = version
262+ inverseDirective. assertPass = ! muzzleDirective. assertPass
263+ inverseDirectives. add(inverseDirective)
271264 }
272265
273266 return inverseDirectives
274267 }
275268
276- private static void limitLargeRanges (VersionRangeResult result , Set<Version > versions , Set<String > skipVersions ) {
277- List<Version > copy = new ArrayList<> (versions)
278- copy. removeAll(skipVersions)
269+ private static Set<String > filterVersions (VersionRangeResult range , Set<String > skipVersions ) {
270+ Set<String > result = new HashSet<> ()
271+
272+ def predicate = new AcceptableVersions (range, skipVersions)
273+ if (predicate. test(range. lowestVersion)) {
274+ result. add(range. lowestVersion. toString())
275+ }
276+ if (predicate. test(range. highestVersion)) {
277+ result. add(range. highestVersion. toString())
278+ }
279+
280+ List<Version > copy = new ArrayList<> (range. versions)
279281 Collections . shuffle(copy)
280- while (RANGE_COUNT_LIMIT <= copy. size ()) {
282+ while (result . size() < RANGE_COUNT_LIMIT && ! copy. isEmpty ()) {
281283 Version version = copy. pop()
282- if (! (version . equals(result . lowestVersion) || version. equals(result . highestVersion) )) {
283- skipVersions . add(version. toString())
284+ if (predicate . test( version)) {
285+ result . add(version. toString())
284286 }
285287 }
286- if (skipVersions. size() > 0 ) {
287- println " Muzzle skipping " + skipVersions. size() + " versions"
288+
289+ return result
290+ }
291+
292+ static class AcceptableVersions implements Predicate<Version > {
293+ private static final Pattern GIT_SHA_PATTERN = Pattern . compile(' ^.*-[0-9a-f]{7,}$' )
294+
295+ private final VersionRangeResult range
296+ private final Collection<String > skipVersions
297+
298+ AcceptableVersions (VersionRangeResult range , Collection<String > skipVersions ) {
299+ this . range = range
300+ this . skipVersions = skipVersions
301+ }
302+
303+ @Override
304+ boolean test (Version version ) {
305+ if (version == null ) {
306+ return false
307+ }
308+ def versionString = version. toString(). toLowerCase()
309+ if (skipVersions. contains(versionString)) {
310+ return false
311+ }
312+
313+ def draftVersion = versionString. contains(" rc" ) ||
314+ versionString. contains(" .cr" ) ||
315+ versionString. contains(" alpha" ) ||
316+ versionString. contains(" beta" ) ||
317+ versionString. contains(" -b" ) ||
318+ versionString. contains(" .m" ) ||
319+ versionString. contains(" -m" ) ||
320+ versionString. contains(" -dev" ) ||
321+ versionString. contains(" -ea" ) ||
322+ versionString. contains(" -atlassian-" ) ||
323+ versionString. contains(" public_draft" ) ||
324+ versionString. matches(GIT_SHA_PATTERN )
325+
326+ return ! draftVersion
288327 }
289328 }
290329
@@ -336,12 +375,13 @@ class MuzzlePlugin implements Plugin<Project> {
336375 String toString () {
337376 return " bogus"
338377 }
378+
339379 }
340380 Thread . currentThread(). contextClassLoader = bogusLoader
341381 ClassLoader userCL = createClassLoaderForTask(instrumentationProject, bootstrapProject, taskName)
342382 try {
343383 // find all instrumenters, get muzzle, and assert
344- Method assertionMethod = instrumentationCL. loadClass(' io.opentelemetry.javaagent.tooling.muzzle.MuzzleVersionScanPlugin ' )
384+ Method assertionMethod = instrumentationCL. loadClass(' io.opentelemetry.javaagent.tooling.muzzle.matcher.MuzzleGradlePluginUtil ' )
345385 .getMethod(' assertInstrumentationMuzzled' , ClassLoader . class, ClassLoader . class, boolean . class)
346386 assertionMethod. invoke(null , instrumentationCL, userCL, muzzleDirective. assertPass)
347387 } finally {
@@ -370,6 +410,7 @@ class MuzzlePlugin implements Plugin<Project> {
370410 return locator. getService(RepositorySystem . class)
371411 }
372412
413+
373414 /**
374415 * Create muzzle's repository system session
375416 */
@@ -383,31 +424,6 @@ class MuzzlePlugin implements Plugin<Project> {
383424
384425 return session
385426 }
386-
387- private static final Pattern GIT_SHA_PATTERN = Pattern . compile(' ^.*-[0-9a-f]{7,}$' )
388-
389- /**
390- * Filter out snapshot-type builds from versions list.
391- */
392- private static filterVersion (Set<Version > list , Set<String > skipVersions ) {
393- list. removeIf {
394- def version = it. toString(). toLowerCase()
395- return version. contains(" rc" ) ||
396- version. contains(" .cr" ) ||
397- version. contains(" alpha" ) ||
398- version. contains(" beta" ) ||
399- version. contains(" -b" ) ||
400- version. contains(" .m" ) ||
401- version. contains(" -m" ) ||
402- version. contains(" -dev" ) ||
403- version. contains(" -ea" ) ||
404- version. contains(" -atlassian-" ) ||
405- version. contains(" public_draft" ) ||
406- skipVersions. contains(version) ||
407- version. matches(GIT_SHA_PATTERN )
408- }
409- return list
410- }
411427}
412428
413429// plugin extension classes
0 commit comments