~ubuntu-branches/ubuntu/trusty/tomcat6/trusty

« back to all changes in this revision

Viewing changes to java/org/apache/jasper/compiler/ELParser.java

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg
  • Date: 2014-02-17 00:02:00 UTC
  • mfrom: (1.2.10)
  • Revision ID: package-import@ubuntu.com-20140217000200-qs6ki7bhqnfhkas7
Tags: 6.0.39-1
* Team upload.
* New upstream release.
  - Refreshed the patches
* Standards-Version updated to 3.9.5 (no changes)
* Switch to debhelper level 9
* Use XZ compression for the upstream tarball
* Use canonical URL for the Vcs-Git field

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
package org.apache.jasper.compiler;
19
19
 
 
20
import org.apache.jasper.JasperException;
 
21
import org.apache.jasper.compiler.ELNode.ELText;
 
22
import org.apache.jasper.compiler.ELNode.Function;
 
23
import org.apache.jasper.compiler.ELNode.Root;
 
24
import org.apache.jasper.compiler.ELNode.Text;
 
25
 
20
26
/**
21
27
 * This class implements a parser for EL expressions.
22
28
 * 
31
37
public class ELParser {
32
38
 
33
39
    private Token curToken; // current token
34
 
 
35
 
    private ELNode.Nodes expr;
 
40
    private String whiteSpace = "";
 
41
    
 
42
    private final ELNode.Nodes expr;
36
43
 
37
44
    private ELNode.Nodes ELexpr;
38
45
 
39
46
    private int index; // Current index of the expression
40
47
 
41
 
    private String expression; // The EL expression
 
48
    private final String expression; // The EL expression
42
49
    
43
50
    private char type;
44
51
 
45
 
    private boolean escapeBS; // is '\' an escape char in text outside EL?
46
 
 
47
52
    private final boolean isDeferredSyntaxAllowedAsLiteral;
48
53
 
49
54
    private static final String reservedWords[] = { "and", "div", "empty",
85
90
    }
86
91
 
87
92
    /**
88
 
     * Parse an EL expression string '${...}'
89
 
     * 
90
 
     * @return An ELNode.Nodes representing the EL expression TODO: Currently
91
 
     *         only parsed into functions and text strings. This should be
92
 
     *         rewritten for a full parser.
 
93
     * Parse an EL expression string '${...}'. Currently only separates the EL
 
94
     * into functions and everything else.
 
95
     * 
 
96
     * @return An ELNode.Nodes representing the EL expression
 
97
     * 
 
98
     * Note: This can not be refactored to use the standard EL implementation as
 
99
     *       the EL API does not provide the level of access required to the
 
100
     *       parsed expression.
93
101
     */
