() {
            @Override
            public Void execute() throws Throwable
            {
                
                NodeRef companyHome = repositoryHelper.getCompanyHome();
                NodeRef newNode = nodeService.getChildByName(companyHome, ContentModel.ASSOC_CONTAINS, FILE_NAME);
                assertNotNull("can't find new node", newNode);
                nodeService.deleteNode(newNode);
                return null;
            }
        };
        tran.doInTransaction(deleteNodeCB, false, true);
        
        try
        {
            getNodeForPath(testConnection, FILE_PATH);
            fail("getNode for path unexpectedly succeeded");
        } 
        catch (IOException ie)
        {
            // expect to go here
        }
        
        /**
         * Delete file by path - file should no longer exist
         */
        try
        {
            driver.deleteFile(testSession, testConnection, FILE_PATH);
            fail("delete unexpectedly succeeded");
        } 
        catch (IOException ie)
        {
            // expect to go here
        }
        
    }
    
    /**
     * This test tries to simulate the shuffling that is done by MS Word 2003 
     * with regard to metadata extraction.
     * 
     * 1: Setup an inbound rule for ContentMetadataExtractor.
     * 2: Write ContentDiskDriverTest1 file to ContentDiskDriver.docx
     * 3: Check metadata extraction for non update test
     * Simulate a WORD 2003 CIFS shuffle
     * 4: Write ContentDiskDriverTest2 file to ~WRD0003.TMP
     * 5: Rename ContentDiskDriver.docx to ~WRL0003.TMP
     * 6: Rename ~WRD0003.TMP to ContentDiskDriver.docx
     * 7: Check metadata extraction
     */
    public void testMetadataExtraction() throws Exception
    {
        logger.debug("testMetadataExtraction");
        final String FILE_NAME = "ContentDiskDriver.docx";
        final String FILE_OLD_TEMP = "~WRL0003.TMP";
        final String FILE_NEW_TEMP = "~WRD0003.TMP";
         
        class TestContext
        {
            NodeRef testDirNodeRef;
            NodeRef testNodeRef;
            NetworkFile firstFileHandle;
            NetworkFile secondFileHandle;
        };
        
        final TestContext testContext = new TestContext();
        
        final String TEST_DIR = TEST_ROOT_DOS_PATH + "\\testMetadataExtraction";
        
        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();
        
        /**
         * Clean up just in case garbage is left from a previous run
         */
        RetryingTransactionCallback deleteGarbageDirCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.deleteDirectory(testSession, testConnection, TEST_DIR);
                return null;
            }
        };
        
        try
        {
            tran.doInTransaction(deleteGarbageDirCB);
        }
        catch (Exception e)
        {
            // expect to go here
        }
        
        logger.debug("create Test directory" + TEST_DIR);
        RetryingTransactionCallback createTestDirCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                /**
                 * Create the test directory we are going to use 
                 */
                FileOpenParams createRootDirParams = new FileOpenParams(TEST_ROOT_DOS_PATH, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                FileOpenParams createDirParams = new FileOpenParams(TEST_DIR, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                driver.createDirectory(testSession, testConnection, createRootDirParams);
                driver.createDirectory(testSession, testConnection, createDirParams);
                
                testContext.testDirNodeRef = getNodeForPath(testConnection, TEST_DIR);
                assertNotNull("testDirNodeRef is null", testContext.testDirNodeRef);   
                
                UserTransaction txn = transactionService.getUserTransaction();
              
                return null;
                
                
            }
        };                
        tran.doInTransaction(createTestDirCB);
        logger.debug("Create rule on test dir");
        
        RetryingTransactionCallback createRuleCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {                 
                Rule rule = new Rule();
                rule.setRuleType(RuleType.INBOUND);
                rule.applyToChildren(true);
                rule.setRuleDisabled(false);
                rule.setTitle("Extract Metadata from content");
                rule.setDescription("ContentDiskDriverTest");
                
                Map props = new HashMap(1);
                Action extractAction = actionService.createAction("extract-metadata", props);
                
                ActionCondition noCondition1 = actionService.createActionCondition(NoConditionEvaluator.NAME);
                extractAction.addActionCondition(noCondition1);
                
                ActionCondition noCondition2 = actionService.createActionCondition(NoConditionEvaluator.NAME);
                CompositeAction compAction = actionService.createCompositeAction();
                compAction.setTitle("Extract Metadata");
                compAction.setDescription("Content Disk Driver Test - Extract Metadata");
                compAction.addAction(extractAction);
                compAction.addActionCondition(noCondition2);
                rule.setAction(compAction);           
                         
                ruleService.saveRule(testContext.testDirNodeRef, rule);
                
                logger.debug("rule created");
                     
                return null;
            }
        };
        tran.doInTransaction(createRuleCB, false, true);
        /**
         * Create a file in the test directory
         */  
        logger.debug("create test file in test directory");
        RetryingTransactionCallback createFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {               
                /**
                 * Create the file we are going to use to test
                 */
                FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_NAME, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                testContext.firstFileHandle = driver.createFile(testSession, testConnection, createFileParams);
                assertNotNull(testContext.firstFileHandle);
                
                // now load up the node with lots of other stuff that we will test to see if it gets preserved during the
                // shuffle.
                testContext.testNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NAME);
                assertNotNull("testContext.testNodeRef is null", testContext.testNodeRef);
                
                // test non CM namespace property
                nodeService.setProperty(testContext.testNodeRef, TransferModel.PROP_ENABLED, true);
        
                return null;
            }
        };
        tran.doInTransaction(createFileCB, false, true);
        
        logger.debug("step b: write content to test file");
        
        /**
         * Write ContentDiskDriverTest1.docx to the test file,
         */
        RetryingTransactionCallback writeFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                ClassPathResource fileResource = new ClassPathResource("filesys/ContentDiskDriverTest1.docx");
                assertNotNull("unable to find test resource filesys/ContentDiskDriverTest1.docx", fileResource);
                writeResourceToNetworkFile(fileResource, testContext.firstFileHandle);
            
                logger.debug("close the file, firstFileHandle");
                driver.closeFile(testSession, testConnection, testContext.firstFileHandle);   
                    
                return null;
            }
        };
        tran.doInTransaction(writeFileCB, false, true);
        
        logger.debug("Step c: validate metadata has been extracted.");
        
        /**
         * c: check simple case of meta-data extraction has worked.
         */
        RetryingTransactionCallback validateFirstExtractionCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                Map props = nodeService.getProperties(testContext.testNodeRef);
                
                assertTrue("Enabled property has been lost", props.containsKey(TransferModel.PROP_ENABLED));
                
                ContentData data = (ContentData)props.get(ContentModel.PROP_CONTENT);
                assertEquals("size is wrong", 11302, data.getSize());
                assertEquals("mimeType is wrong", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", data.getMimetype());
                
                // These metadata values should be extracted.
                assertEquals("description is not correct", "This is a test file", nodeService.getProperty(testContext.testNodeRef, ContentModel.PROP_DESCRIPTION));
                assertEquals("title is not correct", "ContentDiskDriverTest", nodeService.getProperty(testContext.testNodeRef, ContentModel.PROP_TITLE));
                assertEquals("author is not correct", "mrogers", nodeService.getProperty(testContext.testNodeRef, ContentModel.PROP_AUTHOR));
                
    
                        
                return null;
            }
        };
        tran.doInTransaction(validateFirstExtractionCB, false, true);
        
        
        /**
         * d: Save the new file as an update file in the test directory
         */
        logger.debug("Step d: create update file in test directory " + FILE_NEW_TEMP);
        RetryingTransactionCallback createUpdateFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {               
                /**
                 * Create the file we are going to use to test
                 */
                FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_NEW_TEMP, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                testContext.secondFileHandle = driver.createFile(testSession, testConnection, createFileParams);
                assertNotNull(testContext.secondFileHandle);
                  
                return null;
            }
        };
        tran.doInTransaction(createUpdateFileCB, false, true);
        RetryingTransactionCallback writeFile2CB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                ClassPathResource fileResource = new ClassPathResource("filesys/ContentDiskDriverTest2.docx");
                assertNotNull("unable to find test resource filesys/ContentDiskDriverTest2.docx", fileResource);
                byte[] buffer= new byte[1000];
                InputStream is = fileResource.getInputStream();
                try
                {
                    long offset = 0;
                    int i = is.read(buffer, 0, buffer.length);
                    while(i > 0)
                    {
                        testContext.secondFileHandle.writeFile(buffer, i, 0, offset);
                        offset += i;
                        i = is.read(buffer, 0, buffer.length);
                    }                 
                }
                finally
                {
                    is.close();
                }
            
                driver.closeFile(testSession, testConnection, testContext.secondFileHandle);
                    
                return null;
            }
        };
        tran.doInTransaction(writeFile2CB, false, true);
        
        /**
         * rename the old file
         */
        logger.debug("move old file out of the way.");
        RetryingTransactionCallback renameOldFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.renameFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME, TEST_DIR + "\\" + FILE_OLD_TEMP);
                return null;
            }
        };
        tran.doInTransaction(renameOldFileCB, false, true);
  
        /**
         * Check the old file has gone.
         */
        RetryingTransactionCallback validateOldFileGoneCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {   
                try
                {
                    driver.deleteFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME);
                }
                catch (IOException e)
                { 
                    // expect to go here since previous step renamed the file.
                }
                
                return null;
            }
        };
        tran.doInTransaction(validateOldFileGoneCB, false, true);
        
