1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package com.xpn.xwiki.api

File XWiki.java

 

Coverage histogram

../../../../img/srcFileCovDistChart5.png
76% of files have more coverage

Code metrics

136
424
188
1
3,040
1,220
293
0.69
2.26
188
1.56

Classes

Class Line # Actions
XWiki 66 424 0% 293 413
0.4478609644.8%
 

Contributing tests

This file is covered by 30 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 com.xpn.xwiki.api;
21   
22    import java.io.IOException;
23    import java.lang.reflect.Type;
24    import java.util.ArrayList;
25    import java.util.Collections;
26    import java.util.Date;
27    import java.util.List;
28    import java.util.Locale;
29   
30    import org.apache.commons.lang3.StringUtils;
31    import org.apache.commons.lang3.exception.ExceptionUtils;
32    import org.apache.commons.lang3.math.NumberUtils;
33    import org.slf4j.Logger;
34    import org.slf4j.LoggerFactory;
35    import org.xwiki.component.manager.ComponentLookupException;
36    import org.xwiki.job.Job;
37    import org.xwiki.job.event.status.JobStatus;
38    import org.xwiki.job.event.status.JobStatus.State;
39    import org.xwiki.model.EntityType;
40    import org.xwiki.model.reference.DocumentReference;
41    import org.xwiki.model.reference.DocumentReferenceResolver;
42    import org.xwiki.model.reference.EntityReference;
43    import org.xwiki.model.reference.EntityReferenceSerializer;
44    import org.xwiki.model.reference.SpaceReference;
45    import org.xwiki.model.reference.WikiReference;
46    import org.xwiki.rendering.renderer.PrintRendererFactory;
47    import org.xwiki.rendering.syntax.Syntax;
48    import org.xwiki.security.authorization.ContextualAuthorizationManager;
49    import org.xwiki.security.authorization.Right;
50    import org.xwiki.stability.Unstable;
51   
52    import com.xpn.xwiki.XWikiContext;
53    import com.xpn.xwiki.XWikiException;
54    import com.xpn.xwiki.doc.DocumentRevisionProvider;
55    import com.xpn.xwiki.doc.XWikiDeletedDocument;
56    import com.xpn.xwiki.doc.XWikiDocument;
57    import com.xpn.xwiki.internal.XWikiInitializerJob;
58    import com.xpn.xwiki.internal.XWikiInitializerJobStatus;
59    import com.xpn.xwiki.objects.meta.MetaClass;
60    import com.xpn.xwiki.user.api.XWikiUser;
61    import com.xpn.xwiki.util.Programming;
62    import com.xpn.xwiki.web.Utils;
63    import com.xpn.xwiki.web.XWikiEngineContext;
64    import com.xpn.xwiki.web.XWikiURLFactory;
65   
 
