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
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 }