/** * Copyright (C) 2010 Orbeon, Inc. * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * The full text of the license is available at http://www.gnu.org/copyleft/lesser.html */ package org.orbeon.oxf.processor.generator; import org.apache.log4j.Logger; import org.orbeon.dom.Document; import org.orbeon.oxf.common.OXFException; import org.orbeon.oxf.externalcontext.ExternalContext; import org.orbeon.oxf.pipeline.api.PipelineContext; import org.orbeon.oxf.xml.XMLReceiver; import org.orbeon.oxf.processor.*; import org.orbeon.oxf.util.LoggerFactory; import org.orbeon.oxf.xml.XPathUtils; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * NOTE: This generator depends on the Servlet API. Doesn't work with portlets. FIXME! * See an incorrect implementation in NewServletIncludeGenerator. */ public class ServletIncludeGenerator extends ProcessorImpl { private static Logger logger = LoggerFactory.createLogger(ServletIncludeGenerator.class); public static final String SERVLET_INCLUDE_NAMESPACE_URI = "http://www.orbeon.org/oxf/servlet-include"; public ServletIncludeGenerator() { addInputInfo(new ProcessorInputOutputInfo(INPUT_CONFIG, SERVLET_INCLUDE_NAMESPACE_URI)); addOutputInfo(new ProcessorInputOutputInfo(OUTPUT_DATA)); } @Override public ProcessorOutput createOutput(String name) { final ProcessorOutput output = new ProcessorOutputImpl(ServletIncludeGenerator.this, name) { public void readImpl(PipelineContext context, XMLReceiver xmlReceiver) { // Read config final Config config = readCacheInputAsObject(context, getInputByName(INPUT_CONFIG), new CacheableInputReader<Config>() { public Config read(PipelineContext context, ProcessorInput input) { Document configNode = readInputAsOrbeonDom(context, input); String servletName = XPathUtils.selectStringValueNormalize(configNode, "/config/servlet-name"); String path = XPathUtils.selectStringValueNormalize(configNode, "/config/path"); String contextPath = XPathUtils.selectStringValueNormalize(configNode, "/config/context-uripath"); // Get Tidy config (will only apply if content-type is text/html) TidyConfig tidyConfig = new TidyConfig(XPathUtils.selectSingleNode(configNode, "/config/tidy-options")); return new Config(servletName, path, contextPath, tidyConfig); } }); ExternalContext externalContext = (ExternalContext) context.getAttribute(PipelineContext.EXTERNAL_CONTEXT); if (externalContext == null) throw new OXFException("Can't find external context in pipeline context"); HttpServletRequest request = (HttpServletRequest) externalContext.getRequest().getNativeRequest(); HttpServletResponse response = (HttpServletResponse) externalContext.getResponse().getNativeResponse(); // Include the result as XML or HTML ServletResponseWrapper wrapper = new ServletResponseWrapper(response); try { getRequestDispatcher(externalContext, config).include(request, wrapper); } catch (IOException e) { throw new OXFException(e); } catch (ServletException e) { throw new OXFException(e); } // Parse the result wrapper.parse(xmlReceiver, config.getTidyConfig()); } }; addOutput(name, output); return output; } private RequestDispatcher getRequestDispatcher(ExternalContext externalContext, Config config) { Object sc = externalContext.getWebAppContext().getNativeContext(); if ((sc == null) || !(sc instanceof ServletContext)) throw new OXFException("Can't find servlet context in pipeline context"); ServletContext servletContext = (ServletContext) sc; String name = ""; if (config.getContextPath() != null) { name += config.getContextPath() + '/'; } RequestDispatcher requestDispatcher = null; if (config.getServletName() != null) { requestDispatcher = servletContext.getNamedDispatcher(config.getServletName()); name += config.getServletName(); } else if (config.getPath() != null) { requestDispatcher = servletContext.getRequestDispatcher(config.getPath()); name += config.getPath(); } else throw new OXFException("servlet-name or path must be present in config"); logger.info("Including from: " + name); return requestDispatcher; } private static class Config { private String servletName; private String path; private String contextPath; private TidyConfig tidyConfig; public Config(String contextPath, String path, String servletName, TidyConfig tidyConfig) { this.contextPath = contextPath; this.path = path; this.servletName = servletName; this.tidyConfig = tidyConfig; } public String getContextPath() { return contextPath; } public String getPath() { return path; } public String getServletName() { return servletName; } public TidyConfig getTidyConfig() { return tidyConfig; } } }