Merged V3.1 to HEAD

13077: Abstracted ContentStore MBean operations
   13099: Merge V3.0 to V3.1
      13096  Merged V2.2 to V3.0
         13071: Fix ETWOTWO-1058: Hibernate exception while concurrently submitting from and updating same user sandbox.
         13079: Fix ETWOTWO-1117: Misleading exceptions reported during AVM flatten and update
   13102: [no comment]
   13112: Merged V3.0 to V3.1
      13111: Merged V2.2 to V3.0
         13110: Fix 2.1 -> 2.2 upgrade on Postgres
   13114: Build/test fix (Enterprise Remote API project does not yet have any Java files to generate Javadoc)
   13117: DM Index Check - unit test improvements
   13123: *RECORD ONLY* Removed svn:mergeinfo fluff
   13124: Used newer, more efficient NodeService.addProperties method instead of many NodeService.setProperty calls
   13125: Added M2Binding for 'child-association': propagateTimestamps'
   13126: WCM unit tests - reduce build/test time to check (async) submits
   13127: Minor test fix - to allow it to run locally (on Mac OS X)
   13130: Support for 'maxRetries' of zero or less
   13131: Merged V3.0 to V3.1
      13025 *RECORD-ONLY*: Removed unnecessary svn:mergeinfo
      13026: Merged V2.2 to V3.0
         12964: Fixed ETWOTWO-968: Space rules are not run when saving from MS Word
         12993 *RECORD-ONLY*: added openoffice bootstrap context to sample-extensions
         13009 *RECORD-ONLY*: Avoid default OOo config from causing problems on zip/gz installs
   13132: Updated svn:mergeinfo
   13134: ETHREEOH-1202 - initial fix and unit tests
   ___________________________________________________________________
   Modified: svn:mergeinfo
      Merged /alfresco/BRANCHES/V3.0:r13005,13025-13026,13030,13039,13042,13050,13053,13096,13098,13111
      Merged /alfresco/BRANCHES/V2.2:r12964,12993,13009,13071,13079,13110
      Merged /alfresco/BRANCHES/V3.1:r13077,13099,13102,13112,13114,13117,13123-13127,13130-13132,13134


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13564 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2009-03-11 13:19:59 +00:00
parent 9d3fd6680d
commit cf86bf466c
46 changed files with 4765 additions and 4028 deletions

View File

@@ -272,4 +272,20 @@ public abstract class AbstractContentStore implements ContentStore
ContentReader reader = getReader(contentUrl);
return reader.exists();
}
/**
* @return Returns <tt>-1</tt> always
*/
public long getTotalSize()
{
return -1L;
}
/**
* {@inheritDoc}
*/
public String getRootLocation()
{
return ".";
}
}

View File

@@ -245,6 +245,22 @@ public abstract class AbstractRoutingContentStore implements ContentStore
return supported;
}
/**
* @return Returns <b>.</b> always
*/
public String getRootLocation()
{
return ".";
}
/**
* @return Returns <tt>-1</tt> always
*/
public long getTotalSize()
{
return -1L;
}
/**
* @see #selectReadStore(String)
*/

View File

