1 package it.unibo.cs.helm.uwobo;
6 import javax.xml.transform.*;
7 import javax.xml.transform.sax.*;
8 import javax.xml.transform.stream.*;
9 import org.apache.xalan.serialize.*;
10 import org.apache.xalan.xslt.*;
11 import org.apache.xalan.templates.*;
12 import org.apache.xalan.transformer.*;
13 import org.apache.xerces.parsers.*;
15 import org.xml.sax.ext.*;
16 import org.xml.sax.helpers.*;
19 // This file is part of UWOBO, a small and simple XSLT server.
21 // UWOBO is free software; you can redistribute it and/or
22 // modify it under the terms of the GNU General Public License
23 // as published by the Free Software Foundation; either version 2
24 // of the License, or (at your option) any later version.
26 // UWOBO is distributed in the hope that it will be useful,
27 // but WITHOUT ANY WARRANTY; without even the implied warranty of
28 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 // GNU General Public License for more details.
31 // You should have received a copy of the GNU General Public License
32 // along with UWOBO; if not, write to the Free Software
33 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 // For details, send a mail to <luca.padovani@cs.unibo.it>
36 * @author Luca Padovani, Riccardo Solmi
40 private static class Style implements Serializable {
41 public String fileName;
42 public long lastModified;
43 public Templates stylesheet;
46 public static final String SERVERNAME = "uwobo-XSLT-server";
47 public static final String PACKAGE;
48 public static final String VERSION;
49 public static final String DATE;
50 public static final String TIME;
51 public static final String SERIALIZATION_DIR;
54 Properties props = new Properties();
56 InputStream in = Server.class.getResourceAsStream("properties.txt");
59 } catch (IOException ioe) {
60 System.err.println("Could not load the version information.");
63 PACKAGE = props.getProperty("PACKAGE");
64 VERSION = props.getProperty("VERSION");
65 DATE = props.getProperty("DATE");
66 TIME = props.getProperty("TIME");
67 SERIALIZATION_DIR = props.getProperty("SERIALIZATION_DIR");
71 if(!SERIALIZATION_DIR.equals("")) {
72 log("Looking for serialized stylesheets");
73 File [] serialized = new File(SERIALIZATION_DIR).listFiles();
74 if (serialized == null) {
75 log("Serialized stylesheets directory \"" + SERIALIZATION_DIR +
78 for (int i = 0; i < serialized.length ; i++) {
79 File filename = serialized[i];
80 String key = filename.getName();
81 log("Found serialized stylesheet " + key);
82 log("Reloading serialized stylesheet \"" + filename + "\"... ");
83 FileInputStream istream;
85 istream = new FileInputStream(filename);
86 ObjectInputStream p = new ObjectInputStream(istream);
87 Style style = (Style)p.readObject();
89 hashMap.put(key, style);
90 } catch (Exception e) {log(e.toString());};
92 log("Serialized stylesheets loaded!");
95 log("Stylesheet serialization is off. Set the property SERIALIZATION_DIR to a non-empty value to turn it on.");
99 private final HashMap hashMap = new HashMap();
100 private static int logCounter = 0;
102 private final String compileStylesheet(Style style, String key) throws TransformerConfigurationException, SAXException, IOException {
103 StreamSource streamsource =
104 new StreamSource(new URL(style.fileName).openStream());
105 streamsource.setSystemId(style.fileName);
106 Templates templates =
107 ((SAXTransformerFactory)TransformerFactory.newInstance())
108 .newTemplates(streamsource);
109 style.stylesheet = templates;
110 File serializationFile = new File(SERIALIZATION_DIR,key);
112 if(!SERIALIZATION_DIR.equals("")) {
114 FileOutputStream ostream =
115 new FileOutputStream(serializationFile);
116 ObjectOutputStream p = new ObjectOutputStream(ostream);
117 p.writeObject(style);
121 "Stylesheet serialized in \"" + serializationFile + "\"";
123 } catch (FileNotFoundException e) {
124 res = "Warning: Stylesheet not " +
125 "serialized. Error opening " + "file \"" +
126 serializationFile + "\"";
128 res = htmlOfWarning(res);
134 private String getContentType(Templates templates) {
135 final Properties oprops = templates.getOutputProperties();
136 final String encoding = oprops.getProperty(OutputKeys.ENCODING);
137 final String media = oprops.getProperty(OutputKeys.MEDIA_TYPE);
140 if (encoding != null)
141 return media + "; charset=" + encoding;
144 final String method = oprops.getProperty(OutputKeys.METHOD);
145 if (method.equals("html"))
147 else if (method.equals("text"))
154 private final ContentHandler applyStylesheet(Templates stylesheet, HashMap params, ContentHandler saxOutput)
155 throws TransformerConfigurationException, SAXException
157 TransformerHandler th = ((SAXTransformerFactory)TransformerFactory.newInstance()).newTransformerHandler(stylesheet);
159 th.setResult(new SAXResult(saxOutput));
161 if (params != null) {
162 final Transformer transformer = th.getTransformer();
163 Iterator i = params.keySet().iterator();
164 while (i.hasNext()) {
165 final String name = (String) i.next();
166 final String value = (String) params.get(name);
167 transformer.setParameter(name, value);
174 private final void parseFile(String datasheet, ContentHandler saxOutput) throws SAXException, IOException, Exception {
175 final XMLReader reader = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
176 reader.setFeature("http://xml.org/sax/features/namespaces", true);
177 reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
178 reader.setContentHandler(saxOutput);
179 if (saxOutput instanceof LexicalHandler)
180 reader.setProperty("http://xml.org/sax/properties/lexical-handler", (LexicalHandler)saxOutput);
181 reader.parse(datasheet);
184 private final ContentHandler saveFile(OutputStream outputStream, Properties props) throws IOException {
185 final Serializer ser = SerializerFactory.getSerializer(props);
186 ser.setOutputStream(outputStream);
187 return ser.asContentHandler();
190 public static void log(String msg) {
191 System.err.println(SERVERNAME + "[" + logCounter++ + "]: " + msg);
194 public String add(String filename, String key) throws TransformerConfigurationException, SAXException, IOException {
195 log("processing stylesheet \"" + filename + "\" using key " + key + "... ");
196 if (hashMap.containsKey(key)) {
197 Style style = (Style)hashMap.get(key);
198 if (style.fileName.equals(filename)) {
200 "Warning: Stylesheet already loaded. Reloading...";
202 String msg2 = reload(key);
203 return htmlOfWarning(msg) +
204 (msg2.equals("") ? "" : "<br />" + msg2);
207 "Error: There is already a stylesheet with keyword \""+
208 key + "\" (aborted)";
210 return htmlOfError(res);
214 Style style = new Style();
215 style.fileName = filename;
216 style.lastModified = new File(filename).lastModified();
217 String res = compileStylesheet(style,key);
220 hashMap.put(key, style);
224 public ArrayList removeAll() throws TransformerConfigurationException, SAXException, IOException {
225 ArrayList res = new ArrayList();
227 Iterator i = hashMap.keySet().iterator();
228 while (i.hasNext()) {
229 String key = (String)i.next();
230 Style style = (Style)hashMap.get(key);
232 "removing \"" + key + " (" + style.fileName + ")";
235 msg = partialRemove(key,false);
243 private String partialRemove(String key, boolean removeFromHashTable) {
245 Style style = (Style)hashMap.get(key);
247 log("removing \"" + key + " (" + style.fileName + ")");
248 if (removeFromHashTable)
250 if(!SERIALIZATION_DIR.equals("")) {
251 File to_delete = new File(SERIALIZATION_DIR,key);
252 if (!to_delete.delete()) {
253 res = "Warning: Serialized stylesheet \"" +
254 to_delete + "\" to remove not found";
256 res = htmlOfWarning(res);
260 res = "Error: stylesheet \"" + key + "\" not loaded";
262 res = htmlOfError(res);
267 public String remove(String key) {
268 return partialRemove(key,true);
271 public String getContentType(String key) {
272 Style style = (Style)hashMap.get(key);
274 return getContentType(style.stylesheet);
276 log("Error, stylesheet \"" + key + "\" not loaded");
282 log("listing stylesheets...");
283 ArrayList l = new ArrayList();
284 Iterator i = hashMap.keySet().iterator();
285 while (i.hasNext()) {
286 String key = (String)i.next();
287 Style style = (Style)hashMap.get(key);
288 l.add(" " + key + " (" + style.fileName + "; " + getContentType(style.stylesheet) + ")");
289 System.out.println(" " + key + " (" + style.fileName + ")");
295 private ContentHandler applyRec(final Key[] keys, int idx, final ContentHandler saxOutput)
296 throws TransformerConfigurationException, SAXException, IOException
301 final Style style = (Style) hashMap.get(keys[idx].name);
303 log("cannot apply unknwon stylesheet \"" + keys[idx].name + "\" (aborted)");
306 return applyStylesheet(style.stylesheet, keys[idx].params, applyRec(keys, idx - 1, saxOutput));
310 public void apply(String inFile, OutputStream outputStream, Key[] keys, Properties userProperties)
311 throws IOException, TransformerConfigurationException, SAXException, Exception
313 /* File outFile = new File(outFilename);
314 if (outFile.exists())
315 System.out.println("Using cached version\n");
318 final Key[] rkeys = new Key[keys.length];
319 for (int i = 0; i < keys.length; i++)
320 rkeys[i] = keys[keys.length - i - 1];
322 Properties outputProperties;
323 Properties defaultProperties;
326 if (keys.length > 0) {
327 Style style = (Style) hashMap.get(rkeys[0].name);
329 log("Error, stylesheet \"" + rkeys[0].name + "\" not loaded");
332 outputProperties = style.stylesheet.getOutputProperties();
333 method = userProperties.getProperty("method");
334 if (method == null) method = outputProperties.getProperty("method");
335 if (method == null) method = "xml";
336 defaultProperties = org.apache.xalan.templates.OutputProperties.getDefaultMethodProperties(method);
338 method = userProperties.getProperty("method");
339 if (method == null) method = "xml";
340 outputProperties = org.apache.xalan.templates.OutputProperties.getDefaultMethodProperties(method);
341 defaultProperties = outputProperties;
344 for (Enumeration e = userProperties.propertyNames(); e.hasMoreElements(); ) {
345 String prop = (String) e.nextElement();
346 String value = userProperties.getProperty(prop);
347 if (value.equals("")) {
348 String defaultValue = defaultProperties.getProperty(prop);
349 if (defaultValue != null)
350 outputProperties.setProperty(prop, defaultProperties.getProperty(prop));
352 outputProperties.remove(prop);
354 outputProperties.setProperty(prop, value);
358 parseFile(inFile, applyRec(rkeys, rkeys.length - 1, saveFile(outputStream, outputProperties)));
362 public ArrayList reloadAll() throws TransformerConfigurationException, SAXException, IOException {
363 ArrayList res = new ArrayList();
364 Iterator i = hashMap.keySet().iterator();
365 while (i.hasNext()) {
366 String key = (String)i.next();
367 Style style = (Style)hashMap.get(key);
369 "reloading \"" + key + " (" + style.fileName + ")";
379 public String reload(String key) throws TransformerConfigurationException, SAXException, IOException {
381 Style style = (Style)hashMap.get(key);
383 log("reloading \"" + key + "\"... ");
384 style.lastModified = new File(style.fileName).lastModified();
385 res= compileStylesheet(style,key);
388 res = "Error: stylesheet \"" + key + "\" not loaded";
390 res = htmlOfError(res);
395 private String htmlOfWarning(String message)
397 return "<b style=\"color: maroon\">" + message+"</b>";
400 private String htmlOfError(String message)
402 return "<b style=\"color: red\">" + message+"</b>";