001: package org.apache.turbine.services.intake.transform;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.io.BufferedReader;
023: import java.io.FileReader;
024: import java.io.IOException;
025:
026: import javax.xml.parsers.ParserConfigurationException;
027: import javax.xml.parsers.SAXParser;
028: import javax.xml.parsers.SAXParserFactory;
029:
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032:
033: import org.apache.turbine.services.intake.xmlmodel.AppData;
034: import org.apache.turbine.services.intake.xmlmodel.Rule;
035: import org.apache.turbine.services.intake.xmlmodel.XmlField;
036: import org.apache.turbine.services.intake.xmlmodel.XmlGroup;
037:
038: import org.xml.sax.Attributes;
039: import org.xml.sax.InputSource;
040: import org.xml.sax.SAXException;
041: import org.xml.sax.SAXParseException;
042: import org.xml.sax.helpers.DefaultHandler;
043:
044: /**
045: * A Class that is used to parse an input
046: * xml schema file and creates and AppData java structure.
047: * It uses apache Xerces to do the xml parsing.
048: *
049: * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
050: * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
051: * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
052: * @version $Id: XmlToAppData.java 534527 2007-05-02 16:10:59Z tv $
053: */
054: public class XmlToAppData extends DefaultHandler {
055: /** Logging */
056: private static Log log = LogFactory.getLog(XmlToAppData.class);
057:
058: private AppData app = null;
059: private XmlGroup currGroup = null;
060: private XmlField currField = null;
061: private Rule currRule = null;
062:
063: private StringBuffer charBuffer = null;
064:
065: private static SAXParserFactory saxFactory = null;
066:
067: static {
068: saxFactory = SAXParserFactory.newInstance();
069: saxFactory.setValidating(true);
070: }
071:
072: /**
073: * Creates a new instance of the Intake XML Parser
074: */
075: public XmlToAppData() {
076: app = new AppData();
077: }
078:
079: /**
080: * Parses a XML input file and returns a newly created and
081: * populated AppData structure.
082: *
083: * @param xmlFile The input file to parse.
084: * @return AppData populated by <code>xmlFile</code>.
085: * @throws ParserConfigurationException When a serious parser configuration problem occurs.
086: * @throws SAXException When a problem parsing the XML file occurs.
087: * @throws IOException When an I/O error occurs.
088: */
089: public AppData parseFile(String xmlFile)
090: throws ParserConfigurationException, SAXException,
091: IOException {
092: SAXParser parser = saxFactory.newSAXParser();
093:
094: FileReader fr = new FileReader(xmlFile);
095: BufferedReader br = new BufferedReader(fr);
096: try {
097: InputSource is = new InputSource(br);
098: parser.parse(is, this );
099: } finally {
100: br.close();
101: }
102:
103: return app;
104: }
105:
106: /**
107: * EntityResolver implementation. Called by the XML parser
108: *
109: * @param publicId The public identifer, which might be null.
110: * @param systemId The system identifier provided in the XML document.
111: * @return an InputSource for the database.dtd file
112: */
113: public InputSource resolveEntity(String publicId, String systemId) {
114: return new DTDResolver().resolveEntity(publicId, systemId);
115: }
116:
117: /**
118: * Handles opening elements of the xml file.
119: * @param uri The current namespace URI.
120: * @param localName The local name (without prefix), or the empty string if Namespace processing is not being performed.
121: * @param rawName The qualified name (with prefix), or the empty string if qualified names are not available.
122: * @param attributes The specified or defaulted attributes.
123: */
124: public void startElement(String uri, String localName,
125: String rawName, Attributes attributes) {
126: charBuffer = new StringBuffer();
127:
128: if (rawName.equals("input-data")) {
129: app.loadFromXML(attributes);
130: } else if (rawName.equals("group")) {
131: currGroup = app.addGroup(attributes);
132: } else if (rawName.equals("field")) {
133: currField = currGroup.addField(attributes);
134: } else if (rawName.equals("rule")) {
135: currRule = currField.addRule(attributes);
136: }
137: }
138:
139: /**
140: * Handles the character data, which we are using to specify the error message.
141: * @param mesgArray The characters.
142: * @param start The start position in the character array.
143: * @param length The number of characters to use from the character array.
144: */
145: public void characters(char[] mesgArray, int start, int length) {
146: charBuffer.append(mesgArray, start, length);
147: }
148:
149: /**
150: * Handles closing Elements of the XML file
151: * @param uri The current namespace URI.
152: * @param localName The local name (without prefix), or the empty string if Namespace processing is not being performed.
153: * @param rawName The qualified name (with prefix), or the empty string if qualified names are not available.
154: */
155: public void endElement(String uri, String localName, String rawName) {
156: if (charBuffer.length() > 0) {
157: String cdata = charBuffer.toString().trim();
158:
159: if ("rule".equals(rawName)) {
160: currRule.setMessage(cdata);
161: } else if ("required-message".equals(rawName)) {
162: log
163: .warn("The required-message element is deprecated! "
164: + "You should update your intake.xml file to use the "
165: + "'required' rule instead.");
166: currField.setIfRequiredMessage(cdata);
167: }
168: }
169: }
170:
171: /**
172: * Callback function for the xml parser to give warnings.
173: *
174: * @param spe a <code>SAXParseException</code> value
175: */
176: public void warning(SAXParseException spe) {
177: StringBuffer sb = new StringBuffer(64);
178: sb.append("Parser Exception: Line ");
179: sb.append(spe.getLineNumber());
180: sb.append(" Row ");
181: sb.append(spe.getColumnNumber());
182: sb.append(" Msg: ");
183: sb.append(spe.getMessage());
184:
185: log.warn(sb.toString());
186: }
187:
188: /**
189: * Callback function for the xml parser to give errors.
190: *
191: * @param spe a <code>SAXParseException</code> value
192: */
193: public void error(SAXParseException spe) {
194: StringBuffer sb = new StringBuffer(64);
195: sb.append("Parser Exception: Line ");
196: sb.append(spe.getLineNumber());
197: sb.append(" Row ");
198: sb.append(spe.getColumnNumber());
199: sb.append(" Msg: ");
200: sb.append(spe.getMessage());
201:
202: log.error(sb.toString());
203: }
204:
205: /**
206: * Callback function for the xml parser to give fatalErrors.
207: *
208: * @param spe a <code>SAXParseException</code> value
209: */
210: public void fatalError(SAXParseException spe) {
211: StringBuffer sb = new StringBuffer(64);
212: sb.append("Parser Exception: Line ");
213: sb.append(spe.getLineNumber());
214: sb.append(" Row ");
215: sb.append(spe.getColumnNumber());
216: sb.append(" Msg: ");
217: sb.append(spe.getMessage());
218:
219: log.fatal(sb.toString());
220: }
221: }
|