source: greenstone3/trunk/src/java/org/greenstone/gsdl3/core/Skin.java@ 16314

Last change on this file since 16314 was 16314, checked in by davidb, 16 years ago

Merging of skin work with the main trunk

File size: 15.3 KB
Line 
1package org.greenstone.gsdl3.core;
2
3import java.io.*;
4
5import org.apache.xerces.parsers.DOMParser;
6import org.greenstone.gsdl3.util.*;
7import org.w3c.dom.*;
8import org.xml.sax.InputSource;
9
10import java.util.*;
11import javax.xml.transform.*;
12import javax.xml.transform.dom.*;
13import javax.xml.transform.dom.DOMSource;
14import javax.xml.transform.stream.*;
15
16
17
18
19public class Skin {
20
21 public File rootDirectory ;
22 public Document config ;
23 private Receptionist receptionist ;
24
25 protected DOMParser parser = null;
26 TransformerFactory transformerFactory=null;
27
28 // delete this later??
29 //protected XMLConverter converter = null;
30
31 private HashMap<String, String> xsltPagesByAction ;
32
33 public Skin(Page page, Receptionist receptionist) throws Exception{
34
35 this.receptionist = receptionist ;
36 this.transformerFactory = org.apache.xalan.processor.TransformerFactoryImpl.newInstance();
37 //this.converter = new XMLConverter();
38 transformerFactory.setURIResolver(new MyUriResolver()) ;
39
40 this.parser = new DOMParser();
41 this.parser.setFeature("http://xml.org/sax/features/validation", true);
42 // don't try and load external DTD - no need if we are not validating, and may cause connection errors if a proxy is not set up.
43 this.parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
44 // a performance test showed that having this on lead to increased
45 // memory use for small-medium docs, and not much gain for large
46 // docs.
47 // http://www.sosnoski.com/opensrc/xmlbench/conclusions.html
48 this.parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
49
50
51
52 String siteHome = GSFile.siteHome(GlobalProperties.getGSDL3Home(), page.getSite()) ;
53 Document collectUi = page.getCollectUi() ;
54
55 if (collectUi != null) {
56 //System.out.println("looking for skin defined at collect level") ;
57
58 String collectHome = GSFile.collectionBaseDir(siteHome, page.getCollection()) ;
59 Element xmlSkin = (Element) GSXML.getChildByTagName(collectUi.getFirstChild(), "skin") ;
60 if (xmlSkin != null) {
61 //System.out.println("skin defined at collect level") ;
62
63 boolean inherit = Boolean.parseBoolean(xmlSkin.getAttribute("inherit")) ;
64
65 if (inherit != true) {
66 boolean local = Boolean.parseBoolean(xmlSkin.getAttribute("local")) ;
67 if (local == true) {
68 rootDirectory = new File(collectHome + File.separatorChar + "ui") ;
69 } else {
70 String name = xmlSkin.getAttribute("name") ;
71 rootDirectory = new File(GlobalProperties.getGSDL3Home() + File.separatorChar + "ui" + File.separatorChar + "skins" + File.separatorChar + File.separatorChar + name) ;
72 }
73 }
74 }
75 }
76
77 Document siteUi = page.getSiteUi() ;
78
79 if (rootDirectory == null && siteUi != null) {
80 //System.out.println("lookding for skin defined at site level") ;
81
82 Element xmlSkin = (Element) GSXML.getChildByTagName(siteUi.getFirstChild(), "skin") ;
83 if (xmlSkin != null) {
84 //System.out.println("skin defined at site level") ;
85 boolean local = Boolean.parseBoolean(xmlSkin.getAttribute("local")) ;
86 if (local == true) {
87 rootDirectory = new File(siteHome + File.separatorChar + "ui") ;
88 } else {
89 String name = xmlSkin.getAttribute("name") ;
90 rootDirectory = new File(GlobalProperties.getGSDL3Home() + File.separatorChar + "ui" + File.separatorChar + "skins" + File.separatorChar + name) ;
91 }
92 }
93 }
94
95 if(rootDirectory == null) {
96 rootDirectory = new File(GlobalProperties.getGSDL3Home() + File.separatorChar + "ui" + File.separatorChar + "skins" + File.separatorChar + "default") ;
97 }
98
99
100 File configFile = new File(rootDirectory.getAbsolutePath() + File.separatorChar + "skin.xml") ;
101 config = receptionist.converter.getDOM(configFile, "utf-8");
102
103
104 // store which xslt pages are responsible for which actions
105
106 xsltPagesByAction = new HashMap() ;
107
108 NodeList actions = config.getElementsByTagName("action") ;
109
110 for (int ai=0 , an=actions.getLength() ; ai<an ; ai++){
111 Element action = (Element) actions.item(ai) ;
112 String a = action.getAttribute("name") ;
113
114 String xsl = action.getAttribute("xslt") ;
115 if (!xsl.equals(""))
116 xsltPagesByAction.put(a, xsl) ;
117
118 NodeList subactions = action.getElementsByTagName("subaction") ;
119
120 for (int si=0 , sn=subactions.getLength() ; si<sn ; si++){
121 Element subaction = (Element) subactions.item(si) ;
122
123 String sa = subaction.getAttribute("name") ;
124 xsl = subaction.getAttribute("xslt") ;
125 xsltPagesByAction.put(a + "_" + sa, xsl) ;
126 }
127 }
128 }
129
130 private Document getXSLTDoc(String action, String subaction) throws Exception {
131 //System.out.println("getting xslt for " + action + ", " + subaction) ;
132
133 String name = xsltPagesByAction.get(action + "_" + subaction) ;
134
135 if (name == null)
136 name = xsltPagesByAction.get(action) ;
137
138 File xslt_file = new File(rootDirectory.getAbsolutePath() + File.separatorChar + "xsl" + File.separatorChar + name) ;
139 //System.out.println("Skinning page using: " + xslt_file) ;
140
141 //if (!xslt_file.canRead())
142 // xslt_file = new File(GlobalProperties.getGSDL3Home() + File.separatorChar + "ui" + File.separatorChar + "xslt" + File.separatorChar + "error.xsl") ;
143
144 FileReader reader = new FileReader(xslt_file);
145 InputSource xml_source = new InputSource(reader);
146 this.parser.parse(xml_source);
147 Document doc = this.parser.getDocument();
148
149 return doc ;
150 }
151
152 private Document getPreprocessDoc() throws Exception {
153
154 File xslt_file = new File(GlobalProperties.getGSDL3Home() + File.separatorChar + "ui" + File.separatorChar + "xslt" + File.separatorChar + "preProcess.xsl") ;
155
156 FileReader reader = new FileReader(xslt_file);
157 InputSource xml_source = new InputSource(reader);
158 this.parser.parse(xml_source);
159 Document doc = this.parser.getDocument();
160
161 return doc ;
162 }
163
164 private Document getLibraryDoc() throws Exception {
165
166 File xslt_file = new File(GlobalProperties.getGSDL3Home() + File.separatorChar + "ui" + File.separatorChar + "xslt" + File.separatorChar + "library.xsl") ;
167
168 FileReader reader = new FileReader(xslt_file);
169 InputSource xml_source = new InputSource(reader);
170 this.parser.parse(xml_source);
171 Document doc = this.parser.getDocument();
172
173 return doc ;
174 }
175
176
177 public Element transformPage(Page page) throws Exception{
178
179 Element p = page.getPage() ;
180 Element pr = page.getPageResponse() ;
181 Element transformedPage = null ;
182
183 Element blah = receptionist.doc.createElement("Skin") ;
184 blah.setAttribute("skinLocation", rootDirectory.getAbsolutePath()) ;
185 pr.appendChild(blah) ;
186
187 Document sourceXml ;
188 try {
189 sourceXml = receptionist.converter.newDOM();
190 sourceXml.appendChild(sourceXml.importNode(p, true));
191 } catch (Exception e) {
192 System.out.println("error loading source data") ;
193 e.printStackTrace() ;
194 return constructErrorPage(e) ;
195 }
196
197 Document skinXsl ;
198 try {
199 skinXsl = getXSLTDoc(page.getAction(), page.getSubaction()) ;
200 } catch (Exception e) {
201 System.out.println("error loading skin xslt") ;
202 e.printStackTrace() ;
203 return constructErrorPage(e) ;
204 }
205
206 Document preprocessingXsl ;
207 try {
208 preprocessingXsl = getPreprocessDoc() ;
209 } catch (Exception e) {
210 System.out.println("error loading preprocessing xslt") ;
211 e.printStackTrace() ;
212 return constructErrorPage(e) ;
213 }
214
215 Document libraryXsl ;
216 try {
217 libraryXsl = getLibraryDoc() ;
218 } catch (Exception e) {
219 System.out.println("error loading preprocessing xslt") ;
220 e.printStackTrace() ;
221 return constructErrorPage(e) ;
222 }
223
224 // combine skin file and library variables/templates into one document.
225 // we dont just use xsl:import because the preprocessing stage needs
226 // to know what's available in the library.
227
228 Document skinAndLibraryXsl ;
229 Document processedXsl = receptionist.converter.newDOM();
230 try {
231
232 skinAndLibraryXsl = receptionist.converter.newDOM();
233 Element root = skinAndLibraryXsl.createElement("skinAndLibraryXsl") ;
234 skinAndLibraryXsl.appendChild(root) ;
235
236 Element s = skinAndLibraryXsl.createElement("skinXsl") ;
237 s.appendChild(skinAndLibraryXsl.importNode(skinXsl.getDocumentElement(), true)) ;
238 root.appendChild(s) ;
239
240 Element l = skinAndLibraryXsl.createElement("libraryXsl") ;
241 l.appendChild(skinAndLibraryXsl.importNode(libraryXsl.getDocumentElement(), true)) ;
242 root.appendChild(l) ;
243
244
245 System.out.println("Pre - processing") ;
246 //pre-process the skin style sheet
247 Transformer preProcessor = transformerFactory.newTransformer(new DOMSource(preprocessingXsl));
248 DOMResult result = new DOMResult();
249 result.setNode(processedXsl) ;
250 preProcessor.transform(new DOMSource(skinAndLibraryXsl), result);
251 } catch (TransformerException e) {
252 return constructErrorPage(e) ;
253 } catch (Exception e) {
254 System.out.println("error preprocessing the skin xslt") ;
255 e.printStackTrace() ;
256 return constructErrorPage(e) ;
257 }
258
259 //return sourceXml.getDocumentElement() ;
260
261 Document finalPage = receptionist.converter.newDOM();
262 //transform source doc
263 try {
264
265 //Tranform XSL DOM to String
266 TransformerFactory tf = TransformerFactory.newInstance();
267 Transformer trans = tf.newTransformer();
268 StringWriter sw = new StringWriter();
269 trans.transform(new DOMSource(processedXsl), new StreamResult(sw));
270 String theXSLAnswer = sw.toString();
271
272 //writefile("c:\\mr49\\stylesheet.xsl", theXSLAnswer);
273
274
275 //Tranform XML DOM to String
276 TransformerFactory tf2 = TransformerFactory.newInstance();
277 Transformer trans2 = tf2.newTransformer();
278 StringWriter sw2 = new StringWriter();
279 trans2.transform(new DOMSource(sourceXml), new StreamResult(sw2));
280 String theXMLAnswer = sw2.toString();
281
282 //writefile("c:\\mr49\\xml.xml", theXMLAnswer);
283
284
285 Transformer transformer = transformerFactory.newTransformer(new DOMSource(processedXsl));
286 //Transformer transformer = transformerFactory.newTransformer(new StreamSource("c:\\mr49\\stylesheet.xsl"));
287 transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd");
288 DOMResult result = new DOMResult();
289 result.setNode(finalPage);
290
291 //transformer.transform(new DOMSource(sourceXml), result2);
292 StringWriter result2 = new StringWriter();
293 transformer.transform(new DOMSource(sourceXml), result);
294
295 //transformer.transform(new DOMSource(sourceXml), new StreamResult(result2));
296 //writefile("c:\\mr49\\result.html", result2.toString());
297 //System.err.println("outputting result:");
298 //System.err.println(this.converter.getPrettyString(finalPage));
299 /*
300 //Testing stuff
301
302 TransformerFactory tFactory = TransformerFactory.newInstance();
303 Transformer with identity transformation
304 Transformer transformer2 = tFactory.newTransformer(new DOMSource(processedXsl));
305
306 String xml="<root><a><b><c>aaa</c></b></a></root>";
307 StringWriter result2 = new StringWriter();
308 //Transfrom xml (in String) to formatted xml (in String)
309 transformer2.transform(new StreamSource(new StringReader(theXMLAnswer)), new StreamResult(result2));
310 //Output result
311 writefile("c:\\mr49\\testHTML.txt", result2.toString());
312 */
313
314
315
316
317 } catch (TransformerException e) {
318 return constructErrorPage(e) ;
319 } catch (Exception e) {
320
321 System.out.println("error transforming page") ;
322 e.printStackTrace() ;
323
324 //return processedXsl.getDocumentElement() ;
325 return constructErrorPage(e) ;
326 }
327
328 return finalPage.getDocumentElement() ;
329 }
330
331 private Element constructErrorPage(TransformerException exception) {
332 Element page = receptionist.doc.createElement("page") ;
333
334 Element header = receptionist.doc.createElement("h1") ;
335 header.setTextContent("Error") ;
336 page.appendChild(header) ;
337
338 Element prompt = receptionist.doc.createElement("p") ;
339 prompt.setTextContent("The following exception occured: ") ;
340 page.appendChild((prompt)) ;
341
342 Element errorXml = receptionist.doc.createElement("code") ;
343 errorXml.setTextContent(exception.getMessageAndLocation()) ;
344 page.appendChild(errorXml) ;
345
346 return page ;
347
348 }
349
350 private Element constructErrorPage(Exception exception) {
351 Element page = receptionist.doc.createElement("page") ;
352
353 Element header = receptionist.doc.createElement("h1") ;
354 header.setTextContent("Error") ;
355 page.appendChild(header) ;
356
357 Element prompt = receptionist.doc.createElement("p") ;
358 prompt.setTextContent("The following exception occured: ") ;
359 page.appendChild((prompt)) ;
360
361 Element errorXml = receptionist.doc.createElement("code") ;
362 errorXml.setTextContent(exception.toString()) ;
363 page.appendChild(errorXml) ;
364
365
366 return page ;
367 }
368
369
370 private Element constructErrorPage(Element source, Document style, Exception exception) {
371 Element page = receptionist.doc.createElement("page") ;
372
373 Element header = receptionist.doc.createElement("h1") ;
374 header.setTextContent("Error") ;
375 page.appendChild(header) ;
376
377 Element prompt = receptionist.doc.createElement("p") ;
378 prompt.setTextContent("The following exception occured: ") ;
379 page.appendChild((prompt)) ;
380
381 Element errorXml = receptionist.doc.createElement("code") ;
382 errorXml.setTextContent(exception.getMessage()) ;
383 page.appendChild(errorXml) ;
384
385 /*
386 Element stackTrace = receptionist.doc.createElement("ul") ;
387
388 StackTraceElement[] st = exception.getStackTrace() ;
389 for (int i=0 ; i< st.length ; i++) {
390 Element ste = receptionist.doc.createElement("li") ;
391 ste.setTextContent(st[i].toString()) ;
392 stackTrace.appendChild(ste) ;
393 }
394 errorMessage.appendChild(stackTrace) ;
395 */
396
397 Element sourceHeader = receptionist.doc.createElement("h2") ;
398 sourceHeader.setTextContent("Source page:") ;
399 page.appendChild(sourceHeader) ;
400
401 Element sourceXml = receptionist.doc.createElement("pre") ;
402 sourceXml.setTextContent(receptionist.converter.getPrettyString(source)) ;
403 page.appendChild(sourceXml) ;
404
405 Element styleHeader = receptionist.doc.createElement("h2") ;
406 styleHeader.setTextContent("Style page:") ;
407 page.appendChild(styleHeader) ;
408
409 Element styleXml = receptionist.doc.createElement("pre") ;
410 styleXml.setTextContent(receptionist.converter.getPrettyString(style)) ;
411 page.appendChild(styleXml) ;
412
413
414 return (Element)page ;
415 }
416
417 private class MyUriResolver implements URIResolver {
418
419 public Source resolve(String href, String base) {
420
421 System.out.println("resolving href='" + href + "', base='" + base + "'") ;
422
423 // check in the skin directory first
424
425 File file = new File(rootDirectory.getAbsolutePath() + File.separatorChar + "xslt" + File.separatorChar + href) ;
426
427 // then check in the xslt library directory
428 if (!file.canRead())
429 file = new File(GlobalProperties.getGSDL3Home() + File.separatorChar + "ui" + File.separatorChar + "xslt" + File.separatorChar + href) ;
430
431 if (file.canRead()) {
432 Source source = new StreamSource(file) ;
433 return source ;
434 } else
435 return null ;
436 }
437
438 }
439
440 private void writefile(String filename, String contents){
441
442 File testFile = new File(filename);
443
444
445 //use buffering
446
447
448 try {
449 Writer output = new BufferedWriter(new FileWriter(testFile));
450 //FileWriter always assumes default encoding is OK!
451 output.write( contents );
452 output.close();
453 }
454
455 catch (Exception e) {
456 e.printStackTrace();
457 }
458
459
460
461 }
462
463}
464
Note: See TracBrowser for help on using the repository browser.