From f695bcdcd01e3ee684e27e957e1d88735b790e5c Mon Sep 17 00:00:00 2001 From: Mark Rogers Date: Tue, 8 Nov 2011 17:09:09 +0000 Subject: [PATCH] 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 --- .../repo/BufferedContentDiskDriver.java | 23 +++- .../org/alfresco/filesys/repo/CifsHelper.java | 1 + .../filesys/repo/ContentDiskDriver2.java | 29 ++++- .../filesys/repo/ContentDiskDriverTest.java | 116 ++++++++++++++++++ .../filesys/repo/LegacyFileStateDriver.java | 32 ++++- ...NonTransactionalRuleContentDiskDriver.java | 7 ++ .../filesys/repo/TempNetworkFile.java | 3 + 7 files changed, 207 insertions(+), 4 deletions(-) diff --git a/source/java/org/alfresco/filesys/repo/BufferedContentDiskDriver.java b/source/java/org/alfresco/filesys/repo/BufferedContentDiskDriver.java index 4bd2459551..da195d9b8e 100644 --- a/source/java/org/alfresco/filesys/repo/BufferedContentDiskDriver.java +++ b/source/java/org/alfresco/filesys/repo/BufferedContentDiskDriver.java @@ -251,21 +251,40 @@ public class BufferedContentDiskDriver implements ExtendedDiskInterface, FileInfo finfo = new FileInfo(); 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(logger.isDebugEnabled()) + { + logger.debug("replace file size " + info.getSize() + " with " + fstate.getFileSize()); + } finfo.setFileSize(fstate.getFileSize()); } if ( fstate.hasAccessDateTime()) { + if(logger.isDebugEnabled()) + { + logger.debug("replace access date " + new Date(finfo.getAccessDateTime()) + " with " + new Date(fstate.getAccessDateTime())); + } finfo.setAccessDateTime(fstate.getAccessDateTime()); } if ( fstate.hasChangeDateTime()) { + if(logger.isDebugEnabled()) + { + logger.debug("replace change date " + new Date(finfo.getChangeDateTime()) + " with " + new Date(fstate.getChangeDateTime())); + } finfo.setChangeDateTime(fstate.getChangeDateTime()); } if ( fstate.hasModifyDateTime()) { + if(logger.isDebugEnabled()) + { + logger.debug("replace modified date " + new Date(finfo.getModifyDateTime()) + " with " + new Date(fstate.getModifyDateTime())); + } finfo.setModifyDateTime(fstate.getModifyDateTime()); } if ( fstate.hasAllocationSize() && fstate.getAllocationSize() > info.getAllocationSize()) @@ -279,8 +298,10 @@ public class BufferedContentDiskDriver implements ExtendedDiskInterface, ", readOnly:" +finfo.isReadOnly() + ", fileId:" +finfo.getFileId() + ", directoryId:" + finfo.getDirectoryId() + + ", createdDate: " + finfo.getCreationDateTime() + ", accessDate:" + new Date(finfo.getAccessDateTime()) + ", modifiedDate:" + new Date(finfo.getModifyDateTime()) + + ", changeDate:" + new Date(finfo.getChangeDateTime()) + ", mode" + finfo.getMode()); } diff --git a/source/java/org/alfresco/filesys/repo/CifsHelper.java b/source/java/org/alfresco/filesys/repo/CifsHelper.java index 5b799b6113..e1643894e0 100644 --- a/source/java/org/alfresco/filesys/repo/CifsHelper.java +++ b/source/java/org/alfresco/filesys/repo/CifsHelper.java @@ -277,6 +277,7 @@ public class CifsHelper long modified = DefaultTypeConverter.INSTANCE.longValue(modifiedDate); fileInfo.setModifyDateTime(modified); fileInfo.setAccessDateTime(modified); + fileInfo.setChangeDateTime(modified); } // name String name = fileFolderInfo.getName(); diff --git a/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java b/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java index 2529adcb21..57f58e64f4 100644 --- a/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java +++ b/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java @@ -1968,6 +1968,8 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD logger.debug("setFileInformation name=" + name + ", info=" + info); } + NetworkFile networkFile = info.getNetworkFile(); + try { @@ -2057,12 +2059,28 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD // Set the creation date on the file/folder node Date createDate = new Date( info.getCreationDateTime()); auditableProps.put(ContentModel.PROP_CREATED, createDate); + if ( logger.isDebugEnabled()) + { + logger.debug("Set creation date" + name + ", " + createDate); + } } 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()); 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? @@ -2879,6 +2897,13 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD // Some content was written to the temp file. tempFile.flushFile(); 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) String mimetype = mimetypeService.guessMimetype(tempFile.getFullName(), new FileContentReader(tempFile.getFile())); diff --git a/source/java/org/alfresco/filesys/repo/ContentDiskDriverTest.java b/source/java/org/alfresco/filesys/repo/ContentDiskDriverTest.java index afbcde6614..67ac8a1870 100644 --- a/source/java/org/alfresco/filesys/repo/ContentDiskDriverTest.java +++ b/source/java/org/alfresco/filesys/repo/ContentDiskDriverTest.java @@ -3762,6 +3762,122 @@ public class ContentDiskDriverTest extends TestCase } // 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 writeStuffCB = new RetryingTransactionCallback() { + + @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 closeFileCB = new RetryingTransactionCallback() { + + @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 validateCB = new RetryingTransactionCallback() { + + @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 */ diff --git a/source/java/org/alfresco/filesys/repo/LegacyFileStateDriver.java b/source/java/org/alfresco/filesys/repo/LegacyFileStateDriver.java index 6b4ae946cf..d1fab4ed01 100644 --- a/source/java/org/alfresco/filesys/repo/LegacyFileStateDriver.java +++ b/source/java/org/alfresco/filesys/repo/LegacyFileStateDriver.java @@ -20,6 +20,7 @@ package org.alfresco.filesys.repo; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Date; import org.alfresco.filesys.alfresco.ExtendedDiskInterface; 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.NetworkFileStateInterface; import org.alfresco.jlan.smb.SharingMode; +import org.alfresco.model.ContentModel; import org.alfresco.util.PropertyCheck; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -392,7 +394,35 @@ public class LegacyFileStateDriver implements ExtendedDiskInterface public void setFileInformation(SrvSession sess, TreeConnection tree, 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 diff --git a/source/java/org/alfresco/filesys/repo/NonTransactionalRuleContentDiskDriver.java b/source/java/org/alfresco/filesys/repo/NonTransactionalRuleContentDiskDriver.java index 083c948148..c04a36b4bb 100644 --- a/source/java/org/alfresco/filesys/repo/NonTransactionalRuleContentDiskDriver.java +++ b/source/java/org/alfresco/filesys/repo/NonTransactionalRuleContentDiskDriver.java @@ -20,6 +20,7 @@ package org.alfresco.filesys.repo; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Date; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -196,6 +197,12 @@ public class NonTransactionalRuleContentDiskDriver implements ExtendedDiskInterf + " allocationSize: " + params.getAllocationSize()); } + long creationDateTime = params.getCreationDateTime(); + if(creationDateTime != 0) + { + logger.debug("creationDateTime is set:" + new Date(creationDateTime)); + } + ContentContext tctx = (ContentContext) tree.getContext(); NodeRef rootNode = tctx.getRootNode(); diff --git a/source/java/org/alfresco/filesys/repo/TempNetworkFile.java b/source/java/org/alfresco/filesys/repo/TempNetworkFile.java index df1d7274bb..abde1c0614 100644 --- a/source/java/org/alfresco/filesys/repo/TempNetworkFile.java +++ b/source/java/org/alfresco/filesys/repo/TempNetworkFile.java @@ -76,6 +76,7 @@ public class TempNetworkFile extends JavaNetworkFile implements NetworkFileState if(fileState != null) { fileState.updateModifyDateTime(); + fileState.updateAccessDateTime(); fileState.setFileSize(size); } } @@ -92,6 +93,7 @@ public class TempNetworkFile extends JavaNetworkFile implements NetworkFileState if(fileState != null) { fileState.updateModifyDateTime(); + fileState.updateAccessDateTime(); fileState.setFileSize(size); } } @@ -105,6 +107,7 @@ public class TempNetworkFile extends JavaNetworkFile implements NetworkFileState if(fileState != null) { fileState.updateModifyDateTime(); + fileState.updateAccessDateTime(); fileState.setFileSize(size); } }