source: greenstone3/trunk/src/java/org/greenstone/gsdl3/core/TransformingReceptionist.java@ 16374

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

Change to Skin code (returning Node note Element) so XSLT encodes its DocType -- important information for IE to render resultant HTML correctly. This also required Skin.java to be changed from using DomResult to StreamResult. The former is known to have a problem with loosing its DocType info, and as it's then read-only, has no elegant way to put back this info.

  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 KB
Line 
1package org.greenstone.gsdl3.core;
2
3import org.greenstone.gsdl3.util.*;
4import org.greenstone.gsdl3.action.*;
5// XML classes
6import org.w3c.dom.Node;
7import org.w3c.dom.NodeList;
8import org.w3c.dom.Document;
9import org.w3c.dom.Element;
10
11// other java classes
12import java.io.File;
13import java.util.HashMap;
14import java.util.Enumeration;
15
16import org.apache.log4j.*;
17
18/** A receptionist that uses xslt to transform the page_data before returning it. . Receives requests consisting
19 * of an xml representation of cgi args, and returns the page of data - in
20 * html by default. The requests are processed by the appropriate action class
21 *
22 * @see Action
23 */
24public class TransformingReceptionist extends Receptionist{
25
26 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.TransformingReceptionist.class.getName());
27
28 /** the list of xslt to use for actions */
29 protected HashMap xslt_map = null;
30
31 /** a transformer class to transform xml using xslt */
32 protected XMLTransformer transformer=null;
33
34 public TransformingReceptionist() {
35 super();
36 this.xslt_map = new HashMap();
37 this.transformer = new XMLTransformer();
38 }
39
40 /** configures the receptionist - overwrite this to set up the xslt map*/
41 public boolean configure() {
42
43 if (this.config_params==null) {
44 logger.error(" config variables must be set before calling configure");
45 return false;
46 }
47 if (this.mr==null) {
48 logger.error(" message router must be set before calling configure");
49 return false;
50 }
51
52 // find the config file containing a list of actions
53 File interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String)this.config_params.get(GSConstants.INTERFACE_NAME))));
54 if (!interface_config_file.exists()) {
55 logger.error(" interface config file: "+interface_config_file.getPath()+" not found!");
56 return false;
57 }
58 Document config_doc = this.converter.getDOM(interface_config_file, "utf-8");
59 if (config_doc == null) {
60 logger.error(" could not parse interface config file: "+interface_config_file.getPath());
61 return false;
62 }
63 Element config_elem = config_doc.getDocumentElement();
64 String base_interface = config_elem.getAttribute("baseInterface");
65 setUpBaseInterface(base_interface);
66 setUpInterfaceOptions(config_elem);
67
68 Element action_list = (Element)GSXML.getChildByTagName(config_elem, GSXML.ACTION_ELEM+GSXML.LIST_MODIFIER);
69 NodeList actions = action_list.getElementsByTagName(GSXML.ACTION_ELEM);
70
71 for (int i=0; i<actions.getLength(); i++) {
72 Element action = (Element) actions.item(i);
73 String class_name = action.getAttribute("class");
74 String action_name = action.getAttribute("name");
75 Action ac = null;
76 try {
77 ac = (Action)Class.forName("org.greenstone.gsdl3.action."+class_name).newInstance();
78 } catch (Exception e) {
79 logger.error(" couldn't load in action "+class_name);
80 e.printStackTrace();
81 continue;
82 }
83 ac.setConfigParams(this.config_params);
84 ac.setMessageRouter(this.mr);
85 ac.configure();
86 ac.getActionParameters(this.params);
87 this.action_map.put(action_name, ac);
88
89 // now do the xslt map
90 String xslt = action.getAttribute("xslt");
91 if (!xslt.equals("")) {
92 this.xslt_map.put(action_name, xslt);
93 }
94 NodeList subactions = action.getElementsByTagName(GSXML.SUBACTION_ELEM);
95 for (int j=0; j<subactions.getLength(); j++) {
96 Element subaction = (Element)subactions.item(j);
97 String subname = subaction.getAttribute(GSXML.NAME_ATT);
98 String subxslt = subaction.getAttribute("xslt");
99
100 String map_key = action_name+":"+subname;
101 logger.debug("adding in to xslt map, "+map_key+"->"+subxslt);
102 this.xslt_map.put(map_key, subxslt);
103 }
104
105
106 }
107 Element lang_list = (Element)GSXML.getChildByTagName(config_elem, "languageList");
108 if (lang_list == null) {
109 logger.error(" didn't find a language list in the config file!!");
110 } else {
111 this.language_list = (Element) this.doc.importNode(lang_list, true);
112 }
113
114 return true;
115 }
116
117
118 protected Node postProcessPage(Element page) {
119
120 // might need to add some data to the page
121 addExtraInfo(page);
122 // transform the page using xslt
123 Node transformed_page = transformPage(page);
124
125 return transformed_page;
126 }
127
128 /** overwrite this to add any extra info that might be needed in the page before transformation */
129 protected void addExtraInfo(Element page) {}
130
131 /** transform the page using xslt
132 * we need to get any format element out of the page and add it to the xslt
133 * before transforming */
134 protected Node transformPage(Element page) {
135
136 logger.debug("page before transfomring:");
137 logger.debug(this.converter.getPrettyString(page));
138
139 Element request = (Element)GSXML.getChildByTagName(page, GSXML.PAGE_REQUEST_ELEM);
140 String action = request.getAttribute(GSXML.ACTION_ATT);
141 String subaction = request.getAttribute(GSXML.SUBACTION_ATT);
142
143 String output = request.getAttribute(GSXML.OUTPUT_ATT);
144 // we should choose how to transform the data based on output, eg diff
145 // choice for html, and wml??
146 // for now, if output=xml, we don't transform the page, we just return
147 // the page xml
148 if (output.equals("xml")) {
149 return page;
150 }
151
152 Element cgi_param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
153 String collection = "";
154 if (cgi_param_list != null) {
155 HashMap params = GSXML.extractParams(cgi_param_list, false);
156 collection = (String)params.get(GSParams.COLLECTION);
157 if (collection == null) collection = "";
158 }
159
160 String xslt_file = getXSLTFileName(action, subaction, collection);
161 if (xslt_file==null) {
162 // cant transform the page - return null or the original?
163 logger.error(" cant find the xslt file needed, so returning the original page!");
164 return page;
165 }
166 Document style_doc = this.converter.getDOM(new File(xslt_file), "UTF-8");
167 if (style_doc == null) {
168 logger.error(" cant parse the xslt file needed, so returning the original page!");
169 return page;
170
171 }
172
173 // look for the format element in the page response
174 Element page_response = (Element)GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM);
175 Element format_elem = (Element)GSXML.getChildByTagName(page_response, GSXML.FORMAT_ELEM);
176 if (format_elem != null) {
177 //page_response.removeChild(format_elem);
178 logger.debug("format elem="+this.converter.getPrettyString(format_elem));
179 // need to transform the format info
180 String stylesheet_file = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String)this.config_params.get(GSConstants.SITE_NAME), collection, (String)this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, "config_format.xsl");
181 Document stylesheet_doc = this.converter.getDOM(new File(stylesheet_file));
182 if (stylesheet_doc != null) {
183 Document format_doc = this.converter.newDOM();
184 format_doc.appendChild(format_doc.importNode(format_elem, true));
185 Element new_format = (Element)this.transformer.transform(stylesheet_doc, format_doc);
186 logger.debug("new format elem="+this.converter.getPrettyString(new_format));
187
188 // add it in to the main stylesheet
189 GSXSLT.mergeStylesheets(style_doc, new_format);
190 } else {
191 logger.error(" couldn't parse the config_format stylesheet, adding the format info as is");
192 GSXSLT.mergeStylesheets(style_doc, format_elem);
193 }
194 logger.debug("the converted stylesheet is:");
195 logger.debug(this.converter.getPrettyString(style_doc.getDocumentElement()));
196 }
197
198 // there is a thing called a URIResolver which you can set for a
199 // transformer or transformer factory. may be able to use this
200 // instead of this absoluteIncludepaths hack
201
202 GSXSLT.absoluteIncludePaths(style_doc, GlobalProperties.getGSDL3Home(),
203 (String)this.config_params.get(GSConstants.SITE_NAME),
204 collection, (String)this.config_params.get(GSConstants.INTERFACE_NAME),
205 base_interfaces);
206
207 // put the page into a document - this is necessary for xslt to get
208 // the paths right if you have paths relative to the document root
209 // eg /page.
210
211 Document doc = this.converter.newDOM();
212 doc.appendChild(doc.importNode(page, true));
213 return (Element)this.transformer.transform(style_doc, doc, config_params);
214 }
215
216 protected String getXSLTFileName(String action, String subaction,
217 String collection) {
218
219 String name = null;
220 if (!subaction.equals("")) {
221 String key = action+":"+subaction;
222 name = (String) this.xslt_map.get(key);
223 }
224 // try the action by itself
225 if (name==null) {
226 name = (String) this.xslt_map.get(action);
227 }
228 // now find the absolute path
229 String stylesheet = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String)this.config_params.get(GSConstants.SITE_NAME), collection, (String)this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, name);
230 if (stylesheet==null) {
231 logger.info(" cant find stylesheet for "+name);
232 }
233 return stylesheet;
234 }
235
236}
Note: See TracBrowser for help on using the repository browser.