/*
* 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.celements.web.plugin.cmd;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;
import org.xwiki.component.manager.ComponentLookupException;
import org.xwiki.model.reference.DocumentReference;
import com.celements.pagetype.cmd.PageTypeCommand;
import com.celements.sajson.Builder;
import com.celements.web.service.IWebUtilsService;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.api.Document;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.web.Utils;
public class ExternalJavaScriptFilesCommand {
public static final String JAVA_SCRIPT_EXTERNAL_FILES_CLASS_DOC = "ExternalFiles";
public static final String JAVA_SCRIPT_EXTERNAL_FILES_CLASS_SPACE = "JavaScript";
public static final String JAVA_SCRIPT_EXTERNAL_FILES_CLASS = JAVA_SCRIPT_EXTERNAL_FILES_CLASS_SPACE
+ "." + JAVA_SCRIPT_EXTERNAL_FILES_CLASS_DOC;
private static Log LOGGER = LogFactory.getFactory().getInstance(
ExternalJavaScriptFilesCommand.class);
private XWikiContext context;
private Set<String> extJSfileSet;
private Set<String> extJSAttUrlSet;
private List<String> extJSfileList;
private List<String> extJSnotFoundList;
private boolean displayedAll = false;
private AttachmentURLCommand attUrlCmd_injected = null;
public ExternalJavaScriptFilesCommand(XWikiContext context) {
this.context = context;
extJSfileSet = new HashSet<String>();
extJSAttUrlSet = new HashSet<String>();
extJSfileList = new Vector<String>();
extJSnotFoundList = new Vector<String>();
}
public String addLazyExtJSfile(String jsFile) {
return addLazyExtJSfile(jsFile, null);
}
public String addLazyExtJSfile(String jsFile, String action) {
return addLazyExtJSfile(jsFile, action, null);
}
public String addLazyExtJSfile(String jsFile, String action, String params) {
String attUrl;
if (!StringUtils.isEmpty(action)) {
attUrl = getAttUrlCmd().getAttachmentURL(jsFile, action, context);
} else {
attUrl = getAttUrlCmd().getAttachmentURL(jsFile, context);
}
if (!StringUtils.isEmpty(params)) {
if (attUrl.indexOf("?") > -1) {
attUrl += "&" + params;
} else {
attUrl += "?" + params;
}
}
Builder jsonBuilder = new Builder();
jsonBuilder.openDictionary();
jsonBuilder.addStringProperty("fullURL", attUrl);
jsonBuilder.openProperty("initLoad");
jsonBuilder.addBoolean(true);
jsonBuilder.closeDictionary();
return "<span class='cel_lazyloadJS' style='display: none;'>" + jsonBuilder.getJSON()
+ "</span>";
}
public String addExtJSfileOnce(String jsFile) {
return addExtJSfileOnce(jsFile, null);
}
public String addExtJSfileOnce(String jsFile, String action) {
return addExtJSfileOnce(jsFile, action, null);
}
public String addExtJSfileOnce(String jsFile, String action, String params) {
if (!extJSAttUrlSet.contains(jsFile)) {
if (getAttUrlCmd().isAttachmentLink(jsFile) || getAttUrlCmd().isOnDiskLink(jsFile)) {
extJSAttUrlSet.add(jsFile);
}
String attUrl;
if (!StringUtils.isEmpty(action)) {
attUrl = getAttUrlCmd().getAttachmentURL(jsFile, action, context);
} else {
attUrl = getAttUrlCmd().getAttachmentURL(jsFile, context);
}
if (!StringUtils.isEmpty(params)) {
if (attUrl.indexOf("?") > -1) {
attUrl += "&" + params;
} else {
attUrl += "?" + params;
}
}
return addExtJSfileOnce_internal(jsFile, attUrl);
}
return "";
}
private String addExtJSfileOnce_internal(String jsFile, String jsFileUrl) {
String jsIncludes2 = "";
if (jsFileUrl == null) {
if (!extJSfileSet.contains(jsFile)) {
jsIncludes2 = "<!-- WARNING: js-file not found: " + jsFile + "-->";
extJSfileSet.add(jsFile);
extJSnotFoundList.add(jsIncludes2);
}
} else {
if (!extJSfileSet.contains(jsFileUrl)) {
jsIncludes2 = getExtStringForJsFile(jsFileUrl);
extJSfileSet.add(jsFileUrl);
extJSfileList.add(jsFileUrl);
}
}
if (!displayedAll) {
jsIncludes2 = "";
}
return jsIncludes2;
}
AttachmentURLCommand getAttUrlCmd() {
if (attUrlCmd_injected != null) {
return attUrlCmd_injected;
}
return new AttachmentURLCommand();
}
void injectAttUrlCmd(AttachmentURLCommand attUrlCmd) {
attUrlCmd_injected = attUrlCmd;
}
void injectDisplayAll(boolean displayedAll) {
this.displayedAll = displayedAll;
}
String getExtStringForJsFile(String jsFile) {
return "<script type=\"text/javascript\" src=\"" + StringEscapeUtils.escapeHtml(jsFile)
+ "\"></script>";
}
public String getAllExternalJavaScriptFiles() throws XWikiException {
VelocityContext vcontext = ((VelocityContext) context.get("vcontext"));
if ((vcontext != null) && vcontext.containsKey("skin_doc")) {
addAllExtJSfilesFromDoc(context.getWiki().getDocument(getWebUtils().resolveDocumentReference(
((Document) vcontext.get("skin_doc")).getFullName()), context));
}
addAllExtJSfilesFromDoc(context.getWiki().getDocument(new DocumentReference(
context.getDatabase(), "XWiki", "XWikiPreferences"), context));
addAllExtJSfilesFromDoc(context.getWiki().getDocument(new DocumentReference(
context.getDatabase(),
context.getDoc().getDocumentReference().getLastSpaceReference().getName(),
"WebPreferences"), context));
addAllExtJSfilesFromDoc(context.getDoc());
XWikiDocument pagetype = getPageTypeDoc(context.getDoc());
if (pagetype != null) {
addAllExtJSfilesFromDoc(pagetype);
}
notifyExtJavaScriptFileListener();
String jsIncludes = "";
for (String jsFile : extJSfileList) {
jsIncludes += getExtStringForJsFile(jsFile) + "\n";
}
for (String jsFileWarning : extJSnotFoundList) {
jsIncludes += jsFileWarning + "\n";
}
displayedAll = true;
return jsIncludes;
}
private void notifyExtJavaScriptFileListener() {
Map<String, IExtJSFilesListener> listenerMap = getListenerMap();
for (String jsfListenerKey : listenerMap.keySet()) {
listenerMap.get(jsfListenerKey).beforeAllExtFinish(this);
}
}
private Map<String, IExtJSFilesListener> getListenerMap() {
try {
return Utils.getComponent(IWebUtilsService.class).lookupMap(IExtJSFilesListener.class);
} catch (ComponentLookupException exp) {
LOGGER.error("Failed to get IExtJSFilesListener components.", exp);
}
return Collections.emptyMap();
}
private String addAllExtJSfilesFromDoc(XWikiDocument doc) {
String jsIncludes2 = "";
for (String jsFile : getJavaScriptExternalFilePaths(doc)) {
String addJSinclude = addExtJSfileOnce(jsFile);
if (!"".equals(addJSinclude)) {
jsIncludes2 = jsIncludes2 + addJSinclude + "\n";
}
}
return jsIncludes2;
}
private XWikiDocument getPageTypeDoc(XWikiDocument doc) throws XWikiException {
LOGGER.trace("entering with doc: '" + ((doc != null) ? doc.getDocumentReference() : "null")
+ "'");
XWikiDocument pagetypeDoc = null;
BaseObject obj = doc.getXObject(new DocumentReference(context.getDatabase(),
PageTypeCommand.PAGE_TYPE_CLASS_SPACE, PageTypeCommand.PAGE_TYPE_CLASS_DOC));
LOGGER.debug("Celements2.PageType object: '" + obj + "'");
if ((obj != null) && (obj instanceof BaseObject)) {
String pagetypeName = obj.getStringValue("page_type");
LOGGER.debug("PageType name is: '" + pagetypeName + "'");
if ((pagetypeName != null) && (!pagetypeName.equals(""))) {
pagetypeDoc = context.getWiki().getDocument(getWebUtils().resolveDocumentReference(
new PageTypeCommand().completePageTypeDocName(pagetypeName)), context);
}
}
LOGGER.trace("ending. PageType is: '" + ((pagetypeDoc != null)
? pagetypeDoc.getDocumentReference() : "null") + "'");
return pagetypeDoc;
}
private List<String> getJavaScriptExternalFilePaths(XWikiDocument doc) {
List<BaseObject> javaScriptFiles = doc.getXObjects(new DocumentReference(context.getDatabase(),
JAVA_SCRIPT_EXTERNAL_FILES_CLASS_SPACE, JAVA_SCRIPT_EXTERNAL_FILES_CLASS_DOC));
Vector<String> jsFiles = new Vector<String>();
if (javaScriptFiles != null) {
for (Object filepath : javaScriptFiles) {
if ((filepath != null) && (filepath instanceof BaseObject)) {
BaseObject filepathObj = (BaseObject) filepath;
if (!"".equals(filepathObj.getStringValue("filepath"))) {
jsFiles.add(filepathObj.getStringValue("filepath"));
}
}
}
}
return jsFiles;
}
private IWebUtilsService getWebUtils() {
return Utils.getComponent(IWebUtilsService.class);
}
}