1 14 15 package com.sun.facelets.compiler; 16 17 import java.io.BufferedInputStream ; 18 import java.io.IOException ; 19 import java.io.InputStream ; 20 import java.net.URL ; 21 import java.util.regex.Matcher ; 22 import java.util.regex.Pattern ; 23 24 import javax.el.ELException; 25 import javax.faces.FacesException; 26 import javax.xml.parsers.ParserConfigurationException ; 27 import javax.xml.parsers.SAXParser ; 28 import javax.xml.parsers.SAXParserFactory ; 29 30 import org.xml.sax.Attributes ; 31 import org.xml.sax.InputSource ; 32 import org.xml.sax.Locator ; 33 import org.xml.sax.SAXException ; 34 import org.xml.sax.SAXParseException ; 35 import org.xml.sax.XMLReader ; 36 import org.xml.sax.ext.LexicalHandler ; 37 import org.xml.sax.helpers.DefaultHandler ; 38 39 import com.sun.facelets.FaceletException; 40 import com.sun.facelets.FaceletHandler; 41 import com.sun.facelets.tag.Location; 42 import com.sun.facelets.tag.Tag; 43 import com.sun.facelets.tag.TagAttribute; 44 import com.sun.facelets.tag.TagAttributes; 45 46 54 public final class SAXCompiler extends Compiler { 55 56 private final static Pattern XmlDeclaration = Pattern.compile("^<\\?xml.+?version=['\"](.+?)['\"](.+?encoding=['\"]((.+?))['\"])?.*?\\?>"); 57 58 private static class CompilationHandler extends DefaultHandler implements 59 LexicalHandler { 60 61 private final String alias; 62 63 private boolean inDocument = false; 64 65 private boolean trimDoctypeDeclaration = false; 66 67 private Locator locator; 68 69 private final CompilationManager unit; 70 71 public CompilationHandler(CompilationManager unit, String alias, boolean trimDoctypeDeclaration) { 72 this.unit = unit; 73 this.alias = alias; 74 this.trimDoctypeDeclaration = trimDoctypeDeclaration; 75 } 76 77 public void characters(char[] ch, int start, int length) 78 throws SAXException { 79 if (this.inDocument) { 80 this.unit.writeText(new String (ch, start, length)); 81 } 82 } 83 84 public void comment(char[] ch, int start, int length) 85 throws SAXException { 86 if (this.inDocument) { 87 this.unit.writeComment(new String (ch, start, length)); 88 } 89 } 90 91 protected TagAttributes createAttributes(Attributes attrs) { 92 int len = attrs.getLength(); 93 TagAttribute[] ta = new TagAttribute[len]; 94 for (int i = 0; i < len; i++) { 95 ta[i] = new TagAttribute(this.createLocation(), 96 attrs.getURI(i), attrs.getLocalName(i), attrs 97 .getQName(i), attrs.getValue(i)); 98 } 99 return new TagAttributes(ta); 100 } 101 102 protected Location createLocation() { 103 return new Location(this.alias, this.locator.getLineNumber(), 104 this.locator.getColumnNumber()); 105 } 106 107 public void endCDATA() throws SAXException { 108 if (this.inDocument) { 109 this.unit.writeInstruction("]]>"); 110 } 111 } 112 113 public void endDocument() throws SAXException { 114 super.endDocument(); 115 } 116 117 public void endDTD() throws SAXException { 118 this.inDocument = true; 119 } 120 121 public void endElement(String uri, String localName, String qName) 122 throws SAXException { 123 this.unit.popTag(); 124 } 125 126 public void endEntity(String name) throws SAXException { 127 } 128 129 public void endPrefixMapping(String prefix) throws SAXException { 130 this.unit.popNamespace(prefix); 131 } 132 133 public void fatalError(SAXParseException e) throws SAXException { 134 if (this.locator != null) { 135 throw new SAXException ("Error Traced[line: " 136 + this.locator.getLineNumber() + "] " + e.getMessage()); 137 } else { 138 throw e; 139 } 140 } 141 142 public void ignorableWhitespace(char[] ch, int start, int length) 143 throws SAXException { 144 if (this.inDocument) { 145 this.unit.writeWhitespace(new String (ch, start, length)); 146 } 147 } 148 149 public InputSource resolveEntity(String publicId, String systemId) 150 throws SAXException { 151 String dtd = "default.dtd"; 152 157 URL url = Thread.currentThread().getContextClassLoader() 158 .getResource(dtd); 159 return new InputSource (url.toString()); 160 } 161 162 public void setDocumentLocator(Locator locator) { 163 this.locator = locator; 164 } 165 166 public void startCDATA() throws SAXException { 167 if (this.inDocument) { 168 this.unit.writeInstruction("<![CDATA["); 169 } 170 } 171 172 public void startDocument() throws SAXException { 173 this.inDocument = true; 174 } 175 176 public void startDTD(String name, String publicId, String systemId) 177 throws SAXException { 178 if (this.inDocument) { 179 if( !trimDoctypeDeclaration ) { 180 StringBuffer sb = new StringBuffer (64); 181 sb.append("<!DOCTYPE ").append(name); 182 if (publicId != null) { 183 sb.append(" PUBLIC \"").append(publicId).append("\""); 184 if (systemId != null) { 185 sb.append(" \"").append(systemId).append("\""); 186 } 187 } else if (systemId != null) { 188 sb.append(" SYSTEM \"").append(systemId).append("\""); 189 } 190 sb.append(" >\n"); 191 this.unit.writeInstruction(sb.toString()); 192 } 193 } 194 this.inDocument = false; 195 } 196 197 public void startElement(String uri, String localName, String qName, 198 Attributes attributes) throws SAXException { 199 this.unit.pushTag(new Tag(this.createLocation(), uri, localName, 200 qName, this.createAttributes(attributes))); 201 } 202 203 public void startEntity(String name) throws SAXException { 204 } 205 206 public void startPrefixMapping(String prefix, String uri) 207 throws SAXException { 208 this.unit.pushNamespace(prefix, uri); 209 } 210 211 public void processingInstruction(String target, String data) 212 throws SAXException { 213 if (this.inDocument) { 214 StringBuffer sb = new StringBuffer (64); 215 sb.append("<?").append(target).append(' ').append(data).append( 216 "?>\n"); 217 this.unit.writeInstruction(sb.toString()); 218 } 219 } 220 } 221 222 public SAXCompiler() { 223 super(); 224 } 225 226 public FaceletHandler doCompile(URL src, String alias) throws IOException , 227 FaceletException, ELException, FacesException { 228 CompilationManager mngr = null; 229 InputStream is = null; 230 String encoding = "UTF-8"; 231 try { 232 is = new BufferedInputStream (src.openStream(), 1024); 233 mngr = new CompilationManager(alias, this); 234 encoding = writeXmlDecl(is, mngr, isTrimmingXmlDeclarations()); 235 CompilationHandler handler = new CompilationHandler(mngr, alias, isTrimmingDoctypeDeclarations()); 236 SAXParser parser = this.createSAXParser(handler); 237 parser.parse(is, handler); 238 } catch (SAXException e) { 239 throw new FaceletException("Error Parsing " + alias + ": " 240 + e.getMessage(), e.getCause()); 241 } catch (ParserConfigurationException e) { 242 throw new FaceletException("Error Configuring Parser " + alias 243 + ": " + e.getMessage(), e.getCause()); 244 } finally { 245 if (is != null) { 246 is.close(); 247 } 248 } 249 return new EncodingHandler(mngr.createFaceletHandler(), encoding); 250 } 251 252 protected static final String writeXmlDecl(InputStream is, CompilationManager mngr, boolean trimXmlDeclaration) 253 throws IOException { 254 is.mark(128); 255 String encoding = "UTF-8"; 256 try { 257 byte[] b = new byte[128]; 258 if (is.read(b) > 0) { 259 String r = new String (b); 260 Matcher m = XmlDeclaration.matcher(r); 261 if (m.find()) { 262 if( !trimXmlDeclaration ) { 263 mngr.writeInstruction(m.group(0) + "\n"); 264 } 265 if (m.group(3) != null) { 266 encoding = m.group(3); 267 } 268 } 269 } 270 } finally { 271 is.reset(); 272 } 273 return encoding; 274 } 275 276 private final SAXParser createSAXParser(CompilationHandler handler) 277 throws SAXException , ParserConfigurationException { 278 SAXParserFactory factory = SAXParserFactory.newInstance(); 279 factory.setNamespaceAware(true); 280 factory.setFeature("http://xml.org/sax/features/namespace-prefixes", 281 true); 282 factory.setFeature("http://xml.org/sax/features/validation", this 283 .isValidating()); 284 factory.setValidating(this.isValidating()); 285 SAXParser parser = factory.newSAXParser(); 286 XMLReader reader = parser.getXMLReader(); 287 reader.setProperty("http://xml.org/sax/properties/lexical-handler", 288 handler); 289 reader.setErrorHandler(handler); 290 reader.setEntityResolver(handler); 291 return parser; 292 } 293 294 } 295 | Popular Tags |