1 17 package org.apache.jasper.compiler; 18 19 import java.io.InputStream ; 20 import java.io.ByteArrayInputStream ; 21 import java.io.CharArrayWriter ; 22 import java.io.UnsupportedEncodingException ; 23 import java.util.ListIterator ; 24 import javax.servlet.jsp.tagext.PageData ; 25 import org.xml.sax.Attributes ; 26 import org.xml.sax.helpers.AttributesImpl ; 27 import org.apache.jasper.JasperException; 28 29 49 class PageDataImpl extends PageData implements TagConstants { 50 51 private static final String JSP_VERSION = "2.0"; 52 private static final String CDATA_START_SECTION = "<![CDATA[\n"; 53 private static final String CDATA_END_SECTION = "]]>\n"; 54 55 private StringBuffer buf; 57 58 63 public PageDataImpl(Node.Nodes page, Compiler compiler) 64 throws JasperException { 65 66 FirstPassVisitor firstPass = new FirstPassVisitor(page.getRoot(), 68 compiler.getPageInfo()); 69 page.visit(firstPass); 70 71 buf = new StringBuffer (); 73 SecondPassVisitor secondPass 74 = new SecondPassVisitor(page.getRoot(), buf, compiler, 75 firstPass.getJspIdPrefix()); 76 page.visit(secondPass); 77 } 78 79 84 public InputStream getInputStream() { 85 try { 87 return new ByteArrayInputStream (buf.toString().getBytes("UTF-8")); 88 } catch (UnsupportedEncodingException uee) { 89 throw new RuntimeException (uee.toString()); 91 } 92 } 93 94 104 static class FirstPassVisitor 105 extends Node.Visitor implements TagConstants { 106 107 private Node.Root root; 108 private AttributesImpl rootAttrs; 109 private PageInfo pageInfo; 110 111 private String jspIdPrefix; 113 114 117 public FirstPassVisitor(Node.Root root, PageInfo pageInfo) { 118 this.root = root; 119 this.pageInfo = pageInfo; 120 this.rootAttrs = new AttributesImpl (); 121 this.rootAttrs.addAttribute("", "", "version", "CDATA", 122 JSP_VERSION); 123 this.jspIdPrefix = "jsp"; 124 } 125 126 public void visit(Node.Root n) throws JasperException { 127 visitBody(n); 128 if (n == root) { 129 136 if (!JSP_URI.equals(rootAttrs.getValue("xmlns:jsp"))) { 137 rootAttrs.addAttribute("", "", "xmlns:jsp", "CDATA", 138 JSP_URI); 139 } 140 141 if (pageInfo.isJspPrefixHijacked()) { 142 150 jspIdPrefix += "jsp"; 151 while (pageInfo.containsPrefix(jspIdPrefix)) { 152 jspIdPrefix += "jsp"; 153 } 154 rootAttrs.addAttribute("", "", "xmlns:" + jspIdPrefix, 155 "CDATA", JSP_URI); 156 } 157 158 root.setAttributes(rootAttrs); 159 } 160 } 161 162 public void visit(Node.JspRoot n) throws JasperException { 163 addAttributes(n.getTaglibAttributes()); 164 addAttributes(n.getNonTaglibXmlnsAttributes()); 165 addAttributes(n.getAttributes()); 166 167 visitBody(n); 168 } 169 170 174 public void visit(Node.TaglibDirective n) throws JasperException { 175 Attributes attrs = n.getAttributes(); 176 if (attrs != null) { 177 String qName = "xmlns:" + attrs.getValue("prefix"); 178 184 if (rootAttrs.getIndex(qName) == -1) { 185 String location = attrs.getValue("uri"); 186 if (location != null) { 187 if (location.startsWith("/")) { 188 location = URN_JSPTLD + location; 189 } 190 rootAttrs.addAttribute("", "", qName, "CDATA", 191 location); 192 } else { 193 location = attrs.getValue("tagdir"); 194 rootAttrs.addAttribute("", "", qName, "CDATA", 195 URN_JSPTAGDIR + location); 196 } 197 } 198 } 199 } 200 201 public String getJspIdPrefix() { 202 return jspIdPrefix; 203 } 204 205 private void addAttributes(Attributes attrs) { 206 if (attrs != null) { 207 int len = attrs.getLength(); 208 209 for (int i=0; i<len; i++) { 210 String qName = attrs.getQName(i); 211 if ("version".equals(qName)) { 212 continue; 213 } 214 215 if(rootAttrs.getIndex(qName) == -1) { 217 rootAttrs.addAttribute(attrs.getURI(i), 218 attrs.getLocalName(i), 219 qName, 220 attrs.getType(i), 221 attrs.getValue(i)); 222 } 223 } 224 } 225 } 226 } 227 228 229 233 static class SecondPassVisitor extends Node.Visitor 234 implements TagConstants { 235 236 private Node.Root root; 237 private StringBuffer buf; 238 private Compiler compiler; 239 private String jspIdPrefix; 240 private boolean resetDefaultNS = false; 241 242 private int jspId; 244 245 248 public SecondPassVisitor(Node.Root root, StringBuffer buf, 249 Compiler compiler, String jspIdPrefix) { 250 this.root = root; 251 this.buf = buf; 252 this.compiler = compiler; 253 this.jspIdPrefix = jspIdPrefix; 254 } 255 256 259 public void visit(Node.Root n) throws JasperException { 260 if (n == this.root) { 261 appendXmlProlog(); 263 appendTag(n); 264 } else { 265 boolean resetDefaultNSSave = resetDefaultNS; 266 if (n.isXmlSyntax()) { 267 resetDefaultNS = true; 268 } 269 visitBody(n); 270 resetDefaultNS = resetDefaultNSSave; 271 } 272 } 273 274 280 public void visit(Node.JspRoot n) throws JasperException { 281 visitBody(n); 282 } 283 284 public void visit(Node.PageDirective n) throws JasperException { 285 appendPageDirective(n); 286 } 287 288 public void visit(Node.IncludeDirective n) throws JasperException { 289 visitBody(n); 291 } 292 293 public void visit(Node.Comment n) throws JasperException { 294 } 296 297 public void visit(Node.Declaration n) throws JasperException { 298 appendTag(n); 299 } 300 301 public void visit(Node.Expression n) throws JasperException { 302 appendTag(n); 303 } 304 305 public void visit(Node.Scriptlet n) throws JasperException { 306 appendTag(n); 307 } 308 309 public void visit(Node.JspElement n) throws JasperException { 310 appendTag(n); 311 } 312 313 public void visit(Node.ELExpression n) throws JasperException { 314 if (!n.getRoot().isXmlSyntax()) { 315 buf.append("<").append(JSP_TEXT_ACTION); 316 buf.append(" "); 317 buf.append(jspIdPrefix); 318 buf.append(":id=\""); 319 buf.append(jspId++).append("\">"); 320 } 321 buf.append("${"); 322 buf.append(JspUtil.escapeXml(n.getText())); 323 buf.append("}"); 324 if (!n.getRoot().isXmlSyntax()) { 325 buf.append(JSP_TEXT_ACTION_END); 326 } 327 buf.append("\n"); 328 } 329 330 public void visit(Node.IncludeAction n) throws JasperException { 331 appendTag(n); 332 } 333 334 public void visit(Node.ForwardAction n) throws JasperException { 335 appendTag(n); 336 } 337 338 public void visit(Node.GetProperty n) throws JasperException { 339 appendTag(n); 340 } 341 342 public void visit(Node.SetProperty n) throws JasperException { 343 appendTag(n); 344 } 345 346 public void visit(Node.ParamAction n) throws JasperException { 347 appendTag(n); 348 } 349 350 public void visit(Node.ParamsAction n) throws JasperException { 351 appendTag(n); 352 } 353 354 public void visit(Node.FallBackAction n) throws JasperException { 355 appendTag(n); 356 } 357 358 public void visit(Node.UseBean n) throws JasperException { 359 appendTag(n); 360 } 361 362 public void visit(Node.PlugIn n) throws JasperException { 363 appendTag(n); 364 } 365 366 public void visit(Node.NamedAttribute n) throws JasperException { 367 appendTag(n); 368 } 369 370 public void visit(Node.JspBody n) throws JasperException { 371 appendTag(n); 372 } 373 374 public void visit(Node.CustomTag n) throws JasperException { 375 boolean resetDefaultNSSave = resetDefaultNS; 376 appendTag(n, resetDefaultNS); 377 resetDefaultNS = resetDefaultNSSave; 378 } 379 380 public void visit(Node.UninterpretedTag n) throws JasperException { 381 boolean resetDefaultNSSave = resetDefaultNS; 382 appendTag(n, resetDefaultNS); 383 resetDefaultNS = resetDefaultNSSave; 384 } 385 386 public void visit(Node.JspText n) throws JasperException { 387 appendTag(n); 388 } 389 390 public void visit(Node.DoBodyAction n) throws JasperException { 391 appendTag(n); 392 } 393 394 public void visit(Node.InvokeAction n) throws JasperException { 395 appendTag(n); 396 } 397 398 public void visit(Node.TagDirective n) throws JasperException { 399 appendTagDirective(n); 400 } 401 402 public void visit(Node.AttributeDirective n) throws JasperException { 403 appendTag(n); 404 } 405 406 public void visit(Node.VariableDirective n) throws JasperException { 407 appendTag(n); 408 } 409 410 public void visit(Node.TemplateText n) throws JasperException { 411 415 appendText(n.getText(), !n.getRoot().isXmlSyntax()); 416 } 417 418 421 private void appendTag(Node n) throws JasperException { 422 appendTag(n, false); 423 } 424 425 429 private void appendTag(Node n, boolean addDefaultNS) 430 throws JasperException { 431 432 Node.Nodes body = n.getBody(); 433 String text = n.getText(); 434 435 buf.append("<").append(n.getQName()); 436 buf.append("\n"); 437 438 printAttributes(n, addDefaultNS); 439 buf.append(" ").append(jspIdPrefix).append(":id").append("=\""); 440 buf.append(jspId++).append("\"\n"); 441 442 if (ROOT_ACTION.equals(n.getLocalName()) || body != null 443 || text != null) { 444 buf.append(">\n"); 445 if (ROOT_ACTION.equals(n.getLocalName())) { 446 if (compiler.getCompilationContext().isTagFile()) { 447 appendTagDirective(); 448 } else { 449 appendPageDirective(); 450 } 451 } 452 if (body != null) { 453 body.visit(this); 454 } else { 455 appendText(text, false); 456 } 457 buf.append("</" + n.getQName() + ">\n"); 458 } else { 459 buf.append("/>\n"); 460 } 461 } 462 463 477 private void appendPageDirective(Node.PageDirective n) { 478 boolean append = false; 479 Attributes attrs = n.getAttributes(); 480 int len = (attrs == null) ? 0 : attrs.getLength(); 481 for (int i=0; i<len; i++) { 482 String attrName = attrs.getQName(i); 483 if (!"pageEncoding".equals(attrName) 484 && !"contentType".equals(attrName)) { 485 append = true; 486 break; 487 } 488 } 489 if (!append) { 490 return; 491 } 492 493 buf.append("<").append(n.getQName()); 494 buf.append("\n"); 495 496 buf.append(" ").append(jspIdPrefix).append(":id").append("=\""); 498 buf.append(jspId++).append("\"\n"); 499 500 for (int i=0; i<len; i++) { 502 String attrName = attrs.getQName(i); 503 if ("import".equals(attrName) || "contentType".equals(attrName) 504 || "pageEncoding".equals(attrName)) { 505 512 continue; 513 } 514 String value = attrs.getValue(i); 515 buf.append(" ").append(attrName).append("=\""); 516 buf.append(JspUtil.getExprInXml(value)).append("\"\n"); 517 } 518 if (n.getImports().size() > 0) { 519 boolean first = true; 521 ListIterator iter = n.getImports().listIterator(); 522 while (iter.hasNext()) { 523 if (first) { 524 first = false; 525 buf.append(" import=\""); 526 } else { 527 buf.append(","); 528 } 529 buf.append(JspUtil.getExprInXml((String ) iter.next())); 530 } 531 buf.append("\"\n"); 532 } 533 buf.append("/>\n"); 534 } 535 536 545 private void appendPageDirective() { 546 buf.append("<").append(JSP_PAGE_DIRECTIVE_ACTION); 547 buf.append("\n"); 548 549 buf.append(" ").append(jspIdPrefix).append(":id").append("=\""); 551 buf.append(jspId++).append("\"\n"); 552 buf.append(" ").append("pageEncoding").append("=\"UTF-8\"\n"); 553 buf.append(" ").append("contentType").append("=\""); 554 buf.append(compiler.getPageInfo().getContentType()).append("\"\n"); 555 buf.append("/>\n"); 556 } 557 558 566 private void appendTagDirective(Node.TagDirective n) 567 throws JasperException { 568 569 boolean append = false; 570 Attributes attrs = n.getAttributes(); 571 int len = (attrs == null) ? 0 : attrs.getLength(); 572 for (int i=0; i<len; i++) { 573 String attrName = attrs.getQName(i); 574 if (!"pageEncoding".equals(attrName)) { 575 append = true; 576 break; 577 } 578 } 579 if (!append) { 580 return; 581 } 582 583 appendTag(n); 584 } 585 586 590 private void appendTagDirective() { 591 buf.append("<").append(JSP_TAG_DIRECTIVE_ACTION); 592 buf.append("\n"); 593 594 buf.append(" ").append(jspIdPrefix).append(":id").append("=\""); 596 buf.append(jspId++).append("\"\n"); 597 buf.append(" ").append("pageEncoding").append("=\"UTF-8\"\n"); 598 buf.append("/>\n"); 599 } 600 601 private void appendText(String text, boolean createJspTextElement) { 602 if (createJspTextElement) { 603 buf.append("<").append(JSP_TEXT_ACTION); 604 buf.append("\n"); 605 606 buf.append(" ").append(jspIdPrefix).append(":id").append("=\""); 608 buf.append(jspId++).append("\"\n"); 609 buf.append(">\n"); 610 611 appendCDATA(text); 612 buf.append(JSP_TEXT_ACTION_END); 613 buf.append("\n"); 614 } else { 615 appendCDATA(text); 616 } 617 } 618 619 623 private void appendCDATA(String text) { 624 buf.append(CDATA_START_SECTION); 625 buf.append(escapeCDATA(text)); 626 buf.append(CDATA_END_SECTION); 627 } 628 629 633 private String escapeCDATA(String text) { 634 if( text==null ) return ""; 635 int len = text.length(); 636 CharArrayWriter result = new CharArrayWriter (len); 637 for (int i=0; i<len; i++) { 638 if (((i+2) < len) 639 && (text.charAt(i) == ']') 640 && (text.charAt(i+1) == ']') 641 && (text.charAt(i+2) == '>')) { 642 result.write(']'); 644 result.write(']'); 645 result.write('&'); 646 result.write('g'); 647 result.write('t'); 648 result.write(';'); 649 i += 2; 650 } else { 651 result.write(text.charAt(i)); 652 } 653 } 654 return result.toString(); 655 } 656 657 660 private void printAttributes(Node n, boolean addDefaultNS) { 661 662 665 Attributes attrs = n.getTaglibAttributes(); 666 int len = (attrs == null) ? 0 : attrs.getLength(); 667 for (int i=0; i<len; i++) { 668 String name = attrs.getQName(i); 669 String value = attrs.getValue(i); 670 buf.append(" ").append(name).append("=\"").append(value).append("\"\n"); 671 } 672 673 676 attrs = n.getNonTaglibXmlnsAttributes(); 677 len = (attrs == null) ? 0 : attrs.getLength(); 678 boolean defaultNSSeen = false; 679 for (int i=0; i<len; i++) { 680 String name = attrs.getQName(i); 681 String value = attrs.getValue(i); 682 buf.append(" ").append(name).append("=\"").append(value).append("\"\n"); 683 defaultNSSeen |= "xmlns".equals(name); 684 } 685 if (addDefaultNS && !defaultNSSeen) { 686 buf.append(" xmlns=\"\"\n"); 687 } 688 resetDefaultNS = false; 689 690 693 attrs = n.getAttributes(); 694 len = (attrs == null) ? 0 : attrs.getLength(); 695 for (int i=0; i<len; i++) { 696 String name = attrs.getQName(i); 697 String value = attrs.getValue(i); 698 buf.append(" ").append(name).append("=\""); 699 buf.append(JspUtil.getExprInXml(value)).append("\"\n"); 700 } 701 } 702 703 706 private void appendXmlProlog() { 707 buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); 708 } 709 } 710 } 711 712 | Popular Tags |