ALF-10686 - Original modification date is lost when files are copied into Alfresco via CIFS

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@31864 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Mark Rogers
2011-11-08 17:09:09 +00:00
parent 7a03b10f26
commit f695bcdcd0
7 changed files with 207 additions and 4 deletions

View File

@@ -251,21 +251,40 @@ public class BufferedContentDiskDriver implements ExtendedDiskInterface,
FileInfo finfo = new FileInfo(); FileInfo finfo = new FileInfo();
finfo.copyFrom(info); finfo.copyFrom(info);
// TODO what if file state cache is stale or wrong? We are over-writing the "real" value. /*
* TODO what if file state cache is stale?
* We are over-writing the "real" value here.
*/
if(fstate.hasFileSize()) if(fstate.hasFileSize())
{ {
if(logger.isDebugEnabled())
{
logger.debug("replace file size " + info.getSize() + " with " + fstate.getFileSize());
}
finfo.setFileSize(fstate.getFileSize()); finfo.setFileSize(fstate.getFileSize());
} }
if ( fstate.hasAccessDateTime()) if ( fstate.hasAccessDateTime())
{ {
if(logger.isDebugEnabled())
{
logger.debug("replace access date " + new Date(finfo.getAccessDateTime()) + " with " + new Date(fstate.getAccessDateTime()));
}
finfo.setAccessDateTime(fstate.getAccessDateTime()); finfo.setAccessDateTime(fstate.getAccessDateTime());
} }
if ( fstate.hasChangeDateTime()) if ( fstate.hasChangeDateTime())
{ {
if(logger.isDebugEnabled())
{
logger.debug("replace change date " + new Date(finfo.getChangeDateTime()) + " with " + new Date(fstate.getChangeDateTime()));
}
finfo.setChangeDateTime(fstate.getChangeDateTime()); finfo.setChangeDateTime(fstate.getChangeDateTime());
} }
if ( fstate.hasModifyDateTime()) if ( fstate.hasModifyDateTime())
{ {
if(logger.isDebugEnabled())
{
logger.debug("replace modified date " + new Date(finfo.getModifyDateTime()) + " with " + new Date(fstate.getModifyDateTime()));
}
finfo.setModifyDateTime(fstate.getModifyDateTime()); finfo.setModifyDateTime(fstate.getModifyDateTime());
} }
if ( fstate.hasAllocationSize() && fstate.getAllocationSize() > info.getAllocationSize()) if ( fstate.hasAllocationSize() && fstate.getAllocationSize() > info.getAllocationSize())
@@ -279,8 +298,10 @@ public class BufferedContentDiskDriver implements ExtendedDiskInterface,
", readOnly:" +finfo.isReadOnly() + ", readOnly:" +finfo.isReadOnly() +
", fileId:" +finfo.getFileId() + ", fileId:" +finfo.getFileId() +
", directoryId:" + finfo.getDirectoryId() + ", directoryId:" + finfo.getDirectoryId() +
", createdDate: " + finfo.getCreationDateTime() +
", accessDate:" + new Date(finfo.getAccessDateTime()) + ", accessDate:" + new Date(finfo.getAccessDateTime()) +
", modifiedDate:" + new Date(finfo.getModifyDateTime()) + ", modifiedDate:" + new Date(finfo.getModifyDateTime()) +
", changeDate:" + new Date(finfo.getChangeDateTime()) +
", mode" + finfo.getMode()); ", mode" + finfo.getMode());
} }

View File

@@ -277,6 +277,7 @@ public class CifsHelper
long modified = DefaultTypeConverter.INSTANCE.longValue(modifiedDate); long modified = DefaultTypeConverter.INSTANCE.longValue(modifiedDate);
fileInfo.setModifyDateTime(modified); fileInfo.setModifyDateTime(modified);
fileInfo.setAccessDateTime(modified); fileInfo.setAccessDateTime(modified);
fileInfo.setChangeDateTime(modified);
} }
// name // name
String name = fileFolderInfo.getName(); String name = fileFolderInfo.getName();

View File

