All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.microsphere.classloading.ManifestArtifactResolver Maven / Gradle / Ivy

The newest version!
package io.microsphere.classloading;


import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.Enumeration;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import static io.microsphere.constants.FileConstants.JAR_EXTENSION;
import static io.microsphere.net.URLUtils.isArchiveURL;
import static io.microsphere.util.ArrayUtils.isNotEmpty;
import static io.microsphere.util.StringUtils.split;
import static java.lang.System.getProperty;

/**
 * The class {@link ArtifactResolver} based on the resource "META-INF/MANIFEST.MF"
 *
 * @author Mercy
 * @since 1.0.0
 */
public class ManifestArtifactResolver extends AbstractArtifactResolver {

    public static final String MANIFEST_RESOURCE_PATH = "META-INF/MANIFEST.MF";

    public static final String ARTIFACT_ID_ATTRIBUTE_NAMES_PROPERTY_NAME = "microsphere.artifact-id.manifest-attribute-names";

    public static final String VERSION_ATTRIBUTE_NAMES_PROPERTY_NAME = "microsphere.artifact-version.manifest-attribute-names";

    private static final String[] DEFAULT_ARTIFACT_ID_ATTRIBUTE_NAMES = {
            "Bundle-Name",
            "Automatic-Module-Name",
            "Implementation-Title"
    };

    private static final String[] DEFAULT_VERSION_ATTRIBUTE_NAMES = {
            "Bundle-Version",
            "Implementation-Version"
    };

    private static final String[] ARTIFACT_ID_ATTRIBUTE_NAMES = getArtifactIdAttributeNames();

    private static final String[] VERSION_ATTRIBUTE_NAMES = getVersionAttributeNames();

    private static String[] getArtifactIdAttributeNames() {
        return getPropertyValues(ARTIFACT_ID_ATTRIBUTE_NAMES_PROPERTY_NAME, DEFAULT_ARTIFACT_ID_ATTRIBUTE_NAMES);
    }

    private static String[] getVersionAttributeNames() {
        return getPropertyValues(VERSION_ATTRIBUTE_NAMES_PROPERTY_NAME, DEFAULT_VERSION_ATTRIBUTE_NAMES);
    }

    private static String[] getPropertyValues(String propertyName, String... defaultValues) {
        String propertyValue = getProperty(propertyName);
        String[] values = split(propertyValue, ",");
        return isNotEmpty(values) ? values : defaultValues;
    }

    public static final int DEFAULT_PRIORITY = 2;

    public ManifestArtifactResolver() {
        setPriority(DEFAULT_PRIORITY);
    }

    @Override
    protected void doResolve(Collection artifactSet, URLClassLoader urlClassLoader) {
        try {
            Enumeration manifestResourceURLs = urlClassLoader.getResources(MANIFEST_RESOURCE_PATH);
            while (manifestResourceURLs.hasMoreElements()) {
                Artifact artifact = resolveArtifactMetaInfoInManifest(manifestResourceURLs.nextElement());
                if (artifact != null) {
                    artifactSet.add(artifact);
                }
            }
        } catch (IOException e) {
            logger.error("{} can't be resolved", MANIFEST_RESOURCE_PATH, e);
        }
    }

    private Artifact resolveArtifactMetaInfoInManifest(URL manifestResourceURL) {
        Artifact artifact = null;
        try (InputStream inputStream = manifestResourceURL.openStream()) {
            Manifest manifest = new Manifest(inputStream);
            artifact = resolveArtifactMetaInfoInManifest(manifest, manifestResourceURL);
        } catch (IOException e) {
            logger.error("{}[Path : {}] can't be resolved", MANIFEST_RESOURCE_PATH, manifestResourceURL.getPath(), e);
        }
        return artifact;
    }

    private Artifact resolveArtifactMetaInfoInManifest(Manifest manifest, URL manifestResourceURL)
            throws MalformedURLException {
        Attributes mainAttributes = manifest.getMainAttributes();
        URL artifactResourceURL = resolveArtifactResourceURL(manifestResourceURL);
        if (artifactResourceURL == null) {
            return null;
        }

        boolean isArchiveURL = isArchiveURL(artifactResourceURL);
        String artifactId = resolveArtifactId(mainAttributes, artifactResourceURL, isArchiveURL);
        if (artifactId == null) {
            return null;
        }
        String version = resolveVersion(mainAttributes, artifactId, artifactResourceURL, isArchiveURL);
        return Artifact.create(artifactId, version, artifactResourceURL);
    }

    private String resolveArtifactId(Attributes attributes, URL artifactResourceURL, boolean isArchiveURL) {
        String artifactId = null;

        for (String artifactIdAttributeName : ARTIFACT_ID_ATTRIBUTE_NAMES) {
            artifactId = attributes.getValue(artifactIdAttributeName);
            if (artifactId != null) {
                break;
            }
        }

        if (artifactId == null && isArchiveURL) {
            artifactId = resolveArtifactId(artifactResourceURL);
        }

        if (artifactId == null) {
            if (logger.isDebugEnabled()) {
                logger.debug("The artifactId can't be resolved from the {} of artifact[resource: {}] : {}",
                        artifactResourceURL.getPath(),
                        MANIFEST_RESOURCE_PATH,
                        attributes.entrySet()
                );
            }
        }

        return artifactId;
    }

    private String resolveArtifactId(URL artifactResourceURL) {
        String path = artifactResourceURL.getPath();
        int lastSlashIndex = path.lastIndexOf('/');
        if (lastSlashIndex < 0) {
            return null;
        }
        int fileExtensionIndex = path.indexOf(JAR_EXTENSION);
        if (fileExtensionIndex < lastSlashIndex) {
            return null;
        }
        String jarFileName = path.substring(lastSlashIndex + 1, fileExtensionIndex);
        int lastHyphenIndex = jarFileName.lastIndexOf('-');
        if (lastHyphenIndex < 0) {
            return jarFileName;
        }
        return jarFileName.substring(0, lastHyphenIndex);
    }

    private String resolveVersion(Attributes attributes, String artifactId, URL artifactResourceURL, boolean isArchiveURL) {
        String version = null;

        for (String versionAttributeName : VERSION_ATTRIBUTE_NAMES) {
            version = attributes.getValue(versionAttributeName);
            if (version != null) {
                break;
            }
        }

        if (version == null && isArchiveURL) {
            version = resolveVersion(artifactId, artifactResourceURL);
            if (version == null) {
                version = resolveVersion(resolveArtifactId(artifactResourceURL), artifactResourceURL);
            }
        }

        if (version == null) {
            logger.debug("The version can't be found in the {} of artifact[Path: {}]", MANIFEST_RESOURCE_PATH,
                    artifactResourceURL.getPath()
            );
        }

        return version;
    }

    private String resolveVersion(String artifactId, URL artifactResourceURL) {
        String path = artifactResourceURL.getPath();

        int lastArtifactIdIndex = path.lastIndexOf(artifactId);
        if (lastArtifactIdIndex < 0) {
            return null;
        }

        int beginIndex = lastArtifactIdIndex + artifactId.length() + 1;

        int fileExtensionIndex = path.indexOf(JAR_EXTENSION);
        if (fileExtensionIndex <= beginIndex) {
            return null;
        }

        return path.substring(beginIndex, fileExtensionIndex);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy