1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.script.display

File DisplayScriptService.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart8.png
54% of files have more coverage

Code metrics

20
73
10
1
303
176
25
0.34
7.3
10
2.5

Classes

Class Line # Actions
DisplayScriptService 61 73 0% 25 28
0.728155372.8%
 

Contributing tests

No tests hitting this source file were found.

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.script.display;
21   
22    import java.lang.reflect.Field;
23    import java.util.Collections;
24    import java.util.HashMap;
25    import java.util.Map;
26   
27    import javax.inject.Inject;
28    import javax.inject.Named;
29    import javax.inject.Singleton;
30   
31    import org.slf4j.Logger;
32    import org.xwiki.bridge.DocumentModelBridge;
33    import org.xwiki.component.annotation.Component;
34    import org.xwiki.component.manager.ComponentManager;
35    import org.xwiki.context.Execution;
36    import org.xwiki.display.internal.DocumentDisplayer;
37    import org.xwiki.display.internal.DocumentDisplayerParameters;
38    import org.xwiki.rendering.block.XDOM;
39    import org.xwiki.rendering.renderer.BlockRenderer;
40    import org.xwiki.rendering.renderer.printer.DefaultWikiPrinter;
41    import org.xwiki.rendering.renderer.printer.WikiPrinter;
42    import org.xwiki.rendering.syntax.Syntax;
43    import org.xwiki.rendering.syntax.SyntaxFactory;
44    import org.xwiki.rendering.transformation.RenderingContext;
45    import org.xwiki.script.service.ScriptService;
46   
47    import com.xpn.xwiki.XWikiContext;
48    import com.xpn.xwiki.XWikiException;
49    import com.xpn.xwiki.api.Document;
50    import com.xpn.xwiki.internal.cache.rendering.RenderingCache;
51   
52    /**
53    * Exposes {@link org.xwiki.display.internal.Displayer}s to scripts.
54    *
55    * @version $Id: 071c75f248a03387c5fa8095ba0ef29b2ab1363e $
56    * @since 3.2M3
57    */
58    @Component
59    @Named("display")
60    @Singleton
 
