]> matita.cs.unibo.it Git - helm.git/blob - helm/uwobo/src/it/unibo/cs/helm/uwobo/Server.java
1) New syntax: methods add, reload and remove can now process multiple
[helm.git] / helm / uwobo / src / it / unibo / cs / helm / uwobo / Server.java
1 package it.unibo.cs.helm.uwobo;
2
3 import java.io.*;
4 import java.net.URL;
5 import java.util.*;
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.*;
14 import org.xml.sax.*;
15 import org.xml.sax.ext.*;
16 import org.xml.sax.helpers.*;
17
18 /**
19 // This file is part of UWOBO, a small and simple XSLT server.
20 // 
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.
25 //
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.
30 //
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.
34 // 
35 // For details, send a mail to <luca.padovani@cs.unibo.it>
36 * @author Luca Padovani, Riccardo Solmi
37 */
38
39 public class Server {
40         private static class Style implements Serializable {
41                 public String fileName;
42                 public long lastModified;
43                 public Templates stylesheet;
44         };
45
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;
52
53         static {
54                 Properties props = new Properties();
55                 try {
56                         InputStream in = Server.class.getResourceAsStream("properties.txt");
57                         props.load(in);
58                         in.close();
59                 } catch (IOException ioe) {
60                         System.err.println("Could not load the version information.");
61                 }
62
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");
68         }
69
70         Server() {
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 +
76                   "\" not found");
77               } else {
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;
84                     try {
85                        istream = new FileInputStream(filename);
86                        ObjectInputStream p = new ObjectInputStream(istream);
87                        Style style = (Style)p.readObject();
88                        istream.close();
89                        hashMap.put(key, style);
90                     } catch (Exception e) {log(e.toString());};
91                  }
92                  log("Serialized stylesheets loaded!");
93               }
94            } else
95               log("Stylesheet serialization is off. Set the property SERIALIZATION_DIR to a non-empty value to turn it on.");
96           
97         }
98
99         private final HashMap hashMap = new HashMap();
100         private static int logCounter = 0;
101         
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);
111                 String res = "";
112                 if(!SERIALIZATION_DIR.equals("")) {
113                    try {
114                       FileOutputStream ostream =
115                          new FileOutputStream(serializationFile);
116                       ObjectOutputStream p = new ObjectOutputStream(ostream);
117                       p.writeObject(style);
118                       p.flush();
119                       ostream.close();
120                       res =
121                        "Stylesheet serialized in \"" + serializationFile + "\"";
122                       log(res);
123                    } catch (FileNotFoundException e) {
124                       res = "Warning: Stylesheet not " +
125                          "serialized. Error opening " + "file \"" +
126                          serializationFile + "\"";
127                       log(res);
128                       res = htmlOfWarning(res);
129                    }
130                 }
131                 return res;
132         }
133
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);
138
139                 if (media != null) {
140                         if (encoding != null)
141                                 return media + "; charset=" + encoding;
142                         return media;
143                 } else {
144                         final String method = oprops.getProperty(OutputKeys.METHOD);
145                         if (method.equals("html"))
146                                 return "text/html";
147                         else if (method.equals("text"))
148                                 return "text/plain";
149                         else 
150                                 return "text/xml";
151                 }
152         }
153
154         private final ContentHandler applyStylesheet(Templates stylesheet, HashMap params, ContentHandler saxOutput)
155         throws TransformerConfigurationException, SAXException
156         {
157                 TransformerHandler th = ((SAXTransformerFactory)TransformerFactory.newInstance()).newTransformerHandler(stylesheet);
158
159                 th.setResult(new SAXResult(saxOutput));
160
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);
168                         }
169                 }
170
171                 return th;
172         }
173
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);
182         }
183
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();
188         }
189
190         public static void log(String msg) {
191                 System.err.println(SERVERNAME + "[" + logCounter++ + "]: " + msg);
192         }
193
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)) {
199                       String msg =
200                          "Warning: Stylesheet already loaded. Reloading...";
201                       log(msg);
202                       String msg2 = reload(key);
203                       return htmlOfWarning(msg) +
204                          (msg2.equals("") ? "" : "<br />" + msg2);
205                    } else {
206                       String res =
207                          "Error: There is already a stylesheet with keyword \""+
208                           key + "\" (aborted)";
209                       log(res);
210                       return htmlOfError(res);
211                    }
212                 }
213
214                 Style style = new Style();
215                 style.fileName = filename;
216                 style.lastModified = new File(filename).lastModified();
217                 String res = compileStylesheet(style,key);
218                 log("done!");
219
220                 hashMap.put(key, style);
221                 return res;
222         }
223
224         public ArrayList removeAll() throws TransformerConfigurationException, SAXException, IOException {
225                 ArrayList res = new ArrayList();
226                 String log = "";
227                 Iterator i = hashMap.keySet().iterator();
228                 while (i.hasNext()) {
229                         String key = (String)i.next();
230                         Style style = (Style)hashMap.get(key);
231                         String msg =
232                          "removing \"" + key + " (" + style.fileName + ")";
233                         res.add(msg);
234                         log(msg);
235                         msg = partialRemove(key,false);
236                         if(!msg.equals(""))
237                            res.add(msg);
238                 }
239                 hashMap.clear();
240                 return res;
241         }
242
243         private String partialRemove(String key, boolean removeFromHashTable) {
244                 String res = "";
245                 Style style = (Style)hashMap.get(key);
246                 if (style != null) {
247                         log("removing \"" + key + " (" + style.fileName + ")");
248                         if (removeFromHashTable)
249                            hashMap.remove(key);
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";
255                               log(res);
256                               res = htmlOfWarning(res);
257                            }
258                         }
259                 } else {
260                         res = "Error: stylesheet \"" + key + "\" not loaded";
261                         log(res);
262                         res = htmlOfError(res);
263                 }
264                 return res;
265         }
266
267         public String remove(String key) {
268            return partialRemove(key,true);
269         }
270
271         public String getContentType(String key) {
272                 Style style = (Style)hashMap.get(key);
273                 if (style != null) {
274                         return getContentType(style.stylesheet);
275                 } else {
276                         log("Error, stylesheet \"" + key + "\" not loaded");
277                         return null;
278                 }
279         }
280
281         public List list() {
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 + ")");
290                 }
291                 log("done!");
292                 return l;
293         }
294
295         private ContentHandler applyRec(final Key[] keys, int idx, final ContentHandler saxOutput)
296         throws TransformerConfigurationException, SAXException, IOException
297         {
298                 if (idx < 0)
299                         return saxOutput;
300                 else {
301                         final Style style = (Style) hashMap.get(keys[idx].name);
302                         if (style == null) {
303                                 log("cannot apply unknwon stylesheet \"" + keys[idx].name + "\" (aborted)");
304                                 return null;
305                         }
306                         return applyStylesheet(style.stylesheet, keys[idx].params, applyRec(keys, idx - 1, saxOutput));
307                 }
308         }
309
310         public void apply(String inFile, OutputStream outputStream, Key[] keys, Properties userProperties)
311         throws IOException, TransformerConfigurationException, SAXException, Exception
312         {
313 /*              File outFile = new File(outFilename);
314                 if (outFile.exists())
315                         System.out.println("Using cached version\n");
316                 else {
317 */                      
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];
321
322                         Properties outputProperties; 
323                         Properties defaultProperties;
324                         String method;
325
326                         if (keys.length > 0) {
327                                 Style style = (Style) hashMap.get(rkeys[0].name);
328                                 if (style == null) {
329                                         log("Error, stylesheet \"" + rkeys[0].name + "\" not loaded");
330                                         return;
331                                 }
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);
337                         } else {
338                                 method = userProperties.getProperty("method");
339                                 if (method == null) method = "xml";
340                                 outputProperties = org.apache.xalan.templates.OutputProperties.getDefaultMethodProperties(method);
341                                 defaultProperties = outputProperties;
342                         }
343
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));
351                                         else
352                                                 outputProperties.remove(prop);
353                                 } else {
354                                         outputProperties.setProperty(prop, value);
355                                 }
356                         }
357                         
358                         parseFile(inFile, applyRec(rkeys, rkeys.length - 1, saveFile(outputStream, outputProperties)));
359 //              }
360         }
361
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);
368                         String msg =
369                          "reloading \"" + key + " (" + style.fileName + ")";
370                         res.add(msg);
371                         log(msg);
372                         msg = reload(key);
373                         if(!msg.equals(""))
374                            res.add(msg);
375                 }
376                 return res;
377         }
378
379         public String reload(String key) throws TransformerConfigurationException, SAXException, IOException {
380                 String res = "";
381                 Style style = (Style)hashMap.get(key);
382                 if (style != null) {
383                    log("reloading \"" + key + "\"... ");
384                    style.lastModified = new File(style.fileName).lastModified();
385                    res= compileStylesheet(style,key);
386                    log("done!");
387                 } else {
388                         res = "Error: stylesheet \"" + key + "\" not loaded";
389                         log(res);
390                         res = htmlOfError(res);
391                 }
392                 return res;
393         }
394
395         private String htmlOfWarning(String message)
396         {
397            return "<b style=\"color: maroon\">" + message+"</b>";
398         }
399
400         private String htmlOfError(String message)
401         {
402            return "<b style=\"color: red\">" + message+"</b>";
403         }
404 }