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