Clover Coverage Report - XWiki Rendering - Parent POM 4.0-SNAPSHOT (Aggregated)
Coverage timestamp: Mon Mar 12 2012 18:03:13 CET
../../../../../../img/srcFileCovDistChart10.png 0% of files have more coverage
83   274   34   20.75
52   184   0.41   4
4     8.5  
1    
 
  VelocityFilter       Line # 54 83 0% 34 12 91.4% 0.91366905
 
  (92)
 
1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.rendering.internal.parser.xwiki10;
21   
22    import java.util.regex.Pattern;
23   
24    import javax.inject.Inject;
25    import javax.inject.Named;
26    import javax.inject.Singleton;
27   
28    import org.slf4j.Logger;
29    import org.xwiki.component.annotation.Component;
30    import org.xwiki.component.manager.ComponentManager;
31    import org.xwiki.component.phase.Initializable;
32    import org.xwiki.component.phase.InitializationException;
33    import org.xwiki.rendering.internal.parser.xwiki10.velocity.ExtendedVelocityParser;
34    import org.xwiki.rendering.internal.parser.xwiki10.velocity.ExtendedVelocityParserContext;
35    import org.xwiki.rendering.parser.xwiki10.AbstractFilter;
36    import org.xwiki.rendering.parser.xwiki10.FilterContext;
37    import org.xwiki.rendering.parser.xwiki10.util.CleanUtil;
38    import org.xwiki.velocity.internal.util.InvalidVelocityException;
39    import org.xwiki.velocity.internal.util.VelocityBlock;
40    import org.xwiki.velocity.internal.util.VelocityBlock.VelocityType;
41   
42    /**
43    * Register all Velocity comments in order to protect them from following filters. Protect velocity comments, convert
44    * velocity macro into 2.0 macros/syntax and add needed 2.0 velocity macros and convert.
45    * <p>
46    * See http://velocity.apache.org/engine/releases/velocity-1.6.2/vtl-reference-guide.html
47    *
48    * @version $Id: 0bb59c0aaca63f5c41723cb617761c6ee9f699a8 $
49    * @since 1.8M1
50    */
51    @Component
52    @Named("velocity")
53    @Singleton
 
