org.apache.velocity.runtime.directive.Parse Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.liferay.portal.template.velocity
Show all versions of com.liferay.portal.template.velocity
Liferay Portal Template Velocity
The newest version!
package org.apache.velocity.runtime.directive;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.ArrayList;
import org.apache.velocity.Template;
import org.apache.velocity.app.event.EventHandlerUtil;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.VelocityException;
import org.apache.velocity.exception.TemplateInitException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.log.Log;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.runtime.parser.node.SimpleNode;
/**
* Pluggable directive that handles the #parse()
* statement in VTL.
*
*
* Notes:
* -----
* 1) The parsed source material can only come from somewhere in
* the TemplateRoot tree for security reasons. There is no way
* around this. If you want to include content from elsewhere on
* your disk, use a link from somwhere under Template Root to that
* content.
*
* 2) There is a limited parse depth. It is set as a property
* "directive.parse.max.depth = 10" by default. This 10 deep
* limit is a safety feature to prevent infinite loops.
*
*
* @author Geir Magnusson Jr.
* @author Jason van Zyl
* @author Christoph Reck
* @version $Id: Parse.java 938699 2010-04-27 22:19:26Z nbubna $
*/
public class Parse extends InputBase
{
private int maxDepth;
/**
* Return name of this directive.
* @return The name of this directive.
*/
public String getName()
{
return "parse";
}
/**
* Return type of this directive.
* @return The type of this directive.
*/
public int getType()
{
return LINE;
}
/**
* Init's the #parse directive.
* @param rs
* @param context
* @param node
* @throws TemplateInitException
*/
public void init(RuntimeServices rs, InternalContextAdapter context, Node node)
throws TemplateInitException
{
super.init(rs, context, node);
this.maxDepth = rsvc.getInt(RuntimeConstants.PARSE_DIRECTIVE_MAXDEPTH, 10);
}
/**
* iterates through the argument list and renders every
* argument that is appropriate. Any non appropriate
* arguments are logged, but render() continues.
* @param context
* @param writer
* @param node
* @return True if the directive rendered successfully.
* @throws IOException
* @throws ResourceNotFoundException
* @throws ParseErrorException
* @throws MethodInvocationException
*/
public boolean render( InternalContextAdapter context,
Writer writer, Node node)
throws IOException, ResourceNotFoundException, ParseErrorException,
MethodInvocationException
{
/*
* if rendering is no longer allowed (after a stop), we can safely
* skip execution of all the parse directives.
*/
if(!context.getAllowRendering())
{
return true;
}
/*
* did we get an argument?
*/
if ( node.jjtGetChild(0) == null)
{
rsvc.getLog().error("#parse() null argument");
return false;
}
/*
* does it have a value? If you have a null reference, then no.
*/
Object value = node.jjtGetChild(0).value( context );
if ( value == null)
{
rsvc.getLog().error("#parse() null argument");
return false;
}
/*
* get the path
*/
String sourcearg = value.toString();
/*
* check to see if the argument will be changed by the event cartridge
*/
String arg = EventHandlerUtil.includeEvent( rsvc, context, sourcearg, context.getCurrentTemplateName(), getName());
/*
* a null return value from the event cartridge indicates we should not
* input a resource.
*/
boolean blockinput = false;
if (arg == null)
blockinput = true;
if (maxDepth > 0)
{
/*
* see if we have exceeded the configured depth.
*/
Object[] templateStack = context.getTemplateNameStack();
if (templateStack.length >= maxDepth)
{
StringBuffer path = new StringBuffer();
for( int i = 0; i < templateStack.length; ++i)
{
path.append( " > " + templateStack[i] );
}
rsvc.getLog().error("Max recursion depth reached (" +
templateStack.length + ')' + " File stack:" +
path);
return false;
}
}
/*
* now use the Runtime resource loader to get the template
*/
Template t = null;
try
{
if (!blockinput)
t = rsvc.getTemplate( arg, getInputEncoding(context) );
}
catch ( ResourceNotFoundException rnfe )
{
/*
* the arg wasn't found. Note it and throw
*/
rsvc.getLog().error("#parse(): cannot find template '" + arg +
"', called at " + Log.formatFileString(this));
throw rnfe;
}
catch ( ParseErrorException pee )
{
/*
* the arg was found, but didn't parse - syntax error
* note it and throw
*/
rsvc.getLog().error("#parse(): syntax error in #parse()-ed template '"
+ arg + "', called at " + Log.formatFileString(this));
throw pee;
}
/**
* pass through application level runtime exceptions
*/
catch( RuntimeException e )
{
rsvc.getLog().error("Exception rendering #parse(" + arg + ") at " +
Log.formatFileString(this));
throw e;
}
catch ( Exception e)
{
String msg = "Exception rendering #parse(" + arg + ") at " +
Log.formatFileString(this);
rsvc.getLog().error(msg, e);
throw new VelocityException(msg, e);
}
if (!blockinput)
{
/**
* Add the template name to the macro libraries list
*/
List macroLibraries = context.getMacroLibraries();
/**
* if macroLibraries are not set create a new one
*/
if (macroLibraries == null)
{
macroLibraries = new ArrayList();
}
context.setMacroLibraries(macroLibraries);
macroLibraries.add(arg);
}
/*
* and render it
*/
try
{
if (!blockinput) {
context.pushCurrentTemplateName(arg);
((SimpleNode) t.getData()).render( context, writer );
}
}
/**
* pass through application level runtime exceptions
*/
catch( RuntimeException e )
{
/**
* Log #parse errors so the user can track which file called which.
*/
rsvc.getLog().error("Exception rendering #parse(" + arg + ") at " +
Log.formatFileString(this));
throw e;
}
catch ( Exception e )
{
String msg = "Exception rendering #parse(" + arg + ") at " +
Log.formatFileString(this);
rsvc.getLog().error(msg, e);
throw new VelocityException(msg, e);
}
finally
{
if (!blockinput)
context.popCurrentTemplateName();
}
/*
* note - a blocked input is still a successful operation as this is
* expected behavior.
*/
return true;
}
}