/**
* 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;
}
}
}