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(); },