diff --git a/source/java/org/alfresco/repo/content/filestore/FileContentStore.java b/source/java/org/alfresco/repo/content/filestore/FileContentStore.java index 4a3d045650..a4521947c6 100644 --- a/source/java/org/alfresco/repo/content/filestore/FileContentStore.java +++ b/source/java/org/alfresco/repo/content/filestore/FileContentStore.java @@ -21,8 +21,10 @@ package org.alfresco.repo.content.filestore; import java.io.File; import java.io.IOException; import java.io.Serializable; +import java.util.Calendar; import java.util.Collections; import java.util.Date; +import java.util.GregorianCalendar; import java.util.Map; import org.alfresco.api.AlfrescoPublicApi; @@ -37,6 +39,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.util.Deleter; +import org.alfresco.util.GUID; import org.alfresco.util.Pair; import org.apache.commons.io.FilenameUtils; import org.apache.commons.logging.Log; @@ -82,7 +85,6 @@ public class FileContentStore private boolean readOnly; private ApplicationContext applicationContext; private boolean deleteEmptyDirs = true; - private FileContentUrlProvider fileContentUrlProvider = new TimeBasedFileContentUrlProvider(); /** * Private: for Spring-constructed instances only. @@ -199,10 +201,6 @@ public class FileContentStore { this.readOnly = readOnly; } - - public void setFileContentUrlProvider(FileContentUrlProvider fileContentUrlProvider) { - this.fileContentUrlProvider = fileContentUrlProvider; - } /** * Generates a new URL and file appropriate to it. @@ -212,7 +210,7 @@ public class FileContentStore */ /*package*/ File createNewFile() throws IOException { - String contentUrl = fileContentUrlProvider.createNewFileStoreUrl(); + String contentUrl = FileContentStore.createNewFileStoreUrl(); return createNewFile(contentUrl); } @@ -648,13 +646,28 @@ public class FileContentStore * stores that are compatible with Alfresco. * * @return Returns a new and unique content URL - * - * @deprecated New file store URLs are now generated using {@link FileContentUrlProvider}. - * In org.alfresco.repo.content.filestore package use {@link TimeBasedFileContentUrlProvider} */ public static String createNewFileStoreUrl() { - return TimeBasedFileContentUrlProvider.createNewFileStoreUrl(0); + 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(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; } /** diff --git a/source/java/org/alfresco/repo/content/filestore/FileContentUrlProvider.java b/source/java/org/alfresco/repo/content/filestore/FileContentUrlProvider.java deleted file mode 100644 index 48b240c44f..0000000000 --- a/source/java/org/alfresco/repo/content/filestore/FileContentUrlProvider.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2005-2016 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * 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 . - */ - -package org.alfresco.repo.content.filestore; - -/** - * Provider API for file content store URL implementations - * @author Andreea Dragoi - * @since 5.1 - */ -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(); -} diff --git a/source/java/org/alfresco/repo/content/filestore/TimeBasedFileContentUrlProvider.java b/source/java/org/alfresco/repo/content/filestore/TimeBasedFileContentUrlProvider.java deleted file mode 100644 index 586592499d..0000000000 --- a/source/java/org/alfresco/repo/content/filestore/TimeBasedFileContentUrlProvider.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2005-2016 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * 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 . - */ - -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 store://year/month/day/hour/minute/GUID.bin, - * but can be configured to include provision for splitting data into - * buckets within minute range through minuteBucketCount property : - * store://year/month/day/hour/minute/bucket/GUID.bin
- * - *

- * @author Andreea Dragoi - * @since 5.1 - */ - -class TimeBasedFileContentUrlProvider implements FileContentUrlProvider -{ - protected int minuteBucketCount = 0; - - public void setMinuteBucketCount(int minuteBucketCount) - { - this.minuteBucketCount = minuteBucketCount; - } - - @Override - public String createNewFileStoreUrl() - { - return createNewFileStoreUrl(minuteBucketCount); - } - - public static String createTimeBasedPath(int minuteBucketCount){ - 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 (minuteBucketCount != 0) - { - long seconds = System.currentTimeMillis() % (60 * 1000); - int actualBucket = (int) seconds / ((60 * 1000) / minuteBucketCount); - 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(); - } -} diff --git a/source/java/org/alfresco/repo/content/filestore/VolumeAwareContentUrlProvider.java b/source/java/org/alfresco/repo/content/filestore/VolumeAwareContentUrlProvider.java deleted file mode 100644 index 528d5f32d8..0000000000 --- a/source/java/org/alfresco/repo/content/filestore/VolumeAwareContentUrlProvider.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2005-2016 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * 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 . - */ - -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 store://volume/year/month/day/hour/minute/GUID.bin, - * As {@link TimeBasedFileContentUrlProvider TimeBasedFileContentUrlProvider} can be configured to include provision for - * splitting data into buckets within minute range - * @author Andreea Dragoi - * @since 5.1 - */ -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(minuteBucketCount)) - .append(GUID.generate()).append(".bin"); - String newContentUrl = sb.toString(); - return newContentUrl; - } - - private String chooseVolume() - { - int volumesNum = volumes.length; - return volumes[random.nextInt(volumesNum)]; - } - -} diff --git a/source/test-java/org/alfresco/repo/content/filestore/BucketAwareFileContentStoreTest.java b/source/test-java/org/alfresco/repo/content/filestore/BucketAwareFileContentStoreTest.java deleted file mode 100644 index aa4f3b0cfc..0000000000 --- a/source/test-java/org/alfresco/repo/content/filestore/BucketAwareFileContentStoreTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * 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 . - */ - -/** - * Tests bucket provisioning for FileContentStore - * - * @author Andreeea Dragoi - * @since 5.1 - */ -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 minute range - * @author Andreea Dragoi - * @since 5.1 - * - */ -@Category(OwnJVMTestsCategory.class) -public class BucketAwareFileContentStoreTest extends FileContentStoreTest -{ - private static final int MINUTE_BUCKET_COUNT = 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.setMinuteBucketCount(MINUTE_BUCKET_COUNT); - 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); - } - -} diff --git a/source/test-java/org/alfresco/repo/content/filestore/FileContentStoreTest.java b/source/test-java/org/alfresco/repo/content/filestore/FileContentStoreTest.java index 47f19d85e2..e0908ab4d2 100644 --- a/source/test-java/org/alfresco/repo/content/filestore/FileContentStoreTest.java +++ b/source/test-java/org/alfresco/repo/content/filestore/FileContentStoreTest.java @@ -55,7 +55,7 @@ import static org.junit.Assert.fail; @Category(OwnJVMTestsCategory.class) public class FileContentStoreTest extends AbstractWritableContentStoreTest { - protected FileContentStore store; + private FileContentStore store; @Before public void before() throws Exception diff --git a/source/test-java/org/alfresco/repo/content/filestore/VolumeAwareFileContentStoreTest.java b/source/test-java/org/alfresco/repo/content/filestore/VolumeAwareFileContentStoreTest.java deleted file mode 100644 index d0983145bb..0000000000 --- a/source/test-java/org/alfresco/repo/content/filestore/VolumeAwareFileContentStoreTest.java +++ /dev/null @@ -1,50 +0,0 @@ -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 - * @since 5.1 - */ -@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); - } -}