/* * Copyright 2013 The Netty Project * * The Netty Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package io.netty.util; import io.netty.util.internal.PlatformDependent; import java.io.InputStream; import java.net.URL; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Enumeration; import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeMap; /** * Retrieves the version information of available Netty artifacts. *

* This class retrieves the version information from {@code META-INF/io.netty.versions.properties}, which is * generated in build time. Note that it may not be possible to retrieve the information completely, depending on * your environment, such as the specified {@link ClassLoader}, the current {@link SecurityManager}. *

*/ public final class Version { private static final String PROP_VERSION = ".version"; private static final String PROP_BUILD_DATE = ".buildDate"; private static final String PROP_COMMIT_DATE = ".commitDate"; private static final String PROP_SHORT_COMMIT_HASH = ".shortCommitHash"; private static final String PROP_LONG_COMMIT_HASH = ".longCommitHash"; private static final String PROP_REPO_STATUS = ".repoStatus"; /** * Retrieves the version information of Netty artifacts using the current * {@linkplain Thread#getContextClassLoader() context class loader}. * * @return A {@link Map} whose keys are Maven artifact IDs and whose values are {@link Version}s */ public static Map identify() { return identify(null); } /** * Retrieves the version information of Netty artifacts using the specified {@link ClassLoader}. * * @return A {@link Map} whose keys are Maven artifact IDs and whose values are {@link Version}s */ public static Map identify(ClassLoader classLoader) { if (classLoader == null) { classLoader = PlatformDependent.getContextClassLoader(); } // Collect all properties. Properties props = new Properties(); try { Enumeration resources = classLoader.getResources("META-INF/io.netty.versions.properties"); while (resources.hasMoreElements()) { URL url = resources.nextElement(); InputStream in = url.openStream(); try { props.load(in); } finally { try { in.close(); } catch (Exception ignore) { // Ignore. } } } } catch (Exception ignore) { // Not critical. Just ignore. } // Collect all artifactIds. Set artifactIds = new HashSet(); for (Object o: props.keySet()) { String k = (String) o; int dotIndex = k.indexOf('.'); if (dotIndex <= 0) { continue; } String artifactId = k.substring(0, dotIndex); // Skip the entries without required information. if (!props.containsKey(artifactId + PROP_VERSION) || !props.containsKey(artifactId + PROP_BUILD_DATE) || !props.containsKey(artifactId + PROP_COMMIT_DATE) || !props.containsKey(artifactId + PROP_SHORT_COMMIT_HASH) || !props.containsKey(artifactId + PROP_LONG_COMMIT_HASH) || !props.containsKey(artifactId + PROP_REPO_STATUS)) { continue; } artifactIds.add(artifactId); } Map versions = new TreeMap(); for (String artifactId: artifactIds) { versions.put( artifactId, new Version( artifactId, props.getProperty(artifactId + PROP_VERSION), parseIso8601(props.getProperty(artifactId + PROP_BUILD_DATE)), parseIso8601(props.getProperty(artifactId + PROP_COMMIT_DATE)), props.getProperty(artifactId + PROP_SHORT_COMMIT_HASH), props.getProperty(artifactId + PROP_LONG_COMMIT_HASH), props.getProperty(artifactId + PROP_REPO_STATUS))); } return versions; } private static long parseIso8601(String value) { try { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse(value).getTime(); } catch (ParseException e) { return 0; } } /** * Prints the version information to {@link System#err}. */ public static void main(String[] args) { for (Version v: identify().values()) { System.err.println(v); } } private final String artifactId; private final String artifactVersion; private final long buildTimeMillis; private final long commitTimeMillis; private final String shortCommitHash; private final String longCommitHash; private final String repositoryStatus; private Version( String artifactId, String artifactVersion, long buildTimeMillis, long commitTimeMillis, String shortCommitHash, String longCommitHash, String repositoryStatus) { this.artifactId = artifactId; this.artifactVersion = artifactVersion; this.buildTimeMillis = buildTimeMillis; this.commitTimeMillis = commitTimeMillis; this.shortCommitHash = shortCommitHash; this.longCommitHash = longCommitHash; this.repositoryStatus = repositoryStatus; } public String artifactId() { return artifactId; } public String artifactVersion() { return artifactVersion; } public long buildTimeMillis() { return buildTimeMillis; } public long commitTimeMillis() { return commitTimeMillis; } public String shortCommitHash() { return shortCommitHash; } public String longCommitHash() { return longCommitHash; } public String repositoryStatus() { return repositoryStatus; } @Override public String toString() { return artifactId + '-' + artifactVersion + '.' + shortCommitHash + ("clean".equals(repositoryStatus)? "" : " (repository: " + repositoryStatus + ')'); } }