View Javadoc

1   package org.apache.turbine.services.intake.transform;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.BufferedReader;
23  import java.io.FileReader;
24  import java.io.IOException;
25  
26  import javax.xml.parsers.ParserConfigurationException;
27  import javax.xml.parsers.SAXParser;
28  import javax.xml.parsers.SAXParserFactory;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  
33  import org.apache.turbine.services.intake.xmlmodel.AppData;
34  import org.apache.turbine.services.intake.xmlmodel.Rule;
35  import org.apache.turbine.services.intake.xmlmodel.XmlField;
36  import org.apache.turbine.services.intake.xmlmodel.XmlGroup;
37  
38  import org.xml.sax.Attributes;
39  import org.xml.sax.InputSource;
40  import org.xml.sax.SAXException;
41  import org.xml.sax.SAXParseException;
42  import org.xml.sax.helpers.DefaultHandler;
43  
44  /***
45   * A Class that is used to parse an input
46   * xml schema file and creates and AppData java structure.
47   * It uses apache Xerces to do the xml parsing.
48   *
49   * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
50   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
51   * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
52   * @version $Id: XmlToAppData.java 534527 2007-05-02 16:10:59Z tv $
53   */
54  public class XmlToAppData extends DefaultHandler
55  {
56      /*** Logging */
57      private static Log log = LogFactory.getLog(XmlToAppData.class);
58  
59      private AppData app = null;
60      private XmlGroup currGroup = null;
61      private XmlField currField = null;
62      private Rule currRule = null;
63  
64      private StringBuffer charBuffer = null;
65  
66      private static SAXParserFactory saxFactory = null;
67  
68      static
69      {
70          saxFactory = SAXParserFactory.newInstance();
71          saxFactory.setValidating(true);
72      }
73  
74      /***
75       * Creates a new instance of the Intake XML Parser
76       */
77      public XmlToAppData()
78      {
79          app = new AppData();
80      }
81  
82      /***
83       * Parses a XML input file and returns a newly created and
84       * populated AppData structure.
85       *
86       * @param xmlFile The input file to parse.
87       * @return AppData populated by <code>xmlFile</code>.
88       * @throws ParserConfigurationException When a serious parser configuration problem occurs.
89       * @throws SAXException When a problem parsing the XML file occurs.
90       * @throws IOException When an I/O error occurs.
91       */
92      public AppData parseFile(String xmlFile)
93              throws ParserConfigurationException, SAXException, IOException
94      {
95          SAXParser parser = saxFactory.newSAXParser();
96  
97          FileReader fr = new FileReader(xmlFile);
98          BufferedReader br = new BufferedReader(fr);
99          try
100         {
101             InputSource is = new InputSource(br);
102             parser.parse(is, this);
103         }
104         finally
105         {
106             br.close();
107         }
108 
109         return app;
110     }
111 
112     /***
113      * EntityResolver implementation. Called by the XML parser
114      *
115      * @param publicId The public identifer, which might be null.
116      * @param systemId The system identifier provided in the XML document.
117      * @return an InputSource for the database.dtd file
118      */
119     public InputSource resolveEntity(String publicId, String systemId)
120     {
121         return new DTDResolver().resolveEntity(publicId, systemId);
122     }
123 
124     /***
125      * Handles opening elements of the xml file.
126      * @param uri The current namespace URI.
127      * @param localName The local name (without prefix), or the empty string if Namespace processing is not being performed.
128      * @param rawName The qualified name (with prefix), or the empty string if qualified names are not available.
129      * @param attributes The specified or defaulted attributes.
130      */
131     public void startElement(String uri, String localName,
132                              String rawName, Attributes attributes)
133     {
134         charBuffer = new StringBuffer();
135 
136         if (rawName.equals("input-data"))
137         {
138             app.loadFromXML(attributes);
139         }
140         else if (rawName.equals("group"))
141         {
142             currGroup = app.addGroup(attributes);
143         }
144         else if (rawName.equals("field"))
145         {
146             currField = currGroup.addField(attributes);
147         }
148         else if (rawName.equals("rule"))
149         {
150             currRule = currField.addRule(attributes);
151         }
152     }
153 
154     /***
155      * Handles the character data, which we are using to specify the error message.
156      * @param mesgArray The characters.
157      * @param start The start position in the character array.
158      * @param length The number of characters to use from the character array.
159      */
160     public void characters(char[] mesgArray, int start, int length)
161     {
162         charBuffer.append(mesgArray, start, length);
163     }
164 
165     /***
166      * Handles closing Elements of the XML file
167      * @param uri The current namespace URI.
168      * @param localName The local name (without prefix), or the empty string if Namespace processing is not being performed.
169      * @param rawName The qualified name (with prefix), or the empty string if qualified names are not available.
170      */
171     public void endElement(String uri, String localName,
172             String rawName)
173     {
174         if (charBuffer.length() > 0)
175         {
176             String cdata = charBuffer.toString().trim();
177 
178             if ("rule".equals(rawName))
179             {
180                 currRule.setMessage(cdata);
181             }
182             else if ("required-message".equals(rawName))
183             {
184                 log.warn("The required-message element is deprecated!  " +
185                         "You should update your intake.xml file to use the " +
186                         "'required' rule instead.");
187                 currField.setIfRequiredMessage(cdata);
188             }
189         }
190     }
191 
192     /***
193      * Callback function for the xml parser to give warnings.
194      *
195      * @param spe a <code>SAXParseException</code> value
196      */
197     public void warning(SAXParseException spe)
198     {
199         StringBuffer sb = new StringBuffer(64);
200         sb.append("Parser Exception: Line ");
201         sb.append(spe.getLineNumber());
202         sb.append(" Row ");
203         sb.append(spe.getColumnNumber());
204         sb.append(" Msg: ");
205         sb.append(spe.getMessage());
206 
207         log.warn(sb.toString());
208     }
209 
210     /***
211      * Callback function for the xml parser to give errors.
212      *
213      * @param spe a <code>SAXParseException</code> value
214      */
215     public void error(SAXParseException spe)
216     {
217         StringBuffer sb = new StringBuffer(64);
218         sb.append("Parser Exception: Line ");
219         sb.append(spe.getLineNumber());
220         sb.append(" Row ");
221         sb.append(spe.getColumnNumber());
222         sb.append(" Msg: ");
223         sb.append(spe.getMessage());
224 
225         log.error(sb.toString());
226     }
227 
228     /***
229      * Callback function for the xml parser to give fatalErrors.
230      *
231      * @param spe a <code>SAXParseException</code> value
232      */
233     public void fatalError(SAXParseException spe)
234     {
235         StringBuffer sb = new StringBuffer(64);
236         sb.append("Parser Exception: Line ");
237         sb.append(spe.getLineNumber());
238         sb.append(" Row ");
239         sb.append(spe.getColumnNumber());
240         sb.append(" Msg: ");
241         sb.append(spe.getMessage());
242 
243         log.fatal(sb.toString());
244     }
245 }