/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.xpn.xwiki;
import java.lang.reflect.ParameterizedType;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.inject.Provider;
import org.apache.commons.collections4.map.LRUMap;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xwiki.component.util.DefaultParameterizedType;
import org.xwiki.context.Execution;
import org.xwiki.context.ExecutionContext;
import org.xwiki.localization.LocaleUtils;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.DocumentReferenceResolver;
import org.xwiki.model.reference.EntityReferenceSerializer;
import org.xwiki.model.reference.SpaceReference;
import org.xwiki.model.reference.WikiReference;
import org.xwiki.velocity.VelocityManager;
import org.xwiki.velocity.internal.VelocityExecutionContextInitializer;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.objects.classes.BaseClass;
import com.xpn.xwiki.user.api.XWikiRightService;
import com.xpn.xwiki.user.api.XWikiUser;
import com.xpn.xwiki.util.Util;
import com.xpn.xwiki.validation.XWikiValidationStatus;
import com.xpn.xwiki.web.Utils;
import com.xpn.xwiki.web.XWikiEngineContext;
import com.xpn.xwiki.web.XWikiForm;
import com.xpn.xwiki.web.XWikiMessageTool;
import com.xpn.xwiki.web.XWikiRequest;
import com.xpn.xwiki.web.XWikiResponse;
import com.xpn.xwiki.web.XWikiURLFactory;
/**
* Represents the execution environment for all the wiki pages. An instance of the <code>Context</code> class is
* available as a predefined variable for scripting inside any wiki page. You can access it using <code>$xcontext</code>
* in Velocity scripts or simply <code>xcontext</code> in Groovy ones. The <code>Context</code> class provides a means
* of getting contextual information about the current request or configuring XWiki on the fly.
*
* @version $Id: a8bb4f7318670118ece81e791f3321522e2fc3e9 $
*/
public class XWikiContext extends Hashtable<Object, Object>
{
/**
* Type instance for {@code Provider<XWikiContext>}.
*
* @since 5.0M1
*/
public static final ParameterizedType TYPE_PROVIDER =
new DefaultParameterizedType(null, Provider.class, XWikiContext.class);
public static final int MODE_SERVLET = 0;
public static final int MODE_PORTLET = 1;
public static final int MODE_XMLRPC = 2;
public static final int MODE_ATOM = 3;
public static final int MODE_PDF = 4;
public static final int MODE_GWT = 5;
public static final int MODE_GWT_DEBUG = 6;
public static final String EXECUTIONCONTEXT_KEY = "xwikicontext";
/**
* @deprecated use {@link VelocityManager#getVelocityContext()} instead
*/
public static final String KEY_LEGACY_VELOCITYCONTEXT = "vcontext";
/** Logging helper object. */
protected static final Logger LOGGER = LoggerFactory.getLogger(XWikiContext.class);
private static final String WIKI_KEY = "wiki";
private static final String ORIGINAL_WIKI_KEY = "originalWiki";
private static final String USER_KEY = "user";
private static final String USERREFERENCE_KEY = "userreference";
/**
* Used to resolve a string into a proper Document Reference using the current document's reference to fill the
* blanks, except for the page name for which the default page name is used instead and for the wiki name for which
* the current wiki is used instead of the current document reference's wiki.
*/
private DocumentReferenceResolver<String> currentMixedDocumentReferenceResolver;
/**
* Used to convert a proper Document Reference to a string but without the wiki name.
*/
private EntityReferenceSerializer<String> localEntityReferenceSerializer;
/**
* Used to convert a Document Reference to string (compact form without the wiki part if it matches the current
* wiki).
*/
private EntityReferenceSerializer<String> compactWikiEntityReferenceSerializer;
/** The Execution so that we can check if permissions were dropped there. */
private Execution execution;
private boolean finished = false;
private XWiki wiki;
private XWikiEngineContext engine_context;
private XWikiRequest request;
private XWikiResponse response;
private XWikiForm form;
private String action;
private String orig_wikiId;
private WikiReference wikiReference;
private DocumentReference userReference;
private Locale locale;
private static final String LANGUAGE_KEY = "language";
private Locale interfaceLocale;
private int mode;
private URL url;
private XWikiURLFactory URLFactory;
private int cacheDuration = 0;
private int classCacheSize = 20;
// Used to avoid recursive loading of documents if there are recursives usage of classes
// FIXME: why synchronized since a context is supposed to be tied to a thread ?
@SuppressWarnings("unchecked")
private Map<DocumentReference, BaseClass> classCache = Collections.synchronizedMap(new LRUMap(this.classCacheSize));
// FIXME: why synchronized since a context is supposed to be tied to a thread ?
private List<String> displayedFields = Collections.synchronizedList(new ArrayList<String>());
public XWikiContext()
{
}
private DocumentReferenceResolver<String> getCurrentMixedDocumentReferenceResolver()
{
if (this.currentMixedDocumentReferenceResolver == null) {
this.currentMixedDocumentReferenceResolver =
Utils.getComponent(DocumentReferenceResolver.TYPE_STRING, "currentmixed");
}
return this.currentMixedDocumentReferenceResolver;
}
private EntityReferenceSerializer<String> getLocalEntityReferenceSerializer()
{
if (this.localEntityReferenceSerializer == null) {
this.localEntityReferenceSerializer = Utils.getComponent(EntityReferenceSerializer.TYPE_STRING, "local");
}
return this.localEntityReferenceSerializer;
}
private EntityReferenceSerializer<String> getCompactWikiEntityReferenceSerializer()
{
if (this.compactWikiEntityReferenceSerializer == null) {
this.compactWikiEntityReferenceSerializer =
Utils.getComponent(EntityReferenceSerializer.TYPE_STRING, "compactwiki");
}
return this.compactWikiEntityReferenceSerializer;
}
private Execution getExecution()
{
if (this.execution == null) {
this.execution = Utils.getComponent(Execution.class);
}
return this.execution;
}
private ExecutionContext getExecutionContext()
{
if (getExecution() != null) {
return getExecution().getContext();
}
return null;
}
public XWiki getWiki()
{
return this.wiki;
}
public Util getUtil()
{
Util util = (Util) this.get("util");
if (util == null) {
util = new Util();
this.put("util", util);
}
return util;
}
public void setWiki(XWiki wiki)
{
this.wiki = wiki;
}
public XWikiEngineContext getEngineContext()
{
return this.engine_context;
}
public void setEngineContext(XWikiEngineContext engine_context)
{
this.engine_context = engine_context;
}
public XWikiRequest getRequest()
{
return this.request;
}
public void setRequest(XWikiRequest request)
{
this.request = request;
}
public String getAction()
{
return this.action;
}
public void setAction(String action)
{
this.action = action;
}
public XWikiResponse getResponse()
{
return this.response;
}
public void setResponse(XWikiResponse response)
{
this.response = response;
}
/**
* @deprecated since 6.1M1, use {@link #getWikiId()} instead
*/
@Deprecated
public String getDatabase()
{
return getWikiId();
}
/**
* @return the id of the current wiki, or null if none is set
* @since 6.1M1
*/
public String getWikiId()
{
return this.wikiReference != null ? this.wikiReference.getName() : null;
}
/**
* @return the reference of the current wiki or null if none is set
* @since 7.2M1
*/
public WikiReference getWikiReference()
{
return this.wikiReference;
}
/**
* @param wikiId the current wiki id
* @deprecated since 6.1M1, use {@link #setWikiId(String)} instead
*/
@Deprecated
public void setDatabase(String wikiId)
{
setWikiId(wikiId);
}
/**
* @param wikiId the current wiki id
* @since 6.1M1
*/
public void setWikiId(String wikiId)
{
setWikiReference(wikiId != null ? new WikiReference(wikiId) : null);
}
/**
* @param wikiReference the current wiki reference
* @since 7.2M1
*/
public void setWikiReference(WikiReference wikiReference)
{
this.wikiReference = wikiReference;
if (this.wikiReference == null) {
super.remove(WIKI_KEY);
} else {
super.put(WIKI_KEY, this.wikiReference.getName());
if (this.orig_wikiId == null) {
this.orig_wikiId = this.wikiReference.getName();
super.put(ORIGINAL_WIKI_KEY, this.wikiReference.getName());
}
}
}
@Override
public synchronized Object get(Object key)
{
Object value;
if (WIKI_KEY.equals(key)) {
value = getWikiId();
} else if (KEY_LEGACY_VELOCITYCONTEXT.equals(key)) {
ExecutionContext executionContext = getExecutionContext();
if (executionContext != null) {
value = executionContext.getProperty(VelocityExecutionContextInitializer.VELOCITY_CONTEXT_ID);
} else {
value = null;
}
} else {
value = super.get(key);
}
return value;
}
/**
* {@inheritDoc}
* <p>
* Make sure to keep wiki field and map synchronized.
* </p>
*
* @see java.util.Hashtable#put(java.lang.Object, java.lang.Object)
*/
@Override
public synchronized Object put(Object key, Object value)
{
Object previous;
if (WIKI_KEY.equals(key)) {
previous = get(WIKI_KEY);
setWikiId((String) value);
} else if (KEY_LEGACY_VELOCITYCONTEXT.equals(key)) {
ExecutionContext executionContext = getExecutionContext();
if (executionContext != null) {
previous = executionContext.getProperty(VelocityExecutionContextInitializer.VELOCITY_CONTEXT_ID);
executionContext.setProperty(VelocityExecutionContextInitializer.VELOCITY_CONTEXT_ID, value);
} else {
previous = null;
}
} else {
if (value != null) {
previous = super.put(key, value);
} else {
previous = super.remove(key);
}
}
return previous;
}
/**
* {@inheritDoc}
* <p>
* Make sure to keep wiki field and map synchronized.
* </p>
*
* @see java.util.Hashtable#remove(java.lang.Object)
*/
@Override
public synchronized Object remove(Object key)
{
Object previous;
if (WIKI_KEY.equals(key)) {
previous = get(WIKI_KEY);
setWikiId(null);
} else if (KEY_LEGACY_VELOCITYCONTEXT.equals(key)) {
ExecutionContext executionContext = getExecutionContext();
if (executionContext != null) {
previous = executionContext.getProperty(VelocityExecutionContextInitializer.VELOCITY_CONTEXT_ID);
executionContext.removeProperty(VelocityExecutionContextInitializer.VELOCITY_CONTEXT_ID);
} else {
previous = null;
}
} else {
previous = super.remove(key);
}
return previous;
}
/**
* Get the "original" wiki id. This will be the wiki id for the wiki which the user requested. If the wiki is
* switched to load some piece of data, this will remember what it should be switched back to.
*
* @return the wiki id originally requested by the user.
* @deprecated since 6.1M1, use {@link #getOriginalWikiId()} instead
*/
@Deprecated
public String getOriginalDatabase()
{
return getOriginalWikiId();
}
/**
* Get the "original" wiki id. This will be the wiki id for the wiki which the user requested. If the wiki is
* switched to load some piece of data, this will remember what it should be switched back to.
*
* @return the wiki id originally requested by the user.
* @since 6.1M1
*/
public String getOriginalWikiId()
{
return this.orig_wikiId;
}
/**
* @deprecated since 6.1M1, use {@link #setOriginalWikiId(String)} instead
*/
@Deprecated
public void setOriginalDatabase(String wikiId)
{
setOriginalWikiId(wikiId);
}
/**
* Set the "original" wiki id. This will be the wiki id for the wiki which the user requested. If the wiki is
* switched to load some piece of data, this will remember what it should be switched back to.
*
* @param wikiId the wiki id originally requested by the user
* @since 6.1M1
*/
public void setOriginalWikiId(String wikiId)
{
this.orig_wikiId = wikiId;
if (wikiId == null) {
remove(ORIGINAL_WIKI_KEY);
} else {
put(ORIGINAL_WIKI_KEY, wikiId);
}
}
/**
* @return true it's main wiki's context, false otherwise.
*/
public boolean isMainWiki()
{
return isMainWiki(getWikiId());
}
/**
* @param wikiName the name of the wiki.
* @return true it's main wiki's context, false otherwise.
*/
public boolean isMainWiki(String wikiName)
{
return StringUtils.equalsIgnoreCase(wikiName, getMainXWiki());
}
public XWikiDocument getDoc()
{
return (XWikiDocument) get("doc");
}
public void setDoc(XWikiDocument doc)
{
if (doc == null) {
remove("doc");
} else {
put("doc", doc);
}
}
public DocumentReference getUserReference()
{
return this.userReference;
}
public void setUserReference(DocumentReference userReference)
{
if (userReference == null) {
this.userReference = null;
remove(USER_KEY);
remove(USERREFERENCE_KEY);
} else {
this.userReference = new DocumentReference(userReference);
boolean ismain = isMainWiki(this.userReference.getWikiReference().getName());
put(USER_KEY, new XWikiUser(getUser(), ismain));
put(USERREFERENCE_KEY, this.userReference);
// Log this since it's probably a mistake so that we find who is doing bad things
if (this.userReference.getName().equals(XWikiRightService.GUEST_USER)) {
LOGGER.warn("A reference to XWikiGuest user has been set instead of null. This is probably a mistake.",
new Exception("See stack trace"));
}
}
}
private void setUserInternal(String user, boolean main)
{
if (user == null) {
setUserReference(null);
} else if (user.endsWith(XWikiRightService.GUEST_USER_FULLNAME) || user.equals(XWikiRightService.GUEST_USER)) {
setUserReference(null);
// retro-compatibilty hack: some code does not give the same meaning to null XWikiUser and XWikiUser
// containing guest user
put(USER_KEY, new XWikiUser(user, main));
} else {
setUserReference(resolveUserReference(user));
}
}
/**
* Make sure to use "XWiki" as default space when it's not provided in user name.
*/
private DocumentReference resolveUserReference(String user)
{
return getCurrentMixedDocumentReferenceResolver().resolve(user,
new SpaceReference("XWiki", new WikiReference(getWikiId() == null ? "xwiki" : getWikiId())));
}
/**
* @deprecated since 3.1M1 use {@link #setUserReference(DocumentReference)} instead
*/
@Deprecated
public void setUser(String user)
{
setUserInternal(user, false);
}
/**
* @deprecated since 3.1M1 use {@link #getUserReference()} instead
*/
@Deprecated
public String getUser()
{
if (this.userReference != null) {
if (getWikiId() == null) {
return getLocalEntityReferenceSerializer().serialize(this.userReference);
} else {
return getCompactWikiEntityReferenceSerializer().serialize(this.userReference,
new WikiReference(getWikiId()));
}
} else {
return XWikiRightService.GUEST_USER_FULLNAME;
}
}
/**
* @deprecated since 3.1M1 use {@link #getUserReference()} instead
*/
@Deprecated
public String getLocalUser()
{
if (this.userReference != null) {
return getLocalEntityReferenceSerializer().serialize(this.userReference);
} else {
return XWikiRightService.GUEST_USER_FULLNAME;
}
}
/**
* @deprecated since 3.1M1 use {@link #getUserReference()} instead
*/
@Deprecated
public XWikiUser getXWikiUser()
{
if (this.userReference != null) {
boolean ismain = isMainWiki(this.userReference.getWikiReference().getName());
return new XWikiUser(getUser(), ismain);
}
return (XWikiUser) get(USER_KEY);
}
/**
* @deprecated since 4.3M1 use {@link #getLocale()} instead
*/
@Deprecated
public String getLanguage()
{
return this.locale != null ? this.locale.toString() : null;
}
/**
* @deprecated since 4.3M1 use {@link #setLocale(Locale)} instead
*/
@Deprecated
public void setLanguage(String language)
{
setLocale(LocaleUtils.toLocale(Util.normalizeLanguage(language)));
}
/**
* @return the current locale
* @since 4.3M1
*/
public Locale getLocale()
{
return this.locale;
}
/**
* @param locale the current locale
* @since 4.3M1
*/
public void setLocale(Locale locale)
{
this.locale = locale;
if (locale == null) {
remove(LANGUAGE_KEY);
} else {
put(LANGUAGE_KEY, locale.toString());
}
}
/**
* @deprecated since 6.0M1, use {@link #getInterfaceLocale()} instead
*/
@Deprecated
public String getInterfaceLanguage()
{
return this.interfaceLocale != null ? this.interfaceLocale.toString() : null;
}
/**
* @return the {@link Locale} to use to display the user interface
* @since 6.0M1
*/
public Locale getInterfaceLocale()
{
return this.interfaceLocale;
}
/**
* @deprecated since 6.0M1, use {@link #setInterfaceLocale(Locale)} instead
*/
@Deprecated
public void setInterfaceLanguage(String interfaceLanguage)
{
setInterfaceLocale(LocaleUtils.toLocale(Util.normalizeLanguage(interfaceLanguage)));
}
/**
* @param interfaceLocale the {@link Locale} to use to display the content
* @since 6.0M1
*/
public void setInterfaceLocale(Locale interfaceLocale)
{
this.interfaceLocale = interfaceLocale;
}
public int getMode()
{
return this.mode;
}
public void setMode(int mode)
{
this.mode = mode;
}
public URL getURL()
{
return this.url;
}
public void setURL(URL url)
{
this.url = url;
}
public XWikiURLFactory getURLFactory()
{
return this.URLFactory;
}
public void setURLFactory(XWikiURLFactory URLFactory)
{
this.URLFactory = URLFactory;
}
public XWikiForm getForm()
{
return this.form;
}
public void setForm(XWikiForm form)
{
this.form = form;
}
public boolean isFinished()
{
return this.finished;
}
public void setFinished(boolean finished)
{
this.finished = finished;
}
/**
* @deprecated never made any sense since the context wiki can change any time
*/
@Deprecated
public void setWikiOwner(String wikiOwner)
{
// Cannot do anything
}
/**
* @deprecated use {@link XWiki#getWikiOwner(String, XWikiContext)} instead
*/
@Deprecated
public String getWikiOwner()
{
try {
return getWiki().getWikiOwner(getWikiId(), this);
} catch (XWikiException e) {
LOGGER.error("Failed to get owner for wiki [{}]", getWikiId(), e);
}
return null;
}
public XWikiDocument getWikiServer()
{
String currentWiki = getWikiId();
try {
setWikiId(getMainXWiki());
return getWiki().getDocument(XWiki.getServerWikiPage(currentWiki), this);
} catch (XWikiException e) {
LOGGER.error("Failed to get wiki descriptor for wiki [{}]", currentWiki, e);
} finally {
setWikiId(currentWiki);
}
return null;
}
public int getCacheDuration()
{
return this.cacheDuration;
}
public void setCacheDuration(int cacheDuration)
{
this.cacheDuration = cacheDuration;
}
public String getMainXWiki()
{
return (String) get("mainxwiki");
}
public void setMainXWiki(String str)
{
put("mainxwiki", str);
}
// Used to avoid recursive loading of documents if there are recursives usage of classes
public void addBaseClass(BaseClass bclass)
{
this.classCache.put(bclass.getDocumentReference(), bclass);
}
/**
* @since 2.2M2
*/
// Used to avoid recursive loading of documents if there are recursives usage of classes
public BaseClass getBaseClass(DocumentReference classReference)
{
return this.classCache.get(classReference);
}
/**
* @param classReference the reference of the class
* @since 9.0RC1
*/
public void removeBaseClass(DocumentReference classReference)
{
this.classCache.remove(classReference);
}
/**
* Empty the class cache.
*/
public void flushClassCache()
{
this.classCache.clear();
}
public void setLinksAction(String action)
{
put("links_action", action);
}
public void unsetLinksAction()
{
remove("links_action");
}
public String getLinksAction()
{
return (String) get("links_action");
}
public void setLinksQueryString(String value)
{
put("links_qs", value);
}
public void unsetLinksQueryString()
{
remove("links_qs");
}
public String getLinksQueryString()
{
return (String) get("links_qs");
}
/**
* @deprecated since 4.3M2 use {@link org.xwiki.localization.ContextualLocalizationManager} component instead
*/
@Deprecated
public XWikiMessageTool getMessageTool()
{
XWikiMessageTool msg = ((XWikiMessageTool) get("msg"));
if (msg == null) {
getWiki().prepareResources(this);
msg = ((XWikiMessageTool) get("msg"));
}
return msg;
}
public XWikiValidationStatus getValidationStatus()
{
return (XWikiValidationStatus) get("validation_status");
}
public void setValidationStatus(XWikiValidationStatus status)
{
put("validation_status", status);
}
public void addDisplayedField(String fieldname)
{
this.displayedFields.add(fieldname);
}
public List<String> getDisplayedFields()
{
return this.displayedFields;
}
/**
* Returns the list of TextArea fields that use the WYSIWYG editor. This list is automatically built when displaying
* TextArea properties.
*
* @deprecated since 8.2RC1 when we started using the Edit Module to load the configured WYSIWYG editor
* @return a string containing a comma-separated list of TextArea field names for which the WYSIWYG editor should be
* enabled
*/
@Deprecated
public String getEditorWysiwyg()
{
return (String) get("editor_wysiwyg");
}
/**
* Drop permissions for the remainder of the request cycle.
* <p>
* After this is called:
* <ul>
* <li>1. {@link com.xpn.xwiki.api.Api#hasProgrammingRights()} will always return false.</li>
* <li>2. {@link com.xpn.xwiki.api.XWiki#getDocumentAsAuthor(org.xwiki.model.reference.DocumentReference)},
* {@link com.xpn.xwiki.api.XWiki#getDocumentAsAuthor(String)}, {@link com.xpn.xwiki.api.Document#saveAsAuthor()},
* {@link com.xpn.xwiki.api.Document#saveAsAuthor(String)},
* {@link com.xpn.xwiki.api.Document#saveAsAuthor(String, boolean)}, and
* {@link com.xpn.xwiki.api.Document#deleteAsAuthor()} will perform all of their actions as if the document's
* content author was the guest user (XWiki.XWikiGuest).</li>
* </ul>
* <p>
* In effect, no code requiring "programming right" will run, and if the document content author (see:
* {@link com.xpn.xwiki.api.Document#getContentAuthor()}) is a user who has "programming right", there will be no
* way for code following this call to save another document as this user, blessing it too with programming right.
* <p>
* Once dropped, permissions cannot be regained for the duration of the request.
* <p>
* If you are interested in a more flexable sandboxing method which sandboxed code only for the remainder of the
* rendering cycle, consider using {@link com.xpn.xwiki.api.Document#dropPermissions()}.
*
* @since 3.0M3
*/
public void dropPermissions()
{
this.put(XWikiConstant.DROPPED_PERMISSIONS, Boolean.TRUE);
}
/**
* @return true if {@link XWikiContext#dropPermissions()} has been called on this context, or if the
* {@link XWikiConstant#DROPPED_PERMISSIONS} key has been set in the
* {@link org.xwiki.context.ExecutionContext} for this thread. This is done by calling
* {Document#dropPermissions()}
*/
public boolean hasDroppedPermissions()
{
if (this.get(XWikiConstant.DROPPED_PERMISSIONS) != null) {
return true;
}
final Object dropped = getExecution().getContext().getProperty(XWikiConstant.DROPPED_PERMISSIONS);
if (dropped == null || !(dropped instanceof Integer)) {
return false;
}
return ((Integer) dropped) == System.identityHashCode(getExecution().getContext());
}
// Object
@Override
public synchronized XWikiContext clone()
{
XWikiContext context = (XWikiContext) super.clone();
// Make sure to have unique instances of the various caches
context.displayedFields = Collections.synchronizedList(new ArrayList<String>(this.displayedFields));
context.classCache = Collections.synchronizedMap(new LRUMap<DocumentReference, BaseClass>(this.classCacheSize));
return context;
}
/**
* There are several places where the XWiki context needs to be declared in the execution, so we add a common method
* here.
*
* @param executionContext The execution context.
*/
public void declareInExecutionContext(ExecutionContext executionContext)
{
if (!executionContext.hasProperty(XWikiContext.EXECUTIONCONTEXT_KEY)) {
executionContext.newProperty(XWikiContext.EXECUTIONCONTEXT_KEY).initial(this).inherited().declare();
} else {
executionContext.setProperty(XWikiContext.EXECUTIONCONTEXT_KEY, this);
}
}
/**
* @return the reference of the user being used to check script and programming right (i.e. the author of the
* current script)
* @since 8.3M2
*/
public DocumentReference getAuthorReference()
{
XWikiDocument sdoc = (XWikiDocument) get("sdoc");
if (sdoc == null) {
sdoc = getDoc();
}
return sdoc != null ? sdoc.getContentAuthorReference() : getUserReference();
}
}