001    package railo.runtime.helpers;
002    
003    import java.io.InputStream;
004    
005    import org.xml.sax.Attributes;
006    import org.xml.sax.InputSource;
007    import org.xml.sax.SAXException;
008    import org.xml.sax.SAXParseException;
009    import org.xml.sax.XMLReader;
010    import org.xml.sax.helpers.DefaultHandler;
011    
012    import railo.commons.io.IOUtil;
013    import railo.commons.io.res.Resource;
014    import railo.runtime.PageContext;
015    import railo.runtime.engine.ThreadLocalPageContext;
016    import railo.runtime.exp.PageException;
017    import railo.runtime.op.Caster;
018    import railo.runtime.text.xml.XMLUtil;
019    import railo.runtime.type.Struct;
020    import railo.runtime.type.StructImpl;
021    import railo.runtime.type.UDF;
022    import railo.runtime.type.util.ArrayUtil;
023    
024    
025    
026    /**
027     * Sax Parse with callback to CFC Methods
028     */
029    public final class XMLEventParser extends DefaultHandler {
030            
031            private UDF startDocument;
032            private UDF startElement;
033            private UDF body;
034            private UDF endElement;
035            private UDF endDocument;
036            private UDF error;
037            
038            private StringBuffer sbBody;
039            private PageContext pc;
040            private Struct att;
041            /**
042             * Field <code>DEFAULT_SAX_PARSER</code>
043             */
044            public final static String DEFAULT_SAX_PARSER="org.apache.xerces.parsers.SAXParser";
045            
046            /**
047             * constructor of the class
048             * @param pc
049             * @param startDocument
050             * @param startElement
051             * @param body
052             * @param endElement
053             * @param endDocument
054             * @param error
055             */
056            public XMLEventParser(
057                            PageContext pc,
058                            UDF startDocument,
059                            UDF startElement,
060                            UDF body,
061                            UDF endElement,
062                            UDF endDocument,
063                            UDF error) {
064                    
065                    this.pc=pc;
066                    this.startDocument=startDocument;
067                    this.startElement=startElement;
068                    this.body=body;
069                    this.endElement=endElement;
070                    this.endDocument=endDocument;
071                    this.error=error;
072    
073            }
074    
075            /**
076             * start execution of the parser
077             * @param xmlFile
078             * @throws PageException
079             */
080            public void start(Resource xmlFile) throws PageException {
081                    start(xmlFile,DEFAULT_SAX_PARSER);
082            }
083            
084            /**
085             * start execution of the parser
086             * @param xmlFile
087             * @param saxParserCass
088             * @throws PageException
089             */
090            public void start(Resource xmlFile,String saxParserCass) throws PageException {
091                    InputStream is=null;
092                    try {
093                            XMLReader xmlReader = XMLUtil.createXMLReader(saxParserCass);
094                            xmlReader.setContentHandler(this);
095                            xmlReader.setErrorHandler(this);
096                            xmlReader.parse(new InputSource(is=IOUtil.toBufferedInputStream(xmlFile.getInputStream())));
097                    } catch (Exception e) {
098                            throw Caster.toPageException(e); 
099                    }       
100                    finally {
101                            IOUtil.closeEL(is);
102                    }
103                    
104            }
105    
106            @Override
107            public void characters(char[] ch, int start, int length) throws SAXException {
108                    sbBody.append(ch,start,length);
109            }
110    
111            @Override
112            public void error(SAXParseException e) throws SAXException {
113                    error(Caster.toPageException(e));
114            }
115            @Override
116            public void fatalError(SAXParseException e) throws SAXException {
117                    error(Caster.toPageException(e));
118            }
119            @Override
120            public void startElement(String uri, String localName, String qName,
121                            Attributes attributes) throws SAXException {
122                    sbBody=new StringBuffer();
123                    att = toStruct(attributes);
124                    call(startElement,new Object[]{uri,localName,qName,att});
125            }
126    
127            @Override
128            public void endElement(String uri, String localName, String qName) throws SAXException {
129                    call(body,new Object[]{sbBody.toString()});
130                    call(endElement,new Object[]{uri,localName,qName,att});
131            }
132            
133            @Override
134            public void startDocument() throws SAXException {
135                    call(startDocument,ArrayUtil.OBJECT_EMPTY);
136            }
137            
138            @Override
139            public void endDocument() throws SAXException {
140                    call(endDocument,ArrayUtil.OBJECT_EMPTY);
141            }
142            
143            /**
144             * call a user defined function
145             * @param udf
146             * @param arguments
147             */
148            private void call(UDF udf, Object[] arguments) {
149                    try {
150                            udf.call(pc,arguments,false);
151                    } catch (PageException pe) {
152                            error(pe);
153                    }
154            }
155            
156            /**
157             * call back error function if a error occour
158             * @param pe
159             */
160            private void error(PageException pe) {
161                    try {
162                            // TLPC
163                            pc=ThreadLocalPageContext.get(pc);
164                            error.call(pc,new Object[]{pe.getCatchBlock(pc)},false);
165                    } 
166                    catch (PageException e) {}
167            }
168            
169            /**
170             * cast a Attributes object to a Struct
171             * @param att
172             * @return Attributes as Struct
173             */
174            private Struct toStruct(Attributes att) {
175                    int len=att.getLength();
176                    Struct sct=new StructImpl();
177                    for(int i=0;i<len;i++) {
178                            sct.setEL(att.getQName(i),att.getValue(i));
179                    }
180                    return sct;
181            }
182    }