net.nharyes.drivecopy.biz.wfm.FileStorageWorkflowManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for net.nharyes.drivecopy.biz.wfm.FileStorageWorkflowManagerImpl.java

Source

/**
 * Copyright 2012-2013 Luca Zanconato
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.nharyes.drivecopy.biz.wfm;

import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;

import net.nharyes.drivecopy.biz.bo.DirectoryBO;
import net.nharyes.drivecopy.biz.bo.EntryBO;
import net.nharyes.drivecopy.biz.bo.FileBO;
import net.nharyes.drivecopy.biz.bo.TokenBO;
import net.nharyes.drivecopy.biz.exc.WorkflowManagerException;
import net.nharyes.drivecopy.srvc.DriveSdo;
import net.nharyes.drivecopy.srvc.exc.ItemNotFoundException;
import net.nharyes.drivecopy.srvc.exc.SdoException;

import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import com.google.inject.Inject;
import com.google.inject.Singleton;

@Singleton
public class FileStorageWorkflowManagerImpl extends BaseWorkflowManager<FileBO>
        implements FileStorageWorkflowManager {

    // Drive SDO
    private DriveSdo driveSdo;

    // Directory Compressor WFM
    private DirectoryCompressorWorkflowManager directoryCompressorWorkflowManager;

    // Token WFM
    private TokenWorkflowManager tokenWorkflowManager;

    @Inject
    public FileStorageWorkflowManagerImpl(DriveSdo driveSdo,
            DirectoryCompressorWorkflowManager directoryCompressorWorkflowManager,
            TokenWorkflowManager tokenWorkflowManager) {

        this.driveSdo = driveSdo;
        this.directoryCompressorWorkflowManager = directoryCompressorWorkflowManager;
        this.tokenWorkflowManager = tokenWorkflowManager;
    }

    @Override
    public FileBO handleWorkflow(FileBO businessObject, int action) throws WorkflowManagerException {

        switch (action) {

        case ACTION_UPLOAD:
            return upload(businessObject);
        case ACTION_DOWNLOAD:
            return download(businessObject);
        case ACTION_REPLACE:
            return replace(businessObject);
        default:
            throw new WorkflowManagerException("Action not found");
        }
    }

    private TokenBO getToken() throws WorkflowManagerException {

        return tokenWorkflowManager.handleWorkflow(new TokenBO(), TokenWorkflowManager.ACTION_GET);
    }

    private String[] extractFolders(String filePath) {

        // extract folders
        String[] folders = filePath.split("/");
        if (folders.length > 1) {

            // remove file name from folders
            String[] nf = new String[folders.length - 1];
            System.arraycopy(folders, 0, nf, 0, nf.length);
            folders = nf;

        } else
            folders = null;

        return folders;
    }

    private String extractFileName(String filePath) {

        // return only file name
        if (filePath.contains("/"))
            return filePath.substring(filePath.lastIndexOf("/") + 1);

        return filePath;
    }

    private FileBO upsert(FileBO file, boolean upload) throws WorkflowManagerException {

        try {

            // get token
            TokenBO token = getToken();

            // log action
            if (upload)
                logger.info(String.format("Upload '%s' to entry '%s'", file.getFile().getAbsolutePath(),
                        file.getName()));
            else
                logger.info(String.format("Replace entry '%s' with '%s'", file.getName(),
                        file.getFile().getAbsolutePath()));

            // check force option
            if (upload && file.isForce())
                logger.warning("force option ignored");

            EntryBO entry = null;
            String parentId = null;
            try {

                // process folders and get parent ID
                parentId = driveSdo.getLastFolderId(token, extractFolders(file.getName()), file.isCreateFolders());

                // search entry
                entry = driveSdo.searchEntry(token, extractFileName(file.getName()), parentId);

                if (upload) {

                    // entry already exists
                    throw new SdoException(String.format("Entry with name '%s' already exists", file.getName()));
                }

            } catch (ItemNotFoundException ex) {

                // check force option
                if (!upload && !file.isForce()) {

                    // re-throw exception
                    throw ex;

                } else if (!upload && file.isForce()) {

                    // switch to upload mode
                    upload = true;
                    logger.info("Switched to upload mode");
                }

                if (upload) {

                    // compose BO
                    entry = new EntryBO();
                    entry.setName(extractFileName(file.getName()));
                }
            }

            // set file property
            entry.setFile(file.getFile());

            // set MIME type property
            entry.setMimeType(file.getMimeType());

            // check skip revision option
            if (file.isSkipRevision() && upload)
                logger.warning("skip revision option ignored");
            else
                entry.setSkipRevision(file.isSkipRevision());

            // check directory
            DirectoryBO dirBO = new DirectoryBO();
            if (file.isDirectory()) {

                // compress directory
                logger.info(String.format("Compress directory with level '%d'", file.getCompressionLevel()));
                dirBO.setFile(file.getFile());
                dirBO.setLevel(file.getCompressionLevel());
                dirBO = directoryCompressorWorkflowManager.handleWorkflow(dirBO,
                        DirectoryCompressorWorkflowManager.ACTION_COMPRESS);

                // replace file
                entry.setFile(dirBO.getFile());

                // in case set ZIP MIME type
                if (entry.getMimeType() == null)
                    entry.setMimeType("application/zip");

            } else {

                // in case set generic MIME type
                if (entry.getMimeType() == null)
                    entry.setMimeType("application/octet-stream");
            }

            // upload/replace entry
            logger.info(String.format("MIME type of the entry: %s", entry.getMimeType()));
            if (upload)
                entry = driveSdo.uploadEntry(token, entry, parentId);
            else
                entry = driveSdo.updateEntry(token, entry);

            // in case check MD5 of the replaced entry
            if (file.isCheckMd5()) {

                // calculate MD5 of the local file/directory
                logger.info("calculate the MD5 summary of the file...");
                byte[] digest = Files.hash(entry.getFile(), Hashing.md5()).asBytes();
                String sDigest = new BigInteger(1, digest).toString(16);
                logger.fine(String.format("digest of the file: %s", sDigest));
                logger.fine(String.format("digest of the entry: %s", entry.getMd5Sum()));

                // compare digests
                if (!sDigest.equalsIgnoreCase(entry.getMd5Sum()))
                    throw new WorkflowManagerException("wrong digest!");
                logger.info("digests comparison OK");
            }

            // in case delete temporary file
            if (file.isDirectory()) {

                logger.fine("Delete temporary file");
                entry.getFile().delete();
            }

            // in case delete file or directory
            if (file.isDeleteAfter()) {

                logger.info("Process file(s) for deletion...");
                processFileForDeletion(file.getFile(), dirBO.getNotCompressed());
            }

            // return updated entry
            FileBO fBO = new FileBO();
            fBO.setFile(entry.getFile());
            fBO.setName(entry.getName());
            return fBO;

        } catch (SdoException ex) {

            // re-throw exception
            throw new WorkflowManagerException(ex.getMessage(), ex);

        } catch (IOException ex) {

            // re-throw exception
            throw new WorkflowManagerException(ex.getMessage(), ex);
        }
    }

    private FileBO upload(FileBO file) throws WorkflowManagerException {

        return upsert(file, true);
    }

    private FileBO download(FileBO file) throws WorkflowManagerException {

        try {

            // get token
            TokenBO token = getToken();

            // log action
            logger.info(
                    String.format("Download entry '%s' to '%s'", file.getName(), file.getFile().getAbsolutePath()));

            // check delete after option
            if (file.isDeleteAfter())
                logger.warning("Delete option ignored");

            // check MIME type option
            if (file.getMimeType() != null)
                logger.warning("MIME type option ignored");

            // check skip revision option
            if (file.isSkipRevision())
                logger.warning("Skip revision option ignored");

            // check create folders option
            if (file.isCreateFolders())
                logger.warning("Create folders option ignored");

            // process folders and get parent ID
            String parentId = driveSdo.getLastFolderId(token, extractFolders(file.getName()), false);

            // search entry
            EntryBO entry = driveSdo.searchEntry(token, extractFileName(file.getName()), parentId);

            // check directory
            if (file.isDirectory()) {

                // create temporary file
                File tempFile = File.createTempFile("drivecopy" + System.currentTimeMillis(), "temp");
                logger.fine(String.format("Created temporary file '%s'", tempFile.getAbsolutePath()));

                // set file property
                entry.setFile(tempFile);

            } else {

                // set file property
                entry.setFile(file.getFile());
            }

            // download entry
            entry = driveSdo.downloadEntry(token, entry);

            // in case check MD5 of the downloaded entry
            if (file.isCheckMd5()) {

                // calculate MD5 of the local file/directory
                logger.info("calculate the MD5 summary of the file...");
                byte[] digest = Files.hash(entry.getFile(), Hashing.md5()).asBytes();
                String sDigest = new BigInteger(1, digest).toString(16);
                logger.fine(String.format("digest of the file: %s", sDigest));
                logger.fine(String.format("digest of the entry: %s", entry.getMd5Sum()));

                // compare digests
                if (!sDigest.equalsIgnoreCase(entry.getMd5Sum()))
                    throw new WorkflowManagerException("wrong digest!");
                logger.info("digests comparison OK");
            }

            // check directory
            if (file.isDirectory()) {

                logger.info("Decompress file");

                // decompress file
                DirectoryBO dirBO = new DirectoryBO();
                dirBO.setFile(entry.getFile());
                dirBO.setDestinationDirectory(file.getFile());
                dirBO = directoryCompressorWorkflowManager.handleWorkflow(dirBO,
                        DirectoryCompressorWorkflowManager.ACTION_DECOMPRESS);

                // delete downloaded file
                logger.fine("Delete downloaded file");
                entry.getFile().delete();

                // return decompressed directory
                FileBO fBO = new FileBO();
                fBO.setFile(dirBO.getFile());
                fBO.setName(entry.getName());
                return fBO;
            }

            // return downloaded entry
            FileBO fBO = new FileBO();
            fBO.setFile(entry.getFile());
            fBO.setName(entry.getName());
            return fBO;

        } catch (SdoException ex) {

            // re-throw exception
            throw new WorkflowManagerException(ex.getMessage(), ex);

        } catch (IOException ex) {

            // re-throw exception
            throw new WorkflowManagerException(ex.getMessage(), ex);
        }
    }

    private FileBO replace(FileBO file) throws WorkflowManagerException {

        return upsert(file, false);
    }

    private void processFileForDeletion(File f, List<File> notCompressed) throws IOException {

        // check if file not compressed or cannot be read or written
        if (notCompressed.contains(f) || !f.canRead() || !f.canWrite()) {

            // notify UI
            logger.warning(String.format("File '%s' not deleted", f.getAbsolutePath()));

            return;
        }

        // check if file is directory
        if (f.isDirectory()) {

            // process all files contained
            logger.fine(String.format("Process directory '%s' for deletion", f.getAbsolutePath()));
            File[] files = f.listFiles();
            for (File fl : files)
                processFileForDeletion(fl, notCompressed);
        }

        // delete file/directory
        logger.fine(String.format("Delete file/directory '%s'", f.getAbsolutePath()));
        f.delete();
    }
}