1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package com.xpn.xwiki.plugin.skinx; |
21 |
|
|
22 |
|
import java.util.ArrayList; |
23 |
|
import java.util.Collections; |
24 |
|
import java.util.HashMap; |
25 |
|
import java.util.HashSet; |
26 |
|
import java.util.List; |
27 |
|
import java.util.Locale; |
28 |
|
import java.util.Map; |
29 |
|
import java.util.Set; |
30 |
|
|
31 |
|
import org.apache.commons.lang3.StringUtils; |
32 |
|
import org.slf4j.Logger; |
33 |
|
import org.slf4j.LoggerFactory; |
34 |
|
import org.xwiki.bridge.event.DocumentCreatedEvent; |
35 |
|
import org.xwiki.bridge.event.DocumentDeletedEvent; |
36 |
|
import org.xwiki.bridge.event.DocumentUpdatedEvent; |
37 |
|
import org.xwiki.bridge.event.WikiDeletedEvent; |
38 |
|
import org.xwiki.model.EntityType; |
39 |
|
import org.xwiki.model.reference.DocumentReference; |
40 |
|
import org.xwiki.model.reference.EntityReferenceResolver; |
41 |
|
import org.xwiki.model.reference.EntityReferenceSerializer; |
42 |
|
import org.xwiki.observation.EventListener; |
43 |
|
import org.xwiki.observation.ObservationManager; |
44 |
|
import org.xwiki.observation.event.Event; |
45 |
|
import org.xwiki.security.authorization.AuthorizationManager; |
46 |
|
import org.xwiki.security.authorization.ContextualAuthorizationManager; |
47 |
|
import org.xwiki.security.authorization.Right; |
48 |
|
|
49 |
|
import com.xpn.xwiki.XWikiContext; |
50 |
|
import com.xpn.xwiki.XWikiException; |
51 |
|
import com.xpn.xwiki.doc.XWikiDocument; |
52 |
|
import com.xpn.xwiki.objects.BaseObject; |
53 |
|
import com.xpn.xwiki.objects.classes.BaseClass; |
54 |
|
import com.xpn.xwiki.web.Utils; |
55 |
|
|
56 |
|
|
57 |
|
|
58 |
|
|
59 |
|
|
60 |
|
|
61 |
|
@version |
62 |
|
@since |
63 |
|
@see |
64 |
|
@see |
65 |
|
|
|
|
| 81% |
Uncovered Elements: 26 (137) |
Complexity: 37 |
Complexity Density: 0.41 |
|
66 |
|
public abstract class AbstractDocumentSkinExtensionPlugin extends AbstractSkinExtensionPlugin implements EventListener |
67 |
|
{ |
68 |
|
|
69 |
|
|
70 |
|
|
71 |
|
protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractDocumentSkinExtensionPlugin.class); |
72 |
|
|
73 |
|
|
74 |
|
|
75 |
|
|
76 |
|
private static final String USE_FIELDNAME = "use"; |
77 |
|
|
78 |
|
|
79 |
|
|
80 |
|
|
81 |
|
private Map<String, Set<DocumentReference>> alwaysUsedExtensions; |
82 |
|
|
83 |
|
|
84 |
|
|
85 |
|
|
86 |
|
private final List<Event> events = new ArrayList<Event>(3); |
87 |
|
|
88 |
|
|
89 |
|
|
90 |
|
|
91 |
|
@param |
92 |
|
@param |
93 |
|
@param |
94 |
|
@see |
95 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (5) |
Complexity: 1 |
Complexity Density: 0.2 |
|
96 |
64 |
public AbstractDocumentSkinExtensionPlugin(String name, String className, XWikiContext context)... |
97 |
|
{ |
98 |
64 |
super(name, className, context); |
99 |
|
|
100 |
64 |
this.events.add(new DocumentCreatedEvent()); |
101 |
64 |
this.events.add(new DocumentDeletedEvent()); |
102 |
64 |
this.events.add(new DocumentUpdatedEvent()); |
103 |
|
|
104 |
64 |
this.events.add(new WikiDeletedEvent()); |
105 |
|
} |
106 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
107 |
64 |
@Override... |
108 |
|
public List<Event> getEvents() |
109 |
|
{ |
110 |
64 |
return this.events; |
111 |
|
} |
112 |
|
|
113 |
|
|
114 |
|
|
115 |
|
|
116 |
|
@return |
117 |
|
|
118 |
|
protected abstract String getExtensionClassName(); |
119 |
|
|
120 |
|
|
121 |
|
|
122 |
|
|
123 |
|
@return |
124 |
|
|
125 |
|
protected abstract String getExtensionName(); |
126 |
|
|
127 |
|
|
128 |
|
@inheritDoc |
129 |
|
|
130 |
|
|
131 |
|
|
132 |
|
|
133 |
|
|
134 |
|
@see |
135 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 1 |
Complexity Density: 0.25 |
|
136 |
64 |
@Override... |
137 |
|
public void init(XWikiContext context) |
138 |
|
{ |
139 |
64 |
super.init(context); |
140 |
|
|
141 |
64 |
this.alwaysUsedExtensions = new HashMap<String, Set<DocumentReference>>(); |
142 |
64 |
getExtensionClass(context); |
143 |
|
|
144 |
64 |
Utils.getComponent(ObservationManager.class).addListener(this); |
145 |
|
} |
146 |
|
|
147 |
|
|
148 |
|
@inheritDoc |
149 |
|
|
150 |
|
|
151 |
|
|
152 |
|
|
153 |
|
@see |
154 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
155 |
8 |
@Override... |
156 |
|
public void virtualInit(XWikiContext context) |
157 |
|
{ |
158 |
8 |
super.virtualInit(context); |
159 |
|
|
160 |
8 |
getExtensionClass(context); |
161 |
|
} |
162 |
|
|
163 |
|
|
164 |
|
@inheritDoc |
165 |
|
|
166 |
|
|
167 |
|
|
168 |
|
|
169 |
|
|
170 |
|
|
171 |
|
|
172 |
|
@see |
173 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 1 |
Complexity Density: 0.17 |
|
174 |
13785 |
@Override... |
175 |
|
public Set<String> getAlwaysUsedExtensions(XWikiContext context) |
176 |
|
{ |
177 |
13779 |
EntityReferenceSerializer<String> serializer = Utils.getComponent(EntityReferenceSerializer.TYPE_STRING); |
178 |
13785 |
Set<DocumentReference> references = getAlwaysUsedExtensions(); |
179 |
13778 |
Set<String> names = new HashSet<String>(references.size()); |
180 |
13783 |
for (DocumentReference reference : references) { |
181 |
15314 |
names.add(serializer.serialize(reference)); |
182 |
|
} |
183 |
13778 |
return names; |
184 |
|
} |
185 |
|
|
186 |
|
|
187 |
|
|
188 |
|
|
189 |
|
|
190 |
|
|
191 |
|
|
192 |
|
|
193 |
|
|
194 |
|
@return |
195 |
|
|
|
|
| 81% |
Uncovered Elements: 4 (21) |
Complexity: 5 |
Complexity Density: 0.29 |
|
196 |
13793 |
public Set<DocumentReference> getAlwaysUsedExtensions()... |
197 |
|
{ |
198 |
13793 |
XWikiContext context = Utils.getContext(); |
199 |
|
|
200 |
13798 |
String currentWiki = StringUtils.defaultIfEmpty(context.getWikiId(), context.getMainXWiki()); |
201 |
|
|
202 |
13798 |
if (this.alwaysUsedExtensions.get(currentWiki) != null) { |
203 |
13712 |
return this.alwaysUsedExtensions.get(currentWiki); |
204 |
|
} else { |
205 |
|
|
206 |
76 |
Set<DocumentReference> extensions = new HashSet<DocumentReference>(); |
207 |
76 |
String query = |
208 |
|
", BaseObject as obj, StringProperty as use where obj.className='" + getExtensionClassName() + "'" |
209 |
|
+ " and obj.name=doc.fullName and use.id.id=obj.id and use.id.name='use' and use.value='always'"; |
210 |
76 |
try { |
211 |
76 |
for (DocumentReference extension : context.getWiki().getStore() |
212 |
|
.searchDocumentReferences(query, context)) { |
213 |
10 |
try { |
214 |
10 |
XWikiDocument doc = context.getWiki().getDocument(extension, context); |
215 |
|
|
216 |
|
|
217 |
10 |
if (Utils.getComponent(AuthorizationManager.class).hasAccess(Right.PROGRAM, |
218 |
|
doc.getContentAuthorReference(), doc.getDocumentReference())) { |
219 |
10 |
extensions.add(extension); |
220 |
|
} |
221 |
|
} catch (XWikiException e1) { |
222 |
0 |
LOGGER.error("Error while adding skin extension [{}] as always used. It will be ignored.", |
223 |
|
extension, e1); |
224 |
|
} |
225 |
|
} |
226 |
76 |
this.alwaysUsedExtensions.put(currentWiki, extensions); |
227 |
76 |
return extensions; |
228 |
|
} catch (XWikiException e) { |
229 |
0 |
LOGGER.error("Error while retrieving always used JS extensions", e); |
230 |
0 |
return Collections.emptySet(); |
231 |
|
} |
232 |
|
} |
233 |
|
} |
234 |
|
|
|
|
| 86.7% |
Uncovered Elements: 2 (15) |
Complexity: 4 |
Complexity Density: 0.44 |
|
235 |
13783 |
@Override... |
236 |
|
public boolean hasPageExtensions(XWikiContext context) |
237 |
|
{ |
238 |
13780 |
XWikiDocument doc = context.getDoc(); |
239 |
13783 |
List<BaseObject> objects = doc.getObjects(getExtensionClassName()); |
240 |
13781 |
if (objects != null) { |
241 |
124 |
for (BaseObject obj : objects) { |
242 |
124 |
if (obj == null) { |
243 |
0 |
continue; |
244 |
|
} |
245 |
124 |
if (obj.getStringValue(USE_FIELDNAME).equals("currentPage")) { |
246 |
56 |
return true; |
247 |
|
} |
248 |
|
} |
249 |
|
} |
250 |
13729 |
return false; |
251 |
|
} |
252 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 1 |
Complexity Density: 0.25 |
|
253 |
3856 |
@Override... |
254 |
|
public void use(String resource, XWikiContext context) |
255 |
|
{ |
256 |
3856 |
String canonicalResource = getCanonicalDocumentName(resource); |
257 |
3856 |
LOGGER.debug("Using [{}] as [{}] extension", canonicalResource, this.getName()); |
258 |
3856 |
getPulledResources(context).add(canonicalResource); |
259 |
|
|
260 |
|
|
261 |
3856 |
getParametersMap(context).remove(canonicalResource); |
262 |
|
} |
263 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
264 |
172 |
@Override... |
265 |
|
public void use(String resource, Map<String, Object> parameters, XWikiContext context) |
266 |
|
{ |
267 |
172 |
String canonicalResource = getCanonicalDocumentName(resource); |
268 |
172 |
getPulledResources(context).add(canonicalResource); |
269 |
172 |
getParametersMap(context).put(canonicalResource, parameters); |
270 |
|
} |
271 |
|
|
272 |
|
|
273 |
|
@inheritDoc |
274 |
|
|
275 |
|
|
276 |
|
|
277 |
|
|
278 |
|
|
279 |
|
@see |
280 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
281 |
13784 |
@Override... |
282 |
|
public String endParsing(String content, XWikiContext context) |
283 |
|
{ |
284 |
13785 |
return super.endParsing(content, context); |
285 |
|
} |
286 |
|
|
287 |
|
|
288 |
|
@link |
289 |
|
@link |
290 |
|
|
291 |
|
@param |
292 |
|
@return |
293 |
|
|
|
|
| 60% |
Uncovered Elements: 2 (5) |
Complexity: 2 |
Complexity Density: 0.4 |
|
294 |
72 |
public BaseClass getExtensionClass(XWikiContext context)... |
295 |
|
{ |
296 |
72 |
try { |
297 |
72 |
XWikiDocument doc = context.getWiki().getDocument(getExtensionClassName(), context); |
298 |
|
|
299 |
72 |
return doc.getXClass(); |
300 |
|
} catch (Exception ex) { |
301 |
0 |
LOGGER.error("Cannot get skin extension class [{}]", getExtensionClassName(), ex); |
302 |
|
} |
303 |
|
|
304 |
0 |
return null; |
305 |
|
} |
306 |
|
|
307 |
|
|
308 |
|
@inheritDoc |
309 |
|
|
310 |
|
@link |
311 |
|
|
312 |
|
@see |
313 |
|
|
314 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (5) |
Complexity: 2 |
Complexity Density: 0.67 |
|
315 |
2116 |
@Override... |
316 |
|
public void onEvent(Event event, Object source, Object data) |
317 |
|
{ |
318 |
2116 |
if (event instanceof WikiDeletedEvent) { |
319 |
6 |
this.alwaysUsedExtensions.remove(((WikiDeletedEvent) event).getWikiId()); |
320 |
|
} else { |
321 |
2110 |
onDocumentEvent((XWikiDocument) source, (XWikiContext) data); |
322 |
|
} |
323 |
|
} |
324 |
|
|
325 |
|
|
326 |
|
|
327 |
|
|
328 |
|
@param |
329 |
|
@param |
330 |
|
|
|
|
| 59.1% |
Uncovered Elements: 9 (22) |
Complexity: 6 |
Complexity Density: 0.5 |
|
331 |
2110 |
private void onDocumentEvent(XWikiDocument document, XWikiContext context)... |
332 |
|
{ |
333 |
2110 |
boolean remove = false; |
334 |
2110 |
if (document.getObject(getExtensionClassName()) != null) { |
335 |
|
|
336 |
12 |
if (document.getObject(getExtensionClassName(), USE_FIELDNAME, "always", false) != null) { |
337 |
0 |
if (Utils.getComponent(AuthorizationManager.class).hasAccess(Right.PROGRAM, |
338 |
|
document.getContentAuthorReference(), document.getDocumentReference())) { |
339 |
0 |
getAlwaysUsedExtensions().add(document.getDocumentReference()); |
340 |
|
|
341 |
0 |
return; |
342 |
|
} else { |
343 |
|
|
344 |
0 |
remove = true; |
345 |
|
} |
346 |
|
} else { |
347 |
|
|
348 |
12 |
remove = true; |
349 |
|
} |
350 |
2098 |
} else if (document.getOriginalDocument().getObject(getExtensionClassName()) != null) { |
351 |
|
|
352 |
0 |
remove = true; |
353 |
|
} |
354 |
|
|
355 |
2110 |
if (remove) { |
356 |
12 |
getAlwaysUsedExtensions().remove(document.getDocumentReference()); |
357 |
|
} |
358 |
|
} |
359 |
|
|
360 |
|
|
361 |
|
|
362 |
|
|
363 |
|
@param |
364 |
|
@return |
365 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
366 |
4028 |
private String getCanonicalDocumentName(String documentName)... |
367 |
|
{ |
368 |
4028 |
@SuppressWarnings("unchecked") |
369 |
|
EntityReferenceResolver<String> resolver = Utils.getComponent(EntityReferenceResolver.TYPE_STRING, "current"); |
370 |
4028 |
@SuppressWarnings("unchecked") |
371 |
|
EntityReferenceSerializer<String> serializer = Utils.getComponent(EntityReferenceSerializer.TYPE_STRING); |
372 |
4028 |
return serializer.serialize(resolver.resolve(documentName, EntityType.DOCUMENT)); |
373 |
|
} |
374 |
|
|
375 |
|
|
376 |
|
@param |
377 |
|
@param |
378 |
|
@return |
379 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
380 |
0 |
protected boolean isAccessible(String documentName, XWikiContext context)... |
381 |
|
{ |
382 |
0 |
return isAccessible(getCurrentDocumentReferenceResolver().resolve(documentName), context); |
383 |
|
} |
384 |
|
|
385 |
|
|
386 |
|
@param |
387 |
|
@param |
388 |
|
@return |
389 |
|
@since |
390 |
|
|
|
|
| 50% |
Uncovered Elements: 3 (6) |
Complexity: 2 |
Complexity Density: 0.5 |
|
391 |
17295 |
protected boolean isAccessible(DocumentReference documentReference, XWikiContext context)... |
392 |
|
{ |
393 |
17295 |
if (!Utils.getComponent(ContextualAuthorizationManager.class).hasAccess(Right.VIEW, documentReference)) { |
394 |
0 |
LOGGER.debug("[{}] The current user [{}] does not have 'view' rights on the Skin Extension document [{}]", |
395 |
|
getName(), context.getUserReference(), documentReference); |
396 |
|
|
397 |
0 |
return false; |
398 |
|
} |
399 |
|
|
400 |
17295 |
return true; |
401 |
|
} |
402 |
|
|
403 |
|
|
404 |
|
@param |
405 |
|
@param |
406 |
|
@return |
407 |
|
|
|
|
| 50% |
Uncovered Elements: 2 (4) |
Complexity: 2 |
Complexity Density: 0.5 |
|
408 |
17295 |
private String getDocumentVersion(DocumentReference documentReference, XWikiContext context)... |
409 |
|
{ |
410 |
17295 |
try { |
411 |
17295 |
return context.getWiki().getDocument(documentReference, context).getVersion(); |
412 |
|
} catch (XWikiException e) { |
413 |
0 |
LOGGER.error("Failed to load document [{}].", documentReference, e); |
414 |
|
} |
415 |
0 |
return ""; |
416 |
|
} |
417 |
|
|
418 |
|
|
419 |
|
|
420 |
|
|
421 |
|
|
422 |
|
@param |
423 |
|
@param |
424 |
|
@return |
425 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
426 |
17295 |
private String getDocumentVersionQueryString(DocumentReference documentReference, XWikiContext context)... |
427 |
|
{ |
428 |
17295 |
return "docVersion=" + sanitize(getDocumentVersion(documentReference, context)); |
429 |
|
} |
430 |
|
|
431 |
|
|
432 |
|
|
433 |
|
|
434 |
|
@param |
435 |
|
@return |
436 |
|
|
|
|
| 66.7% |
Uncovered Elements: 2 (6) |
Complexity: 2 |
Complexity Density: 0.5 |
|
437 |
17295 |
private String getLanguageQueryString(XWikiContext context)... |
438 |
|
{ |
439 |
17295 |
Locale locale = context.getLocale(); |
440 |
17295 |
if (locale != null) { |
441 |
17295 |
return "language=" + sanitize(locale.toString()); |
442 |
|
} |
443 |
0 |
return ""; |
444 |
|
} |
445 |
|
|
446 |
|
|
447 |
|
|
448 |
|
|
449 |
|
@param |
450 |
|
@param |
451 |
|
@param |
452 |
|
@param |
453 |
|
@return |
454 |
|
|
455 |
|
@since |
456 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
457 |
17295 |
protected String getDocumentSkinExtensionURL(DocumentReference documentReference, String documentName,... |
458 |
|
String pluginName, XWikiContext context) |
459 |
|
{ |
460 |
17295 |
String queryString = String.format("%s&%s%s", |
461 |
|
getLanguageQueryString(context), |
462 |
|
getDocumentVersionQueryString(documentReference, context), |
463 |
|
parametersAsQueryString(documentName, context)); |
464 |
|
|
465 |
17295 |
return context.getWiki().getURL(documentReference, pluginName, queryString, "", context); |
466 |
|
} |
467 |
|
|
468 |
|
|
469 |
|
} |