/*
* 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.render;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.script.ScriptContext;
import org.slf4j.Logger;
import org.xwiki.component.annotation.Component;
import org.xwiki.rendering.syntax.SyntaxFactory;
import org.xwiki.script.ScriptContextInitializer;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.api.Context;
import com.xpn.xwiki.api.Document;
import com.xpn.xwiki.api.XWiki;
import com.xpn.xwiki.doc.XWikiDocument;
/**
* Inject in the {@link ScriptContext} the XWiki context and the {@link XWiki} instance for backward compatibility.
* <p>
* Bridge. To be removed later.
*
* @version $Id: 1902299cc516cb97606214cfad4dd92f23848887 $
*/
@Component
@Named("xwiki")
@Singleton
public class XWikiScriptContextInitializer implements ScriptContextInitializer
{
@Inject
private Logger logger;
@Inject
private SyntaxFactory syntaxFactory;
@Inject
private Provider<XWikiContext> xcontextProvider;
@Override
public void initialize(ScriptContext scriptContext)
{
XWikiContext xcontext = this.xcontextProvider.get();
if (scriptContext.getAttribute("util") == null) {
// Put the Util API in the Script context.
scriptContext.setAttribute("util", new com.xpn.xwiki.api.Util(xcontext.getWiki(), xcontext),
ScriptContext.ENGINE_SCOPE);
// We put the com.xpn.xwiki.api.XWiki object into the context and not the com.xpn.xwiki.XWiki one which is
// for internal use only. In this manner we control what the user can access.
scriptContext.setAttribute("xwiki", new XWiki(xcontext.getWiki(), xcontext), ScriptContext.ENGINE_SCOPE);
scriptContext.setAttribute("request", xcontext.getRequest(), ScriptContext.ENGINE_SCOPE);
scriptContext.setAttribute("response", xcontext.getResponse(), ScriptContext.ENGINE_SCOPE);
// We put the com.xpn.xwiki.api.Context object into the context and not the com.xpn.xwiki.XWikiContext one
// which is for internal use only. In this manner we control what the user can access.
// We use "xcontext" because "context" is a reserved binding in JSR-223 specifications
scriptContext.setAttribute("xcontext", new Context(xcontext), ScriptContext.ENGINE_SCOPE);
// Make the Syntax Factory component available from Script.
// TODO: We need to decide how we want to expose components in general and how to protect users from
// "dangerous" apis.
// TODO: Actually this should probably be moved to legacy, we have a rendering ScriptService now
scriptContext.setAttribute("syntaxFactory", this.syntaxFactory, ScriptContext.ENGINE_SCOPE);
}
// Current document
Document docAPI = null;
XWikiDocument doc = xcontext.getDoc();
if (doc != null) {
docAPI = setDocument(scriptContext, "doc", doc, xcontext);
XWikiDocument tdoc = (XWikiDocument) xcontext.get("tdoc");
if (tdoc == null) {
try {
tdoc = doc.getTranslatedDocument(xcontext);
} catch (XWikiException e) {
this.logger.warn("Failed to retrieve the translated document for [{}]. "
+ "Continue using the default translation.", doc.getDocumentReference(), e);
tdoc = doc;
}
}
Document tdocAPI = setDocument(scriptContext, "tdoc", tdoc, xcontext);
XWikiDocument cdoc = (XWikiDocument) xcontext.get("cdoc");
if (cdoc == null) {
Document cdocAPI = tdocAPI;
if (cdocAPI == null) {
cdocAPI = docAPI;
}
scriptContext.setAttribute("cdoc", cdocAPI, ScriptContext.ENGINE_SCOPE);
} else {
setDocument(scriptContext, "cdoc", cdoc, xcontext);
}
}
// Current secure document
XWikiDocument sdoc = (XWikiDocument) xcontext.get("sdoc");
if (sdoc == null) {
scriptContext.setAttribute("sdoc", docAPI, ScriptContext.ENGINE_SCOPE);
} else {
setDocument(scriptContext, "sdoc", sdoc, xcontext);
}
// Miscellaneous
scriptContext.setAttribute("locale", xcontext.getLocale(), ScriptContext.ENGINE_SCOPE);
}
private Document setDocument(ScriptContext scriptContext, String key, XWikiDocument document, XWikiContext xcontext)
{
// Change the Document instance only if it's not already wrapping the same XWikiDocument (otherwise we might
// loose modifications made in a previous script and not yet saved)
Document apiDocument = (Document) scriptContext.getAttribute(key);
if (apiDocument == null || !apiDocument.same(document)) {
apiDocument = document.newDocument(xcontext);
scriptContext.setAttribute(key, apiDocument, ScriptContext.ENGINE_SCOPE);
}
return apiDocument;
}
}