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