1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package com.xpn.xwiki.internal.template

File InternalTemplateManager.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart7.png
66% of files have more coverage

Code metrics

82
237
67
8
963
687
119
0.5
3.54
8.38
1.78

Classes

Class Line # Actions
InternalTemplateManager 102 169 0% 76 101
0.624535362.5%
InternalTemplateManager.AbtractTemplate 168 17 0% 11 8
0.7333333573.3%
InternalTemplateManager.EnvironmentTemplate 228 2 0% 2 0
1.0100%
InternalTemplateManager.ClassloaderTemplate 242 2 0% 2 0
1.0100%
InternalTemplateManager.DefaultTemplate 256 5 0% 3 0
1.0100%
InternalTemplateManager.StringTemplate 276 2 0% 1 0
1.0100%
InternalTemplateManager.DefaultTemplateContent 287 32 0% 19 15
0.716981171.7%
InternalTemplateManager.FilesystemTemplateContent 428 8 0% 5 5
0.6428571364.3%
 

Contributing tests

This file is covered by 24 tests. .

Source view

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 com.xpn.xwiki.internal.template;
21   
22    import java.io.PrintWriter;
23    import java.io.StringReader;
24    import java.io.StringWriter;
25    import java.io.Writer;
26    import java.lang.reflect.Type;
27    import java.net.URI;
28    import java.net.URL;
29    import java.nio.charset.StandardCharsets;
30    import java.util.ArrayList;
31    import java.util.Arrays;
32    import java.util.Collections;
33    import java.util.HashMap;
34    import java.util.List;
35    import java.util.Map;
36    import java.util.regex.Matcher;
37    import java.util.regex.Pattern;
38   
39    import javax.inject.Inject;
40    import javax.inject.Named;
41    import javax.inject.Provider;
42    import javax.inject.Singleton;
43   
44    import org.apache.commons.io.IOUtils;
45    import org.apache.commons.lang3.StringUtils;
46    import org.slf4j.Logger;
47    import org.xwiki.component.annotation.Component;
48    import org.xwiki.component.manager.ComponentLookupException;
49    import org.xwiki.component.manager.ComponentManager;
50    import org.xwiki.configuration.ConfigurationSource;
51    import org.xwiki.environment.Environment;
52    import org.xwiki.filter.input.InputSource;
53    import org.xwiki.filter.input.InputStreamInputSource;
54    import org.xwiki.filter.input.ReaderInputSource;
55    import org.xwiki.filter.input.StringInputSource;
56    import org.xwiki.job.event.status.JobProgressManager;
57    import org.xwiki.model.reference.DocumentReference;
58    import org.xwiki.model.reference.DocumentReferenceResolver;
59    import org.xwiki.properties.BeanManager;
60    import org.xwiki.properties.ConverterManager;
61    import org.xwiki.properties.PropertyException;
62    import org.xwiki.properties.RawProperties;
63    import org.xwiki.properties.annotation.PropertyHidden;
64    import org.xwiki.properties.annotation.PropertyId;
65    import org.xwiki.rendering.block.Block;
66    import org.xwiki.rendering.block.GroupBlock;
67    import org.xwiki.rendering.block.RawBlock;
68    import org.xwiki.rendering.block.VerbatimBlock;
69    import org.xwiki.rendering.block.WordBlock;
70    import org.xwiki.rendering.block.XDOM;
71    import org.xwiki.rendering.internal.transformation.MutableRenderingContext;
72    import org.xwiki.rendering.parser.ContentParser;
73    import org.xwiki.rendering.renderer.BlockRenderer;
74    import org.xwiki.rendering.renderer.printer.WikiPrinter;
75    import org.xwiki.rendering.renderer.printer.WriterWikiPrinter;
76    import org.xwiki.rendering.syntax.Syntax;
77    import org.xwiki.rendering.transformation.RenderingContext;
78    import org.xwiki.rendering.transformation.TransformationContext;
79    import org.xwiki.rendering.transformation.TransformationManager;
80    import org.xwiki.security.authorization.AuthorExecutor;
81    import org.xwiki.skin.Resource;
82    import org.xwiki.skin.ResourceRepository;
83    import org.xwiki.skin.Skin;
84    import org.xwiki.template.Template;
85    import org.xwiki.template.TemplateContent;
86    import org.xwiki.velocity.VelocityManager;
87   
88    import com.xpn.xwiki.XWiki;
89    import com.xpn.xwiki.internal.skin.AbstractEnvironmentResource;
90    import com.xpn.xwiki.internal.skin.InternalSkinManager;
91    import com.xpn.xwiki.internal.skin.WikiResource;
92    import com.xpn.xwiki.user.api.XWikiRightService;
93   
94    /**
95    * Internal toolkit to experiment on templates.
96    *
97    * @version $Id: 53df6b3da622407835a248489720fb427fdd67ac $
98    * @since 7.0M1
99    */
100    @Component(roles = InternalTemplateManager.class)
101    @Singleton
 
