1 17 18 package org.apache.jasper.compiler; 19 20 import java.io.CharArrayWriter ; 21 import java.io.FileNotFoundException ; 22 import java.io.IOException ; 23 import java.io.InputStreamReader ; 24 import java.util.List ; 25 import java.util.Vector ; 26 import java.util.jar.JarFile ; 27 import java.net.URL ; 28 import java.net.MalformedURLException ; 29 30 import org.apache.commons.logging.Log; 31 import org.apache.commons.logging.LogFactory; 32 import org.apache.jasper.JasperException; 33 import org.apache.jasper.JspCompilationContext; 34 35 50 51 class JspReader { 52 53 56 private Log log = LogFactory.getLog(JspReader.class); 57 58 61 private Mark current; 62 63 66 private String master; 67 68 71 private List sourceFiles; 72 73 76 private int currFileId; 77 78 81 private int size; 82 83 86 private JspCompilationContext context; 87 88 91 private ErrorDispatcher err; 92 93 98 private boolean singleFile; 99 100 112 public JspReader(JspCompilationContext ctxt, 113 String fname, 114 String encoding, 115 JarFile jarFile, 116 ErrorDispatcher err) 117 throws JasperException, FileNotFoundException , IOException { 118 119 this(ctxt, fname, encoding, 120 JspUtil.getReader(fname, encoding, jarFile, ctxt, err), 121 err); 122 } 123 124 128 public JspReader(JspCompilationContext ctxt, 129 String fname, 130 String encoding, 131 InputStreamReader reader, 132 ErrorDispatcher err) 133 throws JasperException, FileNotFoundException { 134 135 this.context = ctxt; 136 this.err = err; 137 sourceFiles = new Vector (); 138 currFileId = 0; 139 size = 0; 140 singleFile = false; 141 pushFile(fname, encoding, reader); 142 } 143 144 148 JspCompilationContext getJspCompilationContext() { 149 return context; 150 } 151 152 158 String getFile(final int fileid) { 159 return (String ) sourceFiles.get(fileid); 160 } 161 162 168 boolean hasMoreInput() throws JasperException { 169 if (current.cursor >= current.stream.length) { 170 if (singleFile) return false; 171 while (popFile()) { 172 if (current.cursor < current.stream.length) return true; 173 } 174 return false; 175 } 176 return true; 177 } 178 179 int nextChar() throws JasperException { 180 if (!hasMoreInput()) 181 return -1; 182 183 int ch = current.stream[current.cursor]; 184 185 current.cursor++; 186 187 if (ch == '\n') { 188 current.line++; 189 current.col = 0; 190 } else { 191 current.col++; 192 } 193 return ch; 194 } 195 196 200 void pushChar() { 201 current.cursor--; 202 current.col--; 203 } 204 205 String getText(Mark start, Mark stop) throws JasperException { 206 Mark oldstart = mark(); 207 reset(start); 208 CharArrayWriter caw = new CharArrayWriter (); 209 while (!stop.equals(mark())) 210 caw.write(nextChar()); 211 caw.close(); 212 reset(oldstart); 213 return caw.toString(); 214 } 215 216 int peekChar() throws JasperException { 217 if (!hasMoreInput()) 218 return -1; 219 return current.stream[current.cursor]; 220 } 221 222 Mark mark() { 223 return new Mark(current); 224 } 225 226 void reset(Mark mark) { 227 current = new Mark(mark); 228 } 229 230 boolean matchesIgnoreCase(String string) throws JasperException { 231 Mark mark = mark(); 232 int ch = 0; 233 int i = 0; 234 do { 235 ch = nextChar(); 236 if (Character.toLowerCase((char) ch) != string.charAt(i++)) { 237 reset(mark); 238 return false; 239 } 240 } while (i < string.length()); 241 reset(mark); 242 return true; 243 } 244 245 252 boolean matches(String string) throws JasperException { 253 Mark mark = mark(); 254 int ch = 0; 255 int i = 0; 256 do { 257 ch = nextChar(); 258 if (((char) ch) != string.charAt(i++)) { 259 reset(mark); 260 return false; 261 } 262 } while (i < string.length()); 263 return true; 264 } 265 266 boolean matchesETag(String tagName) throws JasperException { 267 Mark mark = mark(); 268 269 if (!matches("</" + tagName)) 270 return false; 271 skipSpaces(); 272 if (nextChar() == '>') 273 return true; 274 275 reset(mark); 276 return false; 277 } 278 279 boolean matchesETagWithoutLessThan(String tagName) 280 throws JasperException 281 { 282 Mark mark = mark(); 283 284 if (!matches("/" + tagName)) 285 return false; 286 skipSpaces(); 287 if (nextChar() == '>') 288 return true; 289 290 reset(mark); 291 return false; 292 } 293 294 295 301 boolean matchesOptionalSpacesFollowedBy( String s ) 302 throws JasperException 303 { 304 Mark mark = mark(); 305 306 skipSpaces(); 307 boolean result = matches( s ); 308 if( !result ) { 309 reset( mark ); 310 } 311 312 return result; 313 } 314 315 int skipSpaces() throws JasperException { 316 int i = 0; 317 while (hasMoreInput() && isSpace()) { 318 i++; 319 nextChar(); 320 } 321 return i; 322 } 323 324 333 Mark skipUntil(String limit) throws JasperException { 334 Mark ret = null; 335 int limlen = limit.length(); 336 int ch; 337 338 skip: 339 for (ret = mark(), ch = nextChar() ; ch != -1 ; 340 ret = mark(), ch = nextChar()) { 341 if (ch == limit.charAt(0)) { 342 Mark restart = mark(); 343 for (int i = 1 ; i < limlen ; i++) { 344 if (peekChar() == limit.charAt(i)) 345 nextChar(); 346 else { 347 reset(restart); 348 continue skip; 349 } 350 } 351 return ret; 352 } 353 } 354 return null; 355 } 356 357 367 Mark skipUntilIgnoreEsc(String limit) throws JasperException { 368 Mark ret = null; 369 int limlen = limit.length(); 370 int ch; 371 int prev = 'x'; 373 skip: 374 for (ret = mark(), ch = nextChar() ; ch != -1 ; 375 ret = mark(), prev = ch, ch = nextChar()) { 376 if (ch == '\\' && prev == '\\') { 377 ch = 0; } 379 else if (ch == limit.charAt(0) && prev != '\\') { 380 for (int i = 1 ; i < limlen ; i++) { 381 if (peekChar() == limit.charAt(i)) 382 nextChar(); 383 else 384 continue skip; 385 } 386 return ret; 387 } 388 } 389 return null; 390 } 391 392 400 Mark skipUntilETag(String tag) throws JasperException { 401 Mark ret = skipUntil("</" + tag); 402 if (ret != null) { 403 skipSpaces(); 404 if (nextChar() != '>') 405 ret = null; 406 } 407 return ret; 408 } 409 410 final boolean isSpace() throws JasperException { 411 return peekChar() <= ' '; 413 } 414 415 422 String parseToken(boolean quoted) throws JasperException { 423 StringBuffer stringBuffer = new StringBuffer (); 424 skipSpaces(); 425 stringBuffer.setLength(0); 426 427 if (!hasMoreInput()) { 428 return ""; 429 } 430 431 int ch = peekChar(); 432 433 if (quoted) { 434 if (ch == '"' || ch == '\'') { 435 436 char endQuote = ch == '"' ? '"' : '\''; 437 ch = nextChar(); 439 for (ch = nextChar(); ch != -1 && ch != endQuote; 440 ch = nextChar()) { 441 if (ch == '\\') 442 ch = nextChar(); 443 stringBuffer.append((char) ch); 444 } 445 if (ch == -1) { 447 err.jspError(mark(), "jsp.error.quotes.unterminated"); 448 } 449 } else { 450 err.jspError(mark(), "jsp.error.attr.quoted"); 451 } 452 } else { 453 if (!isDelimiter()) { 454 do { 456 ch = nextChar(); 457 if (ch == '\\') { 459 if (peekChar() == '"' || peekChar() == '\'' || 460 peekChar() == '>' || peekChar() == '%') 461 ch = nextChar(); 462 } 463 stringBuffer.append((char) ch); 464 } while (!isDelimiter()); 465 } 466 } 467 468 return stringBuffer.toString(); 469 } 470 471 void setSingleFile(boolean val) { 472 singleFile = val; 473 } 474 475 476 486 URL getResource(String path) throws MalformedURLException { 487 return context.getResource(path); 488 } 489 490 491 498 private boolean isDelimiter() throws JasperException { 499 if (! isSpace()) { 500 int ch = peekChar(); 501 if (ch == '=' || ch == '>' || ch == '"' || ch == '\'' 503 || ch == '/') { 504 return true; 505 } 506 if (ch == '-') { 508 Mark mark = mark(); 509 if (((ch = nextChar()) == '>') 510 || ((ch == '-') && (nextChar() == '>'))) { 511 reset(mark); 512 return true; 513 } else { 514 reset(mark); 515 return false; 516 } 517 } 518 return false; 519 } else { 520 return true; 521 } 522 } 523 524 532 private int registerSourceFile(final String file) { 533 if (sourceFiles.contains(file)) { 534 return -1; 535 } 536 537 sourceFiles.add(file); 538 this.size++; 539 540 return sourceFiles.size() - 1; 541 } 542 543 544 552 private int unregisterSourceFile(final String file) { 553 if (!sourceFiles.contains(file)) { 554 return -1; 555 } 556 557 sourceFiles.remove(file); 558 this.size--; 559 return sourceFiles.size() - 1; 560 } 561 562 566 private void pushFile(String file, String encoding, 567 InputStreamReader reader) 568 throws JasperException, FileNotFoundException { 569 570 String longName = file; 572 573 int fileid = registerSourceFile(longName); 574 575 if (fileid == -1) { 576 if(reader != null) { 578 try { 579 reader.close(); 580 } catch (Exception any) { 581 if(log.isDebugEnabled()) { 582 log.debug("Exception closing reader: ", any); 583 } 584 } 585 } 586 587 err.jspError("jsp.error.file.already.registered", file); 588 } 589 590 currFileId = fileid; 591 592 try { 593 CharArrayWriter caw = new CharArrayWriter (); 594 char buf[] = new char[1024]; 595 for (int i = 0 ; (i = reader.read(buf)) != -1 ;) 596 caw.write(buf, 0, i); 597 caw.close(); 598 if (current == null) { 599 current = new Mark(this, caw.toCharArray(), fileid, 600 getFile(fileid), master, encoding); 601 } else { 602 current.pushStream(caw.toCharArray(), fileid, getFile(fileid), 603 longName, encoding); 604 } 605 } catch (Throwable ex) { 606 log.error("Exception parsing file ", ex); 607 popFile(); 609 err.jspError("jsp.error.file.cannot.read", file); 610 } finally { 611 if (reader != null) { 612 try { 613 reader.close(); 614 } catch (Exception any) { 615 if(log.isDebugEnabled()) { 616 log.debug("Exception closing reader: ", any); 617 } 618 } 619 } 620 } 621 } 622 623 630 private boolean popFile() throws JasperException { 631 632 if (current == null || currFileId < 0) { 635 return false; 636 } 637 638 String fName = getFile(currFileId); 640 currFileId = unregisterSourceFile(fName); 641 if (currFileId < -1) { 642 err.jspError("jsp.error.file.not.registered", fName); 643 } 644 645 Mark previous = current.popStream(); 646 if (previous != null) { 647 master = current.baseDir; 648 current = previous; 649 return true; 650 } 651 return false; 655 } 656 } 657 658 | Popular Tags |