1 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 ; 60 import java.io.IOException ; 61 import java.net.ServerSocket ; 62 import java.util.HashSet ; 63 import java.util.List ; 64 import java.util.Set ; 65 66 public class DBLocal implements Runnable , XJDialogProgressDelegate, StreamWatcherDelegate { 67 68 public static final String remoteParserClassName = "__Test__"; 69 public static final String parserGlueCodeTemplatePath = "org/antlr/works/debugger/local/"; 70 public static final String parserGlueCodeTemplateName = "DBParserGlueCode"; 71 72 public static final String ST_ATTR_IMPORT = "import"; 73 public static final String ST_ATTR_CLASSNAME = "class_name"; 74 public static final String ST_ATTR_INPUT_FILE = "input_file"; 75 public static final String ST_ATTR_JAVA_PARSER = "java_parser"; 76 public static final String ST_ATTR_JAVA_LEXER = "java_parser_lexer"; 77 public static final String ST_ATTR_START_SYMBOL = "start_symbol"; 78 public static final String ST_ATTR_DEBUG_PORT = "port"; 79 80 protected String outputFileDir; 81 82 protected List <String > grammarGeneratedFiles; 83 protected String fileRemoteParser; 84 protected String fileRemoteParserInputTextFile; 85 86 protected String startRule; 87 protected String lastStartRule; 88 89 protected Process 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 inputFile; 100 protected String lastInputFile; 101 protected String inputText; 102 protected String 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 path) { 116 codeGenerator.setOutputPath(path); 117 } 118 119 public void setStartRule(String rule) { 120 this.startRule = rule; 121 } 122 123 public String 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 (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 SwingUtilities.invokeLater(new Runnable () { 194 public void run() { 195 startThread(); 196 } 197 }); 198 } 199 200 public void startThread() { 201 new Thread (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 () { 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 e) { 243 debugger.getConsole().print(e); 244 } 245 } 246 247 protected void reportError(String 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 () { 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 () { 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 (outputFileDir).mkdirs(); 303 } catch(Exception e) { 304 debugger.getConsole().print(e); 305 String msg = ErrorListener.shared().getFirstErrorMessage(); 306 StringBuffer sb = new StringBuffer ("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 errorMessage = null; 340 try { 341 debugger.getGrammar().analyze(); 342 } catch (Exception 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 errorMessage = null; 353 try { 354 if(!codeGenerator.generate()) 355 errorMessage = codeGenerator.getLastError(); 356 } catch (Exception e) { 357 debugger.getConsole().print(e); 358 errorMessage = e.toString(); 359 } catch (OutOfMemoryError 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 (outputFileDir).mkdirs(); 372 compileFiles(grammarGeneratedFiles.toArray(new String [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 e) { 413 debugger.getConsole().print(e); 414 reportError("Error while generating the glue-code:\n"+e.toString()); 415 } 416 } 417 418 421 private String getCustomImports() { 422 List <ElementBlock> blocks = debugger.getBlocks(); 423 if(blocks == null || blocks.isEmpty()) { 424 return ""; 425 } 426 427 Set <String > imports = new HashSet <String >(); 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 <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 sb = new StringBuffer (); 439 j++; 440 while (j < tokens.size()) { 441 ATEToken t = tokens.get(j); 442 String 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 importLines = new StringBuffer (); 458 for (String 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 [] { fileRemoteParser }); 468 } 469 470 protected void compileFiles(String [] files) { 471 String 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 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 (fileRemoteParser).exists()) return false; 489 490 if(inputMode == 0 && !new File (fileRemoteParserInputTextFile).exists()) return false; 491 if(inputMode == 1 && !new File (inputFile).exists()) return false; 492 493 for(String file : grammarGeneratedFiles) { 494 if(!new File (file).exists()) return false; 495 } 496 497 return true; 498 } 499 500 public boolean checkForLaunch() { 501 boolean success = true; 502 try { 503 ServerSocket serverSocket = new ServerSocket (AWPrefs.getDebugDefaultLocalPort()); 504 serverSocket.close(); 505 } catch (IOException 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 classPath = EngineRuntime.getClassPath(outputFileDir); 517 IDE.debugVerbose(debugger.getConsole(), getClass(), "Launch with path: "+classPath); 518 519 try { 520 remoteParserProcess = Runtime.getRuntime().exec(new String [] { "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 e) { 524 reportError("Cannot launch the remote parser:\n"+e.toString()); 525 return false; 526 } 527 528 try { 532 Thread.sleep(1000); 533 } catch (InterruptedException e) { 534 } 536 537 return true; 538 } 539 540 public void streamWatcherDidStarted() { 541 } 542 543 public void streamWatcherDidReceiveString(String string) { 544 debugger.getConsole().print(string, Console.LEVEL_NORMAL); 545 } 546 547 public void streamWatcherException(Exception e) { 548 debugger.getConsole().print(e); 549 } 550 551 protected static class ErrorReporter { 552 553 public String title; 554 public String message; 555 public boolean hasErrors; 556 557 public void setTitle(String title) { 558 this.title = title; 559 } 560 561 public void setMessage(String 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 |