<commit_before>/*
 * Copyright (c) 2013 - 2015 xxyy (<NAME>; <EMAIL>). All rights reserved.
 *
 * Any usage, including, but not limited to, compiling, running, redistributing, printing,
 *  copying and reverse-engineering is strictly prohibited without explicit written permission
 *  from the original author and may result in legal steps being taken.
 *
 * See the included LICENSE file (core/src/main/resources) or email <EMAIL> for details.
 */

package io.github.xxyy.common.version;

import java.io.IOException;
import java.net.URL;
import java.security.CodeSource;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.JarInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Holds the loaded version of a Plugin, as given in its JAR's Implementation-Title, Implementation-Version and Implementation-Build.
 *
 * @author xxyy98 (http://xxyy.github.io/)
 */
public final class PluginVersion {

    private final String implementationTitle;
    private final String implementationVersion;
    private final String implementationBuild;

    @java.beans.ConstructorProperties({"implementationTitle", "implementationVersion", "implementationBuild"})
    private PluginVersion(String implementationTitle, String implementationVersion, String implementationBuild) {
        this.implementationTitle = implementationTitle;
        this.implementationVersion = implementationVersion;
        this.implementationBuild = implementationBuild;
    }

    public static PluginVersion ofClass(Class<?> clazz) {
        final CodeSource codeSource = clazz.getProtectionDomain().getCodeSource();
        final URL url = codeSource.getLocation();

        if (url.toExternalForm().endsWith("jar")) { //Account for .xyjar
            try (JarInputStream jis = new JarInputStream(url.openStream())) {
                final Attributes attrs = jis.getManifest().getMainAttributes();

                return new PluginVersion(
                        attrs.getValue(Name.IMPLEMENTATION_TITLE),
                        attrs.getValue(Name.IMPLEMENTATION_VERSION),
                        attrs.getValue("Implementation-Build"));
            } catch (IOException ex) {
                Logger.getLogger(PluginVersion.class.getName())
                        .log(Level.SEVERE, null, ex);
            }
        }

        return null;
    }

    @Override
    public String toString() {
        return implementationTitle + " Version " + implementationVersion + " Build " + implementationBuild;
    }

    public String getImplementationTitle() {
        return this.implementationTitle;
    }

    public String getImplementationVersion() {
        return this.implementationVersion;
    }

    public String getImplementationBuild() {
        return this.implementationBuild;
    }
}<commit_msg>Improve PluginVersion<commit_after>/*
 * Copyright (c) 2013 - 2015 xxyy (<NAME>; <EMAIL>). All rights reserved.
 *
 * Any usage, including, but not limited to, compiling, running, redistributing, printing,
 *  copying and reverse-engineering is strictly prohibited without explicit written permission
 *  from the original author and may result in legal steps being taken.
 *
 * See the included LICENSE file (core/src/main/resources) or email <EMAIL> for details.
 */

package io.github.xxyy.common.version;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.net.URL;
import java.security.CodeSource;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.JarInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * This class offers a static utility method to extract manifest version information from JAR files by a class.
 * Instances hold the retrieved immutable information.
 *
 * @author <a href="http://xxyy.github.io/">xxyy</a>
 */
public final class PluginVersion {

    private final String implementationTitle;
    private final String implementationVersion;
    private final String implementationBuild;

    @java.beans.ConstructorProperties({"implementationTitle", "implementationVersion", "implementationBuild"})
    private PluginVersion(String implementationTitle, String implementationVersion, String implementationBuild) {
        this.implementationTitle = implementationTitle;
        this.implementationVersion = implementationVersion;
        this.implementationBuild = implementationBuild;
    }

    /**
     * Attempts to retrieve version information for a class from its enclosing JAR archive's manifest. If the class is
     * not in such archive, or the information cannot be acquired for any other reason, a special instance with
     * {@link Class#getSimpleName()} as implementation title and "unknown" as version and build number will be
     * returned. Note that any or all of the attributes may be unspecified and therefore null.
     *
     * @param clazz the class to retrieve version information for
     * @return the version information for given class
     */
    @NotNull
    public static PluginVersion ofClass(@NotNull Class<?> clazz) {
        @Nullable CodeSource codeSource = clazz.getProtectionDomain().getCodeSource();

        if (codeSource != null) {
            URL url = codeSource.getLocation();

            if (url != null && url.toExternalForm().endsWith(".jar")) {
                try (JarInputStream jis = new JarInputStream(url.openStream())) {
                    if (jis.getManifest() != null) {
                        Attributes attrs = jis.getManifest().getMainAttributes();

                        return new PluginVersion(
                                attrs.getValue(Name.IMPLEMENTATION_TITLE),
                                attrs.getValue(Name.IMPLEMENTATION_VERSION),
                                attrs.getValue("Implementation-Build")
                        );
                    }
                } catch (IOException ex) {
                    Logger.getLogger(PluginVersion.class.getName()).log(Level.SEVERE,
                            "Error occurred while reading JAR version info for " + clazz.getName(), ex);
                }
            }
        }

        return new PluginVersion(clazz.getSimpleName(), "unknown", "unknown");
    }

    @Override
    public String toString() {
        return implementationTitle + " Version " + implementationVersion + " Build " + implementationBuild;
    }

    @Nullable
    public String getImplementationTitle() {
        return this.implementationTitle;
    }

    @Nullable
    public String getImplementationVersion() {
        return this.implementationVersion;
    }

    @Nullable
    public String getImplementationBuild() {
        return this.implementationBuild;
    }
}
{'fraction_non_alphanumeric': 0.08790239600176393, 'fraction_numerical': 0.0026458915184477435, 'mean_word_length': 2.9193548387096775, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5217745', 'n_tokens_mistral': 1711, 'n_tokens_neox': 1608, 'n_words': 495}