001: /*
002: * <copyright>
003: *
004: * Copyright 2001-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.planning.servlet.data.xml;
027:
028: import java.io.IOException;
029: import java.io.InputStream;
030: import java.io.Reader;
031: import java.util.ArrayList;
032: import java.util.List;
033:
034: import org.xml.sax.Attributes;
035: import org.xml.sax.InputSource;
036: import org.xml.sax.SAXException;
037: import org.xml.sax.SAXParseException;
038: import org.xml.sax.XMLReader;
039: import org.xml.sax.helpers.AttributesImpl;
040: import org.xml.sax.helpers.DefaultHandler;
041:
042: /**
043: * Gets deXMLable objects back from an XML stream
044: *
045: * @since 1/24/01
046: **/
047: public class DeXMLizer extends DefaultHandler {
048:
049: //Variables:
050: ////////////
051:
052: /** Default parser name. */
053: protected static final String PARSER_NAME = "org.apache.xerces.parsers.SAXParser";
054:
055: protected static boolean setValidation = false;
056: protected static boolean setNameSpaces = false;
057: protected static boolean setSchemaSupport = true;
058:
059: protected XMLReader parser;
060:
061: /**Buffer data across characters() calls to make sure we have it all**/
062: protected StringBuffer data;
063: /**Buffer data across characters() calls to make sure we have it all**/
064: protected AttributesImpl lastAttr;
065: /**Buffer data across characters() calls to make sure we have it all**/
066: protected String lastTag;
067:
068: /**Stack of objects being built**/
069: protected List stack;
070:
071: /**Return values**/
072: protected List objects;
073:
074: /**Our Factory **/
075: protected DeXMLableFactory factory;
076:
077: //Constructors:
078: ///////////////
079:
080: public DeXMLizer(DeXMLableFactory f) {
081: try {
082: parser = (XMLReader) Class.forName(PARSER_NAME)
083: .newInstance();
084: parser.setFeature("http://xml.org/sax/features/validation",
085: setValidation);
086: parser.setFeature("http://xml.org/sax/features/namespaces",
087: setNameSpaces);
088: parser.setFeature(
089: "http://apache.org/xml/features/validation/schema",
090: setSchemaSupport);
091: parser.setContentHandler(this );
092: parser.setErrorHandler(this );
093: } catch (Exception e) {
094: reportMessage("Exception setting up parser: ", e);
095: }
096: objects = new ArrayList();
097: stack = new ArrayList();
098: data = new StringBuffer();
099: factory = f;
100: }
101:
102: //Members:
103: //////////
104:
105: public DeXMLable parseObject(Reader r) throws SAXException,
106: IOException {
107: return parseObject(new InputSource(r));
108: }
109:
110: public DeXMLable parseObject(InputStream is) throws SAXException,
111: IOException {
112: return parseObject(new InputSource(is));
113: }
114:
115: public DeXMLable parseObject(InputSource is) throws SAXException,
116: IOException {
117: return (DeXMLable) parseObjects(is).get(0);
118: }
119:
120: public List parseObjects(Reader r) throws SAXException, IOException {
121: return parseObjects(new InputSource(r));
122: }
123:
124: public List parseObjects(InputStream is) throws SAXException,
125: IOException {
126: return parseObjects(new InputSource(is));
127: }
128:
129: public List parseObjects(InputSource is) throws SAXException,
130: IOException {
131: try {
132: parser.parse(is);
133: } catch (IOException e) {
134: reportMessage("IO exception while parsing", e);
135: throw e;
136: } catch (SAXException e) {
137: reportMessage("Exception parsing", e);
138: throw e;
139: }
140: return objects;
141: }
142:
143: protected DeXMLable curObj() {
144: if (stack.size() < 1)
145: return null;
146: return (DeXMLable) stack.get(stack.size() - 1);
147: }
148:
149: protected void setCache(String tag, Attributes attrs) {
150: lastTag = tag;
151: if (attrs != null)
152: lastAttr = new AttributesImpl(attrs);
153: else
154: lastAttr = null;
155: data.setLength(0);
156: }
157:
158: protected boolean cacheEmpty() {
159: return lastTag == null;
160: }
161:
162: protected void processCachedTag() {
163: try {
164: //Check if this should be a new SubObj:
165: DeXMLable subObj;
166: subObj = factory
167: .beginSubObject(curObj(), lastTag, lastAttr);
168: if (curObj() == null && subObj == null) {
169: throw new UnexpectedXMLException(
170: "No object registered for tag: " + lastTag);
171: }
172:
173: //New subObj:
174: if (subObj != null) {
175: stack.add(subObj);
176: }
177: curObj().openTag(lastTag, lastAttr, data.toString());
178: } catch (UnexpectedXMLException e) {
179: reportMessage(e);
180: }
181: }
182:
183: //
184: // DocumentHandler methods
185: //
186:
187: /** Start document. */
188: public void startDocument() {
189: lastTag = null;
190: objects.clear();
191: stack.clear();
192: }
193:
194: /** Start element. */
195: public void startElement(String uri, String local, String raw,
196: Attributes attrs) {
197: if (!cacheEmpty()) {
198: processCachedTag();
199: }
200: setCache(raw, attrs);
201: }
202:
203: /** Characters. */
204: public void characters(char ch[], int start, int length) {
205: data.append(ch, start, length);
206: }
207:
208: /** Ignorable whitespace. */
209: public void ignorableWhitespace(char ch[], int start, int length) {
210: }
211:
212: /** End element. */
213: public void endElement(String uri, String local, String raw) {
214: if (!cacheEmpty()) {
215: processCachedTag();
216: }
217: setCache(null, null);
218:
219: try {
220: DeXMLable curObj = curObj();
221: if (curObj == null) {
222: reportMessage("Unexpected 0 stack");
223: return;
224: }
225: if (curObj.closeTag(raw)) {
226: stack.remove(stack.size() - 1);
227: if (stack.size() == 0) {
228: objects.add(curObj);
229: } else {
230: curObj().completeSubObject(raw, curObj);
231: }
232: }
233: } catch (UnexpectedXMLException e) {
234: reportMessage(e);
235: }
236: }
237:
238: //
239: // ErrorHandler methods
240: //
241:
242: /** Warning. */
243: public void warning(SAXParseException ex) {
244: reportMessage("[Warning] " + getLocationString(ex), ex);
245: }
246:
247: /** Error. */
248: public void error(SAXParseException ex) {
249: reportMessage("[Error] " + getLocationString(ex), ex);
250: }
251:
252: /** Fatal error. */
253: public void fatalError(SAXParseException ex) throws SAXException {
254: reportMessage("[Fatal Error] " + getLocationString(ex), ex);
255: }
256:
257: /** Returns a string of the location. */
258: private String getLocationString(SAXParseException ex) {
259: StringBuffer str = new StringBuffer();
260:
261: String systemId = ex.getSystemId();
262: if (systemId != null) {
263: int index = systemId.lastIndexOf('/');
264: if (index != -1)
265: systemId = systemId.substring(index + 1);
266: str.append(systemId);
267: }
268: str.append(':');
269: str.append(ex.getLineNumber());
270: str.append(':');
271: str.append(ex.getColumnNumber());
272:
273: return str.toString();
274: }
275:
276: protected void reportMessage(String m) {
277: System.out.println(m);
278: }
279:
280: protected void reportMessage(String m, Exception e) {
281: reportMessage(m + ": " + e);
282: }
283:
284: protected void reportMessage(Exception e) {
285: reportMessage(e.toString());
286: }
287: }
|