//        /**
//         * Check metadata extraction on intermediate new file
//         */
//        RetryingTransactionCallback validateIntermediateCB = new RetryingTransactionCallback() {
//
//            @Override
//            public Void execute() throws Throwable
//            {
//               NodeRef updateNodeRef = driver.getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NEW_TEMP);
//               
//               Map props = nodeService.getProperties(updateNodeRef);
//                        
//               // These metadata values should be extracted from file2.
//               assertEquals("intermediate file description is not correct", "Content Disk Test 2", props.get(ContentModel.PROP_DESCRIPTION));
//               assertEquals("intermediate file title is not correct", "Updated", props.get(ContentModel.PROP_TITLE));
//               assertEquals("intermediate file author is not correct", "mrogers", props.get(ContentModel.PROP_AUTHOR));
//
//               return null;
//            }
//        };
//        
//        tran.doInTransaction(validateIntermediateCB, true, true);
        
        /**
         * Move the new file into place, stuff should get shuffled
         */
        logger.debug("move new file into place.");
        RetryingTransactionCallback moveNewFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.renameFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NEW_TEMP, TEST_DIR + "\\" + FILE_NAME); 
                return null;
            }
        };
        
        tran.doInTransaction(moveNewFileCB, false, true);
        
        logger.debug("validate update has run correctly.");
        RetryingTransactionCallback validateUpdateCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
               NodeRef shuffledNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NAME);
               
               Map props = nodeService.getProperties(shuffledNodeRef);
               
               // Check trx:enabled has been shuffled and not lost.
               assertTrue("node does not contain shuffled ENABLED property", props.containsKey(TransferModel.PROP_ENABLED));
               
               ContentData data = (ContentData)props.get(ContentModel.PROP_CONTENT);
               assertEquals("mimeType is wrong", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", data.getMimetype());
               assertEquals("size is wrong", 11265, data.getSize());
           
               // These metadata values should be extracted from file2.   However they will not be applied in PRAGMATIC mode.
//               assertEquals("description is not correct", "Content Disk Test 2", props.get(ContentModel.PROP_DESCRIPTION));
//               assertEquals("title is not correct", "Updated", props.get(ContentModel.PROP_TITLE));
//               assertEquals("author is not correct", "mrogers", props.get(ContentModel.PROP_AUTHOR));
               
                    return null;
            }
        };
        
        tran.doInTransaction(validateUpdateCB, true, true);
        
    } // testScenarioShuffleMetadataExtraction
    
    
    /**
     * ALF-12812
     * 
     * This test tries to simulate the shuffling that is done by MS Word 2011 for Mac 
     * with regard to metadata extraction.  In particular the temporary file names are
     * different.
     * 
     * 1: Setup an update rule for ContentMetadataExtractor.
     * Simulate a WORD 2011 for Mac Create
     * 2: Write "Word Work File D_1725484373.tmp"
     * 3: Close file
     * 4: Rename "Word Work File D_1725484373.tmp" to ContentDiskDriver.docx
     * 5: Check metadata extraction
     */
    public void testMetadataExtractionForMac() throws Exception
    {
        logger.debug("testMetadataExtractionForMac");
        final String FILE_NAME = "ContentDiskDriver.docx";
        //final String FILE_OLD_TEMP = "._Word Work File D_1725484373.tmp";
        final String FILE_NEW_TEMP = "Word Work File D_1725484373.tmp";
                 
        class TestContext
        {
            NodeRef testDirNodeRef;
            NodeRef testNodeRef;
            NetworkFile firstFileHandle;
//            NetworkFile secondFileHandle;
        };
        
        final TestContext testContext = new TestContext();
        
        final String TEST_DIR = TEST_ROOT_DOS_PATH + "\\testMetadataExtractionForMac";
        
        ServerConfiguration scfg = new ServerConfiguration("testServer");
        TestServer testServer = new TestServer("testServer", scfg);
        final SrvSession testSession = new TestSrvSession(666, testServer, "cifs", "remoteName");
        DiskSharedDevice share = getDiskSharedDevice();
        final TreeConnection testConnection = testServer.getTreeConnection(share);
        final RetryingTransactionHelper tran = transactionService.getRetryingTransactionHelper();
        
        /**
         * Clean up just in case garbage is left from a previous run
         */
        RetryingTransactionCallback deleteGarbageDirCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.deleteDirectory(testSession, testConnection, TEST_DIR);
                return null;
            }
        };
        
        try
        {
            tran.doInTransaction(deleteGarbageDirCB);
        }
        catch (Exception e)
        {
            // expect to go here
        }
        
        logger.debug("create Test directory" + TEST_DIR);
        RetryingTransactionCallback createTestDirCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                /**
                 * Create the test directory we are going to use 
                 */
                FileOpenParams createRootDirParams = new FileOpenParams(TEST_ROOT_DOS_PATH, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                FileOpenParams createDirParams = new FileOpenParams(TEST_DIR, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                driver.createDirectory(testSession, testConnection, createRootDirParams);
                driver.createDirectory(testSession, testConnection, createDirParams);
                
                testContext.testDirNodeRef = getNodeForPath(testConnection, TEST_DIR);
                assertNotNull("testDirNodeRef is null", testContext.testDirNodeRef);   
                
                UserTransaction txn = transactionService.getUserTransaction();
              
                return null;
                
                
            }
        };                
        tran.doInTransaction(createTestDirCB);
        logger.debug("Create rule on test dir");
        
        RetryingTransactionCallback createRuleCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {                 
                Rule rule = new Rule();
                rule.setRuleType(RuleType.UPDATE);
                rule.applyToChildren(true);
                rule.setRuleDisabled(false);
                rule.setTitle("Extract Metadata from update content");
                rule.setDescription("ContentDiskDriverTest");
                
                Map props = new HashMap(1);
                Action extractAction = actionService.createAction("extract-metadata", props);
                
                ActionCondition noCondition1 = actionService.createActionCondition(NoConditionEvaluator.NAME);
                extractAction.addActionCondition(noCondition1);
                
                ActionCondition noCondition2 = actionService.createActionCondition(NoConditionEvaluator.NAME);
                CompositeAction compAction = actionService.createCompositeAction();
                compAction.setTitle("Extract Metadata");
                compAction.setDescription("Content Disk Driver Test - Extract Metadata");
                compAction.addAction(extractAction);
                compAction.addActionCondition(noCondition2);
                rule.setAction(compAction);           
                         
                ruleService.saveRule(testContext.testDirNodeRef, rule);
                
                logger.debug("rule created");
                     
                return null;
            }
        };
        tran.doInTransaction(createRuleCB, false, true);
        /**
         * Create a file in the test directory
         */  
        logger.debug("create test file in test directory");
        RetryingTransactionCallback createFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {               
                /**
                 * Create the file we are going to use to test
                 */
                FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_NEW_TEMP, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                testContext.firstFileHandle = driver.createFile(testSession, testConnection, createFileParams);
                assertNotNull("first file Handle is null", testContext.firstFileHandle);
                
                // now load up the node with lots of other stuff that we will test to see if it gets preserved during the
                // shuffle.
                testContext.testNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NEW_TEMP);
                assertNotNull("testContext.testNodeRef is null", testContext.testNodeRef);
                
                // test non CM namespace property
                nodeService.setProperty(testContext.testNodeRef, TransferModel.PROP_ENABLED, true);
        
                // Check that the temporary aspect has been applied.
                assertTrue("temporary aspect not applied", nodeService.hasAspect(testContext.testNodeRef, ContentModel.ASPECT_TEMPORARY));
                return null;
            }
        };
        tran.doInTransaction(createFileCB, false, true);
        
        logger.debug("step b: write content to test file");
        
        /**
         * Write ContentDiskDriverTest1.docx to the test file,
         */
        RetryingTransactionCallback writeFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                ClassPathResource fileResource = new ClassPathResource("filesys/ContentDiskDriverTest1.docx");
                assertNotNull("unable to find test resource filesys/ContentDiskDriverTest1.docx", fileResource);
                byte[] buffer= new byte[1000];
                InputStream is = fileResource.getInputStream();
                try
                {
                    long offset = 0;
                    int i = is.read(buffer, 0, buffer.length);
                    while(i > 0)
                    {
                        testContext.firstFileHandle.writeFile(buffer, i, 0, offset);
                        offset += i;
                        i = is.read(buffer, 0, buffer.length);
                    }                 
                }
                finally
                {
                    is.close();
                }
                
                driver.closeFile(testSession, testConnection, testContext.firstFileHandle);
                    
                return null;
            }
        };
        tran.doInTransaction(writeFileCB, false, true);
        
        logger.debug("Step b: rename the test file.");
                
        /**
         * Move the new file into place, stuff should get shuffled
         */
        RetryingTransactionCallback moveNewFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.renameFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NEW_TEMP, TEST_DIR + "\\" + FILE_NAME); 
                return null;
            }
        };
        
        tran.doInTransaction(moveNewFileCB, false, true);
        
      logger.debug("Step c: validate metadata has been extracted.");  
      /**
      * c: check simple case of meta-data extraction has worked.
      */
     RetryingTransactionCallback validateFirstExtractionCB = new RetryingTransactionCallback() {
         @Override
         public Void execute() throws Throwable
         {
             Map props = nodeService.getProperties(testContext.testNodeRef);
             
             assertTrue("Enabled property has been lost", props.containsKey(TransferModel.PROP_ENABLED));
             
             // Check that the temporary aspect has been applied.
             assertTrue("temporary aspect has not been removed", !nodeService.hasAspect(testContext.testNodeRef, ContentModel.ASPECT_TEMPORARY));
             assertTrue("hidden aspect has not been removed", !nodeService.hasAspect(testContext.testNodeRef, ContentModel.ASPECT_HIDDEN));
        
          
             // These metadata values should be extracted.
             assertEquals("description is not correct", "This is a test file", nodeService.getProperty(testContext.testNodeRef, ContentModel.PROP_DESCRIPTION));
             assertEquals("title is not correct", "ContentDiskDriverTest", nodeService.getProperty(testContext.testNodeRef, ContentModel.PROP_TITLE));
             assertEquals("author is not correct", "mrogers", nodeService.getProperty(testContext.testNodeRef, ContentModel.PROP_AUTHOR));
             
             ContentData data = (ContentData)props.get(ContentModel.PROP_CONTENT);
             assertEquals("mimeType is wrong", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", data.getMimetype());
             assertEquals("size is wrong", 11302, data.getSize());
                     
             return null;
         }
     };
     tran.doInTransaction(validateFirstExtractionCB, false, true);
        
    } // testScenarioMetadataExtractionForMac
    
    public void testDirListing()throws Exception
    {
        logger.debug("testDirListing");
        ServerConfiguration scfg = new ServerConfiguration("testServer");
        TestServer testServer = new TestServer("testServer", scfg);
        SrvSession testSession = new TestSrvSession(666, testServer, "test", "remoteName");
        DiskSharedDevice share = getDiskSharedDevice();
        TreeConnection testConnection = testServer.getTreeConnection(share);
        final RetryingTransactionHelper tran = transactionService.getRetryingTransactionHelper();
        
        final String FOLDER_NAME = "parentFolder" + System.currentTimeMillis();
        final String HIDDEN_FOLDER_NAME = "hiddenFolder" + System.currentTimeMillis();
        RetryingTransactionCallback createNodesCB = new RetryingTransactionCallback() {
            @Override
            public NodeRef execute() throws Throwable
            {
                NodeRef companyHome = repositoryHelper.getCompanyHome();
                NodeRef parentNode = nodeService.createNode(companyHome, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, FOLDER_NAME), ContentModel.TYPE_FOLDER).getChildRef();
                nodeService.setProperty(parentNode, ContentModel.PROP_NAME, FOLDER_NAME);
                
                NodeRef hiddenNode = nodeService.createNode(parentNode, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, HIDDEN_FOLDER_NAME), ForumModel.TYPE_FORUM).getChildRef();
                nodeService.setProperty(hiddenNode, ContentModel.PROP_NAME, HIDDEN_FOLDER_NAME);
                return parentNode;
            }
        };
        final NodeRef parentFolder = tran.doInTransaction(createNodesCB);
        
        List excludedTypes = new ArrayList();
        excludedTypes.add(ForumModel.TYPE_FORUM.toString());
        cifsHelper.setExcludedTypes(excludedTypes);
        SearchContext result = driver.startSearch(testSession, testConnection, "\\"+FOLDER_NAME + "\\*", 0);
        while(result.hasMoreFiles())
        {
            if (result.nextFileName().equals(HIDDEN_FOLDER_NAME))
            {
                fail("Exluded types mustn't be shown in cifs");    
            } 
        }
        RetryingTransactionCallback deleteNodeCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                nodeService.deleteNode(parentFolder);
                return null;
            }
        };
        tran.doInTransaction(deleteNodeCB, false, true);
    } //testDirListing
    public void testFileInformationUpdatingByEditorUserForAlf8808() throws Exception
    {
        final Holder editorFolder = new Holder();
        final Holder testFile = new Holder();
        // Configuring test server with test server configuration and getting test tree connection for test shared device
        ServerConfiguration config = new ServerConfiguration(ContentDiskDriverTest.TEST_SERVER_NAME);
        TestServer server = new TestServer(ContentDiskDriverTest.TEST_SERVER_NAME, config);
        DiskSharedDevice device = getDiskSharedDevice();
        final TreeConnection treeConnection = server.getTreeConnection(device);
        // Getting target entity for testing - ContentDiskDriver
        final ExtendedDiskInterface deviceInterface = (ExtendedDiskInterface) treeConnection.getInterface();
        // Creating mock-session
        final SrvSession session = new TestSrvSession(13, server, ContentDiskDriverTest.TEST_PROTOTYPE_NAME, ContentDiskDriverTest.TEST_REMOTE_NAME);
        transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
        {
            @Override
            public Void execute() throws Throwable
            {
                try
                {
                    NodeRef rootNode = repositoryHelper.getCompanyHome();
                    // Creating test user to invite him as Editor for test content. This user will be created correctly (with person and authentication options)
                    createUser(ContentDiskDriverTest.TEST_USER_AUTHORITY, ContentDiskDriverTest.TEST_USER_AUTHORITY, rootNode);
                    // Safely creating folder for test content
                    editorFolder.value = getOrCreateNode(rootNode, PermissionService.EDITOR, ContentModel.TYPE_FOLDER).getFirst();
                    // Creating test content which will be editable by user created above
                    testFile.value = getOrCreateNode(rootNode, "Test.txt", ContentModel.TYPE_CONTENT).getFirst();
                    // Applying 'Editor' role for test user to test file
                    permissionService.setPermission(testFile.value.getNodeRef(), ContentDiskDriverTest.TEST_USER_AUTHORITY, PermissionService.EDITOR, true);
                    try
                    {
                        // Creating data for target method invocation
                        final FileInfo updatedInfo = new FileInfo();
                        updatedInfo.setFileName(testFile.value.getName());
                        updatedInfo.setFileId(DefaultTypeConverter.INSTANCE.intValue(testFile.value.getProperties().get(ContentModel.PROP_NODE_DBID)));
                        // Testing ContentDiskDriver.setFileInformation() with test user authenticated who has 'Editor' role for test content.
                        // This method should fail if check on 'DELETE' permission was not moved to 'DeleteOnClose' context
                        AuthenticationUtil.runAs(new RunAsWork()
                        {
                            @Override
                            public Void doWork() throws Exception
                            {
                                deviceInterface.setFileInformation(session, treeConnection, testFile.value.getName(), updatedInfo);
                                return null;
                            }
                        }, ContentDiskDriverTest.TEST_USER_AUTHORITY);
                    }
                    catch (Exception e)
                    {
                        // Informing about test failure. Expected exception is 'org.alfresco.jlan.server.filesys.AccessDeniedException'
                        if (e.getCause() instanceof AccessDeniedException)
                        {
                            fail("For user='" + TEST_USER_AUTHORITY + "' " + e.getCause().toString());
                        }
                        else
                        {
                            fail("Unexpected exception was caught: " + e.toString());
                        }
                    }
                }
                finally
                {
                    // Cleaning all test data and rolling back transaction to revert all introduced changes during testing
                    if (authenticationService.authenticationExists(ContentDiskDriverTest.TEST_USER_AUTHORITY))
                    {
                        authenticationService.deleteAuthentication(ContentDiskDriverTest.TEST_USER_AUTHORITY);
                    }
                    if (personService.personExists(ContentDiskDriverTest.TEST_USER_AUTHORITY))
                    {
                        personService.deletePerson(ContentDiskDriverTest.TEST_USER_AUTHORITY);
                    }
                    try
                    {
                        if (null != testFile.value)
                        {
                            nodeService.deleteNode(testFile.value.getNodeRef());
                        }
                    }
                    catch (Exception e)
                    {
                        // Doing nothing
                    }
                    try
                    {
                        if (null != editorFolder.value)
                        {
                            nodeService.deleteNode(editorFolder.value.getNodeRef());
                        }
                    }
                    catch (Exception e)
                    {
                        // Doing nothing
                    }
                }
                return null;
            }
        }, false, true);
    }
    /**
     * Searching for file object with specified name or creating new one if such object is not exist
     * 
     * @param parentRef - {@link NodeRef} of desired parent object
     * @param name - {@link String} value for name of desired file object
     * @param type - {@link QName} instance which determines type of the object. It may be cm:content, cm:folder etc (see {@link ContentModel})
     * @return {@link Pair}<{@link org.alfresco.service.cmr.model.FileInfo}, {@link Boolean}> instance which contains {@link NodeRef} of newly created object and
     *         true value if file object with specified name was not found or {@link NodeRef} of existent file object and false in other case
     */
    private Pair getOrCreateNode(NodeRef parentRef, String name, QName type)
    {
        NodeRef result = nodeService.getChildByName(parentRef, ContentModel.ASSOC_CONTAINS, name);
        Boolean created = false;
        if (null == result)
        {
            result = nodeService.getChildByName(parentRef, ContentModel.ASSOC_CHILDREN, name);
        }
        if (created = (null == result))
        {
            result = fileFolderService.create(parentRef, name, type).getNodeRef();
        }
        return new Pair(fileFolderService.getFileInfo(result), created);
    }
    /**
     * Creates correct user entity with correct user home space, person and authentication with password equal to 'password' options if these options are not exist.
     * Method searches for space with name equal to 'name' to make it user home space or creates new folder with name equal to 'name'. All required
     * permissions and roles will be applied to user home space
     * 
     * @param name - {@link String} value which contains new user name
     * @param password - {@link String} value of text password for new user
     * @param parentNodeRef - {@link NodeRef} instance of parent folder where user home space should be found or created
     */
    private void createUser(String name, String password, NodeRef parentNodeRef)
    {
        Map properties = new HashMap();
        properties.put(ContentModel.PROP_USERNAME, name);
        Pair userHome = getOrCreateNode(parentNodeRef, name, ContentModel.TYPE_FOLDER);
        if (userHome.getSecond())
        {
            NodeRef nodeRef = userHome.getFirst().getNodeRef();
            permissionService.setPermission(nodeRef, name, permissionService.getAllPermission(), true);
            permissionService.setPermission(nodeRef, permissionService.getAllAuthorities(), PermissionService.CONSUMER, true);
            permissionService.setPermission(nodeRef, permissionService.getOwnerAuthority(), permissionService.getAllPermission(), true);
            ownableService.setOwner(nodeRef, name);
            permissionService.setInheritParentPermissions(nodeRef, false);
            properties.put(ContentModel.PROP_HOMEFOLDER, nodeRef);
            if (!personService.personExists(name))
            {
                personService.createPerson(properties);
            }
            if (!authenticationService.authenticationExists(name))
            {
                authenticationService.createAuthentication(name, password.toCharArray());
            }
        }
    }
    
    /**
     * Excel 2003 With Versionable file
     *
     * CreateFile 5EE27100
     * RenameFile oldPath:\Espaces Utilisateurs\System\Cherries.xls, 
     *          newPath:\Espaces Utilisateurs\System\Cherries.xls~RF172f241.TMP
     * RenameFile oldName=\Espaces Utilisateurs\System\5EE27100, 
     *          newName=\Espaces Utilisateurs\System\Cherries.xls, session:WNB0
     *
     * Set Delete On Close for Cherries.xls~RF172f241.TMP
     */
    public void testExcel2003SaveShuffle() throws Exception
    {
        //fail("not yet implemented");
        logger.debug("testScenarioExcel2003SaveShuffle");
        final String FILE_NAME = "Cherries.xls";
        final String FILE_TITLE = "Cherries";
        final String FILE_DESCRIPTION = "This is a test document to test CIFS shuffle";
        final String FILE_OLD_TEMP = "Cherries.xls~RF172f241.TMP";
        final String FILE_NEW_TEMP = "5EE27100";
        
        final QName RESIDUAL_MTTEXT = QName.createQName("{gsxhjsx}", "whatever");
        
        class TestContext
        {
            NetworkFile firstFileHandle;
            NetworkFile newFileHandle;
            NetworkFile oldFileHandle;
            
            NodeRef testNodeRef;   // node ref of test.doc
            
            Serializable testCreatedDate;
        };
        
        final TestContext testContext = new TestContext();
        
        final String TEST_DIR = TEST_ROOT_DOS_PATH + "\\testScenarioMSExcel2003SaveShuffle";
        
        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();        
        /**
         * Clean up just in case garbage is left from a previous run
         */
        RetryingTransactionCallback deleteGarbageFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.deleteFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME);
                return null;
            }
        };
     
        /**
         * Create a file in the test directory
         */    
        
        try
        {
            tran.doInTransaction(deleteGarbageFileCB);
        }
        catch (Exception e)
        {
            // expect to go here
        }
        
        RetryingTransactionCallback createFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
  
                /**
                 * Create the test directory we are going to use 
                 */
                FileOpenParams createRootDirParams = new FileOpenParams(TEST_ROOT_DOS_PATH, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                FileOpenParams createDirParams = new FileOpenParams(TEST_DIR, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                driver.createDirectory(testSession, testConnection, createRootDirParams);
                driver.createDirectory(testSession, testConnection, createDirParams);
                
                /**
                 * Create the file we are going to use
                 */
                FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_NAME, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                testContext.firstFileHandle = driver.createFile(testSession, testConnection, createFileParams);
                assertNotNull(testContext.firstFileHandle);
                
                // now load up the node with lots of other stuff that we will test to see if it gets preserved during the
                // shuffle.
                testContext.testNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NAME);
                nodeService.addAspect(testContext.testNodeRef, ContentModel.ASPECT_VERSIONABLE, null);
                
                // test non CM namespace property
                nodeService.setProperty(testContext.testNodeRef, TransferModel.PROP_ENABLED, true);
                // test CM property not related to an aspect
                nodeService.setProperty(testContext.testNodeRef, ContentModel.PROP_ADDRESSEE, "Fred");
                
                nodeService.setProperty(testContext.testNodeRef, ContentModel.PROP_TITLE, FILE_TITLE);
                nodeService.setProperty(testContext.testNodeRef, ContentModel.PROP_DESCRIPTION, FILE_DESCRIPTION);
                
                /**
                 * MLText value - also a residual value in a non cm namespace
                 */
                MLText mltext = new MLText();
                mltext.addValue(Locale.FRENCH, "Bonjour");
                mltext.addValue(Locale.ENGLISH, "Hello");
                mltext.addValue(Locale.ITALY, "Buongiorno");
                mlAwareNodeService.setProperty(testContext.testNodeRef, RESIDUAL_MTTEXT, mltext);
                // classifiable chosen since its not related to any properties.
                nodeService.addAspect(testContext.testNodeRef, ContentModel.ASPECT_CLASSIFIABLE, null);
                //nodeService.createAssociation(testContext.testNodeRef, targetRef, assocTypeQName);
        
                return null;
            }
        };
        tran.doInTransaction(createFileCB, false, true);
        
        /**
         * Write some content to the test file
         */
        RetryingTransactionCallback writeFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                String testContent = "MS Excel 2003 shuffle test";
                byte[] testContentBytes = testContent.getBytes();
                testContext.firstFileHandle.writeFile(testContentBytes, testContentBytes.length, 0, 0);
                testContext.firstFileHandle.close();   
                
                testContext.testCreatedDate = nodeService.getProperty(testContext.testNodeRef, ContentModel.PROP_CREATED);
                
                MLText multi = (MLText)mlAwareNodeService.getProperty(testContext.testNodeRef, RESIDUAL_MTTEXT) ;
                multi.getValues();
     
     
                return null;
            }
        };
        tran.doInTransaction(writeFileCB, false, true);
        
        /**
         * b) Save the new file
         */
        RetryingTransactionCallback saveNewFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_NEW_TEMP, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                testContext.newFileHandle = driver.createFile(testSession, testConnection, createFileParams);
                assertNotNull(testContext.newFileHandle);
                String testContent = "MS Word 2003 shuffle test This is new content";
                byte[] testContentBytes = testContent.getBytes();
                testContext.newFileHandle.writeFile(testContentBytes, testContentBytes.length, 0, 0);
                testContext.newFileHandle.close();
              
                return null;
            }
        };
        tran.doInTransaction(saveNewFileCB, false, true);
        
        /**
         * rename the old file
         */
        RetryingTransactionCallback renameOldFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.renameFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME, TEST_DIR + "\\" + FILE_OLD_TEMP);
                return null;
            }
        };
        tran.doInTransaction(renameOldFileCB, false, true);
        
        RetryingTransactionCallback validateOldFileGoneCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {   
                try
                {
                    driver.deleteFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME);
                }
                catch (IOException e)
                { 
                    // expect to go here since previous step renamed the file.
                }
                
                return null;
            }
        };
        tran.doInTransaction(validateOldFileGoneCB, false, true);
        
        /**
         * Move the new file into place, stuff should get shuffled
         */
        RetryingTransactionCallback moveNewFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.renameFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NEW_TEMP, TEST_DIR + "\\" + FILE_NAME); 
                return null;
            }
        };
        
        tran.doInTransaction(moveNewFileCB, false, true);
        
        RetryingTransactionCallback validateCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
               NodeRef shuffledNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NAME);
               
               Map props = nodeService.getProperties(shuffledNodeRef);
           
               // Check trx:enabled has been shuffled.
               assertTrue("node does not contain shuffled ENABLED property", props.containsKey(TransferModel.PROP_ENABLED));
               // check my residual MLText has been transferred
               assertTrue(props.containsKey(RESIDUAL_MTTEXT));
               
               // Check the titled aspect is correct
               assertEquals("name wrong", FILE_NAME, nodeService.getProperty(shuffledNodeRef, ContentModel.PROP_NAME) );
               assertEquals("title wrong", FILE_TITLE, nodeService.getProperty(shuffledNodeRef, ContentModel.PROP_TITLE) );
               assertEquals("description wrong", FILE_DESCRIPTION, nodeService.getProperty(shuffledNodeRef, ContentModel.PROP_DESCRIPTION) );
               // commented out due to ALF-7641
               // CIFS shuffle, does not preseve MLText values.
               // Map mlProps = mlAwareNodeService.getProperties(shuffledNodeRef);
               
               // MLText multi = (MLText)mlAwareNodeService.getProperty(shuffledNodeRef, RESIDUAL_MTTEXT) ;
               // multi.getValues();
               
               // check auditable properties 
               // commented out due to ALF-7635
               // assertEquals("creation date not preserved", ((Date)testContext.testCreatedDate).getTime(), ((Date)nodeService.getProperty(shuffledNodeRef, ContentModel.PROP_CREATED)).getTime());
               
               // commented out due to ALF-7628 
               // assertEquals("ADDRESSEE PROPERTY Not copied", "Fred", nodeService.getProperty(shuffledNodeRef, ContentModel.PROP_ADDRESSEE));
               // assertTrue("CLASSIFIABLE aspect not present", nodeService.hasAspect(shuffledNodeRef, ContentModel.ASPECT_CLASSIFIABLE));
               
               // commented out due to ALF-7584.
               // assertEquals("noderef changed", testContext.testNodeRef, shuffledNodeRef);
               return null;
            }
        };
        
        tran.doInTransaction(validateCB, true, true);
        
        /**
         * Clean up just in case garbage is left from a previous run
         */
        RetryingTransactionCallback deleteOldFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.deleteFile(testSession, testConnection, TEST_DIR + "\\" + FILE_OLD_TEMP);
                return null;
            }
        };
        
        tran.doInTransaction(deleteOldFileCB, false, true);
        
    }
    /**
     * Excel 2013 With Versionable file  (MNT-13078)
     *
     * CreateFile Cherries.xlsx
     * CreateFile ~herries.tmp
     * CreateFile Cherries.xlsx~RF172f241.TMP
     * DeleteFile Cherries.xlsx~RF172f241.TMP
     * RenameFile oldName: Cherries.xls,
     *            newName: Cherries.xlsx~RF172f241.TMP
     * Delete On Close for Cherries.xlsx~RF172f241.TMP
     * RenameFile oldName: ~herries.tmp,
     *            newName: Cherries.xlsx
     *
     */
    public void testExcel2013SaveShuffle() throws Exception
    {
        logger.debug("testScenarioExcel2013SaveShuffle");
        final String FILE_NAME = "Cherries.xlsx";
        final String FILE_ORIGINAL_TITLE = "Original";
        final String FILE_UNUSED_TEMP = "Cherries.xlsx~RF172f241.TMP";
        final String FILE_USED_TEMP = "~herries.tmp";
        final String TEST_DIR = TEST_ROOT_DOS_PATH + "\\testScenarioMSExcel2013SaveShuffle";
        class TestContext
        {
            NetworkFile firstFileHandle;
            NodeRef testNodeRef;   // node ref of test.doc
        };
        final TestContext testContext = new TestContext();
        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();
        /**
         * Clean up just in case garbage is left from a previous run
         */
        RetryingTransactionCallback deleteGarbageFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.deleteFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME);
                return null;
            }
        };
        /**
         * Delete a file in the test directory
         */
        try
        {
            tran.doInTransaction(deleteGarbageFileCB);
        }
        catch (Exception e)
        {
            // expect to go here
        }
        /**
         * Create a file in the test directory
         */
        RetryingTransactionCallback createOriginalFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable {
               /**
                * Create the test directory we are going to use
                */
               FileOpenParams createRootDirParams = new FileOpenParams(TEST_ROOT_DOS_PATH, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
               FileOpenParams createDirParams = new FileOpenParams(TEST_DIR, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
               driver.createDirectory(testSession, testConnection, createRootDirParams);
               driver.createDirectory(testSession, testConnection, createDirParams);
               /**
                * Create the file we are going to use
                */
               FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_NAME, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
               testContext.firstFileHandle = driver.createFile(testSession, testConnection, createFileParams);
               assertNotNull(testContext.firstFileHandle);
               String testContent = "MS Word 2013 shuffle test. This is first file content";
               byte[] testContentBytes = testContent.getBytes();
               testContext.firstFileHandle.writeFile(testContentBytes, testContentBytes.length, 0, 0);
               testContext.firstFileHandle.close();
               // now load up the node with lots of other stuff that we will test to see if it gets preserved during the
               // shuffle.
               testContext.testNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NAME);
               nodeService.addAspect(testContext.testNodeRef, ContentModel.ASPECT_VERSIONABLE, null);
               // need to remove. Otherwise file will be deleted (not placed into archive spaces store)
               nodeService.removeAspect(testContext.testNodeRef, ContentModel.ASPECT_NO_CONTENT);
               // test non CM namespace property
               nodeService.setProperty(testContext.testNodeRef, TransferModel.PROP_ENABLED, true);
               nodeService.setProperty(testContext.testNodeRef, ContentModel.PROP_TITLE, FILE_ORIGINAL_TITLE);
               return null;
            }
        };
        tran.doInTransaction(createOriginalFileCB, false, true);
        /**
         * Create a file in the test directory
         */
        RetryingTransactionCallback createUsedTempFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                /**
                 * Create the file we are going to use
                 */
                FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_USED_TEMP, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                NetworkFile fileHandle = driver.createFile(testSession, testConnection, createFileParams);
                assertNotNull(fileHandle);
                String testContent = "MS Word 2013 shuffle test. This is used file content";
                byte[] testContentBytes = testContent.getBytes();
                fileHandle.writeFile(testContentBytes, testContentBytes.length, 0, 0);
                fileHandle.close();
                NodeRef usedRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_USED_TEMP);
                nodeService.addAspect(usedRef, ContentModel.ASPECT_VERSIONABLE, null);
                nodeService.removeAspect(usedRef, ContentModel.ASPECT_NO_CONTENT);
                nodeService.setProperty(usedRef, ContentModel.PROP_TITLE, "Used");
                return null;
            }
        };
        tran.doInTransaction(createUsedTempFileCB, false, true);
        /**
         * Create a file in the test directory
         */
        RetryingTransactionCallback createUnusedTempFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                /**
                 * Create the file we are going to use
                 */
                FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_UNUSED_TEMP, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                NetworkFile unusedFile = driver.createFile(testSession, testConnection, createFileParams);
                assertNotNull(unusedFile);
                NodeRef unusedNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_UNUSED_TEMP);
                nodeService.addAspect(unusedNodeRef, ContentModel.ASPECT_VERSIONABLE, null);
                nodeService.setProperty(unusedNodeRef, TransferModel.PROP_ENABLED, true);
                nodeService.setProperty(unusedNodeRef, ContentModel.PROP_TITLE, "Unused");
                return null;
            }
        };
        tran.doInTransaction(createUnusedTempFileCB, false, true);
        /**
         * Delete unused temporary file
         */
        RetryingTransactionCallback deleteUnusedFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                try
                {
                    driver.deleteFile(testSession, testConnection, TEST_DIR + "\\" + FILE_UNUSED_TEMP);
                }
                catch (IOException e)
                {
                    // expect to go here since previous step renamed the file.
                }
                return null;
            }
        };
        tran.doInTransaction(deleteUnusedFileCB, false, true);
        /**
         * Rename the original file to unused file
         */
        RetryingTransactionCallback renameToUnusedFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.renameFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME, TEST_DIR + "\\" + FILE_UNUSED_TEMP);
                return null;
            }
        };
        tran.doInTransaction(renameToUnusedFileCB, false, true);
        /**
         * Delete unused temporary file
         */
        tran.doInTransaction(deleteUnusedFileCB, false, true);
        /**
         * Rename the used temporary file to original file
         */
        RetryingTransactionCallback renameToUsedFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.renameFile(testSession, testConnection, TEST_DIR + "\\" + FILE_USED_TEMP, TEST_DIR + "\\" + FILE_NAME);
                return null;
            }
        };
        tran.doInTransaction(renameToUsedFileCB, false, true);
        RetryingTransactionCallback validateCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                NodeRef shuffledNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NAME);
                Map props = nodeService.getProperties(shuffledNodeRef);
                // Check trx:enabled has been shuffled.
                assertTrue("node does not contain shuffled ENABLED property", props.containsKey(TransferModel.PROP_ENABLED));
                assertTrue("node doesn't contain property 'TITLE'", props.containsKey(ContentModel.PROP_TITLE));
                assertEquals("propety 'TITLE' isn't correct", FILE_ORIGINAL_TITLE, props.get(ContentModel.PROP_TITLE));
                assertEquals("name wrong", FILE_NAME, nodeService.getProperty(shuffledNodeRef, ContentModel.PROP_NAME));
                return null;
            }
        };
        tran.doInTransaction(validateCB, true, true);
    }
    /**
     * Excel 2003 CSV file with Versionable file 
     * 
     * CreateFile csv.csv and 5EE27101 
     * Add versionable aspect 
     * RenameFile oldPath:\Espaces Utilisateurs\System\csv.csv, newPath:\Espaces\Utilisateurs\System\5EE27101 
     * CreateFile name=\Espaces Utilisateurs\System\csv.csv
     * Add content
     */
    public void testCSVExcel2003SaveShuffle() throws Exception
    {
        logger.debug("testCSVExcel2003SaveShuffle");
        final String FILE_NAME = "csv.csv";
        final String FILE_TITLE = "csv";
        final String FILE_DESCRIPTION = "This is a test document to test CIFS shuffle";
        final String FILE_TEMP = "AAAA0000";
        class TestContext
        {
            NetworkFile firstFileHandle;
            NetworkFile newFileHandle;
            NodeRef testNodeRef;
            Serializable testCreatedDate;
        }
        ;
        final TestContext testContext = new TestContext();
        final String TEST_DIR = TEST_ROOT_DOS_PATH + "\\testMSExcel2003CSVShuffle";
        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();
        /**
         * Clean up from a previous run
         */
        RetryingTransactionCallback deleteGarbageFileCB = new RetryingTransactionCallback()
        {
            @Override
            public Void execute() throws Throwable
            {
                driver.deleteFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME);
                return null;
            }
        };
        try
        {
            tran.doInTransaction(deleteGarbageFileCB);
        }
        catch (Exception e)
        {
            // expect to go here
        }
        /**
         * Create a file in the test directory
         */
        RetryingTransactionCallback createTestFileFirstTime = new RetryingTransactionCallback()
        {
            @Override
            public Void execute() throws Throwable
            {
                /**
                 * Create the test directory we are going to use
                 */
                FileOpenParams createRootDirParams = new FileOpenParams(TEST_ROOT_DOS_PATH, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                FileOpenParams createDirParams = new FileOpenParams(TEST_DIR, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                driver.createDirectory(testSession, testConnection, createRootDirParams);
                driver.createDirectory(testSession, testConnection, createDirParams);
                /**
                 * Create the file we are going to use
                 */
                FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_NAME, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                testContext.firstFileHandle = driver.createFile(testSession, testConnection, createFileParams);
                assertNotNull(testContext.firstFileHandle);
                testContext.testNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NAME);
                nodeService.setProperty(testContext.testNodeRef, ContentModel.PROP_TITLE, FILE_TITLE);
                nodeService.setProperty(testContext.testNodeRef, ContentModel.PROP_DESCRIPTION, FILE_DESCRIPTION);
                return null;
            }
        };
        tran.doInTransaction(createTestFileFirstTime, false, true);
        /**
         * Write some content to the test file. Add versionable aspect
         */
        RetryingTransactionCallback writeToTestFileAndAddVersionableAspect = new RetryingTransactionCallback()
        {
            @Override
            public Void execute() throws Throwable
            {
                String testContent = "MS Excel 2003 for CSV shuffle test";
                byte[] testContentBytes = testContent.getBytes();
                testContext.firstFileHandle.writeFile(testContentBytes, testContentBytes.length, 0, 0);
                testContext.firstFileHandle.close();
                testContext.testCreatedDate = nodeService.getProperty(testContext.testNodeRef, ContentModel.PROP_CREATED);
                nodeService.addAspect(testContext.testNodeRef, ContentModel.ASPECT_VERSIONABLE, Collections
                        . singletonMap(ContentModel.PROP_VERSION_TYPE,
                                org.alfresco.service.cmr.version.VersionType.MINOR));
                return null;
            }
        };
        tran.doInTransaction(writeToTestFileAndAddVersionableAspect, false, true);
        /**
         * rename the test file to the temp
         */
        RetryingTransactionCallback renameTestFileToTemp = new RetryingTransactionCallback()
        {
            @Override
            public Void execute() throws Throwable
            {
                driver.renameFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME, TEST_DIR + "\\" + FILE_TEMP);
                return null;
            }
        };
        tran.doInTransaction(renameTestFileToTemp, false, true);
        /**
         * create the test file one more
         */
        RetryingTransactionCallback createTestFileOneMore = new RetryingTransactionCallback()
        {
            @Override
            public Void execute() throws Throwable
            {
                FileOpenParams params = new FileOpenParams(TEST_DIR + "\\" + FILE_NAME, FileAction.TruncateExisting, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                NetworkFile file = driver.createFile(testSession, testConnection, params);
                driver.closeFile(testSession, testConnection, file);
                return null;
            }
        };
        tran.doInTransaction(createTestFileOneMore, false, true);
        
      /**
      * Write the new content
      */
     RetryingTransactionCallback writeUpdate = new RetryingTransactionCallback()
     {
         @Override
         public Void execute() throws Throwable
         {
             FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_NAME, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
             testContext.newFileHandle = driver.openFile(testSession, testConnection, createFileParams);
             assertNotNull(testContext.newFileHandle);
             String testContent = "MS Word 2003 for CSV shuffle test This is new content";
             byte[] testContentBytes = testContent.getBytes();
             testContext.newFileHandle.writeFile(testContentBytes, testContentBytes.length, 0, 0);
             testContext.newFileHandle.close();
             return null;
         }
     };
     tran.doInTransaction(writeUpdate, false, true);
        // Check results
        RetryingTransactionCallback validate = new RetryingTransactionCallback()
        {
            @Override
            public Void execute() throws Throwable
            {
                NodeRef shuffledNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NAME);
                // Check versionable aspect, version label and nodeRef
                assertTrue("VERSIONABLE aspect not present", nodeService.hasAspect(shuffledNodeRef, ContentModel.ASPECT_VERSIONABLE));
                assertEquals("nodeRef changed", testContext.testNodeRef, shuffledNodeRef);
    
                // Check the titled aspect is correct
                assertEquals("name wrong", FILE_NAME, nodeService.getProperty(shuffledNodeRef, ContentModel.PROP_NAME));
                assertEquals("title wrong", FILE_TITLE, nodeService.getProperty(shuffledNodeRef, ContentModel.PROP_TITLE));
                assertEquals("description wrong", FILE_DESCRIPTION, nodeService.getProperty(shuffledNodeRef, ContentModel.PROP_DESCRIPTION));
                return null;
            }
        };
        tran.doInTransaction(validate, true, true);
        /**
         * Clean up just in case garbage is left from a previous run
         */
        RetryingTransactionCallback deleteTestFile = new RetryingTransactionCallback()
        {
            @Override
            public Void execute() throws Throwable
            {
                driver.deleteFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME);
                return null;
            }
        };
        tran.doInTransaction(deleteTestFile, false, true);
    }
    /**
     * Simulates a SaveAs from Word2003
     * 1. Create new document SAVEAS.DOC, file did not exist
     * 2. Create -WRDnnnn.TMP file, where 'nnnn' is a 4 digit sequence to make the name unique
     * 3. Rename SAVEAS.DOC to Backup of SAVEAS.wbk
     * 4. Rename -WRDnnnn.TMP to SAVEAS.DOC 
     */
    public void testScenarioMSWord2003SaveAsShuffle() throws Exception
    {
        logger.debug("testScenarioMSWord2003SaveShuffle");
        final String FILE_NAME = "SAVEAS.DOC";
        final String FILE_OLD_TEMP = "SAVEAS.wbk";
        final String FILE_NEW_TEMP = "~WRD0002.TMP";
        
        class TestContext
        {
            NetworkFile firstFileHandle;
        };
        
        final TestContext testContext = new TestContext();
        
        final String TEST_DIR = TEST_ROOT_DOS_PATH + "\\testScenarioMSWord2003SaveAsShuffle";
        
        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();        
        /**
         * Clean up just in case garbage is left from a previous run
         */
        RetryingTransactionCallback deleteGarbageFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.deleteFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME);
                return null;
            }
        };
     
        /**
         * Create a file in the test directory
         */    
        
        try
        {
            tran.doInTransaction(deleteGarbageFileCB);
        }
        catch (Exception e)
        {
            // expect to go here
        }
        
        logger.debug("a) create new file");
        RetryingTransactionCallback createFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
  
                /**
                 * Create the test directory we are going to use 
                 */
                FileOpenParams createRootDirParams = new FileOpenParams(TEST_ROOT_DOS_PATH, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                FileOpenParams createDirParams = new FileOpenParams(TEST_DIR, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                driver.createDirectory(testSession, testConnection, createRootDirParams);
                driver.createDirectory(testSession, testConnection, createDirParams);
                
                /**
                 * Create the file we are going to use
                 */
                FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_NAME, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                testContext.firstFileHandle = driver.createFile(testSession, testConnection, createFileParams);
                assertNotNull(testContext.firstFileHandle);
                        
                return null;
            }
        };
        tran.doInTransaction(createFileCB, false, true);
             
        /**
         * b) Save the new file
         * Write ContentDiskDriverTest3.doc to the test file,
         */
        logger.debug("b) move new file into place");
        RetryingTransactionCallback writeFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_NEW_TEMP, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
                testContext.firstFileHandle = driver.createFile(testSession, testConnection, createFileParams);    
         
                ClassPathResource fileResource = new ClassPathResource("filesys/ContentDiskDriverTest3.doc");
                assertNotNull("unable to find test resource filesys/ContentDiskDriverTest3.doc", fileResource);
                byte[] buffer= new byte[1000];
                InputStream is = fileResource.getInputStream();
                try
                {
                    long offset = 0;
                    int i = is.read(buffer, 0, buffer.length);
                    while(i > 0)
                    {
                        testContext.firstFileHandle.writeFile(buffer, i, 0, offset);
                        offset += i;
                        i = is.read(buffer, 0, buffer.length);
                    }                 
                }
                finally
                {
                    is.close();
                }
            
                driver.closeFile(testSession, testConnection, testContext.firstFileHandle);   
                    
                return null;
            }
        };
        tran.doInTransaction(writeFileCB, false, true);
        
        /**
         * c) rename the old file
         */
        logger.debug("c) rename old file");
        RetryingTransactionCallback renameOldFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.renameFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME, TEST_DIR + "\\" + FILE_OLD_TEMP);
                return null;
            }
        };
        tran.doInTransaction(renameOldFileCB, false, true);
           
        /**
         * d) Move the new file into place, stuff should get shuffled
         */
        logger.debug("d) move new file into place");
        RetryingTransactionCallback moveNewFileCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
                driver.renameFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NEW_TEMP, TEST_DIR + "\\" + FILE_NAME); 
                return null;
            }
        };
        
        tran.doInTransaction(moveNewFileCB, false, true);
        
        logger.debug("e) validate results");
        /**
         * Now validate everything is correct
         */
        RetryingTransactionCallback