/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This 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 software 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. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xwiki.rendering.internal.macro.velocity; import java.io.StringReader; import java.io.StringWriter; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import org.apache.commons.lang3.StringUtils; import org.apache.velocity.VelocityContext; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; import org.xwiki.component.manager.ComponentLookupException; import org.xwiki.rendering.macro.MacroExecutionException; import org.xwiki.rendering.macro.descriptor.DefaultContentDescriptor; import org.xwiki.rendering.macro.script.AbstractScriptMacro; import org.xwiki.rendering.macro.velocity.VelocityMacroConfiguration; import org.xwiki.rendering.macro.velocity.VelocityMacroParameters; import org.xwiki.rendering.macro.velocity.filter.VelocityMacroFilter; import org.xwiki.rendering.transformation.MacroTransformationContext; import org.xwiki.script.ScriptContextManager; import org.xwiki.velocity.VelocityManager; import org.xwiki.velocity.XWikiVelocityException; /** * Executes <a href="http://velocity.apache.org/">Velocity</a> on the content of this macro and optionally parse the * resulting content with a wiki syntax parser. * * @version $Id: 1872c19427d18d90b2477370b580c39910f5827d $ * @since 1.5M2 */ @Component @Named("velocity") @Singleton public class VelocityMacro extends AbstractScriptMacro<VelocityMacroParameters> { /** * The description of the macro. */ private static final String DESCRIPTION = "Executes a Velocity script."; /** * The description of the macro content. */ private static final String CONTENT_DESCRIPTION = "the velocity script to execute"; /** * Used to get the Velocity Engine and Velocity Context to use to evaluate the passed Velocity script. */ @Inject private VelocityManager velocityManager; /** * The velocity macro configuration. */ @Inject private VelocityMacroConfiguration configuration; @Inject private ScriptContextManager scriptContextManager; /** * The logger to log. */ @Inject private Logger logger; /** * Default constructor. */ public VelocityMacro() { super("Velocity", DESCRIPTION, new DefaultContentDescriptor(CONTENT_DESCRIPTION), VelocityMacroParameters.class); } @Override public boolean supportsInlineMode() { return true; } @Override protected String evaluateString(VelocityMacroParameters parameters, String content, MacroTransformationContext context) throws MacroExecutionException { String result = ""; try { VelocityContext velocityContext = this.velocityManager.getCurrentVelocityContext(); VelocityMacroFilter filter = getFilter(parameters); String cleanedContent = content; // Execute pre filter if (filter != null) { cleanedContent = filter.before(cleanedContent, velocityContext); } StringWriter writer = new StringWriter(); // Use the Transformation id as the name passed to the Velocity Engine. This name is used internally // by Velocity as a cache index key for caching macros. String key = context.getTransformationContext().getId(); if (key == null) { key = "unknown namespace"; } // Execute Velocity context this.velocityManager.evaluate(writer, key, new StringReader(cleanedContent)); result = writer.toString(); // Execute post filter if (filter != null) { result = filter.after(result, velocityContext); } } catch (XWikiVelocityException e) { throw new MacroExecutionException("Failed to evaluate Velocity Macro for content [" + content + "]", e); } return result; } /** * @param parameters the velocity macros parameters * @return the velocity content filter * @since 2.0M1 */ private VelocityMacroFilter getFilter(VelocityMacroParameters parameters) { String filterName = parameters.getFilter(); if (StringUtils.isEmpty(filterName)) { filterName = this.configuration.getFilter(); if (StringUtils.isEmpty(filterName)) { filterName = null; } } VelocityMacroFilter filter = null; if (filterName != null) { try { filter = getComponentManager().getInstance(VelocityMacroFilter.class, filterName); } catch (ComponentLookupException e) { this.logger.error("Can't find velocity macro filter", e); } } return filter; } }