() {
            @Override
            public Void execute() throws Throwable
            {
                
                NodeRef companyHome = repositoryHelper.getCompanyHome();
                NodeRef newNode = nodeService.getChildByName(companyHome, ContentModel.ASSOC_CONTAINS, "testCreateFile.new");
                assertNotNull("can't find new node", newNode);
                nodeService.deleteNode(newNode);
                return null;
            }
        };
        tran.doInTransaction(deleteNodeCB, false, true);
        
        try
        {
            driver.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 = driver.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 = driver.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);
                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();
                }
            
                testContext.firstFileHandle.close();   
                    
                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));
             
                // 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);
        
        
        /**
         * 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();
                }
            
                testContext.secondFileHandle.close();   
                    
                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 = driver.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
    
    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 ContentDiskDriver deviceInterface = (ContentDiskDriver) 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());
            }
        }
    }
    /**
     * 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();
                }
            
                testContext.firstFileHandle.close();   
                    
                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 validateCB = new RetryingTransactionCallback() {
            @Override
            public Void execute() throws Throwable
            {
               NodeRef shuffledNodeRef = driver.getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NAME);
               
               Map props = nodeService.getProperties(shuffledNodeRef);
               
               ContentData data = (ContentData)props.get(ContentModel.PROP_CONTENT);
               assertEquals("size is wrong", 26112, data.getSize());
               assertEquals("mimeType is wrong", "application/msword",data.getMimetype());
           
               return null;
            }
        };
        
        tran.doInTransaction(validateCB, true, true);
        
    }
    
    /**
     * Test server
     */
    public class TestServer extends NetworkFileServer
    {
        
        public TestServer(String proto, ServerConfiguration config)
        {
            super(proto, config);
            // TODO Auto-generated constructor stub
        }
        @Override
        public void startServer()
        {
                       
        }
        @Override
        public void shutdownServer(boolean immediate)
        {
            
        }
        
        public TreeConnection getTreeConnection(SharedDevice share) 
        {
            return new TreeConnection(share);
        }
    }
    
    /**
     * TestSrvSession
     */
    private class TestSrvSession extends SrvSession
    {
        public TestSrvSession(int sessId, NetworkServer srv, String proto,
                String remName)
        {
            super(sessId, srv, proto, remName);
        }
        @Override
        public InetAddress getRemoteAddress()
        {
            return null;
        }
        @Override
        public boolean useCaseSensitiveSearch()
        {
            return false;
        }
    }
}