001: package tide.exttools.checkstyle;
002:
003: import tide.sources.SourceFile;
004: import tide.editor.*;
005: import tide.project.*;
006: import tide.utils.*;
007: import tide.editor.linemessages.*;
008: import snow.utils.gui.*;
009: import snow.utils.storage.*;
010: import snow.utils.*;
011: import javax.swing.*;
012: import javax.swing.event.*;
013: import javax.swing.border.*;
014: import java.awt.event.*;
015: import java.io.*;
016: import java.util.*;
017: import java.util.regex.*;
018: import java.util.jar.*;
019:
020: public final class CheckStyleLauncher // implements ChangedFilesSaveListener
021: {
022: private static CheckStyleLauncher instance = null;
023:
024: private CheckStyleLauncher() {
025: }
026:
027: public static synchronized CheckStyleLauncher getInstance() {
028: if (instance == null)
029: instance = new CheckStyleLauncher();
030: return instance;
031: }
032:
033: /** ChangedFilesSaveListener interface.
034: */
035: public void filesSaved(final Set<SourceFile> sources) {
036: if (!CheckStyleSettingsDialog.isConfigured())
037: return;
038:
039: // Enforce EDT, because we are not necessary beeing called from edt here
040: final ProgressModalDialog[] pmd = new ProgressModalDialog[1];
041: SwingSafeRunnable.invokeAndWait(new Runnable() {
042: public void run() { // MUST WAIT HERE!
043: pmd[0] = new ProgressModalDialog(
044: MainEditorFrame.instance,
045: "Checkstyle autoanalysis (" + sources.size()
046: + " file"
047: + (sources.size() == 1 ? "" : "s")
048: + ")", false);
049: pmd[0].startDelayed(30000L); // big delay, normally never visible...
050: }
051: });
052:
053: Thread t = new Thread() {
054: public void run() {
055: try {
056:
057: _analyse(true, pmd[0], sources
058: .toArray(new SourceFile[sources.size()])); // Silent
059: /*for(SourceFile sf : sources)
060: {
061: if(pmd.getWasCancelled()) break;
062: _analyse(sf, true, pmd); // Silent
063: }*/
064: } catch (Exception ex) {
065: ex.printStackTrace();
066: } finally {
067: pmd[0].closeDialog();
068: }
069: }
070: };
071: t.start();
072: }
073:
074: public static void _analyse(boolean silentMode,
075: ProgressModalDialog pmd, SourceFile... sfs)
076: throws Exception {
077:
078: if (sfs.length == 1) {
079: SourceFile sf = sfs[0];
080: if (sf.isSourceFile()) {
081: LineMessagesManager.getInstance().removeMessagesFor(
082: sf.getJavaName(), CSLineMessage.class);
083: analyse(silentMode, pmd, sf.javaFile);
084: } else if (sf.isDirectory()) {
085: String pn = sf.getPackageName();
086: if (pn.length() > 0)
087: pn += ".";
088: LineMessagesManager.getInstance()
089: .removeMessagesForJavaNameStartingWith(pn,
090: CSLineMessage.class);
091: File d = new File(MainEditorFrame.instance
092: .getActualProject().getSources_Home(), sf
093: .getJavaName().replace(".", "/"));
094: analyse(silentMode, pmd, d);
095: }
096: } else {
097: //List<File> lf = new ArrayList<File>();
098: for (SourceFile sfi : sfs) {
099: LineMessagesManager.getInstance().removeMessagesFor(
100: sfi.getJavaName(), CSLineMessage.class);
101: //lf.add(sfi.javaFile);
102: analyse(silentMode, pmd, sfi.javaFile);
103: }
104: }
105: }
106:
107: /** As argument: either a source or a directory.
108: * must be called in a separate thread
109: */
110: private static void analyse(boolean silentMode,
111: ProgressModalDialog pmd, File sourcesToAnalyse)
112: throws Exception {
113: ProjectSettings actualProject = MainEditorFrame.instance
114: .getActualProject();
115: //LineMessagesManager.getInstance().removeMessages( CSLineMessage.class );
116: boolean ignoreIrrelevant = actualProject.getBooleanProperty(
117: "CheckStyle_ignoreIrrelevant", false);
118:
119: File csJar = new File(actualProject.getProperty(
120: "CheckStyle_path",
121: CheckStyleSettingsDialog.defaultCSLocation));
122: if (!csJar.exists())
123: throw new Exception("CheckStyle jar not found at "
124: + csJar.getAbsolutePath());
125:
126: File javaExePath = actualProject.getJava_TOOL();
127: String options = actualProject.getProperty(
128: "CheckStyle_Options", "-c sun_checks.xml");
129:
130: List<String> execCommand = new ArrayList<String>();
131: execCommand.add(javaExePath.getAbsolutePath());
132: String lang = actualProject.getProperty(
133: "CheckStyle_messagesLanguage", "en");
134: //System.getProperty("user.language","en"));
135: execCommand.add("-Duser.language=" + lang); // 4.2: en,de,fr,es,fi,pt
136: execCommand.add("-cp");
137: // 4.3: missing classes otherwise (bug)
138: execCommand.add(collectPath(csJar.getParentFile()));
139: execCommand.add("-jar");
140: execCommand.add(csJar.getAbsolutePath());
141:
142: // 2: opts
143: if (options != null && options.trim().length() > 0) {
144: // TODO: avoid the -r option !!
145: execCommand.addAll(ProjectUtils.splitArgs(options, false));
146: }
147:
148: // recurse for folders
149: if (sourcesToAnalyse.isDirectory()) {
150: execCommand.add("-r");
151: }
152:
153: // 3: file or dir
154: execCommand.add(sourcesToAnalyse.getAbsolutePath());
155:
156: if (!silentMode) {
157: //SwingSafeRunnable.
158:
159: MainEditorFrame.instance.outputPanels.selectToolsTab(false);
160: MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc
161: .appendLine("CheckStyle analysis of "
162: + sourcesToAnalyse + ":\r\n");
163:
164: pmd.start();
165: }
166:
167: //System.out.println("Running CheckStyle: "+execCommand);
168: ProcessBuilder pb = new ProcessBuilder(execCommand);
169: pb.directory(csJar.getParentFile());
170: Process proc = pb.start();
171:
172: //ProgressModalDialog pmd = new ProgressModalDialog(MainEditorFrame.instance, "CheckStyle analysis", false);
173: pmd.setProcessToOptionalKill(proc);
174: //pmd.start();
175:
176: if (!silentMode) {
177: MainEditorFrame.instance.outputPanels.processesManager
178: .addProcess("CheckStyle analysis of "
179: + sourcesToAnalyse + "", proc, true);
180: }
181:
182: CSStreamGobbler cs = new CSStreamGobbler(
183: proc.getInputStream(),
184: MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc
185: .createWriterForThisDocument(false),
186: ignoreIrrelevant);
187: cs.start();
188:
189: // errors
190: StreamGobbler sge = new StreamGobbler(
191: proc.getErrorStream(),
192: MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc
193: .createWriterForThisDocument(true),
194: "CheckStyle");
195: sge.start();
196:
197: // wait until proc completed...
198: proc.waitFor();
199:
200: // TODO: in a finally block !
201: pmd.closeDialog();
202:
203: cs.join();
204: sge.join();
205:
206: if (!silentMode) {
207: MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc
208: .appendLine("" + cs.wroteLinesCount
209: + " warnings (in the Messages tab)");
210:
211: MainEditorFrame.instance.outputPanels.toolsOutputPanel
212: .setCaret0();
213: }
214:
215: LineMessagesManager.getInstance().refreshView();
216: }
217:
218: /* All but checkstyle itself !
219: */
220: private static String collectPath(File base) {
221: StringBuilder sb = new StringBuilder();
222: String ps = System.getProperty("path.separator");
223:
224: for (File fi : base.listFiles()) {
225: String nl = fi.getName().toLowerCase();
226: if (fi.isDirectory()) {
227: continue;
228: }
229: if (!nl.endsWith(".jar")) {
230: continue;
231: }
232: if (nl.contains("checkstyle")
233: && !nl.contains("checkstyle-optional")) {
234: continue;
235: }
236: sb.append(ps);
237: sb.append(fi.getName());
238: }
239:
240: if (sb.length() == 0)
241: return "";
242:
243: return sb.substring(ps.length());
244: }
245:
246: static final class CSStreamGobbler extends Thread {
247: private final InputStream inputStream;
248: private final Writer writer;
249: public int wroteLinesCount = 0, ignoredLinesCount = 0;
250: final boolean ignoreIrrelevantCat;
251:
252: public CSStreamGobbler(final InputStream inputStream,
253: final Writer w, boolean ignoreIrrelevantCat) {
254: this .inputStream = inputStream;
255: this .writer = w;
256: this .ignoreIrrelevantCat = ignoreIrrelevantCat;
257: }
258:
259: @Override
260: public void run() {
261: try {
262: final InputStreamReader isr = new InputStreamReader(
263: this .inputStream);
264: final BufferedReader br = new BufferedReader(isr);
265:
266: String line = null;
267: wl: while ((line = br.readLine()) != null) {
268:
269: //System.out.println("CSL> "+line);
270: if (line.equals("Starting audit..."))
271: continue; // [Feb2008]
272: if (line.equals("Audit done."))
273: continue;
274:
275: if (!line.contains(".java")) {
276: MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc
277: .appendErrorLine(line);
278: continue;
279: }
280:
281: if (CSLineMessage.createAndAdd(line,
282: ignoreIrrelevantCat)) {
283: wroteLinesCount++;
284: } else {
285: //System.out.println("ignored: "+line);
286: ignoredLinesCount++;
287: }
288:
289: }
290: } catch (IOException ioe) {
291: ioe.printStackTrace();
292: }
293: }
294: }
295:
296: }
|