001/*
002 * JPPF.
003 * Copyright (C) 2005-2016 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    String result = null;
056    TypedProperties props = new TypedProperties();
057    Version v = null;
058    try (InputStream is = VersionUtils.class.getClassLoader().getResourceAsStream("META-INF/jppf-version.properties")) {
059      props.load(is);
060      v = new Version(props.getString("version.number", ""), props.getString("build.number", ""), props.getString("build.date", ""));
061    } catch (Exception e) {
062      String s = "JPPF version information could not be determined";
063      if (debugEnabled) log.debug(s, e);
064      else log.warn(s + ": " + ExceptionUtils.getMessage(e));
065      v = new Version(s, "", "");
066    }
067    return v;
068  }
069
070  /**
071   * Log the JPPF version information and process id.
072   * @param component the JPPF component type: driver, node or client.
073   * @param uuid the component uuid.
074   */
075  public static void logVersionInformation(final String component, final String uuid) {
076    String comp = component == null ? "<unknown component type>" : component;
077    int pid = SystemUtils.getPID();
078    String hrule = StringUtils.padRight("", '-', 80);
079    log.info(hrule);
080    log.info(VersionUtils.VERSION.toString());
081    log.info("starting "+ comp + " with PID=" + pid + ", UUID=" + uuid);
082    log.info(hrule);
083  }
084
085  /**
086   * Return the singleton object which provides the JPPF version information. 
087   * @return a {@link Version} instance.
088   */
089  public static Version getVersion() {
090    return VERSION;
091  }
092
093  /**
094   * Describes the available version information.
095   */
096  public static class Version implements Serializable {
097    /**
098     * The JPPF version number.
099     */
100    private final String versionNumber;
101    /**
102     * The JPPF build number.
103     */
104    private final String buildNumber;
105    /**
106     * The JPPF build date.
107     */
108    private final String buildDate;
109
110    /**
111     * Initialize this version object.
112     * @param versionNumber the JPPF version number.
113     * @param buildNumber the JPPF build number.
114     * @param buildDate the JPPF build date.
115     */
116    public Version(final String versionNumber, final String buildNumber, final String buildDate) {
117      super();
118      this.versionNumber = versionNumber;
119      this.buildNumber = buildNumber;
120      this.buildDate = buildDate;
121    }
122
123    /**
124     * Get the JPPF version number.
125     * @return the version number as a string.
126     */
127    public String getVersionNumber() {
128      return versionNumber;
129    }
130
131    /**
132     * Get the JPPF build number.
133     * @return the build number as a string.
134     */
135    public String getBuildNumber() {
136      return buildNumber;
137    }
138
139    /**
140     * Get the JPPF build date.
141     * @return the build date as a string.
142     */
143    public String getBuildDate() {
144      return buildDate;
145    }
146
147    @Override
148    public String toString() {
149      StringBuilder sb = new StringBuilder();
150      sb.append("JPPF Version: ").append(versionNumber);
151      sb.append(", Build number: ").append(buildNumber);
152      sb.append(", Build date: ").append(buildDate);
153      return sb.toString();
154    }
155  }
156}