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.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 StringBuilder sb = new StringBuilder(); 097 for (Entry<Object, Object> property: properties.entrySet()) { 098 sb.append(property.getKey()).append(':').append(property.getValue()).append('\n'); 099 } 100 releaseDescription = sb.toString(); 101 } 102 103 /** 104 * Initializes version info 105 */ 106 public void init() { 107 try (InputStream stream = Utils.getResourceAsStream(getClass(), "/REVISION")) { 108 if (stream == null) { 109 Logging.warn(tr("The revision file ''/REVISION'' is missing.")); 110 version = 0; 111 releaseDescription = ""; 112 return; 113 } 114 initFromRevisionInfo(stream); 115 } catch (IOException e) { 116 Logging.warn(e); 117 } 118 } 119 120 /** 121 * Replies the version string. Either the SVN revision "1234" (as string) or the 122 * the I18n equivalent of "UNKNOWN". 123 * 124 * @return the JOSM version 125 */ 126 public String getVersionString() { 127 return version == 0 ? tr("UNKNOWN") : Integer.toString(version); 128 } 129 130 /** 131 * Replies a text with the release attributes 132 * 133 * @return a text with the release attributes 134 */ 135 public String getReleaseAttributes() { 136 return releaseDescription; 137 } 138 139 /** 140 * Replies the build date as string 141 * 142 * @return the build date as string 143 */ 144 public String getTime() { 145 return time; 146 } 147 148 /** 149 * Replies the JOSM version. Replies {@link #JOSM_UNKNOWN_VERSION} if the version isn't known. 150 * @return the JOSM version 151 */ 152 public int getVersion() { 153 return version; 154 } 155 156 /** 157 * Replies true if this is a local build, i.e. an unofficial development build. 158 * 159 * @return true if this is a local build, i.e. an unofficial development build. 160 */ 161 public boolean isLocalBuild() { 162 return isLocalBuild; 163 } 164 165 /** 166 * Returns the User-Agent string 167 * @return The User-Agent 168 */ 169 public String getAgentString() { 170 return getAgentString(true); 171 } 172 173 /** 174 * Returns the User-Agent string, with or without OS details 175 * @param includeOsDetails Append Operating System details at the end of the User-Agent 176 * @return The User-Agent 177 * @since 5956 178 */ 179 public String getAgentString(boolean includeOsDetails) { 180 int v = getVersion(); 181 String s = (v == JOSM_UNKNOWN_VERSION) ? "UNKNOWN" : Integer.toString(v); 182 if (buildName != null && !buildName.isEmpty()) { 183 s += ' ' + buildName; 184 } 185 if (isLocalBuild() && v != JOSM_UNKNOWN_VERSION) { 186 s += " SVN"; 187 } 188 String result = "JOSM/1.5 ("+ s+' '+LanguageInfo.getJOSMLocaleCode()+')'; 189 if (includeOsDetails) { 190 result += ' ' + PlatformManager.getPlatform().getOSDescription(); 191 } 192 return result; 193 } 194 195 /** 196 * Returns the full User-Agent string 197 * @return The User-Agent 198 * @since 5868 199 */ 200 public String getFullAgentString() { 201 return getAgentString() + " Java/"+Utils.getSystemProperty("java.version"); 202 } 203}