KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > antlr > works > debugger > local > DBLocal


1 /*
2
3 [The "BSD licence"]
4 Copyright (c) 2005 Jean Bovet
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. The name of the author may not be used to endorse or promote products
17 derived from this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 */

31
32 package org.antlr.works.debugger.local;
33
34 import org.antlr.stringtemplate.StringTemplate;
35 import org.antlr.stringtemplate.StringTemplateGroup;
36 import org.antlr.stringtemplate.language.DefaultTemplateLexer;
37 import org.antlr.works.IDE;
38 import org.antlr.works.ate.syntax.generic.ATESyntaxLexer;
39 import org.antlr.works.ate.syntax.misc.ATEToken;
40 import org.antlr.works.debugger.Debugger;
41 import org.antlr.works.debugger.DebuggerInputDialog;
42 import org.antlr.works.engine.EngineRuntime;
43 import org.antlr.works.generate.CodeGenerate;
44 import org.antlr.works.prefs.AWPrefs;
45 import org.antlr.works.syntax.GrammarSyntaxParser;
46 import org.antlr.works.syntax.element.ElementBlock;
47 import org.antlr.works.syntax.element.ElementGrammarName;
48 import org.antlr.works.utils.Console;
49 import org.antlr.works.utils.ErrorListener;
50 import org.antlr.works.utils.StreamWatcher;
51 import org.antlr.works.utils.StreamWatcherDelegate;
52 import org.antlr.xjlib.appkit.frame.XJDialog;
53 import org.antlr.xjlib.appkit.utils.XJAlert;
54 import org.antlr.xjlib.appkit.utils.XJDialogProgress;
55 import org.antlr.xjlib.appkit.utils.XJDialogProgressDelegate;
56 import org.antlr.xjlib.foundation.XJUtils;
57
58 import javax.swing.*;
59 import java.io.File JavaDoc;
60 import java.io.IOException JavaDoc;
61 import java.net.ServerSocket JavaDoc;
62 import java.util.HashSet JavaDoc;
63 import java.util.List JavaDoc;
64 import java.util.Set JavaDoc;
65
66 public class DBLocal implements Runnable JavaDoc, XJDialogProgressDelegate, StreamWatcherDelegate {
67
68     public static final String JavaDoc remoteParserClassName = "__Test__";
69     public static final String JavaDoc parserGlueCodeTemplatePath = "org/antlr/works/debugger/local/";
70     public static final String JavaDoc parserGlueCodeTemplateName = "DBParserGlueCode";
71
72     public static final String JavaDoc ST_ATTR_IMPORT = "import";
73     public static final String JavaDoc ST_ATTR_CLASSNAME = "class_name";
74     public static final String JavaDoc ST_ATTR_INPUT_FILE = "input_file";
75     public static final String JavaDoc ST_ATTR_JAVA_PARSER = "java_parser";
76     public static final String JavaDoc ST_ATTR_JAVA_LEXER = "java_parser_lexer";
77     public static final String JavaDoc ST_ATTR_START_SYMBOL = "start_symbol";
78     public static final String JavaDoc ST_ATTR_DEBUG_PORT = "port";
79
80     protected String JavaDoc outputFileDir;
81
82     protected List JavaDoc<String JavaDoc> grammarGeneratedFiles;
83     protected String JavaDoc fileRemoteParser;
84     protected String JavaDoc fileRemoteParserInputTextFile;
85
86     protected String JavaDoc startRule;
87     protected String JavaDoc lastStartRule;
88
89     protected Process JavaDoc remoteParserProcess;
90
91     protected boolean cancelled;
92     protected int options;
93
94     protected CodeGenerate codeGenerator;
95     protected Debugger debugger;
96
97     protected int inputMode;
98     protected int lastInputMode;
99     protected String JavaDoc inputFile;
100     protected String JavaDoc lastInputFile;
101     protected String JavaDoc inputText;
102     protected String JavaDoc rawInputText;
103
104     protected XJDialogProgress progress;
105     protected ErrorReporter error = new ErrorReporter();
106
107     protected int debugPort = -1;
108     protected boolean debugPortChanged = true;
109
110     public DBLocal(Debugger debugger) {
111         this.debugger = debugger;
112         this.codeGenerator = new CodeGenerate(debugger.getProvider(), null);
113     }
114
115     public void setOutputPath(String JavaDoc path) {
116         codeGenerator.setOutputPath(path);
117     }
118
119     public void setStartRule(String JavaDoc rule) {
120         this.startRule = rule;
121     }
122
123     public String JavaDoc getStartRule() {
124         return startRule;
125     }
126
127     public boolean canDebugAgain() {
128         if(inputMode == 0) {
129             return inputText != null;
130         } else {
131             return inputFile != null && new File JavaDoc(inputFile).exists();
132         }
133     }
134
135     public void dialogDidCancel() {
136         cancel();
137     }
138
139     public void forceStop() {
140         if(remoteParserProcess != null)
141             remoteParserProcess.destroy();
142     }
143
144     public synchronized void cancel() {
145         cancelled = true;
146     }
147
148     public synchronized boolean cancelled() {
149         return cancelled;
150     }
151
152     public void showProgress() {
153         if(progress == null)
154             progress = new XJDialogProgress(debugger.getWindowComponent());
155         progress.setInfo("Preparing...");
156         progress.setIndeterminate(false);
157         progress.setProgress(0);
158         progress.setProgressMax(3);
159         progress.setDelegate(this);
160         progress.display();
161     }
162
163     public void hideProgress() {
164         if(progress != null)
165             progress.close();
166     }
167
168     private boolean optionBuild() {
169         return (options & Debugger.OPTION_BUILD) > 0 || debugPortChanged;
170     }
171
172     private boolean optionAgain() {
173         return (options & Debugger.OPTION_AGAIN) > 0;
174     }
175
176     public void prepareAndLaunch(int options) {
177         this.options = options;
178         cancelled = false;
179
180         if(debugPort != AWPrefs.getDebugDefaultLocalPort()) {
181             debugPort = AWPrefs.getDebugDefaultLocalPort();
182             debugPortChanged = true;
183         } else {
184             debugPortChanged = false;
185         }
186
187         if(optionBuild()) {
188             showProgress();
189         }
190
191         // Start the thread a little bit later to let
192
// the progress dialog displays first
193
SwingUtilities.invokeLater(new Runnable JavaDoc() {
194             public void run() {
195                 startThread();
196             }
197         });
198     }
199
200     public void startThread() {
201         new Thread JavaDoc(this).start();
202     }
203
204     public void run() {
205         resetErrors();
206
207         if(prepare()) {
208             if(optionBuild()) generateAndCompileGrammar();
209             if(!cancelled() && !optionAgain()) askUserForInputText();
210             if(!cancelled()) generateAndCompileGlueCode(optionBuild());
211             if(!cancelled()) generateInputText();
212             if(!cancelled()) launchRemoteParser();
213         }
214
215         if(hasErrors())
216             notifyErrors();
217         else if(cancelled())
218             notifyCancellation();
219         else
220             notifyCompletion();
221     }
222
223     protected void askUserForInputText() {
224         try {
225             SwingUtilities.invokeAndWait(new Runnable JavaDoc() {
226                 public void run() {
227                     hideProgress();
228
229                     DebuggerInputDialog dialog = new DebuggerInputDialog(debugger, debugger.getWindowComponent());
230                     dialog.setInputText(rawInputText);
231                     if(dialog.runModal() == XJDialog.BUTTON_OK) {
232                         rawInputText = dialog.getRawInputText();
233                         inputText = dialog.getInputText();
234                         inputFile = dialog.getInputFile();
235                         inputMode = dialog.getInputMode();
236                         setStartRule(dialog.getRule());
237                         showProgress();
238                     } else
239                         cancel();
240                 }
241             });
242         } catch (Exception JavaDoc e) {
243             debugger.getConsole().print(e);
244         }
245     }
246
247     protected void reportError(String JavaDoc message) {
248         error.setTitle("Error");
249         error.setMessage(message);
250         error.enable();
251         cancel();
252     }
253
254     protected void resetErrors() {
255         error.reset();
256     }
257
258     protected boolean hasErrors() {
259         return error.hasErrors;
260     }
261
262     protected void notifyErrors() {
263         hideProgress();
264
265         SwingUtilities.invokeLater(new Runnable JavaDoc() {
266             public void run() {
267                 if(XJAlert.displayAlert(debugger.getWindowComponent(), error.title, error.message, "Show Console", "OK", 1) == 0) {
268                     debugger.selectConsoleTab();
269                 }
270             }
271         });
272     }
273
274     protected void notifyCancellation() {
275         hideProgress();
276     }
277
278     protected void notifyCompletion() {
279         hideProgress();
280
281         SwingUtilities.invokeLater(new Runnable JavaDoc() {
282             public void run() {
283                 if(!cancelled())
284                     debugger.debuggerLocalDidRun(optionBuild());
285             }
286         });
287     }
288
289     protected boolean prepare() {
290         try {
291             ErrorListener.shared().clear();
292
293             setOutputPath(AWPrefs.getOutputPath());
294             setStartRule(AWPrefs.getStartSymbol());
295
296             grammarGeneratedFiles = codeGenerator.getGeneratedTextFileNames();
297
298             fileRemoteParser = XJUtils.concatPath(codeGenerator.getOutputPath(), remoteParserClassName+".java");
299             fileRemoteParserInputTextFile = XJUtils.concatPath(codeGenerator.getOutputPath(), remoteParserClassName+"_input.txt");
300
301             outputFileDir = XJUtils.concatPath(codeGenerator.getOutputPath(), "classes");
302             new File JavaDoc(outputFileDir).mkdirs();
303         } catch(Exception JavaDoc e) {
304             debugger.getConsole().print(e);
305             String JavaDoc msg = ErrorListener.shared().getFirstErrorMessage();
306             StringBuffer JavaDoc sb = new StringBuffer JavaDoc("Error while preparing the grammar:\n");
307             if(msg != null) {
308                 sb.append(msg);
309                 sb.append("\n");
310             }
311             sb.append(e.toString());
312             reportError(sb.toString());
313             return false;
314         }
315         return true;
316     }
317
318     protected void generateAndCompileGrammar() {
319         progress.setInfo("Analyzing...");
320         progress.setProgress(1);
321         analyzeGrammar();
322
323         if(cancelled())
324             return;
325
326         progress.setInfo("Generating...");
327         progress.setProgress(2);
328         generateGrammar();
329
330         if(cancelled())
331             return;
332
333         progress.setInfo("Compiling...");
334         progress.setProgress(3);
335         compileGrammar();
336     }
337
338     protected void analyzeGrammar() {
339         String JavaDoc errorMessage = null;
340         try {
341             debugger.getGrammar().analyze();
342         } catch (Exception JavaDoc e) {
343             debugger.getConsole().print(e);
344             errorMessage = e.getLocalizedMessage();
345         }
346         if(errorMessage != null) {
347             reportError("Error while analyzing the grammar:\n"+errorMessage);
348         }
349     }
350
351     protected void generateGrammar() {
352         String JavaDoc errorMessage = null;
353         try {
354             if(!codeGenerator.generate())
355                 errorMessage = codeGenerator.getLastError();
356         } catch (Exception JavaDoc e) {
357             debugger.getConsole().print(e);
358             errorMessage = e.toString();
359         } catch (OutOfMemoryError JavaDoc e) {
360             debugger.getConsole().print(e);
361             errorMessage = e.toString();
362         }
363
364         if(errorMessage != null) {
365             reportError("Error while generating the grammar:\n"+errorMessage);
366         }
367     }
368
369     protected void compileGrammar() {
370         XJUtils.deleteDirectory(outputFileDir);
371         new File JavaDoc(outputFileDir).mkdirs();
372         compileFiles(grammarGeneratedFiles.toArray(new String JavaDoc[grammarGeneratedFiles.size()]));
373     }
374
375     protected void generateAndCompileGlueCode(boolean build) {
376         progress.setInfo("Preparing...");
377         progress.setIndeterminate(true);
378
379         if(!build && lastStartRule != null && startRule.equals(lastStartRule) &&
380                 inputFile.equals(lastInputFile) && lastInputMode == inputMode)
381             return;
382
383         lastStartRule = startRule;
384         lastInputMode = inputMode;
385         lastInputFile = inputFile;
386
387         generateGlueCode();
388
389         if(cancelled())
390             return;
391
392         compileGlueCode();
393     }
394
395     protected void generateGlueCode() {
396         try {
397             StringTemplateGroup group = new StringTemplateGroup("DebuggerLocalGroup", DefaultTemplateLexer.class);
398             StringTemplate glueCode = group.getInstanceOf(parserGlueCodeTemplatePath +parserGlueCodeTemplateName);
399             glueCode.setAttribute(ST_ATTR_IMPORT, getCustomImports());
400             glueCode.setAttribute(ST_ATTR_CLASSNAME, remoteParserClassName);
401             if(inputMode == 0) {
402                 glueCode.setAttribute(ST_ATTR_INPUT_FILE, XJUtils.escapeString(fileRemoteParserInputTextFile));
403             } else {
404                 glueCode.setAttribute(ST_ATTR_INPUT_FILE, XJUtils.escapeString(inputFile));
405             }
406             glueCode.setAttribute(ST_ATTR_JAVA_PARSER, codeGenerator.getGeneratedClassName(ElementGrammarName.PARSER));
407             glueCode.setAttribute(ST_ATTR_JAVA_LEXER, codeGenerator.getGeneratedClassName(ElementGrammarName.LEXER));
408             glueCode.setAttribute(ST_ATTR_START_SYMBOL, startRule);
409             glueCode.setAttribute(ST_ATTR_DEBUG_PORT, AWPrefs.getDebugDefaultLocalPort());
410
411             XJUtils.writeStringToFile(glueCode.toString(), fileRemoteParser);
412         } catch(Exception JavaDoc e) {
413             debugger.getConsole().print(e);
414             reportError("Error while generating the glue-code:\n"+e.toString());
415         }
416     }
417
418     /**
419      * Returns a string of import statement based on the package declaration inside any @header block
420      */

421     private String JavaDoc getCustomImports() {
422         List JavaDoc<ElementBlock> blocks = debugger.getBlocks();
423         if(blocks == null || blocks.isEmpty()) {
424             return "";
425         }
426
427         Set JavaDoc<String JavaDoc> imports = new HashSet JavaDoc<String JavaDoc>();
428         for (ElementBlock block : blocks) {
429             if (!block.name.equals(GrammarSyntaxParser.PARSER_HEADER_BLOCK_NAME) && !block.name.equals(GrammarSyntaxParser.LEXER_HEADER_BLOCK_NAME))
430             {
431                 continue;
432             }
433
434             List JavaDoc<ATEToken> tokens = block.internalTokens;
435             for(int j = 0; j < tokens.size(); j++) {
436                 ATEToken token = tokens.get(j);
437                 if (token.type == ATESyntaxLexer.TOKEN_ID && token.getAttribute().equals("package")) {
438                     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
439                     j++;
440                     while (j < tokens.size()) {
441                         ATEToken t = tokens.get(j);
442                         String JavaDoc at = t.getAttribute();
443                         if (at.equals(";"))
444                             break;
445                         sb.append(at);
446                         j++;
447                     }
448                     imports.add(sb.toString());
449                 }
450             }
451         }
452
453         if(imports.isEmpty()) {
454             return "";
455         }
456
457         StringBuffer JavaDoc importLines = new StringBuffer JavaDoc();
458         for (String JavaDoc importName : imports) {
459             importLines.append("import ");
460             importLines.append(importName);
461             importLines.append(".*;\n");
462         }
463         return importLines.toString();
464     }
465
466     protected void compileGlueCode() {
467         compileFiles(new String JavaDoc[] { fileRemoteParser });
468     }
469
470     protected void compileFiles(String JavaDoc[] files) {
471         String JavaDoc error = EngineRuntime.compileFiles(debugger.getConsole(), files, outputFileDir, this);
472         if(error != null)
473             reportError(error);
474     }
475
476     protected void generateInputText() {
477         try {
478             XJUtils.writeStringToFile(inputText, fileRemoteParserInputTextFile);
479         } catch (IOException JavaDoc e) {
480             debugger.getConsole().print(e);
481             reportError("Error while generating the input text:\n"+e.toString());
482         }
483     }
484
485     public boolean isRequiredFilesExisting() {
486         if(!prepare()) return false;
487
488         if(!new File JavaDoc(fileRemoteParser).exists()) return false;
489
490         if(inputMode == 0 && !new File JavaDoc(fileRemoteParserInputTextFile).exists()) return false;
491         if(inputMode == 1 && !new File JavaDoc(inputFile).exists()) return false;
492
493         for(String JavaDoc file : grammarGeneratedFiles) {
494             if(!new File JavaDoc(file).exists()) return false;
495         }
496
497         return true;
498     }
499
500     public boolean checkForLaunch() {
501         boolean success = true;
502         try {
503             ServerSocket JavaDoc serverSocket = new ServerSocket JavaDoc(AWPrefs.getDebugDefaultLocalPort());
504             serverSocket.close();
505         } catch (IOException JavaDoc e) {
506             reportError("Cannot launch the remote parser because port "+AWPrefs.getDebugDefaultLocalPort()+" is already in use.");
507             success = false;
508         }
509         return success;
510     }
511
512     public boolean launchRemoteParser() {
513         if(!checkForLaunch())
514             return false;
515
516         String JavaDoc classPath = EngineRuntime.getClassPath(outputFileDir);
517         IDE.debugVerbose(debugger.getConsole(), getClass(), "Launch with path: "+classPath);
518
519         try {
520             remoteParserProcess = Runtime.getRuntime().exec(new String JavaDoc[] { "java", "-classpath", classPath, remoteParserClassName});
521             new StreamWatcher(remoteParserProcess.getErrorStream(), "Launcher", debugger.getOutputPanel()).start();
522             new StreamWatcher(remoteParserProcess.getInputStream(), "Launcher", debugger.getOutputPanel()).start();
523         } catch (IOException JavaDoc e) {
524             reportError("Cannot launch the remote parser:\n"+e.toString());
525             return false;
526         }
527
528         // Wait 1 second at least to let the process get started.
529
// The Debugger class will then try several times to connect
530
// to the remote parser
531
try {
532             Thread.sleep(1000);
533         } catch (InterruptedException JavaDoc e) {
534             // We don't care here if the sleep has been interrupted
535
}
536
537         return true;
538     }
539
540     public void streamWatcherDidStarted() {
541     }
542
543     public void streamWatcherDidReceiveString(String JavaDoc string) {
544         debugger.getConsole().print(string, Console.LEVEL_NORMAL);
545     }
546
547     public void streamWatcherException(Exception JavaDoc e) {
548         debugger.getConsole().print(e);
549     }
550
551     protected static class ErrorReporter {
552
553         public String JavaDoc title;
554         public String JavaDoc message;
555         public boolean hasErrors;
556
557         public void setTitle(String JavaDoc title) {
558             this.title = title;
559         }
560
561         public void setMessage(String JavaDoc message) {
562             this.message = message;
563         }
564
565         public void enable() {
566             hasErrors = true;
567         }
568
569         public void reset() {
570             hasErrors = false;
571         }
572     }
573
574
575 }
576
Popular Tags