/*
* Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved.
*
* This library 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 library 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.
*/
package org.entando.entando.aps.internalservlet.system.dispatcher;
import com.agiletec.aps.system.RequestContext;
import com.agiletec.aps.system.SystemConstants;
import com.agiletec.aps.util.ApsWebApplicationUtils;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import freemarker.template.Template;
import java.io.IOException;
import java.io.StringReader;
import java.io.Writer;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.result.ServletDispatcherResult;
import org.entando.entando.aps.system.services.controller.executor.ExecutorBeanContainer;
import org.entando.entando.aps.system.services.guifragment.GuiFragment;
import org.entando.entando.aps.system.services.guifragment.IGuiFragmentManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Renders a view using a GuiFragment (Entando object) builded by Freemarker.
* If the fragment isn't available, includes or forwards to a view (usually a jsp) {@link ServletDispatcherResult}
*
* <b>This result type takes the following parameters:</b>
*
* <!-- START SNIPPET: params -->
*
* <ul>
*
* <li><b>code (default)</b> - the code of the fragment to process.</li>
* <li><b>jspLocation</b> - the location to go to after execution (jsp) if the fragment isn't available.</li>
*
* </ul>
*
* <!-- END SNIPPET: params -->
*
* <b>Example:</b>
*
* <pre>
* <!-- START SNIPPET: example -->
*
* <result name="success" type="guiFragment">fooCode</result>
*
* <!-- END SNIPPET: example -->
* </pre>
* @author E.Santoboni
*/
public class GuiFragmentResult extends ServletDispatcherResult {
private static final Logger _logger = LoggerFactory.getLogger(GuiFragmentResult.class);
/** The default parameter */
public static final String DEFAULT_PARAM = "code";
private Writer _writer;
protected String _code;
protected String _jspLocation;
public GuiFragmentResult() {
super();
}
public GuiFragmentResult(String code) {
super(code);
this._code = code;
}
public GuiFragmentResult(String code, String jspLocation) {
super(code);
this._code = code;
this._jspLocation = jspLocation;
}
/**
* Execute this result, using the specified fragment.
* @param code The code of the fragment
* @param invocation The invocation
*/
@Override
public void doExecute(String code, ActionInvocation invocation) throws Exception {
if (null == code) {
code = conditionalParse(this._code, invocation);
}
if (null == code) {
this.executeDispatcherResult(invocation);
return;
}
ActionContext ctx = invocation.getInvocationContext();
HttpServletRequest req = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
IGuiFragmentManager guiFragmentManager =
(IGuiFragmentManager) ApsWebApplicationUtils.getBean(SystemConstants.GUI_FRAGMENT_MANAGER, req);
try {
GuiFragment guiFragment = guiFragmentManager.getGuiFragment(code);
String output = (null != guiFragment) ? guiFragment.getCurrentGui() : null;
if (StringUtils.isBlank(output)) {
_logger.info("The fragment '{}' is not available - Action '{}' - Namespace '{}'",
code, invocation.getProxy().getActionName(), invocation.getProxy().getNamespace());
boolean execution = this.executeDispatcherResult(invocation);
if (!execution) {
output = "The fragment '" + code + "' is not available";
} else {
return;
}
}
RequestContext reqCtx = (RequestContext) req.getAttribute(RequestContext.REQCTX);
ExecutorBeanContainer ebc = (ExecutorBeanContainer) reqCtx.getExtraParam(SystemConstants.EXTRAPAR_EXECUTOR_BEAN_CONTAINER);
Writer writer = this.getWriter();
Template template = new Template(code, new StringReader(output), ebc.getConfiguration());
template.process(ebc.getTemplateModel(), writer);
} catch (Throwable t) {
_logger.error("Error processing GuiFragment result!", t);
throw new RuntimeException("Error processing GuiFragment result!", t);
}
}
protected boolean executeDispatcherResult(ActionInvocation invocation) throws Exception {
String finalLocation = conditionalParse(this._jspLocation, invocation);
if (null != finalLocation) {
super.doExecute(finalLocation, invocation);
return true;
}
return false;
}
public void setWriter(Writer writer) {
this._writer = writer;
}
protected Writer getWriter() throws IOException {
if (_writer != null) {
return _writer;
}
return ServletActionContext.getResponse().getWriter();
}
public void setCode(String code) {
this._code = code;
}
public void setJspLocation(String jspLocation) {
this._jspLocation = jspLocation;
}
}