1 17 package org.eclipse.emf.codegen.jet; 18 19 20 import java.io.BufferedInputStream ; 21 import java.io.IOException ; 22 import java.io.InputStream ; 23 import java.io.OutputStream ; 24 import java.io.PrintWriter ; 25 import java.net.MalformedURLException ; 26 import java.net.URL ; 27 import java.util.ArrayList ; 28 import java.util.HashMap ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 import java.util.Map ; 32 import java.util.Stack ; 33 34 import org.eclipse.core.runtime.IPath; 35 import org.eclipse.core.runtime.Path; 36 import org.eclipse.core.runtime.Platform; 37 38 import org.eclipse.emf.codegen.CodeGenPlugin; 39 40 41 public class JETCompiler implements JETParseEventListener 42 { 43 protected final static char[] NULL_CHAR_ARRAY = {}; 44 45 protected String [] templateURIPath; 46 47 protected String templateURI; 48 49 protected JETParser parser; 50 51 protected JETSkeleton skeleton; 52 53 protected JETReader reader; 54 55 protected PrintWriter writer; 56 57 protected List generators = new ArrayList (100); 58 59 protected List constants = new ArrayList (100); 60 61 protected Map constantDictionary = new HashMap (100, 100); 62 63 protected long constantCount = 0; 64 65 69 protected boolean fNoNewLineForScriptlets = true; 70 71 protected boolean fUseStaticFinalConstants = true; 72 73 78 protected char[] fSavedLine = null; 79 80 84 protected int sectionDepth = 0; 85 86 89 protected boolean skipping = false; 90 91 94 protected Stack skipSections = new Stack (); 95 96 99 static class SkipSection 100 { 101 int depth; 102 boolean skip; 103 104 SkipSection(int depth, boolean skip) 105 { 106 this.depth = depth; 107 this.skip = skip; 108 } 109 } 110 111 protected static final String CONSTANT_PREFIX = "TEXT_"; 112 113 public JETCompiler(String templateURI) throws JETException 114 { 115 this(templateURI, "UTF8"); 116 } 117 118 public JETCompiler(String templateURI, String encoding) throws JETException 119 { 120 this(templateURI, openStream(templateURI), encoding); 121 } 122 123 public JETCompiler(String templateURI, InputStream inputStream, String encoding) throws JETException 124 { 125 super(); 126 127 this.templateURI = templateURI; 128 this.reader = new JETReader(templateURI, inputStream, encoding); 129 } 130 131 public JETCompiler(String [] templateURIPath, String relativeTemplateURI) throws JETException 132 { 133 this(templateURIPath, relativeTemplateURI, "UTF8"); 134 } 135 136 public JETCompiler(String [] templateURIPath, String relativeTemplateURI, String encoding) throws JETException 137 { 138 super(); 139 140 this.templateURIPath = templateURIPath; 141 this.templateURI = relativeTemplateURI; 142 String [] actualTemplateURI = findLocation(templateURIPath, 0, relativeTemplateURI); 143 this.reader = new JETReader(actualTemplateURI[1], relativeTemplateURI, openStream(actualTemplateURI[0]), encoding); 144 } 145 146 public String getResolvedTemplateURI() 147 { 148 return reader.getFile(0); 149 } 150 151 public void handleDirective(String directive, JETMark start, JETMark stop, Map attributes) throws JETException 152 { 153 if (directive.equals("include")) 154 { 155 String fileURI = (String )attributes.get("file"); 156 if (fileURI != null) 157 { 158 String currentURI = start.getFile(); 159 String [] resolvedFileURI = resolveLocation(templateURIPath, currentURI, fileURI); 160 if (resolvedFileURI[0].equals(currentURI)) 161 { 162 boolean loop = true; 163 if (templateURIPath != null) 164 { 165 String baseURI = start.getBaseURI(); 166 if (baseURI != null) 167 { 168 for (int i = 0; i < templateURIPath.length; ++i) 169 { 170 if (baseURI.equals(templateURIPath[i])) 171 { 172 resolvedFileURI = resolveLocation(templateURIPath, i + 1, currentURI, fileURI); 173 loop = false; 174 } 175 } 176 } 177 } 178 if (loop) 179 { 180 return; 183 } 184 } 185 try 186 { 187 BufferedInputStream bufferedInputStream = new BufferedInputStream (openStream(resolvedFileURI[1])); 188 reader.stackStream(resolvedFileURI[2], resolvedFileURI[0], bufferedInputStream, null); 189 190 if ("alternative".equals(attributes.get("fail"))) 193 { 194 skipSections.push(new SkipSection(sectionDepth + 1, !skipping)); 195 } 196 197 if (fSavedLine != null) 200 { 201 addCharDataGenerator(fSavedLine); 202 } 203 } 204 catch (JETException exception) 205 { 206 String failType = (String )attributes.get("fail"); 209 if ("alternative".equals(failType)) 210 { 211 skipSections.push(new SkipSection(sectionDepth + 1, false)); 212 } 213 else if (!"silent".equals(failType)) 214 { 215 throw 216 new JETException 217 (CodeGenPlugin.getPlugin().getString 218 ("jet.error.file.cannot.read", 219 new Object [] { resolvedFileURI[1], start.format("jet.mark.file.line.column") }), 220 exception); 221 } 222 } 223 } 224 else 225 { 226 throw 227 new JETException 228 (CodeGenPlugin.getPlugin().getString 229 ("jet.error.missing.attribute", 230 new Object []{ "file", start.format("jet.mark.file.line.column") })); 231 } 232 } 233 else if (directive.equals("start")) 234 { 235 sectionDepth++; 236 237 SkipSection skipSection = skipSections.isEmpty() ? null : (SkipSection)skipSections.peek(); 240 if (skipSection == null || skipSection.depth != sectionDepth) 241 { 242 throw new JETException 243 (CodeGenPlugin.getPlugin().getString 244 ("jet.error.section.noinclude", 245 new Object [] { start.format("jet.mark.file.line.column") })); 246 } 247 else if (skipSection.skip) 248 { 249 skipping = true; 250 } 251 } 252 else if (directive.equals("end")) 253 { 254 if (sectionDepth == 0) 255 { 256 throw 257 new JETException 258 (CodeGenPlugin.getPlugin().getString 259 ("jet.error.unmatched.directive", 260 new Object [] { "start", "end", start.format("jet.mark.file.line.column") })); 261 } 262 sectionDepth--; 263 264 if (((SkipSection)skipSections.pop()).skip) 267 { 268 skipping = false; 269 } 270 } 271 else if (directive.equals("jet")) 272 { 273 if (skeleton != null) 274 { 275 } 277 else 278 { 279 skeleton = new JETSkeleton(); 280 String skeletonURI = (String )attributes.get("skeleton"); 283 if (skeletonURI != null) 284 { 285 try 286 { 287 BufferedInputStream bufferedInputStream = 288 new BufferedInputStream (openStream(resolveLocation(templateURIPath, templateURI, skeletonURI)[1])); 289 byte[] input = new byte [bufferedInputStream.available()]; 290 bufferedInputStream.read(input); 291 bufferedInputStream.close(); 292 skeleton.setCompilationUnitContents(new String (input)); 293 } 294 catch (IOException exception) 295 { 296 throw new JETException(exception); 297 } 298 } 299 300 for (Iterator entries = attributes.entrySet().iterator(); entries.hasNext();) 301 { 302 Map.Entry entry = (Map.Entry )entries.next(); 303 304 if (entry.getKey().equals("skeleton")) 307 { 308 } 309 else if (entry.getKey().equals("package")) 310 { 311 skeleton.setPackageName((String )entry.getValue()); 312 } 313 else if (entry.getKey().equals("imports")) 314 { 315 skeleton.addImports((String )entry.getValue()); 316 } 317 else if (entry.getKey().equals("class")) 318 { 319 skeleton.setClassName((String )entry.getValue()); 320 } 321 else if (entry.getKey().equals("nlString")) 322 { 323 skeleton.setNLString((String )entry.getValue()); 324 } 325 else if (entry.getKey().equals("startTag")) 326 { 327 parser.setStartTag((String )entry.getValue()); 328 } 329 else if (entry.getKey().equals("endTag")) 330 { 331 parser.setEndTag((String )entry.getValue()); 332 } 333 else if (entry.getKey().equals("version")) 334 { 335 } 337 338 367 else 368 throw 369 new JETException 370 (CodeGenPlugin.getPlugin().getString 371 ("jet.error.bad.attribute", 372 new Object []{ entry.getKey(), start.format("jet.mark.file.line.column") })); 373 } 374 375 handleNewSkeleton(); 376 } 377 } 378 379 fSavedLine = null; 380 } 381 382 protected void handleNewSkeleton() 383 { 384 } 385 386 public void handleExpression(JETMark start, JETMark stop, Map attributes) throws JETException 387 { 388 if (skipping) return; 389 390 JETGenerator gen = new JETExpressionGenerator(reader.getChars(start, stop)); 391 addGenerator(gen); 392 } 393 394 public void handleScriptlet(JETMark start, JETMark stop, Map attributes) throws JETException 395 { 396 if (skipping) return; 397 398 fSavedLine = null; 399 JETGenerator gen = new JETScriptletGenerator(reader.getChars(start, stop)); 400 addGenerator(gen); 401 } 402 403 public void handleCharData(char[] chars) throws JETException 404 { 405 if (skipping) return; 406 407 if (fNoNewLineForScriptlets) 408 { 409 char[] strippedChars = stripLastNewLineWithBlanks(chars); 410 if (strippedChars.length > 0) 411 { 412 addCharDataGenerator(strippedChars); 413 } 414 } 415 else 416 { 417 addCharDataGenerator(chars); 418 } 419 } 420 421 public void addGenerator(JETGenerator gen) throws JETException 422 { 423 if (fSavedLine != null) 426 { 427 addCharDataGenerator(fSavedLine); 428 fSavedLine = null; 429 } 430 generators.add(gen); 431 } 432 433 public void addCharDataGenerator(char[] chars) throws JETException 434 { 435 if (chars.length > 500) 438 { 439 int nl = 0; 440 int lf = 0; 441 442 int start = 0; 443 LOOP: 444 for (int i = 0; i < chars.length; ++i) 445 { 446 switch (chars[i]) 447 { 448 case '\n': 449 { 450 ++nl; 451 break; 452 } 453 case '\r': 454 { 455 ++lf; 456 break; 457 } 458 default: 459 { 460 continue; 461 } 462 } 463 464 if (lf > 400 || nl > 400) 465 { 466 for (++i; i < chars.length; ++i) 467 { 468 switch (chars[i]) 469 { 470 case '\n': 471 case '\r': 472 { 473 continue; 474 } 475 default: 476 { 477 int size = i - start; 478 char [] block = new char [size]; 479 System.arraycopy(chars, start, block, 0, size); 480 doAddCharDataGenerator(block); 481 start = i; 482 nl = 0; 483 lf = 0; 484 continue LOOP; 485 } 486 } 487 } 488 } 489 } 490 if (start != 0) 491 { 492 int size = chars.length - start; 493 char [] block = new char [size]; 494 System.arraycopy(chars, start, block, 0, size); 495 doAddCharDataGenerator(block); 496 return; 497 } 498 } 499 500 doAddCharDataGenerator(chars); 501 } 502 503 public void doAddCharDataGenerator(char[] chars) throws JETException 504 { 505 if (fUseStaticFinalConstants) 506 { 507 JETConstantDataGenerator gen = (JETConstantDataGenerator)constantDictionary.get(chars); 508 if (gen == null) 509 { 510 if (constantCount == 0) 511 { 512 chars = stripFirstNewLineWithBlanks(chars); 513 } 514 ++constantCount; 515 String label = CONSTANT_PREFIX + constantCount; 516 gen = new JETConstantDataGenerator(chars, label); 517 constantDictionary.put(chars, gen); 518 constants.add(gen); 519 } 520 generators.add(gen); 521 } 522 else 523 { 524 generators.add(new JETCharDataGenerator(chars)); 525 } 526 } 527 528 protected char[] stripFirstNewLineWithBlanks(char[] chars) 529 { 530 if (chars.length >= 2 && 531 (chars[0] == '\n' && chars[1] == '\r' || chars[0] == '\r' && chars[1] == '\n')) 532 { 533 chars = new String (chars, 2, chars.length - 2).toCharArray(); 534 } 535 else if (chars.length >= 1 && 536 (chars[0] == '\n' || chars[0] == '\r')) 537 { 538 chars = new String (chars, 1, chars.length - 1).toCharArray(); 539 } 540 return chars; 541 } 542 543 protected char[] stripLastNewLineWithBlanks(char[] chars) 544 { 545 int i = chars.length - 1; 546 while (i > 0 && chars[i] == ' ') 547 { 548 --i; 549 } 550 if (chars[i] == '\n') 551 { 552 if (i > 0 && chars[i - 1] == '\r') 553 { 554 --i; 555 } 556 fSavedLine = (new String (chars, i, chars.length - i)).toCharArray(); 557 if (i == 0) 558 { 559 return NULL_CHAR_ARRAY; 560 } 561 else 562 { 563 chars = new String (chars, 0, i).toCharArray(); 564 return chars; 565 } 566 } 567 else 568 { 569 return chars; 570 } 571 } 572 573 public void beginPageProcessing() 574 { 575 } 576 577 public void endPageProcessing() throws JETException 578 { 579 if (sectionDepth > 0) 580 { 581 throw 582 new JETException 583 (CodeGenPlugin.getPlugin().getString 584 ("jet.error.unmatched.directive", 585 new Object [] { "end", "start", reader.mark().format("jet.mark.file.line.column") })); 586 } 587 588 if (skeleton == null) 589 { 590 throw 591 new JETException 592 (CodeGenPlugin.getPlugin().getString 593 ("jet.error.missing.jet.directive", 594 new Object []{ reader.mark().format("jet.mark.file.line.column") })); 595 } 596 597 if (fSavedLine != null) 600 { 601 addCharDataGenerator(fSavedLine); 602 } 603 604 List generatedConstants = new ArrayList (constants.size()); 605 for (Iterator i = constants.iterator(); i.hasNext();) 606 { 607 generatedConstants.add(((JETConstantDataGenerator)(i.next())).generateConstant()); 608 } 609 skeleton.setConstants(generatedConstants); 610 611 List generatedBody = new ArrayList (generators.size()); 612 for (Iterator i = generators.iterator(); i.hasNext();) 613 { 614 generatedBody.add(((JETGenerator)(i.next())).generate()); 615 } 616 skeleton.setBody(generatedBody); 617 618 writer.print(skeleton.getCompilationUnitContents()); 619 } 620 621 public void parse() throws JETException 622 { 623 JETParser.Directive directive = new JETParser.Directive(); 626 directive.getDirectives().add("jet"); 627 directive.getDirectives().add("include"); 628 directive.getDirectives().add("start"); 629 directive.getDirectives().add("end"); 630 631 JETCoreElement[] coreElements = 632 { 633 directive, 634 new JETParser.QuoteEscape(), 635 new JETParser.Expression(), 636 new JETParser.Scriptlet() 637 }; 638 639 Class [] accept = 640 { 641 JETParser.Directive.class, 642 JETParser.QuoteEscape.class, 643 JETParser.Expression.class, 644 JETParser.Scriptlet.class 645 }; 646 647 parse(coreElements, accept); 648 } 649 650 protected void parse(JETCoreElement[] coreElements, Class [] accept) throws JETException 651 { 652 parser = new JETParser(reader, this, coreElements); 653 beginPageProcessing(); 654 parser.parse(null, accept); 655 } 656 657 public void generate(OutputStream oStream) throws JETException 658 { 659 writer = new PrintWriter (oStream); 660 endPageProcessing(); 661 writer.close(); 662 } 663 664 public JETSkeleton getSkeleton() 665 { 666 return skeleton; 667 } 668 669 protected static String [] resolveLocation(String [] templateURIPath, String baseLocationURI, String locationURI) 670 { 671 return resolveLocation(templateURIPath, 0, baseLocationURI, locationURI); 672 } 673 674 protected static String [] resolveLocation(String [] templateURIPath, int start, String baseLocationURI, String locationURI) 675 { 676 String [] result = new String []{ locationURI, locationURI, null}; 677 try 678 { 679 String file; 680 try 681 { 682 URL url = new URL (locationURI); 683 url = Platform.resolve(url); 684 file = url.getFile(); 685 } 686 catch (MalformedURLException exception) 687 { 688 file = locationURI; 689 } 690 691 IPath path = new Path(file); 692 if (!path.isAbsolute()) 693 { 694 String resolvedLocation = ""; 695 int index = baseLocationURI.lastIndexOf("/"); 696 if (index != -1) 697 { 698 resolvedLocation = baseLocationURI.substring(0, index + 1); 699 } 700 resolvedLocation += path; 701 result[0] = resolvedLocation; 702 if (templateURIPath != null) 703 { 704 String [] location = findLocation(templateURIPath, start, resolvedLocation); 705 resolvedLocation = location[0]; 706 result[2] = location[1]; 707 } 708 if (resolvedLocation != null) 709 { 710 result[1] = resolvedLocation; 711 } 712 } 713 } 714 catch (IOException exception) 715 { 716 } 717 718 return result; 719 } 720 721 public static String [] findLocation(String [] locationURIPath, int start, String relativeLocationURI) 722 { 723 String [] result = { null, null}; 724 for (int i = start; i < locationURIPath.length; ++i) 725 { 726 result[0] = locationURIPath[i]; 727 result[1] = locationURIPath[i]; 728 729 if (result[0] != null) 730 { 731 try 732 { 733 if (!result[0].endsWith("/")) 734 { 735 result[0] += "/"; 736 } 737 result[0] += relativeLocationURI; 738 739 InputStream inputStream = openStream(result[0]); 740 inputStream.close(); 741 break; 742 } 743 catch (JETException exception) 744 { 745 result[0] = null; 746 } 747 catch (IOException exception) 748 { 749 result[0] = null; 750 } 751 } 752 } 753 return result; 754 } 755 756 public static String find(String [] locationURIPath, String relativeLocationURI) 757 { 758 return findLocation(locationURIPath, 0, relativeLocationURI)[0]; 759 } 760 761 public static InputStream openStream(String locationURI) throws JETException 762 { 763 try 764 { 765 URL url = null; 766 try 767 { 768 url = new URL (locationURI); 769 url = Platform.resolve(url); 770 } 771 catch (MalformedURLException exception) 772 { 773 url = new URL ("file:" + locationURI); 774 } 775 776 BufferedInputStream bufferedInputStream = new BufferedInputStream (url.openStream()); 777 return bufferedInputStream; 778 } 779 catch (IOException exception) 780 { 781 throw new JETException(exception.getLocalizedMessage(), exception); 782 } 783 } 784 } 785 | Popular Tags |