/* * Copyright (C) 2012 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.services.jcr.webdav; import org.exoplatform.container.xml.InitParams; import org.exoplatform.container.xml.ValueParam; import org.exoplatform.container.xml.ValuesParam; import org.exoplatform.services.jcr.webdav.util.InitParamsDefaults; import org.exoplatform.services.jcr.webdav.util.InitParamsNames; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.rest.impl.MultivaluedMapImpl; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; /** * Provides means to parse WebDAV service initial parameters and gain access to their values. * * @author Dmitry Kuleshov - dmi3.kuleshov@gmail.com * @version $Id$ */ public class WebDavServiceInitParams { /** * Logger. */ private static Log log = ExoLogger.getLogger("exo.jcr.component.webdav.WebDavServiceInitParams"); /** * Default folder node type. */ private String defaultFolderNodeType = InitParamsDefaults.FOLDER_NODE_TYPE; /** * Default file node type. */ private String defaultFileNodeType = InitParamsDefaults.FILE_NODE_TYPE; /** * Default file mime type. */ private String defaultFileMimeType = InitParamsDefaults.FILE_MIME_TYPE; /** * Update policy. */ private String defaultUpdatePolicyType = InitParamsDefaults.UPDATE_POLICY; /** * Auto-version default value. */ private String defaultAutoVersionType = InitParamsDefaults.AUTO_VERSION; /** * XSLT parameters. */ private Map<String, String> xsltParams = new HashMap<String, String>(); /** * Set of untrusted user agents. Special rules are applied for listed agents. */ private Set<String> untrustedUserAgents = new HashSet<String>(); /** * Set of pattern untrusted user agents. * */ private Set<Pattern> untrustedUserAgentsPattern = new HashSet<Pattern>(); /** * Set of allowed file node types. */ private Set<String> allowedFileNodeTypes = new HashSet<String>(); /** * Set of allowed folder node types. */ private Set<String> allowedFolderNodeTypes = new HashSet<String>(); /** * Cache control parameters. */ private Map<MediaType, String> cacheControlMap = new HashMap<MediaType, String>(); /** * enable auto versionning strategy (updatePolicyType : create-version , autoVersion : checkin-checkout). */ private boolean enableAutoVersion = false ; /** * Map of jcr (path , workspace) of allowed auto versioning. */ private MultivaluedMap<String,String> allowedAutoVersionPath = new MultivaluedMapImpl(); /** * Default constructor, all initial parameters take default values. * The list of default parameters values may be obtained from {@link InitParamsDefaults}. */ public WebDavServiceInitParams() { allowedFileNodeTypes.add(InitParamsDefaults.FILE_NODE_TYPE); allowedFolderNodeTypes.add(InitParamsDefaults.FOLDER_NODE_TYPE); } /** * Create an instance of WebDAV service initial parameters from {@link InitParams} * which are obtained from configuration file. * @param params initial parameters */ public WebDavServiceInitParams(InitParams params) { this(); Map<String, String> parametersMap = new HashMap<String, String>(); Iterator<ValueParam> valueParamIterator = params.getValueParamIterator(); ValueParam valueParam; while (valueParamIterator.hasNext()) { valueParam = valueParamIterator.next(); parametersMap.put(valueParam.getName(), valueParam.getValue()); } Iterator<ValuesParam> valuesParamIterator = params.getValuesParamIterator(); ValuesParam valuesParam; while (valuesParamIterator.hasNext()) { valuesParam = valuesParamIterator.next(); List<String> values = valuesParam.getValues(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < values.size(); i++) { sb.append(values.get(i)); sb.append(','); } parametersMap.put(valuesParam.getName(), sb.toString()); } processParametersMap(parametersMap); } /** * Create an instance of WebDAV service initial parameters from parameters map. * Please note, that this constructor receives {@code Map<String, String>} instead of InitParams * and we cannot pass multi-valued parameters in the form of * {@link String} {@literal ->} {@link java.util.Map} * To overcome this shortage we pass a set of parameter values as a single {@link String} * with each value separated by comma (",") i.e. "agent1, agent2, agent3" * @param params initial parameters */ public WebDavServiceInitParams(Map<String, String> params) { this(); processParametersMap(params); } private void processParametersMap(Map<String, String> parameters) { ParametersMapProcessor pmp = new ParametersMapProcessor(parameters); defaultFolderNodeType = pmp.processSingleParameter(defaultFolderNodeType, InitParamsNames.DEF_FOLDER_NODE_TYPE); defaultFileNodeType = pmp.processSingleParameter(defaultFileNodeType, InitParamsNames.DEF_FILE_NODE_TYPE); defaultFileMimeType = pmp.processSingleParameter(defaultFileMimeType, InitParamsNames.DEF_FILE_MIME_TYPE); defaultUpdatePolicyType = pmp.processSingleParameter(defaultUpdatePolicyType, InitParamsNames.UPDATE_POLICY); defaultAutoVersionType = pmp.processSingleParameter(defaultAutoVersionType, InitParamsNames.AUTO_VERSION); enableAutoVersion = pmp.processSingleParameter(enableAutoVersion, InitParamsNames.ENABLE_AUTO_VERSION); pmp.processMultiParameter(untrustedUserAgents, InitParamsNames.UNTRUSTED_USER_AGENTS); for (String pattern : untrustedUserAgents) { untrustedUserAgentsPattern.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); } pmp.processMultiParameter(allowedFileNodeTypes, InitParamsNames.ALLOWED_FILE_NODE_TYPES); pmp.processMultiParameter(allowedFolderNodeTypes, InitParamsNames.ALLOWED_FOLDER_NODE_TYPES); pmp.processValueParameterToMap(allowedAutoVersionPath, InitParamsNames.ALLOWED_JCR_PATH_AUTO_VERSION); pmp.processSingleParameterToMap(xsltParams, InitParamsNames.FILE_ICON_PATH); pmp.processSingleParameterToMap(xsltParams, InitParamsNames.FOLDER_ICON_PATH); pmp.processCacheControlParameter(); } public String getDefaultFolderNodeType() { return defaultFolderNodeType; } public String getDefaultFileNodeType() { return defaultFileNodeType; } public String getDefaultFileMimeType() { return defaultFileMimeType; } public String getDefaultUpdatePolicyType() { return defaultUpdatePolicyType; } public String getDefaultAutoVersionType() { return defaultAutoVersionType; } public Map<String, String> getXsltParams() { return xsltParams; } public Set<String> getUntrustedUserAgents() { return untrustedUserAgents; } public Set<Pattern> getUntrustedUserAgentsPattern() { return untrustedUserAgentsPattern; } public boolean isUntrustedUserAgent(String userAgent) { if (userAgent == null) { return false; } for (Pattern p : untrustedUserAgentsPattern) { if (p.matcher(userAgent).find()) { return true; } } return false; } public Set<String> getAllowedFileNodeTypes() { return allowedFileNodeTypes; } public Set<String> getAllowedFolderNodeTypes() { return allowedFolderNodeTypes; } public Map<MediaType, String> getCacheControlMap() { return cacheControlMap; } public void setDefaultFolderNodeType(String defaultFolderNodeType) { this.defaultFolderNodeType = defaultFolderNodeType; } public void setDefaultFileNodeType(String defaultFileNodeType) { this.defaultFileNodeType = defaultFileNodeType; } public void setDefaultFileMimeType(String defaultFileMimeType) { this.defaultFileMimeType = defaultFileMimeType; } public void setDefaultUpdatePolicyType(String defaultUpdatePolicyType) { this.defaultUpdatePolicyType = defaultUpdatePolicyType; } public void setDefaultAutoVersionType(String defaultAutoVersionType) { this.defaultAutoVersionType = defaultAutoVersionType; } public void setXsltParams(Map<String, String> xsltParams) { this.xsltParams = xsltParams; } public void setUntrustedUserAgents(Set<String> untrustedUserAgents) { this.untrustedUserAgents = untrustedUserAgents; } public void setAllowedFileNodeTypes(Set<String> allowedFileNodeTypes) { this.allowedFileNodeTypes = allowedFileNodeTypes; } public void setAllowedFolderNodeTypes(Set<String> allowedFolderNodeTypes) { this.allowedFolderNodeTypes = allowedFolderNodeTypes; } public void setCacheControlMap(Map<MediaType, String> cacheControlMap) { this.cacheControlMap = cacheControlMap; } public void setAllowedAutoVersionPath(MultivaluedMap<String, String> allowedAutoVersionPath) { this.allowedAutoVersionPath = merge( this.allowedAutoVersionPath,allowedAutoVersionPath); } public MultivaluedMap<String, String> getAllowedAutoVersionPath() { return allowedAutoVersionPath; } public void setEnableAutoVersion(boolean enableAutoVersion) { this.enableAutoVersion = enableAutoVersion; } public boolean isEnableAutoVersion() { return enableAutoVersion; } private class ParametersMapProcessor { Map<String, String> parameters; public ParametersMapProcessor(Map<String, String> parameters) { this.parameters = parameters; } private void processSingleParameterToMap(Map<String, String> parameterMap, String parameterName) { String paramValue = parameters.get(parameterName); if (paramValue != null) { parameterMap.put(parameterName, paramValue); log.info(parameterName + " = " + paramValue); } } private void processValueParameterToMap(MultivaluedMap<String, String> parameterMap, String parameterName) { String paramValue = parameters.get(parameterName); if (paramValue != null) { String[] elements = paramValue.split(";"); for (String element : elements) { String workspaceName = element.split(":")[0]; String pathName = element.split(":")[1]; parameterMap.add(workspaceName, pathName); } } } private void processCacheControlParameter() { String paramValue = parameters.get(InitParamsNames.CACHE_CONTROL); if (paramValue != null) { try { String[] elements = paramValue.split(";"); for (String element : elements) { String cacheValue = element.split(":")[1]; String keys = element.split(":")[0]; for (String key : keys.split(",")) { MediaType mediaType = new MediaType(key.split("/")[0], key.split("/")[1]); cacheControlMap.put(mediaType, cacheValue); } } } catch (PatternSyntaxException e) { log.warn("Invalid " + InitParamsNames.CACHE_CONTROL + " parameter"); } catch (UnsupportedOperationException e) { log.warn("Invalid " + InitParamsNames.CACHE_CONTROL + " parameter"); } catch (ClassCastException e) { log.warn("Invalid " + InitParamsNames.CACHE_CONTROL + " parameter"); } catch (IllegalArgumentException e) { log.warn("Invalid " + InitParamsNames.CACHE_CONTROL + " parameter"); } } } private String processSingleParameter(String parameter, String parameterName) { String paramValue = parameters.get(parameterName); if (paramValue != null) { parameter = paramValue; log.info(parameterName + " = " + parameter); } return parameter; } private boolean processSingleParameter(boolean parameter, String parameterName) { String paramValue = parameters.get(parameterName); if (paramValue != null) { parameter = Boolean.getBoolean(paramValue); log.info(parameterName + " = " + parameter); } return parameter; } private void processMultiParameter(Set<String> valuesSet, String parameterName) { String parameterMultivalue = parameters.get(parameterName); if (parameterMultivalue != null) { valuesSet.clear(); for (String value : parameterMultivalue.split(",")) { valuesSet.add(value.trim()); log.info(parameterName + " = " + value.trim()); } } } } private MultivaluedMap<String, String> merge(MultivaluedMap<String, String> map1, MultivaluedMap<String, String> map2) { if (map1.isEmpty()) { return map2; } else if (map2.isEmpty()) { return map1; } else { for (String key : map2.keySet()) { if (key != null) { List<String> list = map2.get(key); for (String value : list) { map1.add(key, value); } } } return map1; } } }