001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.tools; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Dimension; 007import java.awt.GraphicsEnvironment; 008import java.awt.event.KeyEvent; 009import java.io.BufferedReader; 010import java.io.File; 011import java.io.FileReader; 012import java.io.IOException; 013import java.io.InputStreamReader; 014import java.util.Arrays; 015 016import javax.swing.JOptionPane; 017 018import org.openstreetmap.josm.Main; 019import org.openstreetmap.josm.gui.ExtendedDialog; 020 021/** 022 * see PlatformHook.java 023 * 024 * BTW: THIS IS A STUB. See comments below for details. 025 * 026 * Don't write (Main.platform instanceof PlatformHookUnixoid) because other platform 027 * hooks are subclasses of this class. 028 */ 029public class PlatformHookUnixoid implements PlatformHook { 030 031 private String osDescription; 032 033 @Override 034 public void preStartupHook() { 035 } 036 037 @Override 038 public void startupHook() { 039 } 040 041 @Override 042 public void openUrl(String url) throws IOException { 043 String[] programs = {"gnome-open", "kfmclient openURL", "firefox"}; 044 for (String program : programs) { 045 try { 046 Runtime.getRuntime().exec(program+" "+url); 047 return; 048 } catch (IOException e) { 049 Main.warn(e); 050 } 051 } 052 } 053 054 @Override 055 public void initSystemShortcuts() { 056 // TODO: Insert system shortcuts here. See Windows and especially OSX to see how to. 057 for(int i = KeyEvent.VK_F1; i <= KeyEvent.VK_F12; ++i) 058 Shortcut.registerSystemShortcut("screen:toogle"+i, tr("reserved"), i, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK).setAutomatic(); 059 Shortcut.registerSystemShortcut("system:reset", tr("reserved"), KeyEvent.VK_DELETE, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK).setAutomatic(); 060 Shortcut.registerSystemShortcut("system:resetX", tr("reserved"), KeyEvent.VK_BACK_SPACE, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK).setAutomatic(); 061 } 062 063 /** 064 * This should work for all platforms. Yeah, should. 065 * See PlatformHook.java for a list of reasons why 066 * this is implemented here... 067 */ 068 @Override 069 public String makeTooltip(String name, Shortcut sc) { 070 String result = ""; 071 result += "<html>"; 072 result += name; 073 if (sc != null && sc.getKeyText().length() != 0) { 074 result += " "; 075 result += "<font size='-2'>"; 076 result += "("+sc.getKeyText()+")"; 077 result += "</font>"; 078 } 079 result += " </html>"; 080 return result; 081 } 082 083 @Override 084 public String getDefaultStyle() { 085 return "javax.swing.plaf.metal.MetalLookAndFeel"; 086 } 087 088 @Override 089 public boolean canFullscreen() { 090 return GraphicsEnvironment.getLocalGraphicsEnvironment() 091 .getDefaultScreenDevice().isFullScreenSupported(); 092 } 093 094 @Override 095 public boolean rename(File from, File to) { 096 return from.renameTo(to); 097 } 098 099 /** 100 * Get the Java package name including detailed version. 101 * 102 * Some Java bugs are specific to a certain security update, so in addition 103 * to the Java version, we also need the exact package version. 104 * 105 * This was originally written for #8921, so only Debian based distributions 106 * are covered at the moment. This can be extended to other distributions 107 * if needed. 108 * 109 * @return The package name and package version if it can be identified, null 110 * otherwise 111 */ 112 public String getJavaPackageDetails() { 113 try { 114 String dist = Utils.execOutput(Arrays.asList("lsb_release", "-i", "-s")); 115 if ("Debian".equalsIgnoreCase(dist) || "Ubuntu".equalsIgnoreCase(dist)) { 116 String javaHome = System.getProperty("java.home"); 117 if ("/usr/lib/jvm/java-6-openjdk-amd64/jre".equals(javaHome) || 118 "/usr/lib/jvm/java-6-openjdk-i386/jre".equals(javaHome) || 119 "/usr/lib/jvm/java-6-openjdk/jre".equals(javaHome)) { 120 String version = Utils.execOutput(Arrays.asList("dpkg-query", "--show", "--showformat", "${Architecture}-${Version}", "openjdk-6-jre")); 121 return "openjdk-6-jre:" + version; 122 } 123 if ("/usr/lib/jvm/java-7-openjdk-amd64/jre".equals(javaHome) || 124 "/usr/lib/jvm/java-7-openjdk-i386/jre".equals(javaHome)) { 125 String version = Utils.execOutput(Arrays.asList("dpkg-query", "--show", "--showformat", "${Architecture}-${Version}", "openjdk-7-jre")); 126 return "openjdk-7-jre:" + version; 127 } 128 } 129 } catch (IOException e) { 130 Main.warn(e); 131 } 132 return null; 133 } 134 135 protected String buildOSDescription() { 136 String osName = System.getProperty("os.name"); 137 if ("Linux".equalsIgnoreCase(osName)) { 138 try { 139 // Try lsb_release (only available on LSB-compliant Linux systems, see https://www.linuxbase.org/lsb-cert/productdir.php?by_prod ) 140 Process p = Runtime.getRuntime().exec("lsb_release -ds"); 141 BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())); 142 String line = Utils.strip(input.readLine()); 143 Utils.close(input); 144 if (line != null && !line.isEmpty()) { 145 line = line.replaceAll("\"+",""); 146 line = line.replaceAll("NAME=",""); // strange code for some Gentoo's 147 if(line.startsWith("Linux ")) // e.g. Linux Mint 148 return line; 149 else if(!line.isEmpty()) 150 return "Linux " + line; 151 } 152 } catch (IOException e) { 153 // Non LSB-compliant Linux system. List of common fallback release files: http://linuxmafia.com/faq/Admin/release-files.html 154 for (LinuxReleaseInfo info : new LinuxReleaseInfo[]{ 155 new LinuxReleaseInfo("/etc/lsb-release", "DISTRIB_DESCRIPTION", "DISTRIB_ID", "DISTRIB_RELEASE"), 156 new LinuxReleaseInfo("/etc/os-release", "PRETTY_NAME", "NAME", "VERSION"), 157 new LinuxReleaseInfo("/etc/arch-release"), 158 new LinuxReleaseInfo("/etc/debian_version", "Debian GNU/Linux "), 159 new LinuxReleaseInfo("/etc/fedora-release"), 160 new LinuxReleaseInfo("/etc/gentoo-release"), 161 new LinuxReleaseInfo("/etc/redhat-release") 162 }) { 163 String description = info.extractDescription(); 164 if (description != null && !description.isEmpty()) { 165 return "Linux " + description; 166 } 167 } 168 } 169 } 170 return osName; 171 } 172 173 @Override 174 public String getOSDescription() { 175 if (osDescription == null) { 176 osDescription = buildOSDescription(); 177 } 178 return osDescription; 179 } 180 181 protected static class LinuxReleaseInfo { 182 private final String path; 183 private final String descriptionField; 184 private final String idField; 185 private final String releaseField; 186 private final boolean plainText; 187 private final String prefix; 188 189 public LinuxReleaseInfo(String path, String descriptionField, String idField, String releaseField) { 190 this(path, descriptionField, idField, releaseField, false, null); 191 } 192 193 public LinuxReleaseInfo(String path) { 194 this(path, null, null, null, true, null); 195 } 196 197 public LinuxReleaseInfo(String path, String prefix) { 198 this(path, null, null, null, true, prefix); 199 } 200 201 private LinuxReleaseInfo(String path, String descriptionField, String idField, String releaseField, boolean plainText, String prefix) { 202 this.path = path; 203 this.descriptionField = descriptionField; 204 this.idField = idField; 205 this.releaseField = releaseField; 206 this.plainText = plainText; 207 this.prefix = prefix; 208 } 209 210 @Override public String toString() { 211 return "ReleaseInfo [path=" + path + ", descriptionField=" + descriptionField + 212 ", idField=" + idField + ", releaseField=" + releaseField + "]"; 213 } 214 215 /** 216 * Extracts OS detailed information from a Linux release file (/etc/xxx-release) 217 * @return The OS detailed information, or {@code null} 218 */ 219 public String extractDescription() { 220 String result = null; 221 if (path != null) { 222 File file = new File(path); 223 if (file.exists()) { 224 BufferedReader reader = null; 225 try { 226 reader = new BufferedReader(new FileReader(file)); 227 String id = null; 228 String release = null; 229 String line; 230 while (result == null && (line = reader.readLine()) != null) { 231 if (line.contains("=")) { 232 String[] tokens = line.split("="); 233 if (tokens.length >= 2) { 234 // Description, if available, contains exactly what we need 235 if (descriptionField != null && descriptionField.equalsIgnoreCase(tokens[0])) { 236 result = Utils.strip(tokens[1]); 237 } else if (idField != null && idField.equalsIgnoreCase(tokens[0])) { 238 id = Utils.strip(tokens[1]); 239 } else if (releaseField != null && releaseField.equalsIgnoreCase(tokens[0])) { 240 release = Utils.strip(tokens[1]); 241 } 242 } 243 } else if (plainText && !line.isEmpty()) { 244 // Files composed of a single line 245 result = Utils.strip(line); 246 } 247 } 248 // If no description has been found, try to rebuild it with "id" + "release" (i.e. "name" + "version") 249 if (result == null && id != null && release != null) { 250 result = id + " " + release; 251 } 252 } catch (IOException e) { 253 // Ignore 254 } finally { 255 Utils.close(reader); 256 } 257 } 258 } 259 // Append prefix if any 260 if (result != null && !result.isEmpty() && prefix != null && !prefix.isEmpty()) { 261 result = prefix + result; 262 } 263 if(result != null) 264 result = result.replaceAll("\"+",""); 265 return result; 266 } 267 } 268 269 protected void askUpdateJava(String version) { 270 try { 271 ExtendedDialog ed = new ExtendedDialog( 272 Main.parent, 273 tr("Outdated Java version"), 274 new String[]{tr("Update Java"), tr("Cancel")}); 275 // Check if the dialog has not already been permanently hidden by user 276 if (!ed.toggleEnable("askUpdateJava7").toggleCheckState()) { 277 ed.setButtonIcons(new String[]{"java.png", "cancel.png"}).setCancelButton(2); 278 ed.setMinimumSize(new Dimension(460, 260)); 279 ed.setIcon(JOptionPane.WARNING_MESSAGE); 280 ed.setContent(tr("You are running version {0} of Java.", "<b>"+version+"</b>")+"<br><br>"+ 281 "<b>"+tr("This version is no longer supported by {0} since {1} and is not recommended for use.", "Oracle", tr("February 2013"))+"</b><br><br>"+ 282 "<b>"+tr("JOSM will soon stop working with this version; we highly recommend you to update to Java {0}.", "7")+"</b><br><br>"+ 283 tr("Would you like to update now ?")); 284 285 if (ed.showDialog().getValue() == 1) { 286 openUrl("http://www.java.com/download"); 287 } 288 } 289 } catch (IOException e) { 290 Main.warn(e); 291 } 292 } 293}