54    public class VelocityFilter extends AbstractFilter implements Initializable
55    {
56    public static final String VELOCITY_SF = "velocity";
57   
58    public static final String VELOCITYNOOUTPUT_SF = VELOCITY_SF + "nooutput";
59   
60    public static final String VELOCITYOPEN_SF = VELOCITY_SF + "open";
61   
62    public static final String VELOCITYCLOSE_SF = VELOCITY_SF + "close";
63   
64    public static final String VELOCITYCOMMENT_SF = VELOCITYNOOUTPUT_SF + VelocityBlock.VelocityType.COMMENT;
65   
66    public static final String VELOCITY_SPATTERN =
67    "(?:" + FilterContext.XWIKI1020TOKEN_OP + FilterContext.XWIKI1020TOKEN_SF_SPATTERN + VELOCITY_SF
68    + "\\p{L}*\\d+" + FilterContext.XWIKI1020TOKEN_CP + ")";
69   
70    public static final String VELOCITYOPEN_SPATTERN =
71    "(?:" + FilterContext.XWIKI1020TOKEN_OP + FilterContext.XWIKI1020TOKENI_SF_SPATTERN + VELOCITYOPEN_SF + "\\d+"
72    + FilterContext.XWIKI1020TOKEN_CP + ")";
73   
74    public static final String VELOCITYCLOSE_SPATTERN =
75    "(?:" + FilterContext.XWIKI1020TOKEN_OP + FilterContext.XWIKI1020TOKENI_SF_SPATTERN + VELOCITYCLOSE_SF + "\\d+"
76    + FilterContext.XWIKI1020TOKEN_CP + ")";
77   
78    public static final String VELOCITYNOOUTPUT_SPATTERN =
79    "(?:" + FilterContext.XWIKI1020TOKEN_OP + FilterContext.XWIKI1020TOKEN_SF_SPATTERN + VELOCITYNOOUTPUT_SF
80    + "\\p{L}*\\d+" + FilterContext.XWIKI1020TOKEN_CP + ")";
81   
82    public static final String VELOCITYCONTENT_SPATTERN =
83    "(?:" + VELOCITYOPEN_SPATTERN + ".*" + VELOCITYCLOSE_SPATTERN + ")";
84   
85    public static final String NLGROUP_SPATTERN = "(?:(?:\n|" + VELOCITYNOOUTPUT_SPATTERN + ")*)";
86   
87    public static final String SPACEGROUP_SPATTERN = "(?:(?:[ \\t]|" + VELOCITYNOOUTPUT_SPATTERN + ")*)";
88   
89    public static final String EMPTY_OC_SPATTERN =
90    VELOCITYOPEN_SPATTERN + "?" + VELOCITYNOOUTPUT_SPATTERN + "*" + VELOCITYCLOSE_SPATTERN + "?";
91   
92    public static final String SPACEGROUP_OC_SPATTERN =
93    "[ \\t]*" + VELOCITYOPEN_SPATTERN + "?" + SPACEGROUP_SPATTERN + VELOCITYCLOSE_SPATTERN + "?" + "[ \\t]*";
94   
95    public static final Pattern VELOCITYOPEN_PATTERN = Pattern.compile(VELOCITYOPEN_SPATTERN);
96   
97    public static final Pattern VELOCITYCLOSE_PATTERN = Pattern.compile(VELOCITYCLOSE_SPATTERN);
98   
99    public static final Pattern VELOCITYCONTENT_PATTERN = Pattern.compile(VELOCITYCONTENT_SPATTERN, Pattern.DOTALL);
100   
101    /**
102    * Used to lookup macros converters.
103    */
104    @Inject
105    private ComponentManager componentManager;
106   
107    /**
108    * The logger to log.
109    */
110    @Inject
111    private Logger logger;
112   
113    private ExtendedVelocityParser velocityParser;
114   
 
115  92 toggle @Override
116    public void initialize() throws InitializationException
117    {
118  92 setPriority(20);
119   
120  92 this.velocityParser = new ExtendedVelocityParser(componentManager);
121    }
122   
 
123  124 toggle @Override
124    public String filter(String content, FilterContext filterContext)
125    {
126  124 StringBuffer result = new StringBuffer();
127  124 char[] array = content.toCharArray();
128   
129  124 ExtendedVelocityParserContext context = new ExtendedVelocityParserContext(filterContext);
130   
131  124 StringBuffer beforeVelocityBuffer = new StringBuffer();
132  124 StringBuffer velocityBuffer = new StringBuffer();
133  124 StringBuffer afterVelocityBuffer = new StringBuffer();
134   
135  124 boolean inVelocityMacro = false;
136  124 int i = 0;
137   
138  124 StringBuffer velocityBlock = new StringBuffer();
139  5084 for (; i < array.length;) {
140  4960 char c = array[i];
141   
142  4960 context.setVelocity(false);
143  4960 context.setConversion(false);
144  4960 context.setInline(true);
145  4960 context.setProtectedBlock(true);
146  4960 context.setType(null);
147   
148  4960 velocityBlock.setLength(0);
149   
150  4960 try {
151  4960 if (c == '#') {
152  82 i = this.velocityParser.getKeyWord(array, i, velocityBlock, context);
153  4878 } else if (c == '$') {
154  36 i = this.velocityParser.getVar(array, i, velocityBlock, context);
155  4842 } else if (c == '\\') {
156  16 if (array.length > i + 1) {
157  15 char escapedChar = array[i + 1];
158   
159  15 if (escapedChar == '\\') {
160  3 c = escapedChar;
161  3 i++;
162    } else {
163  12 int newI = i + 1;
164  12 if (escapedChar == '#') {
165  1 newI = this.velocityParser.getKeyWord(array, newI, velocityBlock, context);
166  11 } else if (escapedChar == '$') {
167  1 newI = this.velocityParser.getVar(array, newI, velocityBlock, context);
168    }
169   
170  11 if ((context.isVelocity() && context.getType() != VelocityType.COMMENT)
171    || context.isConversion()) {
172  1 c = escapedChar;
173  1 i++;
174    }
175   
176  11 context.setVelocity(false);
177  11 context.setConversion(false);
178  11 context.setInline(true);
179  11 context.setProtectedBlock(true);
180  11 context.setType(null);
181    }
182    }
183    }
184    } catch (InvalidVelocityException e) {
185  12 this.logger.debug("Not a valid Velocity block at char [" + i + "]", e);
186  12 context.setVelocity(false);
187    }
188   
189  4960 if (context.isVelocity()) {
190  79 if (!inVelocityMacro) {
191  40 inVelocityMacro = true;
192    } else {
193  39 velocityBuffer.append(afterVelocityBuffer);
194  39 afterVelocityBuffer.setLength(0);
195    }
196   
197  79 if (context.isConversion()) {
198  2 if (!context.isInline()) {
199  0 if (velocityBuffer.length() > 0) {
200  0 CleanUtil.setTrailingNewLines(velocityBuffer, 2);
201    }
202    }
203    }
204   
205  79 velocityBuffer.append(context.isProtectedBlock() ? filterContext.addProtectedContent(velocityBlock
206  78 .toString(), (velocityBlock.charAt(velocityBlock.length() - 1) == '\n' ? VELOCITYNOOUTPUT_SF
207    : VELOCITY_SF)
208    + context.getType(), context.isInline()) : velocityBlock);
209    } else {
210  4881 StringBuffer nonVelocityBuffer = inVelocityMacro ? afterVelocityBuffer : beforeVelocityBuffer;
211   
212  4881 if (context.isConversion()) {
213  28 if (!context.isInline()) {
214  8 if (nonVelocityBuffer.length() > 0 || velocityBuffer.length() > 0) {
215  3 CleanUtil.setTrailingNewLines(nonVelocityBuffer, 2);
216    }
217    }
218   
219  28 nonVelocityBuffer.append(context.isProtectedBlock() ? filterContext.addProtectedContent(
220    velocityBlock.toString(), context.isInline()) : velocityBlock);
221    } else {
222  4853 nonVelocityBuffer.append(c);
223  4853 ++i;
224    }
225    }
226    }
227   
228    // fix not closed #if, #foreach, etc.
229  124 if (context.isInVelocityBlock()) {
230  0 velocityBuffer.append(afterVelocityBuffer);
231  0 afterVelocityBuffer.setLength(0);
232   
233    // fix unclosed velocity blocks
234  0 for (; context.isInVelocityBlock(); context.popVelocityElement()) {
235  0 velocityBuffer.append(filterContext.addProtectedContent("#end\n", VELOCITYNOOUTPUT_SF, true));
236    }
237    }
238   
239  124 if (velocityBuffer.length() > 0) {
240  40 String beforeVelocityContent = beforeVelocityBuffer.toString();
241  40 String velocityContent = velocityBuffer.toString();
242  40 String unProtectedVelocityContent = filterContext.unProtect(velocityContent);
243  40 String afterVelocityContent = afterVelocityBuffer.toString();
244   
245  40 boolean multilines = unProtectedVelocityContent.indexOf("\n") != -1;
246   
247    // print before velocity content
248  40 result.append(beforeVelocityContent);
249   
250    // print velocity content
251  40 appendVelocityOpen(result, filterContext, multilines);
252  40 result.append(velocityContent);
253  40 appendVelocityClose(result, filterContext, multilines);
254   
255    // print after velocity content
256  40 result.append(afterVelocityContent);
257    } else {
258  84 result = beforeVelocityBuffer;
259    }
260   
261  124 return result.toString();
262    }
263   
 
264  85 toggle public static void appendVelocityOpen(StringBuffer result, FilterContext filterContext, boolean nl)
265    {
266  85 result.append(filterContext.addProtectedContent("{{velocity filter=\"none\"}}" + (nl ? "\n" : ""),
267    VELOCITYOPEN_SF, true));
268    }
269   
 
270  88 toggle public static void appendVelocityClose(StringBuffer result, FilterContext filterContext, boolean nl)
271    {
272  88 result.append(filterContext.addProtectedContent((nl ? "\n" : "") + "{{/velocity}}", VELOCITYCLOSE_SF, true));
273    }
274    }