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

File WikiUIExtensionComponentBuilder.java

 

Coverage histogram

../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

8
42
4
1
213
122
12
0.29
10.5
4
3

Classes

Class Line # Actions
WikiUIExtensionComponentBuilder 57 42 0% 12 2
0.96296396.3%
 

Contributing tests

This file is covered by 4 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.uiextension.internal;
21   
22    import java.util.ArrayList;
23    import java.util.List;
24   
25    import javax.inject.Inject;
26    import javax.inject.Named;
27    import javax.inject.Provider;
28    import javax.inject.Singleton;
29   
30    import org.slf4j.Logger;
31    import org.xwiki.component.annotation.Component;
32    import org.xwiki.component.manager.ComponentManager;
33    import org.xwiki.component.wiki.WikiComponent;
34    import org.xwiki.component.wiki.WikiComponentBuilder;
35    import org.xwiki.component.wiki.WikiComponentException;
36    import org.xwiki.component.wiki.WikiComponentScope;
37    import org.xwiki.model.reference.DocumentReference;
38    import org.xwiki.model.reference.EntityReferenceSerializer;
39    import org.xwiki.security.authorization.AuthorExecutor;
40    import org.xwiki.security.authorization.AuthorizationManager;
41    import org.xwiki.security.authorization.Right;
42   
43    import com.xpn.xwiki.XWikiContext;
44    import com.xpn.xwiki.XWikiException;
45    import com.xpn.xwiki.doc.XWikiDocument;
46    import com.xpn.xwiki.objects.BaseObject;
47   
48    /**
49    * Provides {@link org.xwiki.uiextension.UIExtension} components from definitions stored in XObjects.
50    *
51    * @version $Id: c7d1de5218d2210c8bde253f34d5942651730dc2 $
52    * @since 4.2M3
53    */
54    @Component
55    @Singleton
56    @Named("uiextension")
 
