001/*
002 * JPPF.
003 * Copyright (C) 2005-2018 JPPF Team.
004 * http://www.jppf.org
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.jppf.utils;
019
020import java.io.*;
021
022import org.slf4j.*;
023
024/**
025 * This class provides a utility method to determine the JPPF build number available in the class path.<br>
026 * It is used for the nodes to determine when their code is outdated, in which case they will automatically reload
027 * their own code.
028 * @author Laurent Cohen
029 */
030public final class VersionUtils {
031  /**
032   * Logger for this class.
033   */
034  private static Logger log = LoggerFactory.getLogger(VersionUtils.class);
035  /**
036   * Determines whether debug log statements are enabled.
037   */
038  private static boolean debugEnabled = LoggingUtils.isDebugEnabled(log);
039  /**
040   * The singleton instance holding the version information.
041   */
042  private static final Version VERSION = createVersionInfo();
043
044  /**
045   * Instantiation of this class is not permitted.
046   */
047  private VersionUtils() {
048  }
049
050  /**
051   * Read the version information properties file and return the information in a dedicated object.
052   * @return a {@link Version} instance.
053   */
054  private static Version createVersionInfo() {
055    final TypedProperties props = new TypedProperties();
056    Version v = null;
057    try (final InputStream is = VersionUtils.class.getClassLoader().getResourceAsStream("META-INF/jppf-version.properties")) {
058      props.load(is);
059      v = new Version(props.getString("version.number", ""), props.getString("build.number", ""), props.getString("build.date", ""));
060    } catch (final Exception e) {
061      final String s = "JPPF version information could not be determined";
062      if (debugEnabled) log.debug(s, e);
063      else log.warn(s + ": " + ExceptionUtils.getMessage(e));
064      v = new Version(s, "", "");
065    }
066    return v;
067  }
068
069  /**
070   * Log the JPPF version information and process id.
071   * @param component the JPPF component type: driver, node or client.
072   * @param uuid the component uuid.
073   */
074  public static void logVersionInformation(final String component, final String uuid) {
075    final String comp = component == null ? "<unknown component type>" : component;
076    final int pid = SystemUtils.getPID();
077    final String hrule = StringUtils.padRight("", '-', 80);
078    log.info(hrule);
079    log.info(VersionUtils.VERSION.toString());
080    log.info("starting "+ comp + " with PID=" + pid + ", UUID=" + uuid);
081    log.info(hrule);
082  }
083
084  /**
085   * Return the singleton object which provides the JPPF version information. 
086   * @return a {@link Version} instance.
087   */
088  public static Version getVersion() {
089    return VERSION;
090  }
091
092  /**
093   * Describes the available version information.
094   */
095  public static class Version implements Serializable {
096    /**
097     * Explicit serialVersionUID.
098     */
099    private static final long serialVersionUID = 1L;
100    /**
101     * The JPPF version number.
102     */
103    private final String versionNumber;
104    /**
105     * The JPPF build number.
106     */
107    private final String buildNumber;
108    /**
109     * The JPPF build date.
110     */
111    private final String buildDate;
112
113    /**
114     * Initialize this version object.
115     * @param versionNumber the JPPF version number.
116     * @param buildNumber the JPPF build number.
117     * @param buildDate the JPPF build date.
118     */
119    public Version(final String versionNumber, final String buildNumber, final String buildDate) {
120      super();
121      this.versionNumber = versionNumber;
122      this.buildNumber = buildNumber;
123      this.buildDate = buildDate;
124    }
125
126    /**
127     * Get the JPPF version number.
128     * @return the version number as a string.
129     */
130    public String getVersionNumber() {
131      return versionNumber;
132    }
133
134    /**
135     * Get the JPPF build number.
136     * @return the build number as a string.
137     */
138    public String getBuildNumber() {
139      return buildNumber;
140    }
141
142    /**
143     * Get the JPPF build date.
144     * @return the build date as a string.
145     */
146    public String getBuildDate() {
147      return buildDate;
148    }
149
150    @Override
151    public String toString() {
152      final StringBuilder sb = new StringBuilder();
153      sb.append("JPPF Version: ").append(versionNumber);
154      sb.append(", Build number: ").append(buildNumber);
155      sb.append(", Build date: ").append(buildDate);
156      return sb.toString();
157    }
158  }
159}