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
37 private EnvReport() {
38
39 }
40
41 public static void main(final String[] args) {
42 System.out.println(getEnvReport());
43 }
44
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 */
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
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
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 */
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
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
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 */
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 }