/* ======================================================================
The Bodington System Software License, Version 1.0
 
Copyright (c) 2001 The University of Leeds.  All rights reserved.
 
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
 
1.  Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
 
2.  Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
 
3.  The end-user documentation included with the redistribution, if any,
must include the following acknowledgement:  "This product includes
software developed by the University of Leeds
(http://www.bodington.org/)."  Alternately, this acknowledgement may
appear in the software itself, if and wherever such third-party
acknowledgements normally appear.
 
4.  The names "Bodington", "Nathan Bodington", "Bodington System",
"Bodington Open Source Project", and "The University of Leeds" must not be
used to endorse or promote products derived from this software without
prior written permission. For written permission, please contact
d.gardner@leeds.ac.uk.
 
5.  The name "Bodington" may not appear in the name of products derived
from this software without prior written permission of the University of
Leeds.
 
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO,  TITLE,  THE IMPLIED WARRANTIES
OF QUALITY  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
EVENT SHALL THE UNIVERSITY OF LEEDS OR ITS CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
=========================================================
 
This software was originally created by the University of Leeds and may contain voluntary
contributions from others.  For more information on the Bodington Open Source Project, please
see http://bodington.org/
 
====================================================================== */

package org.bodington.server;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.zip.ZipFile;

import org.bodington.database.PrimaryKey;
import org.bodington.server.realm.AclEntry;
import org.bodington.server.realm.Group;
import org.bodington.server.realm.Permission;
import org.bodington.server.resources.UploadedFileSummary;
import org.bodington.util.FileMover;

public class UploadedFileSessionTest extends BuildingServerTest
{
    public static File createTempDir(String prefix, String suffix)
        throws IOException
    {
        File tempDir = File.createTempFile("test",null);
        tempDir.delete();
        tempDir.mkdir();
        return tempDir;
    }
    
    public static void cleanTempDir(File file)
        throws IOException
    {
        if (file.isDirectory())
        {
            File files[] = file.listFiles();
            for (int count = 0; count < files.length; count++)
                cleanTempDir(files[count]);
        }
        file.delete();
    }

    UploadedFileSession session;
    File publishDir;
    File generatedDir;
    
    public void setUp() throws Exception
    {
        super.setUp();
        
        publishDir = createTempDir("test", null);
        
        BuildingContext.getContext().getProperties().setProperty(
            "webpublish.filestore", publishDir.getAbsolutePath());
        
        generatedDir = createTempDir("test", null);
        
        BuildingContext.getContext().getProperties().setProperty(
            "filegeneration.filestore", generatedDir.getAbsolutePath());
                
        // Need to set to user so permission checking works.
        BuildingContext.getContext().setUser(user);
        
        Group group = new Group();
        group.setDescription("Description");
        group.setName("group");
        group.setResourceId(resource.getPrimaryKey());
        group.save();
        group.addMember(user);
        group.save();
        
        AclEntry entry = new AclEntry();
        entry.setGroup(group);
        entry.addPermission(Permission.SYSADMIN);
        entry.addPermission(Permission.UPLOAD);
        entry.setAcl(acl);
        entry.save();
        
        acl.addEntry(entry);
        acl.save();
        BuildingSession buildingSession = new BuildingSessionImpl();
        buildingSession.init(user.getPrimaryKey(), resource.getPrimaryKey());
        session = new UploadedFileSessionImpl(buildingSession);
        
    }
    
    public void tearDown() throws Exception
    {
        super.tearDown();
        cleanTempDir(publishDir);
    }
    
