diff --git a/repository/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java b/repository/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java
index 86e58e6527..158306bed0 100644
--- a/repository/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java
+++ b/repository/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2019 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,12 +25,21 @@
*/
package org.alfresco.repo.content;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.ContentServicePolicies.OnContentPropertyUpdatePolicy;
import org.alfresco.repo.content.ContentServicePolicies.OnContentReadPolicy;
import org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy;
import org.alfresco.repo.content.cleanup.EagerContentStoreCleaner;
+import org.alfresco.repo.content.directurl.DirectAccessUrlDisabledException;
+import org.alfresco.repo.content.directurl.SystemWideDirectUrlConfig;
import org.alfresco.repo.content.filestore.FileContentStore;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.ClassPolicyDelegate;
@@ -47,6 +56,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.DirectAccessUrl;
+import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.MimetypeServiceAware;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -62,13 +72,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.extensions.surf.util.I18NUtil;
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
/**
* Service implementation acting as a level of indirection between the client
* and the underlying content store.
@@ -82,7 +85,7 @@ import java.util.Set;
*/
public class ContentServiceImpl implements ContentService, ApplicationContextAware
{
- private static Log logger = LogFactory.getLog(ContentServiceImpl.class);
+ private static final Log logger = LogFactory.getLog(ContentServiceImpl.class);
private DictionaryService dictionaryService;
private NodeService nodeService;
@@ -99,6 +102,8 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
/** Should we consider zero byte content to be the same as no content? */
private boolean ignoreEmptyContent;
+ private SystemWideDirectUrlConfig systemWideDirectUrlConfig;
+
/**
* The policy component
*/
@@ -140,7 +145,12 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
{
this.store = store;
}
-
+
+ public void setSystemWideDirectUrlConfig(SystemWideDirectUrlConfig systemWideDirectUrlConfig)
+ {
+ this.systemWideDirectUrlConfig = systemWideDirectUrlConfig;
+ }
+
public void setPolicyComponent(PolicyComponent policyComponent)
{
this.policyComponent = policyComponent;
@@ -510,23 +520,10 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
return tempStore.getWriter(ContentContext.NULL_CONTEXT);
}
- @Override
+ @Deprecated
public DirectAccessUrl getDirectAccessUrl(NodeRef nodeRef, Date expiresAt)
{
- ContentData contentData = getContentData(nodeRef, ContentModel.PROP_CONTENT);
-
- // check that the URL is available
- if (contentData == null || contentData.getContentUrl() == null)
- {
- throw new IllegalArgumentException("The supplied nodeRef " + nodeRef + " has no content.");
- }
-
- if (store.isDirectAccessSupported())
- {
- return store.getDirectAccessUrl(contentData.getContentUrl(), expiresAt);
- }
-
- return null;
+ return requestContentDirectUrl(nodeRef, true, null);
}
/**
@@ -586,4 +583,104 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
}
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isContentDirectUrlEnabled()
+ {
+ return systemWideDirectUrlConfig.isEnabled() && store.isContentDirectUrlEnabled();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isContentDirectUrlEnabled(NodeRef nodeRef)
+ {
+ boolean contentDirectUrlEnabled = false;
+
+ // TODO: update this
+ if (systemWideDirectUrlConfig.isEnabled())
+ {
+ ContentData contentData = getContentData(nodeRef, ContentModel.PROP_CONTENT);
+
+ // check that the URL is available
+ if (contentData == null || contentData.getContentUrl() == null)
+ {
+ throw new IllegalArgumentException("The supplied nodeRef " + nodeRef + " has no content.");
+ }
+
+ contentDirectUrlEnabled = (store.isContentDirectUrlEnabled(nodeRef));
+ }
+
+ return contentDirectUrlEnabled;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DirectAccessUrl requestContentDirectUrl(NodeRef nodeRef, boolean attachment, Long validFor)
+ {
+ if (!systemWideDirectUrlConfig.isEnabled())
+ {
+ throw new DirectAccessUrlDisabledException("Direct access url isn't available.");
+ }
+
+ String contentUrl = getContentUrl(nodeRef);
+ String fileName = getFileName(nodeRef);
+ validFor = adjustValidFor(validFor);
+
+ DirectAccessUrl directAccessUrl = null;
+ if (store.isContentDirectUrlEnabled())
+ {
+ try
+ {
+ directAccessUrl = store.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
+ }
+ catch (UnsupportedOperationException ex)
+ {
+ // expected exception
+ }
+ }
+ return directAccessUrl;
+ }
+
+ protected String getContentUrl(NodeRef nodeRef)
+ {
+ ContentData contentData = getContentData(nodeRef, ContentModel.PROP_CONTENT);
+
+ // check that the URL is available
+ if (contentData == null || contentData.getContentUrl() == null)
+ {
+ throw new IllegalArgumentException("The supplied nodeRef " + nodeRef + " has no content.");
+ }
+
+ return contentData.getContentUrl();
+ }
+
+ protected String getFileName(NodeRef nodeRef)
+ {
+ String fileName = null;
+
+ try
+ {
+ fileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
+ }
+ catch (InvalidNodeRefException ex)
+ {
+ }
+
+ return fileName;
+ }
+
+ private Long adjustValidFor(Long validFor)
+ {
+ if (validFor == null || validFor > systemWideDirectUrlConfig.getDefaultExpiryTimeInSec())
+ {
+ validFor = systemWideDirectUrlConfig.getDefaultExpiryTimeInSec();
+ }
+ return validFor;
+ }
}
\ No newline at end of file
diff --git a/repository/src/main/java/org/alfresco/repo/content/caching/CachingContentStore.java b/repository/src/main/java/org/alfresco/repo/content/caching/CachingContentStore.java
index 5cad001984..77e7851547 100644
--- a/repository/src/main/java/org/alfresco/repo/content/caching/CachingContentStore.java
+++ b/repository/src/main/java/org/alfresco/repo/content/caching/CachingContentStore.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,7 +25,6 @@
*/
package org.alfresco.repo.content.caching;
-import java.util.Date;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
@@ -41,6 +40,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentStreamListener;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.DirectAccessUrl;
+import org.alfresco.service.cmr.repository.NodeRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanNameAware;
@@ -103,7 +103,7 @@ public class CachingContentStore implements ContentStore, ApplicationEventPublis
{
eventPublisher.publishEvent(new CachingContentStoreCreatedEvent(this));
}
-
+
@Override
public boolean isContentUrlSupported(String contentUrl)
{
@@ -137,7 +137,7 @@ public class CachingContentStore implements ContentStore, ApplicationEventPublis
/**
* {@inheritDoc}
*
- * For {@link #SPOOF_PROTOCOL spoofed} URLs, the URL always exists.
+ * For {@link FileContentStore#SPOOF_PROTOCOL spoofed} URLs, the URL always exists.
*/
@Override
public boolean exists(String contentUrl)
@@ -478,13 +478,35 @@ public class CachingContentStore implements ContentStore, ApplicationEventPublis
return this.beanName;
}
- public boolean isDirectAccessSupported()
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isContentDirectUrlEnabled()
{
- return backingStore.isDirectAccessSupported();
+ return backingStore.isContentDirectUrlEnabled();
}
- public DirectAccessUrl getDirectAccessUrl(String contentUrl, Date expiresAt)
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isContentDirectUrlEnabled(NodeRef nodeRef)
{
- return backingStore.getDirectAccessUrl(contentUrl, expiresAt);
+ return backingStore.isContentDirectUrlEnabled(nodeRef);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName)
+ {
+ return backingStore.requestContentDirectUrl(contentUrl, attachment, fileName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName, Long validFor)
+ {
+ return backingStore.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
}
}
diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/AbstractDirectUrlConfig.java b/repository/src/main/java/org/alfresco/repo/content/directurl/AbstractDirectUrlConfig.java
new file mode 100644
index 0000000000..db6ebef9e6
--- /dev/null
+++ b/repository/src/main/java/org/alfresco/repo/content/directurl/AbstractDirectUrlConfig.java
@@ -0,0 +1,81 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.content.directurl;
+
+/**
+ * Direct Access Url configuration settings.
+ *
+ * @author Sara Aspery
+ */
+public abstract class AbstractDirectUrlConfig implements DirectUrlConfig
+{
+ /** System-wide direct access URL configuration */
+ private SystemWideDirectUrlConfig systemWideDirectUrlConfig;
+
+ /** Direct access URL configuration settings */
+ private Boolean enabled;
+ private Long defaultExpiryTimeInSec;
+
+ public void setSystemWideDirectUrlConfig(SystemWideDirectUrlConfig systemWideDirectUrlConfig)
+ {
+ this.systemWideDirectUrlConfig = systemWideDirectUrlConfig;
+ }
+
+ public void setEnabled(Boolean enabled)
+ {
+ this.enabled = enabled;
+ }
+
+ public void setDefaultExpiryTimeInSec(Long defaultExpiryTimeInSec)
+ {
+ this.defaultExpiryTimeInSec = defaultExpiryTimeInSec;
+ }
+
+ protected Boolean isSysWideEnabled()
+ {
+ return systemWideDirectUrlConfig.isEnabled();
+ }
+
+ public Long getSysWideDefaultExpiryTimeInSec()
+ {
+ return systemWideDirectUrlConfig.getDefaultExpiryTimeInSec();
+ }
+
+ public Long getSysWideMaxExpiryTimeInSec()
+ {
+ return systemWideDirectUrlConfig.getMaxExpiryTimeInSec();
+ }
+
+ public Boolean isEnabled()
+ {
+ return enabled;
+ }
+
+ public Long getDefaultExpiryTimeInSec()
+ {
+ return defaultExpiryTimeInSec;
+ }
+}
diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfig.java b/repository/src/main/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfig.java
new file mode 100644
index 0000000000..79494718bf
--- /dev/null
+++ b/repository/src/main/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfig.java
@@ -0,0 +1,134 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.content.directurl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Content store direct access URL configuration settings.
+ *
+ * @author Sara Aspery
+ */
+public class ContentStoreDirectUrlConfig extends AbstractDirectUrlConfig
+{
+ private static final Log logger = LogFactory.getLog(ContentStoreDirectUrlConfig.class);
+
+ private Long maxExpiryTimeInSec;
+
+ public void setMaxExpiryTimeInSec(Long maxExpiryTimeInSec)
+ {
+ this.maxExpiryTimeInSec = maxExpiryTimeInSec;
+ }
+
+ public Long getMaxExpiryTimeInSec()
+ {
+ return maxExpiryTimeInSec;
+ }
+
+ /**
+ * Configuration initialise
+ */
+ public void init()
+ {
+ validate();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void validate()
+ {
+ // Disable direct access URLs for the content store if any error found in the content store direct access URL config
+ try
+ {
+ validateDirectAccessUrlConfig();
+ }
+ catch (InvalidDirectAccessUrlConfigException ex)
+ {
+ logger.error("Disabling content store direct access URLs due to configuration error: " + ex.getMessage());
+ setEnabled(false);
+ }
+ }
+
+ /* Helper method to validate the content direct access url configuration settings */
+ private void validateDirectAccessUrlConfig() throws InvalidDirectAccessUrlConfigException
+ {
+ if (isEnabled())
+ {
+ if (getMaxExpiryTimeInSec() == null)
+ {
+ logger.warn(String.format("Maximum expiry time property is missing: setting to system-wide maximum [%s].", getSysWideMaxExpiryTimeInSec()));
+ setMaxExpiryTimeInSec(getSysWideMaxExpiryTimeInSec());
+ }
+ else if (getMaxExpiryTimeInSec() > getSysWideMaxExpiryTimeInSec())
+ {
+ String errorMsg = String.format("Content store direct access URL maximum expiry time [%s] exceeds system-wide maximum expiry time [%s].",
+ getMaxExpiryTimeInSec(), getSysWideMaxExpiryTimeInSec());
+ throw new InvalidDirectAccessUrlConfigException(errorMsg);
+ }
+
+ if (getDefaultExpiryTimeInSec() == null)
+ {
+ logger.warn(String.format("Default expiry time property is missing: setting to system-wide default [%s].", getSysWideDefaultExpiryTimeInSec()));
+ setDefaultExpiryTimeInSec(getSysWideDefaultExpiryTimeInSec());
+ }
+ else if (getDefaultExpiryTimeInSec() > getMaxExpiryTimeInSec())
+ {
+ logger.warn(String.format("Default expiry time property [%s] exceeds maximum expiry time for content store [%s]: setting to system-wide default [%s].",
+ getDefaultExpiryTimeInSec(), getMaxExpiryTimeInSec(), getSysWideDefaultExpiryTimeInSec()));
+ setDefaultExpiryTimeInSec(getSysWideDefaultExpiryTimeInSec());
+ }
+ else if (getDefaultExpiryTimeInSec() > getSysWideDefaultExpiryTimeInSec())
+ {
+ logger.warn(String.format("Default expiry time property [%s] exceeds system-wide default expiry time [%s]: setting to system-wide default.",
+ getDefaultExpiryTimeInSec(), getSysWideDefaultExpiryTimeInSec()));
+ setDefaultExpiryTimeInSec(getSysWideDefaultExpiryTimeInSec());
+ }
+
+ if (getDefaultExpiryTimeInSec() < 1)
+ {
+ String errorMsg = String.format("Content store direct access URL default expiry time [%s] is invalid.", getDefaultExpiryTimeInSec());
+ throw new InvalidDirectAccessUrlConfigException(errorMsg);
+ }
+
+ if (getDefaultExpiryTimeInSec() > getSysWideMaxExpiryTimeInSec())
+ {
+ String errorMsg = String.format("Content store direct access URL default expiry time [%s] exceeds system-wide maximum expiry time [%s].",
+ getDefaultExpiryTimeInSec(), getSysWideMaxExpiryTimeInSec());
+ throw new InvalidDirectAccessUrlConfigException(errorMsg);
+ }
+
+ if (getDefaultExpiryTimeInSec() > getMaxExpiryTimeInSec())
+ {
+ String errorMsg = String.format("Content store direct access URL default expiry time [%s] exceeds content store maximum expiry time [%s].",
+ getDefaultExpiryTimeInSec(), getMaxExpiryTimeInSec());
+ throw new InvalidDirectAccessUrlConfigException(errorMsg);
+ }
+ }
+ }
+}
diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/DirectAccessUrlDisabledException.java b/repository/src/main/java/org/alfresco/repo/content/directurl/DirectAccessUrlDisabledException.java
new file mode 100644
index 0000000000..d0702b398d
--- /dev/null
+++ b/repository/src/main/java/org/alfresco/repo/content/directurl/DirectAccessUrlDisabledException.java
@@ -0,0 +1,44 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.content.directurl;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+
+/**
+ * Runtime exception thrown when direct access URLs are disabled.
+ *
+ * @author Sara Aspery
+ */
+public class DirectAccessUrlDisabledException extends AlfrescoRuntimeException
+{
+
+ private static final long serialVersionUID = -6506082117146782993L;
+
+ public DirectAccessUrlDisabledException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/DirectUrlConfig.java b/repository/src/main/java/org/alfresco/repo/content/directurl/DirectUrlConfig.java
new file mode 100644
index 0000000000..68ed3a84da
--- /dev/null
+++ b/repository/src/main/java/org/alfresco/repo/content/directurl/DirectUrlConfig.java
@@ -0,0 +1,41 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.content.directurl;
+
+import org.alfresco.api.AlfrescoPublicApi;
+
+/**
+ * Direct Access Url configuration settings interface.
+ *
+ * @author Sara Aspery
+ */
+@AlfrescoPublicApi
+public interface DirectUrlConfig
+{
+ Boolean isEnabled();
+ Long getDefaultExpiryTimeInSec();
+ void validate();
+}
diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/InvalidDirectAccessUrlConfigException.java b/repository/src/main/java/org/alfresco/repo/content/directurl/InvalidDirectAccessUrlConfigException.java
new file mode 100644
index 0000000000..5c6445ed5f
--- /dev/null
+++ b/repository/src/main/java/org/alfresco/repo/content/directurl/InvalidDirectAccessUrlConfigException.java
@@ -0,0 +1,44 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.content.directurl;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+
+/**
+ * Runtime exception thrown when the direct access URL configuration settings are invalid.
+ *
+ * @author Sara Aspery
+ */
+public class InvalidDirectAccessUrlConfigException extends AlfrescoRuntimeException
+{
+ private static final long serialVersionUID = -6318313836484979887L;
+
+ public InvalidDirectAccessUrlConfigException(String msg)
+ {
+ super(msg);
+ }
+}
+
diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfig.java b/repository/src/main/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfig.java
new file mode 100644
index 0000000000..ecfa769e38
--- /dev/null
+++ b/repository/src/main/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfig.java
@@ -0,0 +1,124 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.content.directurl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * System-wide direct access URL configuration settings.
+ *
+ * @author Sara Aspery
+ */
+public class SystemWideDirectUrlConfig implements DirectUrlConfig
+{
+ private static final Log logger = LogFactory.getLog(SystemWideDirectUrlConfig.class);
+
+ /** Direct access url configuration settings */
+ private Boolean enabled;
+ private Long defaultExpiryTimeInSec;
+ private Long maxExpiryTimeInSec;
+
+ public void setEnabled(Boolean enabled)
+ {
+ this.enabled = enabled;
+ }
+
+ public void setDefaultExpiryTimeInSec(Long defaultExpiryTimeInSec)
+ {
+ this.defaultExpiryTimeInSec = defaultExpiryTimeInSec;
+ }
+
+ public void setMaxExpiryTimeInSec(Long maxExpiryTimeInSec)
+ {
+ this.maxExpiryTimeInSec = maxExpiryTimeInSec;
+ }
+
+ public Boolean isEnabled()
+ {
+ return enabled;
+ }
+
+ public Long getDefaultExpiryTimeInSec()
+ {
+ return defaultExpiryTimeInSec;
+ }
+
+ public Long getMaxExpiryTimeInSec()
+ {
+ return maxExpiryTimeInSec;
+ }
+
+ /**
+ * Configuration initialise
+ */
+ public void init()
+ {
+ validate();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void validate()
+ {
+ // Disable direct access URLs system-wide if any error found in the system-wide direct access URL config
+ try
+ {
+ validateSystemDirectAccessUrlConfig();
+ }
+ catch (InvalidDirectAccessUrlConfigException ex)
+ {
+ logger.error("Disabling system-wide direct access URLs due to configuration error: " + ex.getMessage());
+ setEnabled(false);
+ }
+ }
+
+ /* Helper method to validate the system-wide direct access url configuration settings */
+ private void validateSystemDirectAccessUrlConfig() throws InvalidDirectAccessUrlConfigException
+ {
+ if (isEnabled())
+ {
+ if (getDefaultExpiryTimeInSec() == null || getDefaultExpiryTimeInSec() < 1)
+ {
+ throw new InvalidDirectAccessUrlConfigException("System-wide direct access URL default expiry time is missing or invalid.");
+ }
+
+ if (getMaxExpiryTimeInSec() == null || getMaxExpiryTimeInSec() < 1)
+ {
+ throw new InvalidDirectAccessUrlConfigException("System-wide direct access URL maximum expiry time is missing or invalid.");
+ }
+
+ if (getDefaultExpiryTimeInSec() > getMaxExpiryTimeInSec())
+ {
+ String errorMsg = String.format("System-wide direct access URL default expiry time [%s] exceeds maximum expiry time [%s].",
+ getDefaultExpiryTimeInSec(), getMaxExpiryTimeInSec());
+ throw new InvalidDirectAccessUrlConfigException(errorMsg);
+ }
+ }
+ }
+}
diff --git a/repository/src/main/java/org/alfresco/repo/content/replication/AggregatingContentStore.java b/repository/src/main/java/org/alfresco/repo/content/replication/AggregatingContentStore.java
index 15cc9c5246..6c700e0572 100644
--- a/repository/src/main/java/org/alfresco/repo/content/replication/AggregatingContentStore.java
+++ b/repository/src/main/java/org/alfresco/repo/content/replication/AggregatingContentStore.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,7 +25,6 @@
*/
package org.alfresco.repo.content.replication;
-import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
@@ -41,6 +40,7 @@ import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.DirectAccessUrl;
+import org.alfresco.service.cmr.repository.NodeRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -65,7 +65,7 @@ import org.apache.commons.logging.LogFactory;
*/
public class AggregatingContentStore extends AbstractContentStore
{
- private static Log logger = LogFactory.getLog(AggregatingContentStore.class);
+ private static final Log logger = LogFactory.getLog(AggregatingContentStore.class);
private ContentStore primaryStore;
private List secondaryStores;
@@ -266,33 +266,58 @@ public class AggregatingContentStore extends AbstractContentStore
}
/**
- * @return Returns true if at least one store supports direct access
+ * @return Returns {@code true} if at least one store supports direct access URLs
*/
- public boolean isDirectAccessSupported()
+ public boolean isContentDirectUrlEnabled()
{
// Check the primary store
- boolean isDirectAccessSupported = primaryStore.isDirectAccessSupported();
+ boolean isContentDirectUrlEnabled = primaryStore.isContentDirectUrlEnabled();
- if (!isDirectAccessSupported)
+ if (!isContentDirectUrlEnabled)
{
// Direct access is not supported by the primary store so we have to check the
// other stores
for (ContentStore store : secondaryStores)
{
+ isContentDirectUrlEnabled = store.isContentDirectUrlEnabled();
- isDirectAccessSupported = store.isDirectAccessSupported();
-
- if (isDirectAccessSupported)
+ if (isContentDirectUrlEnabled)
{
break;
}
}
}
- return isDirectAccessSupported;
+ return isContentDirectUrlEnabled;
}
- public DirectAccessUrl getDirectAccessUrl(String contentUrl, Date expiresAt)
+ /**
+ * @return Returns {@code true} if at least one store supports direct access URL for node
+ */
+ public boolean isContentDirectUrlEnabled(NodeRef nodeRef)
+ {
+ // Check the primary store
+ boolean isContentDirectUrlEnabled = primaryStore.isContentDirectUrlEnabled(nodeRef);
+
+ if (!isContentDirectUrlEnabled)
+ {
+ // Direct access is not supported by the primary store so we have to check the
+ // other stores
+ for (ContentStore store : secondaryStores)
+ {
+ isContentDirectUrlEnabled = store.isContentDirectUrlEnabled(nodeRef);
+
+ if (isContentDirectUrlEnabled)
+ {
+ break;
+ }
+ }
+ }
+
+ return isContentDirectUrlEnabled;
+ }
+
+ public DirectAccessUrl requestContentDirectUrl(String contentUrl, boolean attachment, String fileName, Long validFor)
{
if (primaryStore == null)
{
@@ -312,13 +337,13 @@ public class AggregatingContentStore extends AbstractContentStore
// Check the primary store
try
{
- directAccessUrl = primaryStore.getDirectAccessUrl(contentUrl, expiresAt);
+ directAccessUrl = primaryStore.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
}
catch (UnsupportedOperationException e)
{
// The store does not support direct access URL
directAccessUrlSupported = false;
- }
+ }
catch (UnsupportedContentUrlException e)
{
// The store can't handle the content URL
@@ -335,7 +360,7 @@ public class AggregatingContentStore extends AbstractContentStore
{
try
{
- directAccessUrl = store.getDirectAccessUrl(contentUrl, expiresAt);
+ directAccessUrl = store.requestContentDirectUrl(contentUrl, attachment, fileName, validFor);
}
catch (UnsupportedOperationException e)
{
diff --git a/repository/src/main/java/org/alfresco/service/cmr/repository/ContentService.java b/repository/src/main/java/org/alfresco/service/cmr/repository/ContentService.java
index 81622ff41a..ce73035374 100644
--- a/repository/src/main/java/org/alfresco/service/cmr/repository/ContentService.java
+++ b/repository/src/main/java/org/alfresco/service/cmr/repository/ContentService.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2019 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,13 +25,13 @@
*/
package org.alfresco.service.cmr.repository;
+import java.util.Date;
+
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.service.Auditable;
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
import org.alfresco.service.namespace.QName;
-import java.util.Date;
-
/**
* Provides methods for accessing and transforming content.
*
@@ -168,6 +168,48 @@ public interface ContentService
* @return A direct access URL object for a binary content or returns null if not supported
* @throws IllegalArgumentException if there is no binary content for the node
*/
+ @Deprecated
@Auditable(parameters = {"nodeRef", "expiresAt"})
public DirectAccessUrl getDirectAccessUrl(NodeRef nodeRef, Date expiresAt);
+
+ /**
+ * Checks if the system and at least one store supports the retrieving of direct access URLs.
+ *
+ * @return {@code true} if direct access URLs retrieving is supported, {@code false} otherwise
+ */
+ boolean isContentDirectUrlEnabled();
+
+ /**
+ * Checks if the system and store supports the retrieving of a direct access {@code URL} for the given node.
+ *
+ * @return {@code true} if direct access URLs retrieving is supported for the node, {@code false} otherwise
+ */
+ boolean isContentDirectUrlEnabled(NodeRef nodeRef);
+
+ /**
+ * Gets a presigned URL to directly access the content. It is up to the actual store
+ * implementation if it can fulfil this request with an expiry time or not.
+ *
+ * @param nodeRef Node ref for which to obtain the direct access {@code URL}.
+ * @param attachment {@code true} if an attachment URL is requested, {@code false} for an embedded {@code URL}.
+ * @return A direct access {@code URL} object for the content.
+ * @throws UnsupportedOperationException if the store is unable to provide the information.
+ */
+ default DirectAccessUrl requestContentDirectUrl(NodeRef nodeRef, boolean attachment)
+ {
+ return requestContentDirectUrl(nodeRef, attachment, null);
+ }
+
+ /**
+ * Gets a presigned URL to directly access the content. It is up to the actual store
+ * implementation if it can fulfil this request with an expiry time or not.
+ *
+ * @param nodeRef Node ref for which to obtain the direct access {@code URL}.
+ * @param attachment {@code true} if an attachment URL is requested, {@code false} for an embedded {@code URL}.
+ * @param validFor The time at which the direct access {@code URL} will expire.
+ * @return A direct access {@code URL} object for the content.
+ * @throws UnsupportedOperationException if the store is unable to provide the information.
+ */
+ @Auditable(parameters = {"nodeRef", "validFor"})
+ DirectAccessUrl requestContentDirectUrl(NodeRef nodeRef, boolean attachment, Long validFor);
}
diff --git a/repository/src/main/resources/alfresco/content-services-context.xml b/repository/src/main/resources/alfresco/content-services-context.xml
index aed14cdd9e..a086db2e41 100644
--- a/repository/src/main/resources/alfresco/content-services-context.xml
+++ b/repository/src/main/resources/alfresco/content-services-context.xml
@@ -1,359 +1,376 @@
-
-
-
-
-
-
- false
-
-
- ContentStore
-
-
-
- ${filecontentstore.subsystem.name}
-
-
-
- manager
-
-
-
-
-
-
-
- true
-
-
- ContentStore
-
-
- unencrypted
-
-
-
- managed
- unencrypted
-
-
-
-
-
-
-
-
-
-
- fileContentStore
-
-
-
- org.alfresco.repo.content.ContentStore
- org.alfresco.repo.content.ContentStoreCaps
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${dir.contentstore.deleted}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${system.content.orphanProtectDays}
-
-
- ${system.content.deletionFailureAction}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${system.content.cleanerBatchSize}
-
-
-
-
-
- ${system.content.eagerOrphanCleanup}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${policy.content.update.ignoreEmpty}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- UTF-8
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- classpath:alfresco/mimetype/mimetype-map.xml
- classpath:alfresco/mimetype/mimetype-map-openoffice.xml
- classpath*:alfresco/module/*/mimetype-map*.xml
- classpath*:alfresco/extension/mimetype/*-map.xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- classpath:alfresco/ml/content-filter-lang.xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- org.alfresco.repo.content.transform.TransformerConfigMBean
-
-
-
-
-
-
-
-
-
-
- transformerDebugLog
-
-
-
- org.apache.commons.logging.Log
-
-
-
-
-
-
-
-
-
-
- transformerLog
-
-
-
- org.apache.commons.logging.Log
-
-
-
-
-
-
+
+
+
+
+
+
+ false
+
+
+ ContentStore
+
+
+
+ ${filecontentstore.subsystem.name}
+
+
+
+ manager
+
+
+
+
+
+
+
+ true
+
+
+ ContentStore
+
+
+ unencrypted
+
+
+
+ managed
+ unencrypted
+
+
+
+
+
+
+
+
+
+
+ fileContentStore
+
+
+
+ org.alfresco.repo.content.ContentStore
+ org.alfresco.repo.content.ContentStoreCaps
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${dir.contentstore.deleted}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${system.content.orphanProtectDays}
+
+
+ ${system.content.deletionFailureAction}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${system.content.cleanerBatchSize}
+
+
+
+
+
+ ${system.content.eagerOrphanCleanup}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${policy.content.update.ignoreEmpty}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ classpath:alfresco/mimetype/mimetype-map.xml
+ classpath:alfresco/mimetype/mimetype-map-openoffice.xml
+ classpath*:alfresco/module/*/mimetype-map*.xml
+ classpath*:alfresco/extension/mimetype/*-map.xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ classpath:alfresco/ml/content-filter-lang.xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.alfresco.repo.content.transform.TransformerConfigMBean
+
+
+
+
+
+
+
+
+
+
+ transformerDebugLog
+
+
+
+ org.apache.commons.logging.Log
+
+
+
+
+
+
+
+
+
+
+ transformerLog
+
+
+
+ org.apache.commons.logging.Log
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/repository/src/main/resources/alfresco/public-services-security-context.xml b/repository/src/main/resources/alfresco/public-services-security-context.xml
index 0129319643..b6e32f9d37 100644
--- a/repository/src/main/resources/alfresco/public-services-security-context.xml
+++ b/repository/src/main/resources/alfresco/public-services-security-context.xml
@@ -494,8 +494,9 @@
org.alfresco.service.cmr.repository.ContentService.getRawReader=ACL_METHOD.ROLE_ADMINISTRATOR
org.alfresco.service.cmr.repository.ContentService.getReader=ACL_NODE.0.sys:base.ReadContent
org.alfresco.service.cmr.repository.ContentService.getWriter=ACL_NODE.0.sys:base.WriteContent
- org.alfresco.service.cmr.repository.ContentService.getDirectAccessUrl=ACL_NODE.0.sys:base.ReadContent
org.alfresco.service.cmr.repository.ContentService.getTempWriter=ACL_ALLOW
+ org.alfresco.service.cmr.repository.ContentService.requestContentDirectUrl=ACL_NODE.0.sys:base.ReadContent
+ org.alfresco.service.cmr.repository.ContentService.isContentDirectUrlEnabled=ACL_ALLOW
org.alfresco.service.cmr.repository.ContentService.*=ACL_DENY
diff --git a/repository/src/main/resources/alfresco/repository.properties b/repository/src/main/resources/alfresco/repository.properties
index ef6bade8a1..b95cbf72ae 100644
--- a/repository/src/main/resources/alfresco/repository.properties
+++ b/repository/src/main/resources/alfresco/repository.properties
@@ -1,1247 +1,1310 @@
-# Repository configuration
-
-repository.name=Main Repository
-
-# Schema number
-version.schema=15001
-
-# Directory configuration
-
-dir.root=./alf_data
-
-dir.contentstore=${dir.root}/contentstore
-dir.contentstore.deleted=${dir.root}/contentstore.deleted
-dir.contentstore.bucketsPerMinute=0
-
-# ContentStore subsystem: default choice
-filecontentstore.subsystem.name=unencryptedContentStore
-
-# The location of cached content
-dir.cachedcontent=${dir.root}/cachedcontent
-
-# The value for the maximum permitted size in bytes of all content.
-# No value (or a negative long) will be taken to mean that no limit should be applied.
-# See content-services-context.xml
-system.content.maximumFileSizeLimit=
-
-#
-# The server mode. Set value in alfresco-global.properties
-# UNKNOWN | TEST | BACKUP | PRODUCTION
-#
-system.serverMode=UNKNOWN
-
-# The location for lucene index files
-dir.indexes=${dir.root}/lucene-indexes
-
-# The location for index backups
-dir.indexes.backup=${dir.root}/backup-lucene-indexes
-
-# The location for lucene index locks
-dir.indexes.lock=${dir.indexes}/locks
-
-#Directory to find external license
-dir.license.external=.
-# Spring resource location of external license files
-location.license.external=file://${dir.license.external}/*.lic
-# Spring resource location of embedded license files
-location.license.embedded=/WEB-INF/alfresco/license/*.lic
-# Spring resource location of license files on shared classpath
-location.license.shared=classpath*:/alfresco/extension/license/*.lic
-
-# WebDAV initialization properties
-system.webdav.servlet.enabled=true
-system.webdav.url.path.prefix=
-system.webdav.storeName=${protocols.storeName}
-system.webdav.rootPath=${protocols.rootPath}
-# File name patterns that trigger rename shuffle detection
-# pattern is used by move - tested against full path after it has been lower cased.
-system.webdav.renameShufflePattern=(.*/\\..*)|(.*[a-f0-9]{8}+$)|(.*\\.tmp$)|(.*atmp[0-9]+$)|(.*\\.wbk$)|(.*\\.bak$)|(.*\\~$)|(.*backup.*\\.do[ct]{1}[x]?[m]?$)|(.*\\.sb\\-\\w{8}\\-\\w{6}$)
-system.webdav.activities.enabled=false
-
-
-system.workflow.jbpm.comment.property.max.length=-1
-system.workflow.comment.property.max.length=4000
-
-#Determines if Activiti definitions are visible
-system.workflow.engine.activiti.definitions.visible=true
-
-
-# Determines if the Activiti engine is enabled
-system.workflow.engine.activiti.enabled=true
-system.workflow.engine.activiti.idblocksize=100
-system.workflow.engine.activiti.taskvariableslimit=20000
-
-# Determines if the workflows that are deployed to the activiti engine should
-# be deployed in the tenant-context of the thread IF the tenant-service is enabled
-# If set to false, all workflows deployed will be shared among tenants. Recommended
-# setting is true unless there is a good reason to not allow deploy tenant-specific
-# worklfows when a MT-environment is set up.
-system.workflow.deployWorkflowsInTenant=true
-#Determines if historic process instance are retained in case of canceling a process instance
-system.workflow.engine.activiti.retentionHistoricProcessInstance=false
-
-# The maximum number of groups to check for pooled tasks. For performance
-# reasons, this is limited to 500 by default.
-system.workflow.maxAuthoritiesForPooledTasks=500
-
-# The maximum number of pooled tasks to return in a query. It may be necessary
-# to limit this depending on UI limitations.
-system.workflow.maxPooledTasks=-1
-
-# The maximum number of reviewers for "Group Review and Approve" workflow.
-# Use '0' for unlimited.
-system.workflow.maxGroupReviewers=0
-
-index.subsystem.name=noindex
-
-# ######################################### #
-# Index Tracking Configuration #
-# ######################################### #
-#
-# Index tracking information of a certain age is cleaned out by a scheduled job.
-# Any clustered system that has been offline for longer than this period will need to be seeded
-# with a more recent backup of the Lucene indexes or the indexes will have to be fully rebuilt.
-# Use -1 to disable purging. This can be switched on at any stage.
-index.tracking.minRecordPurgeAgeDays=30
-# Unused transactions will be purged in chunks determined by commit time boundaries. 'index.tracking.purgeSize' specifies the size
-# of the chunk (in ms). Default is a couple of hours.
-index.tracking.purgeSize=7200000
-
-# Change the failure behaviour of the configuration checker
-system.bootstrap.config_check.strict=true
-
-
-#
-# How long should shutdown wait to complete normally before
-# taking stronger action and calling System.exit()
-# in ms, 10,000 is 10 seconds
-#
-shutdown.backstop.timeout=10000
-shutdown.backstop.enabled=false
-
-# Server Single User Mode
-# note:
-# only allow named user (note: if blank or not set then will allow all users)
-# assuming maxusers is not set to 0
-#server.singleuseronly.name=admin
-
-# Server Max Users - limit number of users with non-expired tickets
-# note:
-# -1 allows any number of users, assuming not in single-user mode
-# 0 prevents further logins, including the ability to enter single-user mode
-server.maxusers=-1
-
-#
-# Disable all shared caches (mutable and immutable)
-# These properties are used for diagnostic purposes
-system.cache.disableMutableSharedCaches=false
-system.cache.disableImmutableSharedCaches=false
-
-# The maximum capacity of the parent assocs cache (the number of nodes whose parents can be cached)
-system.cache.parentAssocs.maxSize=130000
-
-# The average number of parents expected per cache entry. This parameter is multiplied by the above
-# value to compute a limit on the total number of cached parents, which will be proportional to the
-# cache's memory usage. The cache will be pruned when this limit is exceeded to avoid excessive
-# memory usage.
-system.cache.parentAssocs.limitFactor=8
-
-#
-# Properties to limit resources spent on individual searches
-#
-# The maximum time spent pruning results
-system.acl.maxPermissionCheckTimeMillis=10000
-# The maximum number of search results to perform permission checks against
-system.acl.maxPermissionChecks=1000
-system.acl.maxPermissionCheckEnabled=false
-
-# The maximum number of filefolder list results
-system.filefolderservice.defaultListMaxResults=5000
-# DEPRECATED: Use 'system.auditableData.preserve'
-system.preserve.modificationData=false
-# The default to preserve all cm:auditable data on a node when the process is not directly driven by a user action
-system.auditableData.preserve=${system.preserve.modificationData}
-# Specific control of how the FileFolderService treats cm:auditable data when performing moves
-system.auditableData.FileFolderService=${system.auditableData.preserve}
-# Specific control of whether ACL changes on a node trigger the cm:auditable aspect
-system.auditableData.ACLs=${system.auditableData.preserve}
-
-# Properties to control read permission evaluation for acegi
-system.readpermissions.optimise=true
-system.readpermissions.bulkfetchsize=1000
-
-#
-# Manually control how the system handles maximum string lengths.
-# Any zero or negative value is ignored.
-# Only change this after consulting support or reading the appropriate Javadocs for
-# org.alfresco.repo.domain.schema.SchemaBootstrap for V2.1.2.
-# Before database migration, the string value storage may need to be adjusted using the scheduled job
-system.maximumStringLength=-1
-system.maximumStringLength.jobCronExpression=* * * * * ? 2099
-system.maximumStringLength.jobQueryRange=10000
-system.maximumStringLength.jobThreadCount=4
-
-#
-# Limit hibernate session size by trying to amalgamate events for the L2 session invalidation
-# - hibernate works as is up to this size
-# - after the limit is hit events that can be grouped invalidate the L2 cache by type and not instance
-# events may not group if there are post action listener registered (this is not the case with the default distribution)
-system.hibernateMaxExecutions=20000
-
-#
-# Determine if modification timestamp propagation from child to parent nodes is respected or not.
-# Even if 'true', the functionality is only supported for child associations that declare the
-# 'propagateTimestamps' element in the dictionary definition.
-system.enableTimestampPropagation=true
-
-#
-# Enable system model integrity checking.
-# WARNING: Changing this is unsupported; bugs may corrupt data
-system.integrity.enabled=true
-# Do integrity violations fail transactions
-# WARNING: Changing this is unsupported; bugs may corrupt data
-system.integrity.failOnViolation=true
-# The number of errors to report when violations are detected
-system.integrity.maxErrorsPerTransaction=5
-# Add call stacks to integrity events so that errors are logged with possible causes
-# WARNING: This is expensive and should only be switched on for diagnostic purposes
-system.integrity.trace=false
-
-#
-# Decide if content should be removed from the system immediately after being orphaned.
-# Do not change this unless you have examined the impact it has on your backup procedures.
-system.content.eagerOrphanCleanup=false
-# The number of days to keep orphaned content in the content stores.
-# This has no effect on the 'deleted' content stores, which are not automatically emptied.
-system.content.orphanProtectDays=14
-# The action to take when a store or stores fails to delete orphaned content
-# IGNORE: Just log a warning. The binary remains and the record is expunged
-# KEEP_URL: Log a warning and create a URL entry with orphan time 0. It won't be processed or removed.
-system.content.deletionFailureAction=IGNORE
-# The CRON expression to trigger the deletion of resources associated with orphaned content.
-system.content.orphanCleanup.cronExpression=0 0 4 * * ?
-# The batch size user by the content store cleaner
-system.content.cleanerBatchSize=1000
-
-# The CRON expression to trigger the cleanup of deleted nodes and dangling transactions that are old enough
-system.nodeServiceCleanup.cronExpression=0 0 21 * * ?
-
-# When transforming archive files (.zip etc) into text representations (such as
-# for full text indexing), should the files within the archive be processed too?
-# If enabled, transformation takes longer, but searches of the files find more.
-transformer.Archive.includeContents=false
-
-# Database configuration
-db.schema.name=
-db.schema.stopAfterSchemaBootstrap=false
-db.schema.update=true
-db.schema.update.lockRetryCount=24
-db.schema.update.lockRetryWaitSeconds=5
-db.driver=org.gjt.mm.mysql.Driver
-db.name=alfresco
-db.url=jdbc:mysql:///${db.name}
-db.username=alfresco
-db.password=alfresco
-db.pool.initial=10
-db.pool.max=275
-db.txn.isolation=-1
-db.pool.statements.enable=true
-db.pool.statements.max=40
-db.pool.min=10
-db.pool.idle=10
-db.pool.wait.max=5000
-
-db.pool.validate.query=
-db.pool.evict.interval=600000
-db.pool.evict.idle.min=1800000
-#
-# note: for 'db.pool.evict.num.tests' see http://commons.apache.org/dbcp/configuration.html (numTestsPerEvictionRun)
-# and also following extract from "org.apache.commons.pool.impl.GenericKeyedObjectPool" (1.5.5)
-#
-# * The number of objects to examine during each run of the idle object evictor thread (if any).
-# * When a negative value is supplied, ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})
-# * tests will be run. I.e., when the value is -n
, roughly one n
th of the
-# * idle objects will be tested per run.
-#
-db.pool.evict.num.tests=-1
-
-db.pool.evict.validate=false
-db.pool.validate.borrow=true
-db.pool.validate.return=false
-
-db.pool.abandoned.detect=false
-db.pool.abandoned.time=300
-#
-# db.pool.abandoned.log=true (logAbandoned) adds overhead (http://commons.apache.org/dbcp/configuration.html)
-# and also requires db.pool.abandoned.detect=true (removeAbandoned)
-#
-db.pool.abandoned.log=false
-
-
-# Audit configuration
-audit.enabled=true
-audit.tagging.enabled=true
-audit.alfresco-access.enabled=false
-audit.alfresco-access.sub-actions.enabled=false
-audit.cmischangelog.enabled=false
-audit.dod5015.enabled=false
-# Setting this flag to true will force startup failure when invalid audit configurations are detected
-audit.config.strict=false
-# Audit map filter for AccessAuditor - restricts recorded events to user driven events
-audit.filter.alfresco-access.default.enabled=false
-audit.filter.alfresco-access.transaction.user=~System;~null;.*
-audit.filter.alfresco-access.transaction.type=cm:folder;cm:content;st:site
-audit.filter.alfresco-access.transaction.path=~/sys:archivedItem;~/ver:;.*
-
-
-# System Configuration
-system.store=system://system
-system.descriptor.childname=sys:descriptor
-system.descriptor.current.childname=sys:descriptor-current
-
-# User config
-alfresco_user_store.store=user://alfrescoUserStore
-alfresco_user_store.system_container.childname=sys:system
-alfresco_user_store.user_container.childname=sys:people
-
-# note: default admin username - should not be changed after installation
-alfresco_user_store.adminusername=admin
-
-# Initial password - editing this will not have any effect once the repository is installed
-alfresco_user_store.adminpassword=209c6174da490caeb422f3fa5a7ae634
-
-# note: default guest username - should not be changed after installation
-alfresco_user_store.guestusername=guest
-
-# Used to move home folders to a new location
-home_folder_provider_synchronizer.enabled=false
-home_folder_provider_synchronizer.override_provider=
-home_folder_provider_synchronizer.keep_empty_parents=false
-
-# Spaces Archive Configuration
-spaces.archive.store=archive://SpacesStore
-
-# Spaces Configuration
-spaces.store=workspace://SpacesStore
-spaces.company_home.childname=app:company_home
-spaces.guest_home.childname=app:guest_home
-spaces.dictionary.childname=app:dictionary
-spaces.templates.childname=app:space_templates
-spaces.imap_attachments.childname=cm:Imap Attachments
-spaces.imap_home.childname=cm:Imap Home
-spaces.imapConfig.childname=app:imap_configs
-spaces.imap_templates.childname=app:imap_templates
-spaces.scheduled_actions.childname=cm:Scheduled Actions
-spaces.emailActions.childname=app:email_actions
-spaces.searchAction.childname=cm:search
-spaces.templates.content.childname=app:content_templates
-spaces.templates.email.childname=app:email_templates
-spaces.templates.email.invite1.childname=app:invite_email_templates
-spaces.templates.email.notify.childname=app:notify_email_templates
-spaces.templates.email.following.childname=app:following
-spaces.templates.rss.childname=app:rss_templates
-spaces.savedsearches.childname=app:saved_searches
-spaces.scripts.childname=app:scripts
-spaces.content_forms.childname=app:forms
-spaces.user_homes.childname=app:user_homes
-spaces.user_homes.regex.key=userName
-spaces.user_homes.regex.pattern=
-spaces.user_homes.regex.group_order=
-spaces.sites.childname=st:sites
-spaces.templates.email.invite.childname=cm:invite
-spaces.templates.email.activities.childname=cm:activities
-spaces.rendition.rendering_actions.childname=app:rendering_actions
-spaces.replication.replication_actions.childname=app:replication_actions
-spaces.transfers.childname=app:transfers
-spaces.transfer_groups.childname=app:transfer_groups
-spaces.transfer_temp.childname=app:temp
-spaces.inbound_transfer_records.childname=app:inbound_transfer_records
-spaces.webscripts.childname=cm:webscripts
-spaces.extension_webscripts.childname=cm:extensionwebscripts
-spaces.models.childname=app:models
-spaces.workflow.definitions.childname=app:workflow_defs
-spaces.templates.email.workflowemailnotification.childname=cm:workflownotification
-spaces.nodetemplates.childname=app:node_templates
-spaces.shared.childname=app:shared
-spaces.solr_facets.root.childname=srft:facets
-spaces.smartfolders.childname=app:smart_folders
-spaces.smartdownloads.childname=app:smart_downloads
-spaces.transfer_summary_report.location=/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.inbound_transfer_records.childname}
-spaces.quickshare.link_expiry_actions.childname=app:quick_share_link_expiry_actions
-
-
-# ADM VersionStore Configuration
-version.store.initialVersion=true
-version.store.enableAutoVersioning=true
-version.store.enableAutoVersionOnUpdateProps=false
-version.store.deprecated.lightWeightVersionStore=workspace://lightWeightVersionStore
-version.store.version2Store=workspace://version2Store
-
-# Optional Comparator class name to sort versions.
-# Set to: org.alfresco.repo.version.common.VersionLabelComparator
-# if upgrading from a version that used unordered sequences in a cluster.
-version.store.versionComparatorClass=
-
-# Folders for storing people
-system.system_container.childname=sys:system
-system.people_container.childname=sys:people
-system.authorities_container.childname=sys:authorities
-system.zones_container.childname=sys:zones
-
-# Folders for storing workflow related info
-system.workflow_container.childname=sys:workflow
-
-# Folder for storing shared remote credentials
-system.remote_credentials_container.childname=sys:remote_credentials
-
-# Folder for storing syncset definitions
-system.syncset_definition_container.childname=sys:syncset_definitions
-
-# Folder for storing download archives
-system.downloads_container.childname=sys:downloads
-
-# Folder for storing IdP's certificate definitions
-system.certificate_container.childname=sys:samlcertificate
-
-# Are user names case sensitive?
-user.name.caseSensitive=false
-domain.name.caseSensitive=false
-domain.separator=
-
-#Format caption extracted from the XML Schema.
-xforms.formatCaption=true
-
-# ECM content usages/quotas
-system.usages.enabled=false
-system.usages.clearBatchSize=0
-system.usages.updateBatchSize=50
-
-# Repository endpoint - used by Activity Service
-repo.remote.endpoint=/service
-
-# Some authentication mechanisms may need to create people
-# in the repository on demand. This enables that feature.
-# If disabled an error will be generated for missing
-# people. If enabled then a person will be created and
-# persisted.
-create.missing.people=${server.transaction.allow-writes}
-
-# Create home folders (unless disabled, see next property) as people are created (true) or create them lazily (false)
-home.folder.creation.eager=true
-# Disable home folder creation - if true then home folders are not created (neither eagerly nor lazily)
-home.folder.creation.disabled=false
-
-# Should we consider zero byte content to be the same as no content when firing
-# content update policies? Prevents 'premature' firing of inbound content rules
-# for some clients such as Mac OS X Finder
-policy.content.update.ignoreEmpty=true
-
-# Default value of alfresco.rmi.services.host is 0.0.0.0 which means 'listen on all adapters'.
-# This allows connections to JMX both remotely and locally.
-#
-alfresco.rmi.services.port=50500
-alfresco.rmi.services.external.host=localhost
-alfresco.rmi.services.host=0.0.0.0
-
-# If the RMI address is in-use, how many retries should be done before aborting
-# Default value of alfresco.rmi.services.retries is 0 which means 'Don't retry if the address is in-use'
-alfresco.rmi.services.retries=4
-# How long in milliseconds to wait after a failed server socket bind, before retrying
-alfresco.rmi.services.retryInterval=250
-
-# RMI service ports for the individual services.
-# These eight services are available remotely.
-#
-# Assign individual ports for each service for best performance
-# or run several services on the same port, you can even run everything on 50500 if
-# running through a firewall.
-#
-# Specify 0 to use a random unused port.
-#
-monitor.rmi.service.port=50508
-
-#
-# enable or disable individual RMI services
-#
-monitor.rmi.service.enabled=false
-
-
-# Should the Mbean server bind to an existing server. Set to true for most application servers.
-# false for WebSphere clusters.
-mbean.server.locateExistingServerIfPossible=true
-
-# Rendition Service 2
-renditionService2.enabled=true
-
-# Thumbnail Service
-system.thumbnail.generate=true
-
-# when creating doc via CMIS - optionally configure set of renditions names to request async
-cmis.create.doc.request.renditions.set=
-
-# Default thumbnail limits
-# When creating thumbnails, only use the first pageLimit pages
-system.thumbnail.definition.default.timeoutMs=-1
-system.thumbnail.definition.default.readLimitTimeMs=-1
-system.thumbnail.definition.default.maxSourceSizeKBytes=-1
-system.thumbnail.definition.default.readLimitKBytes=-1
-system.thumbnail.definition.default.pageLimit=-1
-system.thumbnail.definition.default.maxPages=-1
-
-# Max mimetype sizes to create thumbnail icons
-system.thumbnail.mimetype.maxSourceSizeKBytes.pdf=-1
-system.thumbnail.mimetype.maxSourceSizeKBytes.txt=-1
-system.thumbnail.mimetype.maxSourceSizeKBytes.docx=-1
-system.thumbnail.mimetype.maxSourceSizeKBytes.xlsx=-1
-system.thumbnail.mimetype.maxSourceSizeKBytes.pptx=-1
-system.thumbnail.mimetype.maxSourceSizeKBytes.odt=-1
-system.thumbnail.mimetype.maxSourceSizeKBytes.ods=-1
-system.thumbnail.mimetype.maxSourceSizeKBytes.odp=-1
-
-# Configuration for handling of failing thumbnails.
-# See NodeEligibleForRethumbnailingEvaluator's javadoc for details.
-#
-# Retry periods limit the frequency with which the repository will attempt to create Share thumbnails
-# for content nodes which have previously failed in their thumbnail attempts.
-# These periods are in seconds.
-#
-# 604800s = 60s * 60m * 24h * 7d = 1 week
-system.thumbnail.retryPeriod=60
-system.thumbnail.retryCount=2
-system.thumbnail.quietPeriod=604800
-system.thumbnail.quietPeriodRetriesEnabled=true
-system.thumbnail.redeployStaticDefsOnStartup=true
-
-content.metadata.async.extract.enabled=true
-content.metadata.async.embed.enabled=true
-
-# The default timeout for metadata mapping extracters
-content.metadataExtracter.default.timeoutMs=20000
-
-# Local transformer urls to T-engines to service transform requests via http. Enabled by default.
-localTransform.core-aio.url=http://localhost:8090/
-
-# When a local transformer .url is set, this value indicates the amount of time to wait after a connection failure
-# before retrying the connection to allow a docker container to (re)start.
-localTransform.core-aio.startupRetryPeriodSeconds=60
-
-# Property to enable upgrade from 2.1-A
-V2.1-A.fixes.to.schema=0
-#V2.1-A.fixes.to.schema=82
-
-# The default authentication chain
-authentication.chain=alfrescoNtlm1:alfrescoNtlm
-
-# Do authentication tickets expire or live for ever?
-authentication.ticket.ticketsExpire=true
-
-# If ticketsEpire is true then how they should expire?
-# Valid values are: AFTER_INACTIVITY, AFTER_FIXED_TIME, DO_NOT_EXPIRE
-# The default is AFTER_FIXED_TIME
-authentication.ticket.expiryMode=AFTER_INACTIVITY
-
-# If authentication.ticket.ticketsExpire is true and
-# authentication.ticket.expiryMode is AFTER_FIXED_TIME or AFTER_INACTIVITY,
-# this controls the minimum period for which tickets are valid.
-# The default is PT1H for one hour.
-authentication.ticket.validDuration=PT1H
-
-# Use one ticket for all user sessions
-# For the pre 4.2 behaviour of one ticket per session set this to false.
-authentication.ticket.useSingleTicketPerUser=true
-
-authentication.alwaysAllowBasicAuthForAdminConsole.enabled=true
-authentication.getRemoteUserTimeoutMilliseconds=10000
-
-# FTP access
-ftp.enabled=false
-
-# Default root path for protocols
-protocols.storeName=${spaces.store}
-protocols.rootPath=/${spaces.company_home.childname}
-
-# OpenCMIS
-opencmis.connector.default.store=${spaces.store}
-opencmis.connector.default.rootPath=/${spaces.company_home.childname}
-opencmis.connector.default.typesDefaultMaxItems=500
-opencmis.connector.default.typesDefaultDepth=-1
-opencmis.connector.default.objectsDefaultMaxItems=10000
-opencmis.connector.default.objectsDefaultDepth=100
-opencmis.connector.default.contentChangesDefaultMaxItems=10000
-opencmis.connector.default.openHttpSession=false
-opencmis.activities.enabled=true
-opencmis.bulkUpdateProperties.maxItemsSize=1000
-opencmis.bulkUpdateProperties.batchSize=20
-opencmis.bulkUpdateProperties.workerThreads=2
-opencmis.maxContentSizeMB=4096
-opencmis.memoryThresholdKB=4096
-
-# URL generation overrides
-
-# if true, the context path of OpenCMIS generated urls will be set to "opencmis.context.value", otherwise it will be taken from the request url
-opencmis.context.override=false
-opencmis.context.value=
-# if true, the servlet path of OpenCMIS generated urls will be set to "opencmis.servletpath.value", otherwise it will be taken from the request url
-opencmis.servletpath.override=false
-opencmis.servletpath.value=
-opencmis.server.override=false
-opencmis.server.value=
-
-# IMAP
-imap.server.enabled=false
-imap.server.port=143
-imap.server.attachments.extraction.enabled=true
-
-# Default IMAP mount points
-imap.config.home.store=${spaces.store}
-imap.config.home.rootPath=/${spaces.company_home.childname}
-imap.config.home.folderPath=${spaces.imap_home.childname}
-imap.config.server.mountPoints=AlfrescoIMAP
-imap.config.server.mountPoints.default.mountPointName=IMAP
-imap.config.server.mountPoints.default.modeName=ARCHIVE
-imap.config.server.mountPoints.default.store=${spaces.store}
-imap.config.server.mountPoints.default.rootPath=${protocols.rootPath}
-imap.config.server.mountPoints.value.AlfrescoIMAP.mountPointName=Alfresco IMAP
-imap.config.server.mountPoints.value.AlfrescoIMAP.modeName=MIXED
-
-#Imap extraction settings
-#imap.attachments.mode:
-# SEPARATE -- All attachments for each email will be extracted to separate folder.
-# COMMON -- All attachments for all emails will be extracted to one folder.
-# SAME -- Attachments will be extracted to the same folder where email lies.
-imap.attachments.mode=SEPARATE
-imap.attachments.folder.store=${spaces.store}
-imap.attachments.folder.rootPath=/${spaces.company_home.childname}
-imap.attachments.folder.folderPath=${spaces.imap_attachments.childname}
-
-# Activities Feed - refer to subsystem
-
-# Feed max ID range to limit maximum number of entries
-activities.feed.max.idRange=1000000
-# Feed max size (number of entries)
-activities.feed.max.size=200
-# Feed max age (eg. 44640 mins => 31 days)
-activities.feed.max.ageMins=44640
-
-activities.feed.generator.jsonFormatOnly=true
-activities.feed.fetchBatchSize=250
-activities.feedNotifier.batchSize=200
-activities.feedNotifier.numThreads=2
-
-# Subsystem unit test values. Will not have any effect on production servers
-subsystems.test.beanProp.default.longProperty=123456789123456789
-subsystems.test.beanProp.default.anotherStringProperty=Global Default
-subsystems.test.beanProp=inst1,inst2,inst3
-subsystems.test.beanProp.value.inst2.boolProperty=true
-subsystems.test.beanProp.value.inst3.anotherStringProperty=Global Instance Default
-subsystems.test.simpleProp2=true
-subsystems.test.simpleProp3=Global Default3
-
-# Default Async Action Thread Pool
-default.async.action.threadPriority=1
-default.async.action.corePoolSize=8
-default.async.action.maximumPoolSize=20
-
-# Deployment Service
-deployment.service.numberOfSendingThreads=5
-deployment.service.corePoolSize=2
-deployment.service.maximumPoolSize=3
-deployment.service.threadPriority=5
-# How long to wait in mS before refreshing a target lock - detects shutdown servers
-deployment.service.targetLockRefreshTime=60000
-# How long to wait in mS from the last communication before deciding that deployment has failed, possibly
-# the destination is no longer available?
-deployment.service.targetLockTimeout=3600000
-# Deployment method used to deploy this Alfresco instance (DEFAULT, INSTALLER, DOCKER_COMPOSE, HELM_CHART, ANSIBLE, ZIP, QUICK_START)
-deployment.method=DEFAULT
-
-#Invitation Service
-# Should send emails as part of invitation process.
-notification.email.siteinvite=true
-# Moderated invite Activiti workflow
-site.invite.moderated.workflowId=activiti$activitiInvitationModerated
-# Add intneral users Activiti workflow (use activiti$activitiInvitationNominated to revert to requiring accept of invite for internal users)
-site.invite.nominated.workflowId=activiti$activitiInvitationNominatedAddDirect
-# Add external users Activiti workflow
-site.invite.nominatedExternal.workflowId=activiti$activitiInvitationNominated
-
-# Replication Service
-replication.enabled=false
-
-# Transfer Service
-transferservice.receiver.enabled=false
-transferservice.receiver.stagingDir=${java.io.tmpdir}/alfresco-transfer-staging
-#
-# How long to wait in mS before refreshing a transfer lock - detects shutdown servers
-# Default 1 minute.
-transferservice.receiver.lockRefreshTime=60000
-#
-# How many times to attempt retry the transfer lock
-transferservice.receiver.lockRetryCount=3
-# How long to wait, in mS, before retrying the transfer lock
-transferservice.receiver.lockRetryWait=100
-#
-# How long to wait, in mS, since the last contact with from the client before
-# timing out a transfer. Needs to be long enough to cope with network delays and "thinking
-# time" for both source and destination. Default 5 minutes.
-transferservice.receiver.lockTimeOut=300000
-
-# OrphanReaper
-orphanReaper.lockRefreshTime=60000
-orphanReaper.lockTimeOut=3600000
-
-
-# security
-security.anyDenyDenies=true
-# Whether to post-process denies. Only applies to solr4+ when anyDenyDenies is true.
-security.postProcessDenies=false
-
-#
-# Encryption properties
-#
-# default keystores location
-dir.keystore=classpath:alfresco/keystore
-
-# general encryption parameters
-encryption.keySpec.class=org.alfresco.encryption.DESEDEKeyGenerator
-encryption.keyAlgorithm=AES
-encryption.cipherAlgorithm=AES/CBC/PKCS5Padding
-
-# secret key keystore configuration
-encryption.keystore.location=${dir.keystore}/keystore
-# configuration via metadata is deprecated
-encryption.keystore.keyMetaData.location=
-encryption.keystore.provider=
-encryption.keystore.type=pkcs12
-
-# backup secret key keystore configuration
-encryption.keystore.backup.location=${dir.keystore}/backup-keystore
-# configuration via metadata is deprecated
-encryption.keystore.backup.keyMetaData.location=
-encryption.keystore.backup.provider=
-encryption.keystore.backup.type=pkcs12
-
-# Should encryptable properties be re-encrypted with new encryption keys on botstrap?
-encryption.bootstrap.reencrypt=false
-
-# mac/md5 encryption
-encryption.mac.messageTimeout=30000
-encryption.mac.algorithm=HmacSHA1
-
-# ssl encryption
-encryption.ssl.keystore.location=${dir.keystore}/ssl.keystore
-encryption.ssl.keystore.provider=
-encryption.ssl.keystore.type=JCEKS
-# configuration via metadata is deprecated
-encryption.ssl.keystore.keyMetaData.location=
-encryption.ssl.truststore.location=${dir.keystore}/ssl.truststore
-encryption.ssl.truststore.provider=
-encryption.ssl.truststore.type=JCEKS
-# configuration via metadata is deprecated
-encryption.ssl.truststore.keyMetaData.location=
-
-# Re-encryptor properties
-encryption.reencryptor.chunkSize=100
-encryption.reencryptor.numThreads=2
-
-# SOLR connection details (e.g. for JMX)
-solr.host=localhost
-solr.port=8983
-solr.port.ssl=8984
-solr.solrUser=solr
-solr.solrPassword=solr
-# none, https
-solr.secureComms=https
-solr.sharedSecret=
-solr.sharedSecret.header=X-Alfresco-Search-Secret
-solr.cmis.alternativeDictionary=DEFAULT_DICTIONARY
-
-solr.max.total.connections=40
-solr.max.host.connections=40
-
-# Solr connection timeouts
-# solr connect timeout in ms
-solr.solrConnectTimeout=5000
-
-# cron expression defining how often the Solr Admin client (used by JMX) pings Solr if it goes away
-solr.solrPingCronExpression=0 0/5 * * * ? *
-
-
-#Default SOLR store mappings mappings
-solr.store.mappings=solrMappingAlfresco,solrMappingArchive
-solr.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory
-solr.store.mappings.value.solrMappingAlfresco.baseUrl=/solr/alfresco
-solr.store.mappings.value.solrMappingAlfresco.protocol=workspace
-solr.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore
-solr.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory
-solr.store.mappings.value.solrMappingArchive.baseUrl=/solr/archive
-solr.store.mappings.value.solrMappingArchive.protocol=archive
-solr.store.mappings.value.solrMappingArchive.identifier=SpacesStore
-
-#Default SOLR 4 store mappings mappings
-solr4.store.mappings=solrMappingAlfresco,solrMappingArchive
-solr4.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory
-solr4.store.mappings.value.solrMappingAlfresco.baseUrl=/solr4/alfresco
-solr4.store.mappings.value.solrMappingAlfresco.protocol=workspace
-solr4.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore
-solr4.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory
-solr4.store.mappings.value.solrMappingArchive.baseUrl=/solr4/archive
-solr4.store.mappings.value.solrMappingArchive.protocol=archive
-solr4.store.mappings.value.solrMappingArchive.identifier=SpacesStore
-
-#Default SOLR 6 store mappings mappings
-solr6.store.mappings=solrMappingAlfresco,solrMappingArchive,solrMappingHistory
-solr6.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory
-solr6.store.mappings.value.solrMappingAlfresco.baseUrl=/solr/alfresco
-solr6.store.mappings.value.solrMappingAlfresco.protocol=workspace
-solr6.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore
-solr6.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory
-solr6.store.mappings.value.solrMappingArchive.baseUrl=/solr/archive
-solr6.store.mappings.value.solrMappingArchive.protocol=archive
-solr6.store.mappings.value.solrMappingArchive.identifier=SpacesStore
-solr6.store.mappings.value.solrMappingHistory.httpClientFactory=solrHttpClientFactory
-solr6.store.mappings.value.solrMappingHistory.baseUrl=/solr/history
-solr6.store.mappings.value.solrMappingHistory.protocol=workspace
-solr6.store.mappings.value.solrMappingHistory.identifier=history
-
-#
-# URL Shortening Properties
-#
-urlshortening.bitly.username=brianalfresco
-urlshortening.bitly.api.key=R_ca15c6c89e9b25ccd170bafd209a0d4f
-urlshortening.bitly.url.length=20
-
-#
-# Bulk Filesystem Importer
-#
-
-# The number of threads to employ in a batch import
-bulkImport.batch.numThreads=4
-
-# The size of a batch in a batch import i.e. the number of files to import in a
-# transaction/thread
-bulkImport.batch.batchSize=20
-
-
-#
-# Caching Content Store
-#
-system.content.caching.cacheOnInbound=true
-system.content.caching.maxDeleteWatchCount=1
-# Clean up every day at 3 am
-system.content.caching.contentCleanup.cronExpression=0 0 3 * * ?
-system.content.caching.minFileAgeMillis=60000
-system.content.caching.maxUsageMB=4096
-# maxFileSizeMB - 0 means no max file size.
-system.content.caching.maxFileSizeMB=0
-# When the CachingContentStore is about to write a cache file but the disk usage is in excess of panicThresholdPct
-# (default 90%) then the cache file is not written and the cleaner is started (if not already running) in a new thread.
-system.content.caching.panicThresholdPct=90
-# When a cache file has been written that results in cleanThresholdPct (default 80%) of maxUsageBytes
-# being exceeded then the cached content cleaner is invoked (if not already running) in a new thread.
-system.content.caching.cleanThresholdPct=80
-# An aggressive cleaner is run till the targetUsagePct (default 70%) of maxUsageBytes is achieved
-system.content.caching.targetUsagePct=70
-# Threshold in seconds indicating a minimal gap between normal cleanup starts
-system.content.caching.normalCleanThresholdSec=0
-
-mybatis.useLocalCaches=false
-
-fileFolderService.checkHidden.enabled=true
-
-
-ticket.cleanup.cronExpression=0 0 * * * ?
-
-#
-# Download Service Cleanup
-#
-download.cleaner.startDelayMilliseconds=3600000
-# 1 hour
-download.cleaner.repeatIntervalMilliseconds=3600000
-download.cleaner.maxAgeMins=60
-# -1 or 0 for not using batches
-download.cleaner.batchSize=1000
-
-# you could set this to false for new installations greater then ACS 6.2
-# see MNT-20212
-download.cleaner.cleanAllSysDownloadFolders=true
-
-#
-# Download Service Limits, in bytes
-#
-download.maxContentSize=2152852358
-
-# Max size of view trashcan files
-#
-trashcan.MaxSize=1000
-
-#
-# Use bridge tables for caching authority evaluation.
-#
-authority.useBridgeTable=true
-
-# Limit the number of results from findAuthority query
-authority.findAuthorityLimit=10000
-
-# enable QuickShare - if false then the QuickShare-specific REST APIs will return 403 Forbidden
-system.quickshare.enabled=true
-system.quickshare.email.from.default=noreply@alfresco.com
-# By default the difference between the quick share expiry date and the current time must be at least 1 day (24 hours).
-# However, this can be changed to at least 1 hour or 1 minute for testing purposes. For example,
-# setting the value to MINUTES, means the service will calculate the difference between NOW and the given expiry date
-# in terms of minutes and checks for the difference to be greater than 1 minute.
-# DAYS | HOURS | MINUTES
-system.quickshare.expiry_date.enforce.minimum.period=DAYS
-
-# Oubound Mail
-mail.service.corePoolSize=8
-mail.service.maximumPoolSize=20
-
-nodes.bulkLoad.cachingThreshold=10
-
-# Multi-Tenancy
-
-# if "dir.contentstore.tenants" is set then
-# tenants are not co-mingled and all content roots will appear below this container (in sub-folder)
-# and when creating a tenant the "contentRootPath" (root content store directory for a given tenant) will be ignored
-dir.contentstore.tenants=
-
-# Gateway Authentication
-# gateway authentication is disabled if empty host is specified
-alfresco.authentication.gateway.host=
-alfresco.authentication.gateway.protocol=https
-alfresco.authentication.gateway.port=443
-alfresco.authentication.gateway.outboundHeaders=Authorization,key
-alfresco.authentication.gateway.inboundHeaders=X-Alfresco-Authenticator-Key,X-Alfresco-Remote-User
-alfresco.authentication.gateway.prefixUrl=/publicapi
-alfresco.authentication.gateway.bufferSize=2048
-alfresco.authentication.gateway.connectTimeout=10000
-alfresco.authentication.gateway.readTimeout=120000
-alfresco.authentication.gateway.httpTcpNodelay=true
-alfresco.authentication.gateway.httpConnectionStalecheck=true
-
-# webscripts config
-webscripts.encryptTempFiles=false
-webscripts.tempDirectoryName=Alfresco-WebScripts
-# 4mb
-webscripts.memoryThreshold=4194304
-# 4gb
-webscripts.setMaxContentSize=5368709120
-
-# Property to enable index upgrade for metadata query (MDQ)
-#
-# The indexes are not added unless this value is changed
-# Adding each the supporting indexes may take several hours depending on the size of the database.
-# The required indexes may be added in stages.
-# See: classpath:alfresco/dbscripts/upgrade/4.2/${db.script.dialect}/metadata-query-indexes.sql
-# See: classpath:alfresco/dbscripts/upgrade/5.1/${db.script.dialect}/metadata-query-indexes-2.sql
-system.metadata-query-indexes.ignored=true
-system.metadata-query-indexes-more.ignored=true
-
-#
-# Do we defer running the shared folder patch?
-#
-system.patch.sharedFolder.deferred=false
-# Default value is run new years day 2030 i.e. not run.
-system.patch.sharedFolder.cronExpression=0 0 0 ? 1 1 2030
-
-#
-# Default values for deferring the running of the addUnmovableAspect patch
-#
-system.patch.addUnmovableAspect.deferred=false
-system.patch.addUnmovableAspect.cronExpression=0 0 0 ? 1 1 2030
-
-# Property to enable removal of all JBPM related data from the database
-#
-# The tables are not removed from the databasen unless explicitly requested by setting this property to false.
-# See: classpath:alfresco/dbscripts/upgrade/5.2/${db.script.dialect}/remove-jbpm-tables-from-db.sql
-system.remove-jbpm-tables-from-db.ignored=true
-
-#
-# Use a canned query when requested to search for people if " [hint:useCQ]" is provided in search term
-#
-people.search.honor.hint.useCQ=true
-
-# Delays cron jobs after bootstrap to allow server to fully come up before jobs start
-system.cronJob.startDelayMilliseconds=60000
-
-# Schedule for reading mimetype config definitions dynamically. Initially checks every 10 seconds and then switches to
-# every hour after the configuration is read successfully. If there is a error later reading the config, the
-# checks return to every 10 seconds.
-mimetype.config.cronExpression=0 30 0/1 * * ?
-mimetype.config.initialAndOnError.cronExpression=0/10 * * * * ?
-
-# Optional property to specify an external file or directory that will be read for mimetype definitions from YAML
-# files (possibly added to a volume via k8 ConfigMaps).
-mimetype.config.dir=shared/classes/alfresco/extension/mimetypes
-
-# Schedule for reading rendition config definitions dynamically. Initially checks every 10 seconds and then switches to
-# every hour after the configuration is read successfully. If there is a error later reading the config, the
-# checks return to every 10 seconds.
-rendition.config.cronExpression=2 30 0/1 * * ?
-rendition.config.initialAndOnError.cronExpression=0/10 * * * * ?
-
-# Optional property to specify an external file or directory that will be read for rendition definitions from YAML
-# files (possibly added to a volume via k8 ConfigMaps).
-rendition.config.dir=shared/classes/alfresco/extension/transform/renditions
-
-# Optional property to specify an external file or directory that will be read for transformer json config.
-local.transform.pipeline.config.dir=shared/classes/alfresco/extension/transform/pipelines
-
-# Used to disable transforms locally.
-local.transform.service.enabled=true
-
-# Schedule for reading local transform config, so that T-Engines and local pipeline config is dynamically
-# picked up, or reintegrated after an outage. Initially checks every 10 seconds and then switches to every hour
-# after the configuration is read successfully. If there is a error later reading the config, the checks return to
-# every 10 seconds.
-local.transform.service.cronExpression=4 30 0/1 * * ?
-local.transform.service.initialAndOnError.cronExpression=0/10 * * * * ?
-
-#
-# Check that the declared mimetype (of the Node) is the same as the derived
-# mimetype of the content (via Tika) before a transformation takes place.
-# Only files in the repository (not intermediate files in a transformer
-# pipeline) are checked. This property provides a trade off between a
-# security check and a relatively expensive (Tika) operation.
-#
-# There are a few issues with the Tika mimetype detection. So that transformations
-# still take place where the detected mimetype is not the same as the declared mimetype,
-# another property (transformer.strict.mimetype.check.whitelist.mimetypes) contains pairs
-# of declared and detected mimetypes that should be allowed. This parameter value is a
-# sequence of ; separated pairs. The declared and derived mimetypes are also ; separated.
-#
-transformer.strict.mimetype.check=true
-
-# A white list of declared and detected mimetypes, that don't match, but should still be transformed.
-transformer.strict.mimetype.check.whitelist.mimetypes=application/eps;application/postscript;application/illustrator;application/pdf;application/x-tar;application/x-gtar;application/acp;application/zip;application/vnd.stardivision.math;application/x-tika-msoffice
-
-#
-# Enable transformation retrying if the file has MIME type differ than file extension.
-# Ignored if transformer.strict.mimetype.check is true as these transformations
-# will not take place.
-#
-content.transformer.retryOn.different.mimetype=true
-
-# Debug and Log buffer sizes
-transformer.debug.entries=0
-transformer.log.entries=50
-
-#
-# Lock timeout configuration
-#
-system.lockTryTimeout=100
-system.lockTryTimeout.DictionaryDAOImpl=10000
-system.lockTryTimeout.MessageServiceImpl=${system.lockTryTimeout}
-system.lockTryTimeout.PolicyComponentImpl=${system.lockTryTimeout}
-
-
-# Scheduled job to clean up unused properties from the alf_prop_xxx tables.
-# Default setting of "0 0 3 ? * SAT" is to run every Saturday at 3am.
-attributes.propcleaner.cronExpression=0 0 3 ? * SAT
-
-# Control Alfresco JMX connectivity
-alfresco.jmx.connector.enabled=false
-
-# Dissallow Attribute Service Entries with "Serializable" objects in key Segments
-# Please, see MNT-11895 for details.
-system.propval.uniquenessCheck.enabled=true
-
-# Requests for ephemeral (in-memory) locks with expiry times (in seconds) greater
-# than this value will result in persistent locks being created instead. By default
-# this value is equal to the maximum allowed expiry for ephemeral locks, therefore
-# this feature is disabled by default. Setting this to -1 would mean that ALL
-# requests for ephemeral locks would result in persistent locks being created.
-alfresco.ephemeralLock.expiryThresh=172800
-
-# SurfConfigFolder Patch
-#
-# Do we defer running the surf-config folder patch?
-#
-system.patch.surfConfigFolder.deferred=false
-# Default value. i.e. never run. It can be triggered using JMX
-system.patch.surfConfigFolder.cronExpression=* * * * * ? 2099
-
-#
-# Solr Facets Config Properties
-#
-solr_facets.root.path=/app:company_home/app:dictionary
-solr_facets.root=${solr_facets.root.path}/${spaces.solr_facets.root.childname}
-solr_facets.inheritanceHierarchy=default,custom
-
-models.enforceTenantInNamespace=false
-
-# Allowed protocols for links
-links.protocosl.white.list=http,https,ftp,mailto
-
-# Fixed ACLs
-# Required for fixing MNT-15368 - Time Consumed for Updating Folder Permission
-# ADMAccessControlListDAO.setFixedAcls called on a large folder hierarchy will take a long time for its execution.
-# For this reason now method can also be called asynchronously if transaction reaches system.fixedACLs.maxTransactionTime.
-# In this case setFixedAcls method recursion will be stopped and unfinished nodes will be marked with ASPECT_PENDING_FIX_ACL.
-# Pending nodes will be processed by FixedAclUpdater, programmatically called but also configured as a scheduled job.
-system.fixedACLs.maxTransactionTime=10000
-# fixedACLsUpdater - lock time to live
-system.fixedACLsUpdater.lockTTL=10000
-# fixedACLsUpdater - maximum number of nodes to process per execution
-system.fixedACLsUpdater.maxItemBatchSize=100
-# fixedACLsUpdater - the number of threads to use
-system.fixedACLsUpdater.numThreads=4
-# fixedACLsUpdater - Force shared ACL to propagate through children even if there is an unexpected ACL
-system.fixedACLsUpdater.forceSharedACL=false
-# fixedACLsUpdater cron expression - fire at midnight every day
-system.fixedACLsUpdater.cronExpression=0 0 0 * * ?
-
-cmis.disable.hidden.leading.period.files=false
-
-#Smart Folders Config Properties
-smart.folders.enabled=false
-
-#Smart reference config
-smart.reference.classpath.hash=${smart.folders.config.vanilla.processor.classpath}->1,${smart.folders.config.system.templates.classpath}->2
-
-#Smart store config
-
-#Company home relative download associations of smart entries
-smart.download.associations.folder=${spaces.dictionary.childname}/${spaces.smartdownloads.childname}
-
-#Generic virtualization methods config
-
-#Vanilla JSON templates javascript processor classpath. A java script processor used to
-#covert JSON templates to internal smart folder definitions.
-
-smart.folders.config.vanilla.processor.classpath=/org/alfresco/repo/virtual/node/vanilla.js
-
-#System virtualization method config
-
-#System virtualization method aspect.
-smart.folders.config.system.aspect=smf:systemConfigSmartFolder
-#System virtualization method aspect defined template location property.
-smart.folders.config.system.aspect.template.location.property=smf:system-template-location
-#Classpath to be explored for *.json entries defining system templates.
-smart.folders.config.system.templates.classpath=/org/alfresco/repo/virtual/node
-#A company home relative name or qname path location of repository system templates.
-smart.folders.config.system.templates.path=${spaces.dictionary.childname}/${spaces.smartfolders.childname}
-#Content sub type of repository system templates.
-smart.folders.config.system.templates.template.type=smf:smartFolderTemplate
-
-#Custom virtualization method config
-
-#Custom virtualization method aspect.
-smart.folders.config.custom.aspect=smf:customConfigSmartFolder
-#Custom virtualization method aspect template content association.
-smart.folders.config.custom.aspect.template.association=smf:custom-template-association
-
-
-#Type virtualization method config
-
-#A company home relative name or qname path location of the type mapped templates.
-smart.folders.config.type.templates.path=${spaces.dictionary.childname}/${spaces.smartfolders.childname}
-#Type and aspect qname regular expression filter.
-smart.folders.config.type.templates.qname.filter=none
-
-# Preferred password encoding, md4, sha256, bcrypt10
-system.preferred.password.encoding=md4
-
-# Upgrade Password Hash Job
-system.upgradePasswordHash.jobBatchSize=100
-system.upgradePasswordHash.jobQueryRange=10000
-system.upgradePasswordHash.jobThreadCount=4
-system.upgradePasswordHash.jobCronExpression=* * * * * ? 2099
-
-system.api.discovery.enabled=true
-
-# Maximum query size for category/tag fetch when not explicitly set by paging parameters
-category.queryFetchSize=5000
-
-# Brute force protection
-authentication.protection.enabled=true
-authentication.protection.limit=10
-authentication.protection.periodSeconds=6
-
-system.email.sender.default=noreply@alfresco.com
-# reset password workflow will expire in an hour
-system.reset-password.endTimer=PT1H
-system.reset-password.sendEmailAsynchronously=true
-
-# HeartBeat
-heartbeat.target.url=
-heartbeat.enabled=true
-
-# CSRF filter overrides
-csrf.filter.enabled=true
-csrf.filter.referer=
-csrf.filter.referer.always=false
-csrf.filter.origin=
-csrf.filter.origin.always=false
-
-# CORS settings
-cors.enabled=false
-cors.allowed.origins=
-cors.allowed.methods=GET,POST,HEAD,OPTIONS,PUT,DELETE
-cors.allowed.headers=Authorization,Content-Type,Cache-Control,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,X-CSRF-Token
-cors.exposed.headers=Access-Control-Allow-Origin,Access-Control-Allow-Credentials
-cors.support.credentials=true
-cors.preflight.maxage=10
-
-# Alfresco Rest Api-Explorer
-api-explorer.url=
-
-# Events subsystem
-events.subsystem.autoStart=false
-# Messaging subsystem
-messaging.subsystem.autoStart=true
-
-
-# Raw events
-acs.repo.rendition.events.endpoint=jms:acs-repo-rendition-events?jmsMessageType=Text
-
-# Transform request events
-acs.repo.transform.request.endpoint=jms:acs-repo-transform-request?jmsMessageType=Text
-
-# If enabled doesn't allow to set content properties via NodeService
-contentPropertyRestrictions.enabled=true
-contentPropertyRestrictions.whitelist=
-
-# Repo events2
-# Type and aspect filters which should be excluded
-# Note: System folders node types are added by default
-repo.event2.filter.nodeTypes=sys:*, fm:*, cm:thumbnail, cm:failedThumbnail, cm:rating, rma:rmsite include_subtypes
-repo.event2.filter.nodeAspects=sys:*
-repo.event2.filter.childAssocTypes=rn:rendition
-# Comma separated list of users which should be excluded
-# Note: username's case-sensitivity depends on the {user.name.caseSensitive} setting
-repo.event2.filter.users=
-# Topic name
-repo.event2.topic.endpoint=amqp:topic:alfresco.repo.event2
-# Thread pool for async enqueue of repo events
-repo.event2.queue.enqueueThreadPool.priority=1
-repo.event2.queue.enqueueThreadPool.coreSize=8
-repo.event2.queue.enqueueThreadPool.maximumSize=10
-# Thread pool for async dequeue and delivery of repo events
-repo.event2.queue.dequeueThreadPool.priority=1
-repo.event2.queue.dequeueThreadPool.coreSize=1
-repo.event2.queue.dequeueThreadPool.maximumSize=1
-
-
-# MNT-21083
-# --DELETE_NOT_EXISTS - default settings
-system.delete_not_exists.batchsize=100000
-system.delete_not_exists.delete_batchsize=1000
-system.delete_not_exists.read_only=false
-system.delete_not_exists.timeout_seconds=-1
-system.prop_table_cleaner.algorithm=V2
-
-# Configure the expiration time of the direct access url. This is the length of time in seconds that the link is valid for.
-# Note: It is up to the actual ContentStore implementation if it can fulfil this request or not.
-alfresco.content.directAccessUrl.lifetimeInSec=300
-
-# Creates additional indexes on alf_node and alf_transaction. Recommended for large repositories.
-system.new-node-transaction-indexes.ignored=true
-
-# Allows the configuration of maximum limits of the temp files to be deleted or the maximum time allowed to run for the job
-system.tempFileCleaner.maxFilesToDelete=
-system.tempFileCleaner.maxTimeToRun=
-
-# Property to long running migration to remove alf_server in v7+ patch.db-V7.1.0-remove-alf_server-table
-system.remove-alf_server-table-from-db.ignored=true
+# Repository configuration
+
+repository.name=Main Repository
+
+# Schema number
+version.schema=15001
+
+# Directory configuration
+
+dir.root=./alf_data
+
+dir.contentstore=${dir.root}/contentstore
+dir.contentstore.deleted=${dir.root}/contentstore.deleted
+dir.contentstore.bucketsPerMinute=0
+
+# ContentStore subsystem: default choice
+filecontentstore.subsystem.name=unencryptedContentStore
+
+# The location of cached content
+dir.cachedcontent=${dir.root}/cachedcontent
+
+# The value for the maximum permitted size in bytes of all content.
+# No value (or a negative long) will be taken to mean that no limit should be applied.
+# See content-services-context.xml
+system.content.maximumFileSizeLimit=
+
+#
+# The server mode. Set value in alfresco-global.properties
+# UNKNOWN | TEST | BACKUP | PRODUCTION
+#
+system.serverMode=UNKNOWN
+
+# The location for lucene index files
+dir.indexes=${dir.root}/lucene-indexes
+
+# The location for index backups
+dir.indexes.backup=${dir.root}/backup-lucene-indexes
+
+# The location for lucene index locks
+dir.indexes.lock=${dir.indexes}/locks
+
+#Directory to find external license
+dir.license.external=.
+# Spring resource location of external license files
+location.license.external=file://${dir.license.external}/*.lic
+# Spring resource location of embedded license files
+location.license.embedded=/WEB-INF/alfresco/license/*.lic
+# Spring resource location of license files on shared classpath
+location.license.shared=classpath*:/alfresco/extension/license/*.lic
+
+# WebDAV initialization properties
+system.webdav.servlet.enabled=true
+system.webdav.url.path.prefix=
+system.webdav.storeName=${protocols.storeName}
+system.webdav.rootPath=${protocols.rootPath}
+# File name patterns that trigger rename shuffle detection
+# pattern is used by move - tested against full path after it has been lower cased.
+system.webdav.renameShufflePattern=(.*/\\..*)|(.*[a-f0-9]{8}+$)|(.*\\.tmp$)|(.*atmp[0-9]+$)|(.*\\.wbk$)|(.*\\.bak$)|(.*\\~$)|(.*backup.*\\.do[ct]{1}[x]?[m]?$)|(.*\\.sb\\-\\w{8}\\-\\w{6}$)
+system.webdav.activities.enabled=false
+
+
+system.workflow.jbpm.comment.property.max.length=-1
+system.workflow.comment.property.max.length=4000
+
+#Determines if Activiti definitions are visible
+system.workflow.engine.activiti.definitions.visible=true
+
+
+# Determines if the Activiti engine is enabled
+system.workflow.engine.activiti.enabled=true
+system.workflow.engine.activiti.idblocksize=100
+system.workflow.engine.activiti.taskvariableslimit=20000
+
+# Determines if the workflows that are deployed to the activiti engine should
+# be deployed in the tenant-context of the thread IF the tenant-service is enabled
+# If set to false, all workflows deployed will be shared among tenants. Recommended
+# setting is true unless there is a good reason to not allow deploy tenant-specific
+# worklfows when a MT-environment is set up.
+system.workflow.deployWorkflowsInTenant=true
+#Determines if historic process instance are retained in case of canceling a process instance
+system.workflow.engine.activiti.retentionHistoricProcessInstance=false
+
+# The maximum number of groups to check for pooled tasks. For performance
+# reasons, this is limited to 500 by default.
+system.workflow.maxAuthoritiesForPooledTasks=500
+
+# The maximum number of pooled tasks to return in a query. It may be necessary
+# to limit this depending on UI limitations.
+system.workflow.maxPooledTasks=-1
+
+# The maximum number of reviewers for "Group Review and Approve" workflow.
+# Use '0' for unlimited.
+system.workflow.maxGroupReviewers=0
+
+index.subsystem.name=noindex
+
+# ######################################### #
+# Index Tracking Configuration #
+# ######################################### #
+#
+# Index tracking information of a certain age is cleaned out by a scheduled job.
+# Any clustered system that has been offline for longer than this period will need to be seeded
+# with a more recent backup of the Lucene indexes or the indexes will have to be fully rebuilt.
+# Use -1 to disable purging. This can be switched on at any stage.
+index.tracking.minRecordPurgeAgeDays=30
+# Unused transactions will be purged in chunks determined by commit time boundaries. 'index.tracking.purgeSize' specifies the size
+# of the chunk (in ms). Default is a couple of hours.
+index.tracking.purgeSize=7200000
+
+# Change the failure behaviour of the configuration checker
+system.bootstrap.config_check.strict=true
+
+
+#
+# How long should shutdown wait to complete normally before
+# taking stronger action and calling System.exit()
+# in ms, 10,000 is 10 seconds
+#
+shutdown.backstop.timeout=10000
+shutdown.backstop.enabled=false
+
+# Server Single User Mode
+# note:
+# only allow named user (note: if blank or not set then will allow all users)
+# assuming maxusers is not set to 0
+#server.singleuseronly.name=admin
+
+# Server Max Users - limit number of users with non-expired tickets
+# note:
+# -1 allows any number of users, assuming not in single-user mode
+# 0 prevents further logins, including the ability to enter single-user mode
+server.maxusers=-1
+
+#
+# Disable all shared caches (mutable and immutable)
+# These properties are used for diagnostic purposes
+system.cache.disableMutableSharedCaches=false
+system.cache.disableImmutableSharedCaches=false
+
+# The maximum capacity of the parent assocs cache (the number of nodes whose parents can be cached)
+system.cache.parentAssocs.maxSize=130000
+
+# The average number of parents expected per cache entry. This parameter is multiplied by the above
+# value to compute a limit on the total number of cached parents, which will be proportional to the
+# cache's memory usage. The cache will be pruned when this limit is exceeded to avoid excessive
+# memory usage.
+system.cache.parentAssocs.limitFactor=8
+
+#
+# Properties to limit resources spent on individual searches
+#
+# The maximum time spent pruning results
+system.acl.maxPermissionCheckTimeMillis=10000
+# The maximum number of search results to perform permission checks against
+system.acl.maxPermissionChecks=1000
+system.acl.maxPermissionCheckEnabled=false
+
+# The maximum number of filefolder list results
+system.filefolderservice.defaultListMaxResults=5000
+# DEPRECATED: Use 'system.auditableData.preserve'
+system.preserve.modificationData=false
+# The default to preserve all cm:auditable data on a node when the process is not directly driven by a user action
+system.auditableData.preserve=${system.preserve.modificationData}
+# Specific control of how the FileFolderService treats cm:auditable data when performing moves
+system.auditableData.FileFolderService=${system.auditableData.preserve}
+# Specific control of whether ACL changes on a node trigger the cm:auditable aspect
+system.auditableData.ACLs=${system.auditableData.preserve}
+
+# Properties to control read permission evaluation for acegi
+system.readpermissions.optimise=true
+system.readpermissions.bulkfetchsize=1000
+
+#
+# Manually control how the system handles maximum string lengths.
+# Any zero or negative value is ignored.
+# Only change this after consulting support or reading the appropriate Javadocs for
+# org.alfresco.repo.domain.schema.SchemaBootstrap for V2.1.2.
+# Before database migration, the string value storage may need to be adjusted using the scheduled job
+system.maximumStringLength=-1
+system.maximumStringLength.jobCronExpression=* * * * * ? 2099
+system.maximumStringLength.jobQueryRange=10000
+system.maximumStringLength.jobThreadCount=4
+
+#
+# Limit hibernate session size by trying to amalgamate events for the L2 session invalidation
+# - hibernate works as is up to this size
+# - after the limit is hit events that can be grouped invalidate the L2 cache by type and not instance
+# events may not group if there are post action listener registered (this is not the case with the default distribution)
+system.hibernateMaxExecutions=20000
+
+#
+# Determine if modification timestamp propagation from child to parent nodes is respected or not.
+# Even if 'true', the functionality is only supported for child associations that declare the
+# 'propagateTimestamps' element in the dictionary definition.
+system.enableTimestampPropagation=true
+
+#
+# Enable system model integrity checking.
+# WARNING: Changing this is unsupported; bugs may corrupt data
+system.integrity.enabled=true
+# Do integrity violations fail transactions
+# WARNING: Changing this is unsupported; bugs may corrupt data
+system.integrity.failOnViolation=true
+# The number of errors to report when violations are detected
+system.integrity.maxErrorsPerTransaction=5
+# Add call stacks to integrity events so that errors are logged with possible causes
+# WARNING: This is expensive and should only be switched on for diagnostic purposes
+system.integrity.trace=false
+
+#
+# Decide if content should be removed from the system immediately after being orphaned.
+# Do not change this unless you have examined the impact it has on your backup procedures.
+system.content.eagerOrphanCleanup=false
+# The number of days to keep orphaned content in the content stores.
+# This has no effect on the 'deleted' content stores, which are not automatically emptied.
+system.content.orphanProtectDays=14
+# The action to take when a store or stores fails to delete orphaned content
+# IGNORE: Just log a warning. The binary remains and the record is expunged
+# KEEP_URL: Log a warning and create a URL entry with orphan time 0. It won't be processed or removed.
+system.content.deletionFailureAction=IGNORE
+# The CRON expression to trigger the deletion of resources associated with orphaned content.
+system.content.orphanCleanup.cronExpression=0 0 4 * * ?
+# The batch size user by the content store cleaner
+system.content.cleanerBatchSize=1000
+
+# The CRON expression to trigger the cleanup of deleted nodes and dangling transactions that are old enough
+system.nodeServiceCleanup.cronExpression=0 0 21 * * ?
+
+# When transforming archive files (.zip etc) into text representations (such as
+# for full text indexing), should the files within the archive be processed too?
+# If enabled, transformation takes longer, but searches of the files find more.
+transformer.Archive.includeContents=false
+
+# Database configuration
+db.schema.name=
+db.schema.stopAfterSchemaBootstrap=false
+db.schema.update=true
+db.schema.update.lockRetryCount=24
+db.schema.update.lockRetryWaitSeconds=5
+db.driver=org.gjt.mm.mysql.Driver
+db.name=alfresco
+db.url=jdbc:mysql:///${db.name}
+db.username=alfresco
+db.password=alfresco
+db.pool.initial=10
+db.pool.max=275
+db.txn.isolation=-1
+db.pool.statements.enable=true
+db.pool.statements.max=40
+db.pool.min=10
+db.pool.idle=10
+db.pool.wait.max=5000
+
+db.pool.validate.query=
+db.pool.evict.interval=600000
+db.pool.evict.idle.min=1800000
+#
+# note: for 'db.pool.evict.num.tests' see http://commons.apache.org/dbcp/configuration.html (numTestsPerEvictionRun)
+# and also following extract from "org.apache.commons.pool.impl.GenericKeyedObjectPool" (1.5.5)
+#
+# * The number of objects to examine during each run of the idle object evictor thread (if any).
+# * When a negative value is supplied, ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})
+# * tests will be run. I.e., when the value is -n
, roughly one n
th of the
+# * idle objects will be tested per run.
+#
+db.pool.evict.num.tests=-1
+
+db.pool.evict.validate=false
+db.pool.validate.borrow=true
+db.pool.validate.return=false
+
+db.pool.abandoned.detect=false
+db.pool.abandoned.time=300
+#
+# db.pool.abandoned.log=true (logAbandoned) adds overhead (http://commons.apache.org/dbcp/configuration.html)
+# and also requires db.pool.abandoned.detect=true (removeAbandoned)
+#
+db.pool.abandoned.log=false
+
+
+# Audit configuration
+audit.enabled=true
+audit.tagging.enabled=true
+audit.alfresco-access.enabled=false
+audit.alfresco-access.sub-actions.enabled=false
+audit.cmischangelog.enabled=false
+audit.dod5015.enabled=false
+# Setting this flag to true will force startup failure when invalid audit configurations are detected
+audit.config.strict=false
+# Audit map filter for AccessAuditor - restricts recorded events to user driven events
+audit.filter.alfresco-access.default.enabled=false
+audit.filter.alfresco-access.transaction.user=~System;~null;.*
+audit.filter.alfresco-access.transaction.type=cm:folder;cm:content;st:site
+audit.filter.alfresco-access.transaction.path=~/sys:archivedItem;~/ver:;.*
+
+
+# System Configuration
+system.store=system://system
+system.descriptor.childname=sys:descriptor
+system.descriptor.current.childname=sys:descriptor-current
+
+# User config
+alfresco_user_store.store=user://alfrescoUserStore
+alfresco_user_store.system_container.childname=sys:system
+alfresco_user_store.user_container.childname=sys:people
+
+# note: default admin username - should not be changed after installation
+alfresco_user_store.adminusername=admin
+
+# Initial password - editing this will not have any effect once the repository is installed
+alfresco_user_store.adminpassword=209c6174da490caeb422f3fa5a7ae634
+
+# note: default guest username - should not be changed after installation
+alfresco_user_store.guestusername=guest
+
+# Used to move home folders to a new location
+home_folder_provider_synchronizer.enabled=false
+home_folder_provider_synchronizer.override_provider=
+home_folder_provider_synchronizer.keep_empty_parents=false
+
+# Spaces Archive Configuration
+spaces.archive.store=archive://SpacesStore
+
+# Spaces Configuration
+spaces.store=workspace://SpacesStore
+spaces.company_home.childname=app:company_home
+spaces.guest_home.childname=app:guest_home
+spaces.dictionary.childname=app:dictionary
+spaces.templates.childname=app:space_templates
+spaces.imap_attachments.childname=cm:Imap Attachments
+spaces.imap_home.childname=cm:Imap Home
+spaces.imapConfig.childname=app:imap_configs
+spaces.imap_templates.childname=app:imap_templates
+spaces.scheduled_actions.childname=cm:Scheduled Actions
+spaces.emailActions.childname=app:email_actions
+spaces.searchAction.childname=cm:search
+spaces.templates.content.childname=app:content_templates
+spaces.templates.email.childname=app:email_templates
+spaces.templates.email.invite1.childname=app:invite_email_templates
+spaces.templates.email.notify.childname=app:notify_email_templates
+spaces.templates.email.following.childname=app:following
+spaces.templates.rss.childname=app:rss_templates
+spaces.savedsearches.childname=app:saved_searches
+spaces.scripts.childname=app:scripts
+spaces.content_forms.childname=app:forms
+spaces.user_homes.childname=app:user_homes
+spaces.user_homes.regex.key=userName
+spaces.user_homes.regex.pattern=
+spaces.user_homes.regex.group_order=
+spaces.sites.childname=st:sites
+spaces.templates.email.invite.childname=cm:invite
+spaces.templates.email.activities.childname=cm:activities
+spaces.rendition.rendering_actions.childname=app:rendering_actions
+spaces.replication.replication_actions.childname=app:replication_actions
+spaces.transfers.childname=app:transfers
+spaces.transfer_groups.childname=app:transfer_groups
+spaces.transfer_temp.childname=app:temp
+spaces.inbound_transfer_records.childname=app:inbound_transfer_records
+spaces.webscripts.childname=cm:webscripts
+spaces.extension_webscripts.childname=cm:extensionwebscripts
+spaces.models.childname=app:models
+spaces.workflow.definitions.childname=app:workflow_defs
+spaces.templates.email.workflowemailnotification.childname=cm:workflownotification
+spaces.nodetemplates.childname=app:node_templates
+spaces.shared.childname=app:shared
+spaces.solr_facets.root.childname=srft:facets
+spaces.smartfolders.childname=app:smart_folders
+spaces.smartdownloads.childname=app:smart_downloads
+spaces.transfer_summary_report.location=/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.inbound_transfer_records.childname}
+spaces.quickshare.link_expiry_actions.childname=app:quick_share_link_expiry_actions
+
+
+# ADM VersionStore Configuration
+version.store.initialVersion=true
+version.store.enableAutoVersioning=true
+version.store.enableAutoVersionOnUpdateProps=false
+version.store.deprecated.lightWeightVersionStore=workspace://lightWeightVersionStore
+version.store.version2Store=workspace://version2Store
+
+# Optional Comparator class name to sort versions.
+# Set to: org.alfresco.repo.version.common.VersionLabelComparator
+# if upgrading from a version that used unordered sequences in a cluster.
+version.store.versionComparatorClass=
+
+# Folders for storing people
+system.system_container.childname=sys:system
+system.people_container.childname=sys:people
+system.authorities_container.childname=sys:authorities
+system.zones_container.childname=sys:zones
+
+# Folders for storing workflow related info
+system.workflow_container.childname=sys:workflow
+
+# Folder for storing shared remote credentials
+system.remote_credentials_container.childname=sys:remote_credentials
+
+# Folder for storing syncset definitions
+system.syncset_definition_container.childname=sys:syncset_definitions
+
+# Folder for storing download archives
+system.downloads_container.childname=sys:downloads
+
+# Folder for storing IdP's certificate definitions
+system.certificate_container.childname=sys:samlcertificate
+
+# Are user names case sensitive?
+user.name.caseSensitive=false
+domain.name.caseSensitive=false
+domain.separator=
+
+#Format caption extracted from the XML Schema.
+xforms.formatCaption=true
+
+# ECM content usages/quotas
+system.usages.enabled=false
+system.usages.clearBatchSize=0
+system.usages.updateBatchSize=50
+
+# Repository endpoint - used by Activity Service
+repo.remote.endpoint=/service
+
+# Some authentication mechanisms may need to create people
+# in the repository on demand. This enables that feature.
+# If disabled an error will be generated for missing
+# people. If enabled then a person will be created and
+# persisted.
+create.missing.people=${server.transaction.allow-writes}
+
+# Create home folders (unless disabled, see next property) as people are created (true) or create them lazily (false)
+home.folder.creation.eager=true
+# Disable home folder creation - if true then home folders are not created (neither eagerly nor lazily)
+home.folder.creation.disabled=false
+
+# Should we consider zero byte content to be the same as no content when firing
+# content update policies? Prevents 'premature' firing of inbound content rules
+# for some clients such as Mac OS X Finder
+policy.content.update.ignoreEmpty=true
+
+# Default value of alfresco.rmi.services.host is 0.0.0.0 which means 'listen on all adapters'.
+# This allows connections to JMX both remotely and locally.
+#
+alfresco.rmi.services.port=50500
+alfresco.rmi.services.external.host=localhost
+alfresco.rmi.services.host=0.0.0.0
+
+# If the RMI address is in-use, how many retries should be done before aborting
+# Default value of alfresco.rmi.services.retries is 0 which means 'Don't retry if the address is in-use'
+alfresco.rmi.services.retries=4
+# How long in milliseconds to wait after a failed server socket bind, before retrying
+alfresco.rmi.services.retryInterval=250
+
+# RMI service ports for the individual services.
+# These eight services are available remotely.
+#
+# Assign individual ports for each service for best performance
+# or run several services on the same port, you can even run everything on 50500 if
+# running through a firewall.
+#
+# Specify 0 to use a random unused port.
+#
+monitor.rmi.service.port=50508
+
+#
+# enable or disable individual RMI services
+#
+monitor.rmi.service.enabled=false
+
+
+# Should the Mbean server bind to an existing server. Set to true for most application servers.
+# false for WebSphere clusters.
+mbean.server.locateExistingServerIfPossible=true
+
+# Rendition Service 2
+renditionService2.enabled=true
+
+# Thumbnail Service
+system.thumbnail.generate=true
+
+# when creating doc via CMIS - optionally configure set of renditions names to request async
+cmis.create.doc.request.renditions.set=
+
+# Default thumbnail limits
+# When creating thumbnails, only use the first pageLimit pages
+system.thumbnail.definition.default.timeoutMs=-1
+system.thumbnail.definition.default.readLimitTimeMs=-1
+system.thumbnail.definition.default.maxSourceSizeKBytes=-1
+system.thumbnail.definition.default.readLimitKBytes=-1
+system.thumbnail.definition.default.pageLimit=-1
+system.thumbnail.definition.default.maxPages=-1
+
+# Max mimetype sizes to create thumbnail icons
+system.thumbnail.mimetype.maxSourceSizeKBytes.pdf=-1
+system.thumbnail.mimetype.maxSourceSizeKBytes.txt=-1
+system.thumbnail.mimetype.maxSourceSizeKBytes.docx=-1
+system.thumbnail.mimetype.maxSourceSizeKBytes.xlsx=-1
+system.thumbnail.mimetype.maxSourceSizeKBytes.pptx=-1
+system.thumbnail.mimetype.maxSourceSizeKBytes.odt=-1
+system.thumbnail.mimetype.maxSourceSizeKBytes.ods=-1
+system.thumbnail.mimetype.maxSourceSizeKBytes.odp=-1
+
+# Configuration for handling of failing thumbnails.
+# See NodeEligibleForRethumbnailingEvaluator's javadoc for details.
+#
+# Retry periods limit the frequency with which the repository will attempt to create Share thumbnails
+# for content nodes which have previously failed in their thumbnail attempts.
+# These periods are in seconds.
+#
+# 604800s = 60s * 60m * 24h * 7d = 1 week
+system.thumbnail.retryPeriod=60
+system.thumbnail.retryCount=2
+system.thumbnail.quietPeriod=604800
+system.thumbnail.quietPeriodRetriesEnabled=true
+system.thumbnail.redeployStaticDefsOnStartup=true
+
+content.metadata.async.extract.enabled=true
+content.metadata.async.embed.enabled=true
+
+# The default timeout for metadata mapping extracters
+content.metadataExtracter.default.timeoutMs=20000
+
+# Local transformer urls to T-engines to service transform requests via http. Enabled by default.
+localTransform.core-aio.url=http://localhost:8090/
+
+# When a local transformer .url is set, this value indicates the amount of time to wait after a connection failure
+# before retrying the connection to allow a docker container to (re)start.
+localTransform.core-aio.startupRetryPeriodSeconds=60
+
+# Property to enable upgrade from 2.1-A
+V2.1-A.fixes.to.schema=0
+#V2.1-A.fixes.to.schema=82
+
+# The default authentication chain
+authentication.chain=alfrescoNtlm1:alfrescoNtlm
+
+# Do authentication tickets expire or live for ever?
+authentication.ticket.ticketsExpire=true
+
+# If ticketsEpire is true then how they should expire?
+# Valid values are: AFTER_INACTIVITY, AFTER_FIXED_TIME, DO_NOT_EXPIRE
+# The default is AFTER_FIXED_TIME
+authentication.ticket.expiryMode=AFTER_INACTIVITY
+
+# If authentication.ticket.ticketsExpire is true and
+# authentication.ticket.expiryMode is AFTER_FIXED_TIME or AFTER_INACTIVITY,
+# this controls the minimum period for which tickets are valid.
+# The default is PT1H for one hour.
+authentication.ticket.validDuration=PT1H
+
+# Use one ticket for all user sessions
+# For the pre 4.2 behaviour of one ticket per session set this to false.
+authentication.ticket.useSingleTicketPerUser=true
+
+authentication.alwaysAllowBasicAuthForAdminConsole.enabled=true
+authentication.getRemoteUserTimeoutMilliseconds=10000
+
+# FTP access
+ftp.enabled=false
+
+# Default root path for protocols
+protocols.storeName=${spaces.store}
+protocols.rootPath=/${spaces.company_home.childname}
+
+# OpenCMIS
+opencmis.connector.default.store=${spaces.store}
+opencmis.connector.default.rootPath=/${spaces.company_home.childname}
+opencmis.connector.default.typesDefaultMaxItems=500
+opencmis.connector.default.typesDefaultDepth=-1
+opencmis.connector.default.objectsDefaultMaxItems=10000
+opencmis.connector.default.objectsDefaultDepth=100
+opencmis.connector.default.contentChangesDefaultMaxItems=10000
+opencmis.connector.default.openHttpSession=false
+opencmis.activities.enabled=true
+opencmis.bulkUpdateProperties.maxItemsSize=1000
+opencmis.bulkUpdateProperties.batchSize=20
+opencmis.bulkUpdateProperties.workerThreads=2
+opencmis.maxContentSizeMB=4096
+opencmis.memoryThresholdKB=4096
+
+# URL generation overrides
+
+# if true, the context path of OpenCMIS generated urls will be set to "opencmis.context.value", otherwise it will be taken from the request url
+opencmis.context.override=false
+opencmis.context.value=
+# if true, the servlet path of OpenCMIS generated urls will be set to "opencmis.servletpath.value", otherwise it will be taken from the request url
+opencmis.servletpath.override=false
+opencmis.servletpath.value=
+opencmis.server.override=false
+opencmis.server.value=
+
+# IMAP
+imap.server.enabled=false
+imap.server.port=143
+imap.server.attachments.extraction.enabled=true
+
+# Default IMAP mount points
+imap.config.home.store=${spaces.store}
+imap.config.home.rootPath=/${spaces.company_home.childname}
+imap.config.home.folderPath=${spaces.imap_home.childname}
+imap.config.server.mountPoints=AlfrescoIMAP
+imap.config.server.mountPoints.default.mountPointName=IMAP
+imap.config.server.mountPoints.default.modeName=ARCHIVE
+imap.config.server.mountPoints.default.store=${spaces.store}
+imap.config.server.mountPoints.default.rootPath=${protocols.rootPath}
+imap.config.server.mountPoints.value.AlfrescoIMAP.mountPointName=Alfresco IMAP
+imap.config.server.mountPoints.value.AlfrescoIMAP.modeName=MIXED
+
+#Imap extraction settings
+#imap.attachments.mode:
+# SEPARATE -- All attachments for each email will be extracted to separate folder.
+# COMMON -- All attachments for all emails will be extracted to one folder.
+# SAME -- Attachments will be extracted to the same folder where email lies.
+imap.attachments.mode=SEPARATE
+imap.attachments.folder.store=${spaces.store}
+imap.attachments.folder.rootPath=/${spaces.company_home.childname}
+imap.attachments.folder.folderPath=${spaces.imap_attachments.childname}
+
+# Activities Feed - refer to subsystem
+
+# Feed max ID range to limit maximum number of entries
+activities.feed.max.idRange=1000000
+# Feed max size (number of entries)
+activities.feed.max.size=200
+# Feed max age (eg. 44640 mins => 31 days)
+activities.feed.max.ageMins=44640
+
+activities.feed.generator.jsonFormatOnly=true
+activities.feed.fetchBatchSize=250
+activities.feedNotifier.batchSize=200
+activities.feedNotifier.numThreads=2
+
+# Subsystem unit test values. Will not have any effect on production servers
+subsystems.test.beanProp.default.longProperty=123456789123456789
+subsystems.test.beanProp.default.anotherStringProperty=Global Default
+subsystems.test.beanProp=inst1,inst2,inst3
+subsystems.test.beanProp.value.inst2.boolProperty=true
+subsystems.test.beanProp.value.inst3.anotherStringProperty=Global Instance Default
+subsystems.test.simpleProp2=true
+subsystems.test.simpleProp3=Global Default3
+
+# Default Async Action Thread Pool
+default.async.action.threadPriority=1
+default.async.action.corePoolSize=8
+default.async.action.maximumPoolSize=20
+
+# Deployment Service
+deployment.service.numberOfSendingThreads=5
+deployment.service.corePoolSize=2
+deployment.service.maximumPoolSize=3
+deployment.service.threadPriority=5
+# How long to wait in mS before refreshing a target lock - detects shutdown servers
+deployment.service.targetLockRefreshTime=60000
+# How long to wait in mS from the last communication before deciding that deployment has failed, possibly
+# the destination is no longer available?
+deployment.service.targetLockTimeout=3600000
+# Deployment method used to deploy this Alfresco instance (DEFAULT, INSTALLER, DOCKER_COMPOSE, HELM_CHART, ANSIBLE, ZIP, QUICK_START)
+deployment.method=DEFAULT
+
+#Invitation Service
+# Should send emails as part of invitation process.
+notification.email.siteinvite=true
+# Moderated invite Activiti workflow
+site.invite.moderated.workflowId=activiti$activitiInvitationModerated
+# Add intneral users Activiti workflow (use activiti$activitiInvitationNominated to revert to requiring accept of invite for internal users)
+site.invite.nominated.workflowId=activiti$activitiInvitationNominatedAddDirect
+# Add external users Activiti workflow
+site.invite.nominatedExternal.workflowId=activiti$activitiInvitationNominated
+
+# Replication Service
+replication.enabled=false
+
+# Transfer Service
+transferservice.receiver.enabled=false
+transferservice.receiver.stagingDir=${java.io.tmpdir}/alfresco-transfer-staging
+#
+# How long to wait in mS before refreshing a transfer lock - detects shutdown servers
+# Default 1 minute.
+transferservice.receiver.lockRefreshTime=60000
+#
+# How many times to attempt retry the transfer lock
+transferservice.receiver.lockRetryCount=3
+# How long to wait, in mS, before retrying the transfer lock
+transferservice.receiver.lockRetryWait=100
+#
+# How long to wait, in mS, since the last contact with from the client before
+# timing out a transfer. Needs to be long enough to cope with network delays and "thinking
+# time" for both source and destination. Default 5 minutes.
+transferservice.receiver.lockTimeOut=300000
+
+# OrphanReaper
+orphanReaper.lockRefreshTime=60000
+orphanReaper.lockTimeOut=3600000
+
+
+# security
+security.anyDenyDenies=true
+# Whether to post-process denies. Only applies to solr4+ when anyDenyDenies is true.
+security.postProcessDenies=false
+
+#
+# Encryption properties
+#
+# default keystores location
+dir.keystore=classpath:alfresco/keystore
+
+# general encryption parameters
+encryption.keySpec.class=org.alfresco.encryption.DESEDEKeyGenerator
+encryption.keyAlgorithm=AES
+encryption.cipherAlgorithm=AES/CBC/PKCS5Padding
+
+# secret key keystore configuration
+encryption.keystore.location=${dir.keystore}/keystore
+# configuration via metadata is deprecated
+encryption.keystore.keyMetaData.location=
+encryption.keystore.provider=
+encryption.keystore.type=pkcs12
+
+# backup secret key keystore configuration
+encryption.keystore.backup.location=${dir.keystore}/backup-keystore
+# configuration via metadata is deprecated
+encryption.keystore.backup.keyMetaData.location=
+encryption.keystore.backup.provider=
+encryption.keystore.backup.type=pkcs12
+
+# Should encryptable properties be re-encrypted with new encryption keys on botstrap?
+encryption.bootstrap.reencrypt=false
+
+# mac/md5 encryption
+encryption.mac.messageTimeout=30000
+encryption.mac.algorithm=HmacSHA1
+
+# ssl encryption
+encryption.ssl.keystore.location=${dir.keystore}/ssl.keystore
+encryption.ssl.keystore.provider=
+encryption.ssl.keystore.type=JCEKS
+# configuration via metadata is deprecated
+encryption.ssl.keystore.keyMetaData.location=
+encryption.ssl.truststore.location=${dir.keystore}/ssl.truststore
+encryption.ssl.truststore.provider=
+encryption.ssl.truststore.type=JCEKS
+# configuration via metadata is deprecated
+encryption.ssl.truststore.keyMetaData.location=
+
+# Re-encryptor properties
+encryption.reencryptor.chunkSize=100
+encryption.reencryptor.numThreads=2
+
+# SOLR connection details (e.g. for JMX)
+solr.host=localhost
+solr.port=8983
+solr.port.ssl=8984
+solr.solrUser=solr
+solr.solrPassword=solr
+# none, https
+solr.secureComms=https
+solr.sharedSecret=
+solr.sharedSecret.header=X-Alfresco-Search-Secret
+solr.cmis.alternativeDictionary=DEFAULT_DICTIONARY
+
+solr.max.total.connections=40
+solr.max.host.connections=40
+
+# Solr connection timeouts
+# solr connect timeout in ms
+solr.solrConnectTimeout=5000
+
+# cron expression defining how often the Solr Admin client (used by JMX) pings Solr if it goes away
+solr.solrPingCronExpression=0 0/5 * * * ? *
+
+
+#Default SOLR store mappings mappings
+solr.store.mappings=solrMappingAlfresco,solrMappingArchive
+solr.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory
+solr.store.mappings.value.solrMappingAlfresco.baseUrl=/solr/alfresco
+solr.store.mappings.value.solrMappingAlfresco.protocol=workspace
+solr.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore
+solr.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory
+solr.store.mappings.value.solrMappingArchive.baseUrl=/solr/archive
+solr.store.mappings.value.solrMappingArchive.protocol=archive
+solr.store.mappings.value.solrMappingArchive.identifier=SpacesStore
+
+#Default SOLR 4 store mappings mappings
+solr4.store.mappings=solrMappingAlfresco,solrMappingArchive
+solr4.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory
+solr4.store.mappings.value.solrMappingAlfresco.baseUrl=/solr4/alfresco
+solr4.store.mappings.value.solrMappingAlfresco.protocol=workspace
+solr4.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore
+solr4.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory
+solr4.store.mappings.value.solrMappingArchive.baseUrl=/solr4/archive
+solr4.store.mappings.value.solrMappingArchive.protocol=archive
+solr4.store.mappings.value.solrMappingArchive.identifier=SpacesStore
+
+#Default SOLR 6 store mappings mappings
+solr6.store.mappings=solrMappingAlfresco,solrMappingArchive,solrMappingHistory
+solr6.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory
+solr6.store.mappings.value.solrMappingAlfresco.baseUrl=/solr/alfresco
+solr6.store.mappings.value.solrMappingAlfresco.protocol=workspace
+solr6.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore
+solr6.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory
+solr6.store.mappings.value.solrMappingArchive.baseUrl=/solr/archive
+solr6.store.mappings.value.solrMappingArchive.protocol=archive
+solr6.store.mappings.value.solrMappingArchive.identifier=SpacesStore
+solr6.store.mappings.value.solrMappingHistory.httpClientFactory=solrHttpClientFactory
+solr6.store.mappings.value.solrMappingHistory.baseUrl=/solr/history
+solr6.store.mappings.value.solrMappingHistory.protocol=workspace
+solr6.store.mappings.value.solrMappingHistory.identifier=history
+
+#
+# URL Shortening Properties
+#
+urlshortening.bitly.username=brianalfresco
+urlshortening.bitly.api.key=R_ca15c6c89e9b25ccd170bafd209a0d4f
+urlshortening.bitly.url.length=20
+
+#
+# Bulk Filesystem Importer
+#
+
+# The number of threads to employ in a batch import
+bulkImport.batch.numThreads=4
+
+# The size of a batch in a batch import i.e. the number of files to import in a
+# transaction/thread
+bulkImport.batch.batchSize=20
+
+
+#
+# Caching Content Store
+#
+system.content.caching.cacheOnInbound=true
+system.content.caching.maxDeleteWatchCount=1
+# Clean up every day at 3 am
+system.content.caching.contentCleanup.cronExpression=0 0 3 * * ?
+system.content.caching.minFileAgeMillis=60000
+system.content.caching.maxUsageMB=4096
+# maxFileSizeMB - 0 means no max file size.
+system.content.caching.maxFileSizeMB=0
+# When the CachingContentStore is about to write a cache file but the disk usage is in excess of panicThresholdPct
+# (default 90%) then the cache file is not written and the cleaner is started (if not already running) in a new thread.
+system.content.caching.panicThresholdPct=90
+# When a cache file has been written that results in cleanThresholdPct (default 80%) of maxUsageBytes
+# being exceeded then the cached content cleaner is invoked (if not already running) in a new thread.
+system.content.caching.cleanThresholdPct=80
+# An aggressive cleaner is run till the targetUsagePct (default 70%) of maxUsageBytes is achieved
+system.content.caching.targetUsagePct=70
+# Threshold in seconds indicating a minimal gap between normal cleanup starts
+system.content.caching.normalCleanThresholdSec=0
+
+mybatis.useLocalCaches=false
+
+fileFolderService.checkHidden.enabled=true
+
+
+ticket.cleanup.cronExpression=0 0 * * * ?
+
+#
+# Download Service Cleanup
+#
+download.cleaner.startDelayMilliseconds=3600000
+# 1 hour
+download.cleaner.repeatIntervalMilliseconds=3600000
+download.cleaner.maxAgeMins=60
+# -1 or 0 for not using batches
+download.cleaner.batchSize=1000
+
+# you could set this to false for new installations greater then ACS 6.2
+# see MNT-20212
+download.cleaner.cleanAllSysDownloadFolders=true
+
+#
+# Download Service Limits, in bytes
+#
+download.maxContentSize=2152852358
+
+# Max size of view trashcan files
+#
+trashcan.MaxSize=1000
+
+#
+# Use bridge tables for caching authority evaluation.
+#
+authority.useBridgeTable=true
+
+# Limit the number of results from findAuthority query
+authority.findAuthorityLimit=10000
+
+# enable QuickShare - if false then the QuickShare-specific REST APIs will return 403 Forbidden
+system.quickshare.enabled=true
+system.quickshare.email.from.default=noreply@alfresco.com
+# By default the difference between the quick share expiry date and the current time must be at least 1 day (24 hours).
+# However, this can be changed to at least 1 hour or 1 minute for testing purposes. For example,
+# setting the value to MINUTES, means the service will calculate the difference between NOW and the given expiry date
+# in terms of minutes and checks for the difference to be greater than 1 minute.
+# DAYS | HOURS | MINUTES
+system.quickshare.expiry_date.enforce.minimum.period=DAYS
+
+# Oubound Mail
+mail.service.corePoolSize=8
+mail.service.maximumPoolSize=20
+
+nodes.bulkLoad.cachingThreshold=10
+
+# Multi-Tenancy
+
+# if "dir.contentstore.tenants" is set then
+# tenants are not co-mingled and all content roots will appear below this container (in sub-folder)
+# and when creating a tenant the "contentRootPath" (root content store directory for a given tenant) will be ignored
+dir.contentstore.tenants=
+
+# Gateway Authentication
+# gateway authentication is disabled if empty host is specified
+alfresco.authentication.gateway.host=
+alfresco.authentication.gateway.protocol=https
+alfresco.authentication.gateway.port=443
+alfresco.authentication.gateway.outboundHeaders=Authorization,key
+alfresco.authentication.gateway.inboundHeaders=X-Alfresco-Authenticator-Key,X-Alfresco-Remote-User
+alfresco.authentication.gateway.prefixUrl=/publicapi
+alfresco.authentication.gateway.bufferSize=2048
+alfresco.authentication.gateway.connectTimeout=10000
+alfresco.authentication.gateway.readTimeout=120000
+alfresco.authentication.gateway.httpTcpNodelay=true
+alfresco.authentication.gateway.httpConnectionStalecheck=true
+
+# webscripts config
+webscripts.encryptTempFiles=false
+webscripts.tempDirectoryName=Alfresco-WebScripts
+# 4mb
+webscripts.memoryThreshold=4194304
+# 4gb
+webscripts.setMaxContentSize=5368709120
+
+# Property to enable index upgrade for metadata query (MDQ)
+#
+# The indexes are not added unless this value is changed
+# Adding each the supporting indexes may take several hours depending on the size of the database.
+# The required indexes may be added in stages.
+# See: classpath:alfresco/dbscripts/upgrade/4.2/${db.script.dialect}/metadata-query-indexes.sql
+# See: classpath:alfresco/dbscripts/upgrade/5.1/${db.script.dialect}/metadata-query-indexes-2.sql
+system.metadata-query-indexes.ignored=true
+system.metadata-query-indexes-more.ignored=true
+
+#
+# Do we defer running the shared folder patch?
+#
+system.patch.sharedFolder.deferred=false
+# Default value is run new years day 2030 i.e. not run.
+system.patch.sharedFolder.cronExpression=0 0 0 ? 1 1 2030
+
+#
+# Default values for deferring the running of the addUnmovableAspect patch
+#
+system.patch.addUnmovableAspect.deferred=false
+system.patch.addUnmovableAspect.cronExpression=0 0 0 ? 1 1 2030
+
+# Property to enable removal of all JBPM related data from the database
+#
+# The tables are not removed from the databasen unless explicitly requested by setting this property to false.
+# See: classpath:alfresco/dbscripts/upgrade/5.2/${db.script.dialect}/remove-jbpm-tables-from-db.sql
+system.remove-jbpm-tables-from-db.ignored=true
+
+#
+# Use a canned query when requested to search for people if " [hint:useCQ]" is provided in search term
+#
+people.search.honor.hint.useCQ=true
+
+# Delays cron jobs after bootstrap to allow server to fully come up before jobs start
+system.cronJob.startDelayMilliseconds=60000
+
+# Schedule for reading mimetype config definitions dynamically. Initially checks every 10 seconds and then switches to
+# every hour after the configuration is read successfully. If there is a error later reading the config, the
+# checks return to every 10 seconds.
+mimetype.config.cronExpression=0 30 0/1 * * ?
+mimetype.config.initialAndOnError.cronExpression=0/10 * * * * ?
+
+# Optional property to specify an external file or directory that will be read for mimetype definitions from YAML
+# files (possibly added to a volume via k8 ConfigMaps).
+mimetype.config.dir=shared/classes/alfresco/extension/mimetypes
+
+# Schedule for reading rendition config definitions dynamically. Initially checks every 10 seconds and then switches to
+# every hour after the configuration is read successfully. If there is a error later reading the config, the
+# checks return to every 10 seconds.
+rendition.config.cronExpression=2 30 0/1 * * ?
+rendition.config.initialAndOnError.cronExpression=0/10 * * * * ?
+
+# Optional property to specify an external file or directory that will be read for rendition definitions from YAML
+# files (possibly added to a volume via k8 ConfigMaps).
+rendition.config.dir=shared/classes/alfresco/extension/transform/renditions
+
+# Optional property to specify an external file or directory that will be read for transformer json config.
+local.transform.pipeline.config.dir=shared/classes/alfresco/extension/transform/pipelines
+
+# Used to disable transforms locally.
+local.transform.service.enabled=true
+
+# Schedule for reading local transform config, so that T-Engines and local pipeline config is dynamically
+# picked up, or reintegrated after an outage. Initially checks every 10 seconds and then switches to every hour
+# after the configuration is read successfully. If there is a error later reading the config, the checks return to
+# every 10 seconds.
+local.transform.service.cronExpression=4 30 0/1 * * ?
+local.transform.service.initialAndOnError.cronExpression=0/10 * * * * ?
+
+#
+# Check that the declared mimetype (of the Node) is the same as the derived
+# mimetype of the content (via Tika) before a transformation takes place.
+# Only files in the repository (not intermediate files in a transformer
+# pipeline) are checked. This property provides a trade off between a
+# security check and a relatively expensive (Tika) operation.
+#
+# There are a few issues with the Tika mimetype detection. So that transformations
+# still take place where the detected mimetype is not the same as the declared mimetype,
+# another property (transformer.strict.mimetype.check.whitelist.mimetypes) contains pairs
+# of declared and detected mimetypes that should be allowed. This parameter value is a
+# sequence of ; separated pairs. The declared and derived mimetypes are also ; separated.
+#
+transformer.strict.mimetype.check=true
+
+# A white list of declared and detected mimetypes, that don't match, but should still be transformed.
+transformer.strict.mimetype.check.whitelist.mimetypes=application/eps;application/postscript;application/illustrator;application/pdf;application/x-tar;application/x-gtar;application/acp;application/zip;application/vnd.stardivision.math;application/x-tika-msoffice
+
+#
+# Enable transformation retrying if the file has MIME type differ than file extension.
+# Ignored if transformer.strict.mimetype.check is true as these transformations
+# will not take place.
+#
+content.transformer.retryOn.different.mimetype=true
+
+# Debug and Log buffer sizes
+transformer.debug.entries=0
+transformer.log.entries=50
+
+#
+# Lock timeout configuration
+#
+system.lockTryTimeout=100
+system.lockTryTimeout.DictionaryDAOImpl=10000
+system.lockTryTimeout.MessageServiceImpl=${system.lockTryTimeout}
+system.lockTryTimeout.PolicyComponentImpl=${system.lockTryTimeout}
+
+
+# Scheduled job to clean up unused properties from the alf_prop_xxx tables.
+# Default setting of "0 0 3 ? * SAT" is to run every Saturday at 3am.
+attributes.propcleaner.cronExpression=0 0 3 ? * SAT
+
+# Control Alfresco JMX connectivity
+alfresco.jmx.connector.enabled=false
+
+# Dissallow Attribute Service Entries with "Serializable" objects in key Segments
+# Please, see MNT-11895 for details.
+system.propval.uniquenessCheck.enabled=true
+
+# Requests for ephemeral (in-memory) locks with expiry times (in seconds) greater
+# than this value will result in persistent locks being created instead. By default
+# this value is equal to the maximum allowed expiry for ephemeral locks, therefore
+# this feature is disabled by default. Setting this to -1 would mean that ALL
+# requests for ephemeral locks would result in persistent locks being created.
+alfresco.ephemeralLock.expiryThresh=172800
+
+# SurfConfigFolder Patch
+#
+# Do we defer running the surf-config folder patch?
+#
+system.patch.surfConfigFolder.deferred=false
+# Default value. i.e. never run. It can be triggered using JMX
+system.patch.surfConfigFolder.cronExpression=* * * * * ? 2099
+
+#
+# Solr Facets Config Properties
+#
+solr_facets.root.path=/app:company_home/app:dictionary
+solr_facets.root=${solr_facets.root.path}/${spaces.solr_facets.root.childname}
+solr_facets.inheritanceHierarchy=default,custom
+
+models.enforceTenantInNamespace=false
+
+# Allowed protocols for links
+links.protocosl.white.list=http,https,ftp,mailto
+
+# Fixed ACLs
+# Required for fixing MNT-15368 - Time Consumed for Updating Folder Permission
+# ADMAccessControlListDAO.setFixedAcls called on a large folder hierarchy will take a long time for its execution.
+# For this reason now method can also be called asynchronously if transaction reaches system.fixedACLs.maxTransactionTime.
+# In this case setFixedAcls method recursion will be stopped and unfinished nodes will be marked with ASPECT_PENDING_FIX_ACL.
+# Pending nodes will be processed by FixedAclUpdater, programmatically called but also configured as a scheduled job.
+system.fixedACLs.maxTransactionTime=10000
+# fixedACLsUpdater - lock time to live
+system.fixedACLsUpdater.lockTTL=10000
+# fixedACLsUpdater - maximum number of nodes to process per execution
+system.fixedACLsUpdater.maxItemBatchSize=100
+# fixedACLsUpdater - the number of threads to use
+system.fixedACLsUpdater.numThreads=4
+# fixedACLsUpdater - Force shared ACL to propagate through children even if there is an unexpected ACL
+system.fixedACLsUpdater.forceSharedACL=false
+# fixedACLsUpdater cron expression - fire at midnight every day
+system.fixedACLsUpdater.cronExpression=0 0 0 * * ?
+
+cmis.disable.hidden.leading.period.files=false
+
+#Smart Folders Config Properties
+smart.folders.enabled=false
+
+#Smart reference config
+smart.reference.classpath.hash=${smart.folders.config.vanilla.processor.classpath}->1,${smart.folders.config.system.templates.classpath}->2
+
+#Smart store config
+
+#Company home relative download associations of smart entries
+smart.download.associations.folder=${spaces.dictionary.childname}/${spaces.smartdownloads.childname}
+
+#Generic virtualization methods config
+
+#Vanilla JSON templates javascript processor classpath. A java script processor used to
+#covert JSON templates to internal smart folder definitions.
+
+smart.folders.config.vanilla.processor.classpath=/org/alfresco/repo/virtual/node/vanilla.js
+
+#System virtualization method config
+
+#System virtualization method aspect.
+smart.folders.config.system.aspect=smf:systemConfigSmartFolder
+#System virtualization method aspect defined template location property.
+smart.folders.config.system.aspect.template.location.property=smf:system-template-location
+#Classpath to be explored for *.json entries defining system templates.
+smart.folders.config.system.templates.classpath=/org/alfresco/repo/virtual/node
+#A company home relative name or qname path location of repository system templates.
+smart.folders.config.system.templates.path=${spaces.dictionary.childname}/${spaces.smartfolders.childname}
+#Content sub type of repository system templates.
+smart.folders.config.system.templates.template.type=smf:smartFolderTemplate
+
+#Custom virtualization method config
+
+#Custom virtualization method aspect.
+smart.folders.config.custom.aspect=smf:customConfigSmartFolder
+#Custom virtualization method aspect template content association.
+smart.folders.config.custom.aspect.template.association=smf:custom-template-association
+
+
+#Type virtualization method config
+
+#A company home relative name or qname path location of the type mapped templates.
+smart.folders.config.type.templates.path=${spaces.dictionary.childname}/${spaces.smartfolders.childname}
+#Type and aspect qname regular expression filter.
+smart.folders.config.type.templates.qname.filter=none
+
+# Preferred password encoding, md4, sha256, bcrypt10
+system.preferred.password.encoding=md4
+
+# Upgrade Password Hash Job
+system.upgradePasswordHash.jobBatchSize=100
+system.upgradePasswordHash.jobQueryRange=10000
+system.upgradePasswordHash.jobThreadCount=4
+system.upgradePasswordHash.jobCronExpression=* * * * * ? 2099
+
+system.api.discovery.enabled=true
+
+# Maximum query size for category/tag fetch when not explicitly set by paging parameters
+category.queryFetchSize=5000
+
+# Brute force protection
+authentication.protection.enabled=true
+authentication.protection.limit=10
+authentication.protection.periodSeconds=6
+
+system.email.sender.default=noreply@alfresco.com
+# reset password workflow will expire in an hour
+system.reset-password.endTimer=PT1H
+system.reset-password.sendEmailAsynchronously=true
+
+# HeartBeat
+heartbeat.target.url=
+heartbeat.enabled=true
+
+# CSRF filter overrides
+csrf.filter.enabled=true
+csrf.filter.referer=
+csrf.filter.referer.always=false
+csrf.filter.origin=
+csrf.filter.origin.always=false
+
+# CORS settings
+cors.enabled=false
+cors.allowed.origins=
+cors.allowed.methods=GET,POST,HEAD,OPTIONS,PUT,DELETE
+cors.allowed.headers=Authorization,Content-Type,Cache-Control,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,X-CSRF-Token
+cors.exposed.headers=Access-Control-Allow-Origin,Access-Control-Allow-Credentials
+cors.support.credentials=true
+cors.preflight.maxage=10
+
+# Alfresco Rest Api-Explorer
+api-explorer.url=
+
+# Events subsystem
+events.subsystem.autoStart=false
+# Messaging subsystem
+messaging.subsystem.autoStart=true
+
+
+# Raw events
+acs.repo.rendition.events.endpoint=jms:acs-repo-rendition-events?jmsMessageType=Text
+
+# Transform request events
+acs.repo.transform.request.endpoint=jms:acs-repo-transform-request?jmsMessageType=Text
+
+# If enabled doesn't allow to set content properties via NodeService
+contentPropertyRestrictions.enabled=true
+contentPropertyRestrictions.whitelist=
+
+# Repo events2
+# Type and aspect filters which should be excluded
+# Note: System folders node types are added by default
+repo.event2.filter.nodeTypes=sys:*, fm:*, cm:thumbnail, cm:failedThumbnail, cm:rating, rma:rmsite include_subtypes
+repo.event2.filter.nodeAspects=sys:*
+repo.event2.filter.childAssocTypes=rn:rendition
+# Comma separated list of users which should be excluded
+# Note: username's case-sensitivity depends on the {user.name.caseSensitive} setting
+repo.event2.filter.users=
+# Topic name
+repo.event2.topic.endpoint=amqp:topic:alfresco.repo.event2
+# Thread pool for async enqueue of repo events
+repo.event2.queue.enqueueThreadPool.priority=1
+repo.event2.queue.enqueueThreadPool.coreSize=8
+repo.event2.queue.enqueueThreadPool.maximumSize=10
+# Thread pool for async dequeue and delivery of repo events
+repo.event2.queue.dequeueThreadPool.priority=1
+repo.event2.queue.dequeueThreadPool.coreSize=1
+repo.event2.queue.dequeueThreadPool.maximumSize=1
+
+
+# MNT-21083
+# --DELETE_NOT_EXISTS - default settings
+system.delete_not_exists.batchsize=100000
+system.delete_not_exists.delete_batchsize=1000
+system.delete_not_exists.read_only=false
+system.delete_not_exists.timeout_seconds=-1
+system.prop_table_cleaner.algorithm=V2
+
+# Configure the system-wide (ACS) settings for direct access urls.
+#
+# For Direct Access URLs to be usable on the service-layer, the feature must be enabled both system-wide and on the
+# content-store(s). For the feature to be usable through REST (outside the JVM) the rest-api configuration must also be
+# enabled.
+#
+# The system.directAccessUrl.enabled property is the main switch of the feature. If this is set to false ALL
+# Direct Access URLs are disabled.
+#
+# The next configuration that controls specific Direct Access URLs is the content store one.
+# The connector.s3.directAccessUrl.enabled property controls whether Direct Access URLs are enabled for that specific store.
+#
+# Whether or not a client can request a Direct Access URL by using a REST endpoint is controlled by the
+# restApi.directAccessUrl.enabled property. If the REST endpoint is disabled, but the feature is enabled
+# system-wide and on the content-store, then the direct access URLs will only be usable by Java clients (only
+# service-level requests will be possible).
+
+# Controls whether this feature is available, system wide.
+# For direct access urls to work, the feature needs to be enabled both system-wide and on the individual content-store.
+system.directAccessUrl.enabled=false
+# Sets the default expiry time for the direct access url across all Content Stores.
+# Its value cannot exceed the system-wide max expiry time, it can only be equal or lower (all DAUs disabled otherwise).
+# This property is mandatory if direct access urls are enabled system-wide - (all DAUs disabled otherwise).
+system.directAccessUrl.defaultExpiryTimeInSec=30
+# Sets the upper limit for the direct access urls expiry time, meaning a Content Store will be able to override this
+# value but not exceed it, and the same goes for the clients.
+# A service (Java Interface) client will be able to request a direct access url for a custom expiry time but that time
+# can’t exceed this value.
+# If the requested time exceeds the max value, the expiry time reverts to the default configured one.
+# This property is mandatory if direct access urls are enabled system-wide - (all DAUs disabled otherwise).
+system.directAccessUrl.maxExpiryTimeInSec=300
+
+# Configure the common S3 storage connector content store settings for direct access urls.
+#
+# Note: When multiple S3 buckets are used for storage in Alfresco, each S3 Content Stores can be configured with either
+# the default (common) S3 Connector-specific properties (i.e. connector.s3.directAccessUrl.enabled etc.) OR new separate
+# properties could be defined for each and every store (e.g.
+# connector.s3store1.directAccessUrl.enabled,
+# connector.s3store2.directAccessUrl.enabled etc.).
+
+# Controls whether DAUs are enabled on this specific content store.
+# For direct access urls to work, the feature needs to be enabled both system-wide and on the individual content-store.
+connector.s3.directAccessUrl.enabled=false
+# Sets the expiry time for the direct access url in this store, by overriding the system-wide config.
+# If this value exceeds the content store upper limit or the system-wide default it will fallback to the system-wide
+# default configuration.
+# Its value cannot exceed the system-wide max expiry time, it can only be equal or lower (DAUs for the specific content
+# store disabled otherwise).
+# If not set, the default system-wide setting will be used.
+connector.s3.directAccessUrl.defaultExpiryTimeInSec=30
+# The maximum expiry time interval that can be requested by clients - content-store specific setting.
+# Its value cannot exceed the system-wide configuration, it can only be equal or lower (DAUs for the specific content
+# store disabled otherwise).
+# If not set, the default system-wide setting will be used.
+connector.s3.directAccessUrl.maxExpiryTimeInSec=300
+
+# Configure the REST API configuration settings for direct access urls.
+#
+# Controls whether direct access url requests via the REST API are enabled.
+restApi.directAccessUrl.enabled=false
+# Sets the expiry time for all the direct access urls requested via a REST call.
+# Its value cannot exceed the system-wide max expiry time configuration, it can only be equal or lower (REST API DAUs
+# disabled otherwise).
+# If not set, the default system-wide setting will be used.
+# Direct Access Url REST API calls cannot request an explicit expiry time.
+restApi.directAccessUrl.defaultExpiryTimeInSec=30
+
+# Creates additional indexes on alf_node and alf_transaction. Recommended for large repositories.
+system.new-node-transaction-indexes.ignored=true
+
+# Allows the configuration of maximum limits of the temp files to be deleted or the maximum time allowed to run for the job
+system.tempFileCleaner.maxFilesToDelete=
+system.tempFileCleaner.maxTimeToRun=
+
+# Property to long running migration to remove alf_server in v7+ patch.db-V7.1.0-remove-alf_server-table
+system.remove-alf_server-table-from-db.ignored=true
diff --git a/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java b/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java
index 75a8e4c9c7..7836b7cbec 100644
--- a/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java
+++ b/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java
@@ -180,6 +180,9 @@ import org.junit.runners.Suite;
org.alfresco.repo.audit.AuditableAnnotationTest.class,
org.alfresco.repo.audit.PropertyAuditFilterTest.class,
org.alfresco.repo.audit.access.NodeChangeTest.class,
+ org.alfresco.repo.content.ContentServiceImplUnitTest.class,
+ org.alfresco.repo.content.directurl.SystemWideDirectUrlConfigUnitTest.class,
+ org.alfresco.repo.content.directurl.ContentStoreDirectUrlConfigUnitTest.class,
org.alfresco.repo.content.LimitedStreamCopierTest.class,
org.alfresco.repo.content.filestore.FileIOTest.class,
org.alfresco.repo.content.filestore.SpoofedTextContentReaderTest.class,
diff --git a/repository/src/test/java/org/alfresco/repo/content/ContentServiceImplUnitTest.java b/repository/src/test/java/org/alfresco/repo/content/ContentServiceImplUnitTest.java
new file mode 100644
index 0000000000..63e6530715
--- /dev/null
+++ b/repository/src/test/java/org/alfresco/repo/content/ContentServiceImplUnitTest.java
@@ -0,0 +1,160 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.content;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.content.directurl.DirectAccessUrlDisabledException;
+import org.alfresco.repo.content.directurl.SystemWideDirectUrlConfig;
+import org.alfresco.service.cmr.repository.ContentData;
+import org.alfresco.service.cmr.repository.DirectAccessUrl;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+/**
+ * Unit tests for content service implementation.
+ *
+ * @author Sara Aspery
+ */
+public class ContentServiceImplUnitTest
+{
+ private static final Boolean ENABLED = Boolean.TRUE;
+ private static final Boolean DISABLED = Boolean.FALSE;
+
+ private static final Long SYS_DEFAULT_EXPIRY_TIME_IN_SECS = 30L;
+ private static final Long SYS_MAX_EXPIRY_TIME_IN_SECS = 300L;
+
+ private static final NodeRef NODE_REF = new NodeRef("content://Node/Ref");
+
+ @InjectMocks
+ private ContentServiceImpl contentService;
+
+ @Mock
+ private ContentStore mockContentStore;
+
+ @Mock
+ private NodeService mockNodeService;
+
+ @Mock
+ private ContentData mockContentData;
+
+ @Before
+ public void setup()
+ {
+ openMocks(this);
+ when(mockNodeService.getProperty(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentData);
+ when(mockContentData.getContentUrl()).thenReturn("someContentUrl");
+ when(mockNodeService.getProperty(NODE_REF, ContentModel.PROP_NAME)).thenReturn("someFilename");
+ }
+
+ @Test
+ public void testIsContentDirectUrlEnabled_SystemWideIsDisabled()
+ {
+ setupSystemWideDirectAccessConfig(DISABLED);
+ assertFalse("Expected contentDirectUrl to be disabled", contentService.isContentDirectUrlEnabled());
+ verify(mockContentStore, never()).isContentDirectUrlEnabled();
+ }
+
+ @Test
+ public void testIsContentDirectUrlEnabled_SystemWideIsEnabledButStoreIsDisabled()
+ {
+ setupSystemWideDirectAccessConfig(ENABLED);
+ when(mockContentStore.isContentDirectUrlEnabled()).thenReturn(DISABLED);
+ assertFalse("Expected contentDirectUrl to be disabled", contentService.isContentDirectUrlEnabled());
+ }
+
+ @Test
+ public void testIsContentDirectUrlEnabled_SystemWideIsEnabledAndStoreIsEnabled()
+ {
+ setupSystemWideDirectAccessConfig(ENABLED);
+ when(mockContentStore.isContentDirectUrlEnabled()).thenReturn(ENABLED);
+ assertTrue("Expected contentDirectUrl to be enabled", contentService.isContentDirectUrlEnabled());
+ }
+
+ @Test
+ public void testRequestContentDirectUrl_SystemWideIsDisabled()
+ {
+ setupSystemWideDirectAccessConfig(DISABLED);
+ try
+ {
+ contentService.requestContentDirectUrl(NODE_REF, true, 20L);
+ fail("Expected DirectAccessUrlDisabledException");
+ }
+ catch (DirectAccessUrlDisabledException ex)
+ {
+ verify(mockContentStore, never()).isContentDirectUrlEnabled();
+ }
+ }
+
+ @Test
+ public void testRequestContentDirectUrl_SystemWideIsEnabledButStoreIsDisabled()
+ {
+ setupSystemWideDirectAccessConfig(ENABLED);
+ when(mockContentStore.isContentDirectUrlEnabled()).thenReturn(DISABLED);
+
+ DirectAccessUrl directAccessUrl = contentService.requestContentDirectUrl(NODE_REF, true, 20L);
+ assertNull(directAccessUrl);
+ verify(mockContentStore, never()).requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong());
+ }
+
+ @Test
+ public void testRequestContentDirectUrl_StoreIsEnabledButNotImplemented()
+ {
+ setupSystemWideDirectAccessConfig(ENABLED);
+ when(mockContentStore.isContentDirectUrlEnabled()).thenReturn(ENABLED);
+
+ DirectAccessUrl directAccessUrl = contentService.requestContentDirectUrl(NODE_REF, true, 20L);
+ assertNull(directAccessUrl);
+ verify(mockContentStore, times(1)).requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong());
+ }
+
+ /* Helper method to set system-wide direct access url configuration settings */
+ private void setupSystemWideDirectAccessConfig(Boolean isEnabled)
+ {
+ SystemWideDirectUrlConfig sysConfig = new SystemWideDirectUrlConfig();
+ sysConfig.setEnabled(isEnabled);
+ sysConfig.setDefaultExpiryTimeInSec(SYS_DEFAULT_EXPIRY_TIME_IN_SECS);
+ sysConfig.setMaxExpiryTimeInSec(SYS_MAX_EXPIRY_TIME_IN_SECS);
+ sysConfig.validate();
+ contentService.setSystemWideDirectUrlConfig(sysConfig);
+ }
+}
diff --git a/repository/src/test/java/org/alfresco/repo/content/caching/CachingContentStoreTest.java b/repository/src/test/java/org/alfresco/repo/content/caching/CachingContentStoreTest.java
index ffac9eea8b..f35d0b08d4 100644
--- a/repository/src/test/java/org/alfresco/repo/content/caching/CachingContentStoreTest.java
+++ b/repository/src/test/java/org/alfresco/repo/content/caching/CachingContentStoreTest.java
@@ -35,6 +35,7 @@ import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
@@ -493,10 +494,10 @@ public class CachingContentStoreTest
@Test
public void isDirectAccessSupported()
{
- assertFalse(cachingStore.isDirectAccessSupported());
+ assertFalse(cachingStore.isContentDirectUrlEnabled());
- when(backingStore.isDirectAccessSupported()).thenReturn(true);
- assertTrue(cachingStore.isDirectAccessSupported());
+ when(backingStore.isContentDirectUrlEnabled()).thenReturn(true);
+ assertTrue(cachingStore.isContentDirectUrlEnabled());
}
@Test
@@ -504,8 +505,8 @@ public class CachingContentStoreTest
{
try
{
- when(backingStore.getDirectAccessUrl(anyString(), any())).thenThrow(new UnsupportedOperationException());
- cachingStore.getDirectAccessUrl("url", null);
+ when(backingStore.requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong())).thenThrow(new UnsupportedOperationException());
+ cachingStore.requestContentDirectUrl("url", true,"someFile", 30L);
fail();
}
catch (UnsupportedOperationException e)
@@ -517,7 +518,7 @@ public class CachingContentStoreTest
@Test
public void getDirectAccessUrl()
{
- when(backingStore.getDirectAccessUrl(anyString(), any())).thenReturn(new DirectAccessUrl());
- cachingStore.getDirectAccessUrl("url", null);
+ when(backingStore.requestContentDirectUrl(anyString(), eq(true), anyString(), anyLong())).thenReturn(new DirectAccessUrl());
+ cachingStore.requestContentDirectUrl("url", true,"someFile", 30L);
}
}
diff --git a/repository/src/test/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfigUnitTest.java b/repository/src/test/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfigUnitTest.java
new file mode 100644
index 0000000000..b32ed63be8
--- /dev/null
+++ b/repository/src/test/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfigUnitTest.java
@@ -0,0 +1,234 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.content.directurl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for content store direct access URL configuration settings.
+ *
+ * @author Sara Aspery
+ */
+public class ContentStoreDirectUrlConfigUnitTest
+{
+ private static final Boolean ENABLED = Boolean.TRUE;
+ private static final Boolean DISABLED = Boolean.FALSE;
+
+ private static final Long DEFAULT_EXPIRY_TIME_IN_SECS = 10L;
+ private static final Long MAX_EXPIRY_TIME_IN_SECS = 20L;
+
+ private static final Long SYS_DEFAULT_EXPIRY_TIME_IN_SECS = 30L;
+ private static final Long SYS_MAX_EXPIRY_TIME_IN_SECS = 300L;
+
+ private ContentStoreDirectUrlConfig contentStoreDirectUrlConfig;
+
+ @Before
+ public void setup()
+ {
+ this.contentStoreDirectUrlConfig = new ContentStoreDirectUrlConfig();
+ setupSystemWideDirectAccessConfig();
+ }
+
+ @Test
+ public void testValidConfig_RemainsEnabled()
+ {
+ setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS);
+
+ assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled());
+ contentStoreDirectUrlConfig.validate();
+ assertTrue("Expected REST API direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testValidConfig_RemainsDisabled()
+ {
+ setupDirectAccessConfig(DISABLED, DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS);
+
+ assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled());
+ contentStoreDirectUrlConfig.validate();
+ assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeMissing_ValidReplacement()
+ {
+ Long maxExpiryTimeInSecs = SYS_DEFAULT_EXPIRY_TIME_IN_SECS + 1;
+ setupDirectAccessConfig(ENABLED, null, maxExpiryTimeInSecs);
+
+ verifyDirectAccessConfig(ENABLED, null, maxExpiryTimeInSecs);
+ contentStoreDirectUrlConfig.validate();
+ verifyDirectAccessConfig(ENABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, maxExpiryTimeInSecs);
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeMissing_ReplacementExceedsMax()
+ {
+ setupDirectAccessConfig(ENABLED, null, MAX_EXPIRY_TIME_IN_SECS);
+
+ verifyDirectAccessConfig(ENABLED, null, MAX_EXPIRY_TIME_IN_SECS);
+ contentStoreDirectUrlConfig.validate();
+ verifyDirectAccessConfig(DISABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS);
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeZero()
+ {
+ setupDirectAccessConfig(ENABLED, 0L, MAX_EXPIRY_TIME_IN_SECS);
+
+ assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled());
+ contentStoreDirectUrlConfig.validate();
+ assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeNegative()
+ {
+ setupDirectAccessConfig(ENABLED, -1L, MAX_EXPIRY_TIME_IN_SECS);
+
+ assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled());
+ contentStoreDirectUrlConfig.validate();
+ assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeExceedsSystemMax()
+ {
+ Long defaultExpiryTimeInSecs = SYS_MAX_EXPIRY_TIME_IN_SECS + 1;
+ setupDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, MAX_EXPIRY_TIME_IN_SECS);
+
+ assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled());
+ contentStoreDirectUrlConfig.validate();
+ assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeExceedsStoreMax_ValidReplacement()
+ {
+ Long maxExpiryTimeInSecs = SYS_DEFAULT_EXPIRY_TIME_IN_SECS + 1;
+ Long defaultExpiryTimeInSecs = maxExpiryTimeInSecs + 1;
+ setupDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, maxExpiryTimeInSecs);
+
+ verifyDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, maxExpiryTimeInSecs);
+ contentStoreDirectUrlConfig.validate();
+ verifyDirectAccessConfig(ENABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, maxExpiryTimeInSecs);
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeExceedsStoreMax_ReplacementExceedsStoreMax()
+ {
+ Long defaultExpiryTimeInSecs = MAX_EXPIRY_TIME_IN_SECS + 1;
+ setupDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, MAX_EXPIRY_TIME_IN_SECS);
+
+ verifyDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, MAX_EXPIRY_TIME_IN_SECS);
+ contentStoreDirectUrlConfig.validate();
+ verifyDirectAccessConfig(DISABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS);
+ }
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeExceedsSystemDefault_ValidReplacement()
+ {
+ Long defaultExpiryTimeInSecs = SYS_DEFAULT_EXPIRY_TIME_IN_SECS + 1;
+ Long maxExpiryTimeInSecs = SYS_MAX_EXPIRY_TIME_IN_SECS;
+ setupDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, maxExpiryTimeInSecs);
+
+ verifyDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, maxExpiryTimeInSecs);
+ contentStoreDirectUrlConfig.validate();
+ verifyDirectAccessConfig(ENABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, maxExpiryTimeInSecs);
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeExceedsSystemDefault_ReplacementExceedsStoreMax()
+ {
+ Long defaultExpiryTimeInSecs = SYS_DEFAULT_EXPIRY_TIME_IN_SECS + 1;
+ setupDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, MAX_EXPIRY_TIME_IN_SECS);
+
+ verifyDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, MAX_EXPIRY_TIME_IN_SECS);
+ contentStoreDirectUrlConfig.validate();
+ verifyDirectAccessConfig(DISABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS);
+ }
+
+ @Test
+ public void testInvalidConfig_MaxExpiryTimeZero()
+ {
+ setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, 0L);
+
+ assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled());
+ contentStoreDirectUrlConfig.validate();
+ assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_MaxExpiryTimeNegative()
+ {
+ setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, -1L);
+
+ assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled());
+ contentStoreDirectUrlConfig.validate();
+ assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_MaxExpiryTimeExceedsSystemMax()
+ {
+ Long maxExpiryTimeInSec = contentStoreDirectUrlConfig.getSysWideMaxExpiryTimeInSec() + 1;
+ setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, maxExpiryTimeInSec);
+
+ assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled());
+ contentStoreDirectUrlConfig.validate();
+ assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled());
+ }
+
+ /* Helper method to set content store direct access url configuration settings */
+ private void setupDirectAccessConfig(Boolean isEnabled, Long defaultExpiryTime, Long maxExpiryTime)
+ {
+ contentStoreDirectUrlConfig.setEnabled(isEnabled);
+ contentStoreDirectUrlConfig.setDefaultExpiryTimeInSec(defaultExpiryTime);
+ contentStoreDirectUrlConfig.setMaxExpiryTimeInSec(maxExpiryTime);
+ }
+
+ /* Helper method to verify content store direct access url configuration settings */
+ private void verifyDirectAccessConfig(Boolean isEnabled, Long defaultExpiryTime, Long maxExpiryTime)
+ {
+ assertEquals("Expected content store direct URLs to be enabled = " + isEnabled, isEnabled, contentStoreDirectUrlConfig.isEnabled());
+ assertEquals("Expected default expiry time to match " + defaultExpiryTime, defaultExpiryTime, contentStoreDirectUrlConfig.getDefaultExpiryTimeInSec());
+ assertEquals("Expected maximum expiry time to match " + maxExpiryTime, maxExpiryTime, contentStoreDirectUrlConfig.getMaxExpiryTimeInSec());
+ }
+
+ /* Helper method to set system-wide direct access url configuration settings */
+ private void setupSystemWideDirectAccessConfig()
+ {
+ SystemWideDirectUrlConfig sysConfig = new SystemWideDirectUrlConfig();
+ sysConfig.setEnabled(ENABLED);
+ sysConfig.setDefaultExpiryTimeInSec(SYS_DEFAULT_EXPIRY_TIME_IN_SECS);
+ sysConfig.setMaxExpiryTimeInSec(SYS_MAX_EXPIRY_TIME_IN_SECS);
+ sysConfig.validate();
+ contentStoreDirectUrlConfig.setSystemWideDirectUrlConfig(sysConfig);
+ }
+}
diff --git a/repository/src/test/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfigUnitTest.java b/repository/src/test/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfigUnitTest.java
new file mode 100644
index 0000000000..d498fac30b
--- /dev/null
+++ b/repository/src/test/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfigUnitTest.java
@@ -0,0 +1,153 @@
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.content.directurl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for system-wide direct access URL configuration settings.
+ *
+ * @author Sara Aspery
+ */
+public class SystemWideDirectUrlConfigUnitTest
+{
+ private static final Boolean ENABLED = Boolean.TRUE;
+ private static final Boolean DISABLED = Boolean.FALSE;
+
+ private static final Long DEFAULT_EXPIRY_TIME_IN_SECS = 30L;
+ private static final Long MAX_EXPIRY_TIME_IN_SECS = 300L;
+
+ private SystemWideDirectUrlConfig systemWideDirectUrlConfig;
+
+ @Before
+ public void setup()
+ {
+ this.systemWideDirectUrlConfig = new SystemWideDirectUrlConfig();
+ }
+
+ @Test
+ public void testValidConfig_RemainsEnabled()
+ {
+ setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS);
+
+ assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled());
+ systemWideDirectUrlConfig.validate();
+ assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testValidConfig_RemainsDisabled()
+ {
+ setupDirectAccessConfig(DISABLED, DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS);
+
+ assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled());
+ systemWideDirectUrlConfig.validate();
+ assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeMissing()
+ {
+ setupDirectAccessConfig(ENABLED, null, MAX_EXPIRY_TIME_IN_SECS);
+
+ assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled());
+ systemWideDirectUrlConfig.validate();
+ assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeZero()
+ {
+ setupDirectAccessConfig(ENABLED, 0L, MAX_EXPIRY_TIME_IN_SECS);
+
+ assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled());
+ systemWideDirectUrlConfig.validate();
+ assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeNegative()
+ {
+ setupDirectAccessConfig(ENABLED, -1L, MAX_EXPIRY_TIME_IN_SECS);
+
+ assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled());
+ systemWideDirectUrlConfig.validate();
+ assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_MaxExpiryTimeMissing()
+ {
+ setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, null);
+
+ assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled());
+ systemWideDirectUrlConfig.validate();
+ assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_MaxExpiryTimeZero()
+ {
+ setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, 0L);
+
+ assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled());
+ systemWideDirectUrlConfig.validate();
+ assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_MaxExpiryTimeNegative()
+ {
+ setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, -1L);
+
+ assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled());
+ systemWideDirectUrlConfig.validate();
+ assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled());
+ }
+
+ @Test
+ public void testInvalidConfig_DefaultExpiryTimeExceedsMax()
+ {
+ setupDirectAccessConfig(ENABLED, MAX_EXPIRY_TIME_IN_SECS + 1, MAX_EXPIRY_TIME_IN_SECS);
+
+ assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled());
+ systemWideDirectUrlConfig.validate();
+ assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled());
+ }
+
+ /* Helper method to set system-wide direct access url configuration settings */
+ private void setupDirectAccessConfig(Boolean isEnabled, Long defaultExpiryTime, Long maxExpiryTime)
+ {
+ systemWideDirectUrlConfig.setEnabled(isEnabled);
+ systemWideDirectUrlConfig.setDefaultExpiryTimeInSec(defaultExpiryTime);
+ systemWideDirectUrlConfig.setMaxExpiryTimeInSec(maxExpiryTime);
+ }
+}
+
diff --git a/repository/src/test/java/org/alfresco/repo/content/replication/AggregatingContentStoreTest.java b/repository/src/test/java/org/alfresco/repo/content/replication/AggregatingContentStoreTest.java
index ecfaf17823..585843f155 100644
--- a/repository/src/test/java/org/alfresco/repo/content/replication/AggregatingContentStoreTest.java
+++ b/repository/src/test/java/org/alfresco/repo/content/replication/AggregatingContentStoreTest.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -56,9 +56,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
@@ -191,7 +189,7 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
}
@Test
- public void testIsDirectAccessSupported()
+ public void testIsContentDirectUrlEnabled()
{
// Create the aggregating store
AggregatingContentStore aggStore = new AggregatingContentStore();
@@ -199,21 +197,21 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
aggStore.setSecondaryStores(List.of(secondaryStoreMock));
// By default it is unsupported
- assertFalse(aggStore.isDirectAccessSupported());
+ assertFalse(aggStore.isContentDirectUrlEnabled());
// Supported if at least one store supports direct access
{
- when(primaryStoreMock.isDirectAccessSupported()).thenReturn(false);
- when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(true);
- assertTrue(aggStore.isDirectAccessSupported());
+ when(primaryStoreMock.isContentDirectUrlEnabled()).thenReturn(false);
+ when(secondaryStoreMock.isContentDirectUrlEnabled()).thenReturn(true);
+ assertTrue(aggStore.isContentDirectUrlEnabled());
- when(primaryStoreMock.isDirectAccessSupported()).thenReturn(true);
- when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(true);
- assertTrue(aggStore.isDirectAccessSupported());
+ when(primaryStoreMock.isContentDirectUrlEnabled()).thenReturn(true);
+ when(secondaryStoreMock.isContentDirectUrlEnabled()).thenReturn(true);
+ assertTrue(aggStore.isContentDirectUrlEnabled());
- when(primaryStoreMock.isDirectAccessSupported()).thenReturn(true);
- when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(false);
- assertTrue(aggStore.isDirectAccessSupported());
+ when(primaryStoreMock.isContentDirectUrlEnabled()).thenReturn(true);
+ when(secondaryStoreMock.isContentDirectUrlEnabled()).thenReturn(false);
+ assertTrue(aggStore.isContentDirectUrlEnabled());
}
}
@@ -229,15 +227,15 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
UnsupportedContentUrlException unsupportedContentUrlExc = new UnsupportedContentUrlException(aggStore, "");
// By default it is unsupported
- DirectAccessUrl directAccessUrl = aggStore.getDirectAccessUrl("url", null);
+ DirectAccessUrl directAccessUrl = aggStore.requestContentDirectUrl("url", true, "anyfilename", 30L);
assertNull(directAccessUrl);
// Direct access not supported
try
{
- when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
- aggStore.getDirectAccessUrl("urlDANotSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ aggStore.requestContentDirectUrl(eq("urlDANotSupported"), true, "anyfilename", 30L);
fail();
}
catch (UnsupportedOperationException e)
@@ -247,9 +245,9 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
try
{
- when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedContentUrlExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
- aggStore.getDirectAccessUrl("urlDANotSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ aggStore.requestContentDirectUrl("urlDANotSupported", true, "anyfilename", 30L);
fail();
}
catch (UnsupportedOperationException e)
@@ -259,9 +257,9 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
try
{
- when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedContentUrlExc);
- aggStore.getDirectAccessUrl("urlDANotSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlDANotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ aggStore.requestContentDirectUrl("urlDANotSupported", true, "anyfilename", 30L);
fail();
}
catch (UnsupportedOperationException e)
@@ -272,9 +270,9 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
// Content url not supported
try
{
- when(primaryStoreMock.getDirectAccessUrl(eq("urlNotSupported"), any())).thenThrow(unsupportedContentUrlExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlNotSupported"), any())).thenThrow(unsupportedContentUrlExc);
- aggStore.getDirectAccessUrl("urlNotSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlNotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlNotSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ aggStore.requestContentDirectUrl("urlNotSupported", true, "anyfilename", 30L);
fail();
}
catch (UnsupportedContentUrlException e)
@@ -282,31 +280,31 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
// Expected
}
- when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl());
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenThrow(unsupportedExc);
- directAccessUrl = aggStore.getDirectAccessUrl("urlPriSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
- when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl());
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenThrow(unsupportedContentUrlExc);
- directAccessUrl = aggStore.getDirectAccessUrl("urlPriSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
- when(primaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenThrow(unsupportedExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl());
- directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenThrow(unsupportedExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
- when(primaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenThrow(unsupportedContentUrlExc);
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl());
- directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenThrow(unsupportedContentUrlExc);
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
- when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl());
- when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl());
- directAccessUrl = aggStore.getDirectAccessUrl("urlPriSupported", null);
+ when(primaryStoreMock.requestContentDirectUrl(eq("urlPriSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ when(secondaryStoreMock.requestContentDirectUrl(eq("urlSecSupported"), any(), any(), any())).thenReturn(new DirectAccessUrl());
+ directAccessUrl = aggStore.requestContentDirectUrl("urlPriSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
- directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null);
+ directAccessUrl = aggStore.requestContentDirectUrl("urlSecSupported", true, "anyfilename", 30L);
assertNotNull(directAccessUrl);
}
}
diff --git a/repository/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java b/repository/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java
index 5cebb8acaf..5423fd3077 100644
--- a/repository/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java
+++ b/repository/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,18 +25,16 @@
*/
package org.alfresco.repo.version;
-import org.alfresco.error.AlfrescoRuntimeException;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.ContentStore;
-import org.alfresco.repo.content.EmptyContentReader;
-import org.alfresco.repo.content.MimetypeMap;
-import org.alfresco.repo.content.MimetypeMapTest;
+import org.alfresco.repo.content.directurl.SystemWideDirectUrlConfig;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
-import org.alfresco.service.cmr.repository.NoTransformerException;
import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.namespace.QName;
import org.alfresco.test_category.OwnJVMTestsCategory;
@@ -44,10 +42,11 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.annotation.Transactional;
-import java.util.Date;
/**
* Tests for getting content readers and writers.
@@ -57,7 +56,9 @@ import java.util.Date;
@Category(OwnJVMTestsCategory.class)
@Transactional
public class ContentServiceImplTest extends BaseVersionStoreTest
-{
+{
+ private static final Boolean ENABLED = Boolean.TRUE;
+
/**
* Test content data
*/
@@ -66,9 +67,14 @@ public class ContentServiceImplTest extends BaseVersionStoreTest
/**
* The version content store
*/
+ @InjectMocks
private ContentService contentService;
+
private ContentStore contentStore;
+ @Mock
+ private SystemWideDirectUrlConfig mockSystemWideDirectUrlConfig;
+
@Before
public void before() throws Exception
{
@@ -139,15 +145,17 @@ public class ContentServiceImplTest extends BaseVersionStoreTest
}
@Test
- public void testWhenGetDirectAccessUrlIsNotSupported()
+ public void testWhenRequestContentDirectUrlIsNotSupported()
{
- assertFalse(contentStore.isDirectAccessSupported());
+ openMocks(this);
+ when(mockSystemWideDirectUrlConfig.isEnabled()).thenReturn(ENABLED);
+ when(mockSystemWideDirectUrlConfig.getDefaultExpiryTimeInSec()).thenReturn(30L);
+ when(mockSystemWideDirectUrlConfig.getMaxExpiryTimeInSec()).thenReturn(300L);
+
+ assertFalse(contentStore.isContentDirectUrlEnabled());
// Set the presigned URL to expire after one minute.
- Date expiresAt = new Date();
- long expTimeMillis = expiresAt.getTime();
- expTimeMillis += 1000 * 60;
- expiresAt.setTime(expTimeMillis);
+ Long validFor = 60L;
try
{
@@ -155,7 +163,7 @@ public class ContentServiceImplTest extends BaseVersionStoreTest
NodeRef nodeRef = this.dbNodeService
.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName("{test}MyNoContentNode"), TEST_TYPE_QNAME, this.nodeProperties).getChildRef();
- assertEquals(null, contentService.getDirectAccessUrl(nodeRef, expiresAt));
+ assertNull(contentService.requestContentDirectUrl(nodeRef, true, validFor));
fail("nodeRef has no content");
}
catch (IllegalArgumentException e)
@@ -165,7 +173,7 @@ public class ContentServiceImplTest extends BaseVersionStoreTest
try
{
- assertEquals(null, contentService.getDirectAccessUrl(null, null));
+ assertNull(contentService.requestContentDirectUrl(null, true, null));
fail("nodeRef is null");
}
catch (IllegalArgumentException e)
@@ -176,7 +184,7 @@ public class ContentServiceImplTest extends BaseVersionStoreTest
// Create a node with content
NodeRef nodeRef = createNewVersionableNode();
- assertEquals(null, contentService.getDirectAccessUrl(nodeRef, null));
- assertEquals(null, contentService.getDirectAccessUrl(nodeRef, expiresAt));
+ assertNull(contentService.requestContentDirectUrl(nodeRef, true, null));
+ assertNull(contentService.requestContentDirectUrl(nodeRef, true, validFor));
}
}