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    import org.xml.sax.helpers.XMLReaderFactory;
012    
013    import railo.commons.io.IOUtil;
014    import railo.commons.io.res.Resource;
015    import railo.runtime.PageContext;
016    import railo.runtime.engine.ThreadLocalPageContext;
017    import railo.runtime.exp.PageException;
018    import railo.runtime.op.Caster;
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 = XMLReaderFactory.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            /**
107             * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
108             */
109            public void characters(char[] ch, int start, int length) throws SAXException {
110                    sbBody.append(ch,start,length);
111            }
112    
113            /**
114             * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
115             */
116            public void error(SAXParseException e) throws SAXException {
117                    error(Caster.toPageException(e));
118            }
119            /**
120             * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
121             */
122            public void fatalError(SAXParseException e) throws SAXException {
123                    error(Caster.toPageException(e));
124            }
125            /**
126             * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
127             */
128            public void startElement(String uri, String localName, String qName,
129                            Attributes attributes) throws SAXException {
130                    sbBody=new StringBuffer();
131                    att = toStruct(attributes);
132                    call(startElement,new Object[]{uri,localName,qName,att});
133            }
134    
135            /**
136             * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
137             */
138            public void endElement(String uri, String localName, String qName) throws SAXException {
139                    call(body,new Object[]{sbBody.toString()});
140                    call(endElement,new Object[]{uri,localName,qName,att});
141            }
142            
143            /**
144             * @see org.xml.sax.helpers.DefaultHandler#startDocument()
145             */
146            public void startDocument() throws SAXException {
147                    call(startDocument,ArrayUtil.OBJECT_EMPTY);
148            }
149            
150            /**
151             * @see org.xml.sax.helpers.DefaultHandler#endDocument()
152             */
153            public void endDocument() throws SAXException {
154                    call(endDocument,ArrayUtil.OBJECT_EMPTY);
155            }
156            
157            /**
158             * call a user defined function
159             * @param udf
160             * @param arguments
161             */
162            private void call(UDF udf, Object[] arguments) {
163                    try {
164                            udf.call(pc,arguments,false);
165                    } catch (PageException pe) {
166                            error(pe);
167                    }
168            }
169            
170            /**
171             * call back error function if a error occour
172             * @param pe
173             */
174            private void error(PageException pe) {
175                    try {
176                            // TLPC
177                            pc=ThreadLocalPageContext.get(pc);
178                            error.call(pc,new Object[]{pe.getCatchBlock(pc)},false);
179                    } 
180                    catch (PageException e) {}
181            }
182            
183            /**
184             * cast a Attributes object to a Struct
185             * @param att
186             * @return Attributes as Struct
187             */
188            private Struct toStruct(Attributes att) {
189                    int len=att.getLength();
190                    Struct sct=new StructImpl();
191                    for(int i=0;i<len;i++) {
192                            sct.setEL(att.getQName(i),att.getValue(i));
193                    }
194                    return sct;
195            }
196    }