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

File DefaultWikiMacroInitializer.java

 

Coverage histogram

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

Code metrics

8
45
9
1
274
141
16
0.36
5
9
1.78

Classes

Class Line # Actions
DefaultWikiMacroInitializer 59 45 0% 16 21
0.6612903566.1%
 

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 org.xwiki.rendering.wikimacro.internal;
21   
22    import java.util.HashSet;
23    import java.util.List;
24    import java.util.Set;
25   
26    import javax.inject.Inject;
27    import javax.inject.Named;
28    import javax.inject.Singleton;
29   
30    import org.slf4j.Logger;
31    import org.xwiki.component.annotation.Component;
32    import org.xwiki.context.Execution;
33    import org.xwiki.model.reference.DocumentReference;
34    import org.xwiki.model.reference.SpaceReference;
35    import org.xwiki.model.reference.SpaceReferenceResolver;
36    import org.xwiki.model.reference.WikiReference;
37    import org.xwiki.query.Query;
38    import org.xwiki.query.QueryManager;
39    import org.xwiki.rendering.macro.wikibridge.InsufficientPrivilegesException;
40    import org.xwiki.rendering.macro.wikibridge.WikiMacro;
41    import org.xwiki.rendering.macro.wikibridge.WikiMacroException;
42    import org.xwiki.rendering.macro.wikibridge.WikiMacroFactory;
43    import org.xwiki.rendering.macro.wikibridge.WikiMacroInitializer;
44    import org.xwiki.rendering.macro.wikibridge.WikiMacroManager;
45   
46    import com.xpn.xwiki.XWikiContext;
47    import com.xpn.xwiki.XWikiException;
48    import com.xpn.xwiki.doc.MandatoryDocumentInitializer;
49    import com.xpn.xwiki.doc.XWikiDocument;
50   
51    /**
52    * A {@link DefaultWikiMacroInitializer} providing wiki macros.
53    *
54    * @version $Id: 0631b7a361c66bdf911a6563384a961c27f601ca $
55    * @since 2.0M2
56    */
57    @Component
58    @Singleton
 
