Source Code Cross Referenced for JspReader.java in  » Sevlet-Container » tomcat-jasper2 » org » apache » jasper » compiler » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Sevlet Container » tomcat jasper2 » org.apache.jasper.compiler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 1999,2004 The Apache Software Foundation.
003:         * 
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         * 
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         * 
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.apache.jasper.compiler;
018:
019:        import java.io.CharArrayWriter;
020:        import java.io.FileNotFoundException;
021:        import java.io.IOException;
022:        import java.io.InputStreamReader;
023:        import java.util.Vector;
024:        import java.util.jar.JarFile;
025:        import java.net.URL;
026:        import java.net.MalformedURLException;
027:
028:        import org.apache.commons.logging.Log;
029:        import org.apache.commons.logging.LogFactory;
030:        import org.apache.jasper.JasperException;
031:        import org.apache.jasper.JspCompilationContext;
032:
033:        /**
034:         * JspReader is an input buffer for the JSP parser. It should allow
035:         * unlimited lookahead and pushback. It also has a bunch of parsing
036:         * utility methods for understanding htmlesque thingies.
037:         *
038:         * @author Anil K. Vijendran
039:         * @author Anselm Baird-Smith
040:         * @author Harish Prabandham
041:         * @author Rajiv Mordani
042:         * @author Mandar Raje
043:         * @author Danno Ferrin
044:         * @author Kin-man Chung
045:         * @author Shawn Bayern
046:         * @author Mark Roth
047:         */
048:
049:        class JspReader {
050:
051:            // Logger
052:            private static Log log = LogFactory.getLog(JspReader.class);
053:
054:            private Mark current;
055:            private String master;
056:            private Vector sourceFiles;
057:            private int currFileId;
058:            private int size;
059:            private JspCompilationContext context;
060:            private ErrorDispatcher err;
061:
062:            /*
063:             * Set to true when using the JspReader on a single file where we read up
064:             * to the end and reset to the beginning many times.
065:             * (as in ParserController.figureOutJspDocument()).
066:             */
067:            private boolean singleFile;
068:
069:            /*
070:             * Constructor.
071:             */
072:            public JspReader(JspCompilationContext ctxt, String fname,
073:                    String encoding, JarFile jarFile, ErrorDispatcher err)
074:                    throws JasperException, FileNotFoundException, IOException {
075:
076:                this (ctxt, fname, encoding, JspUtil.getReader(fname, encoding,
077:                        jarFile, ctxt, err), err);
078:            }
079:
080:            /*
081:             * Constructor.
082:             */
083:            public JspReader(JspCompilationContext ctxt, String fname,
084:                    String encoding, InputStreamReader reader,
085:                    ErrorDispatcher err) throws JasperException,
086:                    FileNotFoundException {
087:
088:                this .context = ctxt;
089:                this .err = err;
090:                sourceFiles = new Vector();
091:                currFileId = 0;
092:                size = 0;
093:                singleFile = false;
094:                pushFile(fname, encoding, reader);
095:            }
096:
097:            /*
098:             * @return JSP compilation context with which this JspReader is 
099:             * associated
100:             */
101:            JspCompilationContext getJspCompilationContext() {
102:                return context;
103:            }
104:
105:            String getFile(int fileid) {
106:                return (String) sourceFiles.elementAt(fileid);
107:            }
108:
109:            boolean hasMoreInput() throws JasperException {
110:                if (current.cursor >= current.stream.length) {
111:                    if (singleFile)
112:                        return false;
113:                    while (popFile()) {
114:                        if (current.cursor < current.stream.length)
115:                            return true;
116:                    }
117:                    return false;
118:                }
119:                return true;
120:            }
121:
122:            int nextChar() throws JasperException {
123:                if (!hasMoreInput())
124:                    return -1;
125:
126:                int ch = current.stream[current.cursor];
127:
128:                current.cursor++;
129:
130:                if (ch == '\n') {
131:                    current.line++;
132:                    current.col = 0;
133:                } else {
134:                    current.col++;
135:                }
136:                return ch;
137:            }
138:
139:            /**
140:             * Back up the current cursor by one char, assumes current.cursor > 0,
141:             * and that the char to be pushed back is not '\n'.
142:             */
143:            void pushChar() {
144:                current.cursor--;
145:                current.col--;
146:            }
147:
148:            String getText(Mark start, Mark stop) throws JasperException {
149:                Mark oldstart = mark();
150:                reset(start);
151:                CharArrayWriter caw = new CharArrayWriter();
152:                while (!stop.equals(mark()))
153:                    caw.write(nextChar());
154:                caw.close();
155:                reset(oldstart);
156:                return caw.toString();
157:            }
158:
159:            int peekChar() {
160:                return current.stream[current.cursor];
161:            }
162:
163:            Mark mark() {
164:                return new Mark(current);
165:            }
166:
167:            void reset(Mark mark) {
168:                current = new Mark(mark);
169:            }
170:
171:            boolean matchesIgnoreCase(String string) throws JasperException {
172:                Mark mark = mark();
173:                int ch = 0;
174:                int i = 0;
175:                do {
176:                    ch = nextChar();
177:                    if (Character.toLowerCase((char) ch) != string.charAt(i++)) {
178:                        reset(mark);
179:                        return false;
180:                    }
181:                } while (i < string.length());
182:                reset(mark);
183:                return true;
184:            }
185:
186:            /**
187:             * search the stream for a match to a string
188:             * @param string The string to match
189:             * @return <strong>true</strong> is one is found, the current position
190:             *         in stream is positioned after the search string, <strong>
191:             *	       false</strong> otherwise, position in stream unchanged.
192:             */
193:            boolean matches(String string) throws JasperException {
194:                Mark mark = mark();
195:                int ch = 0;
196:                int i = 0;
197:                do {
198:                    ch = nextChar();
199:                    if (((char) ch) != string.charAt(i++)) {
200:                        reset(mark);
201:                        return false;
202:                    }
203:                } while (i < string.length());
204:                return true;
205:            }
206:
207:            boolean matchesETag(String tagName) throws JasperException {
208:                Mark mark = mark();
209:
210:                if (!matches("</" + tagName))
211:                    return false;
212:                skipSpaces();
213:                if (nextChar() == '>')
214:                    return true;
215:
216:                reset(mark);
217:                return false;
218:            }
219:
220:            boolean matchesETagWithoutLessThan(String tagName)
221:                    throws JasperException {
222:                Mark mark = mark();
223:
224:                if (!matches("/" + tagName))
225:                    return false;
226:                skipSpaces();
227:                if (nextChar() == '>')
228:                    return true;
229:
230:                reset(mark);
231:                return false;
232:            }
233:
234:            /**
235:             * Looks ahead to see if there are optional spaces followed by
236:             * the given String.  If so, true is returned and those spaces and
237:             * characters are skipped.  If not, false is returned and the
238:             * position is restored to where we were before.
239:             */
240:            boolean matchesOptionalSpacesFollowedBy(String s)
241:                    throws JasperException {
242:                Mark mark = mark();
243:
244:                skipSpaces();
245:                boolean result = matches(s);
246:                if (!result) {
247:                    reset(mark);
248:                }
249:
250:                return result;
251:            }
252:
253:            int skipSpaces() throws JasperException {
254:                int i = 0;
255:                while (hasMoreInput() && isSpace()) {
256:                    i++;
257:                    nextChar();
258:                }
259:                return i;
260:            }
261:
262:            /**
263:             * Skip until the given string is matched in the stream.
264:             * When returned, the context is positioned past the end of the match.
265:             *
266:             * @param s The String to match.
267:             * @return A non-null <code>Mark</code> instance (positioned immediately
268:             *         before the search string) if found, <strong>null</strong>
269:             *         otherwise.
270:             */
271:            Mark skipUntil(String limit) throws JasperException {
272:                Mark ret = null;
273:                int limlen = limit.length();
274:                int ch;
275:
276:                skip: for (ret = mark(), ch = nextChar(); ch != -1; ret = mark(), ch = nextChar()) {
277:                    if (ch == limit.charAt(0)) {
278:                        Mark restart = mark();
279:                        for (int i = 1; i < limlen; i++) {
280:                            if (peekChar() == limit.charAt(i))
281:                                nextChar();
282:                            else {
283:                                reset(restart);
284:                                continue skip;
285:                            }
286:                        }
287:                        return ret;
288:                    }
289:                }
290:                return null;
291:            }
292:
293:            /**
294:             * Skip until the given string is matched in the stream, but ignoring
295:             * chars initially escaped by a '\'.
296:             * When returned, the context is positioned past the end of the match.
297:             *
298:             * @param s The String to match.
299:             * @return A non-null <code>Mark</code> instance (positioned immediately
300:             *         before the search string) if found, <strong>null</strong>
301:             *         otherwise.
302:             */
303:            Mark skipUntilIgnoreEsc(String limit) throws JasperException {
304:                Mark ret = null;
305:                int limlen = limit.length();
306:                int ch;
307:                int prev = 'x'; // Doesn't matter
308:
309:                skip: for (ret = mark(), ch = nextChar(); ch != -1; ret = mark(), prev = ch, ch = nextChar()) {
310:                    if (ch == '\\' && prev == '\\') {
311:                        ch = 0; // Double \ is not an escape char anymore
312:                    } else if (ch == limit.charAt(0) && prev != '\\') {
313:                        for (int i = 1; i < limlen; i++) {
314:                            if (peekChar() == limit.charAt(i))
315:                                nextChar();
316:                            else
317:                                continue skip;
318:                        }
319:                        return ret;
320:                    }
321:                }
322:                return null;
323:            }
324:
325:            /**
326:             * Skip until the given end tag is matched in the stream.
327:             * When returned, the context is positioned past the end of the tag.
328:             *
329:             * @param tag The name of the tag whose ETag (</tag>) to match.
330:             * @return A non-null <code>Mark</code> instance (positioned immediately
331:             *	       before the ETag) if found, <strong>null</strong> otherwise.
332:             */
333:            Mark skipUntilETag(String tag) throws JasperException {
334:                Mark ret = skipUntil("</" + tag);
335:                if (ret != null) {
336:                    skipSpaces();
337:                    if (nextChar() != '>')
338:                        ret = null;
339:                }
340:                return ret;
341:            }
342:
343:            final boolean isSpace() {
344:                // Note: If this logic changes, also update Node.TemplateText.rtrim()
345:                return peekChar() <= ' ';
346:            }
347:
348:            /**
349:             * Parse a space delimited token.
350:             * If quoted the token will consume all characters up to a matching quote,
351:             * otherwise, it consumes up to the first delimiter character.
352:             *
353:             * @param quoted If <strong>true</strong> accept quoted strings.
354:             */
355:            String parseToken(boolean quoted) throws JasperException {
356:                StringBuffer stringBuffer = new StringBuffer();
357:                skipSpaces();
358:                stringBuffer.setLength(0);
359:
360:                int ch = peekChar();
361:
362:                if (quoted) {
363:                    if (ch == '"' || ch == '\'') {
364:
365:                        char endQuote = ch == '"' ? '"' : '\'';
366:                        // Consume the open quote: 
367:                        ch = nextChar();
368:                        for (ch = nextChar(); ch != -1 && ch != endQuote; ch = nextChar()) {
369:                            if (ch == '\\')
370:                                ch = nextChar();
371:                            stringBuffer.append((char) ch);
372:                        }
373:                        // Check end of quote, skip closing quote:
374:                        if (ch == -1) {
375:                            err.jspError(mark(),
376:                                    "jsp.error.quotes.unterminated");
377:                        }
378:                    } else {
379:                        err.jspError(mark(), "jsp.error.attr.quoted");
380:                    }
381:                } else {
382:                    if (!isDelimiter()) {
383:                        // Read value until delimiter is found:
384:                        do {
385:                            ch = nextChar();
386:                            // Take care of the quoting here.
387:                            if (ch == '\\') {
388:                                if (peekChar() == '"' || peekChar() == '\''
389:                                        || peekChar() == '>'
390:                                        || peekChar() == '%')
391:                                    ch = nextChar();
392:                            }
393:                            stringBuffer.append((char) ch);
394:                        } while (!isDelimiter());
395:                    }
396:                }
397:
398:                return stringBuffer.toString();
399:            }
400:
401:            void setSingleFile(boolean val) {
402:                singleFile = val;
403:            }
404:
405:            /**
406:             * Gets the URL for the given path name.
407:             *
408:             * @param path Path name
409:             *
410:             * @return URL for the given path name.
411:             *
412:             * @exception MalformedURLException if the path name is not given in 
413:             * the correct form
414:             */
415:            URL getResource(String path) throws MalformedURLException {
416:                return context.getResource(path);
417:            }
418:
419:            /**
420:             * Parse utils - Is current character a token delimiter ?
421:             * Delimiters are currently defined to be =, &gt;, &lt;, ", and ' or any
422:             * any space character as defined by <code>isSpace</code>.
423:             *
424:             * @return A boolean.
425:             */
426:            private boolean isDelimiter() throws JasperException {
427:                if (!isSpace()) {
428:                    int ch = peekChar();
429:                    // Look for a single-char work delimiter:
430:                    if (ch == '=' || ch == '>' || ch == '"' || ch == '\''
431:                            || ch == '/') {
432:                        return true;
433:                    }
434:                    // Look for an end-of-comment or end-of-tag:		
435:                    if (ch == '-') {
436:                        Mark mark = mark();
437:                        if (((ch = nextChar()) == '>')
438:                                || ((ch == '-') && (nextChar() == '>'))) {
439:                            reset(mark);
440:                            return true;
441:                        } else {
442:                            reset(mark);
443:                            return false;
444:                        }
445:                    }
446:                    return false;
447:                } else {
448:                    return true;
449:                }
450:            }
451:
452:            /**
453:             * Register a new source file.
454:             * This method is used to implement file inclusion. Each included file
455:             * gets a unique identifier (which is the index in the array of source
456:             * files).
457:             *
458:             * @return The index of the now registered file.
459:             */
460:            private int registerSourceFile(String file) {
461:                if (sourceFiles.contains(file))
462:                    return -1;
463:                sourceFiles.addElement(file);
464:                this .size++;
465:                return sourceFiles.size() - 1;
466:            }
467:
468:            /**
469:             * Unregister the source file.
470:             * This method is used to implement file inclusion. Each included file
471:             * gets a uniq identifier (which is the index in the array of source
472:             * files).
473:             *
474:             * @return The index of the now registered file.
475:             */
476:            private int unregisterSourceFile(String file) {
477:                if (!sourceFiles.contains(file))
478:                    return -1;
479:                sourceFiles.removeElement(file);
480:                this .size--;
481:                return sourceFiles.size() - 1;
482:            }
483:
484:            /**
485:             * Push a file (and its associated Stream) on the file stack.  THe
486:             * current position in the current file is remembered.
487:             */
488:            private void pushFile(String file, String encoding,
489:                    InputStreamReader reader) throws JasperException,
490:                    FileNotFoundException {
491:
492:                // Register the file
493:                String longName = file;
494:
495:                int fileid = registerSourceFile(longName);
496:
497:                if (fileid == -1) {
498:                    err.jspError("jsp.error.file.already.registered", file);
499:                }
500:
501:                currFileId = fileid;
502:
503:                try {
504:                    CharArrayWriter caw = new CharArrayWriter();
505:                    char buf[] = new char[1024];
506:                    for (int i = 0; (i = reader.read(buf)) != -1;)
507:                        caw.write(buf, 0, i);
508:                    caw.close();
509:                    if (current == null) {
510:                        current = new Mark(this , caw.toCharArray(), fileid,
511:                                getFile(fileid), master, encoding);
512:                    } else {
513:                        current.pushStream(caw.toCharArray(), fileid,
514:                                getFile(fileid), longName, encoding);
515:                    }
516:                } catch (Throwable ex) {
517:                    log.error("Exception parsing file ", ex);
518:                    // Pop state being constructed:
519:                    popFile();
520:                    err.jspError("jsp.error.file.cannot.read", file);
521:                } finally {
522:                    if (reader != null) {
523:                        try {
524:                            reader.close();
525:                        } catch (Exception any) {
526:                        }
527:                    }
528:                }
529:            }
530:
531:            /**
532:             * Pop a file from the file stack.  The field "current" is retored
533:             * to the value to point to the previous files, if any, and is set
534:             * to null otherwise.
535:             * @return true is there is a previous file on the stck.
536:             *         false otherwise.
537:             */
538:            private boolean popFile() throws JasperException {
539:
540:                // Is stack created ? (will happen if the Jsp file we're looking at is
541:                // missing.
542:                if (current == null || currFileId < 0) {
543:                    return false;
544:                }
545:
546:                // Restore parser state:
547:                String fName = getFile(currFileId);
548:                currFileId = unregisterSourceFile(fName);
549:                if (currFileId < -1) {
550:                    err.jspError("jsp.error.file.not.registered", fName);
551:                }
552:
553:                Mark previous = current.popStream();
554:                if (previous != null) {
555:                    master = current.baseDir;
556:                    current = previous;
557:                    return true;
558:                }
559:                // Note that although the current file is undefined here, "current"
560:                // is not set to null just for convience, for it maybe used to
561:                // set the current (undefined) position.
562:                return false;
563:            }
564:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.