org.obiba.opal.web.FilesResourceTest.java Source code

Java tutorial

Introduction

Here is the source code for org.obiba.opal.web.FilesResourceTest.java

Source

/*
 * Copyright (c) 2012 OBiBa. All rights reserved.
 *
 * This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.obiba.opal.web;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.vfs2.FileContent;
import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileType;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.obiba.opal.core.runtime.OpalRuntime;
import org.obiba.opal.core.service.security.SubjectAclService;
import org.obiba.opal.fs.OpalFileSystem;
import org.obiba.opal.fs.impl.DefaultOpalFileSystem;
import org.obiba.opal.web.model.Opal.FileDto;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.fest.assertions.api.Assertions.assertThat;

@SuppressWarnings({ "OverlyLongMethod", "PMD.NcssMethodCount" })
public class FilesResourceTest {

    private OpalRuntime opalRuntimeMock;

    private SubjectAclService subjectAclServiceMock;

    private OpalFileSystem fileSystem;

    private FilesResource filesResource;

    private FileObject fileObjectMock;

    private FileItem fileItemMock;

    private UriInfo uriInfoMock;

    /**
     * Delete these files in tearDown().
     */
    private final Collection<String> filesCreatedByTest = new ArrayList<>();

    @Before
    public void setUp() throws URISyntaxException {
        opalRuntimeMock = createMock(OpalRuntime.class);
        subjectAclServiceMock = createMock(SubjectAclService.class);

        String rootDir = getClass().getResource("/test-file-system").toURI().toString();
        File emptyDir = new File(rootDir.replace("file:", ""), "folder4/folder41");
        if (!emptyDir.exists()) {
            assertThat(emptyDir.mkdirs()).isTrue();
        }
        fileSystem = new DefaultOpalFileSystem(rootDir);
        filesResource = new FilesResource();
        filesResource.setOpalRuntime(opalRuntimeMock);
        filesResource.setSubjectAclService(subjectAclServiceMock);

        fileItemMock = createMock(FileItem.class);
        fileObjectMock = createMock(FileObject.class);

        uriInfoMock = createMock(UriInfo.class);
    }

    @After
    public void tearDown() throws FileSystemException {
        // Delete any files created by the test.
        for (String filePath : filesCreatedByTest) {
            FileObject file = fileSystem.getRoot().resolveFile(filePath);
            if (file.exists()) {
                file.delete();
            }
        }
    }

    @Test
    public void testGetFileSystem() throws FileSystemException {

        expect(opalRuntimeMock.getFileSystem()).andReturn(fileSystem).once();

        replay(opalRuntimeMock);

        FileSystemResource fsResource = new FileSystemResource();
        fsResource.setOpalRuntime(opalRuntimeMock);
        FileDto rootFileDto = fsResource.getFileSystem();

        assertThat(rootFileDto.getName()).isEqualTo("root");
        assertThat(rootFileDto.getType()).isEqualTo(FileDto.FileType.FOLDER);
        assertThat(rootFileDto.getPath()).isEqualTo("/");

    }

    @Test
    @Ignore
    public void verifyThatAllFilesAndFoldersInDtoStructureExistInFileSystem() throws FileSystemException {
        expect(opalRuntimeMock.getFileSystem()).andReturn(fileSystem).once();

        replay(opalRuntimeMock);

        FileSystemResource fsResource = new FileSystemResource();
        fsResource.setOpalRuntime(opalRuntimeMock);

        FileDto rootFileDto = fsResource.getFileSystem();

        int childrenCounter = 0;
        childrenCounter = verifyThatChildrenExistInFileSystem(rootFileDto, childrenCounter);

        // File count in Dto structure should be the same as file count in file system.
        assertThat(childrenCounter).isEqualTo(20);

        verify(opalRuntimeMock);
    }

    private int verifyThatChildrenExistInFileSystem(FileDto folder, int childrenCounter)
            throws FileSystemException {
        FileObject correspondingFileObj;
        int counter = childrenCounter;
        for (FileDto child : folder.getChildrenList()) {
            counter++;
            correspondingFileObj = fileSystem.getRoot().resolveFile(child.getPath());
            assertThat(correspondingFileObj.exists()).isTrue();
            if (child.getType() == FileDto.FileType.FOLDER) {
                counter = verifyThatChildrenExistInFileSystem(child, childrenCounter);
            }
        }
        return counter;
    }

    @Ignore("SecurityManager dependency not satisfied")
    @Test
    public void testGetFoldersDetailsInFileSystem() throws FileSystemException {
        expect(opalRuntimeMock.getFileSystem()).andReturn(fileSystem).atLeastOnce();

        replay(opalRuntimeMock);

        checkGetFileDetailsResponse("/", "folder1", "folder2", "folder3", "folder4", "folder5", "file2.txt",
                "folder11", "file11.txt", "file21.txt", "folder31", "folder41", "file41.txt", "file42.txt",
                "file43.txt", "file51.txt");
        checkGetFileDetailsResponse("/folder1/folder11", "folder111", "file111.txt", "file1111.txt",
                "file1112.txt");
        checkGetFileDetailsResponse("/folder1/folder11/folder111", "file1111.txt", "file1112.txt");
        checkGetFileDetailsResponse("/folder2", "file21.txt");
        checkGetFileDetailsResponse("/folder3", "folder31", "file311.txt");
        checkGetFileDetailsResponse("/folder4", "folder41", "file41.txt", "file42.txt", "file43.txt");
        checkGetFileDetailsResponse("/folder5", "file51.txt");

        verify(opalRuntimeMock);

    }

    private void checkGetFileDetailsResponse(String path, String... expectedFolderContentArray)
            throws FileSystemException {

        Set<String> expectedFolderContent = new HashSet<>(Arrays.asList(expectedFolderContentArray));
        Response response = filesResource.getFileDetails(path);

        // Make sure response is OK
        assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode());

        FileDto folder = (FileDto) response.getEntity();
        List<FileDto> folderContent = folder.getChildrenList();

        // Check folder content recursively two levels down.
        checkFolderContent(expectedFolderContent, folderContent, 2);

        assertThat(expectedFolderContent).isEmpty();
    }

    private void checkFolderContent(Set<String> expectedFolderContent, Iterable<FileDto> folderContent, int level) {
        // Make sure folder content is as expected.
        for (FileDto oneFileOrFolder : folderContent) {
            assertThat(expectedFolderContent).contains(oneFileOrFolder.getName());
            expectedFolderContent.remove(oneFileOrFolder.getName());
            if (level > 0 && oneFileOrFolder.getChildrenCount() > 0) {
                checkFolderContent(expectedFolderContent, oneFileOrFolder.getChildrenList(), level - 1);
            }
        }
    }

    @Ignore("SecurityManager dependency not satisfied")
    @Test
    public void testGetFile_GetCompressedFolderFromFileSystem() throws IOException {
        expect(opalRuntimeMock.getFileSystem()).andReturn(fileSystem).atLeastOnce();
        replay(opalRuntimeMock);

        checkCompressedFolder("/folder1", "folder1", "folder1/folder11", "folder1/file11.txt",
                "folder1/folder11/folder111", "folder1/folder11/file111.txt",
                "folder1/folder11/folder111/file1111.txt", "folder1/folder11/folder111/file1112.txt");
        checkCompressedFolder("/folder2", "folder2", "folder2/file21.txt");
        checkCompressedFolder("/folder3", "folder3", "folder3/folder31", "folder3/folder31/file311.txt");
        checkCompressedFolder("/folder4", "folder4", "folder4/folder41", "folder4/file41.txt", "folder4/file42.txt",
                "folder4/file43.txt");
        checkCompressedFolder("/folder5", "folder5", "folder5/file51.txt");
        checkCompressedFolder("/", "/", "folder1", "folder1/folder11", "folder1/file11.txt",
                "folder1/folder11/folder111", "folder1/folder11/file111.txt",
                "folder1/folder11/folder111/file1111.txt", "folder1/folder11/folder111/file1112.txt", "folder2",
                "folder2/file21.txt", "folder3", "folder3/folder31", "folder3/folder31/file311.txt", "folder4",
                "folder4/folder41", "folder4/file41.txt", "folder4/file42.txt", "folder4/file43.txt", "folder5",
                "folder5/file51.txt", "file2.txt");

        verify(opalRuntimeMock);

    }

    @SuppressWarnings("unchecked")
    private void checkCompressedFolder(String folderPath, String... expectedFolderContentArray) throws IOException {
        Response response = filesResource.getFile(folderPath, null);
        ZipFile zipfile = new ZipFile(((File) response.getEntity()).getPath());

        // Check that all folders and files exist in the compressed archive that represents the folder.
        for (String anExpectedFolderContentArray : expectedFolderContentArray) {
            assertThat(zipfile.getEntry(anExpectedFolderContentArray)).isNotNull();
        }

        Enumeration<ZipEntry> zipEnum = (Enumeration<ZipEntry>) zipfile.entries();
        int count = 0;

        while (zipEnum.hasMoreElements()) {
            zipEnum.nextElement();
            count++;
        }

        // Make sure that they are no unexpected files in the compressed archive.
        assertThat(expectedFolderContentArray.length).isEqualTo(count);

        zipfile.close();
    }

    @Test
    public void testGetPathThatDoesNotExist() throws FileSystemException {
        expect(opalRuntimeMock.getFileSystem()).andReturn(fileSystem).once();

        replay(opalRuntimeMock);

        Response response = filesResource.getFileDetails("/folder1/folder2");
        assertThat(response.getStatus()).isEqualTo(Status.NOT_FOUND.getStatusCode());

        verify(opalRuntimeMock);

    }

    @Test
    @Ignore
    public void testUploadFileToFileSystem() throws FileUploadException, IOException, URISyntaxException {
        expect(opalRuntimeMock.getFileSystem()).andReturn(fileSystem).once();
        expect(fileItemMock.getName()).andReturn("fileToUpload.txt").atLeastOnce();
        expect(fileItemMock.getInputStream())
                .andReturn(getClass().getResourceAsStream("/files-to-upload/fileToUpload.txt")).once();
        expect(uriInfoMock.getBaseUriBuilder()).andReturn(UriBuilder.fromPath("/"));

        FilesResource fileResource = new FilesResource() {
            @Override
            protected FileItem getUploadedFile(HttpServletRequest request) throws FileUploadException {
                return fileItemMock;
            }
        };
        fileResource.setOpalRuntime(opalRuntimeMock);
        fileResource.setSubjectAclService(subjectAclServiceMock);

        replay(opalRuntimeMock, fileItemMock, uriInfoMock);

        // Upload the file.
        String destinationPath = "/folder1/folder11/folder111";
        Response response = fileResource.uploadFile(destinationPath, uriInfoMock, null);
        filesCreatedByTest.add(destinationPath);

        // Verify that the service response is CREATED.
        assertThat(response.getStatus()).isEqualTo(Status.CREATED.getStatusCode());

        verify(opalRuntimeMock, fileItemMock, uriInfoMock);

        // Verify that the file was uploaded at the right path in the file system.
        assertThat(fileSystem.getRoot().resolveFile("/folder1/folder11/folder111/fileToUpload.txt").exists())
                .isTrue();
        // clean up
        fileSystem.getRoot().resolveFile("/folder1/folder11/folder111/fileToUpload.txt").delete();
    }

    @Test
    public void testUploadFileNoContentSubmitted()
            throws FileSystemException, FileUploadException, URISyntaxException {

        expect(opalRuntimeMock.getFileSystem()).andReturn(fileSystem).once();

        replay(opalRuntimeMock);

        FilesResource fileResource = new FilesResource() {
            @Override
            protected FileItem getUploadedFile(HttpServletRequest request) throws FileUploadException {
                return null;
            }
        };
        fileResource.setOpalRuntime(opalRuntimeMock);
        fileResource.setSubjectAclService(subjectAclServiceMock);

        Response response = fileResource.uploadFile("/", uriInfoMock, null);
        assertThat(response.getStatus()).isEqualTo(Status.BAD_REQUEST.getStatusCode());

        verify(opalRuntimeMock);

    }

    @Test
    public void testUploadFile_ReturnsNotFoundResponseWhenUploadDestinationDoesNotExist()
            throws IOException, FileUploadException, URISyntaxException {
        expect(opalRuntimeMock.getFileSystem()).andReturn(fileSystem).once();

        FilesResource fileResource = new FilesResource() {
            @Override
            protected FileItem getUploadedFile(HttpServletRequest request) throws FileUploadException {
                return fileItemMock;
            }
        };
        fileResource.setOpalRuntime(opalRuntimeMock);
        filesResource.setSubjectAclService(subjectAclServiceMock);

        replay(opalRuntimeMock, fileItemMock, uriInfoMock);

        // Upload the file.
        String destinationPath = "/folder1/folder11/folder111/patate";
        Response response = fileResource.uploadFile(destinationPath, uriInfoMock, null);
        filesCreatedByTest.add(destinationPath);

        // Verify that the service response is CREATED.
        assertThat(response.getStatus()).isEqualTo(Status.NOT_FOUND.getStatusCode());

        verify(opalRuntimeMock, fileItemMock, uriInfoMock);
    }

    @Test
    public void testDeleteFile_FileDoesNotExist() throws FileSystemException {
        expect(opalRuntimeMock.getFileSystem()).andReturn(fileSystem).once();

        replay(opalRuntimeMock);

        Response response = filesResource.deleteFile("/folder1/folder2/filethatdoesnotexist.txt");
        assertThat(response.getStatus()).isEqualTo(Status.NOT_FOUND.getStatusCode());

        verify(opalRuntimeMock);
    }

    @Test
    @Ignore
    public void testDeleteFile_CannotDeleteFolderWithContent() throws FileSystemException {
        expect(opalRuntimeMock.getFileSystem()).andReturn(fileSystem).once();

        replay(opalRuntimeMock);

        Response response = filesResource.deleteFile("/folder1");
        assertThat(response.getStatus()).isEqualTo(Status.FORBIDDEN.getStatusCode());
        assertThat(response.getEntity()).isEqualTo("cannotDeleteNotEmptyFolder");
        verify(opalRuntimeMock);
    }

    @Test
    @Ignore
    public void testDeleteFile_CannotDeleteReadOnlyFile() throws FileSystemException {
        expect(fileObjectMock.getType()).andReturn(FileType.FILE).atLeastOnce();
        expect(fileObjectMock.exists()).andReturn(true).atLeastOnce();
        expect(fileObjectMock.isWriteable()).andReturn(false).atLeastOnce();

        replay(fileObjectMock);

        Response response = getFileResource().deleteFile("path");
        assertThat(response.getStatus()).isEqualTo(Status.FORBIDDEN.getStatusCode());
        assertThat(response.getEntity()).isEqualTo("cannotDeleteReadOnlyFile");
        verify(fileObjectMock);
    }

    @Test
    public void testDeleteFile_FileDeletedSuccessfully() throws FileSystemException {
        expect(fileObjectMock.getType()).andReturn(FileType.FILE).atLeastOnce();
        expect(fileObjectMock.exists()).andReturn(true).atLeastOnce();
        expect(fileObjectMock.isWriteable()).andReturn(true).atLeastOnce();
        expect(fileObjectMock.delete()).andReturn(true).atLeastOnce();

        replay(fileObjectMock);

        Response response = getFileResource().deleteFile("path");
        assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode());

        verify(fileObjectMock);

    }

    @Test
    public void testDeleteFile_CouldNotDeleteFile() throws FileSystemException {
        expect(fileObjectMock.getType()).andReturn(FileType.FILE).atLeastOnce();
        expect(fileObjectMock.exists()).andReturn(true).atLeastOnce();
        expect(fileObjectMock.isWriteable()).andReturn(true).atLeastOnce();
        expect(fileObjectMock.delete()).andThrow(new FileSystemException("test")).atLeastOnce();

        replay(fileObjectMock);

        Response response = getFileResource().deleteFile("path");
        assertThat(response.getStatus()).isEqualTo(Status.INTERNAL_SERVER_ERROR.getStatusCode());
        assertThat(response.getEntity()).isEqualTo("couldNotDeleteFileError");
        verify(fileObjectMock);
    }

    private FilesResource getFileResource() {
        FilesResource resource = new FilesResource() {
            @Override
            protected FileObject resolveFileInFileSystem(String path) throws FileSystemException {
                return fileObjectMock;
            }
        };
        resource.setOpalRuntime(opalRuntimeMock);
        resource.setSubjectAclService(subjectAclServiceMock);
        return resource;
    }

    @Test
    public void testCreateFolder_CannotCreateFolderPathAlreadyExist()
            throws FileSystemException, URISyntaxException {
        expect(fileObjectMock.getType()).andReturn(FileType.FOLDER).atLeastOnce();
        expect(fileObjectMock.exists()).andReturn(true).atLeastOnce();
        expect(fileObjectMock.resolveFile("folder11"))
                .andReturn(fileSystem.getRoot().resolveFile("/folder1/folder11")).atLeastOnce();

        replay(fileObjectMock);

        Response response = getFileResource().createFolder("folder1", "folder11", uriInfoMock);
        assertThat(response.getStatus()).isEqualTo(Status.FORBIDDEN.getStatusCode());
        assertThat(response.getEntity()).isEqualTo("cannotCreateFolderPathAlreadyExist");
        verify(fileObjectMock);
    }

    @Test
    public void testCreateFolder_CannotCreateFolderParentIsReadOnly()
            throws FileSystemException, URISyntaxException {
        expect(fileObjectMock.getType()).andReturn(FileType.FOLDER).atLeastOnce();
        expect(fileObjectMock.exists()).andReturn(true).atLeastOnce();
        FileObject childFolderMock = createMock(FileObject.class);
        expect(childFolderMock.exists()).andReturn(false).atLeastOnce();
        FileObject parentFolderMock = createMock(FileObject.class);
        expect(childFolderMock.getParent()).andReturn(parentFolderMock).atLeastOnce();
        expect(parentFolderMock.isWriteable()).andReturn(false).atLeastOnce();
        expect(fileObjectMock.resolveFile("folder")).andReturn(childFolderMock).atLeastOnce();

        replay(fileObjectMock, parentFolderMock, childFolderMock);

        Response response = getFileResource().createFolder("folder1", "folder", uriInfoMock);
        assertThat(response.getStatus()).isEqualTo(Status.FORBIDDEN.getStatusCode());
        assertThat(response.getEntity()).isEqualTo("cannotCreateFolderParentIsReadOnly");
        verify(fileObjectMock, parentFolderMock, childFolderMock);
    }

    @Test
    public void testCreateFolder_FolderCreatedSuccessfully() throws FileSystemException, URISyntaxException {
        expect(fileObjectMock.getType()).andReturn(FileType.FOLDER).atLeastOnce();
        expect(fileObjectMock.exists()).andReturn(true).atLeastOnce();

        FileObject childFolderMock = createMock(FileObject.class);

        FileName fileNameMock = createMock(FileName.class);
        expect(fileNameMock.getBaseName()).andReturn("folder").atLeastOnce();
        expect(fileNameMock.getPath()).andReturn("folder1/folder").atLeastOnce();

        expect(childFolderMock.getName()).andReturn(fileNameMock).atLeastOnce();
        expect(childFolderMock.exists()).andReturn(false).atLeastOnce();

        FileContent mockContent = createMock(FileContent.class);
        expect(childFolderMock.getContent()).andReturn(mockContent).atLeastOnce();
        expect(mockContent.getLastModifiedTime()).andReturn((long) 1).atLeastOnce();

        childFolderMock.createFolder();
        FileObject parentFolderMock = createMock(FileObject.class);
        expect(childFolderMock.getParent()).andReturn(parentFolderMock).atLeastOnce();
        expect(childFolderMock.isReadable()).andReturn(true).atLeastOnce();
        expect(childFolderMock.isWriteable()).andReturn(true).atLeastOnce();
        expect(parentFolderMock.isWriteable()).andReturn(true).atLeastOnce();
        expect(fileObjectMock.resolveFile("folder")).andReturn(childFolderMock).atLeastOnce();
        expect(uriInfoMock.getBaseUriBuilder()).andReturn(UriBuilder.fromPath("/"));

        replay(fileObjectMock, uriInfoMock, parentFolderMock, childFolderMock, fileNameMock, mockContent);

        Response response = getFileResource().createFolder("folder1", "folder", uriInfoMock);
        assertThat(response.getStatus()).isEqualTo(Status.CREATED.getStatusCode());
        verify(fileObjectMock, uriInfoMock, parentFolderMock, childFolderMock, fileNameMock, mockContent);
    }

    @Test
    public void testCharsetsAvailable() throws Exception {
        Response charSets = filesResource.getAvailableCharsets();
        assertThat(charSets.getEntity().toString()).contains("UTF-8");
    }
}