Skip to content

Commit

Permalink
feat: use embedded documentation files as fallback for fetching docum…
Browse files Browse the repository at this point in the history
…entation online
  • Loading branch information
Mangern committed Sep 19, 2024
1 parent 5b3eb2b commit 6814607
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"test": "vscode-test",
"check-types": "tsc --noEmit",
"copy-images": "cp ../../resources/* ./images",
"langserver-install": "mkdir -p server && cp ../../language-server/target/schema-language-server-jar-with-dependencies.jar ./server/",
"langserver-install": "mkdir -p server && rm -r server/* && cp ../../language-server/target/schema-language-server-jar-with-dependencies.jar ./server/",
"publish": "npm run compile && node out/publish.js"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
package ai.vespa.schemals;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;

import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionOptions;
Expand Down Expand Up @@ -153,11 +166,29 @@ public void connect(LanguageClient languageClient) {
// Start a document fetching job in the background.
Path docPath = serverPath.resolve("hover");

try {
setupDocumentation(docPath);
} catch (IOException ioex) {
this.logger.error("Failed to set up documentation. Error: " + ioex.getMessage());
}
}

/**
* Initial setup of the documentation.
*/
public void setupDocumentation(Path documentationPath) throws IOException {

Files.createDirectories(documentationPath);
Files.createDirectories(documentationPath.resolve("schema"));
Files.createDirectories(documentationPath.resolve("rankExpression"));

ensureLocalDocumentationLoaded(documentationPath);

Thread thread = new Thread() {
@Override
public void run() {
try {
FetchDocumentation.fetchDocs(docPath);
FetchDocumentation.fetchDocs(documentationPath);
} catch(Exception e) {
throw new RuntimeException(e.getMessage());
}
Expand All @@ -167,11 +198,58 @@ public void run() {
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread th, Throwable ex) {
logger.error("Failed to fetch docs:" + ex.getMessage());
logger.warning("Failed to fetch docs: " + ex.getMessage() + " is unavailable. Locally cached documentation will be used.");
}
});
logger.info("Fetching docs to path: " + docPath.toAbsolutePath().toString());
logger.info("Fetching docs to path: " + documentationPath.toAbsolutePath().toString());
thread.start();

}

/**
* Assumes documentation is loaded if documentationPath/schema contains .md files.
* If documentation is not loaded, unpacks markdown files from the current jar.
*/
private void ensureLocalDocumentationLoaded(Path documentationPath) throws IOException {
File dir = new File(documentationPath.resolve("schema").toString());
File[] contents = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".md");
}
});
// Documentation exists
if (contents.length > 0) return;

logger.info("Extracting embedded documentation files.");

// If it doesn't exist, unpack from jar
var resources = Thread.currentThread().getContextClassLoader().getResources(documentationPath.getFileName().toString());

if (!resources.hasMoreElements()) {
throw new IOException("Could not find documentation in jar file!");
}

URL resourceURL = resources.nextElement();

if (!resourceURL.getProtocol().equals("jar")) {
throw new IOException("Unhandled protocol for resource " + resourceURL.toString());
}

String jarPath = resourceURL.getPath().substring(5, resourceURL.getPath().indexOf('!'));
try (JarFile jarFile = new JarFile(URLDecoder.decode(jarPath, "UTF-8"))) {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (!entry.isDirectory() && entry.getName().startsWith(documentationPath.getFileName().toString())) {
Path destination = documentationPath.getParent().resolve(entry.getName());
try (InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(entry.getName())) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String content = reader.lines().collect(Collectors.joining(System.lineSeparator()));
Files.write(destination, content.getBytes(), StandardOpenOption.CREATE);
}
}
}
}
}
}

0 comments on commit 6814607

Please sign in to comment.