1 package org.apache.turbine.services.intake.transform;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 }