1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.rendering.wikimacro.internal

File DefaultWikiMacroFactory.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart9.png
38% of files have more coverage

Code metrics

36
98
5
1
333
220
34
0.35
19.6
5
6.8

Classes

Class Line # Actions
DefaultWikiMacroFactory 65 98 0% 34 18
0.870503687.1%
 

Contributing tests

This file is covered by 6 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 org.xwiki.rendering.wikimacro.internal;
21   
22    import java.util.ArrayList;
23    import java.util.List;
24    import java.util.Vector;
25   
26    import javax.inject.Inject;
27    import javax.inject.Singleton;
28   
29    import org.apache.commons.lang3.StringUtils;
30    import org.slf4j.Logger;
31    import org.xwiki.component.annotation.Component;
32    import org.xwiki.component.manager.ComponentManager;
33    import org.xwiki.context.Execution;
34    import org.xwiki.model.reference.DocumentReference;
35    import org.xwiki.model.reference.EntityReferenceSerializer;
36    import org.xwiki.rendering.block.XDOM;
37    import org.xwiki.rendering.internal.macro.wikibridge.DefaultWikiMacro;
38    import org.xwiki.rendering.macro.MacroId;
39    import org.xwiki.rendering.macro.descriptor.ContentDescriptor;
40    import org.xwiki.rendering.macro.descriptor.DefaultContentDescriptor;
41    import org.xwiki.rendering.macro.descriptor.MacroDescriptor;
42    import org.xwiki.rendering.macro.wikibridge.WikiMacro;
43    import org.xwiki.rendering.macro.wikibridge.WikiMacroDescriptor;
44    import org.xwiki.rendering.macro.wikibridge.WikiMacroException;
45    import org.xwiki.rendering.macro.wikibridge.WikiMacroFactory;
46    import org.xwiki.rendering.macro.wikibridge.WikiMacroParameterDescriptor;
47    import org.xwiki.rendering.macro.wikibridge.WikiMacroVisibility;
48    import org.xwiki.rendering.parser.ContentParser;
49    import org.xwiki.rendering.parser.MissingParserException;
50    import org.xwiki.rendering.parser.ParseException;
51   
52    import com.xpn.xwiki.XWikiContext;
53    import com.xpn.xwiki.XWikiException;
54    import com.xpn.xwiki.doc.XWikiDocument;
55    import com.xpn.xwiki.objects.BaseObject;
56   
57    /**
58    * The default implementation of {@link org.xwiki.rendering.macro.wikibridge.WikiMacroFactory}.
59    *
60    * @version $Id: 00fe4613b78985a6a7a0c20d6a836a7e7a644646 $
61    * @since 2.0M2
62    */
63    @Component
64    @Singleton
 
