1 package net.sf.statsvn.util; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.util.Arrays; 7 import java.util.Collections; 8 import java.util.Iterator; 9 import java.util.Properties; 10 import java.util.Vector; 11 12 import net.sf.statcvs.Messages; 13 14 /** 15 * This class provides a report to standard output of relevant JRE properties 16 * and svn executable information. This output is intended to be included with 17 * bug reports to help the StatSVN team diagnose common issues with wrong SVN 18 * version, wrong JRE version, and locale settings. 19 * 20 * @author jpdaigle jpdaigle@softwareengineering.ca 21 * 22 */ 23 public final class EnvReport { 24 private static String[] envPropKeys = { "file.encoding", "java.home", "java.runtime.version", "os.arch", "os.name", "os.version", "user.country", 25 "user.language" }; 26 27 static final String SVN_VERSION_COMMAND = "svn --version"; 28 29 static final String SVN_VERSION_LINE_PATTERN = ".* [0-9]+\\.[0-9]+\\.[0-9]+.*"; 30 31 static final String KEY_SVN_ABLE_TO_RUN = "svn.able.to.run"; 32 33 static final String KEY_SVN_VERSION = "svn.reportedversion"; 34 35 static final String KEY_STATSVN_VERSION = "statsvn.reportedversion"; 36 EnvReport()37 private EnvReport() { 38 // no public ctor 39 } 40 main(final String[] args)41 public static void main(final String[] args) { 42 System.out.println(getEnvReport()); 43 } 44 getEnvReport()45 public static String getEnvReport() { 46 final StringBuffer buf = new StringBuffer(); 47 buf.append("\nWhen reporting a StatSVN bug or requesting assistance,\n"); 48 buf.append("please include the entirety of the output below.\n"); 49 buf.append("No personally-identifiable information is included.\n\n"); 50 51 buf.append("=== Java Runtime Properties ===\n"); 52 buf.append(fmtPropertiesForScreen(System.getProperties(), envPropKeys)); 53 54 buf.append("\n"); 55 buf.append("=== Subversion Properties ===\n"); 56 buf.append(fmtPropertiesForScreen(getSvnVersionInfo(), null)); 57 58 buf.append("\n"); 59 buf.append("=== StatSVN Properties ===\n"); 60 buf.append(fmtPropertiesForScreen(getStatSVNInfo(), null)); 61 62 return buf.toString(); 63 } 64 65 /** 66 * Format a set of key/value Properties for the screen, by right-aligning 67 * the key column. Each key/value pair is printed and followed by a newline. 68 * 69 * @author jpdaigle 70 * @param props 71 * Property set to format for printout. 72 * @param keySet 73 * The keys of interest to use. If null, use all keys defined in 74 * props. 75 * @return Formatted text block with property keys and values, with a 76 * newline after every set. 77 */ fmtPropertiesForScreen(final Properties props, String[] keySet)78 public static String fmtPropertiesForScreen(final Properties props, String[] keySet) { 79 int maxWidth = 0; 80 final StringBuffer buf = new StringBuffer(); 81 if (keySet == null) { 82 keySet = (String[]) props.keySet().toArray(new String[props.keySet().size()]); 83 } 84 final Vector vKeys = new Vector(Arrays.asList(keySet)); 85 Collections.sort(vKeys); 86 87 // First pass: find length of longest key 88 for (final Iterator ite = vKeys.iterator(); ite.hasNext();) { 89 final String key = ((String) ite.next()).trim(); 90 maxWidth = (key.length() > maxWidth) ? key.length() : maxWidth; 91 } 92 93 // Second pass: output formatted keys / values 94 for (final Iterator ite = vKeys.iterator(); ite.hasNext();) { 95 final String key = ((String) ite.next()).trim(); 96 for (int i = maxWidth - key.length(); i > 0; i--) { 97 buf.append(" "); 98 } 99 buf.append(key).append(":[").append(props.getProperty(key).trim()).append("]\n"); 100 } 101 102 return buf.toString(); 103 } 104 105 /** 106 * Get svn executable version info. We cannot use the excellent 107 * "ProcessUtils" because we are not running in the context of a StatSVN 108 * invocation. We use a plain old exec(). 109 * 110 * @return Property set 111 */ getSvnVersionInfo()112 public static Properties getSvnVersionInfo() { 113 114 String versionLine = ""; 115 String line; 116 final Properties svnProps = new Properties(); 117 BufferedReader input = null; 118 119 try { 120 svnProps.setProperty(KEY_SVN_ABLE_TO_RUN, "YES"); 121 final Process proc = Runtime.getRuntime().exec(SVN_VERSION_COMMAND); 122 123 input = new BufferedReader(new InputStreamReader(proc.getInputStream())); 124 while ((line = input.readLine()) != null) { 125 if (line.matches(SVN_VERSION_LINE_PATTERN)) { 126 // We have our version line 127 versionLine = line.trim(); 128 break; 129 } 130 } 131 } catch (final Exception e) { 132 svnProps.setProperty(KEY_SVN_ABLE_TO_RUN, "NO: " + e.getMessage().trim()); 133 } finally { 134 svnProps.setProperty(KEY_SVN_VERSION, versionLine); 135 if (input != null) { 136 try { 137 input.close(); 138 } catch (final IOException ex) { 139 // swallow it 140 ex.printStackTrace(); 141 } 142 } 143 } 144 return svnProps; 145 } 146 147 /** 148 * Get information about the current version of StatSVN. 149 * @return Property set 150 */ getStatSVNInfo()151 public static Properties getStatSVNInfo() { 152 final Properties statsvnProps = new Properties(); 153 statsvnProps.setProperty(KEY_STATSVN_VERSION, Messages.getString("PROJECT_VERSION")); 154 return statsvnProps; 155 } 156 157 } 158