001package jmri.jmrit.mailreport; 002 003import java.awt.*; 004import java.io.File; 005import java.net.InetAddress; 006import java.net.NetworkInterface; 007import java.net.SocketException; 008import java.util.Collection; 009import java.util.Enumeration; 010 011import javax.swing.JFrame; 012 013import jmri.util.gui.GuiLafPreferencesManager; 014import jmri.InstanceManager; 015import jmri.jmrix.ConnectionConfig; 016import jmri.jmrix.ConnectionConfigManager; 017import jmri.profile.Profile; 018import jmri.profile.ProfileManager; 019import jmri.util.FileUtil; 020import jmri.util.JmriInsets; 021import jmri.util.JmriJFrame; 022import jmri.util.PortNameMapper; 023import jmri.util.PortNameMapper.SerialPortFriendlyName; 024import jmri.util.zeroconf.ZeroConfService; 025import jmri.util.zeroconf.ZeroConfServiceManager; 026 027/** 028 * Provide the JMRI context info. 029 * 030 * @author Bob Jacobsen Copyright (C) 2007, 2009 031 * @author Matt Harris Copyright (C) 2008, 2009 032 */ 033public class ReportContext { 034 035 String report = ""; 036 037 /** 038 * Provide a report of the current JMRI context 039 * 040 * @param reportNetworkInfo true if network connection and zeroconf service 041 * information to be included 042 * @return current JMRI context 043 */ 044 public String getReport(boolean reportNetworkInfo) { 045 046 addString("JMRI Version: " + jmri.Version.name() + " "); 047 048 addEarlyInitializationPreferences(); 049 050 addString("JMRI configuration file name: " 051 + System.getProperty("org.jmri.apps.Apps.configFilename") + " (from org.jmri.apps.Apps.configFilename system property)"); 052 if (!jmri.util.JmriJFrame.getFrameList().isEmpty() && jmri.util.JmriJFrame.getFrameList().get(0) != null) { 053 addString("JMRI main window name: " 054 + jmri.util.JmriJFrame.getFrameList().get(0).getTitle() + " "); 055 } else { 056 addString("No main window present"); 057 } 058 059 addString("JMRI Application: " + jmri.Application.getApplicationName() + " "); 060 ConnectionConfigManager cm = InstanceManager.getNullableDefault(ConnectionConfigManager.class); 061 if (cm != null) { 062 ConnectionConfig[] connList = cm.getConnections(); 063 for (int x = 0; x < connList.length; x++) { 064 ConnectionConfig conn = connList[x]; 065 addString("Connection " + x + ": " + conn.getManufacturer() + " connected via " + conn.name() + " on " + conn.getInfo() + " Disabled " + conn.getDisabled() + " "); 066 } 067 } else { 068 addString("No connections present"); 069 } 070 071 addString("Available Communication Ports:"); 072 addCommunicationPortInfo(); 073 074 Profile profile = ProfileManager.getDefault().getActiveProfile(); 075 if (profile != null) { 076 addString("Active profile: " + profile.getName() + " "); 077 addString("Profile location: " + profile.getPath().getPath() + " "); 078 addString("Profile ID: " + profile.getId() + " "); 079 } else { 080 addString("No active profile"); 081 } 082 083 addString("JMRI Network ID: " + jmri.util.node.NodeIdentity.networkIdentity()); 084 addString("JMRI Storage ID: " + jmri.util.node.NodeIdentity.storageIdentity(profile)); 085 086 String prefs = FileUtil.getUserFilesPath(); 087 addString("Preferences directory: " + prefs + " "); 088 089 String prog = System.getProperty("user.dir"); 090 addString("Program directory: " + prog + " "); 091 092 String roster = jmri.jmrit.roster.Roster.getDefault().getRosterIndexPath(); 093 addString("Roster index location: " + roster + " "); 094 095 File panel = jmri.configurexml.LoadXmlUserAction.getCurrentFile(); 096 addString("Current panel file: " + (panel == null ? "[none]" : panel.getPath()) + " "); 097 098 addString("Locale: " + InstanceManager.getDefault(GuiLafPreferencesManager.class).getLocale()); 099 100 //String operations = jmri.jmrit.operations.setup.OperationsSetupXml.getFileLocation(); 101 //addString("Operations files location: "+operations+" "); 102 jmri.AudioManager am = jmri.InstanceManager.getNullableDefault(jmri.AudioManager.class); 103 jmri.jmrit.audio.AudioFactory af = null; 104 if ( am !=null ) { 105 af = am.getActiveAudioFactory(); 106 } 107 String audio = af != null ? af.toString() : "[not initialised]"; 108 addString("Audio factory type: " + audio + " "); 109 110 addProperty("java.version"); 111 addProperty("java.vendor"); 112 addProperty("java.home"); 113 114 addProperty("java.vm.version"); 115 addProperty("java.vm.vendor"); 116 addProperty("java.vm.name"); 117 118 addProperty("java.specification.version"); 119 addProperty("java.specification.vendor"); 120 addProperty("java.specification.name"); 121 122 addProperty("java.class.version"); 123 addProperty("java.class.path"); 124 addProperty("java.library.path"); 125 126 addProperty("java.compiler"); 127 addProperty("java.ext.dirs"); 128 129 addProperty("file.encoding"); 130 131 addProperty("os.name"); 132 addProperty("os.arch"); 133 addProperty("os.version"); 134 135 addProperty("python.home"); 136 addProperty("python.path"); 137 addProperty("python.cachedir"); 138 addProperty("python.cachedir.skip"); 139 addProperty("python.startup"); 140 141 addProperty("user.name"); 142 addProperty("user.home"); 143 addProperty("user.dir"); 144 addProperty("user.country"); 145 addProperty("user.language"); 146 addProperty("user.timezone"); 147 addProperty("jmri.log.path"); 148 149 addString("FileSystemView#getDefaultDirectory(): "+javax.swing.filechooser.FileSystemView.getFileSystemView().getDefaultDirectory().getPath() ); 150 addString("FileSystemView#getHomeDirectory(): "+javax.swing.filechooser.FileSystemView.getFileSystemView().getHomeDirectory().getPath() ); 151 addString("Default JFileChooser(): "+(new javax.swing.JFileChooser()).getCurrentDirectory().getPath() ); 152 153 addScreenSize(); 154 155 if (reportNetworkInfo) { 156 addNetworkInfo(); 157 } 158 159 return report; 160 161 } 162 163 void addString(String val) { 164 report = report + val + "\n"; 165 } 166 167 void addProperty(String prop) { 168 addString(prop + ": " + System.getProperty(prop) + " "); 169 } 170 171 void addEarlyInitializationPreferences() { 172 jmri.util.EarlyInitializationPreferences eip = 173 jmri.util.EarlyInitializationPreferences.getInstance(); 174 175 for (String pref : eip.getStartupPreferences()) { 176 addString(pref + " "); 177 } 178 } 179 180 /** 181 * Provide screen - size information. This is based on the 182 * jmri.util.JmriJFrame calculation, but isn't refactored to there because 183 * we also want diagnostic info 184 */ 185 public void addScreenSize() { 186 try { 187 // Find screen size. This throws null-pointer exceptions on 188 // some Java installs, however, for unknown reasons, so be 189 // prepared to fall back. 190 JFrame dummy = new JFrame(); 191 try { 192 Insets insets = dummy.getToolkit().getScreenInsets(dummy.getGraphicsConfiguration()); 193 Dimension screen = dummy.getToolkit().getScreenSize(); 194 addString("Screen size h:" + screen.height + ", w:" + screen.width + " Inset t:" + insets.top + ", b:" + insets.bottom 195 + "; l:" + insets.left + ", r:" + insets.right); 196 } catch (NoSuchMethodError ex) { 197 Dimension screen = dummy.getToolkit().getScreenSize(); 198 addString("Screen size h:" + screen.height + ", w:" + screen.width 199 + " (No Inset method available)"); 200 } 201 } catch (HeadlessException ex) { 202 // failed, fall back to standard method 203 addString("(Cannot sense screen size due to " + ex.toString() + ")"); 204 } 205 206 try { 207 // Find screen resolution. Not expected to fail, but just in case.... 208 int dpi = Toolkit.getDefaultToolkit().getScreenResolution(); 209 addString("Screen resolution: " + dpi); 210 } catch (HeadlessException ex) { 211 addString("Screen resolution not available"); 212 } 213 214 // look at context 215 try { 216 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 217 addString("Environment max bounds: " + ge.getMaximumWindowBounds()); 218 219 try { 220 for (JmriJFrame.ScreenDimensions sd: JmriJFrame.getScreenDimensions()) { 221 addString("Device: " + sd.getGraphicsDevice().getIDstring() + " bounds = " + sd.getBounds()); 222 addString("Device: " + sd.getGraphicsDevice().getIDstring() + " insets = " + sd.getInsets()); 223 } 224 } catch (HeadlessException ex) { 225 addString("Exception getting device bounds " + ex.getMessage()); 226 } 227 } catch (HeadlessException ex) { 228 addString("Exception getting max window bounds " + ex.getMessage()); 229 } 230 // Return the insets using a custom class 231 // which should return the correct values under 232 // various Linux window managers 233 try { 234 Insets jmriInsets = JmriInsets.getInsets(); 235 addString("JmriInsets t:" + jmriInsets.top + ", b:" + jmriInsets.bottom 236 + "; l:" + jmriInsets.left + ", r:" + jmriInsets.right); 237 } catch (Exception ex) { 238 addString("Exception getting JmriInsets " + ex.getMessage()); 239 } 240 241 var laf = javax.swing.UIManager.getLookAndFeel(); 242 if ( laf !=null ) { 243 addString("Look and Feel: " + laf.getName()); 244 } else { 245 addString("null LookAndFeel"); 246 } 247 248 } 249 250 /** 251 * Add network connection and running service information 252 */ 253 private void addNetworkInfo() { 254 try { 255 // This code is based on that in jmri.jmrit.withrottle.UserInterface which, 256 // itself, was adapted from http://www.rgagnon.com/javadetails/java-0390.html 257 Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); 258 while (networkInterfaces.hasMoreElements()) { 259 NetworkInterface networkInterface = networkInterfaces.nextElement(); 260 Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses(); 261 while (inetAddresses.hasMoreElements()) { 262 InetAddress inetAddress = inetAddresses.nextElement(); 263 String hostAddress = inetAddress.getHostAddress(); 264 if (!hostAddress.equals("0.0.0.0") && !hostAddress.regionMatches(0, "127", 0, 3) && !hostAddress.contains(":")) { 265 addString("Network Interface: " + networkInterface.getName()); 266 addString(" Long Name: " + networkInterface.getDisplayName()); 267 addString(" Host Name: " + inetAddress.getHostName()); 268 addString(" IP address: " + hostAddress); 269 } 270 } 271 } 272 } catch (SocketException ex) { 273 addString("Unable to enumerate Network Interfaces"); 274 } 275 276 Collection<ZeroConfService> services = InstanceManager.getDefault(ZeroConfServiceManager.class).allServices(); 277 for (InetAddress address : InstanceManager.getDefault(ZeroConfServiceManager.class).getAddresses()) { 278 addString("ZeroConfService host: " + InstanceManager.getDefault(ZeroConfServiceManager.class).hostName(address) + " running " + services.size() + " service(s)"); 279 } 280 if (!services.isEmpty()) { 281 for (ZeroConfService service : services) { 282 addString("ZeroConfService: " + service.getServiceInfo().getQualifiedName() + " "); 283 addString(" Name: " + service.getName() + " "); 284 try { 285 for (String address : service.getServiceInfo().getHostAddresses()) { 286 addString(" Address:" + address + " "); 287 } 288 } catch (NullPointerException ex) { 289 addString(" Address: [unknown due to NPE]"); 290 } 291 addString(" Port: " + service.getServiceInfo().getPort() + " "); 292 addString(" Server: " + service.getServiceInfo().getServer() + " "); 293 addString(" Type: " + service.getType() + " "); 294 try { 295 for (String url : service.getServiceInfo().getURLs()) { 296 addString(" URL: " + url + " "); 297 } 298 } catch (NullPointerException ex) { 299 addString(" URL: [unknown due to NPE]"); 300 } 301 addString(" Published: " + (service.isPublished() ? "yes" : "no")); 302 } 303 } 304 } 305 306 /** 307 * Add communication port information 308 */ 309 private void addCommunicationPortInfo() { 310 var portNames = jmri.jmrix.AbstractSerialPortController.getActualPortNames(); 311 312 addString(String.format(" Found %s serial ports", portNames.size())); 313 314 // now output the details 315 for (String name : portNames) { 316 // output details 317 SerialPortFriendlyName port = PortNameMapper.getPortNameMap().get(name); 318 if (port == null) { 319 port = new SerialPortFriendlyName(name, null); 320 PortNameMapper.getPortNameMap().put(name, port); 321 } 322 addString(" Port: " + name); 323 } 324 } 325 326} 327 328