|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MacroTransformation | Line # 69 | 58 | 0% | 17 | 5 | 93.5% |
0.9350649
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MacroTransformation.MacroHolder | Line # 95 | 3 | 0% | 2 | 0 | 100% |
1.0
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (115) | |||
| Result | |||
|
0.80487806
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.80487806
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.80487806
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.80487806
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.80487806
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5731707
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5731707
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5731707
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5731707
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5731707
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5609756
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5609756
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5609756
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5609756
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5609756
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.46341464
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.46341464
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.46341464
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.46341464
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.46341464
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
|
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute
org.xwiki.rendering.test.integration.RenderingTest.execute
|
1 PASS | |
| 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.transformation.macro; | |
| 21 | ||
| 22 | import java.io.PrintWriter; | |
| 23 | import java.io.StringWriter; | |
| 24 | import java.util.ArrayList; | |
| 25 | import java.util.Arrays; | |
| 26 | import java.util.Collections; | |
| 27 | import java.util.List; | |
| 28 | import java.util.Map; | |
| 29 | ||
| 30 | import javax.inject.Inject; | |
| 31 | import javax.inject.Named; | |
| 32 | import javax.inject.Singleton; | |
| 33 | ||
| 34 | import org.slf4j.Logger; | |
| 35 | import org.xwiki.component.annotation.Component; | |
| 36 | import org.xwiki.properties.BeanManager; | |
| 37 | import org.xwiki.rendering.block.Block; | |
| 38 | import org.xwiki.rendering.block.FormatBlock; | |
| 39 | import org.xwiki.rendering.block.GroupBlock; | |
| 40 | import org.xwiki.rendering.block.MacroBlock; | |
| 41 | import org.xwiki.rendering.block.MacroMarkerBlock; | |
| 42 | import org.xwiki.rendering.block.VerbatimBlock; | |
| 43 | import org.xwiki.rendering.block.WordBlock; | |
| 44 | import org.xwiki.rendering.listener.Format; | |
| 45 | import org.xwiki.rendering.macro.Macro; | |
| 46 | import org.xwiki.rendering.macro.MacroId; | |
| 47 | import org.xwiki.rendering.macro.MacroLookupException; | |
| 48 | import org.xwiki.rendering.macro.MacroManager; | |
| 49 | import org.xwiki.rendering.transformation.MacroTransformationContext; | |
| 50 | import org.xwiki.rendering.syntax.Syntax; | |
| 51 | import org.xwiki.rendering.transformation.AbstractTransformation; | |
| 52 | import org.xwiki.rendering.transformation.TransformationContext; | |
| 53 | import org.xwiki.rendering.transformation.TransformationException; | |
| 54 | ||
| 55 | /** | |
| 56 | * Look for all {@link org.xwiki.rendering.block.MacroBlock} blocks in the passed {@link Block} and iteratively execute | |
| 57 | * each Macro in the correct order. Macros can: | |
| 58 | * <ul> | |
| 59 | * <li>provide a hint specifying when they should run (priority)</li> | |
| 60 | * <li>generate other Macros</li> | |
| 61 | * </ul> | |
| 62 | * | |
| 63 | * @version $Id: 66d225115a1f04891537cf0dbc5d143b71c14b7a $ | |
| 64 | * @since 1.5M2 | |
| 65 | */ | |
| 66 | @Component | |
| 67 | @Named("macro") | |
| 68 | @Singleton | |
| 69 | public class MacroTransformation extends AbstractTransformation | |
| 70 | { | |
| 71 | /** | |
| 72 | * Number of macro executions allowed when rendering the current content before considering that we are in a loop. | |
| 73 | * Such a loop can happen if a macro generates itself for example. | |
| 74 | */ | |
| 75 | private int maxMacroExecutions = 1000; | |
| 76 | ||
| 77 | /** | |
| 78 | * Handles macro registration and macro lookups. Injected by the Component Manager. | |
| 79 | */ | |
| 80 | @Inject | |
| 81 | private MacroManager macroManager; | |
| 82 | ||
| 83 | /** | |
| 84 | * Used to populate automatically macros parameters classes with parameters specified in the Macro Block. | |
| 85 | */ | |
| 86 | @Inject | |
| 87 | private BeanManager beanManager; | |
| 88 | ||
| 89 | /** | |
| 90 | * The logger to log. | |
| 91 | */ | |
| 92 | @Inject | |
| 93 | private Logger logger; | |
| 94 | ||
| 95 | private class MacroHolder implements Comparable<MacroHolder> | |
| 96 | { | |
| 97 | Macro< ? > macro; | |
| 98 | ||
| 99 | MacroBlock macroBlock; | |
| 100 | ||
| 101 | 1162 |
public MacroHolder(Macro< ? > macro, MacroBlock macroBlock) |
| 102 | { | |
| 103 | 1162 | this.macro = macro; |
| 104 | 1162 | this.macroBlock = macroBlock; |
| 105 | } | |
| 106 | ||
| 107 | 22 |
@Override |
| 108 | public int compareTo(MacroHolder holder) | |
| 109 | { | |
| 110 | 22 | return this.macro.compareTo(holder.macro); |
| 111 | } | |
| 112 | } | |
| 113 | ||
| 114 | 0 |
@Override |
| 115 | public int getPriority() | |
| 116 | { | |
| 117 | // Make it one of the transformations that's executed first so that other transformations run on the executed | |
| 118 | // macros. | |
| 119 | 0 | return 100; |
| 120 | } | |
| 121 | ||
| 122 | 132 |
@Override |
| 123 | public void transform(Block rootBlock, TransformationContext context) throws TransformationException | |
| 124 | { | |
| 125 | // Create a macro execution context with all the information required for macros. | |
| 126 | 132 | MacroTransformationContext macroContext = new MacroTransformationContext(context); |
| 127 | 132 | macroContext.setTransformation(this); |
| 128 | ||
| 129 | // Counter to prevent infinite recursion if a macro generates the same macro for example. | |
| 130 | 132 | int executions = 0; |
| 131 | 132 | List<MacroBlock> macroBlocks = rootBlock.getChildrenByType(MacroBlock.class, true); |
| 132 | 1277 | while (!macroBlocks.isEmpty() && executions < this.maxMacroExecutions) { |
| 133 | 1145 | transformOnce(rootBlock, macroContext, context.getSyntax()); |
| 134 | ||
| 135 | // TODO: Make this less inefficient by caching the blocks list. | |
| 136 | 1145 | macroBlocks = rootBlock.getChildrenByType(MacroBlock.class, true); |
| 137 | 1145 | executions++; |
| 138 | } | |
| 139 | } | |
| 140 | ||
| 141 | 1145 |
private void transformOnce(Block rootBlock, MacroTransformationContext context, Syntax syntax) |
| 142 | { | |
| 143 | // 1) Get highest priority macro to execute | |
| 144 | 1145 | MacroHolder macroHolder = getHighestPriorityMacro(rootBlock, syntax); |
| 145 | 1145 | if (macroHolder == null) { |
| 146 | 5 | return; |
| 147 | } | |
| 148 | ||
| 149 | // 2) Verify if we're in macro inline mode and if the macro supports it. If not, send an error. | |
| 150 | 1140 | if (macroHolder.macroBlock.isInline()) { |
| 151 | 41 | context.setInline(true); |
| 152 | 41 | if (!macroHolder.macro.supportsInlineMode()) { |
| 153 | // The macro doesn't support inline mode, raise a warning but continue. | |
| 154 | // The macro will not be executed and we generate an error message instead of the macro | |
| 155 | // execution result. | |
| 156 | 5 | generateError(macroHolder.macroBlock, "Not an inline macro", |
| 157 | "This macro can only be used by itself on a new line"); | |
| 158 | 5 | this.logger.debug("The [" + macroHolder.macroBlock.getId() + "] macro doesn't support inline mode."); |
| 159 | 5 | return; |
| 160 | } | |
| 161 | } else { | |
| 162 | 1099 | context.setInline(false); |
| 163 | } | |
| 164 | ||
| 165 | // 3) Execute the highest priority macro | |
| 166 | 1135 | List<Block> newBlocks; |
| 167 | 1135 | try { |
| 168 | 1135 | context.setCurrentMacroBlock(macroHolder.macroBlock); |
| 169 | ||
| 170 | // Populate and validate macro parameters. | |
| 171 | 1135 | Object macroParameters; |
| 172 | 1135 | try { |
| 173 | 1135 | macroParameters = macroHolder.macro.getDescriptor().getParametersBeanClass().newInstance(); |
| 174 | 1135 | this.beanManager.populate(macroParameters, macroHolder.macroBlock.getParameters()); |
| 175 | } catch (Throwable e) { | |
| 176 | // One macro parameter was invalid. | |
| 177 | // The macro will not be executed and we generate an error message instead of the macro | |
| 178 | // execution result. | |
| 179 | 0 | generateError(macroHolder.macroBlock, "Invalid macro parameters used for the \"" |
| 180 | + macroHolder.macroBlock.getId() + "\" macro", e); | |
| 181 | 0 | this.logger.debug( |
| 182 | "Invalid macro parameter for the [" + macroHolder.macroBlock.getId() + "] macro. Internal error: [" | |
| 183 | + e.getMessage() + "]"); | |
| 184 | ||
| 185 | 0 | return; |
| 186 | } | |
| 187 | ||
| 188 | 1135 | newBlocks = |
| 189 | ((Macro<Object>) macroHolder.macro).execute(macroParameters, macroHolder.macroBlock.getContent(), | |
| 190 | context); | |
| 191 | } catch (Throwable e) { | |
| 192 | // The Macro failed to execute. | |
| 193 | // The macro will not be executed and we generate an error message instead of the macro | |
| 194 | // execution result. | |
| 195 | // Note: We catch any Exception because we want to never break the whole rendering. | |
| 196 | 10 | generateError(macroHolder.macroBlock, "Failed to execute the [" + macroHolder.macroBlock.getId() |
| 197 | + "] macro", e); | |
| 198 | 10 | this.logger.debug( |
| 199 | "Failed to execute the [" + macroHolder.macroBlock.getId() + "]macro. Internal error [" | |
| 200 | + e.getMessage() + "]"); | |
| 201 | ||
| 202 | 10 | return; |
| 203 | } | |
| 204 | ||
| 205 | // We wrap the blocks generated by the macro execution with MacroMarker blocks so that listeners/renderers | |
| 206 | // who wish to know the group of blocks that makes up the executed macro can. For example this is useful for | |
| 207 | // the XWiki Syntax renderer so that it can reconstruct the macros from the transformed XDOM. | |
| 208 | 1125 | Block resultBlock = wrapInMacroMarker(macroHolder.macroBlock, newBlocks); |
| 209 | ||
| 210 | // 4) Replace the MacroBlock by the Blocks generated by the execution of the Macro | |
| 211 | 1125 | macroHolder.macroBlock.getParent().replaceChild(resultBlock, macroHolder.macroBlock); |
| 212 | } | |
| 213 | ||
| 214 | /** | |
| 215 | * @return the macro with the highest priority for the passed syntax or null if no macro is found | |
| 216 | */ | |
| 217 | 1145 |
private MacroHolder getHighestPriorityMacro(Block rootBlock, Syntax syntax) |
| 218 | { | |
| 219 | 1145 | List<MacroHolder> macroHolders = new ArrayList<MacroHolder>(); |
| 220 | ||
| 221 | // 1) Sort the macros by priority to find the highest priority macro to execute | |
| 222 | 1145 | for (MacroBlock macroBlock : rootBlock.getChildrenByType(MacroBlock.class, true)) { |
| 223 | 1167 | try { |
| 224 | 1167 | Macro< ? > macro = this.macroManager.getMacro(new MacroId(macroBlock.getId(), syntax)); |
| 225 | 1162 | macroHolders.add(new MacroHolder(macro, macroBlock)); |
| 226 | } catch (MacroLookupException e) { | |
| 227 | // Macro cannot be found. Generate an error message instead of the macro execution result. | |
| 228 | // TODO: make it internationalized | |
| 229 | 5 | generateError(macroBlock, "Unknown macro: " + macroBlock.getId(), "The \"" + macroBlock.getId() |
| 230 | + "\" macro is not in the list of registered macros. Verify the " | |
| 231 | + "spelling or contact your administrator."); | |
| 232 | 5 | this.logger.debug("Failed to locate the [" + macroBlock.getId() + "] macro. Ignoring it."); |
| 233 | } | |
| 234 | } | |
| 235 | ||
| 236 | // Sort the Macros by priority | |
| 237 | 1145 | Collections.sort(macroHolders); |
| 238 | ||
| 239 | 1145 | return macroHolders.size() > 0 ? macroHolders.get(0) : null; |
| 240 | } | |
| 241 | ||
| 242 | /** | |
| 243 | * Wrap the output of a macro block with a {@link MacroMarkerBlock}. | |
| 244 | * | |
| 245 | * @param macroBlockToWrap the block that should be replaced | |
| 246 | * @param newBlocks list of blocks to wrap | |
| 247 | * @return the wrapper | |
| 248 | */ | |
| 249 | 1145 |
private Block wrapInMacroMarker(MacroBlock macroBlockToWrap, List<Block> newBlocks) |
| 250 | { | |
| 251 | 1145 | return new MacroMarkerBlock(macroBlockToWrap.getId(), macroBlockToWrap.getParameters(), macroBlockToWrap |
| 252 | .getContent(), newBlocks, macroBlockToWrap.isInline()); | |
| 253 | } | |
| 254 | ||
| 255 | 20 |
private void generateError(MacroBlock macroToReplace, String message, String description) |
| 256 | { | |
| 257 | 20 | List<Block> errorBlocks = new ArrayList<Block>(); |
| 258 | ||
| 259 | 20 | Map<String, String> errorBlockParams = Collections.singletonMap("class", "xwikirenderingerror"); |
| 260 | 20 | Map<String, String> errorDescriptionBlockParams = |
| 261 | Collections.singletonMap("class", "xwikirenderingerrordescription hidden"); | |
| 262 | ||
| 263 | 20 | Block descriptionBlock = new VerbatimBlock(description, macroToReplace.isInline()); |
| 264 | ||
| 265 | 20 | if (macroToReplace.isInline()) { |
| 266 | 15 | errorBlocks.add(new FormatBlock(Arrays.<Block> asList(new WordBlock(message)), Format.NONE, |
| 267 | errorBlockParams)); | |
| 268 | 15 | errorBlocks.add(new FormatBlock(Arrays.asList(descriptionBlock), Format.NONE, errorDescriptionBlockParams)); |
| 269 | } else { | |
| 270 | 5 | errorBlocks.add(new GroupBlock(Arrays.<Block> asList(new WordBlock(message)), errorBlockParams)); |
| 271 | 5 | errorBlocks.add(new GroupBlock(Arrays.asList(descriptionBlock), errorDescriptionBlockParams)); |
| 272 | } | |
| 273 | ||
| 274 | 20 | macroToReplace.getParent().replaceChild(wrapInMacroMarker(macroToReplace, errorBlocks), macroToReplace); |
| 275 | } | |
| 276 | ||
| 277 | 10 |
private void generateError(MacroBlock macroToReplace, String message, Throwable throwable) |
| 278 | { | |
| 279 | 10 | StringWriter writer = new StringWriter(); |
| 280 | 10 | throwable.printStackTrace(new PrintWriter(writer)); |
| 281 | 10 | generateError(macroToReplace, message, writer.getBuffer().toString()); |
| 282 | } | |
| 283 | } | |
|
||||||||||||