@@ -102,6 +102,25 @@ public abstract class AbstractWritableContentStoreTest extends AbstractReadOnlyC
ContentStore store = getStore();
assertTrue("The store cannot be read-only", store.isWriteSupported());
}
/**
* Just check that the method doesn't blow up
*/
public void testTotalSize() throws Exception
{
ContentStore store = getStore();
store.getTotalSize();
}
/**
* Just check that the method doesn't blow up
*/
public void testRootLocation() throws Exception
{
ContentStore store = getStore();
String rootLocation = store.getRootLocation();
assertNotNull("The root location may not be null", rootLocation);
}
/**
* Helper to ensure that illegal content URLs are flagged for <b>getWriter</b> requests

View File

@@ -102,6 +102,28 @@ public interface ContentStore
*/
public boolean isWriteSupported();
/**
* Calculates the total size of content stored.
* <p>
* <b>NOTE:</b> For efficiency, some implementations may provide a guess. If not, this call could
* take a long time.
* <p>
* Implementations should focus on calculating a size value quickly, rather than accurately.
*
* @return
* Returns the total, possibly approximate size (in bytes) of the binary data stored or <tt>-1</tt>
* if no size data is available.
*/
public long getTotalSize();
/**
* Get the location where the store is rooted. The format of the returned value will depend on the
* specific implementation of the store.
*
* @return Returns the store's root location or <b>.</b> if no information is available
*/
public String getRootLocation();
/**
* Check for the existence of content in the store.
* <p>

View File

@@ -22,10 +22,9 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.content.filestore;
import java.io.File;
package org.alfresco.repo.content;
import org.alfresco.repo.content.filestore.FileContentStore;
import org.springframework.context.ApplicationEvent;
/**
@@ -33,14 +32,12 @@ import org.springframework.context.ApplicationEvent;
* purposes.
*
* @author dward
* @since 3.1
*/
public class FileContentStoreCreatedEvent extends ApplicationEvent
public class ContentStoreCreatedEvent extends ApplicationEvent
{
private static final long serialVersionUID = 7090069096441126707L;
/** The root directory of the store. */
private final File rootDirectory;
/**
* The Constructor.
*
@@ -49,19 +46,16 @@ public class FileContentStoreCreatedEvent extends ApplicationEvent
* @param rootDirectory
* the root directory
*/
public FileContentStoreCreatedEvent(FileContentStore source, File rootDirectory)
public ContentStoreCreatedEvent(ContentStore source)
{
super(source);
this.rootDirectory = rootDirectory;
}
/**
* Gets the root directory.
*
* @return the root directory
* @return Returns the source {@link ContentStore}
*/
public File getRootDirectory()
public ContentStore getContentStore()
{
return this.rootDirectory;
return (ContentStore) getSource();
}
}

View File

