package com.intellij.javascript.debugger.execution;
import com.intellij.javascript.debugger.impl.DebuggableFileFinder;
import com.intellij.javascript.debugger.impl.ScriptUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.text.CharFilter;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
public class RemoteDebuggingFileFinder extends DebuggableFileFinder {
private Map<String, VirtualFile> myUrl2Local;
private final THashSet<VirtualFile> myLocalFiles;
private final Project myProject;
public RemoteDebuggingFileFinder(Project project, List<RemoteJavaScriptDebugConfiguration.RemoteUrlMappingBean> mappings) {
this.myProject = project;
this.myUrl2Local = createUrl2LocalMap(mappings);
this.myLocalFiles = new THashSet<VirtualFile>(this.myUrl2Local.values());
}
private static Map<String, VirtualFile> createUrl2LocalMap(List<RemoteJavaScriptDebugConfiguration.RemoteUrlMappingBean> mappings) {
Map<String,VirtualFile> url2Local = new THashMap<String,VirtualFile>();
LocalFileSystem fileSystem = LocalFileSystem.getInstance();
for (RemoteJavaScriptDebugConfiguration.RemoteUrlMappingBean mapping : mappings) {
VirtualFile file = fileSystem.findFileByPath(mapping.getLocalFilePath());
if (file != null)
url2Local.put(mapping.getRemoteUrl(), file);
}
return url2Local;
}
private static String trimUrlParameters(@NotNull String url) {
int end = StringUtil.findFirst(url, new CharFilter() {
public boolean accept(char ch) {
return ((ch == '?') || (ch == '#') || (ch == ';'));
}
});
return ((end != -1) ? url.substring(0, end) : url);
}
public VirtualFile findFile(@NotNull String fileUrl) {
String url = trimUrlParameters(fileUrl);
int i = url.length();
while (i != -1) {
String prefix = url.substring(0, i);
VirtualFile file = this.myUrl2Local.get(prefix);
if (file == null) {
file = this.myUrl2Local.get(prefix + "/");
}
if (file != null) {
if (i >= url.length()) {
if (!(ScriptUtil.isHtmlOrJavaScript(file))) break;
return file;
}
String relativePath = url.substring(i + 1);
VirtualFile child = file.findFileByRelativePath(relativePath);
// Begin Jangaroo hack: try with tweaked extension!
if (child == null && relativePath.endsWith(".js")) {
relativePath = relativePath.substring(0,relativePath.length()-3)+".as";
child = file.findFileByRelativePath(relativePath);
}
// End Jangaroo hack
if ((child != null) && (ScriptUtil.isHtmlOrJavaScript(child))) {
return child;
}
break;
}
i = url.lastIndexOf(47, i - 1);
}
return VirtualFileManager.getInstance().findFileByUrl(url);
}
public boolean isDebuggable(@NotNull VirtualFile file) {
if (file instanceof HttpVirtualFile) {
return true;
}
VirtualFile current = file;
while (current != null) {
if (this.myLocalFiles.contains(current))
return true;
current = current.getParent();
}
return false;
}
public boolean canSetRemoteUrl(@NotNull VirtualFile file) {
return ProjectRootManager.getInstance(this.myProject).getFileIndex().isInContent(file);
}
public boolean updateRemoteUrlMapping(List<RemoteJavaScriptDebugConfiguration.RemoteUrlMappingBean> mappings) {
Map<String, VirtualFile> newMap = createUrl2LocalMap(mappings);
if (!(newMap.equals(this.myUrl2Local))) {
this.myUrl2Local = newMap;
this.myLocalFiles.clear();
this.myLocalFiles.addAll(this.myUrl2Local.values());
return true;
}
return false;
}
}