001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions; 003 004import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 005import static org.openstreetmap.josm.tools.I18n.tr; 006 007import java.awt.Dimension; 008import java.awt.event.ActionEvent; 009import java.awt.event.KeyEvent; 010import java.lang.management.ManagementFactory; 011import java.util.ArrayList; 012import java.util.Arrays; 013import java.util.HashSet; 014import java.util.List; 015import java.util.ListIterator; 016import java.util.Map; 017import java.util.Map.Entry; 018import java.util.Set; 019 020import javax.swing.JScrollPane; 021 022import org.openstreetmap.josm.Main; 023import org.openstreetmap.josm.data.Preferences.Setting; 024import org.openstreetmap.josm.data.Version; 025import org.openstreetmap.josm.data.osm.DataSet; 026import org.openstreetmap.josm.data.osm.DatasetConsistencyTest; 027import org.openstreetmap.josm.gui.ExtendedDialog; 028import org.openstreetmap.josm.gui.widgets.JosmTextArea; 029import org.openstreetmap.josm.plugins.PluginHandler; 030import org.openstreetmap.josm.tools.BugReportExceptionHandler; 031import org.openstreetmap.josm.tools.OpenBrowser; 032import org.openstreetmap.josm.tools.PlatformHookUnixoid; 033import org.openstreetmap.josm.tools.PlatformHookWindows; 034import org.openstreetmap.josm.tools.Shortcut; 035import org.openstreetmap.josm.tools.Utils; 036 037/** 038 * @author xeen 039 * 040 * Opens a dialog with useful status information like version numbers for Java, JOSM and plugins 041 * Also includes preferences with stripped username and password 042 */ 043public final class ShowStatusReportAction extends JosmAction { 044 045 /** 046 * Constructs a new {@code ShowStatusReportAction} 047 */ 048 public ShowStatusReportAction() { 049 super( 050 tr("Show Status Report"), 051 "clock", 052 tr("Show status report with useful information that can be attached to bugs"), 053 Shortcut.registerShortcut("help:showstatusreport", tr("Help: {0}", 054 tr("Show Status Report")), KeyEvent.CHAR_UNDEFINED, Shortcut.NONE), false); 055 056 putValue("help", ht("/Action/ShowStatusReport")); 057 putValue("toolbar", "help/showstatusreport"); 058 Main.toolbar.register(this); 059 } 060 061 private static void shortenParam(ListIterator<String> it, String[] param, String source, String target) { 062 if (source != null && target.length() < source.length() && param[1].startsWith(source)) { 063 it.set(param[0] + "=" + param[1].replace(source, target)); 064 } 065 } 066 067 /** 068 * Replies the report header (software and system info) 069 * @return The report header (software and system info) 070 */ 071 public static String getReportHeader() 072 { 073 StringBuilder text = new StringBuilder(); 074 text.append(Version.getInstance().getReleaseAttributes()); 075 text.append("\n"); 076 text.append("Identification: " + Version.getInstance().getAgentString()); 077 text.append("\n"); 078 text.append("Memory Usage: "); 079 text.append(Runtime.getRuntime().totalMemory()/1024/1024); 080 text.append(" MB / "); 081 text.append(Runtime.getRuntime().maxMemory()/1024/1024); 082 text.append(" MB ("); 083 text.append(Runtime.getRuntime().freeMemory()/1024/1024); 084 text.append(" MB allocated, but free)"); 085 text.append("\n"); 086 text.append("Java version: " + System.getProperty("java.version") + ", " + System.getProperty("java.vendor") + ", " + System.getProperty("java.vm.name")); 087 text.append("\n"); 088 if (Main.platform.getClass() == PlatformHookUnixoid.class) { 089 String packageDetails = ((PlatformHookUnixoid) Main.platform).getJavaPackageDetails(); 090 if (packageDetails != null) { 091 text.append("Java package: "); 092 text.append(packageDetails); 093 text.append("\n"); 094 } 095 } 096 try { 097 final String env_java_home = System.getenv("JAVA_HOME"); 098 final String env_java_home_alt = Main.platform instanceof PlatformHookWindows ? "%JAVA_HOME%" : "${JAVA_HOME}"; 099 final String prop_java_home = System.getProperty("java.home"); 100 final String prop_java_home_alt = "<java.home>"; 101 // Build a new list of VM parameters to modify it below if needed (default implementation returns an UnmodifiableList instance) 102 List<String> vmArguments = new ArrayList<String>(ManagementFactory.getRuntimeMXBean().getInputArguments()); 103 for (ListIterator<String> it = vmArguments.listIterator(); it.hasNext(); ) { 104 String value = it.next(); 105 if (value.contains("=")) { 106 String[] param = value.split("="); 107 // Hide some parameters for privacy concerns 108 if (param[0].toLowerCase().startsWith("-dproxy")) { 109 it.set(param[0]+"=xxx"); 110 // Shorten some parameters for readability concerns 111 } else { 112 shortenParam(it, param, env_java_home, env_java_home_alt); 113 shortenParam(it, param, prop_java_home, prop_java_home_alt); 114 } 115 } 116 } 117 if (!vmArguments.isEmpty()) { 118 text.append("VM arguments: "+ vmArguments.toString().replace("\\\\", "\\")); 119 text.append("\n"); 120 } 121 } catch (SecurityException e) { 122 // Ignore exception 123 } 124 if (Main.commandLineArgs.length > 0) { 125 text.append("Program arguments: "+ Arrays.toString(Main.commandLineArgs)); 126 text.append("\n"); 127 } 128 if (Main.main != null) { 129 DataSet dataset = Main.main.getCurrentDataSet(); 130 if (dataset != null) { 131 String result = DatasetConsistencyTest.runTests(dataset); 132 if (result.length() == 0) { 133 text.append("Dataset consistency test: No problems found\n"); 134 } else { 135 text.append("\nDataset consistency test:\n"+result+"\n"); 136 } 137 } 138 } 139 text.append("\n"); 140 text.append(PluginHandler.getBugReportText()); 141 text.append("\n"); 142 143 return text.toString(); 144 } 145 146 @Override 147 public void actionPerformed(ActionEvent e) { 148 StringBuilder text = new StringBuilder(); 149 String reportHeader = getReportHeader(); 150 text.append(reportHeader); 151 try { 152 Map<String, Setting> settings = Main.pref.getAllSettings(); 153 settings.remove("osm-server.username"); 154 settings.remove("osm-server.password"); 155 settings.remove("oauth.access-token.key"); 156 settings.remove("oauth.access-token.secret"); 157 Set<String> keys = new HashSet<String>(settings.keySet()); 158 for (String key : keys) { 159 if (key.startsWith("marker.show")) { 160 settings.remove(key); 161 } 162 } 163 for (Entry<String, Setting> entry : settings.entrySet()) { 164 text.append(entry.getKey()).append("=").append(entry.getValue().getValue().toString()).append("\n"); 165 } 166 } catch (Exception x) { 167 x.printStackTrace(); 168 } 169 170 JosmTextArea ta = new JosmTextArea(text.toString()); 171 ta.setWrapStyleWord(true); 172 ta.setLineWrap(true); 173 ta.setEditable(false); 174 JScrollPane sp = new JScrollPane(ta); 175 176 ExtendedDialog ed = new ExtendedDialog(Main.parent, 177 tr("Status Report"), 178 new String[] {tr("Copy to clipboard and close"), tr("Report bug"), tr("Close") }); 179 ed.setButtonIcons(new String[] {"copy.png", "bug.png", "cancel.png" }); 180 ed.setContent(sp, false); 181 ed.setMinimumSize(new Dimension(380, 200)); 182 ed.setPreferredSize(new Dimension(700, Main.parent.getHeight()-50)); 183 184 switch (ed.showDialog().getValue()) { 185 case 1: Utils.copyToClipboard(text.toString()); break; 186 case 2: OpenBrowser.displayUrl(BugReportExceptionHandler.getBugReportUrl( 187 Utils.strip(reportHeader)).toExternalForm()) ; break; 188 } 189 } 190}