66    public class XWiki extends Api
67    {
68    /** Logging helper object. */
69    protected static final Logger LOGGER = LoggerFactory.getLogger(XWiki.class);
70   
71    /** The internal object wrapped by this API. */
72    private com.xpn.xwiki.XWiki xwiki;
73   
74    /**
75    * @see #getStatsService()
76    */
77    private StatsService statsService;
78   
79    /**
80    * @see #getCriteriaService()
81    */
82    private CriteriaService criteriaService;
83   
84    /**
85    * @see com.xpn.xwiki.internal.model.reference.CurrentMixedStringDocumentReferenceResolver
86    */
87    private DocumentReferenceResolver<String> currentMixedDocumentReferenceResolver;
88   
89    /**
90    * @see org.xwiki.model.internal.reference.DefaultStringDocumentReferenceResolver
91    */
92    private DocumentReferenceResolver<String> defaultDocumentReferenceResolver;
93   
94    /**
95    * The object used to serialize entity references into strings. We need it because we have script APIs that work
96    * with entity references but have to call older, often internal, methods that still use string references.
97    */
98    private EntityReferenceSerializer<String> defaultStringEntityReferenceSerializer;
99   
100    private DocumentReferenceResolver<EntityReference> currentgetdocumentResolver;
101   
102    private DocumentRevisionProvider documentRevisionProvider;
103   
104    private ContextualAuthorizationManager contextualAuthorizationManager;
105   
106    /**
107    * XWiki API Constructor
108    *
109    * @param xwiki XWiki Main Object to wrap
110    * @param context XWikiContext to wrap
111    */
 
112  170727 toggle public XWiki(com.xpn.xwiki.XWiki xwiki, XWikiContext context)
113    {
114  170615 super(context);
115   
116  170839 this.xwiki = xwiki;
117  171289 this.statsService = new StatsService(context);
118  171110 this.criteriaService = new CriteriaService(context);
119    }
120   
 
121  333008 toggle private DocumentReferenceResolver<String> getCurrentMixedDocumentReferenceResolver()
122    {
123  333319 if (this.currentMixedDocumentReferenceResolver == null) {
124  54458 this.currentMixedDocumentReferenceResolver =
125    Utils.getComponent(DocumentReferenceResolver.TYPE_STRING, "currentmixed");
126    }
127   
128  333256 return this.currentMixedDocumentReferenceResolver;
129    }
130   
 
131  0 toggle private DocumentReferenceResolver<EntityReference> getCurrentgetdocumentResolver()
132    {
133  0 if (this.currentgetdocumentResolver == null) {
134  0 this.currentgetdocumentResolver =
135    Utils.getComponent(DocumentReferenceResolver.TYPE_REFERENCE, "currentgetdocument");
136    }
137   
138  0 return this.currentgetdocumentResolver;
139    }
140   
 
141  0 toggle private DocumentReferenceResolver<String> getDefaultDocumentReferenceResolver()
142    {
143  0 if (this.defaultDocumentReferenceResolver == null) {
144  0 this.defaultDocumentReferenceResolver = Utils.getComponent(DocumentReferenceResolver.TYPE_STRING);
145    }
146   
147  0 return this.defaultDocumentReferenceResolver;
148    }
149   
 
150  6 toggle private EntityReferenceSerializer<String> getDefaultStringEntityReferenceSerializer()
151    {
152  6 if (this.defaultStringEntityReferenceSerializer == null) {
153  3 this.defaultStringEntityReferenceSerializer = Utils.getComponent(EntityReferenceSerializer.TYPE_STRING);
154    }
155   
156  6 return this.defaultStringEntityReferenceSerializer;
157    }
158   
 
159  15 toggle private DocumentRevisionProvider getDocumentRevisionProvider()
160    {
161  15 if (this.documentRevisionProvider == null) {
162  11 this.documentRevisionProvider = Utils.getComponent(DocumentRevisionProvider.class);
163    }
164   
165  15 return this.documentRevisionProvider;
166    }
167   
 
168  22 toggle private ContextualAuthorizationManager getContextualAuthorizationManager()
169    {
170  22 if (this.contextualAuthorizationManager == null) {
171  16 this.contextualAuthorizationManager = Utils.getComponent(ContextualAuthorizationManager.class);
172    }
173   
174  22 return this.contextualAuthorizationManager;
175    }
176   
177    /**
178    * Privileged API allowing to access the underlying main XWiki Object
179    *
180    * @return Privileged Main XWiki Object
181    */
 
182  14 toggle @Programming
183    public com.xpn.xwiki.XWiki getXWiki()
184    {
185  14 if (hasProgrammingRights()) {
186  14 return this.xwiki;
187    }
188   
189  0 return null;
190    }
191   
192    /**
193    * @return the status of the job initializing {@link com.xpn.xwiki.XWiki} instance
194    * @since 6.1M1
195    */
 
196  0 toggle public XWikiInitializerJobStatus getJobStatus()
197    {
198  0 XWikiInitializerJob job = Utils.getComponent((Type) Job.class, XWikiInitializerJob.JOBTYPE);
199   
200  0 return job != null ? job.getStatus() : null;
201    }
202   
203    /**
204    * @return the status of the job initializing the instance or the current wiki
205    * @since 8.4RC1
206    */
 
207  0 toggle public JobStatus getCurrentInitializerJobStatus()
208    {
209    // Get XWiki initializer job
210  0 JobStatus jobStatus = getJobStatus();
211   
212  0 if (jobStatus == null) {
213  0 return null;
214    }
215   
216    // The XWiki initialization is not done yet
217  0 if (jobStatus.getState() != State.FINISHED) {
218  0 return jobStatus;
219    }
220   
221    // If XWiki initialization did not failed
222  0 if (this.xwiki != null) {
223    // Get current wiki initializer job
224  0 Job wikiJob = this.xwiki.getWikiInitializerJob(this.context.getWikiId());
225   
226  0 jobStatus = wikiJob != null ? wikiJob.getStatus() : null;
227    }
228   
229  0 return jobStatus;
230    }
231   
232    /**
233    * @return XWiki's version in the format <code>(version).(SVN build number)</code>, or "Unknown version" if it
234    * failed to be retrieved
235    */
 
236  12858 toggle public String getVersion()
237    {
238  12858 return this.xwiki.getVersion();
239    }
240   
241    /**
242    * API Allowing to access the current request URL being requested.
243    *
244    * @return the URL
245    * @throws XWikiException failed to create the URL
246    */
 
247  87 toggle public String getRequestURL() throws XWikiException
248    {
249  87 return getXWikiContext().getURLFactory().getRequestURL(getXWikiContext()).toString();
250    }
251   
252    /**
253    * API Allowing to access the current request URL being requested as a relative URL.
254    *
255    * @return the URL
256    * @throws XWikiException failed to create the URL
257    * @since 4.0M1
258    */
 
259  69489 toggle public String getRelativeRequestURL() throws XWikiException
260    {
261  69491 XWikiURLFactory urlFactory = getXWikiContext().getURLFactory();
262   
263  69495 return urlFactory.getURL(urlFactory.getRequestURL(getXWikiContext()), getXWikiContext());
264    }
265   
266    /**
267    * Loads an Document from the database. Rights are checked before sending back the document.
268    * <p>
269    * This is a helper for document reference but you can use {@link #getEntityDocument(String, EntityType)} for any
270    * other kind of reference.
271    *
272    * @param documentReference the reference of the document to be loaded
273    * @return a Document object (if the document couldn't be found a new one is created in memory - but not saved, you
274    * can check whether it's a new document or not by using {@link com.xpn.xwiki.api.Document#isNew()}
275    * @throws XWikiException
276    * @see #getEntityDocument(String, EntityType)
277    */
 
278  331686 toggle public Document getDocument(String documentReference) throws XWikiException
279    {
280  331843 DocumentReference reference;
281   
282    // We ignore the passed full name if it's null to be backward compatible with previous behaviors.
283  331945 if (documentReference != null) {
284    // Note: We use the CurrentMixed Resolver since we want to use the default page name if the page isn't
285    // specified in the passed string, rather than use the current document's page name.
286  331911 reference = getCurrentMixedDocumentReferenceResolver().resolve(documentReference);
287    } else {
288  0 reference = getDefaultDocumentReferenceResolver().resolve("");
289    }
290   
291  331908 return getDocument(reference);
292    }
293   
294    /**
295    * Loads an Document from the database. Rights are checked before sending back the document.
296    *
297    * @param reference the reference of the document to be loaded
298    * @param type the type of the reference
299    * @return a Document object (if the document couldn't be found a new one is created in memory - but not saved, you
300    * can check whether it's a new document or not by using {@link com.xpn.xwiki.api.Document#isNew()}
301    * @throws XWikiException
302    * @since 10.6RC1
303    */
 
304  0 toggle @Unstable
305    public Document getEntityDocument(String reference, EntityType type) throws XWikiException
306    {
307  0 XWikiDocument doc = this.xwiki.getDocument(reference, type, getXWikiContext());
308  0 if (!getContextualAuthorizationManager().hasAccess(Right.VIEW, doc.getDocumentReference())) {
309  0 return null;
310    }
311   
312  0 return doc.newDocument(getXWikiContext());
313    }
314   
315    /**
316    * Loads a Document from the database. Rights are checked before sending back the document.
317    *
318    * @param reference the reference of the XWiki document to be loaded
319    * @return a Document object (if the document couldn't be found a new one is created in memory - but not saved, you
320    * can check whether it's a new document or not by using {@link com.xpn.xwiki.api.Document#isNew()}
321    * @throws XWikiException
322    * @since 2.3M1
323    */
 
324  434192 toggle public Document getDocument(DocumentReference reference) throws XWikiException
325    {
326  434636 try {
327  434821 XWikiDocument doc = this.xwiki.getDocument(reference, getXWikiContext());
328  435353 if (this.xwiki.getRightService().hasAccessLevel("view", getXWikiContext().getUser(),
329    doc.getPrefixedFullName(), getXWikiContext()) == false) {
330  15619 return null;
331    }
332   
333  419750 return doc.newDocument(getXWikiContext());
334    } catch (Exception ex) {
335  0 LOGGER.warn("Failed to access document [{}]. Root reason: [{}]", reference,
336    ExceptionUtils.getRootCauseMessage(ex));
337  0 return new Document(new XWikiDocument(reference), getXWikiContext());
338    }
339    }
340   
341    /**
342    * Loads a Document from the store. Rights are checked before sending back the document.
343    * <p>
344    * The passed reference can be anything. If if a document child, the document reference will be extracted from it.
345    * If it's a document parent it will be completed with the necessary default references (for example if it's a space
346    * reference it will load the space home page).
347    *
348    * @param reference the reference close to the XWiki document to be loaded
349    * @return a Document object (if the document couldn't be found a new one is created in memory - but not saved, you
350    * can check whether it's a new document or not by using {@link com.xpn.xwiki.api.Document#isNew()}
351    * @throws XWikiException
352    * @since 7.1M2
353    */
 
354  15640 toggle public Document getDocument(EntityReference reference) throws XWikiException
355    {
356  15640 return getDocument(this.xwiki.getDocumentReference(reference, getXWikiContext()));
357    }
358   
359    /**
360    * Loads an Document from the database. Rights are checked on the author (contentAuthor) of the document containing
361    * the currently executing script before sending back the loaded document.
362    *
363    * @param fullName the full name of the XWiki document to be loaded
364    * @return a Document object (if the document couldn't be found a new one is created in memory - but not saved, you
365    * can check whether it's a new document or not by using {@link com.xpn.xwiki.api.Document#isNew()}
366    * @throws XWikiException
367    * @since 2.3M2
368    */
 
369  222 toggle public Document getDocumentAsAuthor(String fullName) throws XWikiException
370    {
371  222 DocumentReference reference;
372   
373    // We ignore the passed full name if it's null to match behavior of getDocument
374  222 if (fullName != null) {
375    // Note: We use the CurrentMixed Resolver since we want to use the default page name if the page isn't
376    // specified in the passed string, rather than use the current document's page name.
377  222 reference = getCurrentMixedDocumentReferenceResolver().resolve(fullName);
378    } else {
379  0 reference = getDefaultDocumentReferenceResolver().resolve("");
380    }
381   
382  222 return getDocumentAsAuthor(reference);
383    }
384   
385    /**
386    * Loads an Document from the database. Rights are checked on the author (contentAuthor) of the document containing
387    * the currently executing script before sending back the loaded document.
388    *
389    * @param reference the reference of the XWiki document to be loaded
390    * @return a Document object (if the document couldn't be found a new one is created in memory - but not saved, you
391    * can check whether it's a new document or not by using {@link com.xpn.xwiki.api.Document#isNew()}
392    * @throws XWikiException
393    * @since 2.3M2
394    */
 
395  222 toggle public Document getDocumentAsAuthor(DocumentReference reference) throws XWikiException
396    {
397  222 if (!getAuthorizationManager().hasAccess(Right.VIEW, getEffectiveAuthorReference(), reference)) {
398  0 return null;
399    }
400   
401  222 return this.xwiki.getDocument(reference, getXWikiContext()).newDocument(getXWikiContext());
402    }
403   
404    /**
405    * @param fullname the {@link XWikiDocument#getFullName() name} of the document to search for.
406    * @param locale an optional {@link XWikiDocument#getLocale() locale} to filter results.
407    * @return A list with all the deleted versions of a document in the recycle bin.
408    * @throws XWikiException if any error
409    */
 
410  6749 toggle public List<DeletedDocument> getDeletedDocuments(String fullname, String locale) throws XWikiException
411    {
412  6749 XWikiDeletedDocument[] deletedDocuments = this.xwiki.getDeletedDocuments(fullname, locale, this.context);
413  6748 List<DeletedDocument> result = wrapDeletedDocuments(deletedDocuments);
414  6749 return result;
415    }
416   
417    /**
418    * @param batchId id of the operation that deleted multiple documents at the same time; useful when trying to revert
419    * the operation
420    * @return a list of all document versions that were deleted in the same batch, as part of the same operation
421    * @throws XWikiException if any error
422    * @since 9.4RC1
423    */
 
424  0 toggle public List<DeletedDocument> getDeletedDocuments(String batchId) throws XWikiException
425    {
426  0 XWikiDeletedDocument[] deletedDocuments = this.xwiki.getDeletedDocuments(batchId, this.context);
427  0 List<DeletedDocument> result = wrapDeletedDocuments(deletedDocuments);
428  0 return result;
429    }
430   
 
431  6748 toggle private List<DeletedDocument> wrapDeletedDocuments(XWikiDeletedDocument[] deletedDocuments)
432    {
433  6749 if (deletedDocuments == null || deletedDocuments.length == 0) {
434  6686 return Collections.emptyList();
435    }
436   
437  63 List<DeletedDocument> result = new ArrayList<>(deletedDocuments.length);
438  63 for (XWikiDeletedDocument deletedDocument : deletedDocuments) {
439  107 result.add(new DeletedDocument(deletedDocument, this.context));
440    }
441   
442  63 return result;
443    }
444   
445    /**
446    * @param fullname - {@link XWikiDocument#getFullName()}
447    * @param locale - {@link XWikiDocument#getLocale()}
448    * @param index - {@link XWikiDocument#getId()}
449    * @return the specified document from the recycle bin
450    * @throws XWikiException if any error
451    * @deprecated since 9.4RC1. Use {@link #getDeletedDocument(String)} instead.
452    */
 
453  0 toggle @Deprecated
454    public DeletedDocument getDeletedDocument(String fullname, String locale, String index) throws XWikiException
455    {
456  0 return getDeletedDocument(index);
457    }
458   
459    /**
460    * @return the specified document from the recycle bin
461    * @throws XWikiException if any error
462    * @since 9.4RC1
463    */
 
464  90 toggle public DeletedDocument getDeletedDocument(String index) throws XWikiException
465    {
466  90 if (!NumberUtils.isDigits(index)) {
467  0 return null;
468    }
469   
470  90 XWikiDeletedDocument dd = this.xwiki.getDeletedDocument(Long.parseLong(index), this.context);
471  90 if (dd == null) {
472  0 return null;
473    }
474   
475  90 return new DeletedDocument(dd, this.context);
476    }
477   
478    /**
479    * Retrieve all the deleted attachments that belonged to a certain document. Note that this does not distinguish
480    * between different incarnations of a document name, and it does not require that the document still exists, it
481    * returns all the attachments that at the time of their deletion had a document with the specified name as their
482    * owner.
483    *
484    * @param docName the {@link XWikiDocument#getFullName() name} of the owner document
485    * @return A list with all the deleted attachments which belonged to the specified document. If no such attachments
486    * are found in the trash, an empty list is returned.
487    */
 
488  0 toggle public List<DeletedAttachment> getDeletedAttachments(String docName)
489    {
490  0 try {
491  0 List<com.xpn.xwiki.doc.DeletedAttachment> attachments =
492    this.xwiki.getDeletedAttachments(docName, this.context);
493  0 if (attachments == null || attachments.isEmpty()) {
494  0 attachments = Collections.emptyList();
495    }
496  0 List<DeletedAttachment> result = new ArrayList<DeletedAttachment>(attachments.size());
497  0 for (com.xpn.xwiki.doc.DeletedAttachment attachment : attachments) {
498  0 result.add(new DeletedAttachment(attachment, this.context));
499    }
500  0 return result;
501    } catch (Exception ex) {
502  0 LOGGER.warn("Failed to retrieve deleted attachments", ex);
503    }
504  0 return Collections.emptyList();
505    }
506   
507    /**
508    * Retrieve all the deleted attachments that belonged to a certain document and had the specified name. Multiple
509    * versions can be returned since the same file can be uploaded and deleted several times, creating different
510    * instances in the trash. Note that this does not distinguish between different incarnations of a document name,
511    * and it does not require that the document still exists, it returns all the attachments that at the time of their
512    * deletion had a document with the specified name as their owner.
513    *
514    * @param docName the {@link DeletedAttachment#getDocName() name of the document} the attachment belonged to
515    * @param filename the {@link DeletedAttachment#getFilename() name} of the attachment to search for
516    * @return A list with all the deleted attachments which belonged to the specified document and had the specified
517    * filename. If no such attachments are found in the trash, an empty list is returned.
518    */
 
519  0 toggle public List<DeletedAttachment> getDeletedAttachments(String docName, String filename)
520    {
521  0 try {
522  0 List<com.xpn.xwiki.doc.DeletedAttachment> attachments =
523    this.xwiki.getDeletedAttachments(docName, filename, this.context);
524  0 if (attachments == null) {
525  0 attachments = Collections.emptyList();
526    }
527  0 List<DeletedAttachment> result = new ArrayList<DeletedAttachment>(attachments.size());
528  0 for (com.xpn.xwiki.doc.DeletedAttachment attachment : attachments) {
529  0 result.add(new DeletedAttachment(attachment, this.context));
530    }
531  0 return result;
532    } catch (Exception ex) {
533  0 LOGGER.warn("Failed to retrieve deleted attachments", ex);
534    }
535  0 return Collections.emptyList();
536    }
537   
538    /**
539    * Retrieve a specific attachment from the trash.
540    *
541    * @param id the unique identifier of the entry in the trash
542    * @return specified attachment from the trash, {@code null} if not found
543    */
 
544  0 toggle public DeletedAttachment getDeletedAttachment(String id)
545    {
546  0 try {
547  0 com.xpn.xwiki.doc.DeletedAttachment attachment = this.xwiki.getDeletedAttachment(id, this.context);
548  0 if (attachment != null) {
549  0 return new DeletedAttachment(attachment, this.context);
550    }
551    } catch (Exception ex) {
552  0 LOGGER.warn("Failed to retrieve deleted attachment", ex);
553    }
554  0 return null;
555    }
556   
557    /**
558    * Returns whether a document exists or not
559    *
560    * @param fullname Fullname of the XWiki document to be loaded
561    * @return true if the document exists, false if not
562    * @throws XWikiException
563    */
 
564  258272 toggle public boolean exists(String fullname) throws XWikiException
565    {
566  258306 return this.xwiki.exists(fullname, getXWikiContext());
567    }
568   
569    /**
570    * Returns whether a document exists or not
571    *
572    * @param reference the reference of the document to check for its existence
573    * @return true if the document exists, false if not
574    * @since 2.3M2
575    */
 
576  60498 toggle public boolean exists(DocumentReference reference) throws XWikiException
577    {
578  60498 return this.xwiki.exists(reference, getXWikiContext());
579    }
580   
581    /**
582    * Verify the rights the current user has on a document. If the document requires rights and the user is not
583    * authenticated he will be redirected to the login page.
584    *
585    * @param docname fullname of the document
586    * @param right right to check ("view", "edit", "admin", "delete")
587    * @return true if it exists
588    */
 
589  29 toggle public boolean checkAccess(String docname, String right)
590    {
591  29 try {
592  29 DocumentReference docReference = getCurrentMixedDocumentReferenceResolver().resolve(docname);
593  29 XWikiDocument doc = getXWikiContext().getWiki().getDocument(docReference, this.context);
594  29 return getXWikiContext().getWiki().checkAccess(right, doc, getXWikiContext());
595    } catch (XWikiException e) {
596  0 return false;
597    }
598    }
599   
600    /**
601    * Loads an Document from the database. Rights are checked before sending back the document.
602    *
603    * @param space Space to use in case no space is defined in the provided <code>fullname</code>
604    * @param fullname the full name or relative name of the document to load
605    * @return a Document object (if the document couldn't be found a new one is created in memory - but not saved, you
606    * can check whether it's a new document or not by using {@link com.xpn.xwiki.api.Document#isNew()}
607    * @throws XWikiException
608    */
 
609  1 toggle public Document getDocument(String space, String fullname) throws XWikiException
610    {
611  1 XWikiDocument doc = this.xwiki.getDocument(space, fullname, getXWikiContext());
612  1 if (this.xwiki.getRightService().hasAccessLevel("view", getXWikiContext().getUser(), doc.getFullName(),
613    getXWikiContext()) == false) {
614  0 return null;
615    }
616   
617  1 return doc.newDocument(getXWikiContext());
618    }
619   
620    /**
621    * Load a specific revision of a document
622    *
623    * @param doc Document for which to load a specific revision
624    * @param rev Revision number
625    * @return Specific revision of a document
626    * @throws XWikiException is never thrown
627    */
 
628  7 toggle public Document getDocument(Document doc, String rev) throws XWikiException
629    {
630  7 if (doc == null || doc.getDoc() == null) {
631  0 return null;
632    }
633   
634  7 if (!getContextualAuthorizationManager().hasAccess(Right.VIEW, doc.getDocumentReference())) {
635    // Finally we return null, otherwise showing search result is a real pain
636  0 return null;
637    }
638   
639  7 return doc.getDocumentRevision(rev);
640    }
641   
642    /**
643    * Load a specific revision of a document
644    *
645    * @param reference Document for which to load a specific revision
646    * @param revision Revision number
647    * @return Specific revision of a document
648    * @throws XWikiException is never thrown
649    * @since 9.4RC1
650    */
 
651  15 toggle public Document getDocument(DocumentReference reference, String revision) throws XWikiException
652    {
653  15 try {
654  15 if (reference != null && getContextualAuthorizationManager().hasAccess(Right.VIEW, reference)) {
655  15 XWikiDocument documentRevision = getDocumentRevisionProvider().getRevision(reference, revision);
656   
657  13 if (documentRevision != null) {
658  4 return new Document(documentRevision, this.context);
659    }
660    }
661    } catch (Exception e) {
662  2 LOGGER.error("Failed to access revision [{}] of document {}", revision, reference, e);
663    }
664   
665  11 return null;
666    }
667   
668    /**
669    * Output content in the edit content textarea
670    *
671    * @param content content to output
672    * @return the textarea text content
673    */
 
674  0 toggle public String getTextArea(String content)
675    {
676  0 return com.xpn.xwiki.XWiki.getTextArea(content, getXWikiContext());
677    }
678   
679    /**
680    * Get the list of available classes in the wiki
681    *
682    * @return list of classes names
683    * @throws XWikiException
684    */
 
685  180 toggle public List<String> getClassList() throws XWikiException
686    {
687  180 return this.xwiki.getClassList(getXWikiContext());
688    }
689   
690    /**
691    * Get the global MetaClass object
692    *
693    * @return MetaClass object
694    */
 
695  2853 toggle public MetaClass getMetaclass()
696    {
697  2853 return this.xwiki.getMetaclass();
698    }
699   
700    /**
701    * API allowing to search for document names matching a query. Examples:
702    * <ul>
703    * <li>Query: <code>where doc.space='Main' order by doc.creationDate desc</code>. Result: All the documents in space
704    * 'Main' ordered by the creation date from the most recent</li>
705    * <li>Query: <code>where doc.name like '%sport%' order by doc.name asc</code>. Result: All the documents containing
706    * 'sport' in their name ordered by document name</li>
707    * <li>Query: <code>where doc.content like '%sport%' order by doc.author</code> Result: All the documents containing
708    * 'sport' in their content ordered by the author</li>
709    * <li>Query: <code>where doc.creator = 'XWiki.LudovicDubost' order by doc.creationDate
710    * desc</code>. Result: All the documents with creator LudovicDubost ordered by the creation date from the
711    * most recent</li>
712    * <li>Query: <code>where doc.author = 'XWiki.LudovicDubost' order by doc.date desc</code>. Result: All the
713    * documents with last author LudovicDubost ordered by the last modification date from the most recent.</li>
714    * <li>Query: <code>,BaseObject as obj where doc.fullName=obj.name and
715    * obj.className='XWiki.XWikiComments' order by doc.date desc</code>. Result: All the documents with at least
716    * one comment ordered by the last modification date from the most recent</li>
717    * <li>Query: <code>,BaseObject as obj, StringProperty as prop where
718    * doc.fullName=obj.name and obj.className='XWiki.XWikiComments' and obj.id=prop.id.id
719    * and prop.id.name='author' and prop.value='XWiki.LudovicDubost' order by doc.date
720    * desc</code>. Result: All the documents with at least one comment from LudovicDubost ordered by the last
721    * modification date from the most recent</li>
722    * </ul>
723    *
724    * @param wheresql Query to be run (either starting with ", BaseObject as obj where.." or by "where ..."
725    * @return List of document names matching (Main.Page1, Main.Page2)
726    * @throws XWikiException
727    * @deprecated use query service instead
728    */
 
729  0 toggle @Deprecated
730    public List<String> searchDocuments(String wheresql) throws XWikiException
731    {
732  0 return this.xwiki.getStore().searchDocumentsNames(wheresql, getXWikiContext());
733    }
734   
735    /**
736    * API allowing to search for document names matching a query return only a limited number of elements and skipping
737    * the first rows. The query part is the same as searchDocuments
738    *
739    * @param wheresql query to use similar to searchDocuments(wheresql)
740    * @param nb return only 'nb' rows
741    * @param start skip the first 'start' rows
742    * @return List of document names matching
743    * @throws XWikiException
744    * @see List searchDocuments(String where sql)
745    * @deprecated use query service instead
746    */
 
747  0 toggle @Deprecated
748    public List<String> searchDocuments(String wheresql, int nb, int start) throws XWikiException
749    {
750  0 return this.xwiki.getStore().searchDocumentsNames(wheresql, nb, start, getXWikiContext());
751    }
752   
753    /**
754    * Privileged API allowing to search for document names matching a query return only a limited number of elements
755    * and skipping the first rows. The return values contain the list of columns specified in addition to the document
756    * space and name The query part is the same as searchDocuments
757    *
758    * @param wheresql query to use similar to searchDocuments(wheresql)
759    * @param nb return only 'nb' rows
760    * @param start skip the first 'start' rows
761    * @param selectColumns List of columns to add to the result
762    * @return List of Object[] with the column values of the matching rows
763    * @throws XWikiException
764    * @deprecated use query service instead
765    */
 
766  0 toggle @Deprecated
767    public List<String> searchDocuments(String wheresql, int nb, int start, String selectColumns) throws XWikiException
768    {
769  0 if (hasProgrammingRights()) {
770  0 return this.xwiki.getStore().searchDocumentsNames(wheresql, nb, start, selectColumns, getXWikiContext());
771    }
772   
773  0 return Collections.emptyList();
774    }
775   
776    /**
777    * API allowing to search for documents allowing to have mutliple entries per locale
778    *
779    * @param wheresql query to use similar to searchDocuments(wheresql)
780    * @param distinctbylocale true to return multiple rows per locale
781    * @return List of Document object matching
782    * @throws XWikiException
783    */
 
784  0 toggle public List<Document> searchDocuments(String wheresql, boolean distinctbylocale) throws XWikiException
785    {
786  0 return convert(this.xwiki.getStore().searchDocuments(wheresql, distinctbylocale, getXWikiContext()));
787    }
788   
789    /**
790    * API allowing to search for documents allowing to have multiple entries per locale
791    *
792    * @param wheresql query to use similar to searchDocuments(wheresql)
793    * @param distinctbylocale true to return multiple rows per locale
794    * @return List of Document object matching
795    * @param nb return only 'nb' rows
796    * @param start skip the first 'start' rows
797    * @throws XWikiException
798    */
 
799  0 toggle public List<Document> searchDocuments(String wheresql, boolean distinctbylocale, int nb, int start)
800    throws XWikiException
801    {
802  0 return convert(this.xwiki.getStore().searchDocuments(wheresql, distinctbylocale, nb, start, getXWikiContext()));
803    }
804   
805    /**
806    * Search documents by passing HQL where clause values as parameters. This allows generating a Named HQL query which
807    * will automatically encode the passed values (like escaping single quotes). This API is recommended to be used
808    * over the other similar methods where the values are passed inside the where clause and for which you'll need to
809    * do the encoding/escaping yourself before calling them.
810    * <p>
811    * Example
812    * </p>
813    *
814    * <pre>
815    * &lt;code&gt;
816    * #set($orphans = $xwiki.searchDocuments(&quot; where doc.fullName &lt;&gt; ? and (doc.parent = ? or &quot;
817    * + &quot;(doc.parent = ? and doc.space = ?))&quot;,
818    * [&quot;${doc.fullName}as&quot;, ${doc.fullName}, ${doc.name}, ${doc.space}]))
819    * &lt;/code&gt;
820    * </pre>
821    *
822    * @param parameterizedWhereClause the HQL where clause. For example
823    * {@code where doc.fullName <> ? and (doc.parent = ? or (doc.parent = ? and doc.space = ?))}
824    * @param maxResults the number of rows to return. If 0 then all rows are returned
825    * @param startOffset the number of rows to skip. If 0 don't skip any row
826    * @param parameterValues the where clause values that replace the question marks (?)
827    * @return a list of document names
828    * @throws XWikiException in case of error while performing the query
829    * @deprecated use query service instead
830    */
 
831  0 toggle @Deprecated
832    public List<String> searchDocuments(String parameterizedWhereClause, int maxResults, int startOffset,
833    List<?> parameterValues) throws XWikiException
834    {
835  0 return this.xwiki.getStore().searchDocumentsNames(parameterizedWhereClause, maxResults, startOffset,
836    parameterValues, getXWikiContext());
837    }
838   
839    /**
840    * Same as {@link #searchDocuments(String, int, int, java.util.List)} but returns all rows.
841    *
842    * @see #searchDocuments(String, int, int, java.util.List)
843    * @deprecated use query service instead
844    */
 
845  0 toggle @Deprecated
846    public List<String> searchDocuments(String parameterizedWhereClause, List<?> parameterValues) throws XWikiException
847    {
848  0 return this.xwiki.getStore().searchDocumentsNames(parameterizedWhereClause, parameterValues, getXWikiContext());
849    }
850   
851    /**
852    * Search documents in the provided wiki by passing HQL where clause values as parameters. See
853    * {@link #searchDocuments(String, int, int, java.util.List)} for more details.
854    *
855    * @param wikiName the name of the wiki where to search.
856    * @param parameterizedWhereClause the HQL where clause. For example
857    * {@code where doc.fullName <> ? and (doc.parent = ? or (doc.parent = ? and doc.space = ?))}
858    * @param maxResults the number of rows to return. If 0 then all rows are returned
859    * @param startOffset the number of rows to skip. If 0 don't skip any row
860    * @param parameterValues the where clause values that replace the question marks (?)
861    * @return a list of document full names (Space.Name).
862    * @see #searchDocuments(String, int, int, java.util.List)
863    * @throws XWikiException in case of error while performing the query
864    * @deprecated use query service instead
865    */
 
866  0 toggle @Deprecated
867    public List<String> searchDocumentsNames(String wikiName, String parameterizedWhereClause, int maxResults,
868    int startOffset, List<?> parameterValues) throws XWikiException
869    {
870  0 String database = this.context.getWikiId();
871   
872  0 try {
873  0 this.context.setWikiId(wikiName);
874   
875  0 return searchDocuments(parameterizedWhereClause, maxResults, startOffset, parameterValues);
876    } finally {
877  0 this.context.setWikiId(database);
878    }
879    }
880   
881    /**
882    * Search spaces by passing HQL where clause values as parameters. See
883    * {@link #searchDocuments(String, int, int, List)} for more about parameterized hql clauses.
884    *
885    * @param parametrizedSqlClause the HQL where clause. For example
886    * {@code where doc.fullName <> ? and (doc.parent = ? or (doc.parent = ? and doc.space = ?))}
887    * @param nb the number of rows to return. If 0 then all rows are returned
888    * @param start the number of rows to skip. If 0 don't skip any row
889    * @param parameterValues the where clause values that replace the question marks (?)
890    * @return a list of spaces names.
891    * @throws XWikiException in case of error while performing the query
892    */
 
893  0 toggle public List<String> searchSpacesNames(String parametrizedSqlClause, int nb, int start, List<?> parameterValues)
894    throws XWikiException
895    {
896  0 return this.xwiki.getStore().search("select distinct doc.space from XWikiDocument doc " + parametrizedSqlClause,
897    nb, start, parameterValues, this.context);
898    }
899   
900    /**
901    * Search attachments by passing HQL where clause values as parameters. See
902    * {@link #searchDocuments(String, int, int, List)} for more about parameterized hql clauses. You can specify
903    * properties of attach (the attachment) or doc (the document it is attached to)
904    *
905    * @param parametrizedSqlClause The HQL where clause. For example
906    * {@code where doc.fullName <> ? and (attach.author = ? or (attach.filename = ? and doc.space = ?))}
907    * @param nb The number of rows to return. If 0 then all rows are returned
908    * @param start The number of rows to skip at the beginning.
909    * @param parameterValues A {@link java.util.List} of the where clause values that replace the question marks (?)
910    * @return A List of {@link Attachment} objects.
911    * @throws XWikiException in case of error while performing the query
912    * @since 5.0M2
913    */
 
914  0 toggle public List<Attachment> searchAttachments(String parametrizedSqlClause, int nb, int start, List<?> parameterValues)
915    throws XWikiException
916    {
917  0 return convertAttachments(
918    this.xwiki.searchAttachments(parametrizedSqlClause, true, nb, start, parameterValues, this.context));
919    }
920   
921    /**
922    * Count attachments returned by a given parameterized query
923    *
924    * @param parametrizedSqlClause Everything which would follow the "WHERE" in HQL see:
925    * {@link #searchDocuments(String, int, int, List)}
926    * @param parameterValues A {@link java.util.List} of the where clause values that replace the question marks (?)
927    * @return int number of attachments found.
928    * @throws XWikiException
929    * @see #searchAttachments(String, int, int, List)
930    * @since 5.0M2
931    */
 
932  0 toggle public int countAttachments(String parametrizedSqlClause, List<?> parameterValues) throws XWikiException
933    {
934  0 return this.xwiki.countAttachments(parametrizedSqlClause, parameterValues, this.context);
935    }
936   
937    /**
938    * Function to wrap a list of XWikiDocument into Document objects
939    *
940    * @param docs list of XWikiDocument
941    * @return list of Document objects
942    */
 
943  2 toggle public List<Document> wrapDocs(List<?> docs)
944    {
945  2 List<Document> result = new ArrayList<Document>();
946  2 if (docs != null) {
947  2 for (java.lang.Object obj : docs) {
948  4 try {
949  4 if (obj instanceof XWikiDocument) {
950  4 XWikiDocument doc = (XWikiDocument) obj;
951  4 Document wrappedDoc = doc.newDocument(getXWikiContext());
952  4 result.add(wrappedDoc);
953  0 } else if (obj instanceof Document) {
954  0 result.add((Document) obj);
955  0 } else if (obj instanceof String) {
956  0 Document doc = getDocument(obj.toString());
957  0 if (doc != null) {
958  0 result.add(doc);
959    }
960    }
961    } catch (XWikiException ex) {
962    }
963    }
964    }
965   
966  2 return result;
967    }
968   
969    /**
970    * API allowing to parse a text content to evaluate velocity scripts
971    *
972    * @param content
973    * @return evaluated content if the content contains velocity scripts
974    * @deprecated Since 7.2M1. Use specific rendering/parsing options for the content type you want to parse/render.
975    */
 
976  0 toggle @Deprecated
977    public String parseContent(String content)
978    {
979  0 return this.xwiki.parseContent(content, getXWikiContext());
980    }
981   
982    /**
983    * API to parse a velocity template provided by the current Skin The template is first looked in the skin active for
984    * the user, the space or the wiki. If the template does not exist in that skin, the template is looked up in the
985    * "parent skin" of the skin
986    *
987    * @param template Template name ("view", "edit", "comment")
988    * @return Evaluated content from the template
989    */
 
990  754460 toggle public String parseTemplate(String template)
991    {
992  754867 return this.xwiki.parseTemplate(template, getXWikiContext());
993    }
994   
995    /**
996    * API to render a velocity template provided by the current Skin The template is first looked in the skin active
997    * for the user, the space or the wiki. If the template does not exist in that skin, the template is looked up in
998    * the "parent skin" of the skin
999    *
1000    * @param template Template name ("view", "edit", "comment")
1001    * @return Evaluated content from the template
1002    */
 
1003  0 toggle public String renderTemplate(String template)
1004    {
1005  0 return this.xwiki.renderTemplate(template, getXWikiContext());
1006    }
1007   
1008    /**
1009    * Designed to include dynamic content, such as Servlets or JSPs, inside Velocity templates; works by creating a
1010    * RequestDispatcher, buffering the output, then returning it as a string.
1011    *
1012    * @param url URL of the servlet
1013    * @return text result of the servlet
1014    */
 
1015  0 toggle public String invokeServletAndReturnAsString(String url)
1016    {
1017  0 return this.xwiki.invokeServletAndReturnAsString(url, getXWikiContext());
1018    }
1019   
1020    /**
1021    * Return the URL of the static file provided by the current skin The file is first looked in the skin active for
1022    * the user, the space or the wiki. If the file does not exist in that skin, the file is looked up in the "parent
1023    * skin" of the skin. The file can be a CSS file, an image file, a javascript file, etc.
1024    *
1025    * @param filename Filename to be looked up in the skin (logo.gif, style.css)
1026    * @return URL to access this file
1027    */
 
1028  127078 toggle public String getSkinFile(String filename)
1029    {
1030  127085 return this.xwiki.getSkinFile(filename, getXWikiContext());
1031    }
1032   
1033    /**
1034    * Return the URL of the static file provided by the current skin The file is first looked in the skin active for
1035    * the user, the space or the wiki. If the file does not exist in that skin, the file is looked up in the "parent
1036    * skin" of the skin. The file can be a CSS file, an image file, a javascript file, etc.
1037    *
1038    * @param filename Filename to be looked up in the skin (logo.gif, style.css)
1039    * @param forceSkinAction true to make sure that static files are retrieved through the skin action, to allow
1040    * parsing of velocity on CSS files
1041    * @return URL to access this file
1042    */
 
1043  84020 toggle public String getSkinFile(String filename, boolean forceSkinAction)
1044    {
1045  84022 return this.xwiki.getSkinFile(filename, forceSkinAction, getXWikiContext());
1046    }
1047   
1048    /**
1049    * API to retrieve the current skin for this request and user The skin is first derived from the request "skin"
1050    * parameter If this parameter does not exist, the user preference "skin" is looked up If this parameter does not
1051    * exist or is empty, the space preference "skin" is looked up If this parameter does not exist or is empty, the
1052    * XWiki preference "skin" is looked up If this parameter does not exist or is empty, the xwiki.cfg parameter
1053    * xwiki.defaultskin is looked up If this parameter does not exist or is empty, the xwiki.cfg parameter
1054    * xwiki.defaultbaseskin is looked up If this parameter does not exist or is empty, the skin is "colibri"
1055    *
1056    * @return The current skin for this request and user
1057    */
 
1058  75228 toggle public String getSkin()
1059    {
1060  75231 return this.xwiki.getSkin(getXWikiContext());
1061    }
1062   
1063    /**
1064    * API to retrieve the current skin for this request and user. Each skin has a skin it is based on. If not the base
1065    * skin is the xwiki.cfg parameter "xwiki.defaultbaseskin". If this parameter does not exist or is empty, the base
1066    * skin is "colibri".
1067    *
1068    * @return The current baseskin for this request and user
1069    */
 
1070  0 toggle public String getBaseSkin()
1071    {
1072  0 return this.xwiki.getBaseSkin(getXWikiContext());
1073    }
1074   
1075    /**
1076    * API to access the copyright for this space. The copyright is read in the space preferences. If it does not exist
1077    * or is empty it is read from the XWiki preferences.
1078    *
1079    * @return the text for the copyright
1080    */
 
1081  50238 toggle public String getSpaceCopyright()
1082    {
1083  50239 return this.xwiki.getSpaceCopyright(getXWikiContext());
1084    }
1085   
1086    /**
1087    * API to access an XWiki Preference There can be one preference object per locale This function will find the right
1088    * preference object associated to the current active locale
1089    *
1090    * @param preference Preference name
1091    * @return The preference for this wiki and the current locale
1092    */
 
1093  23319 toggle public String getXWikiPreference(String preference)
1094    {
1095  23319 return this.xwiki.getXWikiPreference(preference, getXWikiContext());
1096    }
1097   
1098    /**
1099    * API to access an XWiki Preference There can be one preference object per locale This function will find the right
1100    * preference object associated to the current active locale
1101    *
1102    * @param preference Preference name
1103    * @param defaultValue default value to return if the preference does not exist or is empty
1104    * @return The preference for this wiki and the current locale
1105    */
 
1106  57 toggle public String getXWikiPreference(String preference, String defaultValue)
1107    {
1108  57 return this.xwiki.getXWikiPreference(preference, defaultValue, getXWikiContext());
1109    }
1110   
1111    /**
1112    * API to access an Space Preference There can be one preference object per locale This function will find the right
1113    * preference object associated to the current active locale If no preference is found it will look in the XWiki
1114    * Preferences
1115    *
1116    * @param preference Preference name
1117    * @return The preference for this wiki and the current locale
1118    */
 
1119  363047 toggle public String getSpacePreference(String preference)
1120    {
1121  363315 return this.xwiki.getSpacePreference(preference, getXWikiContext());
1122    }
1123   
1124    /**
1125    * API to access an Space Preference There can be one preference object per locale This function will find the right
1126    * preference object associated to the current active locale If no preference is found it will look in the XWiki
1127    * Preferences
1128    *
1129    * @param preference Preference name
1130    * @param defaultValue default value to return if the preference does not exist or is empty
1131    * @return The preference for this wiki and the current locale
1132    */
 
1133  0 toggle public String getSpacePreference(String preference, String defaultValue)
1134    {
1135  0 return this.xwiki.getSpacePreference(preference, defaultValue, getXWikiContext());
1136    }
1137   
1138    /**
1139    * API to access a Skin Preference The skin object is the current user's skin
1140    *
1141    * @param preference Preference name
1142    * @return The preference for the current skin
1143    */
 
1144  0 toggle public String getSkinPreference(String preference)
1145    {
1146  0 return this.xwiki.getSkinPreference(preference, getXWikiContext());
1147    }
1148   
1149    /**
1150    * API to access a Skin Preference The skin object is the current user's skin
1151    *
1152    * @param preference Preference name
1153    * @param defaultValue default value to return if the preference does not exist or is empty
1154    * @return The preference for the current skin
1155    */
 
1156  1158 toggle public String getSkinPreference(String preference, String defaultValue)
1157    {
1158  1158 return this.xwiki.getSkinPreference(preference, defaultValue, getXWikiContext());
1159    }
1160   
1161    /**
1162    * Get the reference of the space and fallback on parent space or wiki in case nothing is found.
1163    * <p>
1164    * If the property is not set on any level then empty String is returned.
1165    *
1166    * @param preference Preference name
1167    * @param space The space for which this preference is requested
1168    * @return The preference for this wiki and the current locale
1169    */
 
1170  12 toggle public String getSpacePreferenceFor(String preference, String space)
1171    {
1172  12 return getSpacePreferenceFor(preference, space, "");
1173    }
1174   
1175    /**
1176    * Get the reference of the space and fallback on parent space or wiki in case nothing is found.
1177    * <p>
1178    * If the property is not set on any level then <code>defaultValue</code> is returned.
1179    *
1180    * @param preference Preference name
1181    * @param space The space for which this preference is requested
1182    * @param defaultValue default value to return if the preference does not exist or is empty
1183    * @return The preference for this wiki and the current locale in long format
1184    */
 
1185  12 toggle public String getSpacePreferenceFor(String preference, String space, String defaultValue)
1186    {
1187  12 return this.xwiki.getSpacePreference(preference, space, defaultValue, getXWikiContext());
1188    }
1189   
1190    /**
1191    * Get the reference of the space and fallback on parent space or wiki in case nothing is found.
1192    * <p>
1193    * If the property is not set on any level then empty String is returned.
1194    *
1195    * @param preference the name of the preference key
1196    * @param spaceReference the reference of the space
1197    * @return the value of the preference or empty String if it could not be found
1198    * @since 7.4M1
1199    */
 
1200  0 toggle public String getSpacePreferenceFor(String preference, SpaceReference spaceReference)
1201    {
1202  0 return this.xwiki.getSpacePreference(preference, spaceReference, getXWikiContext());
1203    }
1204   
1205    /**
1206    * Get the reference of the space and fallback on parent space or wiki in case nothing is found.
1207    * <p>
1208    * If the property is not set on any level then <code>defaultValue</code> is returned.
1209    *
1210    * @param preference the name of the preference key
1211    * @param spaceReference the reference of the space
1212    * @param defaultValue the value to return if the preference can't be found
1213    * @return the value of the preference or <code>defaultValue</code> if it could not be found
1214    * @since 7.4M1
1215    */
 
1216  0 toggle public String getSpacePreferenceFor(String preference, SpaceReference spaceReference, String defaultValue)
1217    {
1218  0 return this.xwiki.getSpacePreference(preference, spaceReference, defaultValue, getXWikiContext());
1219    }
1220   
1221    /**
1222    * API to access an XWiki Preference as a long number There can be one preference object per locale This function
1223    * will find the right preference object associated to the current active locale
1224    *
1225    * @param preference Preference name
1226    * @param defaultValue default value to return if the preference does not exist or is empty
1227    * @return The preference for this wiki and the current locale in long format
1228    */
 
1229  0 toggle public long getXWikiPreferenceAsLong(String preference, long defaultValue)
1230    {
1231  0 return this.xwiki.getXWikiPreferenceAsLong(preference, defaultValue, getXWikiContext());
1232    }
1233   
1234    /**
1235    * API to access an XWiki Preference as a long number There can be one preference object per locale This function
1236    * will find the right preference object associated to the current active locale
1237    *
1238    * @param preference Preference name
1239    * @return The preference for this wiki and the current locale in long format
1240    */
 
1241  0 toggle public long getXWikiPreferenceAsLong(String preference)
1242    {
1243  0 return this.xwiki.getXWikiPreferenceAsLong(preference, getXWikiContext());
1244    }
1245   
1246    /**
1247    * API to access a Space Preference as a long number There can be one preference object per locale This function
1248    * will find the right preference object associated to the current active locale If no preference is found it will
1249    * look for the XWiki Preference
1250    *
1251    * @param preference Preference name
1252    * @param defaultValue default value to return if the prefenrece does not exist or is empty
1253    * @return The preference for this wiki and the current locale in long format
1254    */
 
1255  0 toggle public long getSpacePreferenceAsLong(String preference, long defaultValue)
1256    {
1257  0 return this.xwiki.getSpacePreferenceAsLong(preference, defaultValue, getXWikiContext());
1258    }
1259   
1260    /**
1261    * API to access a Space Preference as a long number There can be one preference object per locale This function
1262    * will find the right preference object associated to the current active locale If no preference is found it will
1263    * look for the XWiki Preference
1264    *
1265    * @param preference Preference name
1266    * @return The preference for this wiki and the current locale in long format
1267    */
 
1268  0 toggle public long getSpacePreferenceAsLong(String preference)
1269    {
1270  0 return this.xwiki.getSpacePreferenceAsLong(preference, getXWikiContext());
1271    }
1272   
1273    /**
1274    * API to access an XWiki Preference as an int number There can be one preference object per locale This function
1275    * will find the right preference object associated to the current active locale
1276    *
1277    * @param preference Preference name
1278    * @param defaultValue default value to return if the prefenrece does not exist or is empty
1279    * @return The preference for this wiki and the current locale in int format
1280    */
 
1281  717 toggle public int getXWikiPreferenceAsInt(String preference, int defaultValue)
1282    {
1283  717 return this.xwiki.getXWikiPreferenceAsInt(preference, defaultValue, getXWikiContext());
1284    }
1285   
1286    /**
1287    * API to access an XWiki Preference as a int number There can be one preference object per locale This function
1288    * will find the right preference object associated to the current active locale
1289    *
1290    * @param preference Preference name
1291    * @return The preference for this wiki and the current locale in int format
1292    */
 
1293  0 toggle public int getXWikiPreferenceAsInt(String preference)
1294    {
1295  0 return this.xwiki.getXWikiPreferenceAsInt(preference, getXWikiContext());
1296    }
1297   
1298    /**
1299    * API to access a space Preference as a int number There can be one preference object per locale This function will
1300    * find the right preference object associated to the current active locale If no preference is found it will look
1301    * for the XWiki Preference
1302    *
1303    * @param preference Preference name
1304    * @param defaultValue default value to return if the prefenrece does not exist or is empty
1305    * @return The preference for this wiki and the current locale in int format
1306    */
 
1307  1796 toggle public int getSpacePreferenceAsInt(String preference, int defaultValue)
1308    {
1309  1796 return this.xwiki.getSpacePreferenceAsInt(preference, defaultValue, getXWikiContext());
1310    }
1311   
1312    /**
1313    * API to access a Space Preference as a int number There can be one preference object per locale This function will
1314    * find the right preference object associated to the current active locale If no preference is found it will look
1315    * for the XWiki Preference
1316    *
1317    * @param preference Preference name
1318    * @return The preference for this wiki and the current locale in int format
1319    */
 
1320  0 toggle public int getSpacePreferenceAsInt(String preference)
1321    {
1322  0 return this.xwiki.getSpacePreferenceAsInt(preference, getXWikiContext());
1323    }
1324   
1325    /**
1326    * API to access a User Preference This function will look in the User profile for the preference If no preference
1327    * is found it will look in the Space Preferences If no preference is found it will look in the XWiki Preferences
1328    *
1329    * @param preference Preference name
1330    * @return The preference for this wiki and the current locale
1331    */
 
1332  55591 toggle public String getUserPreference(String preference)
1333    {
1334  55592 return this.xwiki.getUserPreference(preference, getXWikiContext());
1335    }
1336   
1337    /**
1338    * API to access a User Preference from cookie This function will look in the session cookie for the preference
1339    *
1340    * @param preference Preference name
1341    * @return The preference for this wiki and the current locale
1342    */
 
1343  0 toggle public String getUserPreferenceFromCookie(String preference)
1344    {
1345  0 return this.xwiki.getUserPreferenceFromCookie(preference, getXWikiContext());
1346    }
1347   
1348    /**
1349    * Same as {@link #getLocalePreference()} but as a String.
1350    *
1351    * @return the locale to use
1352    * @deprecated since 8.0M1, use {@link #getLocalePreference()} instead
1353    */
 
1354  0 toggle @Deprecated
1355    public String getLanguagePreference()
1356    {
1357  0 return this.xwiki.getLanguagePreference(getXWikiContext());
1358    }
1359   
1360    /**
1361    * First try to find the current locale in use from the XWiki context. If none is used and if the wiki is not
1362    * multilingual use the default locale defined in the XWiki preferences. If the wiki is multilingual try to get the
1363    * locale passed in the request. If none was passed try to get it from a cookie. If no locale cookie exists then use
1364    * the user default locale and barring that use the browser's "Accept-Language" header sent in HTTP request. If none
1365    * is defined use the default locale.
1366    *
1367    * @return the locale to use
1368    * @since 8.0M1
1369    */
 
1370  0 toggle public Locale getLocalePreference()
1371    {
1372  0 return this.xwiki.getLocalePreference(getXWikiContext());
1373    }
1374   
1375    /**
1376    * Same as {@link #getInterfaceLocalePreference()} but as a String.
1377    *
1378    * @return the document locale preference for the request
1379    * @deprecated since 8.0M1, use {@link #getInterfaceLocalePreference()} instead
1380    */
 
1381  0 toggle @Deprecated
1382    public String getInterfaceLanguagePreference()
1383    {
1384  0 return this.xwiki.getInterfaceLanguagePreference(getXWikiContext());
1385    }
1386   
1387    /**
1388    * API to access the interface locale preference for the request Order of evaluation is: locale of the wiki in
1389    * mono-lingual mode locale request parameter locale in context locale user preference locale in cookie locale
1390    * accepted by the navigator
1391    *
1392    * @return the document locale preference for the request
1393    */
 
1394  0 toggle public Locale getInterfaceLocalePreference()
1395    {
1396  0 return this.xwiki.getInterfaceLocalePreference(getXWikiContext());
1397    }
1398   
1399    /**
1400    * @return the list of all wiki names, including the main wiki, corresponding to the available wiki descriptors.
1401    * Example: the descriptor for the wiki <i>wikiname</i> is a document in the main wiki, named
1402    * <i>XWiki.XWikiServerWikiname</i>, containing an XWiki.XWikiServerClass object.
1403    * @see com.xpn.xwiki.XWiki#getVirtualWikisDatabaseNames(XWikiContext)
1404    */
 
1405  565 toggle public List<String> getWikiNames()
1406    {
1407  565 List<String> result = new ArrayList<String>();
1408   
1409  565 try {
1410  565 result = this.xwiki.getVirtualWikisDatabaseNames(getXWikiContext());
1411    } catch (Exception e) {
1412  0 LOGGER.error("Failed to get the list of all wiki names", e);
1413    }
1414   
1415  565 return result;
1416    }
1417   
1418    /**
1419    * Convenience method to ask if the current XWiki instance contains subwikis (in addition to the main wiki)
1420    *
1421    * @return true if at least 1 subwiki exists; false otherwise
1422    * @see #getWikiNames()
1423    */
 
1424  557 toggle public boolean hasSubWikis()
1425    {
1426  557 return getWikiNames().size() > 1;
1427    }
1428   
1429    /**
1430    * API to check is wiki is multi-lingual
1431    *
1432    * @return true for multi-lingual/false for mono-lingual
1433    */
 
1434  108165 toggle public boolean isMultiLingual()
1435    {
1436  108170 return this.xwiki.isMultiLingual(getXWikiContext());
1437    }
1438   
1439    /**
1440    * Privileged API to flush the cache of the Wiki installation This flushed the cache of all wikis, all plugins, all
1441    * renderers
1442    */
 
1443  1 toggle public void flushCache()
1444    {
1445  1 if (hasProgrammingRights()) {
1446  1 this.xwiki.flushCache(getXWikiContext());
1447    }
1448    }
1449   
1450    /**
1451    * Privileged API to create a new user from the request This API is used by RegisterNewUser wiki page
1452    *
1453    * @return the integer status code
1454    * <ul>
1455    * <li>1: ok</li>
1456    * <li>-2: passwords are different or password is empty</li>
1457    * <li>-3: user already exists</li>
1458    * <li>-4: invalid username provided</li>
1459    * <li>-8: user already exists</li>
1460    * </ul>
1461