in core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java [117:191]
public void doExecute(String locationArg, ActionInvocation invocation) throws IOException, TemplateException {
this.location = locationArg;
this.invocation = invocation;
this.configuration = getConfiguration();
this.wrapper = getObjectWrapper();
ActionContext ctx = invocation.getInvocationContext();
HttpServletRequest req = ctx.getServletRequest();
String absoluteLocation;
if (location.startsWith("/")) {
absoluteLocation = location;
} else {
String namespace = invocation.getProxy().getNamespace();
if (namespace == null || namespace.isEmpty() || namespace.equals("/")) {
absoluteLocation = "/" + location;
} else if (namespace.startsWith("/")) {
absoluteLocation = namespace + "/" + location;
} else {
absoluteLocation = "/" + namespace + "/" + location;
}
}
Template template = configuration.getTemplate(absoluteLocation, deduceLocale());
TemplateModel model = createModel();
// Give subclasses a chance to hook into preprocessing
if (preTemplateProcess(template, model)) {
try {
final boolean willWriteIfCompleted;
if (writeIfCompleted != null) {
willWriteIfCompleted = isWriteIfCompleted();
} else {
willWriteIfCompleted = template.getTemplateExceptionHandler() == TemplateExceptionHandler.RETHROW_HANDLER;
}
// Process the template
Writer writer = getWriter();
if (willWriteIfCompleted) {
CharArrayWriter parentCharArrayWriter = (CharArrayWriter) req.getAttribute(PARENT_TEMPLATE_WRITER);
boolean isTopTemplate;
if (isTopTemplate = (parentCharArrayWriter == null)) {
//this is the top template
parentCharArrayWriter = new CharArrayWriter();
//set it in the request because when the "action" tag is used a new VS and ActionContext is created
req.setAttribute(PARENT_TEMPLATE_WRITER, parentCharArrayWriter);
}
try {
template.process(model, parentCharArrayWriter);
if (isTopTemplate) {
parentCharArrayWriter.flush();
parentCharArrayWriter.writeTo(writer);
}
} catch (TemplateException | IOException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Error processing Freemarker result!", e);
}
throw e;
} finally {
if (isTopTemplate) {
req.removeAttribute(PARENT_TEMPLATE_WRITER);
parentCharArrayWriter.close();
}
}
} else {
template.process(model, writer);
}
} finally {
// Give subclasses a chance to hook into postprocessing
postTemplateProcess(template, model);
}
}
}