102    public class InternalTemplateManager
103    {
104    private static final Pattern PROPERTY_LINE = Pattern.compile("^##!(.+)=(.*)$\r?\n?", Pattern.MULTILINE);
105   
106    /**
107    * The reference of the superadmin user.
108    */
109    private static final DocumentReference SUPERADMIN_REFERENCE =
110    new DocumentReference("xwiki", XWiki.SYSTEM_SPACE, XWikiRightService.SUPERADMIN_USER);
111   
112    @Inject
113    private Environment environment;
114   
115    @Inject
116    private ContentParser parser;
117   
118    @Inject
119    private VelocityManager velocityManager;
120   
121    /**
122    * Used to execute transformations.
123    */
124    @Inject
125    private TransformationManager transformationManager;
126   
127    @Inject
128    @Named("context")
129    private Provider<ComponentManager> componentManagerProvider;
130   
131    @Inject
132    private RenderingContext renderingContext;
133   
134    @Inject
135    @Named("plain/1.0")
136    private BlockRenderer plainRenderer;
137   
138    @Inject
139    @Named("xwikicfg")
140    private ConfigurationSource xwikicfg;
141   
142    @Inject
143    @Named("all")
144    private ConfigurationSource allConfiguration;
145   
146    @Inject
147    @Named("currentmixed")
148    private DocumentReferenceResolver<String> currentMixedDocumentReferenceResolver;
149   
150    @Inject
151    private BeanManager beanManager;
152   
153    @Inject
154    private ConverterManager converter;
155   
156    @Inject
157    private AuthorExecutor authorExecutor;
158   
159    @Inject
160    private InternalSkinManager skins;
161   
162    @Inject
163    private JobProgressManager progress;
164   
165    @Inject
166    private Logger logger;
167   
 
168    private static abstract class AbtractTemplate<T extends TemplateContent, R extends Resource<?>> implements Template
169    {
170    protected R resource;
171   
172    protected T content;
173   
 
174  906570 toggle public AbtractTemplate(R resource)
175    {
176  906780 this.resource = resource;
177    }
178   
 
179  3560044 toggle @Override
180    public String getId()
181    {
182  3560962 return this.resource.getId();
183    }
184   
 
185  0 toggle @Override
186    public String getPath()
187    {
188  0 return this.resource.getPath();
189    }
190   
 
191  3300446 toggle @Override
192    public TemplateContent getContent() throws Exception
193    {
194  3301362 if (this.content == null) {
195    // TODO: work with streams instead of forcing String
196  834070 String strinContent;
197   
198  833889 try (InputSource source = this.resource.getInputSource()) {
199  833426 if (source instanceof StringInputSource) {
200  3 strinContent = source.toString();
201  833263 } else if (source instanceof ReaderInputSource) {
202  0 strinContent = IOUtils.toString(((ReaderInputSource) source).getReader());
203  834100 } else if (source instanceof InputStreamInputSource) {
204    // It's impossible to know the real attachment encoding, but let's assume that they respect the
205    // standard and use UTF-8 (which is required for the files located on the filesystem)
206  834198 strinContent = IOUtils.toString(((InputStreamInputSource) source).getInputStream(),
207    StandardCharsets.UTF_8);
208    } else {
209  0 return null;
210    }
211    }
212   
213  834194 this.content = getContentInternal(strinContent);
214    }
215   
216  3301248 return this.content;
217    }
218   
219    protected abstract T getContentInternal(String content) throws Exception;
220   
 
221  0 toggle @Override
222    public String toString()
223    {
224  0 return this.resource.getId();
225    }
226    }
227   
 
228    private class EnvironmentTemplate extends AbtractTemplate<FilesystemTemplateContent, AbstractEnvironmentResource>
229    {
 
230  906731 toggle EnvironmentTemplate(AbstractEnvironmentResource resource)
231    {
232  906614 super(resource);
233    }
234   
 
235  834210 toggle @Override
236    protected FilesystemTemplateContent getContentInternal(String content)
237    {
238  834214 return new FilesystemTemplateContent(content);
239    }
240    }
241   
 
242    private class ClassloaderTemplate extends AbtractTemplate<FilesystemTemplateContent, ClassloaderResource>
243    {
 
244  1 toggle ClassloaderTemplate(ClassloaderResource resource)
245    {
246  1 super(resource);
247    }
248   
 
249  1 toggle @Override
250    protected FilesystemTemplateContent getContentInternal(String content)
251    {
252  1 return new FilesystemTemplateContent(content);
253    }
254    }
255   
 
256    private class DefaultTemplate extends AbtractTemplate<DefaultTemplateContent, Resource<?>>
257    {
 
258  4 toggle DefaultTemplate(Resource<?> resource)
259    {
260  4 super(resource);
261    }
262   
 
263  4 toggle @Override
264    protected DefaultTemplateContent getContentInternal(String content)
265    {
266  4 if (this.resource instanceof WikiResource) {
267  3 WikiResource<?> wikiResource = ((WikiResource<?>) this.resource);
268  3 return new DefaultTemplateContent(content, wikiResource.getAuthorReference(),
269    wikiResource.getDocumentReference());
270    } else {
271  1 return new DefaultTemplateContent(content);
272    }
273    }
274    }
275   
 
276    private class StringTemplate extends DefaultTemplate
277    {
 
278  1 toggle StringTemplate(String content, DocumentReference authorReference) throws Exception
279    {
280  1 super(new StringResource(content));
281    // Initialize the template content
282    // As StringTemplate extends DefaultTemplate, the TemplateContent is DefaultTemplateContent
283  1 ((DefaultTemplateContent) this.getContent()).setAuthorReference(authorReference);
284    }
285    }
286   
 
287    private class DefaultTemplateContent implements RawProperties, TemplateContent
288    {
289    // TODO: work with streams instead
290    protected String content;
291   
292    protected boolean authorProvided;
293   
294    protected DocumentReference authorReference;
295   
296    protected DocumentReference documentReference;
297   
298    @PropertyId("source.syntax")
299    public Syntax sourceSyntax;
300   
301    @PropertyId("raw.syntax")
302    public Syntax rawSyntax;
303   
304    protected Map<String, Object> properties = new HashMap<>();
305   
 
306  833848 toggle DefaultTemplateContent(String content)
307    {
308  833872 this.content = content;
309   
310  833923 init();
311    }
312   
 
313  3 toggle DefaultTemplateContent(String content, DocumentReference authorReference)
314    {
315  3 this(content);
316   
317  3 setAuthorReference(authorReference);
318    }
319   
 
320  3 toggle DefaultTemplateContent(String content, DocumentReference authorReference, DocumentReference sourceReference)
321    {
322  3 this(content, authorReference);
323   
324  3 setDocumentReference(sourceReference);
325    }
326   
 
327  822027 toggle @Override
328    public Syntax getSourceSyntax()
329    {
330  822350 return this.sourceSyntax;
331    }
332   
 
333  35325 toggle @Override
334    public Syntax getRawSyntax()
335    {
336  35426 return this.rawSyntax;
337    }
338   
 
339  0 toggle @Override
340    public <T> T getProperty(String name, T def)
341    {
342  0 if (!this.properties.containsKey(name)) {
343  0 return def;
344    }
345   
346  0 if (def != null) {
347  0 return getProperty(name, def.getClass());
348    }
349   
350  0 return (T) this.properties.get(name);
351    }
352   
 
353  0 toggle @Override
354    public <T> T getProperty(String name, Type type)
355    {
356  0 return converter.convert(type, this.properties.get(name));
357    }
358   
 
359  833762 toggle protected void init()
360    {
361  833861 Matcher matcher = PROPERTY_LINE.matcher(this.content);
362   
363  833924 Map<String, String> map = new HashMap<>();
364  833665 while (matcher.find()) {
365  23 String key = matcher.group(1);
366  23 String value = matcher.group(2);
367   
368  23 map.put(key, value);
369   
370    // Remove the line from the content
371  23 this.content = this.content.substring(matcher.end());
372    }
373   
374  833541 try {
375  833604 InternalTemplateManager.this.beanManager.populate(this, map);
376    } catch (PropertyException e) {
377    // Should never happen
378  0 InternalTemplateManager.this.logger.error("Failed to populate properties of template", e);
379    }
380    }
381   
 
382  833639 toggle @Override
383    public String getContent()
384    {
385  833828 return this.content;
386    }
387   
 
388  821872 toggle @PropertyHidden
389    @Override
390    public boolean isAuthorProvided()
391    {
392  822500 return this.authorProvided;
393    }
394   
 
395  822581 toggle @PropertyId("author")
396    @Override
397    public DocumentReference getAuthorReference()
398    {
399  822780 return this.authorReference;
400    }
401   
 
402  833467 toggle protected void setAuthorReference(DocumentReference authorReference)
403    {
404  833670 this.authorReference = authorReference;
405  833550 this.authorProvided = true;
406    }
407   
 
408  822682 toggle @Override
409    public DocumentReference getDocumentReference()
410    {
411  822796 return this.documentReference;
412    }
413   
 
414  3 toggle protected void setDocumentReference(DocumentReference documentReference)
415    {
416  3 this.documentReference = documentReference;
417    }
418   
419    // RawProperties
420   
 
421  0 toggle @Override
422    public void set(String propertyName, Object value)
423    {
424  0 this.properties.put(propertyName, value);
425    }
426    }
427   
 
428    private class FilesystemTemplateContent extends DefaultTemplateContent
429    {
 
430  833777 toggle public FilesystemTemplateContent(String content)
431    {
432  833553 super(content);
433   
434    // Give programming right to filesystem templates by default
435  833804 setPrivileged(true);
436    }
437   
438    /**
439    * {@inheritDoc}
440    * <p>
441    * Allow filesystem template to indicate the user to executed them with.
442    * </p>
443    *
444    * @see #setAuthorReference(DocumentReference)
445    */
 
446  833883 toggle @Override
447    public void setAuthorReference(DocumentReference authorReference)
448    {
449  833745 super.setAuthorReference(authorReference);
450    }
451   
452    /**
453    * Made public to be seen as bean property.
454    *
455    * @since 6.3.1
456    * @since 6.4M1
457    */
 
458  0 toggle @SuppressWarnings("unused")
459    public boolean isPrivileged()
460    {
461  0 return SUPERADMIN_REFERENCE.equals(getAuthorReference());
462    }
463   
464    /**
465    * Made public to be seen as bean property.
466    *
467    * @since 6.3.1
468    * @since 6.4M1
469    */
 
470  834008 toggle public void setPrivileged(boolean privileged)
471    {
472  834082 if (privileged) {
473  833884 setAuthorReference(SUPERADMIN_REFERENCE);
474    } else {
475    // Reset author
476  0 this.authorReference = null;
477  0 this.authorProvided = false;
478    }
479    }
480    }
481   
 
482  453089 toggle private String getResourcePath(String suffixPath, String templateName, boolean testExist)
483    {
484  454033 String templatePath = suffixPath + templateName;
485   
486    // Prevent inclusion of templates from other directories
487  453854 String normalizedTemplate = URI.create(templatePath).normalize().toString();
488  453288 if (!normalizedTemplate.startsWith(suffixPath)) {
489  4 this.logger.warn("Direct access to template file [{}] refused. Possible break-in attempt!",
490    normalizedTemplate);
491   
492  4 return null;
493    }
494   
495  453776 if (testExist) {
496    // Check if the resource exist
497  453892 if (this.environment.getResource(templatePath) == null) {
498  19795 return null;
499    }
500    }
501   
502  434065 return templatePath;
503    }
504   
 
505  0 toggle private void renderError(Throwable throwable, Writer writer)
506    {
507  0 XDOM xdom = generateError(throwable);
508   
509  0 render(xdom, writer);
510    }
511   
 
512  0 toggle private XDOM generateError(Throwable throwable)
513    {
514  0 List<Block> errorBlocks = new ArrayList<Block>();
515   
516    // Add short message
517  0 Map<String, String> errorBlockParams = Collections.singletonMap("class", "xwikirenderingerror");
518  0 errorBlocks.add(
519    new GroupBlock(Arrays.<Block>asList(new WordBlock("Failed to render step content")), errorBlockParams));
520   
521    // Add complete error
522  0 StringWriter writer = new StringWriter();
523  0 throwable.printStackTrace(new PrintWriter(writer));
524  0 Block descriptionBlock = new VerbatimBlock(writer.toString(), false);
525  0 Map<String, String> errorDescriptionBlockParams =
526    Collections.singletonMap("class", "xwikirenderingerrordescription hidden");
527  0 errorBlocks.add(new GroupBlock(Arrays.asList(descriptionBlock), errorDescriptionBlockParams));
528   
529  0 return new XDOM(errorBlocks);
530    }
531   
 
532  35608 toggle private void transform(Block block)
533    {
534  35720 TransformationContext txContext =
535  35806 new TransformationContext(block instanceof XDOM ? (XDOM) block : new XDOM(Arrays.asList(block)),
536    this.renderingContext.getDefaultSyntax(), this.renderingContext.isRestricted());
537   
538  35741 txContext.setId(this.renderingContext.getTransformationId());
539  35758 txContext.setTargetSyntax(getTargetSyntax());
540   
541  35725 try {
542  35707 this.transformationManager.performTransformations(block, txContext);
543    } catch (Exception e) {
544  0 throw new RuntimeException(e);
545    }
546    }
547   
548    /**
549    * @param templateName the template to parse
550    * @return the result of the template parsing
551    */
 
552  0 toggle public XDOM getXDOMNoException(String templateName)
553    {
554  0 XDOM xdom;
555   
556  0 try {
557  0 xdom = getXDOM(templateName);
558    } catch (Throwable e) {
559  0 this.logger.error("Error while getting template [{}] XDOM", templateName, e);
560   
561  0 xdom = generateError(e);
562    }
563   
564  0 return xdom;
565    }
566   
567    /**
568    * @param template the template to parse
569    * @return the result of the template parsing
570    * @since 8.3RC1
571    */
 
572  0 toggle public XDOM getXDOMNoException(Template template)
573    {
574  0 XDOM xdom;
575   
576  0 try {
577  0 xdom = getXDOM(template);
578    } catch (Throwable e) {
579  0 this.logger.error("Error while getting template [{}] XDOM", template.getId(), e);
580   
581  0 xdom = generateError(e);
582    }
583   
584  0 return xdom;
585    }
586   
 
587  0 toggle public XDOM getXDOM(Template template) throws Exception
588    {
589  0 XDOM xdom;
590   
591  0 if (template != null) {
592  0 xdom = getXDOM(template, template.getContent());
593    } else {
594  0 xdom = new XDOM(Collections.<Block>emptyList());
595    }
596   
597  0 return xdom;
598    }
599   
 
600  35425 toggle private XDOM getXDOM(Template template, TemplateContent content) throws Exception
601    {
602  35708 XDOM xdom;
603   
604  35743 if (content.getSourceSyntax() != null) {
605  23 xdom = this.parser.parse(content.getContent(), content.getSourceSyntax());
606    } else {
607  35611 String result = evaluateContent(template, content);
608  35773 if (StringUtils.isEmpty(result)) {
609  387 xdom = new XDOM(Collections.emptyList());
610    } else {
611  35385 xdom = new XDOM(Arrays.asList(new RawBlock(result,
612  35391 content.getRawSyntax() != null ? content.getRawSyntax() : renderingContext.getTargetSyntax())));
613    }
614    }
615   
616  35692 return xdom;
617    }
618   
 
619  0 toggle public XDOM getXDOM(String templateName) throws Exception
620    {
621  0 Template template = getTemplate(templateName);
622   
623  0 return getXDOM(template);
624    }
625   
 
626  0 toggle public String renderNoException(String template)
627    {
628  0 Writer writer = new StringWriter();
629   
630  0 renderNoException(template, writer);
631   
632  0 return writer.toString();
633    }
634   
 
635  0 toggle public void renderNoException(String templateName, Writer writer)
636    {
637  0 try {
638  0 render(templateName, writer);
639    } catch (Exception e) {
640  0 this.logger.error("Error while rendering template [{}]", templateName, e);
641   
642  0 renderError(e, writer);
643    }
644    }
645   
646    /**
647    * @since 8.3RC1
648    */
 
649  0 toggle public void renderNoException(Template template, Writer writer)
650    {
651  0 try {
652  0 render(template, writer);
653    } catch (Exception e) {
654  0 this.logger.error("Error while rendering template [{}]", template, e);
655   
656  0 renderError(e, writer);
657    }
658    }
659   
 
660  786313 toggle public String render(String templateName) throws Exception
661    {
662  786657 return renderFromSkin(templateName, (Skin) null);
663    }
664   
 
665  0 toggle public String renderFromSkin(String templateName, String skinId) throws Exception
666    {
667  0 Skin skin = this.skins.getSkin(skinId);
668   
669  0 return skin != null ? renderFromSkin(templateName, skin) : null;
670    }
671   
 
672  786624 toggle public String renderFromSkin(String templateName, Skin skin) throws Exception
673    {
674  786528 Writer writer = new StringWriter();
675   
676  786515 renderFromSkin(templateName, skin, writer);
677   
678  786942 return writer.toString();
679    }
680   
 
681  0 toggle public void render(String templateName, Writer writer) throws Exception
682    {
683  0 renderFromSkin(templateName, null, writer);
684    }
685   
 
686  786868 toggle public void renderFromSkin(final String templateName, ResourceRepository repository, final Writer writer)
687    throws Exception
688    {
689  787085 this.progress.startStep(templateName, "template.render.message", "Render template [{}]", templateName);
690   
691  786907 try {
692  787083 final Template template =
693  786991 repository != null ? getTemplate(templateName, repository) : getTemplate(templateName);
694   
695  786696 if (template != null) {
696  785828 if (template.getContent().isAuthorProvided()) {
697  786441 this.authorExecutor.call(() -> {
698  786884 render(template, template.getContent(), writer);
699   
700  786966 return null;
701    }, template.getContent().getAuthorReference(), template.getContent().getDocumentReference());
702    } else {
703  0 render(template, template.getContent(), writer);
704    }
705    }
706    } finally {
707  787036 this.progress.endStep(templateName);
708    }
709    }
710   
 
711  0 toggle public void render(Template template, Writer writer) throws Exception
712    {
713  0 render(template, template.getContent(), writer);
714    }
715   
 
716  786857 toggle private void render(Template template, TemplateContent content, Writer writer) throws Exception
717    {
718  786639 if (content.getSourceSyntax() != null) {
719  1 XDOM xdom = execute(template, content);
720   
721  1 render(xdom, writer);
722    } else {
723  786450 evaluateContent(template, content, writer);
724    }
725    }
726   
 
727  1 toggle private void render(XDOM xdom, Writer writer)
728    {
729  1 WikiPrinter printer = new WriterWikiPrinter(writer);
730   
731  1 BlockRenderer blockRenderer;
732  1 try {
733  1 blockRenderer =
734    this.componentManagerProvider.get().getInstance(BlockRenderer.class, getTargetSyntax().toIdString());
735    } catch (ComponentLookupException e) {
736  0 blockRenderer = this.plainRenderer;
737    }
738   
739  1 blockRenderer.render(xdom, printer);
740    }
741   
 
742  22 toggle public XDOM executeNoException(String templateName)
743    {
744  22 XDOM xdom;
745   
746  22 try {
747  22 xdom = execute(templateName);
748    } catch (Throwable e) {
749  0 this.logger.error("Error while executing template [{}]", templateName, e);
750   
751  0 xdom = generateError(e);
752    }
753   
754  22 return xdom;
755    }
756   
757    /**
758    * @since 8.3RC1
759    */
 
760  0 toggle public XDOM executeNoException(Template template)
761    {
762  0 XDOM xdom;
763   
764  0 try {
765  0 xdom = execute(template);
766    } catch (Throwable e) {
767  0 this.logger.error("Error while executing template [{}]", template.getId(), e);
768   
769  0 xdom = generateError(e);
770    }
771   
772  0 return xdom;
773    }
774   
 
775  35487 toggle private XDOM execute(Template template, TemplateContent content) throws Exception
776    {
777  35762 XDOM xdom = getXDOM(template, content);
778   
779  35625 transform(xdom);
780   
781  35643 return xdom;
782    }
783   
 
784  35843 toggle public XDOM execute(String templateName) throws Exception
785    {
786  35852 final Template template = getTemplate(templateName);
787   
788  35826 if (template != null) {
789  35480 if (template.getContent().isAuthorProvided()) {
790  35499 return this.authorExecutor.call(() -> execute(template, template.getContent()),
791    template.getContent().getAuthorReference(), template.getContent().getDocumentReference());
792    } else {
793  0 return execute(template, template.getContent());
794    }
795    }
796   
797  0 return null;
798    }
799   
 
800  15 toggle public XDOM execute(Template template) throws Exception
801    {
802  15 if (template != null) {
803  15 if (template.getContent().isAuthorProvided()) {
804  15 return this.authorExecutor.call(() -> execute(template, template.getContent()),
805    template.getContent().getAuthorReference(), template.getContent().getDocumentReference());
806    } else {
807  0 return execute(template, template.getContent());
808    }
809    }
810   
811  0 return null;
812    }
813   
 
814  35495 toggle private String evaluateContent(Template template, TemplateContent content) throws Exception
815    {
816  35728 Writer writer = new StringWriter();
817   
818  35614 evaluateContent(template, content, writer);
819   
820  35730 return writer.toString();
821    }
822   
 
823  821606 toggle private void evaluateContent(Template template, TemplateContent content, Writer writer) throws Exception
824    {
825    // Use the Transformation id as the name passed to the Velocity Engine. This name is used internally
826    // by Velocity as a cache index key for caching macros.
827  822131 String namespace = this.renderingContext.getTransformationId();
828   
829  822389 boolean renderingContextPushed = false;
830  822658 if (namespace == null) {
831  55880 namespace = template.getId() != null ? template.getId() : "unknown namespace";
832   
833  55958 if (this.renderingContext instanceof MutableRenderingContext) {
834    // Make the current velocity template id available
835  55891 ((MutableRenderingContext) this.renderingContext).push(this.renderingContext.getTransformation(),
836    this.renderingContext.getXDOM(), this.renderingContext.getDefaultSyntax(), namespace,
837    this.renderingContext.isRestricted(), this.renderingContext.getTargetSyntax());
838   
839  55578 renderingContextPushed = true;
840    }
841    }
842   
843  822410 this.progress.startStep(template, "template.evaluateContent.message",
844    "Evaluate content of template with id [{}]", template.getId());
845   
846  822527 try {
847  822604 this.velocityManager.evaluate(writer, namespace, new StringReader(content.getContent()));
848    } finally {
849    // Get rid of temporary rendering context
850  822921 if (renderingContextPushed) {
851  56048 ((MutableRenderingContext) this.renderingContext).pop();
852    }
853   
854  822845 this.progress.endStep(template);
855    }
856    }
857   
 
858  35708 toggle private Syntax getTargetSyntax()
859    {
860  35805 Syntax targetSyntax = this.renderingContext.getTargetSyntax();
861   
862  35793 return targetSyntax != null ? targetSyntax : Syntax.PLAIN_1_0;
863    }
864   
 
865  452950 toggle private EnvironmentTemplate getFileSystemTemplate(String suffixPath, String templateName)
866    {
867  453455 String path = getResourcePath(suffixPath, templateName, true);
868   
869  454132 return path != null
870    ? new EnvironmentTemplate(new TemplateEnvironmentResource(path, templateName, this.environment)) : null;
871    }
872   
 
873  19799 toggle private Template getClassloaderTemplate(String suffixPath, String templateName)
874    {
875  19799 return getClassloaderTemplate(Thread.currentThread().getContextClassLoader(), suffixPath, templateName);
876    }
877   
 
878  19799 toggle private Template getClassloaderTemplate(ClassLoader classloader, String suffixPath, String templateName)
879    {
880  19799 String templatePath = suffixPath + templateName;
881   
882  19799 URL url = classloader.getResource(templatePath);
883   
884  19799 return url != null ? new ClassloaderTemplate(new ClassloaderResource(url, templateName)) : null;
885    }
886   
 
887  472970 toggle private Template createTemplate(Resource<?> resource)
888    {
889  473037 Template template;
890   
891  473303 if (resource instanceof AbstractEnvironmentResource) {
892  473310 template = new EnvironmentTemplate((AbstractEnvironmentResource) resource);
893    } else {
894  3 template = new DefaultTemplate(resource);
895    }
896   
897  473137 return template;
898    }
899   
 
900  0 toggle public Template getResourceTemplate(String templateName, ResourceRepository repository)
901    {
902  0 Resource<?> resource = repository.getLocalResource(templateName);
903  0 if (resource != null) {
904  0 return createTemplate(resource);
905    }
906   
907  0 return null;
908    }
909   
 
910  926309 toggle public Template getTemplate(String templateName, ResourceRepository repository)
911    {
912  927223 Resource<?> resource = repository.getResource(templateName);
913  926799 if (resource != null) {
914  473158 return createTemplate(resource);
915    }
916   
917  453345 return null;
918    }
919   
 
920  914783 toggle public Template getTemplate(String templateName)
921    {
922  915297 Template template = null;
923   
924    // Try from skin
925  916085 Skin skin = this.skins.getCurrentSkin(false);
926  916071 if (skin != null) {
927  915959 template = getTemplate(templateName, skin);
928    }
929   
930    // Try from base skin if no skin is set
931  916082 if (skin == null) {
932  0 Skin baseSkin = this.skins.getCurrentParentSkin(false);
933  0 if (baseSkin != null) {
934  0 template = getTemplate(templateName, baseSkin);
935    }
936    }
937   
938    // Try from /templates/ environment resources
939  915514 if (template == null) {
940  453650 template = getFileSystemTemplate("/templates/", templateName);
941    }
942   
943    // Try from current Thread classloader
944  915788 if (template == null) {
945  19799 template = getClassloaderTemplate("templates/", templateName);
946    }
947   
948  915720 return template;
949    }
950   
951    /**
952    * Create a DefaultTemplate with the given content and the given author.
953    *
954    * @since 9.6RC1
955    * @param content the template content
956    * @param author the template author
957    * @return the template
958    */
 
959  1 toggle public Template createStringTemplate(String content, DocumentReference author) throws Exception
960    {
961  1 return new StringTemplate(content, author);
962    }
963    }