diff --git a/config/alfresco/web-client-config-wcm.xml b/config/alfresco/web-client-config-wcm.xml
index 393e6c1f97..c9e0e71651 100644
--- a/config/alfresco/web-client-config-wcm.xml
+++ b/config/alfresco/web-client-config-wcm.xml
@@ -81,6 +81,32 @@
javascript-class-name="alfresco.xforms.FilePicker">
wcm:avmcontent,wcm:avmfolder
+
+ wcm:avmcontent,wcm:avmfolder
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/web/bean/wcm/FilePickerBean.java b/source/java/org/alfresco/web/bean/wcm/FilePickerBean.java
index 7421ab220d..08e468b6b3 100644
--- a/source/java/org/alfresco/web/bean/wcm/FilePickerBean.java
+++ b/source/java/org/alfresco/web/bean/wcm/FilePickerBean.java
@@ -1,411 +1,953 @@
-/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program 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 General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * As a special exception to the terms and conditions of version 2.0 of
- * the GPL, you may redistribute this Program in connection with Free/Libre
- * and Open Source Software ("FLOSS") applications as described in Alfresco's
- * FLOSS exception. You should have recieved a copy of the text describing
- * the FLOSS exception, and it is also available here:
- * http://www.alfresco.com/legal/licensing"
- */
-package org.alfresco.web.bean.wcm;
-
-import java.io.InputStream;
-import java.io.Serializable;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import javax.faces.context.ExternalContext;
-import javax.faces.context.FacesContext;
-import javax.faces.context.ResponseWriter;
-import javax.servlet.http.HttpServletRequest;
-
-import org.alfresco.model.ContentModel;
-import org.alfresco.model.WCMModel;
-import org.alfresco.repo.avm.AVMNodeConverter;
-import org.alfresco.repo.content.MimetypeMap;
-import org.alfresco.repo.domain.PropertyValue;
-import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
-import org.alfresco.service.cmr.avm.AVMService;
-import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.namespace.NamespaceService;
-import org.alfresco.service.namespace.QName;
-import org.alfresco.web.app.Application;
-import org.alfresco.web.app.servlet.ajax.InvokeCommand;
-import org.alfresco.web.bean.FileUploadBean;
-import org.alfresco.web.bean.repository.Repository;
-import org.alfresco.web.forms.XMLUtil;
-import org.alfresco.web.ui.common.Utils;
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.util.FileCopyUtils;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-/**
- * Bean for interacting with the file picker widget using ajax requests.
- */
-public class FilePickerBean implements Serializable
-{
- private static final long serialVersionUID = -8301307105698624196L;
-
- private static final Log LOGGER = LogFactory.getLog(FilePickerBean.class);
- private final Set uploads = new HashSet();
-
- private AVMBrowseBean avmBrowseBean;
- transient private AVMService avmService;
- transient private NamespaceService namespaceService;
-
- public FilePickerBean()
- {
- }
-
- public void clearUploadedFiles()
- {
- this.uploads.clear();
- }
-
- public NodeRef[] getUploadedFiles()
- {
- return (NodeRef[])this.uploads.toArray(new NodeRef[this.uploads.size()]);
- }
-
- /**
- * @param avmBrowseBean the avmBrowseBean to set.
- */
- public void setAvmBrowseBean(final AVMBrowseBean avmBrowseBean)
- {
- this.avmBrowseBean = avmBrowseBean;
- }
-
- /**
- * @param avmService the avmService to set.
- */
- public void setAvmService(final AVMService avmService)
- {
- this.avmService = avmService;
- }
-
- private AVMService getAvmService()
- {
- if (avmService == null)
- {
- avmService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getAVMService();
- }
- return avmService;
- }
-
- /**
- * @param namespaceService the namespaceService to set.
- */
- public void setNamespaceService(final NamespaceService namespaceService)
- {
- this.namespaceService = namespaceService;
- }
-
- private NamespaceService getNamespaceService()
- {
- if (namespaceService == null)
- {
- namespaceService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNamespaceService();
- }
- return namespaceService;
- }
-
- /**
- * Provides data for a file picker widget.
- */
- @InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_XML)
- public void getFilePickerData()
- throws Exception
- {
- final FacesContext facesContext = FacesContext.getCurrentInstance();
- final ExternalContext externalContext = facesContext.getExternalContext();
-
- String currentPath = (String)externalContext.getRequestParameterMap().get("currentPath");
- if (currentPath == null)
- {
- currentPath = this.getCurrentAVMPath();
- }
- else
- {
- final String previewStorePath =
- AVMUtil.getCorrespondingPathInPreviewStore(this.getCurrentAVMPath());
- currentPath = AVMUtil.buildPath(previewStorePath,
- currentPath,
- AVMUtil.PathRelation.WEBAPP_RELATIVE);
- }
-
- final QName[] selectableTypes =
- this.getSelectableTypes((String[])externalContext.getRequestParameterValuesMap().get("selectableTypes"));
- final Pattern[] filterMimetypes =
- this.getFilterMimetypes((String[])externalContext.getRequestParameterValuesMap().get("filterMimetypes"));
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug(this + ".getFilePickerData(path = " + currentPath +
- ", selectableTypes = [" + StringUtils.join(selectableTypes, ",") +
- "], filterMimetypes = [" + StringUtils.join(filterMimetypes, ",") +
- "])");
- }
-
- final Document result = XMLUtil.newDocument();
- final Element filePickerDataElement = result.createElement("file-picker-data");
- result.appendChild(filePickerDataElement);
-
-
- final AVMNodeDescriptor currentNode = this.getAvmService().lookup(-1, currentPath);
- if (currentNode == null)
- {
- currentPath = AVMUtil.getWebappRelativePath(currentPath);
-
- filePickerDataElement.setAttribute("error",
- MessageFormat.format(Application.getMessage(facesContext, "error_not_found"),
- currentPath.substring(currentPath.lastIndexOf("/") + 1,
- currentPath.length()),
- (currentPath.lastIndexOf("/") == 0
- ? "/"
- : currentPath.substring(0, currentPath.lastIndexOf("/")))));
- currentPath = this.getCurrentAVMPath();
- }
- else if (! currentNode.isDirectory())
- {
- currentPath = AVMNodeConverter.SplitBase(currentPath)[0];
- }
-
- Element e = result.createElement("current-node");
- e.setAttribute("avmPath", currentPath);
- e.setAttribute("webappRelativePath",
- AVMUtil.getWebappRelativePath(currentPath));
- e.setAttribute("type", "directory");
- e.setAttribute("image", "/images/icons/space_small.gif");
- filePickerDataElement.appendChild(e);
-
- for (final Map.Entry entry :
- this.getAvmService().getDirectoryListing(-1, currentPath).entrySet())
- {
- if (!entry.getValue().isDirectory() && filterMimetypes.length != 0)
- {
- final String contentMimetype = this.getAvmService().getContentDataForRead(entry.getValue()).getMimetype();
- boolean matched = false;
- for (final Pattern p : filterMimetypes)
- {
- matched = p.matcher(contentMimetype).matches();
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug(p + ".matches(" + contentMimetype + ") = " + matched);
- }
- if (matched)
- {
- break;
- }
- }
- if (!matched)
- {
- continue;
- }
- }
- e = result.createElement("child-node");
- e.setAttribute("avmPath", entry.getValue().getPath());
- e.setAttribute("webappRelativePath",
- AVMUtil.getWebappRelativePath(entry.getValue().getPath()));
- e.setAttribute("type", entry.getValue().isDirectory() ? "directory" : "file");
- e.setAttribute("image", (entry.getValue().isDirectory()
- ? "/images/icons/space_small.gif"
- : Utils.getFileTypeImage(facesContext,
- entry.getValue().getName(),
- true)));
-
- boolean selectable = false;
- // faking this for now since i can't figure out how to efficiently get the type
- // qname from the avmservice
- for (final QName typeQName : selectableTypes)
- {
- selectable = selectable || (WCMModel.TYPE_AVM_FOLDER.equals(typeQName) &&
- entry.getValue().isDirectory());
- selectable = selectable || (WCMModel.TYPE_AVM_CONTENT.equals(typeQName) &&
- !entry.getValue().isDirectory());
- }
- e.setAttribute("selectable", Boolean.toString(selectable));
- filePickerDataElement.appendChild(e);
- }
-
- final ResponseWriter out = facesContext.getResponseWriter();
- XMLUtil.print(result, out);
- }
-
- @InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
- public void uploadFile()
- throws Exception
- {
- LOGGER.debug(this + ".uploadFile()");
- final FacesContext facesContext = FacesContext.getCurrentInstance();
- final ExternalContext externalContext = facesContext.getExternalContext();
- final HttpServletRequest request = (HttpServletRequest)
- externalContext.getRequest();
-
- final ServletFileUpload upload =
- new ServletFileUpload(new DiskFileItemFactory());
- upload.setHeaderEncoding("UTF-8");
- final List fileItems = upload.parseRequest(request);
- final FileUploadBean bean = new FileUploadBean();
- String uploadId = null;
- String currentPath = null;
- String filename = null;
- String returnPage = null;
- InputStream fileInputStream = null;
- for (FileItem item : fileItems)
- {
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("item = " + item);
- }
- if (item.isFormField() && item.getFieldName().equals("upload-id"))
- {
- uploadId = item.getString();
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("uploadId is " + uploadId);
- }
- }
- if (item.isFormField() && item.getFieldName().equals("return-page"))
- {
- returnPage = item.getString();
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("returnPage is " + returnPage);
- }
- }
- else if (item.isFormField() && item.getFieldName().equals("currentPath"))
- {
- final String previewStorePath =
- AVMUtil.getCorrespondingPathInPreviewStore(this.getCurrentAVMPath());
- currentPath = AVMUtil.buildPath(previewStorePath,
- item.getString(),
- AVMUtil.PathRelation.WEBAPP_RELATIVE);
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("currentPath is " + currentPath);
- }
- }
- else
- {
- filename = FilenameUtils.getName(item.getName());
- fileInputStream = item.getInputStream();
-
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("uploading file " + filename);
- }
- }
- }
-
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("saving file " + filename + " to " + currentPath);
- }
-
- try
- {
- FileCopyUtils.copy(fileInputStream,
- this.getAvmService().createFile(currentPath, filename));
- final Map props = new HashMap(1, 1.0f);
- props.put(ContentModel.PROP_TITLE, new PropertyValue(DataTypeDefinition.TEXT, filename));
-// props.put(ContentModel.PROP_DESCRIPTION,
-// new PropertyValue(DataTypeDefinition.TEXT,
-// "Uploaded for form " + this.xformsSession.getForm().getName()));
- this.getAvmService().setNodeProperties(currentPath + "/" + filename, props);
- this.getAvmService().addAspect(currentPath + "/" + filename, ContentModel.ASPECT_TITLED);
-
- this.uploads.add(AVMNodeConverter.ToNodeRef(-1, currentPath + "/" + filename));
- returnPage = returnPage.replace("${_FILE_TYPE_IMAGE}",
- Utils.getFileTypeImage(facesContext, filename, true));
- }
- catch (Exception e)
- {
- LOGGER.debug(e.getMessage(), e);
- returnPage = returnPage.replace("${_UPLOAD_ERROR}", e.getMessage());
- }
-
- LOGGER.debug("upload complete. sending response: " + returnPage);
- final Document result = XMLUtil.newDocument();
- final Element htmlEl = result.createElement("html");
- result.appendChild(htmlEl);
- final Element bodyEl = result.createElement("body");
- htmlEl.appendChild(bodyEl);
-
- final Element scriptEl = result.createElement("script");
- bodyEl.appendChild(scriptEl);
- scriptEl.setAttribute("type", "text/javascript");
- final Node scriptText = result.createTextNode(returnPage);
- scriptEl.appendChild(scriptText);
-
- final ResponseWriter out = facesContext.getResponseWriter();
- XMLUtil.print(result, out);
- }
-
- private String getCurrentAVMPath()
- {
- final AVMNode node = this.avmBrowseBean.getAvmActionNode();
- if (node == null)
- {
- return this.avmBrowseBean.getCurrentPath();
- }
-
- final String result = node.getPath();
- return node.isDirectory() ? result : AVMNodeConverter.SplitBase(result)[0];
- }
-
- private QName[] getSelectableTypes(final String[] selectableTypes)
- {
- final QName[] result = (selectableTypes == null
- ? new QName[] { WCMModel.TYPE_AVM_CONTENT, WCMModel.TYPE_AVM_FOLDER }
- : new QName[selectableTypes.length]);
-
- if (selectableTypes != null)
- {
- for (int i = 0; i < selectableTypes.length; i++)
- {
- result[i] = QName.resolveToQName(this.getNamespaceService(), selectableTypes[i]);
- }
- }
- return result;
- }
-
- private Pattern[] getFilterMimetypes(final String[] filterMimetypes)
- {
- final Pattern[] result = filterMimetypes == null ? new Pattern[0] : new Pattern[filterMimetypes.length];
- if (filterMimetypes != null)
- {
- for (int i = 0; i < filterMimetypes.length; i++)
- {
- result[i] = Pattern.compile(filterMimetypes[i].replaceAll("\\*", "\\.*").replaceAll("\\/", "\\\\/"));
- }
- }
- return result;
- }
-}
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.web.bean.wcm;
+
+import java.io.InputStream;
+import java.io.Serializable;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.servlet.http.HttpServletRequest;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.model.ContentModel;
+import org.alfresco.model.WCMModel;
+import org.alfresco.repo.avm.AVMNodeConverter;
+import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.repo.domain.PropertyValue;
+import org.alfresco.repo.security.permissions.AccessDeniedException;
+import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
+import org.alfresco.service.cmr.avm.AVMService;
+import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.ContentReader;
+import org.alfresco.service.cmr.repository.ContentService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.cmr.search.ResultSet;
+import org.alfresco.service.cmr.search.ResultSetRow;
+import org.alfresco.service.cmr.search.SearchService;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.service.namespace.RegexQNamePattern;
+import org.alfresco.util.ISO9075;
+import org.alfresco.util.Pair;
+import org.alfresco.web.app.Application;
+import org.alfresco.web.app.servlet.ajax.InvokeCommand;
+import org.alfresco.web.bean.FileUploadBean;
+import org.alfresco.web.bean.repository.Node;
+import org.alfresco.web.bean.repository.Repository;
+import org.alfresco.web.bean.repository.User;
+import org.alfresco.web.forms.XMLUtil;
+import org.alfresco.web.ui.common.Utils;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+import org.dom4j.XPath;
+import org.dom4j.io.SAXReader;
+import org.springframework.util.FileCopyUtils;
+
+/**
+ * Bean for interacting with the file picker widget using ajax requests.
+ */
+public class FilePickerBean implements Serializable {
+ private static final Log LOGGER = LogFactory.getLog(FilePickerBean.class);
+
+ private static final String SAVED_SEARCH_QUERY_XPATH = "/search/query";
+ private static final String CDATA_START_DELIM = "![CDATA[";
+ private static final String CDATA_END_DELIM = "]]";
+
+ // possible values for the saved_search_context parameter
+ private static final String SAVED_SEARCHES_CONTEXT_USER = "user";
+ private static final String SAVED_SEARCHES_CONTEXT_GLOBAL = "global";
+
+ // parameter names
+ private static final String PARAM_FOLDER_RESTRICTION = "folderRestriction";
+ private static final String PARAM_SAVED_SEARCH_NAME = "savedSearchName";
+ private static final String PARAM_SAVED_SEARCH_CONTEXT = "savedSearchContext";
+ private static final String PARAM_SELECTABLE_TYPES = "selectableTypes";
+ private static final String PARAM_FILTER_MIME_TYPES = "filterMimetypes";
+ private static final String PARAM_CURRENT_PATH = "currentPath";
+
+ private final Set uploads = new HashSet();
+
+ // property instance variables
+ private AVMBrowseBean avmBrowseBean;
+ transient private AVMService avmService;
+ transient private NamespaceService namespaceService;
+ transient private SearchService searchService;
+ transient private NodeService nodeService;
+ transient private DictionaryService dictionaryService;
+ transient private ContentService contentService;
+
+ /** cached reference to the global saved searches folder */
+ private NodeRef globalSearchesRef = null;
+
+ /** cached reference to the current users saved searches folder */
+ private NodeRef userSearchesRef = null;
+
+ public FilePickerBean() {
+ }
+
+ public void clearUploadedFiles() {
+ this.uploads.clear();
+ }
+
+ public NodeRef[] getUploadedFiles() {
+ return (NodeRef[]) this.uploads.toArray(new NodeRef[this.uploads.size()]);
+ }
+
+ /**
+ * Set avmBrowseBean property for this bean
+ *
+ * @param avmBrowseBean
+ * the AVMBrowseBean object to pass into this property
+ */
+ public void setAvmBrowseBean(final AVMBrowseBean avmBrowseBean) {
+ this.avmBrowseBean = avmBrowseBean;
+ }
+
+ /**
+ * Get avmBrowseBean property for this bean
+ *
+ * @return avmBrowseBean property value for this bean
+ */
+ public AVMBrowseBean getAvmBrowseBean() {
+ return this.avmBrowseBean;
+ }
+
+ /**
+ * Set avmService property for this bean
+ *
+ * @param avmService
+ * the avmService object to pass into this property
+ */
+ public void setAvmService(final AVMService avmService) {
+ this.avmService = avmService;
+ }
+
+ /**
+ * Get avmService property for this bean
+ *
+ * @return avmService property value for this bean
+ */
+ public AVMService getAvmService() {
+ if (this.avmService == null) {
+ this.avmService = Repository.getServiceRegistry(
+ FacesContext.getCurrentInstance()).getAVMService();
+ }
+ return this.avmService;
+ }
+
+ /**
+ * Set nodeService property value for this bean
+ *
+ * @param nodeService
+ * the NodeService object to pass into this property
+ */
+ public void setNodeService(final NodeService nodeService) {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * Get nodeService property for this bean
+ *
+ * @return nodeService property value for this bean
+ */
+ public NodeService getNodeService() {
+ if (this.nodeService == null) {
+ this.nodeService = Repository.getServiceRegistry(
+ FacesContext.getCurrentInstance()).getNodeService();
+ }
+ return this.nodeService;
+ }
+
+ /**
+ * Set searchService property for this bean
+ *
+ * @param searchService
+ * the SearchService object to pass into this property
+ */
+ public void setSearchService(final SearchService searchService) {
+ this.searchService = searchService;
+ }
+
+ /**
+ * Get SearchService property for this bean
+ *
+ * @return searchService property value for this bean
+ */
+ public SearchService getSearchService() {
+ if (this.searchService == null) {
+ this.searchService = Repository.getServiceRegistry(
+ FacesContext.getCurrentInstance()).getSearchService();
+ }
+ return this.searchService;
+ }
+
+ /**
+ * Set dictionaryService property value for this bean
+ *
+ * @param dictionaryService
+ * the DictionaryService object to pass into this property
+ */
+ public void setDictionaryService(final DictionaryService dictionaryService) {
+ this.dictionaryService = dictionaryService;
+ }
+
+ /**
+ * Get dictionaryService property for this bean
+ *
+ * @return dictionaryService property value for this bean
+ */
+ public DictionaryService getDictionaryService() {
+ if (this.dictionaryService == null) {
+ this.dictionaryService = Repository.getServiceRegistry(
+ FacesContext.getCurrentInstance()).getDictionaryService();
+ }
+ return this.dictionaryService;
+ }
+
+ /**
+ * Set namespaceService property for this bean
+ *
+ * @param namespaceService
+ * the NamespaceService object to pass into this property
+ */
+ public void setNamespaceService(final NamespaceService namespaceService) {
+ this.namespaceService = namespaceService;
+ }
+
+ /**
+ * Get the namespaceService property value for this bean
+ *
+ * @return namespaceService property value for this bean
+ */
+ public NamespaceService getNamespaceService() {
+ if (this.namespaceService == null) {
+ this.namespaceService = Repository.getServiceRegistry(
+ FacesContext.getCurrentInstance()).getNamespaceService();
+ }
+ return this.namespaceService;
+ }
+
+ /**
+ * Set contentService property
+ *
+ * @param contentService
+ * the ContentService object to pass into this property
+ */
+ public void setContentService(final ContentService contentService) {
+ this.contentService = contentService;
+ }
+
+ /**
+ * Get contentService property value for this bean
+ *
+ * @return contentService property value for this bean
+ */
+ public ContentService getContentService() {
+ if (this.contentService == null) {
+ this.contentService = Repository.getServiceRegistry(
+ FacesContext.getCurrentInstance()).getContentService();
+ }
+ return this.contentService;
+ }
+
+ /**
+ * Provides data for a file picker widget.
+ */
+ @InvokeCommand.ResponseMimetype(value = MimetypeMap.MIMETYPE_XML)
+ public void getFilePickerData() throws Exception {
+ final FacesContext facesContext = FacesContext.getCurrentInstance();
+ final ExternalContext externalContext = facesContext.getExternalContext();
+
+ String currentPath = null;
+
+ // get 'folderRestriction' parameter value
+ // - expecting an absolute AVM folder path to be held in this parameter
+ String folderPathRestriction = null;
+ String[] folderPathRestrictionParam = (String[]) externalContext
+ .getRequestParameterValuesMap().get(PARAM_FOLDER_RESTRICTION);
+ if ((folderPathRestrictionParam != null)
+ && (folderPathRestrictionParam.length != 0)) {
+ folderPathRestriction = folderPathRestrictionParam[0];
+ }
+
+ // if folder restriction path is neither null nor an empty string, then
+ // assign it to current path
+ if ((folderPathRestriction != null)
+ && (folderPathRestriction.length() > 0)) {
+ currentPath = folderPathRestriction;
+ }
+ // else set current path to current path parameter
+ else {
+ String currentPathParam = (String) externalContext
+ .getRequestParameterMap().get(PARAM_CURRENT_PATH);
+
+ // if current path parameter null then set current path to the current
+ // AVM path
+ if ((currentPathParam == null)) {
+ currentPath = this.getCurrentAVMPath();
+ }
+ // else set current path to value help in current path
+ // parameter (converted to absolute AVM path)
+ else {
+ final String previewStorePath = AVMUtil
+ .getCorrespondingPathInPreviewStore(this.getCurrentAVMPath());
+ currentPath = AVMUtil.buildPath(previewStorePath, currentPathParam,
+ AVMUtil.PathRelation.WEBAPP_RELATIVE);
+ }
+ }
+
+ // get savedSearchName parameter value
+ String savedSearchName = null;
+ String[] savedSearchNameParam = (String[]) externalContext
+ .getRequestParameterValuesMap().get(PARAM_SAVED_SEARCH_NAME);
+ if ((savedSearchNameParam != null) && (savedSearchNameParam.length != 0)) {
+ savedSearchName = savedSearchNameParam[0];
+ }
+
+ // get savedSearchContext parameter value
+ String savedSearchContext = null;
+ String[] savedSearchContextParam = (String[]) externalContext
+ .getRequestParameterValuesMap().get(PARAM_SAVED_SEARCH_CONTEXT);
+ if ((savedSearchContextParam != null)
+ && (savedSearchContextParam.length != 0)) {
+ savedSearchContext = savedSearchContextParam[0];
+ }
+
+ // get selectableTypes parameter value
+ final QName[] selectableTypes = this
+ .getSelectableTypes((String[]) externalContext
+ .getRequestParameterValuesMap().get(PARAM_SELECTABLE_TYPES));
+
+ // / get filterMimetypes parameter value
+ final Pattern[] filterMimetypes = this
+ .getFilterMimetypes((String[]) externalContext
+ .getRequestParameterValuesMap().get(PARAM_FILTER_MIME_TYPES));
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug(this + ".getFilePickerData(path = " + currentPath
+ + ", selectableTypes = ["
+ + StringUtils.join(selectableTypes, ",")
+ + "], filterMimetypes = ["
+ + StringUtils.join(filterMimetypes, ",") + "])");
+ }
+
+ // create file picker data XML document to return
+ // and append file picker data element to it
+ final org.w3c.dom.Document filePickerDataDoc = XMLUtil.newDocument();
+ final org.w3c.dom.Element filePickerDataElement = filePickerDataDoc
+ .createElement("file-picker-data");
+ filePickerDataDoc.appendChild(filePickerDataElement);
+
+ // make sure that there is a node associated with current path
+ // if not, set an applicable error message as an attribute on
+ // the file picker data element
+ final AVMNodeDescriptor currentNode = this.getAvmService().lookup(-1,
+ currentPath);
+ if (currentNode == null) {
+ currentPath = AVMUtil.getWebappRelativePath(currentPath);
+
+ filePickerDataElement.setAttribute("error", MessageFormat.format(
+ Application.getMessage(facesContext, "error_not_found"),
+ currentPath.substring(currentPath.lastIndexOf("/") + 1,
+ currentPath.length()),
+ (currentPath.lastIndexOf("/") == 0 ? "/" : currentPath
+ .substring(0, currentPath.lastIndexOf("/")))));
+
+ // TODO (Glen): Ariel's code - What on earth is this doing here?
+ // It is overriding the value assigned two statements above!!!
+ currentPath = this.getCurrentAVMPath();
+ }
+ // if the path points to a file instead of a directory,
+ // then make sure that the current path points to
+ // just the directory part of the path
+ else if (!currentNode.isDirectory()) {
+ currentPath = AVMNodeConverter.SplitBase(currentPath)[0];
+ }
+
+ // create current-node element representing node for current path
+ // and append it to the file picker data element
+ org.w3c.dom.Element currentNodeElement = filePickerDataDoc
+ .createElement("current-node");
+ currentNodeElement.setAttribute("avmPath", currentPath);
+ currentNodeElement.setAttribute("webappRelativePath", AVMUtil
+ .getWebappRelativePath(currentPath));
+ currentNodeElement.setAttribute("type", "directory");
+
+ // TODO (Glen): This was in Ariel's code. Is this the correct
+ // image to set?
+ currentNodeElement.setAttribute("image", "/images/icons/space_small.gif");
+
+ filePickerDataElement.appendChild(currentNodeElement);
+
+ // if saved search name and saved search context parameters supplied (i.e.
+ // not null),
+ // then get saved saved search node matching given name and context
+ if ((savedSearchName != null) && (savedSearchName.length() != 0)
+ && (savedSearchContext != null)
+ && (savedSearchContext.length() != 0)) {
+ // get node reference for named saved search in the given saved search
+ // context
+ NodeRef savedSearchNodeRef = getSavedSearches(savedSearchName,
+ savedSearchContext);
+
+ // run search to get content nodes returned in search result
+ List searchResultNodes = runSavedSearch(savedSearchNodeRef);
+
+ // add elements for content nodes from search results as child nodes
+ // of the file picker data element.
+ addAVMNodesToElement(filePickerDataDoc, filePickerDataElement,
+ searchResultNodes, selectableTypes, facesContext);
+ } else {
+ // add elements for child nodes of current path to file picker
+ // data element
+ addPathChildNodesToElement(filePickerDataDoc, filePickerDataElement,
+ currentPath, selectableTypes, filterMimetypes, facesContext);
+ }
+
+ final ResponseWriter out = facesContext.getResponseWriter();
+ XMLUtil.print(filePickerDataDoc, out);
+ }
+
+ @InvokeCommand.ResponseMimetype(value = MimetypeMap.MIMETYPE_HTML)
+ public void uploadFile() throws Exception {
+ LOGGER.debug(this + ".uploadFile()");
+ final FacesContext facesContext = FacesContext.getCurrentInstance();
+ final ExternalContext externalContext = facesContext.getExternalContext();
+ final HttpServletRequest request = (HttpServletRequest) externalContext
+ .getRequest();
+
+ final ServletFileUpload upload = new ServletFileUpload(
+ new DiskFileItemFactory());
+ upload.setHeaderEncoding("UTF-8");
+ final List fileItems = upload.parseRequest(request);
+ final FileUploadBean bean = new FileUploadBean();
+ String uploadId = null;
+ String currentPath = null;
+ String filename = null;
+ String returnPage = null;
+ InputStream fileInputStream = null;
+ for (FileItem item : fileItems) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("item = " + item);
+ }
+ if (item.isFormField() && item.getFieldName().equals("upload-id")) {
+ uploadId = item.getString();
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("uploadId is " + uploadId);
+ }
+ }
+ if (item.isFormField() && item.getFieldName().equals("return-page")) {
+ returnPage = item.getString();
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("returnPage is " + returnPage);
+ }
+ } else if (item.isFormField()
+ && item.getFieldName().equals("currentPath")) {
+ final String previewStorePath = AVMUtil
+ .getCorrespondingPathInPreviewStore(this.getCurrentAVMPath());
+ currentPath = AVMUtil.buildPath(previewStorePath, item.getString(),
+ AVMUtil.PathRelation.WEBAPP_RELATIVE);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("currentPath is " + currentPath);
+ }
+ } else {
+ filename = FilenameUtils.getName(item.getName());
+ fileInputStream = item.getInputStream();
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("uploading file " + filename);
+ }
+ }
+ }
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("saving file " + filename + " to " + currentPath);
+ }
+
+ try {
+ FileCopyUtils.copy(fileInputStream, this.getAvmService().createFile(
+ currentPath, filename));
+ final Map props = new HashMap(
+ 1, 1.0f);
+ props.put(ContentModel.PROP_TITLE, new PropertyValue(
+ DataTypeDefinition.TEXT, filename));
+ // props.put(ContentModel.PROP_DESCRIPTION,
+ // new PropertyValue(DataTypeDefinition.TEXT,
+ // "Uploaded for form " + this.xformsSession.getForm().getName()));
+ this.getAvmService().setNodeProperties(currentPath + "/" + filename,
+ props);
+ this.getAvmService().addAspect(currentPath + "/" + filename,
+ ContentModel.ASPECT_TITLED);
+
+ this.uploads.add(AVMNodeConverter.ToNodeRef(-1, currentPath + "/"
+ + filename));
+ returnPage = returnPage.replace("${_FILE_TYPE_IMAGE}", Utils
+ .getFileTypeImage(facesContext, filename, true));
+ } catch (Exception e) {
+ LOGGER.debug(e.getMessage(), e);
+ returnPage = returnPage.replace("${_UPLOAD_ERROR}", e.getMessage());
+ }
+
+ LOGGER.debug("upload complete. sending response: " + returnPage);
+ final org.w3c.dom.Document result = XMLUtil.newDocument();
+ final org.w3c.dom.Element htmlEl = result.createElement("html");
+ result.appendChild(htmlEl);
+ final org.w3c.dom.Element bodyEl = result.createElement("body");
+ htmlEl.appendChild(bodyEl);
+
+ final org.w3c.dom.Element scriptEl = result.createElement("script");
+ bodyEl.appendChild(scriptEl);
+ scriptEl.setAttribute("type", "text/javascript");
+ final org.w3c.dom.Node scriptText = result.createTextNode(returnPage);
+ scriptEl.appendChild(scriptText);
+
+ final ResponseWriter out = facesContext.getResponseWriter();
+ XMLUtil.print(result, out);
+ }
+
+ private String getCurrentAVMPath() {
+ final AVMNode node = this.getAvmBrowseBean().getAvmActionNode();
+ if (node == null) {
+ return this.getAvmBrowseBean().getCurrentPath();
+ }
+
+ final String result = node.getPath();
+ return node.isDirectory() ? result
+ : AVMNodeConverter.SplitBase(result)[0];
+ }
+
+ private QName[] getSelectableTypes(final String[] selectableTypes) {
+ final QName[] result = (selectableTypes == null ? new QName[] {
+ WCMModel.TYPE_AVM_CONTENT, WCMModel.TYPE_AVM_FOLDER }
+ : new QName[selectableTypes.length]);
+
+ if (selectableTypes != null) {
+ for (int i = 0; i < selectableTypes.length; i++) {
+ result[i] = QName.resolveToQName(this.getNamespaceService(),
+ selectableTypes[i]);
+ }
+ }
+ return result;
+ }
+
+ private Pattern[] getFilterMimetypes(final String[] filterMimetypes) {
+ final Pattern[] result = filterMimetypes == null ? new Pattern[0]
+ : new Pattern[filterMimetypes.length];
+ if (filterMimetypes != null) {
+ for (int i = 0; i < filterMimetypes.length; i++) {
+ result[i] = Pattern.compile(filterMimetypes[i].replaceAll("\\*",
+ "\\.*").replaceAll("\\/", "\\\\/"));
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Add child nodes of supplied path to given parent element. Directory
+ * listing is done on given path. Elements representing the child nodes
+ * returned in the directory listing are added to the supplied parent
+ * element.
+ *
+ * @param doc
+ * XML document to which the parent node belongs
+ * @param parent
+ * parent element to add given nodes to as child elements
+ * @param path
+ * path from which to extract child nodes
+ * @param selectableTypes
+ * array of types which are the only ones that should be selectable
+ * in the file picker
+ * @param filterMimetypes
+ * array of MIME type patterns used to filter out child nodes
+ * extracted from the given path which don't match the given MIME
+ * type patterns
+ * @param facesContext
+ * faces context used to set image attribute on each child element
+ */
+ private void addPathChildNodesToElement(org.w3c.dom.Document doc,
+ org.w3c.dom.Element parent, String path, QName[] selectableTypes,
+ Pattern[] filterMimetypes, FacesContext facesContext) {
+ // append elements for the child AVM nodes of the current path
+ // to parent element
+ for (final Map.Entry entry : this
+ .getAvmService().getDirectoryListing(-1, path).entrySet()) {
+ // if AVM node is a content node and the filter MIME types parameter
+ // has been set, then only add child element for AVM node if it matches
+ // one of the specified MIME types in the parameter
+ if (!entry.getValue().isDirectory() && filterMimetypes.length != 0) {
+ final String contentMimetype = this.getAvmService()
+ .getContentDataForRead(entry.getValue()).getMimetype();
+
+ boolean matched = false;
+ for (final Pattern p : filterMimetypes) {
+ matched = p.matcher(contentMimetype).matches();
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug(p + ".matches(" + contentMimetype + ") = "
+ + matched);
+ }
+ if (matched) {
+ break;
+ }
+ }
+
+ // if AVM node MIME type doesn't match any of the types in the
+ // filter MIME types parameter, then don't do any further processing
+ // on it and jump back to the start of the AVM node traversal loop
+ if (!matched) {
+ continue;
+ }
+ }
+
+ // create child element representing AVM node and add to file picker
+ // data element
+ addAVMChildNodeToParentElement(doc, parent, entry.getValue(),
+ selectableTypes, facesContext);
+ }
+ }
+
+ /**
+ * Add provided AVM node descriptors as child node elements to the provided
+ * parent element
+ *
+ * @param doc
+ * XML document to which the parent node belongs
+ * @param parent
+ * parent element to add given nodes as child elements
+ * @param nodes
+ * nodes which to add as child elements to parent elements
+ * @param selectableTypes
+ * AVM node types which must be marked as selectable
+ * @param facesContext
+ * faces context used to set image attribute on each child element
+ */
+ private void addAVMNodesToElement(org.w3c.dom.Document doc,
+ org.w3c.dom.Element parent, List nodes,
+ QName[] selectableTypes, FacesContext facesContext) {
+ for (AVMNodeDescriptor node : nodes) {
+ // create child element representing AVM node and add to file picker
+ // data element
+ addAVMChildNodeToParentElement(doc, parent, node, selectableTypes,
+ facesContext);
+ }
+ }
+
+ /**
+ * Run a saved search represented by the given node reference, against the
+ * web project the XForm is currently within
+ *
+ * @param savedQueryNodRef
+ * NodeRef of the saved query with which to run the search
+ *
+ * @return content nodes returned by the search
+ */
+ private List runSavedSearch(NodeRef savedSearchNodeRef) {
+ // get the store id used to run the saved search query
+ WebProject webProject = this.getAvmBrowseBean().getWebProject();
+ String storeID = webProject.getStoreId();
+
+ // extract the content of saved search node to XML document
+ ContentReader contentReader = getContentService().getReader(
+ savedSearchNodeRef, ContentModel.PROP_CONTENT);
+ InputStream queryInpStream = contentReader.getContentInputStream();
+ SAXReader reader = new SAXReader();
+ Document savedQueryDoc = null;
+ try {
+ savedQueryDoc = reader.read(queryInpStream);
+ } catch (DocumentException de) {
+ // ignore exception and return null
+ return null;
+ }
+
+ // extract search query from saved search XML document
+ String query = null;
+ XPath queryXPath = DocumentHelper.createXPath(SAVED_SEARCH_QUERY_XPATH);
+ List xpathResult = queryXPath.selectNodes(savedQueryDoc);
+ if ((xpathResult != null) && (xpathResult.size() != 0)) {
+ // get the text from the query element
+ Element queryElement = (Element) xpathResult.get(0);
+ String queryElemText = queryElement.getText();
+
+ // now extract the actual search query string from the CDATA section
+ // within that text
+
+ int cdataStartDelimIndex = queryElemText.indexOf(CDATA_START_DELIM);
+ int cdataEndDelimIndex = queryElemText.indexOf(CDATA_END_DELIM);
+
+ // if the CDATA start delimiter is found in the query element text
+ // && there is text between the CDATA start and end delimiters then
+ // extract
+ // the query string from the CDATA section
+ if ((cdataStartDelimIndex > -1)
+ && ((cdataStartDelimIndex + CDATA_START_DELIM.length()) < cdataEndDelimIndex)) {
+ query = queryElemText.substring(cdataStartDelimIndex
+ + CDATA_START_DELIM.length(), cdataEndDelimIndex);
+ }
+ }
+
+ // perform the search against the repository
+ // if query was extracted from the saved search successfully
+ // (extracted query non-null)
+ List resultNodeDescriptors = null;
+ if ((query != null) && (query.length() != 0)) {
+ ResultSet results = null;
+ try {
+ results = this.getSearchService().query(
+ new StoreRef(StoreRef.PROTOCOL_AVM, storeID),
+ SearchService.LANGUAGE_LUCENE, query);
+
+ if (results.length() != 0) {
+ resultNodeDescriptors = new ArrayList();
+ for (int i = 0; i < results.length(); i++) {
+ ResultSetRow row = results.getRow(i);
+ NodeRef resultNodeRef = row.getNodeRef();
+ Node resultNode = new Node(resultNodeRef);
+
+ // only add content type nodes to the search result
+ // as we don't want the user to navigate down into folders
+ // in the search results
+ if (getDictionaryService().isSubClass(resultNode.getType(),
+ ContentModel.TYPE_CONTENT)) {
+ Pair pair = AVMNodeConverter
+ .ToAVMVersionPath(resultNodeRef);
+ Integer version = pair.getFirst();
+ String path = pair.getSecond();
+ resultNodeDescriptors.add(getAvmService().lookup(version,
+ path));
+ }
+ }
+ }
+ } catch (Throwable err) {
+ throw new AlfrescoRuntimeException("Failed to execute search: "
+ + query, err);
+ } finally {
+ if (results != null) {
+ results.close();
+ }
+ }
+ }
+
+ return resultNodeDescriptors;
+ }
+
+ /**
+ * Get the cached reference to the current user's saved searches folder. This
+ * method will first get a reference to the current user's saved searches
+ * folder and assign it to the cached reference if is it is null.
+ *
+ * @return the cached reference to the current user's Saved Searches folder
+ */
+ private NodeRef getUserSearchesRef() {
+ // if the cached reference is null, then get a reference to the
+ // user's saved searches folder to assign to it
+ if (userSearchesRef == null) {
+ NodeRef globalRef = getGlobalSearchesRef();
+ if (globalRef != null) {
+ // Use the search service get a reference to the
+ // current user's saved searches folder.
+ // Search within the context of the global saved searches
+ // folder
+ FacesContext fc = FacesContext.getCurrentInstance();
+ User user = Application.getCurrentUser(fc);
+ String userName = ISO9075.encode(user.getUserName());
+ String xpath = NamespaceService.APP_MODEL_PREFIX + ":"
+ + QName.createValidLocalName(userName);
+
+ List results = null;
+ try {
+ results = getSearchService().selectNodes(globalRef, xpath, null,
+ getNamespaceService(), false);
+ } catch (AccessDeniedException err) {
+ // ignore and return null
+ }
+
+ if ((results != null) && (results.size() != 0)) {
+ userSearchesRef = results.get(0);
+ }
+ }
+ }
+
+ return userSearchesRef;
+ }
+
+ /**
+ * Get the cached reference to the global saved searches folder. This method
+ * will first get a reference to the global saved searches folder and assign
+ * it to the cached reference if is it is null.
+ *
+ * @return the cached reference to the global Saved Searches folder
+ */
+ private NodeRef getGlobalSearchesRef() {
+ // if the cached reference is null, then get a reference to the
+ // global saved searches folder to assign to it
+ if (globalSearchesRef == null) {
+ // Use the search service get a reference to the
+ // global saved searches folder.
+ FacesContext fc = FacesContext.getCurrentInstance();
+ String xpath = Application.getRootPath(fc) + "/"
+ + Application.getGlossaryFolderName(fc) + "/"
+ + Application.getSavedSearchesFolderName(fc);
+
+ List results = null;
+ try {
+ results = getSearchService().selectNodes(
+ getNodeService().getRootNode(Repository.getStoreRef()),
+ xpath, null, getNamespaceService(), false);
+ } catch (AccessDeniedException err) {
+ // ignore and return null
+ }
+
+ if (results != null && results.size() != 0) {
+ globalSearchesRef = results.get(0);
+ }
+ }
+
+ return globalSearchesRef;
+ }
+
+ /**
+ * Get node for saved search by name.
+ *
+ * @param savedSearchName
+ * name of saved search for which to get node
+ * @param savedSearchContext
+ * either "user" or "global", which says whether to get saved
+ * search out of current user's saved searches folder or global
+ * saved searches folder respectively
+ * @return node reference for saved search
+ */
+ public NodeRef getSavedSearches(String savedSearchName,
+ String savedSearchContext) {
+ NodeRef savedSearchNodeRef = null;
+
+ // get the saved searches folder reference from the
+ // current user or global searches location
+ NodeRef savedSearchesFolderRef = null;
+ if (SAVED_SEARCHES_CONTEXT_USER.equals(savedSearchContext)) {
+ savedSearchesFolderRef = getUserSearchesRef();
+ } else if (SAVED_SEARCHES_CONTEXT_GLOBAL.equals(savedSearchContext)) {
+ savedSearchesFolderRef = getGlobalSearchesRef();
+ }
+
+ // read the content nodes under the folder
+ List childRefs = getNodeService().getChildAssocs(
+ savedSearchesFolderRef, ContentModel.ASSOC_CONTAINS,
+ RegexQNamePattern.MATCH_ALL);
+
+ // return content node with name matching given saved search name
+ if (childRefs.size() != 0) {
+ for (ChildAssociationRef ref : childRefs) {
+ NodeRef childNodeRef = ref.getChildRef();
+ Node childNode = new Node(childNodeRef);
+ if (getDictionaryService().isSubClass(childNode.getType(),
+ ContentModel.TYPE_CONTENT)) {
+ String childNodeName = childNode.getName();
+ if (childNodeName.equals(savedSearchName)) {
+ savedSearchNodeRef = childNodeRef;
+ break;
+ }
+ }
+ }
+ }
+
+ return savedSearchNodeRef;
+ }
+
+ /**
+ * Create child element representing given AVM node and add to given parent
+ * element
+ *
+ * @param doc
+ * Document to which given parent element belongs
+ * @param parent
+ * parent element to add AVM node to as child element
+ * @param node
+ * AVM node to add as child node to given parent
+ * @param selectableTypes
+ * AVM node types which must be marked as selectable
+ * @param facesContent
+ * Faces context used to get file-type icon for given AVM node
+ */
+ private void addAVMChildNodeToParentElement(org.w3c.dom.Document doc,
+ org.w3c.dom.Element parent, AVMNodeDescriptor node,
+ QName[] selectableTypes, FacesContext facesContext) {
+ // create child node element to add to file picker data
+ org.w3c.dom.Element childNodeElement = doc.createElement("child-node");
+ childNodeElement.setAttribute("avmPath", node.getPath());
+ childNodeElement.setAttribute("webappRelativePath", AVMUtil
+ .getWebappRelativePath(node.getPath()));
+ childNodeElement.setAttribute("type", node.isDirectory() ? "directory"
+ : "file");
+
+ // Set image attribute on each child
+ // TODO (Glen): IS this the right image to set?
+ // originally from Ariel's code
+ childNodeElement.setAttribute("image",
+ (node.isDirectory() ? "/images/icons/space_small.gif" : Utils
+ .getFileTypeImage(facesContext, node.getName(), true)));
+
+ boolean selectable = false;
+
+ // set 'selectable' attribute on child node to mark whether node should
+ // be selectable in file picker or not
+ //
+ // TODO Ariel: faking this for now since i can't figure out how to
+ // efficiently get the type
+ // qname from the avmservice
+ for (final QName typeQName : selectableTypes) {
+ selectable = selectable
+ || (WCMModel.TYPE_AVM_FOLDER.equals(typeQName) && node
+ .isDirectory());
+ selectable = selectable
+ || (WCMModel.TYPE_AVM_CONTENT.equals(typeQName) && !node
+ .isDirectory());
+ }
+ childNodeElement.setAttribute("selectable", Boolean.toString(selectable));
+
+ // append child node element to parent
+ parent.appendChild(childNodeElement);
+ }
+}
diff --git a/source/test-resources/xforms/unit-tests/simple-test/upload-simple-test.xsd b/source/test-resources/xforms/unit-tests/simple-test/upload-simple-test.xsd
index 79835c1f3a..19dc7ce4bc 100644
--- a/source/test-resources/xforms/unit-tests/simple-test/upload-simple-test.xsd
+++ b/source/test-resources/xforms/unit-tests/simple-test/upload-simple-test.xsd
@@ -19,9 +19,15 @@
-
- image_file_picker
+
+ image_file_picker
+
+
+ folder_restricted_file_picker
+
+ search_restricted_file_picker
+
html_file_picker
diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml
index 40f9036e24..439ae79f74 100644
--- a/source/web/WEB-INF/faces-config-beans.xml
+++ b/source/web/WEB-INF/faces-config-beans.xml
@@ -4547,6 +4547,22 @@
avmBrowseBean
#{AVMBrowseBean}
+
+ searchService
+ #{SearchService}
+
+
+ nodeService
+ #{NodeService}
+
+
+ dictionaryService
+ #{DictionaryService}
+
+
+ contentService
+ #{ContentService}
+
diff --git a/source/web/scripts/ajax/file_picker_widget.js b/source/web/scripts/ajax/file_picker_widget.js
index 6dcc343386..141be5233a 100644
--- a/source/web/scripts/ajax/file_picker_widget.js
+++ b/source/web/scripts/ajax/file_picker_widget.js
@@ -50,7 +50,10 @@ alfresco.FilePickerWidget = function(uploadId,
cancel_callback,
resize_callback,
selectableTypes,
- filterMimetypes)
+ filterMimetypes,
+ folderRestriction,
+ savedSearchName,
+ savedSearchContext)
{
this.uploadId = uploadId;
this.node = node;
@@ -61,6 +64,9 @@ alfresco.FilePickerWidget = function(uploadId,
this.resize_callback = resize_callback || function() {};
this.selectableTypes = selectableTypes;
this.filterMimetypes = filterMimetypes;
+ this.folderRestriction = folderRestriction;
+ this.savedSearchName = savedSearchName;
+ this.savedSearchContext = savedSearchContext;
}
// static methods and properties
@@ -256,6 +262,18 @@ _navigateToNode: function(path)
{
params.filterMimetypes = this.filterMimetypes;
}
+ if (this.folderRestriction)
+ {
+ req.content.folderRestriction = this.folderRestriction;
+ }
+ if (this.savedSearchName)
+ {
+ req.content.savedSearchName = this.savedSearchName;
+ }
+ if (this.savedSearchContext)
+ {
+ req.content.savedSearchContext = this.savedSearchContext;
+ }
alfresco.AjaxHelper.sendRequest("FilePickerBean.getFilePickerData",
params,
diff --git a/source/web/scripts/ajax/xforms.js b/source/web/scripts/ajax/xforms.js
index fb4e8b1af4..7a958813d8 100644
--- a/source/web/scripts/ajax/xforms.js
+++ b/source/web/scripts/ajax/xforms.js
@@ -508,9 +508,9 @@ alfresco.xforms.FilePicker = alfresco.xforms.Widget.extend({
this.parent(xform, xformsNode);
this._selectableTypes = "selectable_types" in params ? params["selectable_types"].split(",") : null;
this._filterMimetypes = "filter_mimetypes" in params ? params["filter_mimetypes"].split(",") : [];
-
- // JanV - temp
- this._dirPath = "dir_path" in params ? params["dir_path"] : null;
+ this._folderRestriction = "folder_restriction" in params ? params["folder_restriction"] : null;
+ this._savedSearchName = "saved_search_name" in params ? params["saved_search_name"] : null;
+ this._savedSearchContext = "saved_search_context" in params ? params["saved_search_context"] : null;
},
/////////////////////////////////////////////////////////////////
@@ -531,7 +531,9 @@ alfresco.xforms.FilePicker = alfresco.xforms.Widget.extend({
this._filePicker_resizeHandler.bindAsEventListener(this),
this._selectableTypes,
this._filterMimetypes,
- this._dirPath);
+ this._folderRestriction,
+ this._savedSearchName,
+ this._savedSearchContext);
this.widget.render();
},