io.microsphere.classloading.ArtifactDetector Maven / Gradle / Ivy
The newest version!
package io.microsphere.classloading;
import io.microsphere.collection.CollectionUtils;
import io.microsphere.logging.Logger;
import io.microsphere.util.ClassLoaderUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
import static io.microsphere.logging.LoggerFactory.getLogger;
import static io.microsphere.net.URLUtils.normalizePath;
import static io.microsphere.util.ClassLoaderUtils.getDefaultClassLoader;
import static io.microsphere.util.ClassPathUtils.getBootstrapClassPaths;
import static io.microsphere.util.ServiceLoaderUtils.loadServicesList;
import static java.lang.System.getProperty;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
/**
* {@link Artifact} Detector
*
* @author Mercy
* @since 1.0.0
*/
public class ArtifactDetector {
private static final Logger logger = getLogger(ArtifactDetector.class);
private static final String JAVA_HOME_PATH = normalizePath(getProperty("java.home"));
private static final ClassLoader DEFAULT_CLASS_LOADER = ArtifactDetector.class.getClassLoader();
private static final List ARTIFACT_INFO_RESOLVERS = loadServicesList(ArtifactResolver.class, DEFAULT_CLASS_LOADER);
private final @Nonnull ClassLoader classLoader;
public ArtifactDetector() {
this(DEFAULT_CLASS_LOADER);
}
public ArtifactDetector(@Nullable ClassLoader classLoader) {
this.classLoader = classLoader == null ? getDefaultClassLoader() : classLoader;
}
public List detect() {
return detect(true);
}
public List detect(boolean includedJdkLibraries) {
Set classPathURLs = getClassPathURLs(includedJdkLibraries);
return detect(classPathURLs);
}
protected List detect(Set classPathURLs) {
if (CollectionUtils.isEmpty(classPathURLs)) {
return emptyList();
}
List artifactList = new LinkedList<>();
for (ArtifactResolver artifactResolver : ARTIFACT_INFO_RESOLVERS) {
Set artifactSet = artifactResolver.resolve(classPathURLs);
for (Artifact artifact : artifactSet) {
artifactList.add(artifact);
classPathURLs.remove(artifact.getLocation());
}
}
return unmodifiableList(artifactList);
}
protected Set getClassPathURLs(boolean includedJdkLibraries) {
Set urls = ClassLoaderUtils.findAllClassPathURLs(classLoader);
Set classPathURLs = new LinkedHashSet<>(urls);
if (!includedJdkLibraries) {
removeJdkClassPathURLs(classPathURLs);
}
if (logger.isDebugEnabled()) {
StringJoiner stringJoiner = new StringJoiner(System.lineSeparator());
for (URL classPathURL : classPathURLs) {
stringJoiner.add(classPathURL.toString());
}
logger.debug("ClassLoader[{}] covers the URLs[expected: {}, actual: {}], class-path : {}",
classLoader, urls.size(), classPathURLs.size(), stringJoiner);
}
return classPathURLs;
}
private void removeJdkClassPathURLs(Set classPathURLs) {
// Remove the URLs of Bootstrap Class-Path
Set bootstrapClassPaths = getBootstrapClassPaths();
Iterator iterator = classPathURLs.iterator();
while (iterator.hasNext()) {
URL url = iterator.next();
String path = url.getPath();
if (bootstrapClassPaths.contains(path) || path.contains(JAVA_HOME_PATH)) {
iterator.remove();
}
}
}
}