65    public class DefaultWikiMacroFactory implements WikiMacroFactory, WikiMacroConstants
66    {
67    /**
68    * The {@link ComponentManager} component.
69    */
70    @Inject
71    private ComponentManager componentManager;
72   
73    /**
74    * The {@link Execution} component used for accessing XWikiContext.
75    */
76    @Inject
77    private Execution execution;
78   
79    /**
80    * Used to serialize references of documents.
81    */
82    @Inject
83    private EntityReferenceSerializer<String> serializer;
84   
85    /**
86    * Content parser used to parse the macro content.
87    */
88    @Inject
89    private ContentParser parser;
90   
91    /**
92    * The logger to log.
93    */
94    @Inject
95    private Logger logger;
96   
97    /**
98    * Utility method for accessing XWikiContext.
99    *
100    * @return the XWikiContext.
101    */
 
102  1708 toggle private XWikiContext getContext()
103    {
104  1708 return (XWikiContext) this.execution.getContext().getProperty("xwikicontext");
105    }
106   
 
107  232 toggle @Override
108    public WikiMacro createWikiMacro(DocumentReference documentReference) throws WikiMacroException
109    {
110  232 XWikiDocument doc;
111  232 try {
112  232 doc = getContext().getWiki().getDocument(documentReference, getContext());
113    } catch (XWikiException ex) {
114  0 throw new WikiMacroException(String.format("Could not build macro from : [%s], unable to load document",
115    documentReference), ex);
116    }
117  232 return buildMacro(doc);
118    }
119   
120    /**
121    * Creates a {@link WikiMacro} from an {@link XWikiDocument} which contains a macro definition.
122    *
123    * @param doc the {@link XWikiDocument} to look for a macro definition
124    * @return the {@link WikiMacro} found inside the document
125    * @throws WikiMacroException when an invalid macro definition or no macro definition was found
126    */
 
127  232 toggle private WikiMacro buildMacro(XWikiDocument doc) throws WikiMacroException
128    {
129  232 DocumentReference documentReference = doc.getDocumentReference();
130   
131    // Check whether this document contains a macro definition.
132  232 BaseObject macroDefinition = doc.getObject(WIKI_MACRO_CLASS);
133  232 if (null == macroDefinition) {
134  0 throw new WikiMacroException(String.format("No macro definition found in document : [%s]",
135    documentReference));
136    }
137   
138    // Extract macro definition.
139  232 String macroId = macroDefinition.getStringValue(MACRO_ID_PROPERTY);
140  232 String macroName = macroDefinition.getStringValue(MACRO_NAME_PROPERTY);
141    // The macro description as plain text
142  232 String macroDescription = macroDefinition.getStringValue(MACRO_DESCRIPTION_PROPERTY);
143  232 String macroDefaultCategory = macroDefinition.getStringValue(MACRO_DEFAULT_CATEGORY_PROPERTY);
144  232 WikiMacroVisibility macroVisibility =
145    WikiMacroVisibility.fromString(macroDefinition.getStringValue(MACRO_VISIBILITY_PROPERTY));
146  232 boolean macroSupportsInlineMode = (macroDefinition.getIntValue(MACRO_INLINE_PROPERTY) == 0) ? false : true;
147  232 String macroContentType = macroDefinition.getStringValue(MACRO_CONTENT_TYPE_PROPERTY);
148    // The macro content description as plain text
149  232 String macroContentDescription = macroDefinition.getStringValue(MACRO_CONTENT_DESCRIPTION_PROPERTY);
150  232 String macroCode = macroDefinition.getStringValue(MACRO_CODE_PROPERTY);
151   
152    // Verify macro id.
153  232 if (StringUtils.isEmpty(macroId)) {
154  0 throw new WikiMacroException(String.format("Incomplete macro definition in [%s], macro id is empty",
155    documentReference));
156    }
157   
158    // Verify macro name.
159  232 if (StringUtils.isEmpty(macroName)) {
160  4 macroName = macroId;
161  4 this.logger.debug(String.format("Incomplete macro definition in [%s], macro name is empty",
162    documentReference));
163    }
164   
165    // Verify macro description.
166  232 if (StringUtils.isEmpty(macroDescription)) {
167  3 this.logger.debug(String.format("Incomplete macro definition in [%s], macro description is empty",
168    documentReference));
169    }
170   
171    // Verify default macro category.
172  232 if (StringUtils.isEmpty(macroDefaultCategory)) {
173  38 macroDefaultCategory = null;
174  38 this.logger.debug(String.format("Incomplete macro definition in [%s], default macro category is empty",
175    documentReference));
176    }
177   
178    // Verify macro content type.
179  232 if (StringUtils.isEmpty(macroContentType)) {
180  3 macroContentType = MACRO_CONTENT_OPTIONAL;
181    }
182   
183    // Verify macro content description.
184  232 if (!macroContentType.equals(MACRO_CONTENT_EMPTY) && StringUtils.isEmpty(macroContentDescription)) {
185  3 String errorMsg = "Incomplete macro definition in [%s], macro content description is empty";
186  3 this.logger.debug(String.format(errorMsg, documentReference));
187  3 macroContentDescription = "Macro content";
188    }
189   
190    // Verify macro code.
191  232 if (StringUtils.isEmpty(macroCode)) {
192  0 throw new WikiMacroException(String.format("Incomplete macro definition in [%s], macro code is empty",
193    documentReference));
194    }
195   
196    // Extract macro parameters.
197  232 List<WikiMacroParameterDescriptor> parameterDescriptors = new ArrayList<WikiMacroParameterDescriptor>();
198  232 Vector<BaseObject> macroParameters = doc.getObjects(WIKI_MACRO_PARAMETER_CLASS);
199  232 if (null != macroParameters) {
200  154 for (BaseObject macroParameter : macroParameters) {
201    // Vectors can contain null values
202  2020 if (null == macroParameter) {
203  170 continue;
204    }
205   
206    // Extract parameter definition.
207  1850 String parameterName = macroParameter.getStringValue(PARAMETER_NAME_PROPERTY);
208  1850 String parameterDescription = macroParameter.getStringValue(PARAMETER_DESCRIPTION_PROPERTY);
209  1850 boolean parameterMandatory =
210  1850 (macroParameter.getIntValue(PARAMETER_MANDATORY_PROPERTY) == 0) ? false : true;
211  1850 String parameterDefaultValue = macroParameter.getStringValue(PARAMETER_DEFAULT_VALUE_PROPERTY);
212   
213    // Verify parameter name.
214  1850 if (StringUtils.isEmpty(parameterName)) {
215  0 throw new WikiMacroException(String.format(
216    "Incomplete macro definition in [%s], macro parameter name is empty", documentReference));
217    }
218   
219    // Verify parameter description.
220  1850 if (StringUtils.isEmpty(parameterDescription)) {
221  0 String errorMessage = "Incomplete macro definition in [%s], macro parameter description is empty";
222  0 this.logger.debug(String.format(errorMessage, documentReference));
223    }
224   
225    // If field empty, assume no default value was provided.
226  1850 if (StringUtils.isEmpty(parameterDefaultValue)) {
227  770 parameterDefaultValue = null;
228    }
229   
230    // Create the parameter descriptor.
231  1850 parameterDescriptors.add(new WikiMacroParameterDescriptor(parameterName, parameterDescription,
232    parameterMandatory, parameterDefaultValue));
233    }
234    }
235   
236    // Create macro content descriptor.
237  232 ContentDescriptor contentDescriptor = null;
238  232 if (!macroContentType.equals(MACRO_CONTENT_EMPTY)) {
239  39 contentDescriptor =
240    new DefaultContentDescriptor(macroContentDescription, macroContentType.equals(MACRO_CONTENT_MANDATORY));
241    }
242   
243    // Create macro descriptor.
244  232 MacroId id = new MacroId(macroId, doc.getSyntax());
245  232 MacroDescriptor macroDescriptor =
246    new WikiMacroDescriptor(id, macroName, macroDescription, macroDefaultCategory, macroVisibility,
247    contentDescriptor, parameterDescriptors);
248   
249  232 XDOM xdom;
250  232 try {
251  232 xdom = parser.parse(macroCode, doc.getSyntax(), documentReference);
252    } catch (MissingParserException ex) {
253  0 throw new WikiMacroException("Could not find a parser for macro content", ex);
254    } catch (ParseException ex) {
255  0 throw new WikiMacroException("Error while parsing macro content", ex);
256    }
257   
258    // Create & return the macro.
259  232 return new DefaultWikiMacro(documentReference, doc.getAuthorReference(), macroSupportsInlineMode,
260    macroDescriptor, xdom, doc.getSyntax(), this.componentManager);
261    }
262   
 
263  372 toggle @Override
264    public boolean containsWikiMacro(DocumentReference documentReference)
265    {
266  372 boolean result;
267  372 try {
268  372 XWikiDocument doc = getContext().getWiki().getDocument(documentReference, getContext());
269  372 BaseObject macroDefinition = doc.getObject(WIKI_MACRO_CLASS);
270  372 result = (null != macroDefinition);
271    } catch (XWikiException ex) {
272  0 result = false;
273    }
274  372 return result;
275    }
276   
 
277  250 toggle @Override
278    public boolean isAllowed(DocumentReference documentReference, WikiMacroVisibility visibility)
279    {
280  250 boolean isAllowed = false;
281   
282  250 XWikiContext xcontext = getContext();
283   
284  250 DocumentReference authorReference;
285   
286  250 XWikiDocument doc;
287  250 try {
288  250 doc = xcontext.getWiki().getDocument(documentReference, getContext());
289  250 authorReference = doc.getAuthorReference();
290    } catch (XWikiException ex) {
291  0 doc = null;
292  0 authorReference = null;
293    }
294   
295  250 try {
296  250 switch (visibility) {
297  16 case GLOBAL:
298    // Verify that the user has programming rights
299  16 if (doc != null && authorReference != null) {
300  11 isAllowed =
301    xcontext
302    .getWiki()
303    .getRightService()
304    .hasAccessLevel("programming", this.serializer.serialize(authorReference),
305    this.serializer.serialize(doc.getDocumentReference()), xcontext);
306    } else {
307  5 isAllowed = xcontext.getWiki().getRightService().hasProgrammingRights(xcontext);
308    }
309  16 break;
310  194 case WIKI:
311    // Verify that the user has admin right on the macro wiki
312  194 if (doc != null && authorReference != null) {
313  193 isAllowed =
314    xcontext
315    .getWiki()
316    .getRightService()
317    .hasAccessLevel("admin", this.serializer.serialize(authorReference),
318    doc.getDocumentReference().getWikiReference().getName() + ":XWiki.XWikiPreferences",
319    xcontext);
320    } else {
321  1 isAllowed = xcontext.getWiki().getRightService().hasWikiAdminRights(xcontext);
322    }
323  194 break;
324  40 default:
325  40 isAllowed = true;
326    }
327    } catch (XWikiException ex) {
328  0 isAllowed = false;
329    }
330   
331  250 return isAllowed;
332    }
333    }