in velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/RuntimeMacro.java [277:370]
public boolean render(InternalContextAdapter context, Writer writer,
Node node, Renderable body)
throws IOException, ResourceNotFoundException,
ParseErrorException, MethodInvocationException
{
VelocimacroProxy vmProxy = null;
Template renderingTemplate = (Template)context.getCurrentResource();
/*
* first look in the source template
*/
Object o = rsvc.getVelocimacro(macroName, renderingTemplate, getTemplate());
if( o != null )
{
// getVelocimacro can only return a VelocimacroProxy so we don't need the
// costly instanceof check
vmProxy = (VelocimacroProxy)o;
}
/*
* if not found, look in the macro libraries.
*/
if (vmProxy == null)
{
List<Template> macroLibraries = context.getMacroLibraries();
if (macroLibraries != null)
{
for (int i = macroLibraries.size() - 1; i >= 0; i--)
{
o = rsvc.getVelocimacro(macroName, renderingTemplate, macroLibraries.get(i));
// get the first matching macro
if (o != null)
{
vmProxy = (VelocimacroProxy) o;
break;
}
}
}
}
if (vmProxy != null)
{
if (badArgsErrorMsg != null)
{
throw new TemplateInitException(badArgsErrorMsg,
null, rsvc.getLogContext().getStackTrace(),
context.getCurrentTemplateName(), node.getColumn(), node.getLine());
}
try
{
preRender(context);
return vmProxy.render(context, writer, node, body);
}
catch (StopCommand stop)
{
if (!stop.isFor(this))
{
throw stop;
}
return true;
}
catch (RuntimeException | IOException e)
{
/*
* We catch, the exception here so that we can record in
* the logs the template and line number of the macro call
* which generate the exception. This information is
* especially important for multiple macro call levels.
* this is also true for the following catch blocks.
*/
log.error("Exception in macro #{} called at {}",
macroName, StringUtils.formatFileString(node));
throw e;
}
finally
{
postRender(context);
}
}
else if (strictRef)
{
throw new VelocityException("Macro '#" + macroName + "' is not defined at "
+ StringUtils.formatFileString(node), null, rsvc.getLogContext().getStackTrace());
}
/*
* If we cannot find an implementation write the literal text
*/
writer.write(getLiteral());
return true;
}