fr.acxio.tools.agia.io.AbstractFileOperations.java Source code

Java tutorial

Introduction

Here is the source code for fr.acxio.tools.agia.io.AbstractFileOperations.java

Source

package fr.acxio.tools.agia.io;

/*
 * Copyright 2014 Acxio
 * 
 * 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.
 */

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFileFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.core.io.Resource;

/**
 * <p>Abstract files manipulation utilities.</p>
 * <p>The source resources must be provided by the subclass.</p>
 * <p>The destination of a copy or move operation must be a single resource.
 * This resource can be built by a {@code ResourceFactory}.</p>
 * <p>The destination is built for each source: it can be a single folder or
 * different filenames calculated from a complex expression.</p>
 * <p>Each source resource and the current StepExecution are sent in the
 * evaluation context of the destination factory.</p>
 * <p>These objects can be used to calculate a complex path. For example:</p>
 * 
 * <pre>
 * ${config.destdir}/@{#in.STEP_EXEC.jobExecution.jobId}/@{#in.SOURCE.filename}
 * </pre>
 * <p>
 * In this expression, the base path is read from a properties file, the folder
 * just under the base path is named from the current job instance ID, and the
 * source filename is used as the destination filename.
 * </p>
 * <p>A subclass may provide a default destination Resource in the case of the
 * destination ResourceFactory is null.</p>
 * 
 * @author pcollardez
 *
 */
public abstract class AbstractFileOperations {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractFileOperations.class);

    private static final String SAME_RELATIVE_PATH = "/.";

    public enum Operation {
        COPY, MOVE, REMOVE
    }

    protected Operation operation;
    protected ResourceFactory destinationFactory;
    protected boolean preserveAttributes = false;
    protected boolean recursive = false;

    public Operation getOperation() {
        return operation;
    }

    public void setOperation(Operation sOperation) {
        operation = sOperation;
    }

    public void setDestinationFactory(ResourceFactory sDestinationFactory) {
        destinationFactory = sDestinationFactory;
    }

    public boolean isPreserveAttributes() {
        return preserveAttributes;
    }

    public void setPreserveAttributes(boolean sPreserveAttributes) {
        preserveAttributes = sPreserveAttributes;
    }

    public boolean isRecursive() {
        return recursive;
    }

    public void setRecursive(boolean sRecursive) {
        recursive = sRecursive;
    }

    protected void moveFile(Resource sOriginFile, Resource sDestinationFile) throws IOException {
        File aOrigineFile = sOriginFile.getFile();
        if (aOrigineFile.isFile()) {
            if (!isDirectory(sDestinationFile)) {
                FileUtils.moveFile(aOrigineFile, sDestinationFile.getFile());
            } else {
                FileUtils.moveFileToDirectory(aOrigineFile, sDestinationFile.getFile(), true);
            }
        } else {
            FileUtils.moveDirectoryToDirectory(aOrigineFile, sDestinationFile.getFile(), true);
        }
    }

    protected void copyFile(Resource sOriginFile, Resource sDestinationFile) throws IOException {
        File aOrigineFile = sOriginFile.getFile();
        if (aOrigineFile.isFile()) {
            if (!isDirectory(sDestinationFile)) {
                FileUtils.copyFile(aOrigineFile, sDestinationFile.getFile(), preserveAttributes);
            } else {
                FileUtils.copyFileToDirectory(aOrigineFile, sDestinationFile.getFile(), preserveAttributes);
            }
        } else {
            if (recursive) {
                FileUtils.copyDirectory(aOrigineFile, sDestinationFile.getFile(), preserveAttributes);
            } else {
                FileUtils.copyDirectory(aOrigineFile, sDestinationFile.getFile(), FileFileFilter.FILE,
                        preserveAttributes);
            }
        }
    }

    protected void removeFile(Resource sOriginFile) throws IOException {
        FileUtils.forceDelete(sOriginFile.getFile());
    }

    protected boolean isDirectory(Resource sResource) throws IOException {
        if (sResource.exists()) {
            return sResource.getFile().isDirectory();
        } else {
            // Dirty trick to tell if the resource is a directory or not when it does not exist yet
            return sResource.createRelative(SAME_RELATIVE_PATH).getFile().getCanonicalPath()
                    .equals(sResource.getFile().getCanonicalPath());
        }
    }

    protected List<String> doOperation(Resource aSourceResource, Map<String, Object> aDestinationParams,
            StepContribution sContribution, StepExecution sStepExecution)
            throws IOException, ResourceCreationException, FileOperationException {

        List<String> aDestinationFilesList = new ArrayList<String>();

        File aOriginFile = aSourceResource.getFile();
        if (aOriginFile.exists()) {
            if (sContribution != null) {
                sContribution.incrementReadCount();
            }

            if (operation == Operation.REMOVE) {

                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info("Deleting : {}", aOriginFile.getAbsolutePath());
                }

                removeFile(aSourceResource);
            } else {
                Resource aDestination = getDefaultDestination();
                if (destinationFactory != null) {
                    aDestinationParams.put(ResourceFactoryConstants.PARAM_SOURCE, aSourceResource);
                    aDestinationParams.put(ResourceFactoryConstants.PARAM_STEP_EXEC, sStepExecution);
                    aDestination = destinationFactory.getResource(aDestinationParams);
                }
                if ((aDestination != null) && (aDestination.getFile() != null)) {
                    File aDestinationFile = aDestination.getFile();
                    if (operation == Operation.COPY) {

                        if (LOGGER.isInfoEnabled()) {
                            LOGGER.info("Copying : {} => {}", aOriginFile.getAbsolutePath(),
                                    aDestinationFile.getAbsolutePath());
                        }

                        copyFile(aSourceResource, aDestination);
                    } else if (operation == Operation.MOVE) {

                        if (LOGGER.isInfoEnabled()) {
                            LOGGER.info("Moving : {} => {}", aOriginFile.getAbsolutePath(),
                                    aDestinationFile.getAbsolutePath());
                        }

                        moveFile(aSourceResource, aDestination);
                    } else {
                        throw new FileOperationException("Unknown operation");
                    }
                } else {
                    throw new FileOperationException("No destination specified");
                }
                aDestinationFilesList.add(aDestination.getFile().getCanonicalPath());
            }

            if (sContribution != null) {
                sContribution.incrementWriteCount(1);
            }
        } else {
            throw new FileOperationException("File not found: " + aOriginFile);
        }

        return aDestinationFilesList;
    }

    protected abstract Resource getDefaultDestination();
}