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

org.aesh.io.PathResolver Maven / Gradle / Ivy

The newest version!
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the @authors tag. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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 org.aesh.io;

import org.aesh.terminal.utils.Config;

import java.io.File;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Resolve a file that might contain (~,*,?) to its proper parentPath
 * Returns a list of files.
 * @author Ståle W. Pedersen
 */
public class PathResolver {

    private static final char SEPARATOR = Config.getPathSeparator().charAt(0);
    private static final char TILDE = '~';
    private static final String TILDE_WITH_SEPARATOR = "~"+Config.getPathSeparator();
    private static final char STAR = '*';
    private static final char WILDCARD = '?';
    private static final String PARENT = "..";
    private static final String PARENT_WITH_SEPARATOR = ".."+ Config.getPathSeparator();
    private static final String ROOT = Config.getPathSeparator();
    private static final String DRIVER_SEPARATOR = ":";
    private static final String CURRENT_WITH_SEPARATOR = "."+Config.getPathSeparator();
    private static final String SEPARATOR_WITH_CURRENT = Config.getPathSeparator()+".";
    private static final String SEPARATOR_CURRENT_SEPARATOR = Config.getPathSeparator()+"."+Config.getPathSeparator();
    private static final String CURRENT = ".";
    private static final Pattern starPattern = Pattern.compile("[\\*]+");

    /**
     * 1. find the absolute root directory
     * 2. check for wildcards
     *
     * @param incPath
     * @param cwd
     * @return
     */
    @SuppressWarnings("IndexOfReplaceableByContains")
    public static List resolvePath(File incPath, File cwd) {
        if(cwd == null)
            cwd = new File(Config.getHomeDir());

        //if incPath start with eg: ./, remove it
        if(incPath.toString().startsWith(CURRENT_WITH_SEPARATOR)) {
            incPath = new File(incPath.toString().substring(CURRENT_WITH_SEPARATOR.length()));
        }

        if(incPath.toString().startsWith(TILDE_WITH_SEPARATOR)) {
            if(Config.getHomeDir().endsWith(Config.getPathSeparator()))
                incPath = new File(Config.getHomeDir()+incPath.toString().substring(2));
            else
                incPath = new File(Config.getHomeDir()+incPath.toString().substring(1));
        }

        if(incPath.toString().indexOf(TILDE) == 0) {
            if(incPath.toString().length() > 1) {
                // directories which name starts with tilde
                incPath = new File(cwd.toString() + Config.getPathSeparator() + incPath.toString());
            } else {
                incPath = new File(Config.getHomeDir());
            }
        }

        //  foo1/./foo2 is changed to foo1/foo2
        if(incPath.toString().indexOf(SEPARATOR_CURRENT_SEPARATOR) > -1) {
            int index = incPath.toString().indexOf(SEPARATOR_CURRENT_SEPARATOR);
            if(index == 0) {
                incPath = new File(incPath.toString().substring(SEPARATOR_CURRENT_SEPARATOR.length()-1));
            }
            else {
                incPath = new File(incPath.toString().substring(0, index) +
                        incPath.toString().substring(index+2, incPath.toString().length()));
            }
        }

        //parentPath do not start with / or by a windows driver letter and cwd is not / either
        if( incPath.toString().indexOf(ROOT) != 0 && incPath.toString().indexOf(DRIVER_SEPARATOR) == -1 && !cwd.toString().equals(ROOT)) {
            if(cwd.toString().endsWith(Config.getPathSeparator()))
                incPath = new File(cwd.toString() + incPath.toString());
            else
                incPath = new File(cwd.toString() + Config.getPathSeparator() + incPath.toString());
        }

        if(incPath.toString().indexOf(PARENT_WITH_SEPARATOR) > -1) {
            String tmp = incPath.toString();
            while(tmp.indexOf(PARENT_WITH_SEPARATOR) > -1) {
                int index = tmp.indexOf(PARENT_WITH_SEPARATOR);
                if(index == 0) {
                    tmp = tmp.substring(PARENT_WITH_SEPARATOR.length());
                }
                else {
                    File tmpFile = new File(tmp.substring(0, index));
                    tmpFile = tmpFile.getParentFile();
                    if(tmpFile == null)
                        tmpFile = new File(Config.getPathSeparator());
                    tmpFile = new File(tmpFile.toString() + tmp.substring(index+ PARENT_WITH_SEPARATOR.length()-1));
                    //tmp = tmp.substring(0, index) + tmp.substring(index+PARENT_WITH_SEPARATOR.length());
                    tmp = tmpFile.toString();
                }
            }
            incPath = new File(tmp);
        }

        if(incPath.toString().endsWith(PARENT)) {
            incPath = new File(incPath.toString().substring(0, incPath.toString().length()-PARENT.length()));
            incPath = incPath.getParentFile();
            if(incPath == null)
                incPath = new File(Config.getPathSeparator());
        }

        if( incPath.toString().indexOf(STAR) > -1 || incPath.toString().indexOf(WILDCARD) > -1) {
            PathCriteria pathCriteria = parsePath(incPath);
            if(incPath.toString().indexOf(SEPARATOR) > -1) {
                List foundFiles  = null;
                if(pathCriteria.getCriteria().equals(String.valueOf(STAR))) {
                    foundFiles = new ArrayList<>();
                    foundFiles.add(new File(pathCriteria.getParentPath()));
                }
                else
                    foundFiles = findFiles(new File(pathCriteria.parentPath), pathCriteria.getCriteria(), false);
                if(pathCriteria.childPath.length() == 0)
                    return foundFiles;
                else {
                    List outFiles = new ArrayList<>();
                    for(File f : foundFiles)
                        if(new File(f+Config.getPathSeparator()+pathCriteria.childPath).exists())
                            outFiles.add(new File(f+Config.getPathSeparator()+pathCriteria.childPath));

                    return outFiles;
                }
            }
            //just wildcard without separators
            else {
                if(incPath.toString().length() == 1) {
                    List foundFiles = findFiles(new File(pathCriteria.parentPath), pathCriteria.getCriteria(), false);
                    if(pathCriteria.childPath.length() == 0)
                        return foundFiles;
                }

                return new ArrayList();
            }
        }
        else {
            //no wildcards
            ArrayList fileList = new ArrayList<>(1);
            fileList.add(incPath);
            return fileList;
        }
    }

