mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-22 15:12:38 +00:00
REPO-1219: Allow file content URLs to be generated by a provider
- merged implementation from ACE-5093 - marked the FileContentUrlProvider as public - added the default implementation bean, and injected it in the TenantRoutingFileContentStore git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@132105 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -60,6 +60,9 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="defaultFileContentUrlProvider" class="org.alfresco.repo.content.filestore.TimeBasedFileContentUrlProvider">
|
||||||
|
<property name="bucketsPerMinute" value="${dir.contentstore.bucketsPerMinute}"/>
|
||||||
|
</bean>
|
||||||
<!-- This content limit provider is used above (and can also be overriden, eg. by modules). -->
|
<!-- This content limit provider is used above (and can also be overriden, eg. by modules). -->
|
||||||
<bean id="defaultContentLimitProvider" class="org.alfresco.repo.content.ContentLimitProvider$SimpleFixedLimitProvider">
|
<bean id="defaultContentLimitProvider" class="org.alfresco.repo.content.ContentLimitProvider$SimpleFixedLimitProvider">
|
||||||
<property name="sizeLimitString" value="${system.content.maximumFileSizeLimit}"/>
|
<property name="sizeLimitString" value="${system.content.maximumFileSizeLimit}"/>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ dir.root=./alf_data
|
|||||||
|
|
||||||
dir.contentstore=${dir.root}/contentstore
|
dir.contentstore=${dir.root}/contentstore
|
||||||
dir.contentstore.deleted=${dir.root}/contentstore.deleted
|
dir.contentstore.deleted=${dir.root}/contentstore.deleted
|
||||||
|
dir.contentstore.bucketsPerMinute=0
|
||||||
|
|
||||||
# ContentStore subsystem: default choice
|
# ContentStore subsystem: default choice
|
||||||
filecontentstore.subsystem.name=unencryptedContentStore
|
filecontentstore.subsystem.name=unencryptedContentStore
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<bean id="fileContentStore" class="org.alfresco.repo.tenant.TenantRoutingFileContentStore" parent="baseTenantRoutingContentStore">
|
<bean id="fileContentStore" class="org.alfresco.repo.tenant.TenantRoutingFileContentStore" parent="baseTenantRoutingContentStore">
|
||||||
<property name="rootLocation" value="${dir.contentstore}" />
|
<property name="rootLocation" value="${dir.contentstore}" />
|
||||||
<property name="contentLimitProvider" ref="defaultContentLimitProvider" />
|
<property name="contentLimitProvider" ref="defaultContentLimitProvider" />
|
||||||
|
<property name="fileContentUrlProvider" ref="defaultFileContentUrlProvider"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
|||||||
@@ -42,13 +42,12 @@ import org.alfresco.repo.content.ContentStoreCreatedEvent;
|
|||||||
import org.alfresco.repo.content.EmptyContentReader;
|
import org.alfresco.repo.content.EmptyContentReader;
|
||||||
import org.alfresco.repo.content.UnsupportedContentUrlException;
|
import org.alfresco.repo.content.UnsupportedContentUrlException;
|
||||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
import org.alfresco.util.Deleter;
|
import org.alfresco.util.Deleter;
|
||||||
import org.alfresco.util.GUID;
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.util.Pair;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
@@ -91,6 +90,7 @@ public class FileContentStore
|
|||||||
private boolean readOnly;
|
private boolean readOnly;
|
||||||
private ApplicationContext applicationContext;
|
private ApplicationContext applicationContext;
|
||||||
private boolean deleteEmptyDirs = true;
|
private boolean deleteEmptyDirs = true;
|
||||||
|
private FileContentUrlProvider fileContentUrlProvider = new TimeBasedFileContentUrlProvider();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private: for Spring-constructed instances only.
|
* Private: for Spring-constructed instances only.
|
||||||
@@ -207,6 +207,10 @@ public class FileContentStore
|
|||||||
{
|
{
|
||||||
this.readOnly = readOnly;
|
this.readOnly = readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFileContentUrlProvider(FileContentUrlProvider fileContentUrlProvider) {
|
||||||
|
this.fileContentUrlProvider = fileContentUrlProvider;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new URL and file appropriate to it.
|
* Generates a new URL and file appropriate to it.
|
||||||
@@ -216,7 +220,7 @@ public class FileContentStore
|
|||||||
*/
|
*/
|
||||||
/*package*/ File createNewFile() throws IOException
|
/*package*/ File createNewFile() throws IOException
|
||||||
{
|
{
|
||||||
String contentUrl = FileContentStore.createNewFileStoreUrl();
|
String contentUrl = fileContentUrlProvider.createNewFileStoreUrl();
|
||||||
return createNewFile(contentUrl);
|
return createNewFile(contentUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,25 +591,7 @@ public class FileContentStore
|
|||||||
*/
|
*/
|
||||||
public static String createNewFileStoreUrl()
|
public static String createNewFileStoreUrl()
|
||||||
{
|
{
|
||||||
Calendar calendar = new GregorianCalendar();
|
return TimeBasedFileContentUrlProvider.createNewFileStoreUrl(0);
|
||||||
int year = calendar.get(Calendar.YEAR);
|
|
||||||
int month = calendar.get(Calendar.MONTH) + 1; // 0-based
|
|
||||||
int day = calendar.get(Calendar.DAY_OF_MONTH);
|
|
||||||
int hour = calendar.get(Calendar.HOUR_OF_DAY);
|
|
||||||
int minute = calendar.get(Calendar.MINUTE);
|
|
||||||
// create the URL
|
|
||||||
StringBuilder sb = new StringBuilder(20);
|
|
||||||
sb.append(FileContentStore.STORE_PROTOCOL)
|
|
||||||
.append(ContentStore.PROTOCOL_DELIMITER)
|
|
||||||
.append(year).append('/')
|
|
||||||
.append(month).append('/')
|
|
||||||
.append(day).append('/')
|
|
||||||
.append(hour).append('/')
|
|
||||||
.append(minute).append('/')
|
|
||||||
.append(GUID.generate()).append(".bin");
|
|
||||||
String newContentUrl = sb.toString();
|
|
||||||
// done
|
|
||||||
return newContentUrl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 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 <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.content.filestore;
|
||||||
|
|
||||||
|
import org.alfresco.api.AlfrescoPublicApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider API for file content store URL implementations
|
||||||
|
* @author Andreea Dragoi
|
||||||
|
*/
|
||||||
|
@AlfrescoPublicApi
|
||||||
|
public interface FileContentUrlProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Content URLs must consist of a prefix or protocol followed by an implementation-specific identifier
|
||||||
|
* @return file content store URL
|
||||||
|
*/
|
||||||
|
public String createNewFileStoreUrl();
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 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 <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.content.filestore;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
import org.alfresco.repo.content.ContentStore;
|
||||||
|
import org.alfresco.util.GUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default Content URL provider for file stores.
|
||||||
|
* Content URL format is <b>store://year/month/day/hour/minute/GUID.bin</b>,
|
||||||
|
* but can be configured to include provision for splitting data into
|
||||||
|
* buckets within <b>minute</b> range through bucketsPerMinute property :
|
||||||
|
* <b>store://year/month/day/hour/minute/bucket/GUID.bin</b> <br>
|
||||||
|
* <ul>
|
||||||
|
* <li> <b>store://</b>: prefix identifying an Alfresco content stores
|
||||||
|
* regardless of the persistence mechanism. </li>
|
||||||
|
* <li> <b>year</b>: year </li>
|
||||||
|
* <li> <b>month</b>: 1-based month of the year </li>
|
||||||
|
* <li> <b>day</b>: 1-based day of the month </li>
|
||||||
|
* <li> <b>hour</b>: 0-based hour of the day </li>
|
||||||
|
* <li> <b>minute</b>: 0-based minute of the hour </li>
|
||||||
|
* <li> <b>bucket</b>: 0-based bucket depending second of minute </li>
|
||||||
|
* <li> <b>GUID</b>: A unique identifier </li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* @author Andreea Dragoi
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TimeBasedFileContentUrlProvider implements FileContentUrlProvider
|
||||||
|
{
|
||||||
|
protected int bucketsPerMinute = 0;
|
||||||
|
|
||||||
|
public void setBucketsPerMinute(int bucketsPerMinute)
|
||||||
|
{
|
||||||
|
this.bucketsPerMinute = bucketsPerMinute;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String createNewFileStoreUrl()
|
||||||
|
{
|
||||||
|
return createNewFileStoreUrl(bucketsPerMinute);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String createTimeBasedPath(int bucketsPerMinute){
|
||||||
|
Calendar calendar = new GregorianCalendar();
|
||||||
|
int year = calendar.get(Calendar.YEAR);
|
||||||
|
int month = calendar.get(Calendar.MONTH) + 1; // 0-based
|
||||||
|
int day = calendar.get(Calendar.DAY_OF_MONTH);
|
||||||
|
int hour = calendar.get(Calendar.HOUR_OF_DAY);
|
||||||
|
int minute = calendar.get(Calendar.MINUTE);
|
||||||
|
// create the URL
|
||||||
|
StringBuilder sb = new StringBuilder(20);
|
||||||
|
sb.append(year).append('/')
|
||||||
|
.append(month).append('/')
|
||||||
|
.append(day).append('/')
|
||||||
|
.append(hour).append('/')
|
||||||
|
.append(minute).append('/');
|
||||||
|
|
||||||
|
if (bucketsPerMinute != 0)
|
||||||
|
{
|
||||||
|
long seconds = System.currentTimeMillis() % (60 * 1000);
|
||||||
|
int actualBucket = (int) seconds / ((60 * 1000) / bucketsPerMinute);
|
||||||
|
sb.append(actualBucket).append('/');
|
||||||
|
}
|
||||||
|
//done
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String createNewFileStoreUrl(int minuteBucketCount)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder(20);
|
||||||
|
sb.append(FileContentStore.STORE_PROTOCOL);
|
||||||
|
sb.append(ContentStore.PROTOCOL_DELIMITER);
|
||||||
|
sb.append(createTimeBasedPath(minuteBucketCount));
|
||||||
|
sb.append(GUID.generate()).append(".bin");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 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 <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.content.filestore;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.alfresco.repo.content.ContentStore;
|
||||||
|
import org.alfresco.util.GUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content URL provider for file stores which allows routing content from a store to a selection of filesystem volumes.
|
||||||
|
* Content is randomly distributed on configured volumes.
|
||||||
|
* Content URL format is <b>store://volume/year/month/day/hour/minute/GUID.bin</b>,
|
||||||
|
* As {@link TimeBasedFileContentUrlProvider TimeBasedFileContentUrlProvider} can be configured to include provision for
|
||||||
|
* splitting data into buckets within <b>minute</b> range
|
||||||
|
* @author Andreea Dragoi
|
||||||
|
*/
|
||||||
|
class VolumeAwareContentUrlProvider extends TimeBasedFileContentUrlProvider
|
||||||
|
{
|
||||||
|
private String[] volumes;
|
||||||
|
private Random random = new Random();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param volumeNames(name of volumes separated by comma)
|
||||||
|
*/
|
||||||
|
public VolumeAwareContentUrlProvider(String volumeNames)
|
||||||
|
{
|
||||||
|
if (volumeNames == null || volumeNames.isEmpty())
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Invalid volumeNames argument");
|
||||||
|
}
|
||||||
|
this.volumes = volumeNames.split(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String createNewFileStoreUrl()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder(20);
|
||||||
|
sb.append(FileContentStore.STORE_PROTOCOL)
|
||||||
|
.append(ContentStore.PROTOCOL_DELIMITER)
|
||||||
|
.append(chooseVolume()).append("/")
|
||||||
|
.append(TimeBasedFileContentUrlProvider.createTimeBasedPath(bucketsPerMinute))
|
||||||
|
.append(GUID.generate()).append(".bin");
|
||||||
|
String newContentUrl = sb.toString();
|
||||||
|
return newContentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String chooseVolume()
|
||||||
|
{
|
||||||
|
int volumesNum = volumes.length;
|
||||||
|
return volumes[random.nextInt(volumesNum)];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -33,7 +33,8 @@ import java.util.Map;
|
|||||||
import org.alfresco.repo.content.ContentLimitProvider;
|
import org.alfresco.repo.content.ContentLimitProvider;
|
||||||
import org.alfresco.repo.content.ContentLimitProvider.NoLimitProvider;
|
import org.alfresco.repo.content.ContentLimitProvider.NoLimitProvider;
|
||||||
import org.alfresco.repo.content.ContentStore;
|
import org.alfresco.repo.content.ContentStore;
|
||||||
import org.alfresco.repo.content.filestore.FileContentStore;
|
import org.alfresco.repo.content.filestore.FileContentStore;
|
||||||
|
import org.alfresco.repo.content.filestore.FileContentUrlProvider;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,7 +42,8 @@ import org.springframework.context.ApplicationContext;
|
|||||||
*/
|
*/
|
||||||
public class TenantRoutingFileContentStore extends AbstractTenantRoutingContentStore
|
public class TenantRoutingFileContentStore extends AbstractTenantRoutingContentStore
|
||||||
{
|
{
|
||||||
private ContentLimitProvider contentLimitProvider = new NoLimitProvider();
|
private ContentLimitProvider contentLimitProvider = new NoLimitProvider();
|
||||||
|
private FileContentUrlProvider fileContentUrlProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a new {@link ContentLimitProvider} which will provide a maximum filesize for content.
|
* Sets a new {@link ContentLimitProvider} which will provide a maximum filesize for content.
|
||||||
@@ -49,6 +51,14 @@ public class TenantRoutingFileContentStore extends AbstractTenantRoutingContentS
|
|||||||
public void setContentLimitProvider(ContentLimitProvider contentLimitProvider)
|
public void setContentLimitProvider(ContentLimitProvider contentLimitProvider)
|
||||||
{
|
{
|
||||||
this.contentLimitProvider = contentLimitProvider;
|
this.contentLimitProvider = contentLimitProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a new {@link FileContentUrlProvider} which will build the content url.
|
||||||
|
*/
|
||||||
|
public void setFileContentUrlProvider(FileContentUrlProvider fileContentUrlProvider)
|
||||||
|
{
|
||||||
|
this.fileContentUrlProvider = fileContentUrlProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ContentStore initContentStore(ApplicationContext ctx, String contentRoot)
|
protected ContentStore initContentStore(ApplicationContext ctx, String contentRoot)
|
||||||
@@ -66,7 +76,11 @@ public class TenantRoutingFileContentStore extends AbstractTenantRoutingContentS
|
|||||||
{
|
{
|
||||||
fileContentStore.setContentLimitProvider(contentLimitProvider);
|
fileContentStore.setContentLimitProvider(contentLimitProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(fileContentUrlProvider != null)
|
||||||
|
{
|
||||||
|
fileContentStore.setFileContentUrlProvider(fileContentUrlProvider);
|
||||||
|
}
|
||||||
return fileContentStore;
|
return fileContentStore;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited./*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 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 <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.content.filestore;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.alfresco.test_category.OwnJVMTestsCategory;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.experimental.categories.Category;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link FileContentStore FileContentStore} which uses
|
||||||
|
* {@link TimeBasedFileContentUrlProvider TimeBasedFileContentUrlProvider}
|
||||||
|
* configured for provisioning splitting data into buckets within the
|
||||||
|
* <b>minute</b> range
|
||||||
|
*
|
||||||
|
* @author Andreea Dragoi
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Category(OwnJVMTestsCategory.class)
|
||||||
|
public class BucketAwareFileContentStoreTest extends FileContentStoreTest
|
||||||
|
{
|
||||||
|
private static final int BUCKETS_PER_MINUTE = 20;
|
||||||
|
private static final int ITERATIONS = 5;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() throws Exception
|
||||||
|
{
|
||||||
|
super.before();
|
||||||
|
|
||||||
|
TimeBasedFileContentUrlProvider fileContentUrlProvider = new TimeBasedFileContentUrlProvider();
|
||||||
|
// configure url provider to create buckets on minute range on a
|
||||||
|
// interval of 3 seconds (60/MINUTE_BUCKET_COUNT)
|
||||||
|
fileContentUrlProvider.setBucketsPerMinute(BUCKETS_PER_MINUTE);
|
||||||
|
store.setFileContentUrlProvider(fileContentUrlProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBucketCreation() throws Exception
|
||||||
|
{
|
||||||
|
// create several files in a interval of ~15 seconds
|
||||||
|
// depending when the test is started files can be created on same
|
||||||
|
// minute or not
|
||||||
|
File firstFile = store.createNewFile();
|
||||||
|
for (int i = 0; i < ITERATIONS; i++)
|
||||||
|
{
|
||||||
|
store.createNewFile();
|
||||||
|
Thread.sleep(3000);
|
||||||
|
}
|
||||||
|
File lastFile = store.createNewFile();
|
||||||
|
|
||||||
|
// check the minute for first and last file created
|
||||||
|
File firstFileMinute = firstFile.getParentFile().getParentFile();
|
||||||
|
File lastFileMinute = lastFile.getParentFile().getParentFile();
|
||||||
|
|
||||||
|
int createdBuckets;
|
||||||
|
int firstFileMinuteBuckets = firstFileMinute.list().length;
|
||||||
|
|
||||||
|
if (!firstFileMinute.equals(lastFileMinute))
|
||||||
|
{
|
||||||
|
// files are created in different minutes
|
||||||
|
int lastFileMinutesBuckets = lastFileMinute.list().length;
|
||||||
|
createdBuckets = firstFileMinuteBuckets + lastFileMinutesBuckets;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// files are created on same minute
|
||||||
|
createdBuckets = firstFileMinuteBuckets;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interval of 15s + time for file creation, expecting (ITERATIONS + 1)
|
||||||
|
// buckets
|
||||||
|
assertTrue("Unexpected number of buckets created", createdBuckets == ITERATIONS + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -28,7 +28,7 @@ package org.alfresco.repo.content.filestore;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.alfresco.repo.content.AbstractWritableContentStoreTest;
|
import org.alfresco.repo.content.AbstractWritableContentStoreTest;
|
||||||
import org.alfresco.repo.content.ContentContext;
|
import org.alfresco.repo.content.ContentContext;
|
||||||
import org.alfresco.repo.content.ContentExistsException;
|
import org.alfresco.repo.content.ContentExistsException;
|
||||||
@@ -45,7 +45,7 @@ import org.junit.After;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.experimental.categories.Category;
|
import org.junit.experimental.categories.Category;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
@@ -62,7 +62,7 @@ import static org.junit.Assert.fail;
|
|||||||
@Category(OwnJVMTestsCategory.class)
|
@Category(OwnJVMTestsCategory.class)
|
||||||
public class FileContentStoreTest extends AbstractWritableContentStoreTest
|
public class FileContentStoreTest extends AbstractWritableContentStoreTest
|
||||||
{
|
{
|
||||||
private FileContentStore store;
|
protected FileContentStore store;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() throws Exception
|
public void before() throws Exception
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 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 <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.content.filestore;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.alfresco.test_category.OwnJVMTestsCategory;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.experimental.categories.Category;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link FileContentStore} that uses {@link VolumeAwareContentUrlProvider}
|
||||||
|
* to route content from a store to a selection of filesystem volumes
|
||||||
|
* @author Andreea Dragoi
|
||||||
|
*/
|
||||||
|
@Category(OwnJVMTestsCategory.class)
|
||||||
|
public class VolumeAwareFileContentStoreTest extends FileContentStoreTest{
|
||||||
|
|
||||||
|
private static final String VOLUMES = "volumeA,volumeB,volumeC";
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() throws Exception
|
||||||
|
{
|
||||||
|
super.before();
|
||||||
|
|
||||||
|
VolumeAwareContentUrlProvider volumeAwareContentUrlProvider = new VolumeAwareContentUrlProvider(VOLUMES);
|
||||||
|
store.setFileContentUrlProvider(volumeAwareContentUrlProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVolumeCreation() throws IOException
|
||||||
|
{
|
||||||
|
int volumesNumber = VOLUMES.split(",").length;
|
||||||
|
// create several files
|
||||||
|
for (int i = 0; i < volumesNumber * 5 ; i++)
|
||||||
|
{
|
||||||
|
store.createNewFile();
|
||||||
|
}
|
||||||
|
File root = new File(store.getRootLocation());
|
||||||
|
String[] folders = root.list();
|
||||||
|
// check if root folders contains configured volumes
|
||||||
|
for (String file : folders)
|
||||||
|
{
|
||||||
|
assertTrue("Unknown volume", VOLUMES.contains(file));
|
||||||
|
}
|
||||||
|
assertTrue("Not all configured volumes were created", folders.length == volumesNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user