    /*
     * Test method for 'org.bodington.server.UploadedFileSession.copyFile(String, String, String)'
     */
    public void testCopyFile()
    {

    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.transferFile(String, String, String)'
     */
    public void testTransferFile() throws Exception
    {
        // Find the test file
        URL url = getClass().getResource("text.txt");
        assertNotNull(url);
 
        // Must copy the file into a temp location as transfer file deletes
        // the orginal.
        File source = new File(url.getFile());
        File temp = File.createTempFile("test", null);
        temp.delete();

        FileMover.copyFile(source, temp);
        UploadedFileSummary summary = session.transferFile(temp
            .getAbsolutePath(), "/file.txt", "text/plain");
        assertEquals(session.getFileSummary("/file.txt"), summary);
        
        FileMover.copyFile(source, temp);
        session.transferFile(temp.getAbsolutePath(), "/folder/file.txt", "text/plain");
        assertNotNull(session.getFileSummary("/folder/file.txt"));
        
        FileMover.copyFile(source, temp);
        session.transferFile(temp.getAbsolutePath(), "/1/2/3/4/5/file.txt", "text/plain");
        assertNotNull(session.getFileSummary("/1/2/3/4/5/file.txt"));
        assertNotNull(session.getFileSummary("/1/2/3/"));
        assertNull(session.getFileSummary("/1/2/3/4/5/6/"));
        
        FileMover.copyFile(source, temp);
        try
        {
            session.transferFile(temp.getAbsolutePath(), "/file.txt/file.txt", "text/plain");
            fail("Exception Expected: Can't create a file as a child of a file");
        }
        catch (BuildingServerException bse)
        {}
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.transferZipFile(ZipFile, String)'
     */
    public void testTransferZipFile() throws Exception
    {
        // test.zip contains file1.txt and file2.txt
        URL url = getClass().getResource("test.zip");
        assertNotNull(url);
        
        // Must copy the file into a temp location as transfer file deletes
        // the orginal.
        File source = new File(url.getFile());
        File temp = File.createTempFile("zip", null);
        temp.delete();

        ZipFile zip;
        
        // Unpacking at the root.
        FileMover.copyFile(source, temp);
        zip = new ZipFile(temp);
        session.transferZipFile(zip, "/");
        assertNotNull(session.getFileSummary("/file1.txt"));

        // Unpacking ontop.
        FileMover.copyFile(source, temp);
        zip = new ZipFile(temp);
        session.transferZipFile(zip, "/");
        assertNotNull(session.getFileSummary("/file1.txt"));
        
        // Now try with a file containsing directories.
        // test.zip contains file1.txt and file2.txt
        url = getClass().getResource("testdirs.zip");
        assertNotNull(url);
        source = new File(url.getFile());
        
        FileMover.copyFile(source, temp);
        zip = new ZipFile(temp);
        session.transferZipFile(zip, "/");
        assertNotNull(session.getFileSummary("/dir1/file.txt"));
        assertNotNull(session.getFileSummary("/dir2/file.txt"));
        
        
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.createFolder(String)'
     */
    public void testCreateFolder() throws Exception
    {
        // Try creating the root folder.
        UploadedFileSummary root = session.createFolder("/");
        assertNotNull(root);
        assertEquals(session.getFileSummary((String)null), root);
        
        // Try creating root folder again.
        root = session.createFolder("/");
        assertEquals(session.getFileSummary((String)null), root);
        
        // Check that null is the same as "/"
        assertEquals(root, session.createFolder(null));
        
        // Try to create a child folder.
        UploadedFileSummary child = session.createFolder("/child");
        assertNotNull(child);
        assertEquals(session.getFileSummary("/child"), child);
        
        // Delete the child folder and then see if it reapears.
        session.deleteFile("/child");
        assertEquals(child, session.createFolder("/child"));
        assertEquals(child, session.getFileSummary("/child"));
        
        // Check that we can't replace a file with a folder
        assertNotNull(session.copyFile(getClass().getResource("text.txt")
            .getFile(), "/file", "text/plain"));
        
        // Check that we don't need to leading slash
        assertNotNull(session.createFolder("noslash"));
        assertNotNull(session.getFileSummary("/noslash"));
        
        assertNotNull(session.createFolder("/extraslash/"));
        assertNotNull(session.getFileSummary("/extraslash"));
        
        try
        {
            session.createFolder("/file");
            fail("Expected Exception: A file exists here");
        }
        catch (BuildingServerException bse)
        {}
        
        // Check we can't create folders inside files.
        try
        {
            session.createFolder("/file/folder");
            fail("Expected Exception: You can't create folders in files.");
        }
        catch (BuildingServerException bse)
        {}
        
        // Check we can't create folders inside deleted folders.
        session.deleteFile("/child");
        try
        {
            session.createFolder("/child/folder");
            fail("Expected Exception: You can't create folders in deleted folders.");
        }
        catch (BuildingServerException bse)
        {}

    }
    
    public void testCreateFolderWithoutRoot() throws Exception
    {
        // Check that the root folder is automatically created.
        session.createFolder("/folder");
        assertTrue(session.getFileSummary("/").isFolder());
        assertTrue(session.getFileSummary("/folder").isFolder());
    }
    
    public void testCreateFolderWithoutRootNested() throws Exception
    {
        // Make sure that code for automatically creating the root folder doesn't 
        // create nested folders as well.
        try
        {
            session.createFolder("/nested/folder/creation");
            fail("Expected Exception: Nested folders shouldn't be created automatically.");
        }
        catch (Exception e)
        {}
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.createFile(String, long, String)'
     */
    public void testCreateFile()
    {
        // Current unimplemented
        try
        {
            session.createFile("/file", 100, "text/plain");
            fail("Need to create a test.");
        }
        catch (Exception e)
        {}
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.checkCreateFolder(String)'
     */
    public void testCheckCreateFolder()
    {
        // Current unimplemented
        try
        {
            session.checkCreateFolder("/folder");
            fail("Need to create a test.");
        }
        catch (Exception e)
        {}
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.checkCreateFile(String, long)'
     */
    public void testCheckCreateFile()
    {
        // Current unimplemented
        try
        {
            session.checkCreateFile("/file", 100);
            fail("Need to create a test.");
        }
        catch (Exception e)
        {}
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.deleteFile(String)'
     */
    public void testDeleteFile() throws Exception
    {
        // Create the root.
        assertNotNull(session.createFolder("/"));
        
        // Try to delete a folder.
        assertNotNull(session.createFolder("/folder"));
        session.deleteFile("/folder");
        
        // Try to delete an already deleted folder.
        session.deleteFile("/folder");
        
        // Try to delete an file.
        assertNotNull(session.copyFile(getClass().getResource("text.txt")
            .getFile(), "/file", "text/plain"));
        session.deleteFile("/file");
        
        // Try to delete a file again.
        session.deleteFile("/file");
        
        // Try deleting a folder containing a file.
        assertNotNull(session.createFolder("/folder"));
        assertNotNull(session.copyFile(getClass().getResource("text.txt")
            .getFile(), "/folder/file", "text/plain"));
        session.deleteFile("/folder");
        
        // Try deleting the root folder.
        session.deleteFile("/");
        
        // Delete a file that doesn't exist.
        session.deleteFile("/does not exist");
        
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.renameFile(String, String)'
     */
    public void testRenameFile() throws Exception
    {
        
        // Sucessful rename.
        assertNotNull(session.createFolder("/"));
        assertNotNull(session.createFolder("/folder"));
        session.renameFile("/folder", "newfolder");
        assertNull(session.getFileSummary("/folder"));
        assertNotNull(session.getFileSummary("/newfolder"));
        
        // And back.
        session.renameFile("/newfolder", "folder");
        assertNull(session.getFileSummary("/newfolder"));
        assertNotNull(session.getFileSummary("/folder"));
        
        // Renaming non-existant.
        try
        {
            session.renameFile("/does not exist", "not here");
            fail("Excepted Exception: Source for rename does not exist");    
        }
        catch (Exception e)
        {}
        
        // Renaming to a file containing "/"
        try
        {
            session.renameFile("/folder", "/folder/new");
            fail("Expected Exception: Can't use rename to move files");
        }
        catch (Exception e)
        {}
        
        // Renaming to an existing file
        session.createFolder("/otherfolder");
        try
        {
            session.renameFile("/folder", "otherfolder");
            fail("Expected Exception; Rename shouldn't replace existing folders");
        }
        catch (Exception e)
        {}
        
        // Shouldn't be able to rename the root folder.
        try
        {
            session.renameFile("/", "broken");
            fail("Expected Exception: You can't rename the root folder.");
        }
        catch (Exception e)
        {}

    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.undeleteFile(String, boolean)'
     */
    public void testUndeleteFile() throws Exception
    {
        // Check that undeleting works.
        session.createFolder("/");
        session.createFolder("/folder");
        session.deleteFile("/folder");
        assertTrue(session.getFileSummary("/folder").isDeleted());
        session.undeleteFile("/folder", false);
        assertFalse(session.getFileSummary("/folder").isDeleted());
        
        session.undeleteFile("/does not exist", false);
        
        // Test recursive undeleting
        session.deleteFile("/");
        assertTrue(session.getFileSummary("/folder").isDeleted());
        session.undeleteFile("/", false);
        assertTrue(session.getFileSummary("/folder").isDeleted());
        session.undeleteFile("/", true);
        assertFalse(session.getFileSummary("/folder").isDeleted());
        
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.writeToFile(String, long, byte[], int)'
     */
    public void testWriteToFile()
    {
        // Current unimplemented
        try
        {
            session.writeToFile("/", 0, null, 0);
            fail("Need to create a test.");
        }
        catch (Exception e)
        {}
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.compareWithFile(String, long, long, int)'
     */
    public void testCompareWithFile()
    {
        // Current unimplemented
        try
        {
            session.compareWithFile("/", 0, 0, 0);
            fail("Need to create a test.");
        }
        catch (Exception e)
        {}

    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.readFromFile(String, long, byte[])'
     */
    public void testReadFromFile()
    {
        // Current unimplemented
        try
        {
            session.readFromFile("/", 0, null);
            fail("Need to create a test.");
        }
        catch (Exception e)
        {}
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.getRealURL(PrimaryKey)'
     */
    public void testGetRealURL()
    {

    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.getPublishedURL(PrimaryKey)'
     */
    public void testGetPublishedURL()
    {

    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.getFileMimeType(String)'
     */
    public void testGetFileMimeType()
    {

    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.setFileMimeType(String, String)'
     */
    public void testSetFileMimeType()
    {

    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.getFileSummary(String)'
     */
    public void testGetFileSummaryString() throws Exception
    {
        UploadedFileSummary summary = session.getFileSummary((String)null);
        assertNull(summary);
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.getFileSummary(String[])'
     */
    public void testGetFileSummaryStringArray() throws Exception
    {
        UploadedFileSummary summary = session.getFileSummary((String[])null);
        assertNull(summary);
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.getFileSummary(PrimaryKey)'
     */
    public void testGetFileSummaryPrimaryKey() throws Exception
    {
        UploadedFileSummary summary = session.getFileSummary((PrimaryKey)null);
        assertNull(summary);
    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.getFile(PrimaryKey)'
     */
    public void testGetFile() throws Exception
    {
        // Check we can get the root directory
        assertNotNull(session.createFolder("/"));
        File file = session.getFile(session.getFileSummary("/").getPrimaryKey());
        assertTrue(file.exists());
        assertTrue(file.isDirectory());

    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.getFileAndDescendentSummaries(String, boolean)'
     */
    public void testGetFileAndDescendentSummaries()
    {

    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.getFileAndAncestorSummaries(String)'
     */
    public void testGetFileAndAncestorSummaries()
    {

    }

    /*
     * Test method for 'org.bodington.server.UploadedFileSession.getFileAndDescendentSummaryTree(String, boolean)'
     */
    public void testGetFileAndDescendentSummaryTree()
    {

    }

}