Skip to content

Commit d3ddc98

Browse files
chore: merge main into release [skip ci]
2 parents 4ab54e9 + b8ffd75 commit d3ddc98

4 files changed

Lines changed: 105 additions & 33 deletions

File tree

microsphere-java-core/src/main/java/io/microsphere/classloading/ArtifactDetector.java

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,21 @@
66
import io.microsphere.lang.Prioritized;
77
import io.microsphere.logging.Logger;
88

9+
import java.io.File;
910
import java.net.URL;
1011
import java.util.Iterator;
1112
import java.util.LinkedHashSet;
12-
import java.util.LinkedList;
1313
import java.util.List;
1414
import java.util.Set;
1515

16-
import static io.microsphere.collection.CollectionUtils.isEmpty;
16+
import static io.microsphere.collection.CollectionUtils.size;
17+
import static io.microsphere.collection.ListUtils.newArrayList;
18+
import static io.microsphere.lang.function.ThrowableSupplier.execute;
1719
import static io.microsphere.logging.LoggerFactory.getLogger;
20+
import static io.microsphere.net.URLUtils.resolveArchiveFile;
1821
import static io.microsphere.util.ClassLoaderUtils.findAllClassPathURLs;
1922
import static io.microsphere.util.ClassLoaderUtils.getClassLoader;
23+
import static io.microsphere.util.ClassLoaderUtils.getClassResource;
2024
import static io.microsphere.util.ClassPathUtils.getBootstrapClassPaths;
2125
import static io.microsphere.util.ServiceLoaderUtils.loadServicesList;
2226
import static io.microsphere.util.SystemUtils.JAVA_HOME;
@@ -108,25 +112,46 @@ public List<Artifact> detect(boolean includedJdkLibraries) {
108112

109113
@Nonnull
110114
@Immutable
111-
protected List<Artifact> detect(Set<URL> classPathURLs) {
112-
if (isEmpty(classPathURLs)) {
115+
public List<Artifact> detect(@Nullable Set<URL> resourceURLs) {
116+
int size = size(resourceURLs);
117+
if (size < 1) {
113118
return emptyList();
114119
}
115-
116-
List<Artifact> artifactList = new LinkedList<>();
117-
for (URL resourceURL : classPathURLs) {
118-
for (ArtifactResourceResolver artifactResourceResolver : artifactResourceResolvers) {
119-
Artifact artifact = artifactResourceResolver.resolve(resourceURL);
120-
if (artifact != null) {
121-
artifactList.add(artifact);
122-
break;
123-
}
120+
List<Artifact> artifactList = newArrayList(size);
121+
for (URL resourceURL : resourceURLs) {
122+
Artifact artifact = detect(resourceURL);
123+
if (artifact != null) {
124+
artifactList.add(artifact);
125+
break;
124126
}
125127
}
126-
127128
return unmodifiableList(artifactList);
128129
}
129130

131+
@Nullable
132+
public Artifact detect(@Nonnull Class<?> classInResource) {
133+
URL classResource = getClassResource(classInResource);
134+
return detect(classResource);
135+
}
136+
137+
@Nullable
138+
public Artifact detect(@Nonnull URL resourceURL) {
139+
File archiveFile = resolveArchiveFile(resourceURL);
140+
if (archiveFile == null) {
141+
return null;
142+
}
143+
URL classPathURL = execute(archiveFile.toURI()::toURL);
144+
Artifact artifact = null;
145+
for (ArtifactResourceResolver artifactResourceResolver : artifactResourceResolvers) {
146+
artifact = artifactResourceResolver.resolve(classPathURL);
147+
if (artifact != null) {
148+
break;
149+
}
150+
}
151+
return artifact;
152+
}
153+
154+
130155
protected Set<URL> getClassPathURLs(boolean includedJdkLibraries) {
131156
Set<URL> urls = findAllClassPathURLs(classLoader);
132157
Set<URL> classPathURLs = new LinkedHashSet<>(urls);

microsphere-java-core/src/main/java/io/microsphere/util/Version.java

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import io.microsphere.annotation.Immutable;
2020
import io.microsphere.annotation.Nonnull;
2121
import io.microsphere.annotation.Nullable;
22+
import io.microsphere.classloading.Artifact;
23+
import io.microsphere.classloading.ArtifactDetector;
2224

2325
import java.io.Serializable;
2426
import java.net.URL;
@@ -108,7 +110,6 @@ public class Version implements Comparable<Version>, Serializable {
108110
* }</pre>
109111
*
110112
* @param major the major version number
111-
* @since 1.0.0
112113
*/
113114
public Version(int major) {
114115
this(major, 0);
@@ -125,7 +126,6 @@ public Version(int major) {
125126
*
126127
* @param major the major version number
127128
* @param minor the minor version number
128-
* @since 1.0.0
129129
*/
130130
public Version(int major, int minor) {
131131
this(major, minor, 0);
@@ -142,7 +142,6 @@ public Version(int major, int minor) {
142142
* @param major the major version number
143143
* @param minor the minor version number
144144
* @param patch the patch version number
145-
* @since 1.0.0
146145
*/
147146
public Version(int major, int minor, int patch) {
148147
this(major, minor, patch, null);
@@ -161,7 +160,6 @@ public Version(int major, int minor, int patch) {
161160
* @param patch the patch version number (must be non-negative)
162161
* @param preRelease the optional pre-release identifier (e.g., "SNAPSHOT", "alpha")
163162
* @throws IllegalArgumentException if major, minor, or patch is negative, or all are zero
164-
* @since 1.0.0
165163
*/
166164
public Version(int major, int minor, int patch, String preRelease) {
167165
assertTrue(major >= 0, "The 'major' version must not be a non-negative integer!");
@@ -342,7 +340,6 @@ public boolean equals(Object o) {
342340
* }</pre>
343341
*
344342
* @return a hash code value for this version
345-
* @since 1.0.0
346343
*/
347344
@Override
348345
public int hashCode() {
@@ -368,8 +365,7 @@ public int hashCode() {
368365
*
369366
* @param that the version to compare against
370367
* @return a negative integer, zero, or a positive integer as this version
371-
* is less than, equal to, or greater than the specified version
372-
* @since 1.0.0
368+
* is less than, equal to, or greater than the specified version
373369
*/
374370
@Override
375371
public int compareTo(Version that) {
@@ -424,7 +420,6 @@ static int comparePreRelease(String v1, String v2) {
424420
* }</pre>
425421
*
426422
* @return the version string
427-
* @since 1.0.0
428423
*/
429424
@Override
430425
public String toString() {
@@ -441,7 +436,6 @@ public String toString() {
441436
*
442437
* @param major the major version number
443438
* @return a new {@link Version} instance
444-
* @since 1.0.0
445439
*/
446440
public static Version of(int major) {
447441
return ofVersion(major);
@@ -458,7 +452,6 @@ public static Version of(int major) {
458452
* @param major the major version number
459453
* @param minor the minor version number
460454
* @return a new {@link Version} instance
461-
* @since 1.0.0
462455
*/
463456
public static Version of(int major, int minor) {
464457
return ofVersion(major, minor);
@@ -476,7 +469,6 @@ public static Version of(int major, int minor) {
476469
* @param minor the minor version number
477470
* @param patch the patch version number
478471
* @return a new {@link Version} instance
479-
* @since 1.0.0
480472
*/
481473
public static Version of(int major, int minor, int patch) {
482474
return ofVersion(major, minor, patch);
@@ -495,7 +487,6 @@ public static Version of(int major, int minor, int patch) {
495487
* @param patch the patch version number
496488
* @param preRelease the pre-release identifier
497489
* @return a new {@link Version} instance
498-
* @since 1.0.0
499490
*/
500491
public static Version of(int major, int minor, int patch, String preRelease) {
501492
return ofVersion(major, minor, patch, preRelease);
@@ -514,7 +505,6 @@ public static Version of(int major, int minor, int patch, String preRelease) {
514505
* @param version the version string to parse
515506
* @return a new {@link Version} instance
516507
* @throws IllegalArgumentException if the version string is null, blank, or invalid
517-
* @since 1.0.0
518508
*/
519509
public static Version of(String version) {
520510
return ofVersion(version);
@@ -530,7 +520,6 @@ public static Version of(String version) {
530520
*
531521
* @param major the major version number
532522
* @return a new {@link Version} instance
533-
* @since 1.0.0
534523
*/
535524
public static Version ofVersion(int major) {
536525
return new Version(major);
@@ -547,7 +536,6 @@ public static Version ofVersion(int major) {
547536
* @param major the major version number
548537
* @param minor the minor version number
549538
* @return a new {@link Version} instance
550-
* @since 1.0.0
551539
*/
552540
public static Version ofVersion(int major, int minor) {
553541
return new Version(major, minor);
@@ -565,7 +553,6 @@ public static Version ofVersion(int major, int minor) {
565553
* @param minor the minor version number
566554
* @param patch the patch version number
567555
* @return a new {@link Version} instance
568-
* @since 1.0.0
569556
*/
570557
public static Version ofVersion(int major, int minor, int patch) {
571558
return new Version(major, minor, patch);
@@ -584,7 +571,6 @@ public static Version ofVersion(int major, int minor, int patch) {
584571
* @param patch the patch version number
585572
* @param preRelease the pre-release identifier
586573
* @return a new {@link Version} instance
587-
* @since 1.0.0
588574
*/
589575
public static Version ofVersion(int major, int minor, int patch, String preRelease) {
590576
return new Version(major, minor, patch, preRelease);
@@ -604,7 +590,6 @@ public static Version ofVersion(int major, int minor, int patch, String preRelea
604590
* @param version the version string to parse
605591
* @return a new {@link Version} instance
606592
* @throws IllegalArgumentException if the version string is null, blank, or contains non-numeric parts
607-
* @since 1.0.0
608593
*/
609594
public static Version ofVersion(String version) {
610595
assertNotNull(version, () -> "The 'version' argument must not be null!");
@@ -624,6 +609,27 @@ public static Version ofVersion(String version) {
624609
return of(major, minor, patch, preRelease);
625610
}
626611

612+
/**
613+
* Creates a {@link Version} by detecting the version from the artifact containing the specified class.
614+
* This method uses {@link ArtifactDetector} to locate the artifact and retrieve its version.
615+
*
616+
* <h3>Example Usage</h3>
617+
* <pre>{@code
618+
* Version version = Version.ofVersion(MyClass.class); // e.g., 1.0.0
619+
* }</pre>
620+
*
621+
* @param classInResource the class contained in the artifact whose version is to be detected
622+
* @return a new {@link Version} instance
623+
*/
624+
public static Version ofVersion(@Nonnull Class<?> classInResource) {
625+
assertNotNull(classInResource, () -> "The 'classInResource' argument must not be null!");
626+
ClassLoader classLoader = classInResource.getClassLoader();
627+
ArtifactDetector detector = new ArtifactDetector(classLoader);
628+
Artifact artifact = detector.detect(classInResource);
629+
String version = artifact.getVersion();
630+
return ofVersion(version);
631+
}
632+
627633
/**
628634
* Class that exposes the version. Fetches the "Implementation-Version" manifest attribute from the jar file.
629635
*

microsphere-java-core/src/test/java/io/microsphere/classloading/ArtifactDetectorTest.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,19 @@
2020
import io.microsphere.LoggingTest;
2121
import org.junit.jupiter.api.Test;
2222

23+
import javax.annotation.Nonnull;
24+
import java.net.URL;
2325
import java.util.List;
2426

27+
import static io.microsphere.AbstractTestCase.TEST_NULL_SET;
28+
import static io.microsphere.collection.Sets.ofSet;
29+
import static io.microsphere.net.URLUtils.ofURL;
2530
import static io.microsphere.util.ClassLoaderUtils.getDefaultClassLoader;
2631
import static java.util.Collections.emptySet;
32+
import static org.junit.jupiter.api.Assertions.assertEquals;
2733
import static org.junit.jupiter.api.Assertions.assertNotNull;
34+
import static org.junit.jupiter.api.Assertions.assertNull;
35+
import static org.junit.jupiter.api.Assertions.assertThrows;
2836
import static org.junit.jupiter.api.Assertions.assertTrue;
2937

3038
/**
@@ -43,16 +51,41 @@ void testDetect() {
4351
assertNotNull(artifacts);
4452
}
4553

54+
@Test
55+
void testDetectOnClassInResource() {
56+
ArtifactDetector instance = new ArtifactDetector();
57+
assertThrows(NullPointerException.class, () -> instance.detect((Class) null));
58+
59+
Artifact artifact = instance.detect(ArtifactDetector.class);
60+
assertNull(artifact);
61+
62+
artifact = instance.detect(Nonnull.class);
63+
assertNotNull(artifact);
64+
assertEquals("jsr305", artifact.getArtifactId());
65+
assertEquals("3.0.2", artifact.getVersion());
66+
}
67+
68+
@Test
69+
void testDetectOnResourceURL() {
70+
ArtifactDetector instance = new ArtifactDetector();
71+
assertThrows(NullPointerException.class, () -> instance.detect((URL) null));
72+
73+
URL url = ofURL("file:///not-found");
74+
Artifact artifact = instance.detect(url);
75+
assertNull(artifact);
76+
}
77+
4678
@Test
4779
void testDetectOnNullSet() {
4880
ArtifactDetector instance = new ArtifactDetector(getDefaultClassLoader());
49-
assertTrue(instance.detect(null).isEmpty());
81+
assertTrue(instance.detect(TEST_NULL_SET).isEmpty());
5082
}
5183

5284
@Test
5385
void testDetectOnEmptySet() {
5486
ArtifactDetector instance = new ArtifactDetector(null);
5587
assertTrue(instance.detect(emptySet()).isEmpty());
88+
assertTrue(instance.detect(ofSet(ofURL("file:///not-found"))).isEmpty());
5689
}
5790

5891
@Test

microsphere-java-core/src/test/java/io/microsphere/util/VersionTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import org.junit.jupiter.api.Test;
2020

21+
import javax.annotation.Nullable;
22+
2123
import static io.microsphere.constants.SymbolConstants.DOT;
2224
import static io.microsphere.constants.SymbolConstants.HYPHEN;
2325
import static io.microsphere.constants.SymbolConstants.SPACE;
@@ -117,6 +119,12 @@ void testOfWithVersion() {
117119
assertEquals(PATCH, version.getPatch());
118120
}
119121

122+
@Test
123+
void testOfVersionOnClassInResource() {
124+
Version version = ofVersion(Nullable.class);
125+
assertEquals("3.0.2", version.toString());
126+
}
127+
120128
@Test
121129
void testOfOnNullPointException() {
122130
assertThrows(IllegalArgumentException.class, () -> of(null));

0 commit comments

Comments
 (0)