package org.greenstone.gsdl3.core; import org.greenstone.gsdl3.util.*; import org.greenstone.gsdl3.action.*; // XML classes import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Document; import org.w3c.dom.Element; // other java classes import java.io.File; import java.util.HashMap; import java.util.Enumeration; import org.apache.log4j.*; /** A receptionist that uses xslt to transform the page_data before returning it. . Receives requests consisting * of an xml representation of cgi args, and returns the page of data - in * html by default. The requests are processed by the appropriate action class * * @see Action */ public class TransformingReceptionist extends Receptionist{ static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.TransformingReceptionist.class.getName()); /** the list of xslt to use for actions */ protected HashMap xslt_map = null; /** a transformer class to transform xml using xslt */ protected XMLTransformer transformer=null; public TransformingReceptionist() { super(); this.xslt_map = new HashMap(); this.transformer = new XMLTransformer(); } /** configures the receptionist - overwrite this to set up the xslt map*/ public boolean configure() { if (this.config_params==null) { logger.error(" config variables must be set before calling configure"); return false; } if (this.mr==null) { logger.error(" message router must be set before calling configure"); return false; } // find the config file containing a list of actions File interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String)this.config_params.get(GSConstants.INTERFACE_NAME)))); if (!interface_config_file.exists()) { logger.error(" interface config file: "+interface_config_file.getPath()+" not found!"); return false; } Document config_doc = this.converter.getDOM(interface_config_file, "utf-8"); if (config_doc == null) { logger.error(" could not parse interface config file: "+interface_config_file.getPath()); return false; } Element config_elem = config_doc.getDocumentElement(); String base_interface = config_elem.getAttribute("baseInterface"); setUpBaseInterface(base_interface); setUpInterfaceOptions(config_elem); Element action_list = (Element)GSXML.getChildByTagName(config_elem, GSXML.ACTION_ELEM+GSXML.LIST_MODIFIER); NodeList actions = action_list.getElementsByTagName(GSXML.ACTION_ELEM); for (int i=0; i"+subxslt); this.xslt_map.put(map_key, subxslt); } } Element lang_list = (Element)GSXML.getChildByTagName(config_elem, "languageList"); if (lang_list == null) { logger.error(" didn't find a language list in the config file!!"); } else { this.language_list = (Element) this.doc.importNode(lang_list, true); } return true; } protected Node postProcessPage(Element page) { // might need to add some data to the page addExtraInfo(page); // transform the page using xslt Node transformed_page = transformPage(page); return transformed_page; } /** overwrite this to add any extra info that might be needed in the page before transformation */ protected void addExtraInfo(Element page) {} /** transform the page using xslt * we need to get any format element out of the page and add it to the xslt * before transforming */ protected Node transformPage(Element page) { logger.debug("page before transfomring:"); logger.debug(this.converter.getPrettyString(page)); Element request = (Element)GSXML.getChildByTagName(page, GSXML.PAGE_REQUEST_ELEM); String action = request.getAttribute(GSXML.ACTION_ATT); String subaction = request.getAttribute(GSXML.SUBACTION_ATT); String output = request.getAttribute(GSXML.OUTPUT_ATT); // we should choose how to transform the data based on output, eg diff // choice for html, and wml?? // for now, if output=xml, we don't transform the page, we just return // the page xml if (output.equals("xml")) { return page; } Element cgi_param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER); String collection = ""; if (cgi_param_list != null) { HashMap params = GSXML.extractParams(cgi_param_list, false); collection = (String)params.get(GSParams.COLLECTION); if (collection == null) collection = ""; } String xslt_file = getXSLTFileName(action, subaction, collection); if (xslt_file==null) { // cant transform the page - return null or the original? logger.error(" cant find the xslt file needed, so returning the original page!"); return page; } Document style_doc = this.converter.getDOM(new File(xslt_file), "UTF-8"); if (style_doc == null) { logger.error(" cant parse the xslt file needed, so returning the original page!"); return page; } // look for the format element in the page response Element page_response = (Element)GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM); Element format_elem = (Element)GSXML.getChildByTagName(page_response, GSXML.FORMAT_ELEM); if (format_elem != null) { //page_response.removeChild(format_elem); logger.debug("format elem="+this.converter.getPrettyString(format_elem)); // need to transform the format info 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"); Document stylesheet_doc = this.converter.getDOM(new File(stylesheet_file)); if (stylesheet_doc != null) { Document format_doc = this.converter.newDOM(); format_doc.appendChild(format_doc.importNode(format_elem, true)); Element new_format = (Element)this.transformer.transform(stylesheet_doc, format_doc); logger.debug("new format elem="+this.converter.getPrettyString(new_format)); // add it in to the main stylesheet GSXSLT.mergeStylesheets(style_doc, new_format); } else { logger.error(" couldn't parse the config_format stylesheet, adding the format info as is"); GSXSLT.mergeStylesheets(style_doc, format_elem); } logger.debug("the converted stylesheet is:"); logger.debug(this.converter.getPrettyString(style_doc.getDocumentElement())); } // there is a thing called a URIResolver which you can set for a // transformer or transformer factory. may be able to use this // instead of this absoluteIncludepaths hack GSXSLT.absoluteIncludePaths(style_doc, GlobalProperties.getGSDL3Home(), (String)this.config_params.get(GSConstants.SITE_NAME), collection, (String)this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces); // put the page into a document - this is necessary for xslt to get // the paths right if you have paths relative to the document root // eg /page. Document doc = this.converter.newDOM(); doc.appendChild(doc.importNode(page, true)); return (Element)this.transformer.transform(style_doc, doc, config_params); } protected String getXSLTFileName(String action, String subaction, String collection) { String name = null; if (!subaction.equals("")) { String key = action+":"+subaction; name = (String) this.xslt_map.get(key); } // try the action by itself if (name==null) { name = (String) this.xslt_map.get(action); } // now find the absolute path 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); if (stylesheet==null) { logger.info(" cant find stylesheet for "+name); } return stylesheet; } }