001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.io.IOException;
007import java.io.InputStream;
008import java.util.Optional;
009import java.util.Properties;
010import java.util.stream.Collectors;
011
012import org.openstreetmap.josm.tools.LanguageInfo;
013import org.openstreetmap.josm.tools.Logging;
014import org.openstreetmap.josm.tools.PlatformManager;
015import org.openstreetmap.josm.tools.Utils;
016
017/**
018 * Provides basic information about the currently used JOSM build.
019 * @since 2358
020 */
021public class Version {
022    /** constant to indicate that the current build isn't assigned a JOSM version number */
023    public static final int JOSM_UNKNOWN_VERSION = 0;
024
025    /** the unique instance */
026    private static Version instance;
027
028    /**
029     * Replies the unique instance of the version information
030     *
031     * @return the unique instance of the version information
032     */
033    public static synchronized Version getInstance() {
034        if (instance == null) {
035            instance = new Version();
036            instance.init();
037        }
038        return instance;
039    }
040
041    private int version;
042    private String releaseDescription;
043    private String time;
044    private String buildName;
045    private boolean isLocalBuild;
046
047    /**
048     * Initializes the version infos from the revision resource file
049     *
050     * @param revisionInfo the revision info from a revision resource file as InputStream
051     */
052    protected void initFromRevisionInfo(InputStream revisionInfo) {
053        if (revisionInfo == null) {
054            this.releaseDescription = tr("UNKNOWN");
055            this.version = JOSM_UNKNOWN_VERSION;
056            this.time = null;
057            return;
058        }
059
060        Properties properties = new Properties();
061        try {
062            properties.load(revisionInfo);
063        } catch (IOException e) {
064            Logging.log(Logging.LEVEL_WARN, tr("Error reading revision info from revision file: {0}", e.getMessage()), e);
065        }
066        String value = Optional.ofNullable(properties.getProperty("Revision")).orElse("").trim();
067        if (!value.isEmpty()) {
068            try {
069                version = Integer.parseInt(value);
070            } catch (NumberFormatException e) {
071                version = 0;
072                Logging.warn(tr("Unexpected JOSM version number in revision file, value is ''{0}''", value));
073            }
074        } else {
075            version = JOSM_UNKNOWN_VERSION;
076        }
077
078        // the last changed data
079        //
080        time = properties.getProperty("Last Changed Date");
081        if (time == null) {
082            time = properties.getProperty("Build-Date");
083        }
084
085        // is this a local build ?
086        //
087        isLocalBuild = "true".equalsIgnoreCase(
088                Optional.ofNullable(properties.getProperty("Is-Local-Build")).orElse("").trim());
089
090        // is this a specific build ?
091        //
092        buildName = Optional.ofNullable(properties.getProperty("Build-Name")).orElse("").trim();
093
094        // the revision info
095        //
096        releaseDescription = properties.entrySet().stream()
097                .map(property -> property.getKey() + ":" + property.getValue() + "\n")
098                .collect(Collectors.joining());
099    }
100
101    /**
102     * Initializes version info
103     */
104    public void init() {
105        try (InputStream stream = Utils.getResourceAsStream(getClass(), "/REVISION")) {
106            if (stream == null) {
107                Logging.warn(tr("The revision file ''/REVISION'' is missing."));
108                version = 0;
109                releaseDescription = "";
110                return;
111            }
112            initFromRevisionInfo(stream);
113        } catch (IOException e) {
114            Logging.warn(e);
115        }
116    }
117
118    /**
119     * Replies the version string. Either the SVN revision "1234" (as string) or the
120     * the I18n equivalent of "UNKNOWN".
121     *
122     * @return the JOSM version
123     */
124    public String getVersionString() {
125        return version == 0 ? tr("UNKNOWN") : Integer.toString(version);
126    }
127
128    /**
129     * Replies a text with the release attributes
130     *
131     * @return a text with the release attributes
132     */
133    public String getReleaseAttributes() {
134        return releaseDescription;
135    }
136
137    /**
138     * Replies the build date as string
139     *
140     * @return the build date as string
141     */
142    public String getTime() {
143        return time;
144    }
145
146    /**
147     * Replies the JOSM version. Replies {@link #JOSM_UNKNOWN_VERSION} if the version isn't known.
148     * @return the JOSM version
149     */
150    public int getVersion() {
151        return version;
152    }
153
154    /**
155     * Replies true if this is a local build, i.e. an unofficial development build.
156     *
157     * @return true if this is a local build, i.e. an unofficial development build.
158     */
159    public boolean isLocalBuild() {
160        return isLocalBuild;
161    }
162
163    /**
164     * Returns the User-Agent string
165     * @return The User-Agent
166     */
167    public String getAgentString() {
168        return getAgentString(true);
169    }
170
171    /**
172     * Returns the User-Agent string, with or without OS details
173     * @param includeOsDetails Append Operating System details at the end of the User-Agent
174     * @return The User-Agent
175     * @since 5956
176     */
177    public String getAgentString(boolean includeOsDetails) {
178        int v = getVersion();
179        String s = (v == JOSM_UNKNOWN_VERSION) ? "UNKNOWN" : Integer.toString(v);
180        if (!Utils.isEmpty(buildName)) {
181            s += ' ' + buildName;
182        }
183        if (isLocalBuild() && v != JOSM_UNKNOWN_VERSION) {
184            s += " SVN";
185        }
186        String result = "JOSM/1.5 ("+ s+' '+LanguageInfo.getJOSMLocaleCode()+')';
187        if (includeOsDetails) {
188            result += ' ' + PlatformManager.getPlatform().getOSDescription();
189        }
190        return result;
191    }
192
193    /**
194     * Returns the full User-Agent string
195     * @return The User-Agent
196     * @since 5868
197     */
198    public String getFullAgentString() {
199        return getAgentString() + " Java/"+Utils.getSystemProperty("java.version");
200    }
201}