package org.netbeans.gradle.project.output;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
import org.netbeans.gradle.project.NbGradleProject;
import org.netbeans.gradle.project.util.StringUtils;
import org.openide.filesystems.FileObject;
import org.openide.util.Utilities;
public final class ProjectFileConsumer implements OutputLinkFinder {
private final String normalizedPath;
public ProjectFileConsumer(NbGradleProject project) {
FileObject projectDirectory = project.getProjectDirectory();
// In case the filesystem is not case-sesitive, otherwise it shouldn't
// hurt much, since we will check if the file exists anyway.
normalizedPath = projectDirectory.getPath().toLowerCase(Locale.ROOT);
}
public static boolean isBrowserFile(String path) {
String lowerPath = path.toLowerCase(Locale.US);
return lowerPath.endsWith(".html")
|| lowerPath.endsWith(".xhtml")
|| lowerPath.endsWith(".htm");
}
private static boolean isLineSeparator(char ch) {
return ch <= ' ' || ch == ':' || ch == ';';
}
private static int tryFindEndLineIndex(String line, int startIndex) {
int lineLength = line.length();
int actualStartIndex = startIndex;
for (; actualStartIndex < lineLength; actualStartIndex++) {
if (line.charAt(actualStartIndex) > ' ') {
break;
}
}
if (actualStartIndex >= lineLength) {
return -1;
}
for (int i = actualStartIndex; i < lineLength; i++) {
char ch = line.charAt(i);
if (ch < '0' || ch > '9') {
return i;
}
}
return lineLength;
}
private static ParsedIntDef tryReadNumber(String line, int startIndex) {
int endOfNumberIndex = tryFindEndLineIndex(line, startIndex);
if (endOfNumberIndex <= startIndex) {
return null;
}
String intStr = line.substring(startIndex, endOfNumberIndex);
try {
return new ParsedIntDef(Integer.parseInt(intStr.trim()), intStr.length());
} catch (NumberFormatException ex) {
return null;
}
}
@Override
public OutputLinkDef tryFindLink(String line) {
String normalizedLine = line.replace(File.separatorChar, '/').toLowerCase(Locale.ROOT);
int startIndex = normalizedLine.indexOf(normalizedPath);
if (startIndex < 0) {
return null;
}
int endPathIndex = normalizedLine.lastIndexOf('/');
if (endPathIndex < 0) {
// I don't think that this is possible but just in case it happens.
return null;
}
int lineLength = line.length();
int endIndex = lineLength;
for (int i = endPathIndex + 1; i < lineLength; i++) {
if (isLineSeparator(line.charAt(i))) {
endIndex = i;
break;
}
}
ParsedIntDef lineNumberDef = tryReadNumber(line, endIndex + 1);
int completeLinkEndIndex = endIndex;
int lineNumber = -1;
if (lineNumberDef != null) {
completeLinkEndIndex = endIndex + 1 + lineNumberDef.strLength;
lineNumber = lineNumberDef.value;
}
if (lineNumber < 0) {
lineNumber = -1;
}
String unstrippedFileStr = line.substring(startIndex, endIndex);
String fileStr = StringUtils.stripSeperatorsFromEnd(unstrippedFileStr);
completeLinkEndIndex = completeLinkEndIndex - (unstrippedFileStr.length() - fileStr.length());
File file = new File(fileStr);
if (!file.isFile()) {
return null;
}
Runnable outputListener = null;
if (isBrowserFile(fileStr)) {
try {
URL url = Utilities.toURI(file).toURL();
outputListener = OutputUrlConsumer.getUrlOpenTask(url);
} catch (MalformedURLException ex) {
}
}
if (outputListener == null) {
outputListener = OpenEditorOutputListener.tryCreateListener(file, lineNumber);
if (outputListener == null) {
return null;
}
}
return new OutputLinkDef(startIndex, completeLinkEndIndex, outputListener);
}
private static final class ParsedIntDef {
public final int value;
public final int strLength;
public ParsedIntDef(int value, int strLength) {
this.value = value;
this.strLength = strLength;
}
}
}