61    public class DisplayScriptService implements ScriptService
62    {
63    /**
64    * The key used to store the displayer parameters in the display parameter map.
65    */
66    private static final String DISPLAYER_PARAMETERS_KEY = "displayerParameters";
67   
68    /** Logging helper object. */
69    @Inject
70    private Logger logger;
71   
72    /**
73    * The component manager.
74    */
75    @Inject
76    private ComponentManager componentManager;
77   
78    /**
79    * The rendering cache.
80    */
81    @Inject
82    private RenderingCache renderingCache;
83   
84    /**
85    * Execution context handler, needed for accessing the XWikiContext.
86    */
87    @Inject
88    private Execution execution;
89   
90    /**
91    * The component used to create syntax instances from syntax identifiers.
92    */
93    @Inject
94    private SyntaxFactory syntaxFactory;
95   
96    @Inject
97    private RenderingContext renderingContext;
98   
 
99  341 toggle private Syntax getOutputSyntax(Map<String, Object> parameters)
100    {
101  341 Syntax outputSyntax = (Syntax) parameters.get("outputSyntax");
102  341 if (outputSyntax == null) {
103  341 String outputSyntaxId = (String) parameters.get("outputSyntaxId");
104  341 if (outputSyntaxId != null) {
105  107 try {
106  107 outputSyntax = this.syntaxFactory.createSyntaxFromIdString(outputSyntaxId);
107    } catch (Exception e) {
108  0 this.logger.error("Failed to parse output syntax ID [{}].", outputSyntaxId, e);
109  0 return null;
110    }
111    } else {
112  234 outputSyntax = renderingContext.getTargetSyntax();
113    }
114    }
115   
116  341 return outputSyntax;
117    }
118   
119    /**
120    * Displays a document.
121    *
122    * @param document the document to display
123    * @param parameters the display parameters
124    * @return the result of displaying the given document
125    */
 
126  341 toggle private String document(Document document, Map<String, Object> parameters, Syntax outputSyntax)
127    {
128  341 DocumentDisplayerParameters displayerParameters =
129    (DocumentDisplayerParameters) parameters.get(DISPLAYER_PARAMETERS_KEY);
130  341 if (displayerParameters == null) {
131  0 displayerParameters = new DocumentDisplayerParameters();
132  0 displayerParameters.setTargetSyntax(outputSyntax);
133    }
134   
135  341 String displayerHint = (String) parameters.get("displayerHint");
136  341 if (displayerHint == null) {
137  158 displayerHint = "configured";
138    }
139  341 try {
140  341 DocumentDisplayer displayer = this.componentManager.getInstance(DocumentDisplayer.class, displayerHint);
141  341 return renderXDOM(displayer.display(getDocument(document), displayerParameters), outputSyntax);
142    } catch (Exception e) {
143  0 this.logger.error("Failed to display document [{}].", document.getPrefixedFullName(), e);
144  0 return null;
145    }
146    }
147   
148    /**
149    * @return a new instance of {@link DocumentDisplayerParameters}
150    */
 
151  0 toggle public DocumentDisplayerParameters createDocumentDisplayerParameters()
152    {
153  0 return new DocumentDisplayerParameters();
154    }
155   
156    /**
157    * @param document the document whose content is displayed
158    * @return the result of rendering the content of the given document as XHTML using the configured displayer
159    * @see #content(Document, Map)
160    */
 
161  158 toggle public String content(Document document)
162    {
163  158 return content(document, Collections.<String, Object>emptyMap());
164    }
165   
166    /**
167    * Displays the content of the given document.
168    *
169    * @param document the document whose content is displayed
170    * @param parameters the display parameters
171    * @return the result of rendering the content of the given document using the provided parameters
172    */
 
173  158 toggle public String content(Document document, Map<String, Object> parameters)
174    {
175  158 XWikiContext context = getXWikiContext();
176  158 String content = null;
177  158 try {
178  158 content = document.getTranslatedContent();
179    } catch (XWikiException e) {
180  0 this.logger.warn("Failed to get the translated content of document [{}].", document.getPrefixedFullName(),
181    e);
182  0 return null;
183    }
184  158 String renderedContent =
185    this.renderingCache.getRenderedContent(document.getDocumentReference(), content, context);
186  158 if (renderedContent == null) {
187  158 Map<String, Object> actualParameters = new HashMap<String, Object>(parameters);
188  158 DocumentDisplayerParameters displayerParameters =
189    (DocumentDisplayerParameters) parameters.get(DISPLAYER_PARAMETERS_KEY);
190  158 if (displayerParameters == null) {
191  158 displayerParameters = new DocumentDisplayerParameters();
192    // Default content display parameters.
193  158 displayerParameters.setExecutionContextIsolated(true);
194  158 displayerParameters.setContentTranslated(true);
195  0 } else if (displayerParameters.isTitleDisplayed()) {
196    // Clone because we have to enforce content display.
197  0 displayerParameters = displayerParameters.clone();
198    }
199    // Ensure the content is displayed.
200  158 displayerParameters.setTitleDisplayed(false);
201  158 Syntax outputSyntax = getOutputSyntax(parameters);
202  158 displayerParameters.setTargetSyntax(outputSyntax);
203  158 actualParameters.put(DISPLAYER_PARAMETERS_KEY, displayerParameters);
204  158 renderedContent = document(document, actualParameters, outputSyntax);
205  158 if (renderedContent != null) {
206  158 this.renderingCache.setRenderedContent(document.getDocumentReference(), content, renderedContent,
207    context);
208    }
209    }
210  158 return renderedContent;
211    }
212   
213    /**
214    * Displays the document title. If a title has not been provided through the title field, it looks for a section
215    * title in the document's content and if not found return the page name. The returned title is also interpreted
216    * which means it's allowed to use Velocity, Groovy, etc. syntax within a title.
217    *
218    * @param document the document whose title is displayed
219    * @param parameters the display parameters
220    * @return the result of displaying the title of the given document
221    */
 
222  183 toggle public String title(Document document, Map<String, Object> parameters)
223    {
224  183 Map<String, Object> actualParameters = new HashMap<String, Object>(parameters);
225  183 DocumentDisplayerParameters displayerParameters =
226    (DocumentDisplayerParameters) parameters.get(DISPLAYER_PARAMETERS_KEY);
227  183 if (displayerParameters == null) {
228  183 displayerParameters = new DocumentDisplayerParameters();
229    // Default title display parameters.
230  183 displayerParameters.setExecutionContextIsolated(true);
231  0 } else if (!displayerParameters.isTitleDisplayed()) {
232    // Clone because we have to enforce title display.
233  0 displayerParameters = displayerParameters.clone();
234    }
235    // Ensure the title is displayed.
236  183 displayerParameters.setTitleDisplayed(true);
237  183 Syntax outputSyntax = getOutputSyntax(parameters);
238  183 displayerParameters.setTargetSyntax(outputSyntax);
239  183 actualParameters.put(DISPLAYER_PARAMETERS_KEY, displayerParameters);
240  183 return document(document, actualParameters, outputSyntax);
241    }
242   
243    /**
244    * @param document the document whose title is displayed
245    * @return the result of rendering the title of the given document as XHTML using the configured displayer
246    * @see #title(Document, Map)
247    */
 
248  0 toggle public String title(Document document)
249    {
250  0 return title(document, Collections.<String, Object>emptyMap());
251    }
252   
253    /**
254    * Note: This method accesses the low level XWiki document through reflection in order to bypass programming rights.
255    *
256    * @param document an instance of {@link Document} received from a script
257    * @return an instance of {@link DocumentModelBridge} that wraps the low level document object exposed by the given
258    * document API
259    */
 
260  341 toggle private DocumentModelBridge getDocument(Document document)
261    {
262  341 try {
263    // HACK: We try to access the XWikiDocument instance wrapped by the document API using reflection because we
264    // want to bypass the programming rights requirements.
265  341 Field docField = Document.class.getDeclaredField("doc");
266  341 docField.setAccessible(true);
267  341 return (DocumentModelBridge) docField.get(document);
268    } catch (Exception e) {
269  0 throw new RuntimeException("Failed to access the XWikiDocument instance wrapped by the document API.", e);
270    }
271    }
272   
273    /**
274    * Renders the provided XDOM.
275    *
276    * @param content the XDOM content to render
277    * @param targetSyntax the syntax of the rendering result
278    * @return the result of rendering the given XDOM
279    * @throws XWikiException if an exception occurred during the rendering process
280    */
 
281  341 toggle private String renderXDOM(XDOM content, Syntax targetSyntax) throws XWikiException
282    {
283  341 try {
284  341 BlockRenderer renderer = this.componentManager.getInstance(BlockRenderer.class, targetSyntax.toIdString());
285  341 WikiPrinter printer = new DefaultWikiPrinter();
286  341 renderer.render(content, printer);
287  341 return printer.toString();
288    } catch (Exception e) {
289  0 throw new XWikiException(XWikiException.MODULE_XWIKI_RENDERING, XWikiException.ERROR_XWIKI_UNKNOWN,
290    "Failed to render XDOM to syntax [" + targetSyntax + "]", e);
291    }
292    }
293   
294    /**
295    * @return the XWiki context
296    * @deprecated avoid using this method; try using the document access bridge instead
297    */
 
298  158 toggle @Deprecated
299    private XWikiContext getXWikiContext()
300    {
301  158 return (XWikiContext) this.execution.getContext().getProperty("xwikicontext");
302    }
303    }