@@ -1968,6 +1968,8 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
logger.debug("setFileInformation name=" + name + ", info=" + info); logger.debug("setFileInformation name=" + name + ", info=" + info);
} }
NetworkFile networkFile = info.getNetworkFile();
try try
{ {
@@ -2057,12 +2059,28 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
// Set the creation date on the file/folder node // Set the creation date on the file/folder node
Date createDate = new Date( info.getCreationDateTime()); Date createDate = new Date( info.getCreationDateTime());
auditableProps.put(ContentModel.PROP_CREATED, createDate); auditableProps.put(ContentModel.PROP_CREATED, createDate);
if ( logger.isDebugEnabled())
{
logger.debug("Set creation date" + name + ", " + createDate);
}
} }
if ( info.hasSetFlag(FileInfo.SetModifyDate)) if ( info.hasSetFlag(FileInfo.SetModifyDate))
{ {
// Set the modification date on the file/folder node // Set the modification date on the file/folder node
Date modifyDate = new Date( info.getModifyDateTime()); Date modifyDate = new Date( info.getModifyDateTime());
auditableProps.put(ContentModel.PROP_MODIFIED, modifyDate); auditableProps.put(ContentModel.PROP_MODIFIED, modifyDate);
// Set the network file so we don't reverse this change in close file.
if(networkFile != null && !networkFile.isReadOnly())
{
networkFile.setModifyDate(info.getModifyDateTime());
}
if ( logger.isDebugEnabled())
{
logger.debug("Set modification date" + name + ", " + modifyDate);
}
} }
// Did we have any cm:auditable properties? // Did we have any cm:auditable properties?
@@ -2879,6 +2897,13 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
// Some content was written to the temp file. // Some content was written to the temp file.
tempFile.flushFile(); tempFile.flushFile();
tempFile.close(); tempFile.close();
/**
* Take over the behaviour of the auditable aspect
*/
getPolicyFilter().disableBehaviour(target, ContentModel.ASPECT_AUDITABLE);
nodeService.setProperty(target, ContentModel.PROP_MODIFIER, authService.getCurrentUserName());
nodeService.setProperty(target, ContentModel.PROP_MODIFIED, new Date(tempFile.getModifyDate()));
// Take an initial guess at the mimetype (if it has not been set by something already) // Take an initial guess at the mimetype (if it has not been set by something already)
String mimetype = mimetypeService.guessMimetype(tempFile.getFullName(), new FileContentReader(tempFile.getFile())); String mimetype = mimetypeService.guessMimetype(tempFile.getFullName(), new FileContentReader(tempFile.getFile()));

View File

