All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apacheextras.camel.component.jcifs.SmbOperations Maven / Gradle / Ivy

/**************************************************************************************
 https://camel-extra.github.io

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public License
 as published by the Free Software Foundation; either version 3
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Lesser General Public License for more details.


 You should have received a copy of the GNU Lesser General Public
 License along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301, USA.

 http://www.gnu.org/licenses/lgpl-3.0-standalone.html
 ***************************************************************************************/
package org.apacheextras.camel.component.jcifs;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.camel.Exchange;
import org.apache.camel.component.file.FileComponent;
import org.apache.camel.component.file.GenericFile;
import org.apache.camel.component.file.GenericFileEndpoint;
import org.apache.camel.component.file.GenericFileExist;
import org.apache.camel.component.file.GenericFileOperationFailedException;
import org.apache.camel.component.file.GenericFileOperations;
import org.apache.camel.util.ExchangeHelper;
import org.apache.camel.util.FileUtil;
import org.apache.camel.util.IOHelper;
import org.apache.camel.util.ObjectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SmbOperations implements GenericFileOperations {
    private static final Logger LOGGER = LoggerFactory.getLogger(SmbOperations.class);

    private GenericFileEndpoint endpoint;
    private SmbClient client;

    public SmbOperations(SmbClient smbClient) {
        this.client = smbClient;
    }

    @Override
    public void setEndpoint(GenericFileEndpoint endpoint) {
        this.endpoint = endpoint;
    }

    @Override
    public boolean deleteFile(String name) {
        try {
            login();
            return client.delete(getPath(name));

        } catch (Exception e) {
            throw new GenericFileOperationFailedException("Could not delete file", e);
        }
    }

    @Override
    public boolean existsFile(String name) {
        try {
            login();
            return client.isExist(getPath(name));
        } catch (Exception e) {
            throw new GenericFileOperationFailedException("Could not determine if file exists", e);
        }
    }

    @Override
    public boolean renameFile(String from, String to) {
        final String fromPath = getPath(from);
        final String toPath = getPath(to);
        try {
            login();
            return client.rename(fromPath, toPath);
        } catch (final Exception e) {
            throw new GenericFileOperationFailedException("Could not rename file", e);
        }
    }

    @Override
    public boolean buildDirectory(String directory, boolean absolute) {
        try {
            login();
            return client.createDirs(getPath(directory));
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean retrieveFile(String name, Exchange exchange, long size) {
        if (ObjectHelper.isNotEmpty(endpoint.getLocalWorkDirectory())) {
            return retrieveFileToFileInLocalWorkDirectory(name, exchange);
        }
        return retrieveFileToStreamInBody(name, exchange);
    }

    @SuppressWarnings("unchecked")
    private boolean retrieveFileToFileInLocalWorkDirectory(String name, Exchange exchange) {
        File temp;

        File local = new File(endpoint.getLocalWorkDirectory());
        local.mkdirs();
        OutputStream os;
        GenericFile file = (GenericFile)exchange.getProperty(FileComponent.FILE_EXCHANGE_FILE);
        ObjectHelper.notNull(file, "Exchange should have the " + FileComponent.FILE_EXCHANGE_FILE + " set");

        // use relative filename in local work directory
        String relativeName = file.getRelativeFilePath();
        temp = new File(local, relativeName + ".inprogress");
        local = new File(local, relativeName);

        // delete any existing files
        if (temp.exists() && (!FileUtil.deleteFile(temp))) {
            throw new GenericFileOperationFailedException("Cannot delete existing local work file: " + temp);
        }
        if (local.exists() && (!FileUtil.deleteFile(local))) {
            throw new GenericFileOperationFailedException("Cannot delete existing local work file: " + local);
        }
        // create new temp local work file
        try {
            if (!temp.createNewFile()) {
                throw new GenericFileOperationFailedException("Cannot create new local work file: " + temp);
            }
        } catch (IOException e1) {
            throw new GenericFileOperationFailedException("Cannot create new local work file: " + temp, e1);
        }

        // store content as a file in the local work directory in the temp
        // handle
        try {
            os = new FileOutputStream(temp);
        } catch (FileNotFoundException e1) {
            throw new GenericFileOperationFailedException("File not found: " + temp, e1);
        }

        // set header with the path to the local work file
        exchange.getIn().setHeader(Exchange.FILE_LOCAL_WORK_PATH, local.getPath());

        boolean result;

        try {
            // store the java.io.File handle as the body
            file.setBody(local);
            login();
            result = client.retrieveFile(getPath(name), os);
        } catch (IOException e) {
            throw new GenericFileOperationFailedException("Cannot retrieve file: " + name, e);
        } catch (Exception e) {
            throw new GenericFileOperationFailedException("Cannot retrieve file: " + name, e);
        } finally {
            IOHelper.close(os, "retrieve: " + name);
        }

        try {
            if (!FileUtil.renameFile(temp, local, true)) {
                throw new GenericFileOperationFailedException("Cannot rename local work file from: " + temp + " to: " + local);
            }
        } catch (IOException e) {
            throw new GenericFileOperationFailedException("Cannot rename local work file from: " + temp + " to: " + local, e);
        }

        return result;
    }

    @SuppressWarnings("unchecked")
    private boolean retrieveFileToStreamInBody(String name, Exchange exchange) {
        OutputStream os = null;
        boolean result;
        try {
            os = new ByteArrayOutputStream();
            GenericFile target = (GenericFile)exchange.getProperty(FileComponent.FILE_EXCHANGE_FILE);
            ObjectHelper.notNull(target, "Exchange should have the " + FileComponent.FILE_EXCHANGE_FILE + " set");
            target.setBody(os);

            // use input stream which works with Apache SSHD used for testing
            login();
            result = client.retrieveFile(getPath(name), os);

        } catch (IOException e) {
            throw new GenericFileOperationFailedException("Cannot retrieve file: " + name, e);
        } catch (Exception e) {
            throw new GenericFileOperationFailedException("Cannot retrieve file: " + name, e);
        } finally {
            IOHelper.close(os, "retrieve: " + name);
        }

        return result;
    }

    private void doMoveExistingFile(String fileName) throws GenericFileOperationFailedException {
        // need to evaluate using a dummy and simulate the file first, to have
        // access to all the file attributes
        // create a dummy exchange as Exchange is needed for expression
        // evaluation
        // we support only the following 3 tokens.
        Exchange dummy = endpoint.createExchange();
        String parent = FileUtil.onlyPath(fileName);
        String onlyName = FileUtil.stripPath(fileName);
        dummy.getIn().setHeader(Exchange.FILE_NAME, fileName);
        dummy.getIn().setHeader(Exchange.FILE_NAME_ONLY, onlyName);
        dummy.getIn().setHeader(Exchange.FILE_PARENT, parent);

        String to = endpoint.getMoveExisting().evaluate(dummy, String.class);
        // we must normalize it (to avoid having both \ and / in the name which
        // confuses java.io.File)
        to = FileUtil.normalizePath(to);
        if (ObjectHelper.isEmpty(to)) {
            throw new GenericFileOperationFailedException("moveExisting evaluated as empty String, cannot move existing file: " + fileName);
        }

        // ensure any paths is created before we rename as the renamed file may
        // be in a different path (which may be non exiting)
        // use java.io.File to compute the file path
        File toFile = new File(to);
        String directory = toFile.getParent();
        boolean absolute = FileUtil.isAbsolute(toFile);
        if (directory != null) {
            if (!buildDirectory(directory, absolute)) {
                LOGGER.debug("Cannot build directory [{}] (could be because of denied permissions)", directory);
            }
        }

        // deal if there already exists a file
        if (existsFile(to)) {
            if (endpoint.isEagerDeleteTargetFile()) {
                LOGGER.trace("Deleting existing file: {}", to);
                if (!deleteFile(to)) {
                    throw new GenericFileOperationFailedException("Cannot delete file: " + to);
                }
            } else {
                throw new GenericFileOperationFailedException("Cannot moved existing file from: " + fileName + " to: " + to + " as there already exists a file: " + to);
            }
        }

        LOGGER.trace("Moving existing file: {} to: {}", fileName, to);
        if (!renameFile(fileName, to)) {
            throw new GenericFileOperationFailedException("Cannot rename file from: " + fileName + " to: " + to);
        }
    }

    @Override
    public boolean storeFile(String name, Exchange exchange, long size){
        boolean append = false;
        // if an existing file already exists what should we do?
        if (existsFile(name)) {
            if (endpoint.getFileExist() == GenericFileExist.Ignore) {
                // ignore but indicate that the file was written
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("An existing file already exists: " + name + ". Ignore and do not override it.");
                }
                return true;
            } else if (endpoint.getFileExist() == GenericFileExist.Fail) {
                throw new GenericFileOperationFailedException("File already exist: " + name + ". Cannot write new file.");
            } else if (endpoint.getFileExist() == GenericFileExist.Move) {
                // move any existing file first
                doMoveExistingFile(name);
            } else if (endpoint.isEagerDeleteTargetFile() && endpoint.getFileExist() == GenericFileExist.Override) {
                // we override the target so we do this by deleting it so the
                // temp file can be renamed later
                // with success as the existing target file have been deleted
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("Eagerly deleting existing file: " + name);
                }
                if (!deleteFile(name)) {
                    throw new GenericFileOperationFailedException("Cannot delete file: " + name);
                }
            } else if (endpoint.getFileExist() == GenericFileExist.Append) {
                append = true;
            }
        }

        String storeName = getPath(name);

        InputStream is = null;
        try {
            is = ExchangeHelper.getMandatoryInBody(exchange, InputStream.class);

            login();
            client.storeFile(storeName, is, append, lastModifiedDate(exchange));
            return true;
        } catch (Exception e) {
            throw new GenericFileOperationFailedException("Cannot store file " + storeName, e);
        } finally {
            IOHelper.close(is, "store: " + storeName);
        }
    }

    private Long lastModifiedDate(Exchange exchange) {
        Long last = null;
        if (endpoint.isKeepLastModified()) {
            Date date = exchange.getIn().getHeader(Exchange.FILE_LAST_MODIFIED, Date.class);
            if (date != null) {
                last = date.getTime();
            } else {
                // fallback and try a long
                last = exchange.getIn().getHeader(Exchange.FILE_LAST_MODIFIED, Long.class);
            }
        }
        return last;
    }

    @Override
    public String getCurrentDirectory() {
        return null;
    }

    @Override
    public void changeCurrentDirectory(String path) {
    }

    @Override
    public void changeToParentDirectory() {
    }

    @Override
    public List listFiles() {
        return null;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List listFiles(String path) {
        String listPath = getDirPath(path);
        List files = new ArrayList();
        try {
            login();
            for (Object f : client.listFiles(listPath)) {
                files.add((SmbFile)f);
            }
        } catch (Exception e) {
            throw new GenericFileOperationFailedException("Could not get files " + e.getMessage(), e);
        }
        return files;
    }

    public void login() {
        String domain = ((SmbConfiguration)endpoint.getConfiguration()).getDomain();
        String username = ((SmbConfiguration)endpoint.getConfiguration()).getUsername();
        String password = ((SmbConfiguration)endpoint.getConfiguration()).getPassword();

        client.login(domain, username, password);
    }

    private String getPath(String pathEnd) {
        String path = ((SmbConfiguration)endpoint.getConfiguration()).getSmbHostPath() + pathEnd;
        return path.replace('\\', '/');
    }

    private String getDirPath(String pathEnd) {
        String path = ((SmbConfiguration)endpoint.getConfiguration()).getSmbHostPath() + pathEnd;
        if (!path.endsWith("/")) {
            path = path + "/";
        }
        return path.replace('\\', '/');
    }

    @Override
    public void releaseRetrievedFileResources(Exchange exchange) {
        // Right now do nothing
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy