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}