mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-07 18:25:23 +00:00
- MOB-30: Content Purge - MOB-415: Content Properties Refactor - Adds to MOB-214: Upgrade scripts for Ent DBs git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@14810 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
304 lines
12 KiB
Java
304 lines
12 KiB
Java
/*
|
|
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
* As a special exception to the terms and conditions of version 2.0 of
|
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
|
* FLOSS exception. You should have recieved a copy of the text describing
|
|
* the FLOSS exception, and it is also available here:
|
|
* http://www.alfresco.com/legal/licensing"
|
|
*/
|
|
package org.alfresco.repo.domain.contentdata;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
|
|
import junit.framework.TestCase;
|
|
|
|
import org.alfresco.repo.content.ContentContext;
|
|
import org.alfresco.repo.content.ContentStore;
|
|
import org.alfresco.repo.content.MimetypeMap;
|
|
import org.alfresco.repo.content.filestore.FileContentStore;
|
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
|
import org.alfresco.service.ServiceRegistry;
|
|
import org.alfresco.service.cmr.repository.ContentData;
|
|
import org.alfresco.service.transaction.TransactionService;
|
|
import org.alfresco.util.ApplicationContextHelper;
|
|
import org.alfresco.util.Pair;
|
|
import org.alfresco.util.TempFileProvider;
|
|
import org.springframework.context.ConfigurableApplicationContext;
|
|
|
|
/**
|
|
* @see ContentDataDAO
|
|
*
|
|
* @author Derek Hulley
|
|
* @since 3.2
|
|
*/
|
|
public class ContentDataDAOTest extends TestCase
|
|
{
|
|
private ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) ApplicationContextHelper.getApplicationContext();
|
|
|
|
private TransactionService transactionService;
|
|
private RetryingTransactionHelper txnHelper;
|
|
private ContentDataDAO contentDataDAO;
|
|
private ContentStore contentStore;
|
|
|
|
@Override
|
|
public void setUp() throws Exception
|
|
{
|
|
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
|
transactionService = serviceRegistry.getTransactionService();
|
|
txnHelper = transactionService.getRetryingTransactionHelper();
|
|
|
|
contentDataDAO = (ContentDataDAO) ctx.getBean("contentDataDAO");
|
|
contentStore = new FileContentStore(ctx, TempFileProvider.getTempDir());
|
|
}
|
|
|
|
private Pair<Long, ContentData> create(final ContentData contentData)
|
|
{
|
|
RetryingTransactionCallback<Pair<Long, ContentData>> callback = new RetryingTransactionCallback<Pair<Long, ContentData>>()
|
|
{
|
|
public Pair<Long, ContentData> execute() throws Throwable
|
|
{
|
|
Pair<Long, ContentData> contentDataPair = contentDataDAO.createContentData(contentData);
|
|
return contentDataPair;
|
|
}
|
|
};
|
|
return txnHelper.doInTransaction(callback, false, false);
|
|
}
|
|
|
|
/**
|
|
* Retrieves and checks the ContentData for equality
|
|
*/
|
|
private void getAndCheck(final Long contentDataId, ContentData checkContentData)
|
|
{
|
|
RetryingTransactionCallback<Pair<Long, ContentData>> callback = new RetryingTransactionCallback<Pair<Long, ContentData>>()
|
|
{
|
|
public Pair<Long, ContentData> execute() throws Throwable
|
|
{
|
|
Pair<Long, ContentData> contentDataPair = contentDataDAO.getContentData(contentDataId);
|
|
return contentDataPair;
|
|
}
|
|
};
|
|
Pair<Long, ContentData> resultPair = txnHelper.doInTransaction(callback, true, false);
|
|
assertNotNull("Failed to find result for ID " + contentDataId, resultPair);
|
|
assertEquals("ContentData retrieved not the same as persisted: ", checkContentData, resultPair.getSecond());
|
|
}
|
|
|
|
private ContentData getContentData()
|
|
{
|
|
ContentContext contentCtx = new ContentContext(null, null);
|
|
String contentUrl = contentStore.getWriter(contentCtx).getContentUrl();
|
|
ContentData contentData = new ContentData(
|
|
contentUrl,
|
|
MimetypeMap.MIMETYPE_TEXT_PLAIN,
|
|
12335L,
|
|
"UTF-8",
|
|
Locale.FRENCH);
|
|
return contentData;
|
|
}
|
|
|
|
public void testGetWithInvalidId()
|
|
{
|
|
assertNull("Expected null for invalid ID", contentDataDAO.getContentData(-1L));
|
|
}
|
|
|
|
/**
|
|
* Check that the <code>ContentData</code> is decoded and persisted correctly.
|
|
*/
|
|
public void testCreateContentDataSimple() throws Exception
|
|
{
|
|
ContentData contentData = getContentData();
|
|
|
|
Pair<Long, ContentData> resultPair = create(contentData);
|
|
getAndCheck(resultPair.getFirst(), contentData);
|
|
}
|
|
|
|
/**
|
|
* Check that the <code>ContentData</code> is decoded and persisted correctly.
|
|
*/
|
|
public void testCreateContentDataNulls() throws Exception
|
|
{
|
|
ContentData contentData = new ContentData(null, null, 0L, null, null);
|
|
|
|
Pair<Long, ContentData> resultPair = create(contentData);
|
|
getAndCheck(resultPair.getFirst(), contentData);
|
|
}
|
|
|
|
/**
|
|
* Ensure that upper and lowercase URLs don't clash
|
|
* @throws Exception
|
|
*/
|
|
public void testEnsureCaseSensitiveStorage() throws Exception
|
|
{
|
|
ContentData contentData = getContentData();
|
|
String contentUrlUpper = contentData.getContentUrl().toUpperCase();
|
|
ContentData contentDataUpper = new ContentData(
|
|
contentUrlUpper, MimetypeMap.MIMETYPE_TEXT_PLAIN, 0L, "UTF-8", new Locale("FR"));
|
|
String contentUrlLower = contentData.getContentUrl().toLowerCase();
|
|
ContentData contentDataLower = new ContentData(
|
|
contentUrlLower, MimetypeMap.MIMETYPE_TEXT_PLAIN, 0L, "utf-8", new Locale("fr"));
|
|
|
|
Pair<Long, ContentData> resultPairUpper = create(contentDataUpper);
|
|
getAndCheck(resultPairUpper.getFirst(), contentDataUpper);
|
|
|
|
Pair<Long, ContentData> resultPairLower = create(contentDataLower);
|
|
getAndCheck(resultPairLower.getFirst(), contentDataLower);
|
|
}
|
|
|
|
public void testDelete() throws Exception
|
|
{
|
|
ContentData contentData = getContentData();
|
|
|
|
Pair<Long, ContentData> resultPair = create(contentData);
|
|
getAndCheck(resultPair.getFirst(), contentData);
|
|
contentDataDAO.deleteContentData(resultPair.getFirst());
|
|
try
|
|
{
|
|
getAndCheck(resultPair.getFirst(), contentData);
|
|
fail("Entity still exists");
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
// Expected
|
|
}
|
|
}
|
|
|
|
private static final String[] MIMETYPES = new String[]
|
|
{
|
|
MimetypeMap.MIMETYPE_ACP,
|
|
MimetypeMap.MIMETYPE_EXCEL,
|
|
MimetypeMap.MIMETYPE_IMAGE_JPEG,
|
|
MimetypeMap.MIMETYPE_JAVASCRIPT,
|
|
MimetypeMap.MIMETYPE_RSS
|
|
};
|
|
private static final String[] ENCODINGS = new String[]
|
|
{
|
|
"utf-8",
|
|
"ascii",
|
|
"latin1",
|
|
"wibbles",
|
|
"iso-whatever"
|
|
};
|
|
private static final Locale[] LOCALES = new Locale[]
|
|
{
|
|
Locale.FRENCH,
|
|
Locale.CHINESE,
|
|
Locale.ITALIAN,
|
|
Locale.JAPANESE,
|
|
Locale.ENGLISH
|
|
};
|
|
|
|
private List<Pair<Long, ContentData>> speedTestWrite(String name, int total)
|
|
{
|
|
System.out.println("Starting write speed test: " + name);
|
|
long start = System.nanoTime();
|
|
List<Pair<Long, ContentData>> pairs = new ArrayList<Pair<Long, ContentData>>(100000);
|
|
// Loop and check for performance degradation
|
|
for (int i = 0; i < (total / 200 / 5); i++)
|
|
{
|
|
for (int j = 0; j < 200; j++)
|
|
{
|
|
for (int k = 0; k < 5; k++)
|
|
{
|
|
ContentData contentData = getContentData();
|
|
String contentUrl = contentData.getContentUrl();
|
|
contentData = new ContentData(
|
|
contentUrl,
|
|
MIMETYPES[k],
|
|
(long) j*k,
|
|
ENCODINGS[k],
|
|
LOCALES[k]);
|
|
Pair<Long, ContentData> pair = create(contentData);
|
|
pairs.add(pair);
|
|
}
|
|
}
|
|
// That's 1000
|
|
long now = System.nanoTime();
|
|
double diffMs = (double) (now - start) / 1E6;
|
|
double aveMs = diffMs / (double) pairs.size();
|
|
String msg = String.format(
|
|
" Wrote %7d rows; average is %5.2f ms per row or %5.2f rows per second",
|
|
pairs.size(),
|
|
aveMs,
|
|
1000.0 / aveMs);
|
|
System.out.println(msg);
|
|
}
|
|
// Done
|
|
return pairs;
|
|
}
|
|
|
|
private void speedTestRead(String name, List<Pair<Long, ContentData>> pairs)
|
|
{
|
|
System.out.println("Starting read speed test: " + name);
|
|
long start = System.nanoTime();
|
|
// Loop and check for performance degradation
|
|
int num = 1;
|
|
for (Pair<Long, ContentData> pair : pairs)
|
|
{
|
|
Long id = pair.getFirst();
|
|
ContentData contentData = pair.getSecond();
|
|
// Retrieve it
|
|
getAndCheck(id, contentData);
|
|
// Report
|
|
if (num % 1000 == 0)
|
|
{
|
|
long now = System.nanoTime();
|
|
double diffMs = (double) (now - start) / 1E6;
|
|
double aveMs = diffMs / (double) num;
|
|
String msg = String.format(
|
|
" Read %7d rows; average is %5.2f ms per row or %5.2f rows per second",
|
|
num,
|
|
aveMs,
|
|
1000.0 / aveMs);
|
|
System.out.println(msg);
|
|
}
|
|
num++;
|
|
}
|
|
// Done
|
|
}
|
|
|
|
public void testCreateSpeedIndividualTxns()
|
|
{
|
|
List<Pair<Long, ContentData>> pairs = speedTestWrite(getName(), 2000);
|
|
speedTestRead(getName(), pairs);
|
|
}
|
|
|
|
public void testCreateSpeedSingleTxn()
|
|
{
|
|
RetryingTransactionCallback<List<Pair<Long, ContentData>>> writeCallback = new RetryingTransactionCallback<List<Pair<Long, ContentData>>>()
|
|
{
|
|
public List<Pair<Long, ContentData>> execute() throws Throwable
|
|
{
|
|
return speedTestWrite(getName(), 10000);
|
|
}
|
|
};
|
|
final List<Pair<Long, ContentData>> pairs = txnHelper.doInTransaction(writeCallback, false, false);
|
|
RetryingTransactionCallback<Void> readCallback = new RetryingTransactionCallback<Void>()
|
|
{
|
|
public Void execute() throws Throwable
|
|
{
|
|
speedTestRead(getName(), pairs);
|
|
return null;
|
|
}
|
|
};
|
|
txnHelper.doInTransaction(readCallback, false, false);
|
|
}
|
|
}
|