View Javadoc

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  		// no public ctor
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  		// 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 	 */
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 	 */
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 }