@@ -3762,6 +3762,122 @@ public class ContentDiskDriverTest extends TestCase
} // Test Word Save Locked File } // Test Word Save Locked File
/**
* ALF-10686
* This scenario is executed by windows explorer.
*
* A file is created and the file handle kept open.
* stuff is written
* Then the modified date is set
* Then the file is closed.
* @throws Exception
*/
public void testSetFileScenario() throws Exception
{
logger.debug("testSetFileInfo");
ServerConfiguration scfg = new ServerConfiguration("testServer");
TestServer testServer = new TestServer("testServer", scfg);
final SrvSession testSession = new TestSrvSession(666, testServer, "test", "remoteName");
DiskSharedDevice share = getDiskSharedDevice();
final TreeConnection testConnection = testServer.getTreeConnection(share);
final RetryingTransactionHelper tran = transactionService.getRetryingTransactionHelper();
Date now = new Date();
// CREATE 6 hours ago
final Date CREATED = new Date(now.getTime() - 1000 * 60 * 60 * 6);
// Modify one hour ago
final Date MODIFIED = new Date(now.getTime() - 1000 * 60 * 60 * 1);
class TestContext
{
NodeRef testNodeRef;
};
final TestContext testContext = new TestContext();
/**
* Step 1 : Create a new file in read/write mode and add some content.
* Call SetInfo to set the creation date
*/
int openAction = FileAction.CreateNotExist;
final String FILE_NAME="testSetFileScenario.txt";
final String FILE_PATH="\\"+FILE_NAME;
// Clean up junk if it exists
try
{
driver.deleteFile(testSession, testConnection, FILE_PATH);
}
catch (IOException ie)
{
// expect to go here
}
final FileOpenParams params = new FileOpenParams(FILE_PATH, openAction, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
final NetworkFile file = driver.createFile(testSession, testConnection, params);
assertNotNull("file is null", file);
assertFalse("file is read only, should be read-write", file.isReadOnly());
RetryingTransactionCallback<Void> writeStuffCB = new RetryingTransactionCallback<Void>() {
@Override
public Void execute() throws Throwable
{
byte[] stuff = "Hello World".getBytes();
driver.writeFile(testSession, testConnection, file, stuff, 0, stuff.length, 0);
FileInfo info = driver.getFileInformation(testSession, testConnection, FILE_PATH);
info.setFileInformationFlags(FileInfo.SetModifyDate);
info.setModifyDateTime(MODIFIED.getTime());
info.setNetworkFile(file);
driver.setFileInformation(testSession, testConnection, FILE_PATH, info);
return null;
}
};
tran.doInTransaction(writeStuffCB);
RetryingTransactionCallback<Void> closeFileCB = new RetryingTransactionCallback<Void>() {
@Override
public Void execute() throws Throwable
{
// This close is in a different position to the simple setFileInformation scenarios above.
driver.closeFile(testSession, testConnection, file);
return null;
}
};
tran.doInTransaction(closeFileCB);
RetryingTransactionCallback<Void> validateCB = new RetryingTransactionCallback<Void>() {
@Override
public Void execute() throws Throwable
{
NodeRef companyHome = repositoryHelper.getCompanyHome();
NodeRef newNode = nodeService.getChildByName(companyHome, ContentModel.ASSOC_CONTAINS, FILE_NAME);
testContext.testNodeRef = newNode;
assertNotNull("can't find new node", newNode);
Serializable content = nodeService.getProperty(newNode, ContentModel.PROP_CONTENT);
assertNotNull("content is null", content);
Date modified = (Date)nodeService.getProperty(newNode, ContentModel.PROP_MODIFIED);
assertEquals("modified time not set correctly", MODIFIED, modified);
return null;
}
};
tran.doInTransaction(validateCB);
// clean up so we could run the test again
//driver.deleteFile(testSession, testConnection, FILE_PATH);
} // test set modified scenario
/** /**
* Test server * Test server
*/ */

View File

@@ -20,6 +20,7 @@ package org.alfresco.filesys.repo;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.Date;
import org.alfresco.filesys.alfresco.ExtendedDiskInterface; import org.alfresco.filesys.alfresco.ExtendedDiskInterface;
import org.alfresco.filesys.config.ServerConfigurationBean; import org.alfresco.filesys.config.ServerConfigurationBean;
@@ -37,6 +38,7 @@ import org.alfresco.jlan.server.filesys.cache.FileState;
import org.alfresco.jlan.server.filesys.cache.FileStateCache; import org.alfresco.jlan.server.filesys.cache.FileStateCache;
import org.alfresco.jlan.server.filesys.cache.NetworkFileStateInterface; import org.alfresco.jlan.server.filesys.cache.NetworkFileStateInterface;
import org.alfresco.jlan.smb.SharingMode; import org.alfresco.jlan.smb.SharingMode;
import org.alfresco.model.ContentModel;
import org.alfresco.util.PropertyCheck; import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -392,7 +394,35 @@ public class LegacyFileStateDriver implements ExtendedDiskInterface
public void setFileInformation(SrvSession sess, TreeConnection tree, public void setFileInformation(SrvSession sess, TreeConnection tree,
String name, FileInfo info) throws IOException String name, FileInfo info) throws IOException
{ {
diskInterface.setFileInformation(sess, tree, name, info);
diskInterface.setFileInformation(sess, tree, name, info);
ContentContext tctx = (ContentContext) tree.getContext();
if(tctx.hasStateCache())
{
FileStateCache cache = tctx.getStateCache();
FileState fstate = cache.findFileState( name, true);
// if ( info.hasSetFlag(FileInfo.SetCreationDate))
// {
// if ( logger.isDebugEnabled())
// {
// logger.debug("Set creation date in file state cache" + name + ", " + info.getCreationDateTime());
// }
// Date createDate = new Date( info.getCreationDateTime());
// fstate.u(createDate.getTime());
// }
if ( info.hasSetFlag(FileInfo.SetModifyDate))
{
if ( logger.isDebugEnabled())
{
logger.debug("Set modification date in file state cache" + name + ", " + info.getModifyDateTime());
}
Date modifyDate = new Date( info.getModifyDateTime());
fstate.updateModifyDateTime(modifyDate.getTime());
}
}
} }
@Override @Override

View File

@@ -20,6 +20,7 @@ package org.alfresco.filesys.repo;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@@ -196,6 +197,12 @@ public class NonTransactionalRuleContentDiskDriver implements ExtendedDiskInterf
+ " allocationSize: " + params.getAllocationSize()); + " allocationSize: " + params.getAllocationSize());
} }
long creationDateTime = params.getCreationDateTime();
if(creationDateTime != 0)
{
logger.debug("creationDateTime is set:" + new Date(creationDateTime));
}
ContentContext tctx = (ContentContext) tree.getContext(); ContentContext tctx = (ContentContext) tree.getContext();
NodeRef rootNode = tctx.getRootNode(); NodeRef rootNode = tctx.getRootNode();

View File

@@ -76,6 +76,7 @@ public class TempNetworkFile extends JavaNetworkFile implements NetworkFileState
if(fileState != null) if(fileState != null)
{ {
fileState.updateModifyDateTime(); fileState.updateModifyDateTime();
fileState.updateAccessDateTime();
fileState.setFileSize(size); fileState.setFileSize(size);
} }
} }
@@ -92,6 +93,7 @@ public class TempNetworkFile extends JavaNetworkFile implements NetworkFileState
if(fileState != null) if(fileState != null)
{ {
fileState.updateModifyDateTime(); fileState.updateModifyDateTime();
fileState.updateAccessDateTime();
fileState.setFileSize(size); fileState.setFileSize(size);
} }
} }
@@ -105,6 +107,7 @@ public class TempNetworkFile extends JavaNetworkFile implements NetworkFileState
if(fileState != null) if(fileState != null)
{ {
fileState.updateModifyDateTime(); fileState.updateModifyDateTime();
fileState.updateAccessDateTime();
fileState.setFileSize(size); fileState.setFileSize(size);
} }
} }