94
102
    private ELNode.Nodes parseEL() {
95
103
 
96
 
        StringBuffer buf = new StringBuffer();
 
104
        StringBuilder buf = new StringBuilder();
97
105
        ELexpr = new ELNode.Nodes();
 
106
        curToken = null;
98
107
        while (hasNext()) {
99
108
            curToken = nextToken();
100
109
            if (curToken instanceof Char) {
101
110
                if (curToken.toChar() == '}') {
102
111
                    break;
103
112
                }
104
 
                buf.append(curToken.toChar());
 
113
                buf.append(curToken.toString());
105
114
            } else {
106
115
                // Output whatever is in buffer
107
116
                if (buf.length() > 0) {
108
117
                    ELexpr.add(new ELNode.ELText(buf.toString()));
 
118
                    buf.setLength(0);
109
119
                }
110
120
                if (!parseFunction()) {
111
121
                    ELexpr.add(new ELNode.ELText(curToken.toString()));
112
122
                }
113
123
            }
114
124
        }
 
125
        if (curToken != null) {
 
126
            buf.append(curToken.getWhiteSpace());
 
127
        }
115
128
        if (buf.length() > 0) {
116
129
            ELexpr.add(new ELNode.ELText(buf.toString()));
117
130
        }
125
138
     * arguments
126
139
     */
127
140
    private boolean parseFunction() {
128
 
        if (!(curToken instanceof Id) || isELReserved(curToken.toString())) {
 
141
        if (!(curToken instanceof Id) || isELReserved(curToken.toTrimmedString())) {
129
142
            return false;
130
143
        }
131
144
        String s1 = null; // Function prefix
132
 
        String s2 = curToken.toString(); // Function name
133
 
        int mark = getIndex();
 
145
        String s2 = curToken.toTrimmedString(); // Function name
 
146
        int start = index - curToken.toString().length();
 
147
        Token original = curToken;
134
148
        if (hasNext()) {
135
 
            Token t = nextToken();
136
 
            if (t.toChar() == ':') {
 
149
            int mark = getIndex() - whiteSpace.length();
 
150
            curToken = nextToken();
 
151
            if (curToken.toChar() == ':') {
137
152
                if (hasNext()) {
138
153
                    Token t2 = nextToken();
139
154
                    if (t2 instanceof Id) {
140
155
                        s1 = s2;
141
 
                        s2 = t2.toString();
 
156
                        s2 = t2.toTrimmedString();
142
157
                        if (hasNext()) {
143
 
                            t = nextToken();
 
158
                            curToken = nextToken();
144
159
                        }
145
160
                    }
146
161
                }
147
162
            }
148
 
            if (t.toChar() == '(') {
149
 
                ELexpr.add(new ELNode.Function(s1, s2));
 
163
            if (curToken.toChar() == '(') {
 
164
                ELexpr.add(new ELNode.Function(s1, s2, expression.substring(start, index - 1)));
150
165
                return true;
151
166
            }
 
167
            curToken = original;
 
168
            setIndex(mark);
152
169
        }
153
 
        setIndex(mark);
154
170
        return false;
155
171
    }
156
172
 
183
199
     */
184
200
    private String skipUntilEL() {
185
201
        char prev = 0;
186
 
        StringBuffer buf = new StringBuffer();
 
202
        StringBuilder buf = new StringBuilder();
187
203
        while (hasNextChar()) {
188
204
            char ch = nextChar();
189
205
            if (prev == '\\') {
190
206
                prev = 0;
191
207
                if (ch == '\\') {
192
208
                    buf.append('\\');
193
 
                    if (!escapeBS)
194
 
                        prev = '\\';
 
209
                    prev = '\\';
195
210
                } else if (ch == '$'
196
211
                        || (!isDeferredSyntaxAllowedAsLiteral && ch == '#')) {
197
212
                    buf.append(ch);
229
244
        return hasNextChar();
230
245
    }
231
246
 
 
247
    private String getAndResetWhiteSpace() {
 
248
        String result = whiteSpace;
 
249
        whiteSpace = "";
 
250
        return result;
 
251
    }
 
252
    
232
253
    /*
 
254
     * Implementation note: This method assumes that it is always preceded by a
 
255
     * call to hasNext() in order for whitespace handling to be correct.
 
256
     *
233
257
     * @return The next token in the EL expression buffer.
234
258
     */
235
259
    private Token nextToken() {
236
 
        skipSpaces();
237
260
        if (hasNextChar()) {
238
261
            char ch = nextChar();
239
262
            if (Character.isJavaIdentifierStart(ch)) {
240
 
                StringBuffer buf = new StringBuffer();
241
 
                buf.append(ch);
242
 
                while ((ch = peekChar()) != -1
243
 
                        && Character.isJavaIdentifierPart(ch)) {
244
 
                    buf.append(ch);
 
263
                int start = index - 1;
 
264
                while (index < expression.length() &&
 
265
                        Character.isJavaIdentifierPart(
 
266
                                ch = expression.charAt(index))) {
245
267
                    nextChar();
246
268
                }
247
 
                return new Id(buf.toString());
 
269
                return new Id(getAndResetWhiteSpace(), expression.substring(start, index));
248
270
            }
249
271
 
250
272
            if (ch == '\'' || ch == '"') {
251
273
                return parseQuotedChars(ch);
252
274
            } else {
253
275
                // For now...
254
 
                return new Char(ch);
 
276
                return new Char(getAndResetWhiteSpace(), ch);
255
277
            }
256
278
        }
257
279
        return null;
262
284
     * '\\', and ('\"', or "\'")
263
285
     */
264
286
    private Token parseQuotedChars(char quote) {
265
 
        StringBuffer buf = new StringBuffer();
 
287
        StringBuilder buf = new StringBuilder();
266
288
        buf.append(quote);
267
289
        while (hasNextChar()) {
268
290
            char ch = nextChar();
279
301
                buf.append(ch);
280
302
            }
281
303
        }
282
 
        return new QuotedString(buf.toString());
 
304
        return new QuotedString(getAndResetWhiteSpace(), buf.toString());
283
305
    }
284
306
 
285
307
    /*
288
310
     */
289
311
 
290
312
    private void skipSpaces() {
 
313
        int start = index;
291
314
        while (hasNextChar()) {
292
 
            if (expression.charAt(index) > ' ')
 
315
            char c = expression.charAt(index);
 
316
            if (c > ' ')
293
317
                break;
294
318
            index++;
295
319
        }
 
320
        whiteSpace = expression.substring(start, index);
296
321
    }
297
322
 
298
323
    private boolean hasNextChar() {
306
331
        return expression.charAt(index++);
307
332
    }
308
333
 
309
 
    private char peekChar() {
310
 
        if (index >= expression.length()) {
311
 
            return (char) -1;
312
 
        }
313
 
        return expression.charAt(index);
314
 
    }
315
 
 
316
334
    private int getIndex() {
317
335
        return index;
318
336
    }
326
344
     */
327
345
    private static class Token {
328
346
 
 
347
        protected final String whiteSpace;
 
348
 
 
349
        Token(String whiteSpace) {
 
350
            this.whiteSpace = whiteSpace;
 
351
        }
 
352
        
329
353
        char toChar() {
330
354
            return 0;
331
355
        }
332
356
 
 
357
        @Override
333
358
        public String toString() {
 
359
            return whiteSpace;
 
360
        }
 
361
        
 
362
        String toTrimmedString() {
334
363
            return "";
335
364
        }
 
365
        
 
366
        String getWhiteSpace() {
 
367
            return whiteSpace;
 
368
        }
336
369
    }
337
370
 
338
371
    /*
341
374
    private static class Id extends Token {
342
375
        String id;
343
376
 
344
 
        Id(String id) {
 
377
        Id(String whiteSpace, String id) {
 
378
            super(whiteSpace);
345
379
            this.id = id;
346
380
        }
347
381
 
 
382
        @Override
348
383
        public String toString() {
 
384
            return whiteSpace + id;
 
385
        }
 
386
 
 
387
        @Override
 
388
        String toTrimmedString() {
349
389
            return id;
350
390
        }
351
391
    }
357
397
 
358
398
        private char ch;
359
399
 
360
 
        Char(char ch) {
 
400
        Char(String whiteSpace, char ch) {
 
401
            super(whiteSpace);
361
402
            this.ch = ch;
362
403
        }
363
404
 
 
405
        @Override
364
406
        char toChar() {
365
407
            return ch;
366
408
        }
367
409
 
 
410
        @Override
368
411
        public String toString() {
369
 
            return (new Character(ch)).toString();
 
412
            return whiteSpace + ch;
 
413
        }
 
414
 
 
415
        @Override
 
416
        String toTrimmedString() {
 
417
            return "" + ch;
370
418
        }
371
419
    }
372
420
 
377
425
 
378
426
        private String value;
379
427
 
380
 
        QuotedString(String v) {
 
428
        QuotedString(String whiteSpace, String v) {
 
429
            super(whiteSpace);
381
430
            this.value = v;
382
431
        }
383
432
 
 
433
        @Override
384
434
        public String toString() {
 
435
            return whiteSpace + value;
 
436
        }
 
437
 
 
438
        @Override
 
439
        String toTrimmedString() {
385
440
            return value;
386
441
        }
387
442
    }
389
444
    public char getType() {
390
445
        return type;
391
446
    }
 
447
 
 
448
 
 
449
    protected static class TextBuilder extends ELNode.Visitor {
 
450
 
 
451
        protected StringBuilder output = new StringBuilder();
 
452
 
 
453
        public String getText() {
 
454
            return output.toString();
 
455
        }
 
456
 
 
457
        @Override
 
458
        public void visit(Root n) throws JasperException {
 
459
            output.append(n.getType());
 
460
            output.append('{');
 
461
            n.getExpression().visit(this);
 
462
            output.append('}');
 
463
        }
 
464
 
 
465
        @Override
 
466
        public void visit(Function n) throws JasperException {
 
467
            output.append(n.getOriginalText());
 
468
            output.append('(');
 
469
        }
 
470
 
 
471
        @Override
 
472
        public void visit(Text n) throws JasperException {
 
473
            output.append(n.getText());
 
474
        }
 
475
 
 
476
        @Override
 
477
        public void visit(ELText n) throws JasperException {
 
478
            output.append(n.getText());
 
479
        }
 
480
    }
392
481
}