/*
* Copyright 2012 Future Systems
*
* 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.krakenapps.api;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class PathAutoCompleter implements ScriptAutoCompletionHelper {
enum FilterOption {
All, DirectoryOnly, FileOnly
}
private FilterOption filterOption;
public PathAutoCompleter() {
filterOption = FilterOption.All;
}
public PathAutoCompleter(FilterOption filterOption) {
this.filterOption = filterOption;
}
@Override
public List<ScriptAutoCompletion> matches(ScriptSession session, String prefix) {
File dir = (File) session.getProperty("dir");
int p = prefix.lastIndexOf('/');
String parent = null;
if (p > 0)
parent = prefix.substring(0, p);
else if (p == 0)
parent = "/";
List<ScriptAutoCompletion> paths = new ArrayList<ScriptAutoCompletion>();
String filePrefix = p >= 0 ? prefix.substring(p + 1) : prefix;
File parentFile = canonicalize(dir, parent);
if (parentFile == null)
return paths;
boolean absolute = parent != null && (parent.startsWith("/") || isWindowsDriveRoot(parentFile.getAbsolutePath()));
File[] files = null;
// for windows drive root enumeration
if (parent != null && parent.equals("/") && File.separatorChar == '\\') {
files = File.listRoots();
} else {
files = parentFile.listFiles();
}
if (files == null)
return paths;
for (File f : files) {
String name = f.getName();
if (name.startsWith(filePrefix)) {
if (filterOption == FilterOption.DirectoryOnly && !f.isDirectory())
continue;
if (filterOption == FilterOption.FileOnly && !f.isFile())
continue;
if (absolute) {
String path = f.getAbsolutePath();
try {
path = f.getCanonicalPath();
} catch (IOException e) {
}
if (!path.startsWith("/"))
path = "/" + path;
path = path.replaceAll("\\\\", "/");
if (f.isDirectory() && !path.endsWith("/"))
path = path + "/";
if (path.toLowerCase().startsWith(prefix.toLowerCase()))
paths.add(new ScriptAutoCompletion(path, name));
} else {
if (f.isDirectory())
name = name + "/";
if (p > 0) {
String completion = parent + "/" + name;
if (completion.toLowerCase().startsWith(prefix.toLowerCase()))
paths.add(new ScriptAutoCompletion(completion, name));
} else {
if (name.toLowerCase().startsWith(prefix.toLowerCase()))
paths.add(new ScriptAutoCompletion(name));
}
}
}
}
return paths;
}
private File canonicalize(File dir, String path) {
try {
if (path == null || path.isEmpty()) {
return dir.getCanonicalFile();
} else if (path.startsWith("/") || isWindowsDriveRoot(path)) {
File f = new File(path.endsWith("/") ? path : path + "/");
return f.getCanonicalFile();
} else {
return new File(dir, path).getCanonicalFile();
}
} catch (IOException e) {
return null;
}
}
private boolean isWindowsDriveRoot(String path) {
try {
File f = new File(path);
for (File root : File.listRoots()) {
String s1 = root.getCanonicalPath();
String s2 = f.getCanonicalPath();
if (s1.equals(s2))
return true;
}
} catch (IOException e) {
}
return false;
}
}