blob: 2bc9bd193f8fd10a583e5eb71afa4f1227e1dc99 [file] [log] [blame]
package org.eclipse.help.internal.contributors.xml;
/*
* Licensed Materials - Property of IBM,
* WebSphere Studio Workbench
* (c) Copyright IBM Corp 2000
*/
import org.xml.sax.*;
import java.util.*;
import java.io.*;
import org.eclipse.help.internal.HelpSystem;
import org.eclipse.help.internal.util.*;
import org.eclipse.help.internal.contributions.*;
import org.eclipse.help.internal.contributions.xml.HelpContribution;
import java.net.URL;
import org.apache.xerces.parsers.SAXParser;
/**
* Parser for xml file
*/
public class ContributionParser
extends SAXParser
implements ErrorHandler, ContentHandler {
protected Stack elementStack = new Stack();
protected Contribution contribution;
protected ContributionFactory factory;
protected boolean FATAL_ERROR_OCCURRED = false;
public ContributionParser() {
this(ContributionFactory.instance());
}
public ContributionParser(ContributionFactory factory) {
super();
this.factory = factory;
try {
setContinueAfterFatalError(false);
} catch (SAXNotSupportedException e) {
} catch (SAXNotRecognizedException e) {
}
setErrorHandler(this);
setContentHandler((ContentHandler) this);
}
/**
* Receive notification of character data.
*/
public void characters(char ch[], int start, int length) throws SAXException {
// no op
}
/**
* Receive notification of the end of a document.
*/
public void endDocument() throws SAXException {
// no op
}
/**
* Receive notification of the end of an element.
*/
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
// only pop when no error has occurred.
if (!FATAL_ERROR_OCCURRED)
elementStack.pop();
}
public void endPrefixMapping(String s) {
}
/** Recoverable parser errors, such as an invalid document */
public void error(SAXParseException ex) {
String message = getMessage("E001", ex);
Logger.logError(message, null);
}
/** Irrecoverable errors, such as a document that is not well formed */
public void fatalError(SAXParseException ex) throws SAXException {
// capture that error has occurred. The way we handle contribution files with
// errors is by trying to add as much of the file as possible. The minute an error
// is detected, no other contributions from this file are created.
FATAL_ERROR_OCCURRED = true;
// create message string from exception
String message = getMessage("E002", ex);
// Log the error.
Logger.logError(message, ex);
// now pass it to the RuntimeHelpStatus object explicitly because we
// still need to display errors even if Logging is turned off.
RuntimeHelpStatus.getInstance().addParseError(message, ex.getSystemId());
}
public Contribution getContribution() {
// return null the minute an error occurres. Null is handled properly by calling
// classes.
if (FATAL_ERROR_OCCURRED)
return null;
else
return contribution;
}
protected ContributionFactory getContributionFactory() {
return factory;
}
private String getLocationString(SAXParseException ex) {
String systemId = ex.getSystemId();
return systemId;
}
private String getMessage(String messageID, SAXParseException ex) {
String param1 = getLocationString(ex);
String param2 = Integer.toString(ex.getLineNumber());
String param3 = Integer.toString(ex.getColumnNumber());
String param4 = ex.getMessage();
String message = Resources.getString(messageID, param1, param2, param3, param4);
return message;
}
/**
* Receive notification of ignorable whitespace in element content.
*/
public void ignorableWhitespace(char ch[], int start, int length)
throws SAXException {
// no op
}
/**
* Receive notification of a processing instruction.
*/
public void processingInstruction(String target, String data)
throws SAXException {
// no op
}
/**
* Receive an object for locating the origin of SAX document events.
*/
public void setDocumentLocator(Locator locator) {
// no op
if (Logger.DEBUG)
Logger.logDebugMessage(
"ContributionParser",
"setDocumentLocator called with: " + locator.getPublicId());
}
public void skippedEntity(String s) {
}
/**
* Receive notification of the beginning of a document.
*
* <p>The SAX parser will invoke this method only once, before any
* other methods in this interface or in DTDHandler (except for
* setDocumentLocator).</p>
*
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
*/
public void startDocument() throws SAXException {
// no op
}
/**
* Receive notification of the beginning of an element.
*/
public void startElement(
String namespaceURI,
String localName,
String qName,
Attributes atts)
throws SAXException {
// make sure that no error has already occurred before adding to stack.
// for performance, do not create Contribution if error has already occurred.
if (!FATAL_ERROR_OCCURRED) {
Contribution e = getContributionFactory().createContribution(qName, atts);
if (e == null)
return;
if (elementStack.empty())
contribution = e;
else
((HelpContribution) elementStack.peek()).addChild(e);
elementStack.push(e);
}
}
public void startPrefixMapping(String prefix, String uri) throws SAXException {
}
public void warning(SAXParseException ex) {
String message = getMessage("E003", ex);
Logger.logWarning(message);
}
}