00001
package com.quadcap.http.servlets.jsp;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
import java.io.CharArrayWriter;
00042
import java.io.IOException;
00043
import java.io.Reader;
00044
00045
import org.xml.sax.AttributeList;
00046
import org.xml.sax.DocumentHandler;
00047
import org.xml.sax.DTDHandler;
00048
import org.xml.sax.EntityResolver;
00049
import org.xml.sax.ErrorHandler;
00050
import org.xml.sax.InputSource;
00051
import org.xml.sax.Parser;
00052
import org.xml.sax.SAXException;
00053
00054
import org.xml.sax.helpers.AttributeListImpl;
00055
00056
import com.quadcap.util.collections.ArrayQueue;
00057
00058
00059
00060
00061
00062
00063 public class JspParser implements Parser {
00064 InputSource
in;
00065 Reader
r;
00066 DocumentHandler
docHandler = null;
00067 DTDHandler
dtdHandler = null;
00068 EntityResolver
entityResolver = null;
00069 CharArrayWriter
tag =
new CharArrayWriter();
00070 CharArrayWriter
data =
new CharArrayWriter();
00071 AttributeListImpl
attributes =
new AttributeListImpl();
00072 int tagState = 0;
00073 String
tagName = null;
00074 JspHandler jspHandler = null;
00075 String
nonJspTag = null;
00076 ArrayQueue
inStack = null;
00077
00078 final static int TAG = 1;
00079 final static int DIRECTIVE = 2;
00080 final static int DECLARATION = 3;
00081 final static int SCRIPTLET = 4;
00082 final static int EXPRESSION = 5;
00083
00084 public JspParser() {}
00085
00087
this.in =
in;
00088
this.r =
in.getCharacterStream();
00089
tag.reset();
00090
data.reset();
00091
parse();
00092 }
00093
00094 public void pushInputSource(InputSource in2) {
00095
if (
inStack == null)
inStack =
new ArrayQueue();
00096
inStack.push(
in);
00097
in = in2;
00098
r =
in.getCharacterStream();
00099 }
00100
00101 boolean popInputSource() {
00102
if (
inStack == null ||
inStack.size() == 0)
return false;
00103
in = (InputSource)
inStack.pop();
00104
r =
in.getCharacterStream();
00105
return true;
00106 }
00107
00108 public void setJspHandler(
JspHandler jspHandler) {
00109
this.jspHandler = jspHandler;
00110 }
00111
00112 public void parse(String s) {
00113 }
00114
00115 public void setDocumentHandler(DocumentHandler dh) {
00116
this.docHandler = dh;
00117 }
00118
00119 public void setDTDHandler(DTDHandler dh) {
00120
this.dtdHandler = dh;
00121 }
00122
00123 public void setEntityResolver(EntityResolver er) {
00124
this.entityResolver = er;
00125 }
00126
00127 public EntityResolver
getEntityResolver() {
00128
return entityResolver;
00129 }
00130
00132 }
00133
00134 public void setLocale(java.util.Locale locale) {
00135 }
00136
00138
int state = 0;
00139
int commentState = 0;
00140 String attrName = null;
00141
docHandler.startDocument();
00142
docHandler.startElement(
"jsp:root",
attributes);
00143
while (state >= 0) {
00144
int c =
r.read();
00145
00146
if (c < 0) {
00147
if (
popInputSource())
continue;
00148 state = -1;
00149
break;
00150 }
00151
switch (commentState) {
00152
case 0:
00153
break;
00154
case 1:
00155
if (c ==
'-') commentState = 2;
00156
break;
00157
case 2:
00158
if (c ==
'-') commentState = 3;
00159
else commentState = 1;
00160
break;
00161
case 3:
00162
if (c ==
'>') commentState = 0;
00163
else if (c !=
'-') commentState = 1;
00164 }
00165
00166
switch (state) {
00167
case 0:
00168
if (c ==
'<') {
00169
if (
data.size() > 0) {
00170
docHandler.characters(
data.toCharArray(), 0,
data.size());
00171
data.reset();
00172 }
00173 state = 1;
00174 }
else {
00175
data.write(c);
00176 }
00177
break;
00178
case 1:
00179
switch (c) {
00180
case '%':
00181 state = 2;
00182
break;
00183
case '!':
00184
data.write(
'<');
00185
data.write(
'!');
00186 commentState = 1;
00187 state = 0;
00188
break;
00189
case '\\':
00190 state = 4;
00191
break;
00192
case '/':
00193 state = 8;
00194
break;
00195
default:
00196
tag.write(c);
00197
tagState =
TAG;
00198 state = 5;
00199
break;
00200 }
00201
break;
00202
case 2:
00203
tag.reset();
00204 state = 3;
00205
switch (c) {
00206
case '@':
00207 state = 51;
00208
tagState =
DIRECTIVE;
00209
break;
00210
case '!':
00211
tagState =
DECLARATION;
00212
break;
00213
case '=':
00214
tagState =
EXPRESSION;
00215
break;
00216
case '-':
00217 state = 15;
00218
break;
00219
default:
00220
tag.write(c);
00221
tagState =
SCRIPTLET;
00222
break;
00223 }
00224
break;
00225
case 3:
00226
if (c ==
'%') state = 7;
00227
else tag.write(c);
00228
break;
00229
case 4:
00230
data.write(
'<');
00231
data.write(c);
00232 state = 0;
00233
break;
00234
case 51:
00235
if (c !=
' ') {
00236
tag.write(c);
00237 state = 52;
00238 }
00239
break;
00240
case 52:
00241
if (c ==
' ') {
00242
tagName =
tag.toString();
00243
tag.reset();
00244 state = 6;
00245 }
else {
00246
tag.write(c);
00247 }
00248
break;
00249
case 5:
00250
switch (c) {
00251
case ' ':
00252
tagName =
tag.toString();
00253
tag.reset();
00254 state =
checkTag(6);
00255
break;
00256
case '/':
00257
tagName =
tag.toString();
00258
tag.reset();
00259 state = 9;
00260
break;
00261
case '>':
00262
tagName =
tag.toString();
00263
tag.reset();
00264
docHandler.startElement(
tagName,
attributes);
00265
attributes.clear();
00266 state = 0;
00267
break;
00268
case '<':
00269
tagName =
tag.toString();
00270
tag.reset();
00271
if (checkTag(1) == 0) {
00272
if (
data.size() > 0) {
00273
docHandler.characters(
data.toCharArray(),
00274 0,
data.size());
00275
data.reset();
00276 }
00277 state = 1;
00278 }
00279
break;
00280
default:
00281
tag.write(c);
00282 }
00283
break;
00284
case 6:
00285
switch (c) {
00286
case ' ':
case '\n':
case '\r':
case '\t':
00287
break;
00288
case '/':
00289
if (
tagState ==
TAG) {
00290 state = 9;
00291 }
else {
00292
tag.write(c);
00293 }
00294
break;
00295
case '%':
00296
if (
tagState !=
TAG) {
00297 state = 11;
00298 }
else {
00299
tag.write(c);
00300 }
00301
break;
00302
case '>':
00303
docHandler.startElement(
tagName,
attributes);
00304
attributes.clear();
00305 state = 0;
00306
break;
00307
case '=':
00308 attrName =
tag.toString();
00309
tag.reset();
00310 state = 10;
00311
break;
00312
default:
00313
tag.write(c);
00314 }
00315
break;
00316
case 7:
00317
if (c ==
'>') {
00318
doTag();
00319 state = 0;
00320 }
else {
00321
tag.write(
'%');
00322
if (c !=
'%') {
00323
tag.write(c);
00324 state = 3;
00325 }
00326 }
00327
break;
00328
case 8:
00329
if (c ==
'>') {
00330
tagName =
tag.toString();
00331
tag.reset();
00332
if (
nonJspTag != null &&
tagName.equals(
nonJspTag)) {
00333
nonJspTag = null;
00334
data.write(
"</");
00335
data.write(
tagName);
00336
data.write(
'>');
00337 }
else {
00338
docHandler.endElement(
tagName);
00339 }
00340 state = 0;
00341 }
else {
00342
tag.write(c);
00343 }
00344
break;
00345
case 9:
00346
if (c ==
'>') {
00347
docHandler.startElement(
tagName,
attributes);
00348
attributes.clear();
00349
docHandler.endElement(
tagName);
00350 state = 0;
00351 }
else {
00352
tag.write(
'/');
00353
tag.write(c);
00354 state = 6;
00355 }
00356
break;
00357
case 10:
00358
if (c ==
'"') {
00359 state = 12;
00360 }
else if (c ==
'\'') {
00361 state = 121;
00362 }
else {
00363
tag.write(c);
00364 state = 13;
00365 }
00366
break;
00367
case 11:
00368
if (c ==
'>') {
00369
doDirective();
00370 state = 0;
00371 }
else {
00372
tag.write(
'%');
00373
tag.write(c);
00374 state = 6;
00375 }
00376
break;
00377
case 12:
00378
if (c ==
'"') {
00379
attributes.addAttribute(attrName,
"string",
00380
tag.toString());
00381
tag.reset();
00382 state = 6;
00383 }
else {
00384
tag.write(c);
00385 }
00386
break;
00387
case 121:
00388
if (c ==
'\'') {
00389
attributes.addAttribute(attrName,
"string",
00390
tag.toString());
00391
tag.reset();
00392 state = 6;
00393 }
else {
00394
tag.write(c);
00395 }
00396
break;
00397
case 13:
00398
switch (c) {
00399
case ' ':
00400
attributes.addAttribute(attrName,
"string",
00401
tag.toString());
00402
tag.reset();
00403 state = 6;
00404
break;
00405
case '/':
00406 state = 14;
00407
break;
00408
case '>':
00409
attributes.addAttribute(attrName,
"string",
00410
tag.toString());
00411
tag.reset();
00412
docHandler.startElement(
tagName,
attributes);
00413
attributes.clear();
00414 state = 0;
00415
break;
00416
default:
00417
tag.write(c);
00418 }
00419
break;
00420
case 14:
00421
if (c ==
'>') {
00422
attributes.addAttribute(attrName,
"string",
00423
tag.toString());
00424
tag.reset();
00425
docHandler.startElement(
tagName,
attributes);
00426
attributes.clear();
00427 state = 0;
00428 }
else {
00429
tag.write(
'/');
00430
if (c !=
'/') {
00431
tag.write(c);
00432 state = 13;
00433 }
00434 }
00435
break;
00436
case 15:
00437
if (c ==
'-') state = 16;
00438
break;
00439
case 16:
00440
if (c ==
'-') state = 17;
00441
else state = 15;
00442
break;
00443
case 17:
00444
if (c ==
'>') state = 0;
00445
else if (c !=
'-') state = 15;
00446
break;
00447 }
00448 }
00449
docHandler.endElement(
"jsp:root");
00450 }
00451
00452 public int checkTag(
int validState)
throws IOException {
00453
if (
jspHandler.
isValidTag(
tagName)) {
00454
return validState;
00455 }
else {
00456
nonJspTag =
tagName;
00457
data.write(
'<');
00458
data.write(tagName);
00459
data.write(
' ');
00460
return 0;
00461 }
00462 }
00463
00465
switch (
tagState) {
00466
case TAG:
00467
break;
00468
case EXPRESSION:
00469
docHandler.startElement(
"jsp:expression",
attributes);
00470
docHandler.characters(
tag.toCharArray(), 0,
tag.size());
00471
docHandler.endElement(
"jsp:expression");
00472
tag.reset();
00473
attributes.clear();
00474
break;
00475
case DECLARATION:
00476
docHandler.startElement(
"jsp:decl",
attributes);
00477
docHandler.characters(
tag.toCharArray(), 0,
tag.size());
00478
docHandler.endElement(
"jsp:decl");
00479
tag.reset();
00480
attributes.clear();
00481
break;
00482
case SCRIPTLET:
00483
docHandler.startElement(
"jsp:scriptlet",
attributes);
00484
docHandler.characters(
tag.toCharArray(), 0,
tag.size());
00485
docHandler.endElement(
"jsp:scriptlet");
00486
tag.reset();
00487
attributes.clear();
00488
break;
00489 }
00490 }
00491
00493
docHandler.startElement(
"jsp:directive." +
tagName,
attributes);
00494
docHandler.endElement(
"jsp:directive." +
tagName);
00495
attributes.clear();
00496 }
00497 }