View Javadoc

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