@@ -200,7 +200,7 @@ public class RoutingContentService implements ContentService, ApplicationContext
Map<QName, Serializable> after)
{
boolean fire = false;
boolean newContent = false;
boolean isNewContent = false;
// check if any of the content properties have changed
for (QName propertyQName : after.keySet())
{
@@ -221,49 +221,39 @@ public class RoutingContentService implements ContentService, ApplicationContext
{
ContentData beforeValue = (ContentData) before.get(propertyQName);
ContentData afterValue = (ContentData) after.get(propertyQName);
if (afterValue != null && afterValue.getContentUrl() == null)
boolean hasContentBefore = ContentData.hasContent(beforeValue);
boolean hasContentAfter = ContentData.hasContent(afterValue);
// There are some shortcuts here
if (!hasContentBefore && !hasContentAfter)
{
// no URL - ignore
// Really, nothing happened
continue;
}
else if (!EqualsHelper.nullSafeEquals(beforeValue, afterValue))
else if (EqualsHelper.nullSafeEquals(beforeValue, afterValue))
{
// So debug ...
if (logger.isDebugEnabled() == true)
{
String beforeString = "";
if (beforeValue != null)
{
beforeString = beforeValue.toString();
}
String afterString = "";
if (afterValue != null)
{
afterString = afterValue.toString();
}
logger.debug("onContentUpate: before = " + beforeString + "; after = " + afterString);
}
// Figure out if the content is new or not
String beforeContentUrl = null;
if (beforeValue != null)
{
beforeContentUrl = beforeValue.getContentUrl();
}
String afterContentUrl = null;
if (afterValue != null)
{
afterContentUrl = afterValue.getContentUrl();
}
if (beforeContentUrl == null && afterContentUrl != null)
{
newContent = true;
}
// the content changed
// at the moment, we are only interested in this one change
fire = true;
break;
// Still, nothing happening
continue;
}
// Check for new content
isNewContent = !hasContentBefore && hasContentAfter;
// So debug ...
if (logger.isDebugEnabled() == true)
{
String name = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
logger.debug(
"onContentUpdate will fire: \n" +
" Name: " + name + "\n" +
" Is new: " + isNewContent + "\n" +
" Before: " + beforeValue + "\n" +
" After: " + afterValue);
}
// We are interested in any content change
fire = true;
break;
}
catch (ClassCastException e)
{
@@ -278,7 +268,7 @@ public class RoutingContentService implements ContentService, ApplicationContext
Set<QName> types = new HashSet<QName>(this.nodeService.getAspects(nodeRef));
types.add(this.nodeService.getType(nodeRef));
OnContentUpdatePolicy policy = this.onContentUpdateDelegate.get(nodeRef, types);
policy.onContentUpdate(nodeRef, newContent);
policy.onContentUpdate(nodeRef, isNewContent);
}
}
@@ -327,10 +317,11 @@ public class RoutingContentService implements ContentService, ApplicationContext
Serializable propValue = nodeService.getProperty(nodeRef, propertyQName);
if (propValue instanceof Collection)
{
Collection colPropValue = (Collection)propValue;
@SuppressWarnings("unchecked")
Collection<Serializable> colPropValue = (Collection<Serializable>)propValue;
if (colPropValue.size() > 0)
{
propValue = (Serializable)colPropValue.iterator().next();
propValue = colPropValue.iterator().next();
}
}

View File

@@ -34,6 +34,7 @@ import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.AbstractContentStore;
import org.alfresco.repo.content.ContentContext;
import org.alfresco.repo.content.ContentStore;
import org.alfresco.repo.content.ContentStoreCreatedEvent;
import org.alfresco.repo.content.EmptyContentReader;
import org.alfresco.repo.content.UnsupportedContentUrlException;
import org.alfresco.service.cmr.repository.ContentIOException;
@@ -352,6 +353,53 @@ public class FileContentStore extends AbstractContentStore implements Applicatio
return file.exists();
}
/**
* Performs a full, deep size calculation
*/
@Override
public long getTotalSize()
{
return calculateDirectorySize(rootDirectory);
}
/**
* Recursive directory size calculation
*/
private long calculateDirectorySize(File dir)
{
int size = 0;
File[] files = dir.listFiles();
for (File file : files)
{
if (file.isDirectory())
{
size += calculateDirectorySize(file);
}
else
{
size += file.length();
}
}
return size;
}
/**
* @return Returns the canonical path to the root directory
*/
@Override
public String getRootLocation()
{
try
{
return rootDirectory.getCanonicalPath();
}
catch (Throwable e)
{
logger.warn("Unabled to return root location", e);
return super.getRootLocation();
}
}
/**
* This implementation requires that the URL start with
* {@link FileContentStore#STORE_PROTOCOL }.
@@ -585,7 +633,7 @@ public class FileContentStore extends AbstractContentStore implements Applicatio
try
{
// Neither context.isActive() or context.isRunning() seem to detect whether the refresh() has completed
context.publishEvent(new FileContentStoreCreatedEvent(this, rootDirectory));
context.publishEvent(new ContentStoreCreatedEvent(this));
}
catch (IllegalStateException e)
{
@@ -593,11 +641,6 @@ public class FileContentStore extends AbstractContentStore implements Applicatio
}
}
/*
* (non-Javadoc)
* @see
* org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(ApplicationEvent event)
{
// Once the context has been refreshed, we tell other interested beans about the existence of this content store
@@ -605,7 +648,7 @@ public class FileContentStore extends AbstractContentStore implements Applicatio
if (event instanceof ContextRefreshedEvent)
{
((ContextRefreshedEvent) event).getApplicationContext().publishEvent(
new FileContentStoreCreatedEvent(this, rootDirectory));
new ContentStoreCreatedEvent(this));
}
}
}

View File

@@ -88,4 +88,23 @@ public class FileContentStoreTest extends AbstractWritableContentStoreTest
// expected
}
}
@Override
public void testRootLocation() throws Exception
{
ContentStore store = getStore();
String root = store.getRootLocation();
assertNotNull("Root value can't be null", root);
File dir = new File(root);
assertTrue("Root location for FileContentStore must exist", dir.exists());
}
@Override
public void testTotalSize() throws Exception
{
ContentStore store = getStore();
store.getWriter(new ContentContext(null, null)).putContent("Test content");
long size = store.getTotalSize();
assertTrue("Size must be positive", size > 0L);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
* 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
@@ -56,6 +56,7 @@ public class RuntimeExecutableContentTransformerTest extends BaseAlfrescoTestCas
// the command to execute
RuntimeExec transformCommand = new RuntimeExec();
Map<String, String> commandMap = new HashMap<String, String>(5);
commandMap.put("Mac OS X", "mv -f ${source} ${target}");
commandMap.put("Linux", "mv -f ${source} ${target}");
commandMap.put(".*", "cmd /c copy /Y \"${source}\" \"${target}\"");
transformCommand.setCommandMap(commandMap);