--- /dev/null
+package it.unibo.cs.helm.uwobo;
+
+import java.io.*;
+import java.net.URL;
+import java.util.*;
+import javax.xml.transform.*;
+import javax.xml.transform.sax.*;
+import javax.xml.transform.stream.*;
+import org.apache.xalan.serialize.*;
+import org.apache.xalan.xslt.*;
+import org.apache.xalan.templates.*;
+import org.apache.xalan.transformer.*;
+import org.apache.xerces.parsers.*;
+import org.xml.sax.*;
+import org.xml.sax.ext.*;
+import org.xml.sax.helpers.*;
+
+/**
+// This file is part of UWOBO, a small and simple XSLT server.
+//
+// UWOBO is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// UWOBO is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with UWOBO; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// For details, send a mail to <luca.padovani@cs.unibo.it>
+* @author Luca Padovani, Riccardo Solmi
+*/
+
+public class Server {
+ private static class Style {
+ public String fileName;
+ public long lastModified;
+ public Templates stylesheet;
+ };
+
+ public static final String SERVERNAME = "uwobo-XSLT-server";
+ public static final String PACKAGE;
+ public static final String VERSION;
+ public static final String DATE;
+ public static final String TIME;
+
+ static {
+ Properties props = new Properties();
+ try {
+ InputStream in = Server.class.getResourceAsStream("properties.txt");
+ props.load(in);
+ in.close();
+ } catch (IOException ioe) {
+ System.err.println("Could not load the version information.");
+ }
+
+ PACKAGE = props.getProperty("PACKAGE");
+ VERSION = props.getProperty("VERSION");
+ DATE = props.getProperty("DATE");
+ TIME = props.getProperty("TIME");
+ }
+
+ private final HashMap hashMap = new HashMap();
+ private static int logCounter = 0;
+
+ private final Templates compileStylesheet(String xsl_file) throws TransformerConfigurationException, SAXException, IOException {
+ StreamSource streamsource =
+ new StreamSource(new URL(xsl_file).openStream());
+ streamsource.setSystemId(xsl_file);
+ return ((SAXTransformerFactory)TransformerFactory.newInstance())
+ .newTemplates(streamsource);
+ }
+
+ private String getContentType(Templates templates) {
+ final Properties oprops = templates.getOutputProperties();
+ final String encoding = oprops.getProperty(OutputKeys.ENCODING);
+ final String media = oprops.getProperty(OutputKeys.MEDIA_TYPE);
+
+ if (media != null) {
+ if (encoding != null)
+ return media + "; charset=" + encoding;
+ return media;
+ } else {
+ final String method = oprops.getProperty(OutputKeys.METHOD);
+ if (method.equals("html"))
+ return "text/html";
+ else if (method.equals("text"))
+ return "text/plain";
+ else
+ return "text/xml";
+ }
+ }
+
+ private final ContentHandler applyStylesheet(Templates stylesheet, HashMap params, ContentHandler saxOutput)
+ throws TransformerConfigurationException, SAXException
+ {
+ TransformerHandler th = ((SAXTransformerFactory)TransformerFactory.newInstance()).newTransformerHandler(stylesheet);
+
+ th.setResult(new SAXResult(saxOutput));
+
+ if (params != null) {
+ final Transformer transformer = th.getTransformer();
+ Iterator i = params.keySet().iterator();
+ while (i.hasNext()) {
+ final String name = (String) i.next();
+ final String value = (String) params.get(name);
+ transformer.setParameter(name, value);
+ }
+ }
+
+ return th;
+ }
+
+ private final void parseFile(String datasheet, ContentHandler saxOutput) throws SAXException, IOException, Exception {
+ final XMLReader reader = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
+ reader.setFeature("http://xml.org/sax/features/namespaces", true);
+ reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+ reader.setContentHandler(saxOutput);
+ if (saxOutput instanceof LexicalHandler)
+ reader.setProperty("http://xml.org/sax/properties/lexical-handler", (LexicalHandler)saxOutput);
+ reader.parse(datasheet);
+ }
+
+ private final ContentHandler saveFile(OutputStream outputStream, Properties props) throws IOException {
+ final Serializer ser = SerializerFactory.getSerializer(props);
+ ser.setOutputStream(outputStream);
+ return ser.asContentHandler();
+ }
+
+ public static void log(String msg) {
+ System.err.println(SERVERNAME + "[" + logCounter++ + "]: " + msg);
+ }
+
+ public void add(String filename, String key) throws TransformerConfigurationException, SAXException, IOException {
+ if (hashMap.containsKey(key)) {
+ log("there is already a stylesheet with keyword \"" + key + "\" (aborted)");
+ return;
+ }
+
+ Style style = new Style();
+ style.fileName = filename;
+ style.lastModified = new File(filename).lastModified();
+ log("processing stylesheet \"" + filename + "\"... ");
+ style.stylesheet = compileStylesheet(filename);
+ log("done!");
+
+ hashMap.put(key, style);
+ }
+
+ public void removeAll() throws TransformerConfigurationException, SAXException, IOException {
+ String key;
+ Style style;
+ Iterator i = hashMap.keySet().iterator();
+ while (i.hasNext()) {
+ key = (String)i.next();
+ style = (Style)hashMap.get(key);
+ log("removing \"" + key + " (" + style.fileName + ")");
+ }
+ hashMap.clear();
+ }
+
+ public void remove(String key) {
+ Style style = (Style)hashMap.get(key);
+ if (style != null) {
+ log("removing \"" + key + " (" + style.fileName + ")");
+ hashMap.remove(key);
+ } else {
+ log("error, stylesheet \"" + key + "\" not loaded");
+ }
+ }
+
+ public String getContentType(String key) {
+ Style style = (Style)hashMap.get(key);
+ if (style != null) {
+ return getContentType(style.stylesheet);
+ } else {
+ log("error, stylesheet \"" + key + "\" not loaded");
+ return null;
+ }
+ }
+
+ public List list() {
+ log("listing stylesheets...");
+ ArrayList l = new ArrayList();
+ Iterator i = hashMap.keySet().iterator();
+ while (i.hasNext()) {
+ String key = (String)i.next();
+ Style style = (Style)hashMap.get(key);
+ l.add(" " + key + " (" + style.fileName + "; " + getContentType(style.stylesheet) + ")");
+ System.out.println(" " + key + " (" + style.fileName + ")");
+ }
+ log("done!");
+ return l;
+ }
+
+ private ContentHandler applyRec(final Key[] keys, int idx, final ContentHandler saxOutput)
+ throws TransformerConfigurationException, SAXException, IOException
+ {
+ if (idx < 0)
+ return saxOutput;
+ else {
+ final Style style = (Style) hashMap.get(keys[idx].name);
+ if (style == null) {
+ log("cannot apply unknwon stylesheet \"" + keys[idx].name + "\" (aborted)");
+ return null;
+ }
+ return applyStylesheet(style.stylesheet, keys[idx].params, applyRec(keys, idx - 1, saxOutput));
+ }
+ }
+
+ public void apply(String inFile, OutputStream outputStream, Key[] keys, Properties userProperties)
+ throws FileNotFoundException, IOException, TransformerConfigurationException, SAXException, Exception
+ {
+/* File outFile = new File(outFilename);
+ if (outFile.exists())
+ System.out.println("Using cached version\n");
+ else {
+*/
+ final Key[] rkeys = new Key[keys.length];
+ for (int i = 0; i < keys.length; i++)
+ rkeys[i] = keys[keys.length - i - 1];
+
+ Properties outputProperties;
+ Properties defaultProperties;
+ String method;
+
+ if (keys.length > 0) {
+ Style style = (Style) hashMap.get(rkeys[0].name);
+ if (style == null) {
+ log("error, stylesheet \"" + rkeys[0].name + "\" not loaded");
+ return;
+ }
+ outputProperties = style.stylesheet.getOutputProperties();
+ method = userProperties.getProperty("method");
+ if (method == null) method = outputProperties.getProperty("method");
+ if (method == null) method = "xml";
+ defaultProperties = org.apache.xalan.templates.OutputProperties.getDefaultMethodProperties(method);
+ } else {
+ method = userProperties.getProperty("method");
+ if (method == null) method = "xml";
+ outputProperties = org.apache.xalan.templates.OutputProperties.getDefaultMethodProperties(method);
+ defaultProperties = outputProperties;
+ }
+
+ for (Enumeration e = userProperties.propertyNames(); e.hasMoreElements(); ) {
+ String prop = (String) e.nextElement();
+ String value = userProperties.getProperty(prop);
+ if (value.equals("")) {
+ String defaultValue = defaultProperties.getProperty(prop);
+ if (defaultValue != null)
+ outputProperties.setProperty(prop, defaultProperties.getProperty(prop));
+ else
+ outputProperties.remove(prop);
+ } else {
+ outputProperties.setProperty(prop, value);
+ }
+ }
+
+ parseFile(inFile, applyRec(rkeys, rkeys.length - 1, saveFile(outputStream, outputProperties)));
+// }
+ }
+
+ public void reloadAll() throws TransformerConfigurationException, SAXException, IOException {
+ Iterator i = hashMap.keySet().iterator();
+ while (i.hasNext())
+ reload((String)i.next());
+ }
+
+ public void reload(String key) throws TransformerConfigurationException, SAXException, IOException {
+ Style style = (Style)hashMap.get(key);
+
+ log("reloading \"" + key + "\"... ");
+ style.stylesheet = compileStylesheet(style.fileName);
+ style.lastModified = new File(style.fileName).lastModified();
+ log("done!");
+ }
+
+ public void updateAll() throws TransformerConfigurationException, SAXException, IOException {
+ Iterator i = hashMap.keySet().iterator();
+ while (i.hasNext())
+ update((String)i.next());
+ }
+
+ public void update(String key) throws TransformerConfigurationException, SAXException, IOException {
+ Style style = (Style)hashMap.get(key);
+
+ log("updating \"" + key + "\"... ");
+ File styleFile = new File(style.fileName);
+ if (styleFile.lastModified() > style.lastModified) {
+ style.stylesheet = compileStylesheet(style.fileName);
+ style.lastModified = styleFile.lastModified();
+ log("done!");
+ } else
+ log("\"" + key + "\" is up to date");
+ }
+}