211 lines
6.6 KiB
Java
Executable File
211 lines
6.6 KiB
Java
Executable File
package com.arsdigita.london.importer;
|
|
|
|
import com.arsdigita.util.UncheckedWrapperException;
|
|
import com.arsdigita.xml.XML;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.Stack;
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
import javax.xml.parsers.SAXParser;
|
|
import javax.xml.parsers.SAXParserFactory;
|
|
import org.apache.log4j.Logger;
|
|
import org.xml.sax.Attributes;
|
|
import org.xml.sax.InputSource;
|
|
import org.xml.sax.SAXException;
|
|
import org.xml.sax.helpers.DefaultHandler;
|
|
|
|
/**
|
|
* The main entry point to importer facility.
|
|
* ParserDispatcher is XML parser implementation which delegates the
|
|
* control to one of the registered {@link TagParser} instances,
|
|
* depending on the XML tag encountered. When an XML tag with no
|
|
* associated TagParser instance is encountered, the control is retained
|
|
* by the currently active parser.
|
|
*
|
|
* @see com.arsdigita.london.importer
|
|
*/
|
|
public class ParserDispatcher extends DefaultHandler {
|
|
private static Logger s_log =
|
|
Logger.getLogger(ParserDispatcher.class);
|
|
|
|
// Parsers for individual elements.
|
|
private Map m_parsers;
|
|
private Stack m_parserContext;
|
|
|
|
public ParserDispatcher() {
|
|
m_parsers = new HashMap();
|
|
}
|
|
|
|
/**
|
|
* Import objects specified by <tt>importFile</tt>.
|
|
* <em>Important notice</em>: before this method can be called, the caller must
|
|
* register one or more instances of {@link TagHandler} interface via
|
|
* {@link #addParser(TagParser) addParser} method.
|
|
*
|
|
* @param importFile name of the file containing XML source for import.
|
|
*/
|
|
public void execute(String importFile) {
|
|
m_parserContext = new Stack();
|
|
|
|
if (s_log.isInfoEnabled()) {
|
|
s_log.info("Parsing from " + importFile);
|
|
}
|
|
|
|
InputStream is = null;
|
|
try {
|
|
is = new FileInputStream(new File(importFile));
|
|
XML.parse(is, this);
|
|
} catch (IOException ex) {
|
|
throw new UncheckedWrapperException(
|
|
"cannot load file " + importFile,
|
|
ex);
|
|
} finally {
|
|
if (is != null) {
|
|
try {
|
|
is.close();
|
|
} catch (IOException e) {
|
|
s_log.warn("Failed to close " + importFile, e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Import objects specified by <tt>source</tt>.
|
|
* <em>Important notice</em>: before this method can be called, the caller must
|
|
* register one or more instances of {@link TagHandler} interface via
|
|
* {@link #addParser(TagParser) addParser} method.
|
|
*/
|
|
public void execute(InputSource source) {
|
|
m_parserContext = new Stack();
|
|
|
|
if (s_log.isInfoEnabled()) {
|
|
s_log.info("Parsing from InputSource");
|
|
}
|
|
|
|
try {
|
|
SAXParserFactory spf = SAXParserFactory.newInstance();
|
|
spf.setFeature("http://xml.org/sax/features/namespaces", true);
|
|
SAXParser parser = spf.newSAXParser();
|
|
parser.parse(source, this);
|
|
} catch (ParserConfigurationException e) {
|
|
throw new UncheckedWrapperException("error parsing stream", e);
|
|
} catch (SAXException e) {
|
|
if (e.getException() != null) {
|
|
throw new UncheckedWrapperException("error parsing stream",
|
|
e.getException());
|
|
} else {
|
|
throw new UncheckedWrapperException("error parsing stream", e);
|
|
}
|
|
} catch (IOException e) {
|
|
throw new UncheckedWrapperException("error parsing stream", e);
|
|
}
|
|
}
|
|
|
|
public void addParser(TagParser parser) {
|
|
m_parsers.put(getKey(parser), parser);
|
|
}
|
|
|
|
/**
|
|
* Based on the element name, switch to the parser handling that element.
|
|
*/
|
|
public void startElement(String uri, String local,
|
|
String qname, Attributes atts) {
|
|
if (s_log.isDebugEnabled()) {
|
|
s_log.debug("Processing start element: " +
|
|
qname + " " + uri + " " + local);
|
|
}
|
|
|
|
if (m_parsers.containsKey(getKey(local, uri))) {
|
|
TagParser current = getCurrentParser();
|
|
TagParser next = (TagParser) m_parsers.get(getKey(local, uri));
|
|
|
|
if (s_log.isInfoEnabled()) {
|
|
s_log.info("Switching from " + current + " to " + next);
|
|
}
|
|
|
|
if (current != null) {
|
|
current.startSubBlock(next);
|
|
}
|
|
next.startBlock();
|
|
|
|
m_parserContext.push(next);
|
|
}
|
|
|
|
if (s_log.isDebugEnabled()) {
|
|
s_log.debug("In start, current parser is " +
|
|
getCurrentParser());
|
|
}
|
|
TagParser current = getCurrentParser();
|
|
if (current != null) {
|
|
current.startElement(local, uri, atts);
|
|
} else {
|
|
s_log.warn("No current parser available for " + local + " " + uri);
|
|
}
|
|
}
|
|
|
|
public void characters(char[] ch, int start, int length) {
|
|
getCurrentParser().characters(ch, start, length);
|
|
}
|
|
|
|
public void endElement(String uri, String local, String qname ) {
|
|
if (s_log.isDebugEnabled()) {
|
|
s_log.debug("Processing end element: " +
|
|
qname + " " + uri + " " + local);
|
|
}
|
|
|
|
getCurrentParser().endElement(local, uri);
|
|
if (s_log.isDebugEnabled()) {
|
|
s_log.debug("In end, current parser is " +
|
|
getCurrentParser());
|
|
}
|
|
|
|
if (m_parsers.containsKey(getKey(local, uri))) {
|
|
TagParser current = getCurrentParser();
|
|
m_parserContext.pop();
|
|
TagParser previous = m_parserContext.empty() ? null :
|
|
(TagParser)m_parserContext.peek();
|
|
|
|
current.endBlock();
|
|
if (previous != null) {
|
|
previous.endSubBlock(current);
|
|
}
|
|
|
|
if (s_log.isInfoEnabled()) {
|
|
s_log.info("Reverting from " + current + " to " + previous);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
protected String getKey(TagParser parser) {
|
|
String name = parser.getTagName();
|
|
String uri = parser.getTagURI();
|
|
|
|
return getKey(name, uri);
|
|
}
|
|
|
|
protected String getKey(String name,
|
|
String uri) {
|
|
if (uri == null) {
|
|
return name;
|
|
} else {
|
|
return name + ":" + uri;
|
|
}
|
|
}
|
|
|
|
protected TagParser getCurrentParser() {
|
|
if (m_parserContext.empty()) {
|
|
return null;
|
|
} else {
|
|
return (TagParser)m_parserContext.peek();
|
|
}
|
|
}
|
|
}
|
|
|
|
|