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;
}