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