57    public class WikiUIExtensionComponentBuilder implements WikiComponentBuilder, WikiUIExtensionConstants
58    {
59    /**
60    * The logger to log.
61    */
62    @Inject
63    private Logger logger;
64   
65    /**
66    * Used to transform the reference to the UI Extension XClass to a string usable in a query. {@see
67    * #searchDocumentReferences()}
68    */
69    @Inject
70    @Named("compactwiki")
71    private EntityReferenceSerializer<String> compactWikiSerializer;
72   
73    /**
74    * Used to generate a role hint for UI extensions based on their object reference.
75    */
76    @Inject
77    private EntityReferenceSerializer<String> serializer;
78   
79    /**
80    * Used to get the parser to transform the extension content to a XDOM.
81    */
82    @Inject
83    @Named("wiki")
84    private ComponentManager cm;
85   
86    @Inject
87    private Provider<XWikiContext> xcontextProvider;
88   
89    @Inject
90    private AuthorizationManager authorization;
91   
92    @Inject
93    private AuthorExecutor authorExecutor;
94   
95    /**
96    * Checks if the last author of the document holding the extension(s) has the rights required to register extensions
97    * for the given scope. If the document author doesn't have the required rights a {@link WikiComponentException} is
98    * thrown.
99    *
100    * @param extensionsDoc the document holding the extension(s)
101    * @param scope the scope to check the rights for
102    * @throws WikiComponentException if the document author doesn't have the required rights to register extensions
103    */
 
104  130 toggle private void checkRights(XWikiDocument extensionsDoc, WikiComponentScope scope) throws WikiComponentException
105    {
106  130 if (scope == WikiComponentScope.GLOBAL
107    && !this.authorization.hasAccess(Right.PROGRAM, extensionsDoc.getContentAuthorReference(), null)) {
108  1 throw new WikiComponentException("Registering global UI extensions requires programming rights");
109  129 } else if (scope == WikiComponentScope.WIKI
110    && !this.authorization.hasAccess(Right.ADMIN, extensionsDoc.getContentAuthorReference(), extensionsDoc
111    .getDocumentReference().getWikiReference())) {
112  1 throw new WikiComponentException(
113    "Registering UI extensions at wiki level requires wiki administration rights");
114    }
115    }
116   
117    /**
118    * Retrieve the list of {@link BaseObject} defining UI extensions.
119    *
120    * @param extensionsDoc the document to retrieve the definitions from
121    * @return the list of {@link BaseObject} defining UI extensions in the given document
122    * @throws WikiComponentException if no extension definition can be found in the document
123    */
 
124  130 toggle private List<BaseObject> getExtensionDefinitions(XWikiDocument extensionsDoc) throws WikiComponentException
125    {
126    // Check whether this document contains a listener definition.
127  130 List<BaseObject> extensionDefinitions = extensionsDoc.getXObjects(UI_EXTENSION_CLASS);
128   
129  130 if (extensionDefinitions.size() == 0) {
130  1 throw new WikiComponentException(String.format("No UI extension object could be found in document [%s]",
131    extensionsDoc.getDocumentReference()));
132    }
133   
134  129 return extensionDefinitions;
135    }
136   
 
137  130 toggle @Override
138    public List<WikiComponent> buildComponents(DocumentReference reference) throws WikiComponentException
139    {
140  130 List<WikiComponent> extensions = new ArrayList<WikiComponent>();
141  130 XWikiDocument doc = null;
142   
143  130 try {
144  130 XWikiContext xcontext = xcontextProvider.get();
145  130 doc = xcontext.getWiki().getDocument(reference, xcontext);
146    } catch (XWikiException e) {
147  0 throw new WikiComponentException(
148    String.format("Failed to create UI Extension(s) document [%s]", reference), e);
149    }
150   
151  130 for (BaseObject extensionDefinition : this.getExtensionDefinitions(doc)) {
152  133 if (extensionDefinition == null) {
153  3 continue;
154    }
155    // Extract extension definition.
156  130 String id = extensionDefinition.getStringValue(ID_PROPERTY);
157  130 String extensionPointId = extensionDefinition.getStringValue(EXTENSION_POINT_ID_PROPERTY);
158  130 String content = extensionDefinition.getStringValue(CONTENT_PROPERTY);
159  130 String rawParameters = extensionDefinition.getStringValue(PARAMETERS_PROPERTY);
160  130 WikiComponentScope scope =
161    WikiComponentScope.fromString(extensionDefinition.getStringValue(SCOPE_PROPERTY));
162   
163    // Before going further we need to check the document author is authorized to register the extension
164  130 this.checkRights(doc, scope);
165   
166  128 String roleHint = this.serializer.serialize(extensionDefinition.getReference());
167   
168  128 WikiUIExtension extension =
169    new WikiUIExtension(roleHint, id, extensionPointId, extensionDefinition.getReference(),
170    doc.getAuthorReference(), this.authorExecutor);
171   
172    // It would be nice to have PER_LOOKUP components for UIX parameters but without constructor injection it's
173    // safer to use a POJO and pass the Component Manager to it.
174  128 WikiUIExtensionParameters parameters = new WikiUIExtensionParameters(id, rawParameters, cm);
175  128 extension.setParameters(parameters);
176    // It would be nice to have PER_LOOKUP components for UIX renderers but without constructor injection it's
177    // safer to use a POJO and pass the Component Manager to it.
178  128 WikiUIExtensionRenderer renderer =
179    new WikiUIExtensionRenderer(roleHint, content, doc.getDocumentReference(), cm);
180  128 extension.setRenderer(renderer);
181  128 extension.setScope(scope);
182  128 extensions.add(extension);
183    }
184   
185  127 return extensions;
186    }
187   
188    /**
189    * @return list of document references to documents containing a UI extension object.
190    */
 
191  3873 toggle @Override
192    public List<DocumentReference> getDocumentReferences()
193    {
194  3873 List<DocumentReference> results = new ArrayList<DocumentReference>();
195    // Note that the query is made to work with Oracle which treats empty strings as null.
196  3873 String query =
197    ", BaseObject as obj, StringProperty as epId where obj.className=? "
198    + "and obj.name=doc.fullName and epId.id.id=obj.id and epId.id.name=? "
199    + "and (epId.value <> '' or (epId.value is not null and '' is null))";
200  3873 List<String> parameters = new ArrayList<String>();
201  3873 parameters.add(this.compactWikiSerializer.serialize(UI_EXTENSION_CLASS));
202  3873 parameters.add(EXTENSION_POINT_ID_PROPERTY);
203   
204  3873 try {
205  3873 XWikiContext xcontext = xcontextProvider.get();
206  3873 results.addAll(xcontext.getWiki().getStore().searchDocumentReferences(query, parameters, xcontext));
207    } catch (XWikiException e) {
208  0 this.logger.warn("Search for UI extensions failed: [{}]", e.getMessage());
209    }
210   
211  3873 return results;
212    }
213    }