59    public class DefaultWikiMacroInitializer implements WikiMacroInitializer, WikiMacroConstants
60    {
61    /**
62    * The {@link org.xwiki.rendering.macro.wikibridge.WikiMacroFactory} component.
63    */
64    @Inject
65    private WikiMacroFactory wikiMacroFactory;
66   
67    /**
68    * The {@link WikiMacroManager} component.
69    */
70    @Inject
71    private WikiMacroManager wikiMacroManager;
72   
73    /**
74    * The {@link Execution} component used for accessing XWikiContext.
75    */
76    @Inject
77    private Execution execution;
78   
79    @Inject
80    @Named(WIKI_MACRO_CLASS)
81    private MandatoryDocumentInitializer wikiMacroInitializer;
82   
83    @Inject
84    @Named(WIKI_MACRO_PARAMETER_CLASS)
85    private MandatoryDocumentInitializer wikiMacroParameterInitializer;
86   
87    /**
88    * The logger to log.
89    */
90    @Inject
91    private Logger logger;
92   
93    @Inject
94    private SpaceReferenceResolver<String> spaceReferenceResolver;
95   
96    /**
97    * Utility method for accessing XWikiContext.
98    *
99    * @return the XWikiContext.
100    */
 
101  76 toggle private XWikiContext getContext()
102    {
103  76 return (XWikiContext) this.execution.getContext().getProperty("xwikicontext");
104    }
105   
 
106  0 toggle @Override
107    public void registerExistingWikiMacros() throws Exception
108    {
109  0 registerExistingWikiMacros(false, null);
110    }
111   
 
112  38 toggle @Override
113    public void registerExistingWikiMacros(String wiki) throws Exception
114    {
115  38 registerExistingWikiMacros(true, wiki);
116    }
117   
118    /**
119    * Registers the wiki macros for all the wikis or a specific wiki, according to the passed parameter. <br>
120    * FIXME: I don't like this way of passing params, but it's kinda the best I can do for the moment without
121    * duplicating at least the logic inside this function, if not some code as well.
122    *
123    * @param local false if only macros in a specified wiki are to be registered, in which case, the name of the wiki
124    * should be specified in the second parameter, false if the macros in all the wikis should be
125    * registered, in which case the value of the second parameter is ignored
126    * @param wiki the name of the wiki to register macros for, if local is true
127    * @throws Exception if xwiki classes required for defining wiki macros are missing or if an error occurs while
128    * searching for existing wiki macros.
129    */
 
130  38 toggle private void registerExistingWikiMacros(boolean local, String wiki) throws Exception
131    {
132  38 XWikiContext xcontext = getContext();
133   
134    // Register the wiki macros that exist
135  38 String originalWiki = xcontext.getWikiId();
136  38 try {
137  38 if (!local) {
138  0 Set<String> wikiNames = new HashSet<String>();
139    // Add the list of all subwikis
140  0 wikiNames.addAll(xcontext.getWiki().getVirtualWikisDatabaseNames(xcontext));
141   
142  0 for (String wikiName : wikiNames) {
143  0 registerMacrosForWiki(wikiName, xcontext);
144    }
145    } else {
146  38 registerMacrosForWiki(wiki, xcontext);
147    }
148    } finally {
149  38 xcontext.setWikiId(originalWiki);
150    }
151    }
152   
153    /**
154    * Search and register all the macros from the given wiki.
155    *
156    * @param wikiName the name of the wiki to process, lowercase database name
157    * @param xcontext the current request context
158    */
 
159  38 toggle private void registerMacrosForWiki(String wikiName, XWikiContext xcontext)
160    {
161  38 try {
162  38 this.logger.debug("Registering all wiki macros found in wiki [{}]", wikiName);
163   
164    // Set the context to be in that wiki so that both the search for XWikiMacro class objects and the
165    // registration of macros registered for the current wiki will work.
166    // TODO: In the future when we have APIs for it, move the code to set the current wiki and the current user
167    // (see below) to the WikiMacroManager's implementation.
168  38 xcontext.setWikiId(wikiName);
169   
170    // Make sure classes exists and are up to date in this wiki
171  38 installOrUpgradeWikiMacroClasses();
172   
173    // Search for all those documents with macro definitions and for each register the macro
174  38 for (Object[] wikiMacroDocumentData : getWikiMacroDocumentData(xcontext)) {
175    // In the database the space and page names are always specified for a document. However the wiki
176    // part isn't, so we need to replace the wiki reference with the current wiki.
177    // Note that the space part can contain one or more spaces since XWiki 7.2 and the introduction of
178    // Nested Spaces.
179  211 SpaceReference spaceReference =
180    this.spaceReferenceResolver.resolve((String) wikiMacroDocumentData[0], new WikiReference(wikiName));
181  211 DocumentReference wikiMacroDocumentReference =
182    new DocumentReference((String) wikiMacroDocumentData[1], spaceReference);
183   
184  211 registerMacro(wikiMacroDocumentReference, (String) wikiMacroDocumentData[2], xcontext);
185    }
186    } catch (Exception ex) {
187  0 this.logger.warn("Failed to register macros for wiki [{}]: {}", wikiName, ex.getMessage());
188    }
189    }
190   
191    /**
192    * Search for all wiki macros in the current wiki.
193    *
194    * @param xcontext the current request context
195    * @return a list of documents containing wiki macros, each item as a List of 3 strings: space name, document name,
196    * last author of the document
197    * @throws Exception if the database search fails
198    */
 
199  38 toggle private List<Object[]> getWikiMacroDocumentData(XWikiContext xcontext) throws Exception
200    {
201  38 final QueryManager qm = xcontext.getWiki().getStore().getQueryManager();
202  38 final Query q = qm.getNamedQuery("getWikiMacroDocuments");
203  38 return (List<Object[]>) (List) q.execute();
204    }
205   
206    /**
207    * Register a wiki macro in the component manager, if the macro author has the required rights.
208    *
209    * @param wikiMacroDocumentReference the document holding the macro definition
210    * @param wikiMacroDocumentAuthor the author of the macro document
211    * @param xcontext the current request context
212    */
 
213  211 toggle private void registerMacro(DocumentReference wikiMacroDocumentReference, String wikiMacroDocumentAuthor,
214    XWikiContext xcontext)
215    {
216  211 this.logger.debug("Registering macro in document [{}]...", wikiMacroDocumentReference);
217   
218  211 DocumentReference originalAuthor = xcontext.getUserReference();
219  211 try {
220  211 WikiMacro macro = this.wikiMacroFactory.createWikiMacro(wikiMacroDocumentReference);
221   
222  211 this.wikiMacroManager.registerWikiMacro(wikiMacroDocumentReference, macro);
223   
224  211 this.logger.debug("Macro [{}] from document [{}] is now registered.",
225    macro.getDescriptor().getId().getId(), wikiMacroDocumentReference);
226    } catch (InsufficientPrivilegesException ex) {
227    // Just log the exception and skip to the next.
228    // We only log at the debug level here as this is not really an error
229  0 this.logger.debug(ex.getMessage(), ex);
230    } catch (WikiMacroException ex) {
231    // Just log the exception and skip to the next.
232  0 this.logger.error(ex.getMessage(), ex);
233    } finally {
234  211 xcontext.setUserReference(originalAuthor);
235    }
236    }
237   
 
238  38 toggle @Override
239    public void installOrUpgradeWikiMacroClasses() throws Exception
240    {
241  38 XWikiContext xcontext = getContext();
242   
243    // Install or Upgrade XWiki.WikiMacroClass
244  38 XWikiDocument doc = xcontext.getWiki().getDocument(this.wikiMacroInitializer.getDocumentReference(), xcontext);
245   
246  38 if (this.wikiMacroInitializer.updateDocument(doc)) {
247  0 update(doc);
248    }
249   
250    // Install or Upgrade XWiki.WikiMacroParameterClass
251  38 doc = xcontext.getWiki().getDocument(WIKI_MACRO_PARAMETER_CLASS, xcontext);
252   
253  38 if (this.wikiMacroParameterInitializer.updateDocument(doc)) {
254  0 update(doc);
255    }
256    }
257   
258    /**
259    * Utility method for updating a wiki macro class definition document.
260    *
261    * @param doc xwiki document containing the wiki macro class.
262    * @throws XWikiException if an error occurs while saving the document.
263    */
 
264  0 toggle private void update(XWikiDocument doc) throws Exception
265    {
266  0 XWikiContext xcontext = getContext();
267   
268  0 if (doc.isNew()) {
269  0 doc.setParent("XWiki.WebHome");
270    }
271   
272  0 xcontext.getWiki().saveDocument(doc, xcontext);
273    }
274    }