package org.madore.damlengine; import java.util.MissingResourceException; import java.util.regex.Pattern; import java.util.regex.Matcher; import java.io.InputStream; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.BufferedReader; import java.io.PrintStream; import javax.xml.XMLConstants; import javax.xml.namespace.NamespaceContext; import org.w3c.dom.*; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSParser; import org.w3c.dom.ls.LSInput; import org.apache.xerces.dom.DOMImplementationSourceImpl; import org.apache.xerces.xni.parser.XMLErrorHandler; import org.apache.xerces.xni.parser.XMLParseException; public final class DamlEngine { public static final String XMLNS_NS = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; public static final String XML_NS = XMLConstants.XML_NS_URI; public static final String XHTML_NS = "http://www.w3.org/1999/xhtml"; public static final String DAML_NS = "http://www.madore.org/~david/NS/daml/"; public static final String RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; public static final String RSS10_NS = "http://purl.org/rss/1.0/"; public static final String DUBLINCORE_NS = "http://purl.org/dc/elements/1.1/"; public static final String SYNDICATION_NS = "http://purl.org/rss/1.0/modules/syndication/"; public static final class DamlNSMapping implements NamespaceContext { // This is used for XPath resolution (_not_ for parsing the document). public String getNamespaceURI(String prefix) { if ( prefix == null ) throw new IllegalArgumentException("getNamespaceURI() called with null prefix"); else if ( prefix.equals("") ) return XHTML_NS; else if ( prefix.equals("d") ) return DAML_NS; else if ( prefix.equals("xml") ) return XML_NS; else if ( prefix.equals("xmlns") ) return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; else return XMLConstants.NULL_NS_URI; } public String getPrefix(String uri) { throw new UnsupportedOperationException("getPrefix() not implemented"); } public java.util.Iterator getPrefixes(String uri) { throw new UnsupportedOperationException("getPrefixes() not implemented"); } } public static class SelectiveErrorHandler implements XMLErrorHandler { public void warning(String domain, String key, XMLParseException exc) { System.err.println("warning: line "+exc.getLineNumber() +": "+exc.getMessage()); } public void error(String domain, String key, XMLParseException exc) { if ( domain.equals("http://www.w3.org/TR/1998/REC-xml-19980210") && key.equals("MSG_ELEMENT_NOT_DECLARED") ) return; System.err.println("error: line "+exc.getLineNumber() +": "+exc.getMessage()); } public void fatalError(String domain, String key, XMLParseException exc) { System.err.println("fatal error: line "+exc.getLineNumber() +": "+exc.getMessage()); throw exc; } } public static final class IncantDOM { static DOMImplementation domi; public static DOMImplementation getDOMI() { if ( domi == null ) { DOMImplementationSource source = new DOMImplementationSourceImpl(); domi = source.getDOMImplementation("XML 3.0 Core 3.0 LS 3.0"); if ( domi == null ) throw new MissingResourceException("failed to obtain DOM implementation", "org.w3c.dom.ls.DOMImplementationLS", ""); } return domi; } } private DamlEngine() { // Forbid instantiation throw new AssertionError("DamlEngine cannot be instantiated"); } public static class RootTodo extends TodoItem { public RootTodo(Context ctx) { super(ctx, null); } public void handle() { TodoItem it = TodoElement.getTodoElement(ctx.doc.getDocumentElement(), ctx, this); this.ownerDeque.registerAtEnd(it); } } public static void processDocument(Document doc, Context.WeblogSelectionContext wsc) { TodoDeque todoDeque = new TodoDeque(); Context ctx = new Context(doc); ctx.wsc = wsc; todoDeque.registerAtEnd(new RootTodo(ctx)); todoDeque.dispatchLoop(); } public static void processDocument(Document doc) { processDocument(doc, null); } public static void fullProcess(InputStream in, OutputStream out, Context.WeblogSelectionContext wsc) throws Exception { final DOMImplementationLS domils = (DOMImplementationLS)(IncantDOM.getDOMI()); LSParser par = domils.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null); par.getDomConfig().setParameter("resource-resolver", new Resolver()); par.getDomConfig().setParameter("http://xml.org/sax/features/validation", true); par.getDomConfig().setParameter("http://xml.org/sax/features/namespaces", true); par.getDomConfig().setParameter("http://apache.org/xml/properties/internal/error-handler", new SelectiveErrorHandler()); LSInput input = domils.createLSInput(); input.setByteStream(in); Document doc = par.parse(input); processDocument(doc, wsc); doc.normalizeDocument(); Unparser unparser = new Unparser(doc, new OutputStreamWriter(out, "UTF-8"), "html"); unparser.unparse(); } public static void fullProcess(InputStream in, OutputStream out) throws Exception { fullProcess(in, out, null); } public static void main(String[] args) throws Exception { BufferedReader buf = new BufferedReader(new InputStreamReader(System.in, "UTF-8")); String line; Matcher matcher; while ( ( line = buf.readLine() ) != null ) { if ( Pattern.matches("^\\s+$", line) ) continue; System.err.println(line); if ( (matcher=Pattern.compile("process\\s+(\\S+)(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) { String inf = matcher.group(1); String outf = matcher.group(2); InputStream in = new FileInputStream(inf); OutputStream out = (outf != null) ? new FileOutputStream(outf) : System.out; fullProcess(in, out); if ( out != System.out ) out.close(); } else if ( (matcher=Pattern.compile("process-weblog-month\\s+(\\d{4})\\-(\\d{2})(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) { String year = matcher.group(1); String month = matcher.group(2); String outf = matcher.group(3); OutputStream out = (outf != null) ? new FileOutputStream(outf) : System.out; WeblogSelect.fullProcess(new Context.WeblogMonthSelectionContext(year,month), out); if ( out != System.out ) out.close(); } else if ( (matcher=Pattern.compile("process-weblog-cat\\s+([a-z0-9\\-]+)(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) { String code = matcher.group(1); String outf = matcher.group(2); OutputStream out = (outf != null) ? new FileOutputStream(outf) : System.out; WeblogSelect.fullProcess(new Context.WeblogCategorySelectionContext(code), out); if ( out != System.out ) out.close(); } else if ( (matcher=Pattern.compile("process-weblog-recent\\s+(\\d+)(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) { int count = Integer.parseInt(matcher.group(1)); String outf = matcher.group(2); OutputStream out = (outf != null) ? new FileOutputStream(outf) : System.out; WeblogSelect.fullProcess(new Context.WeblogRecentSelectionContext(count), out); } else if ( (matcher=Pattern.compile("process-weblog-index(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) { String outf = matcher.group(1); OutputStream out = (outf != null) ? new FileOutputStream(outf) : System.out; WeblogIndexSelect.fullProcess(out); if ( out != System.out ) out.close(); } else if ( (matcher=Pattern.compile("process-weblog-rss(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) { String outf = matcher.group(1); OutputStream out = (outf != null) ? new FileOutputStream(outf) : System.out; WeblogRSS.fullProcess(out); if ( out != System.out ) out.close(); } else if ( (matcher=Pattern.compile("populate-weblog\\s+(\\S+)\\s*").matcher(line)).matches() ) { String inf = matcher.group(1); InputStream in = new FileInputStream(inf); WeblogPopulate.populate(in); } else if ( (matcher=Pattern.compile("echo\\s+(\\S+)(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) { String str = matcher.group(1); String outf = matcher.group(2); OutputStream out = (outf != null) ? new FileOutputStream(outf) : System.out; new PrintStream(out, true).println(str); if ( out != System.out ) out.close(); } else { throw new IllegalArgumentException("couldn't understand command"); } } } }