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

org.nuiton.eugene.writer.FileGrabberFromClassPath Maven / Gradle / Ivy

There is a newer version: 3.0-beta-2
Show newest version
package org.nuiton.eugene.writer;

/*
 * #%L
 * EUGene :: EUGene Core
 * %%
 * Copyright (C) 2004 - 2017 Code Lutin, Ultreia.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 General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import io.ultreia.java4all.lang.ClassLoaders;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.plexus.util.FileUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created on 5/24/15.
 *
 * @author Tony Chemit - [email protected]
 * @since 3.0
 */
public class FileGrabberFromClassPath implements FileGrabber {

    /** Logger. */
    private static final Log log = LogFactory.getLog(FileGrabberFromClassPath.class);

    private final ChainedFileWriterConfiguration configuration;

    public FileGrabberFromClassPath(ChainedFileWriterConfiguration configuration) {
        this.configuration = configuration;
    }

    @Override
    public void addFilesToTreate(File extractDirectory,
                                 String inputDirectory,
                                 Set includePatterns,
                                 ChainedFileWriterData result) throws IOException {

        Map> filesByRoot = result.getFilesByRoot();
        Map> resourcesByFile = result.getResourcesByFile();

        // final input directory to use

        File realInputDirectory;

        // use the extracted path as input directory, otherwise there
        // will have a problem : the incoming inputPath will not be
        // an ancestor of his resources, so prefer to use the extracted
        // path which fix this problem.
        String inputPath = inputDirectory;
        if (inputPath.equals("/")) {
            realInputDirectory = extractDirectory;
        } else {
            realInputDirectory = new File(extractDirectory, inputPath.substring(1));
        }

        List newUrls = getFiles(inputDirectory, includePatterns);

        List files = filesByRoot.get(realInputDirectory);
        if (files == null) {
            files = new ArrayList<>();
            filesByRoot.put(realInputDirectory, files);
        }

        for (URL url : newUrls) {

            // get the file
            File file = extractFileFromClassPath(extractDirectory, url);

            // add the file in reactor
            files.add(file);

            // get resources associated with the file
            URL resourceFileUrl = getAssociatedResource(url);

            if (resourceFileUrl == null) {

                // no resource associated with the file
                if (log.isDebugEnabled()) {
                    log.debug("[" + file + "] No resource associated.");
                }

            } else {

                // get the resource file
                File resourceFile = extractFileFromClassPath(extractDirectory, resourceFileUrl);
                if (log.isDebugEnabled()) {
                    log.debug("[" + file + "] Detected resource " + resourceFile);
                }
                resourcesByFile.put(file, Collections.singletonList(resourceFile));

            }

        }

        if (CollectionUtils.isNotEmpty(files)) {

            // check that extracted directory exists, or creates it
            boolean b = extractDirectory.exists() || extractDirectory.mkdirs();
            if (!b) {
                throw new IOException("Could not create directory " + extractDirectory);
            }

        }

    }

    protected List getFiles(String inputPath, Set includePattern) {

        if (CollectionUtils.isEmpty(includePattern)) {
            throw new IllegalArgumentException("Must have at least one include pattern");
        }

        List result = new ArrayList<>();

        // search in class-path

        ClassLoader loader = configuration.getClassLoader();

        for (String pattern : includePattern) {

            String path = inputPath;

            //FIXME must change the file.separator to /
            if (!path.endsWith("/")) {
                path += "/";
            }
            path += pattern;

            if (path.startsWith("/")) {
                path = path.substring(1);
            }

            if (log.isDebugEnabled()) {
                log.debug("Try to seek class-path file " + path);
            }

            if (pattern.contains("*")) {

                // this is a multi-files to search
                List urlList = ClassLoaders.getURLs(path, (URLClassLoader) loader);
                if (CollectionUtils.isEmpty(urlList)) {

                    log.warn("Could not find in class-path files " + path);
                } else {
                    for (URL url : urlList) {

                        if (configuration.isVerbose()) {
                            log.info("Detected class-path file " + url);
                        }
                        result.add(url);
                    }
                }
            } else {

                // this is a simple unique search, improve performance
                // by searching directly in classloader the resource
                URL url = loader.getResource(path);
                if (url == null) {

                    log.warn("Could not find in class-path the file " + path);
                } else {

                    if (configuration.isVerbose()) {
                        log.info("Detected class-path file " + url);
                    }
                    result.add(url);
                }
            }
        }
        return result;
    }

    protected URL getAssociatedResource(URL file) throws IOException {

        // obtain the properties files associated with the file
        String path = file.toString();

        String extension = "." + FileUtils.extension(path);

        String filename = StringUtils.substring(path, 0, -extension.length()).concat(".properties");

        if (log.isDebugEnabled()) {
            log.info("path of file : " + path);
            log.info("path of resource : " + filename);
        }

        URL result;

        URL propertiesFile = URI.create(filename).toURL();

        if (path.startsWith("file:")) {

            //FIXME-tchemit-2015-05-24 Does this case happen here ?
            // local file (not from class-path)
            // can test directly on resource if it exists
            File file1 = new File(propertiesFile.getFile());
            if (file1.exists()) {

                // resource exist, keep it
                result = propertiesFile;

            } else {

                result = null;

            }

        } else {

            InputStream in = null;
            try {
                in = propertiesFile.openStream();

                // resource exist, keep it
                result = propertiesFile;

            } catch (IOException eee) {

                // resource does not exists
                log.warn("Could not find resource " + propertiesFile);
                result = null;

            } finally {

                if (in != null) {
                    in.close();
                }

            }

        }

        return result;

    }

    protected File extractFileFromClassPath(File extractDirectory, URL url) throws IOException {

        String path = url.getPath();

        // case where file is extracted from jar, "!" found into url, ex:
        // url:  /home/.../agrosyst-api/target/agrosyst-api-1.0.1-SNAPSHOT.jar!/agrosyst.objectmodel
        // path: /home/.../agrosyst-services/target/extracted-sources/model/agrosyst.objectmodel

        // case where file is no extracted from jar, "!" not found into url, ex:
        // url:  /home/.../agrosyst-api/target/classes/agrosyst.objectmodel
        // path: /home/.../agrosyst-services/target/extracted-sources/model/agrosyst.objectmodel

        int index = path.indexOf("!");
        if (index == -1) {
            // case where file is no extracted from jar:
            index = path.lastIndexOf("/") - 1; // -1: because we need to keep the last "/" from path
        }
        String relativePath = path.substring(index + 1);

        File f = new File(extractDirectory, relativePath);
        if (log.isDebugEnabled()) {
            log.debug("extract " + url + " to " + f);
        }
        File parentFile = f.getParentFile();

        boolean b = parentFile.exists() || parentFile.mkdirs();
        if (!b) {
            throw new IOException("Could not create directory " + f);
        }

        try (FileOutputStream out = new FileOutputStream(f)) {
            IOUtils.copy(url.openStream(), out);
        }
        return f;

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy