1 17 18 package org.apache.jasper.compiler; 19 20 import java.io.FileNotFoundException ; 21 import java.io.IOException ; 22 import java.io.InputStreamReader ; 23 import java.net.JarURLConnection ; 24 import java.net.URL ; 25 import java.util.Stack ; 26 import java.util.jar.JarFile ; 27 28 import org.apache.jasper.JasperException; 29 import org.apache.jasper.JspCompilationContext; 30 import org.apache.jasper.xmlparser.XMLEncodingDetector; 31 import org.xml.sax.Attributes ; 32 33 44 class ParserController implements TagConstants { 45 46 private static final String CHARSET = "charset="; 47 48 private JspCompilationContext ctxt; 49 private Compiler compiler; 50 private ErrorDispatcher err; 51 52 55 private boolean isXml; 56 57 61 private Stack baseDirStack = new Stack (); 62 63 private boolean isEncodingSpecifiedInProlog; 64 private boolean isBomPresent; 65 66 private String sourceEnc; 67 68 private boolean isDefaultPageEncoding; 69 private boolean isTagFile; 70 private boolean directiveOnly; 71 72 75 public ParserController(JspCompilationContext ctxt, Compiler compiler) { 76 this.ctxt = ctxt; 77 this.compiler = compiler; 78 this.err = compiler.getErrorDispatcher(); 79 } 80 81 public JspCompilationContext getJspCompilationContext () { 82 return ctxt; 83 } 84 85 public Compiler getCompiler () { 86 return compiler; 87 } 88 89 94 public Node.Nodes parse(String inFileName) 95 throws FileNotFoundException , JasperException, IOException { 96 isTagFile = ctxt.isTagFile(); 101 directiveOnly = false; 102 return doParse(inFileName, null, ctxt.getTagFileJarUrl()); 103 } 104 105 113 public Node.Nodes parse(String inFileName, Node parent, 114 URL jarFileUrl) 115 throws FileNotFoundException , JasperException, IOException { 116 return doParse(inFileName, parent, jarFileUrl); 119 } 120 121 129 public Node.Nodes parseTagFileDirectives(String inFileName) 130 throws FileNotFoundException , JasperException, IOException { 131 boolean isTagFileSave = isTagFile; 132 boolean directiveOnlySave = directiveOnly; 133 isTagFile = true; 134 directiveOnly = true; 135 Node.Nodes page = doParse(inFileName, null, 136 ctxt.getTagFileJarUrl(inFileName)); 137 directiveOnly = directiveOnlySave; 138 isTagFile = isTagFileSave; 139 return page; 140 } 141 142 156 private Node.Nodes doParse(String inFileName, 157 Node parent, 158 URL jarFileUrl) 159 throws FileNotFoundException , JasperException, IOException { 160 161 Node.Nodes parsedPage = null; 162 isEncodingSpecifiedInProlog = false; 163 isBomPresent = false; 164 isDefaultPageEncoding = false; 165 166 JarFile jarFile = getJarFile(jarFileUrl); 167 String absFileName = resolveFileName(inFileName); 168 String jspConfigPageEnc = getJspConfigPageEncoding(absFileName); 169 170 determineSyntaxAndEncoding(absFileName, jarFile, jspConfigPageEnc); 173 174 if (parent != null) { 175 compiler.getPageInfo().addDependant(absFileName); 177 } 178 179 if ((isXml && isEncodingSpecifiedInProlog) || isBomPresent) { 180 186 if (jspConfigPageEnc != null && !jspConfigPageEnc.equals(sourceEnc) 187 && (!jspConfigPageEnc.startsWith("UTF-16") 188 || !sourceEnc.startsWith("UTF-16"))) { 189 err.jspError("jsp.error.prolog_config_encoding_mismatch", 190 sourceEnc, jspConfigPageEnc); 191 } 192 } 193 194 if (isXml) { 196 parsedPage = JspDocumentParser.parse(this, absFileName, 200 jarFile, parent, 201 isTagFile, directiveOnly, 202 sourceEnc, 203 jspConfigPageEnc, 204 isEncodingSpecifiedInProlog, 205 isBomPresent); 206 } else { 207 InputStreamReader inStreamReader = null; 209 try { 210 inStreamReader = JspUtil.getReader(absFileName, sourceEnc, 211 jarFile, ctxt, err); 212 JspReader jspReader = new JspReader(ctxt, absFileName, 213 sourceEnc, inStreamReader, 214 err); 215 parsedPage = Parser.parse(this, jspReader, parent, isTagFile, 216 directiveOnly, jarFileUrl, 217 sourceEnc, jspConfigPageEnc, 218 isDefaultPageEncoding, isBomPresent); 219 } finally { 220 if (inStreamReader != null) { 221 try { 222 inStreamReader.close(); 223 } catch (Exception any) { 224 } 225 } 226 } 227 } 228 229 if (jarFile != null) { 230 try { 231 jarFile.close(); 232 } catch (Throwable t) {} 233 } 234 235 baseDirStack.pop(); 236 237 return parsedPage; 238 } 239 240 250 private String getJspConfigPageEncoding(String absFileName) 251 throws JasperException { 252 253 JspConfig jspConfig = ctxt.getOptions().getJspConfig(); 254 JspConfig.JspProperty jspProperty 255 = jspConfig.findJspProperty(absFileName); 256 return jspProperty.getPageEncoding(); 257 } 258 259 264 private void determineSyntaxAndEncoding(String absFileName, 265 JarFile jarFile, 266 String jspConfigPageEnc) 267 throws JasperException, IOException { 268 269 isXml = false; 270 271 276 boolean isExternal = false; 277 278 282 boolean revert = false; 283 284 JspConfig jspConfig = ctxt.getOptions().getJspConfig(); 285 JspConfig.JspProperty jspProperty = jspConfig.findJspProperty( 286 absFileName); 287 if (jspProperty.isXml() != null) { 288 isXml = JspUtil.booleanValue(jspProperty.isXml()); 290 isExternal = true; 291 } else if (absFileName.endsWith(".jspx") 292 || absFileName.endsWith(".tagx")) { 293 isXml = true; 294 isExternal = true; 295 } 296 297 if (isExternal && !isXml) { 298 sourceEnc = jspConfigPageEnc; 301 if (sourceEnc != null) { 302 return; 303 } 304 sourceEnc = "ISO-8859-1"; 306 } else { 307 Object [] ret = XMLEncodingDetector.getEncoding(absFileName, 309 jarFile, ctxt, err); 310 sourceEnc = (String ) ret[0]; 311 if (((Boolean ) ret[1]).booleanValue()) { 312 isEncodingSpecifiedInProlog = true; 313 } 314 if (((Boolean ) ret[2]).booleanValue()) { 315 isBomPresent = true; 316 } 317 318 if (!isXml && sourceEnc.equals("UTF-8")) { 319 335 sourceEnc = "ISO-8859-1"; 336 revert = true; 337 } 338 } 339 340 if (isXml) { 341 return; 345 } 346 347 356 JspReader jspReader = null; 357 try { 358 jspReader = new JspReader(ctxt, absFileName, sourceEnc, jarFile, 359 err); 360 } catch (FileNotFoundException ex) { 361 throw new JasperException(ex); 362 } 363 jspReader.setSingleFile(true); 364 Mark startMark = jspReader.mark(); 365 if (!isExternal) { 366 jspReader.reset(startMark); 367 if (hasJspRoot(jspReader)) { 368 if (revert) { 369 sourceEnc = "UTF-8"; 370 } 371 isXml = true; 372 return; 373 } else { 374 if (revert && isBomPresent) { 375 sourceEnc = "UTF-8"; 376 } 377 isXml = false; 378 } 379 } 380 381 387 if (!isBomPresent) { 388 sourceEnc = jspConfigPageEnc; 389 if (sourceEnc == null) { 390 sourceEnc = getPageEncodingForJspSyntax(jspReader, startMark); 391 if (sourceEnc == null) { 392 sourceEnc = "ISO-8859-1"; 394 isDefaultPageEncoding = true; 395 } 396 } 397 } 398 399 } 400 401 409 private String getPageEncodingForJspSyntax(JspReader jspReader, 410 Mark startMark) 411 throws JasperException { 412 413 String encoding = null; 414 String saveEncoding = null; 415 416 jspReader.reset(startMark); 417 418 422 while (true) { 423 if (jspReader.skipUntil("<") == null) { 424 break; 425 } 426 if (jspReader.matches("%--")) { 428 if (jspReader.skipUntil("--%>") == null) { 429 break; 431 } 432 continue; 433 } 434 boolean isDirective = jspReader.matches("%@"); 435 if (isDirective) { 436 jspReader.skipSpaces(); 437 } 438 else { 439 isDirective = jspReader.matches("jsp:directive."); 440 } 441 if (!isDirective) { 442 continue; 443 } 444 445 if (jspReader.matches("tag ") || jspReader.matches("page")) { 447 448 jspReader.skipSpaces(); 449 Attributes attrs = Parser.parseAttributes(this, jspReader); 450 encoding = getPageEncodingFromDirective(attrs, "pageEncoding"); 451 if (encoding != null) { 452 break; 453 } 454 encoding = getPageEncodingFromDirective(attrs, "contentType"); 455 if (encoding != null) { 456 saveEncoding = encoding; 457 } 458 } 459 } 460 461 if (encoding == null) { 462 encoding = saveEncoding; 463 } 464 465 return encoding; 466 } 467 468 482 private String getPageEncodingFromDirective(Attributes attrs, 483 String attrName) { 484 String value = attrs.getValue(attrName); 485 if (attrName.equals("pageEncoding")) { 486 return value; 487 } 488 489 String contentType = value; 491 String encoding = null; 492 if (contentType != null) { 493 int loc = contentType.indexOf(CHARSET); 494 if (loc != -1) { 495 encoding = contentType.substring(loc + CHARSET.length()); 496 } 497 } 498 499 return encoding; 500 } 501 502 508 private String resolveFileName(String inFileName) { 509 String fileName = inFileName.replace('\\', '/'); 510 boolean isAbsolute = fileName.startsWith("/"); 511 fileName = isAbsolute ? fileName 512 : (String ) baseDirStack.peek() + fileName; 513 String baseDir = 514 fileName.substring(0, fileName.lastIndexOf("/") + 1); 515 baseDirStack.push(baseDir); 516 return fileName; 517 } 518 519 532 private boolean hasJspRoot(JspReader reader) throws JasperException { 533 534 Mark start = null; 536 while ((start = reader.skipUntil("<")) != null) { 537 int c = reader.nextChar(); 538 if (c != '!' && c != '?') break; 539 } 540 if (start == null) { 541 return false; 542 } 543 Mark stop = reader.skipUntil(":root"); 544 if (stop == null) { 545 return false; 546 } 547 String prefix = reader.getText(start, stop).substring(1); 549 550 start = stop; 551 stop = reader.skipUntil(">"); 552 if (stop == null) { 553 return false; 554 } 555 556 String root = reader.getText(start, stop); 558 String xmlnsDecl = "xmlns:" + prefix; 559 int index = root.indexOf(xmlnsDecl); 560 if (index == -1) { 561 return false; 562 } 563 index += xmlnsDecl.length(); 564 while (index < root.length() 565 && Character.isWhitespace(root.charAt(index))) { 566 index++; 567 } 568 if (index < root.length() && root.charAt(index) == '=') { 569 index++; 570 while (index < root.length() 571 && Character.isWhitespace(root.charAt(index))) { 572 index++; 573 } 574 if (index < root.length() && root.charAt(index++) == '"' 575 && root.regionMatches(index, JSP_URI, 0, 576 JSP_URI.length())) { 577 return true; 578 } 579 } 580 581 return false; 582 } 583 584 private JarFile getJarFile(URL jarFileUrl) throws IOException { 585 JarFile jarFile = null; 586 587 if (jarFileUrl != null) { 588 JarURLConnection conn = (JarURLConnection ) jarFileUrl.openConnection(); 589 conn.setUseCaches(false); 590 conn.connect(); 591 jarFile = conn.getJarFile(); 592 } 593 594 return jarFile; 595 } 596 597 } 598 | Popular Tags |