/** * * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * **/ package lucee.runtime.helpers; import java.io.InputStream; import java.util.Stack; import lucee.commons.io.IOUtil; import lucee.commons.io.res.Resource; import lucee.runtime.PageContext; import lucee.runtime.engine.ThreadLocalPageContext; import lucee.runtime.exp.PageException; import lucee.runtime.exp.PageRuntimeException; import lucee.runtime.op.Caster; import lucee.runtime.text.xml.XMLUtil; import lucee.runtime.type.Struct; import lucee.runtime.type.StructImpl; import lucee.runtime.type.UDF; import lucee.runtime.type.util.ArrayUtil; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; /** * Sax Parse with callback to CFC Methods */ public final class XMLEventParser extends DefaultHandler { private UDF startDocument; private UDF startElement; private UDF body; private UDF endElement; private UDF endDocument; private UDF error; private Stack<StringBuilder> bodies=new Stack<StringBuilder>(); private PageContext pc; private Struct att; /** * Field <code>DEFAULT_SAX_PARSER</code> */ public final static String DEFAULT_SAX_PARSER="org.apache.xerces.parsers.SAXParser"; /** * constructor of the class * @param pc * @param startDocument * @param startElement * @param body * @param endElement * @param endDocument * @param error */ public XMLEventParser( PageContext pc, UDF startDocument, UDF startElement, UDF body, UDF endElement, UDF endDocument, UDF error) { this.pc=pc; this.startDocument=startDocument; this.startElement=startElement; this.body=body; this.endElement=endElement; this.endDocument=endDocument; this.error=error; } /** * start execution of the parser * @param xmlFile * @throws PageException */ public void start(Resource xmlFile) throws PageException { start(xmlFile,DEFAULT_SAX_PARSER); } /** * start execution of the parser * @param xmlFile * @param saxParserCass * @throws PageException */ public void start(Resource xmlFile,String saxParserCass) throws PageException { InputStream is=null; try { XMLReader xmlReader = XMLUtil.createXMLReader(saxParserCass); xmlReader.setContentHandler(this); xmlReader.setErrorHandler(this); xmlReader.parse(new InputSource(is=IOUtil.toBufferedInputStream(xmlFile.getInputStream()))); } catch (Exception e) { throw Caster.toPageException(e); } finally { IOUtil.closeEL(is); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { bodies.peek().append(ch,start,length); } @Override public void error(SAXParseException e) throws SAXException { error(Caster.toPageException(e)); } @Override public void fatalError(SAXParseException e) throws SAXException { error(Caster.toPageException(e)); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { bodies.add(new StringBuilder()); att = toStruct(attributes); call(startElement,new Object[]{uri,localName,qName,att}); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { call(body,new Object[]{bodies.pop().toString()}); call(endElement,new Object[]{uri,localName,qName,att}); } @Override public void startDocument() throws SAXException { call(startDocument,ArrayUtil.OBJECT_EMPTY); } @Override public void endDocument() throws SAXException { call(endDocument,ArrayUtil.OBJECT_EMPTY); } /** * call a user defined function * @param udf * @param arguments */ private void call(UDF udf, Object[] arguments) { try { udf.call(pc,arguments,false); } catch (PageException pe) { error(pe); } } /** * call back error function if a error occour * @param pe */ private void error(PageException pe) { if(error==null) throw new PageRuntimeException(pe); try { pc=ThreadLocalPageContext.get(pc); error.call(pc,new Object[]{pe.getCatchBlock(pc.getConfig())},false); } catch (PageException e) {} } /** * cast a Attributes object to a Struct * @param att * @return Attributes as Struct */ private Struct toStruct(Attributes att) { int len=att.getLength(); Struct sct=new StructImpl(); for(int i=0;i<len;i++) { sct.setEL(att.getQName(i),att.getValue(i)); } return sct; } }