1 19 20 package org.netbeans.modules.web.jspparser; 21 22 import java.io.BufferedReader ; 23 import java.io.ByteArrayInputStream ; 24 import java.io.IOException ; 25 import java.io.InputStream ; 26 import java.io.InputStreamReader ; 27 import java.io.StringReader ; 28 import java.util.ArrayList ; 29 import java.util.List ; 30 import javax.xml.parsers.ParserConfigurationException ; 31 import javax.xml.parsers.SAXParser ; 32 import javax.xml.parsers.SAXParserFactory ; 33 import org.netbeans.modules.web.jsps.parserapi.JspParserAPI; 34 import org.netbeans.modules.web.jsps.parserapi.JspParserAPI.WebModule; 35 import org.openide.filesystems.FileObject; 36 import org.xml.sax.Attributes ; 37 import org.xml.sax.InputSource ; 38 import org.xml.sax.Locator ; 39 import org.xml.sax.SAXException ; 40 import org.xml.sax.helpers.DefaultHandler ; 41 42 import org.netbeans.modules.xml.api.EncodingUtil; 43 44 66 public class FastOpenInfoParser { 67 68 static final boolean debug = Boolean.getBoolean("netbeans.debug.fastopeninfo"); 70 static FastOpenInfoParser get(WebModule wm) { 71 return new FastOpenInfoParser(wm); 72 } 73 74 private WebModule wm; 75 76 77 private FastOpenInfoParser(WebModule wm) { 78 this.wm = wm; 79 } 80 81 public JspParserAPI.JspOpenInfo getJspOpenInfo(FileObject fo, boolean useEditor) { 82 long a = System.currentTimeMillis(); 83 try { 84 if(wm != null && wm.getDocumentBase() != null && useEditor) return null; 86 if(wm != null) { 88 FileObject documentBase = wm.getDocumentBase(); 90 if(documentBase != null) { 91 FileObject dd = documentBase.getFileObject("WEB-INF/web.xml"); 93 if(dd != null) { 95 DDParseInfo ddParseInfo = parse(new InputSource (dd.getInputStream())); 98 if(ddParseInfo.definesEncoding || ddParseInfo.marksXMLDocuments) return null; 100 } 101 } 102 } 103 104 String enc = null; 105 106 109 byte[] buffer = new byte[8192*4]; 111 InputStream _is = fo.getInputStream(); 112 int readed = _is.read(buffer); 113 InputStream is = new ByteArrayInputStream (buffer,0,readed); 114 _is.close(); 115 116 if(isXMLSyntax(fo)) { 117 enc = EncodingUtil.detectEncoding(is); 119 } else { 120 enc = parseEncodingFromFile(is); 123 } 124 125 if(debug) System.out.println("[fast open parser] detected " + enc + " encoding."); 126 return enc == null ? null : new JspParserAPI.JspOpenInfo(isXMLSyntax(fo), enc); 127 128 } catch(IOException e) { 129 } catch(SAXException se) { 131 } catch(ParserConfigurationException pce) { 133 } finally { 135 if(debug) System.out.println("[fast open parser] taken " + (System.currentTimeMillis() - a) + "ms."); 136 } 137 return null; 138 } 139 140 private static String parseEncodingFromFile(InputStream is) throws IOException { 141 InputStreamReader isr = new InputStreamReader (is); char[] buffer = new char[8192]; 144 int readed = isr.read(buffer); 145 isr.close(); 146 147 return parseJspText(buffer, readed); 148 } 149 150 private static boolean isXMLSyntax(FileObject fo) { 151 String ext = fo.getExt(); 152 if(ext != null && ("jspx".equalsIgnoreCase(ext) || "tagx".equalsIgnoreCase(ext))) return true; 153 else return false; 154 } 155 156 private static final String PAGE = "page"; 158 private static final String ENCODING = "pageEncoding"; 159 private static final String CONTENTYPE = "contentType"; 160 private static final String CHARSET = "charset="; 161 162 private static final int P_INIT = 0; 163 private static final int P_LT = 1; private static final int P_LT_PER = 2; private static final int P_LT_PER_ATS = 3; private static final int P_PD = 4; private static final int P_APER = 5; 169 private static final int P_ENC = 7; private static final int P_ENC_EQ = 8; private static final int P_ENC_EQ_VAL = 9; 173 private static final int P_CT = 11; private static final int P_CT_EQ = 12; private static final int P_CT_EQ_VAL = 13; private static final int P_CT_VAL_CHS = 14; 178 private static String parseJspText(char[] buffer, int len) { 179 String contentType = null; 180 181 int state = P_INIT; 182 int i = 0; 183 int pos = -1; 184 while(i < len) { 185 char c = buffer[i]; 186 187 switch(state) { 188 case P_INIT: 189 if(c == '<') state = P_LT; 190 i++; 191 break; 192 case P_LT: 193 switch(c) { 194 case '%' : 195 state = P_LT_PER; 196 break; 197 default: state = P_INIT; 198 } 199 i++; 200 break; 201 202 case P_LT_PER: 203 switch(c) { 204 case '@': 205 state = P_LT_PER_ATS; 206 break; 207 default: state = P_INIT; 208 } 209 i++; 210 break; 211 case P_LT_PER_ATS: 212 if(c == ' ' || c == '\t') { 213 i++; 214 break; 215 } else if(prescanFor(buffer, i, PAGE)) { 216 state = P_PD; 217 i = i + PAGE.length(); 218 break; 219 } 220 state = P_INIT; 221 i++; 222 break; 223 case P_PD: 224 if(prescanFor(buffer, i, ENCODING)) { 225 state = P_ENC; 226 i = i + ENCODING.length(); 227 break; 228 } else if(prescanFor(buffer, i, CONTENTYPE)) { 229 state = P_CT; 230 i = i + CONTENTYPE.length(); 231 break; 232 } else if(c == '%') state = P_APER; 233 i++; 234 break; 235 case P_APER: 236 if(c == '>') state = P_INIT; 237 else state = P_PD; 238 i++; 239 break; 240 case P_ENC: 241 switch(c) { 242 case ' ': 243 case '\t': 244 ; 245 break; 246 case '=': 247 state = P_ENC_EQ; 248 break; 249 case '%': 250 state = P_APER; 251 break; 252 default: 253 state = P_PD; 254 } 255 i++; 256 break; 257 case P_ENC_EQ: 258 switch(c) { 259 case ' ': 260 case '\t': 261 break; 262 case '"': 263 state = P_ENC_EQ_VAL; 264 pos = i + 1; 265 break; 266 case '%': 267 state = P_APER; 268 break; 269 default: 270 state = P_PD; 271 } 272 i++; 273 break; 274 case P_ENC_EQ_VAL: 275 switch(c) { 276 case '"': return new String (buffer, pos, i - pos); default: 278 } 279 i++; 280 break; 281 282 case P_CT: 283 switch(c) { 284 case ' ': 285 case '\t': 286 break; 287 case '=': 288 state = P_CT_EQ; 289 break; 290 case '%': 291 state = P_APER; 292 break; 293 default: 294 state = P_PD; 295 } 296 i++; 297 break; 298 case P_CT_EQ: 299 switch(c) { 300 case ' ': 301 case '\t': 302 break; 303 case '"': 304 state = P_CT_EQ_VAL; 305 break; 306 case '%': 307 state = P_APER; 308 break; 309 default: 310 state = P_PD; 311 } 312 i++; 313 break; 314 case P_CT_EQ_VAL: 315 if(prescanFor(buffer, i, CHARSET)) { 316 state = P_CT_VAL_CHS; 317 i = i + CHARSET.length(); 318 pos = i; 319 break; 320 } else if(c == '"') { 321 state = P_PD; 322 break; 323 } 324 i++; 325 break; 326 case P_CT_VAL_CHS: 327 switch(c) { 328 case '"': 329 contentType = new String (buffer, pos, i - pos); state = P_PD; 331 break; 332 default: 333 } 334 i++; 335 break; 336 337 } } 339 340 return contentType; 342 } 343 344 345 private static boolean prescanFor(char[] buffer, int position, String text) { 346 if((buffer.length - position) < text.length()) return false; for(int i = 0; i < text.length(); i++) { 348 if(buffer[position+i] != text.charAt(i)) return false; 349 } 350 return true; 351 } 352 353 354 static final String JSP_PROPERTY_GROUP = "jsp-property-group"; 355 static final String PAGE_ENCODING = "page-encoding"; 356 static final String IS_XML = "is-xml"; 357 358 360 private static DDParseInfo parse(InputSource src) throws IOException , SAXException , ParserConfigurationException { 361 SAXParserFactory factory = SAXParserFactory.newInstance(); 362 factory.setValidating(false); 363 SAXParser parser = factory.newSAXParser(); 364 final DDParseInfo ddParseInfo = new DDParseInfo(); 365 366 class Handler extends DefaultHandler { 367 private boolean inJspPropertyGroup = false; 368 public void startElement(String uri, String localname, String qname, Attributes attr) throws SAXException { 369 String tagName = qname.toLowerCase(); 370 if(JSP_PROPERTY_GROUP.equals(tagName)) inJspPropertyGroup = true; 371 if(inJspPropertyGroup) { 372 if(PAGE_ENCODING.equals(tagName)) ddParseInfo.definesEncoding = true; 373 if(IS_XML.equals(tagName)) ddParseInfo.marksXMLDocuments = true; 374 } 375 } 376 public void endElement(String uri, String localname, String qname) throws SAXException { 377 String tagName = qname.toLowerCase(); 378 if(JSP_PROPERTY_GROUP.equals(tagName)) inJspPropertyGroup = false; 379 } 380 public InputSource resolveEntity (String publicId, String systemId) { 381 return new InputSource (new StringReader ("")); } 383 } 384 parser.parse(src, new Handler ()); 385 return ddParseInfo; 386 } 387 388 private static final class DDParseInfo { 389 public boolean definesEncoding, marksXMLDocuments; 390 public DDParseInfo() {} 391 } 392 393 } 394 | Popular Tags |