Quadcap Embeddable Server

com/quadcap/http/servlets/jsp/JspParser.java

Go to the documentation of this file.
00001 package com.quadcap.http.servlets.jsp; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 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 * JSP Parser class that fires SAX events. 00060 * 00061 * @author Stan Bailes 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 //System.out.println("[" + ((char)c) + "] [" + state + "] <" + tag.toString() + ">"); 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: // seen '<' 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: // seen '<%' 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: // in <% %> 00226 if (c == '%') state = 7; 00227 else tag.write(c); 00228 break; 00229 case 4: // seen <\ 00230 data.write('<'); 00231 data.write(c); 00232 state = 0; 00233 break; 00234 case 51: // collect directive name 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: // collect tag name 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: // collect attributes 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: // in <%, seen % 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: // seen </ 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: // in <tag, seen / 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: // in attriblist, seen name= 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: // in <%@, seen % 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: // in attriblist, seen name=" 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: // in attriblist, seen name=' 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: // in attriblist, seen name=c 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: // in attriblist, seen name=dfdf/ 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 }