package fr.gouv.vitam.common.server.application.resources;
import fr.gouv.vitam.common.logging.VitamLogger;
import fr.gouv.vitam.common.logging.VitamLoggerFactory;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
/**
* Created by kw on 31/12/2016.
*/
public class VersionHelper {
private static final VitamLogger LOGGER = VitamLoggerFactory.getInstance(VersionHelper.class);
private final static List<Map<String, String>> cachedComponents = new ArrayList<>();
private final static String MANIFEST_VITAM_FLAG = "Vitam-component";
/**
* Tag used to group the summary by
*/
public final static String MANIFEST_SUMMARY_TAG = "Scm-commit-id";
/**
* Read-only list of attributes searched into the main section of the jar manifests.
*/
public final static List<String> MANIFEST_FIELDS = Collections.unmodifiableList(Arrays.asList("Maven-groupId", "Maven-artefactId",
"Maven-version", "Scm-branch", "Scm-tags", MANIFEST_SUMMARY_TAG, "Scm-commit-id-abbrev", "Scm-dirty",
"Scm-commit-time", "Maven-build-timestamp", "Build-Jdk"));
static {
List<URL> resources;
try {
resources = Collections.list(Thread.currentThread().getContextClassLoader().getResources(JarFile.MANIFEST_NAME));
} catch (IOException e) {
LOGGER.warn("Unable to open any MANIFEST.MF during the search of component versions... No component version will be available in status API.", e);
resources = new LinkedList<>();
}
if (resources.isEmpty()) {
LOGGER.warn("No MANIFEST.MF file was found ! No component version will be available in status API");
} else {
LOGGER.info("Found {} components in classpath.", resources.size());
}
for (URL resource : resources) {
try {
Manifest manifest = new Manifest(resource.openStream());
if (manifest.getMainAttributes().getValue(MANIFEST_VITAM_FLAG) != null) {
cachedComponents.add(extractManifestInfo(manifest));
}
} catch (Exception e) {
LOGGER.warn("Unable to open MANIFEST.MF (from " + resource + ") to search for the component version... Skipping component.", e);
}
}
}
/**
* Get detailed information on all internal vitam components versions
* @return A read-only list of informations ; each entry stands for a component.
*/
public static List<Map<String, String>> getVersionDetailedInfo() {
return Collections.unmodifiableList(cachedComponents);
}
/**
* Get the summary version information for vitam components found in the current classpath.
* @return A map with keys being the git commit id (long hash) and the value the number of components having this version.
*/
public static Map<String, Long> getVersionSummary() {
// No need to return a read-only collection here, as this map is created just there and doesn't contain mutable elements.
return cachedComponents.stream().collect(Collectors.groupingBy(n -> n.getOrDefault(MANIFEST_SUMMARY_TAG, "<no commit id found>"), Collectors.counting()));
}
/**
* Extract manifest attributes into a map
* @param mf
* @return A read-only map of attributes.
*/
private static Map<String, String> extractManifestInfo(Manifest mf) {
Map<String, String> result = new HashMap<>();
Attributes attr = mf.getMainAttributes();
for (String field : MANIFEST_FIELDS) {
result.put(field, attr.getValue(field));
}
LOGGER.info("Found component : {}", result);
return Collections.unmodifiableMap(result);
}
}