package nl.siegmann.epublib.epub;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import nl.siegmann.epublib.Constants;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;
/**
* Various low-level support methods for reading/writing epubs.
*
* @author paul.siegmann
*
*/
public class EpubProcessorSupport {
private static final Logger log = Logger.getLogger(EpubProcessorSupport.class.getName());
protected static DocumentBuilderFactory documentBuilderFactory;
static {
init();
}
static class EntityResolverImpl implements EntityResolver {
private String previousLocation;
@Override
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
String resourcePath;
if (systemId.startsWith("http:")) {
URL url = new URL(systemId);
resourcePath = "resources/dtd/" + url.getHost() + url.getPath();
previousLocation = resourcePath.substring(0, resourcePath.lastIndexOf('/'));
} else {
resourcePath = previousLocation + systemId.substring(systemId.lastIndexOf('/'));
}
if (this.getClass().getClassLoader().getResource(resourcePath) == null) {
throw new RuntimeException("remote resource is not cached : [" + systemId + "] cannot continue");
}
InputStream in = EpubProcessorSupport.class.getClassLoader().getResourceAsStream(resourcePath);
return new InputSource(in);
}
}
private static void init() {
EpubProcessorSupport.documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setValidating(false);
}
public static XmlSerializer createXmlSerializer(OutputStream out) throws UnsupportedEncodingException {
return createXmlSerializer(new OutputStreamWriter(out, Constants.ENCODING));
}
public static XmlSerializer createXmlSerializer(Writer out) {
XmlSerializer result = null;
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setValidating(true);
result = factory.newSerializer();
result.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
result.setOutput(out);
} catch (Exception e) {
log.log(Level.WARNING, " When creating XmlSerializer: " + e.getClass().getName() + ": " + e.getMessage(), e);
}
return result;
}
public DocumentBuilderFactory getDocumentBuilderFactory() {
return documentBuilderFactory;
}
/**
* Creates a DocumentBuilder that looks up dtd's and schema's from epublib's classpath.
*
* @return
*/
public static DocumentBuilder createDocumentBuilder() {
DocumentBuilder result = null;
try {
result = documentBuilderFactory.newDocumentBuilder();
result.setEntityResolver(new EntityResolverImpl());
} catch (ParserConfigurationException e) {
log.warning(e.getMessage());
}
return result;
}
}