    private static List parseWildcard(File incPath) {
        ArrayList files = new ArrayList<>();
        int index = -1;
        while(incPath.toString().indexOf(STAR) > -1) {

        }

        return files;
    }

    private static List findFiles(File incPath, String searchArgument, boolean findDirectory) {
        ArrayList files = new ArrayList<>();

        final PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**");
        /*
         DirectoryStream.Filter filter = new DirectoryStream.Filter() {
            @Override
            public boolean accept(Path entry)  {
                return matcher.matches(entry.getFileName());
            }
        };
        */

        if(starPattern.matcher(searchArgument).matches()) {
            try (DirectoryStream stream = findDirectory ?
                         Files.newDirectoryStream(incPath.toPath(), new DirectoryFilter()) :
                    Files.newDirectoryStream(incPath.toPath(), new FileFilter())) {
                for(Path p : stream)
                    files.add(p.toFile());
                return files;
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
        else {
            try (DirectoryStream stream = Files.newDirectoryStream(incPath.toPath(), searchArgument)) {
                if(findDirectory) {
                    for(Path p : stream)
                        if(Files.isDirectory(p))
                            files.add(p.toFile());
                }
                else {
                    for(Path p : stream)
                        files.add(p.toFile());
                }
                return files;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return files;
    }

    private static class DirectoryFilter implements DirectoryStream.Filter {
        @Override
        public boolean accept(Path entry) throws IOException {
            return Files.isDirectory(entry);
        }
    }

    private static class FileFilter implements DirectoryStream.Filter {
        @Override
        public boolean accept(Path entry) throws IOException {
            return Files.exists(entry);
        }
    }

    //todo: path criteria need to check if separator is in the path
    private static PathCriteria parsePath(File path) {
        int starIndex = path.toString().indexOf(STAR);
        int wildcardIndex = path.toString().indexOf(WILDCARD);

        int index = (starIndex < wildcardIndex || wildcardIndex < 0) ? starIndex : wildcardIndex;

        if(index == 0 && path.toString().length() == 1)
            return new PathCriteria(String.valueOf(SEPARATOR), "", path.toString());
        else {
            int parentSeparatorIndex = index-1;
            while(path.toString().charAt(parentSeparatorIndex) != SEPARATOR && parentSeparatorIndex > -1)
                parentSeparatorIndex--;

            int childSeparatorIndex = index+1;
            if(childSeparatorIndex < path.toString().length())
                while(path.toString().charAt(childSeparatorIndex) != SEPARATOR && parentSeparatorIndex < path.toString().length())
                    childSeparatorIndex++;

            String parentPath = path.toString().substring(0, parentSeparatorIndex);
            String criteria = path.toString().substring(parentSeparatorIndex+1, childSeparatorIndex);
            String childPath = path.toString().substring(childSeparatorIndex, path.toString().length());

            return new PathCriteria(parentPath, childPath, criteria);
        }
    }

    static class PathCriteria {
        private final String parentPath;
        private final String childPath;
        private final String criteria;

        PathCriteria(String parentPath, String childPath, String criteria) {
            this.parentPath = parentPath;
            this.childPath = childPath;
            this.criteria = criteria;
        }

        public String getParentPath() {
            return parentPath;
        }

        public String getCriteria() {
            return criteria;
        }

        public String getChildPath() {
            return childPath;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy