protected List generateFileNames()

in gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Expander.java [494:665]


    protected List<? extends CharSequence> generateFileNames(CharSequence arg) throws IOException
    {
        // Disable if currentDir is not set
        Path currentDir = evaluate.currentDir();
        if (currentDir == null || inQuote)
        {
            return Collections.singletonList(arg);
        }
        // Search for unquoted escapes
        boolean hasUnescapedReserved = false;
        boolean escaped = false;
        boolean doubleQuoted = false;
        boolean singleQuoted = false;
        StringBuilder buf = new StringBuilder(arg.length());
        String pfx = "";
        for (int i = 0; i < arg.length(); i++)
        {
            char c = arg.charAt(i);
            if (doubleQuoted && escaped)
            {
                if (c != '"' && c != '\\' && c != '$' && c != '%')
                {
                    buf.append('\\');
                }
                buf.append(c);
                escaped = false;
            }
            else if (escaped)
            {
                buf.append(c);
                escaped = false;
            }
            else if (singleQuoted)
            {
                if (c == '\'')
                {
                    singleQuoted = false;
                }
                else
                {
                    buf.append(c);
                }
            }
            else if (doubleQuoted)
            {
                if (c == '\\')
                {
                    escaped = true;
                }
                else if (c == '\"')
                {
                    doubleQuoted = false;
                }
                else
                {
                    buf.append(c);
                }
            }
            else if (c == '\\')
            {
                escaped = true;
            }
            else if (c == '\'')
            {
                singleQuoted = true;
            }
            else if (c == '"')
            {
                doubleQuoted = true;
            }
            else if (c == '~')
            {
                Object home = evaluate.get("HOME");
                if (home != null)
                {
                    buf.append(home.toString());
                }
            }
            else
            {
                if ("*(|<[?".indexOf(c) >= 0 && !hasUnescapedReserved)
                {
                    hasUnescapedReserved = true;
                    pfx = buf.toString();
                }
                buf.append(c);
            }
        }
        if (!hasUnescapedReserved)
        {
            return Collections.singletonList(arg);
        }

        String org = buf.toString();
        final List<String> expanded = new ArrayList<>();
        final Path dir;
        final String prefix;
        if (pfx.indexOf('/') >= 0)
        {
            pfx = pfx.substring(0, pfx.lastIndexOf('/'));
            arg = org.substring(pfx.length() + 1);
            dir = currentDir.resolve(pfx).normalize();
            prefix = pfx + "/";
        }
        else
        {
            dir = currentDir;
            prefix = "";
        }
        final GlobPathMatcher matcher = new GlobPathMatcher(arg.toString());
        Files.walkFileTree(dir,
                EnumSet.of(FileVisitOption.FOLLOW_LINKS),
                Integer.MAX_VALUE,
                new FileVisitor<Path>()
                {
                    @Override
                    public FileVisitResult preVisitDirectory(Path file, BasicFileAttributes attrs) throws IOException
                    {
                        if (file.equals(dir))
                        {
                            return FileVisitResult.CONTINUE;
                        }
                        if (Files.isHidden(file))
                        {
                            return FileVisitResult.SKIP_SUBTREE;
                        }
                        Path r = dir.relativize(file);
                        if (matcher.matches(r.toString(), true))
                        {
                            expanded.add(prefix + r.toString());
                        }
                        if (matcher.matches(r.toString(), false))
                        {
                            return FileVisitResult.CONTINUE;
                        }
                        else
                        {
                            return FileVisitResult.SKIP_SUBTREE;
                        }
                    }

                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
                    {
                        if (!Files.isHidden(file))
                        {
                            Path r = dir.relativize(file);
                            if (matcher.matches(r.toString(), true))
                            {
                                expanded.add(prefix + r.toString());
                            }
                        }
                        return FileVisitResult.CONTINUE;
                    }

                    @Override
                    public FileVisitResult visitFileFailed(Path file, IOException exc) {
                        return FileVisitResult.CONTINUE;
                    }

                    @Override
                    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
                        return FileVisitResult.CONTINUE;
                    }
                });
        Collections.sort(expanded);
        if (expanded.isEmpty())
        {
            throw new IOException("no matches found: " + org);
        }
        return expanded;
    }