davidlday / vscode-languagetool-linter

A from scratch redesign of LanguageTool integration for VS Code.
https://marketplace.visualstudio.com/items?itemName=davidlday.languagetool-linter
Apache License 2.0
158 stars 12 forks source link

Class org.languagetool.GlobalConfig not found on ArchLinux #39

Closed damienflament closed 4 years ago

damienflament commented 5 years ago

Hi!

I just installed the LanguageTool Linter extension for VSCode on ArchLinux. I choose to let the extension manage the LanguageTool server.

I use the following configuration in settings.json:

"languageToolLinter.enabled": true,
"languageToolLinter.serviceType": "managed",
"languageToolLinter.managed.jarFile": "/usr/share/java/languagetool/languagetool-server.jar",
"languageToolLinter.languageTool.motherTongue": "fr",
"languageToolLinter.languageTool.language": "en-US",

The extension output in VSCode is shown below:

Starting managed service.
Picked up JAVA_TOOL_OPTIONS:  -Djdk.gtk.version=3

LanguageTool Linter Activated!
Exception in thread "main" java.lang.NoClassDefFoundError: org/languagetool/GlobalConfig
    at org.languagetool.server.HTTPServerConfig.<init>(HTTPServerConfig.java:94)
    at org.languagetool.server.HTTPServer.main(HTTPServer.java:140)
Caused by: java.lang.ClassNotFoundException: org.languagetool.GlobalConfig
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:604)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    ... 2 more

Managed service command failed: java -cp /usr/share/java/languagetool/languagetool-server.jar org.languagetool.server.HTTPServer --port 8000
Error Message: Command failed with exit code 1: java -cp /usr/share/java/languagetool/languagetool-server.jar org.languagetool.server.HTTPServer --port 8000

After looking at the LanguageTool launch script available on ArchLinux, I think the classpath is not well defined when this extension run the server:

#!/bin/bash

file_present=false
asked_for_help=false
start_server=false
http_server=false

declare -a argv=("$@")

i=0
for arg in "$@"; do
  if [[ $arg != -* ]]; then
    file_present=true
  fi
  if [[ $arg == --config* ]]; then
    start_server=true
  fi
  if [[ $arg == --http ]]; then
    start_server=true
    http_server=true
    unset argv[$i]
  fi
  if [[ $arg == -h ]]; then
    asked_for_help=true
    unset argv[$i]
  fi
  if [[ $arg == --help ]]; then
    asked_for_help=true
    unset argv[$i]
  fi
  ((i++))
done

CP=/usr/share/languagetool
for name in /usr/share/java/languagetool/*.jar ; do
  CP=$CP:$name
done

CLI_command='org.languagetool.commandline.Main'
GUI_command='org.languagetool.gui.Main'
NSRV_command='org.languagetool.server.HTTPServer'
SSRV_command='org.languagetool.server.HTTPSServer'

if $asked_for_help; then
  echo "Command-line interface (CLI) help:"
  "$JAVA_HOME/bin/java" -cp $CP $CLI_command -h | sed "s/java -jar languagetool-commandline.jar/languagetool/"
  echo
  echo "Graphical user interface (GUI) help:"
  "$JAVA_HOME/bin/java" -cp $CP $GUI_command -h | sed "s/java org.languagetool.gui.Main/languagetool/"
  echo
  echo "HTTP server help:"
  "$JAVA_HOME/bin/java" -cp $CP $NSRV_command -h | sed "s/HTTPServer/languagetool --http/"
  echo
  echo "HTTPS server help:"
  "$JAVA_HOME/bin/java" -cp $CP $SSRV_command -h | sed "s/HTTPSServer/languagetool/"
else
  if $start_server; then
    if $http_server; then
      "$JAVA_HOME/bin/java" -cp $CP $NSRV_command "${argv[@]}"
    else
      "$JAVA_HOME/bin/java" -cp $CP $SSRV_command "${argv[@]}"
    fi
  else
    if $file_present; then
      "$JAVA_HOME/bin/java" -cp $CP $CLI_command "${argv[@]}"
    else
      "$JAVA_HOME/bin/java" -cp $CP $GUI_command "${argv[@]}"
    fi
  fi
fi

Each JAR file located in the /usr/share/java/languagetool directory is appended to the classpath. As your extension only include the the languagetool-server.jar file to the classpath, some classes are not found.

I don't know how LanguageTool is packaged on other Linux distribution, but it seems your extension does not work well with the ArchLinux package.

I think about another solution: it may be useful to specify a command to launch instead of a path to the JAR file.

davidlday commented 5 years ago

Hi! Can you tell me what version of ArchLinux you're using? I'll spin up a VM and tinker with it.

In the instructions on the wiki, I recommend installing LanguageTool on Linux using LinuxBrew and not the native package manager. This provides a consistent install across distributions and is typically more current. That said, I'm happy to look into accommodating installs via native package managers. I had problems managing the service when started by a wrapper script, but I can look at it again. It may take some time to figure it out, thought.

damienflament commented 5 years ago

ArchLinux is a rolling release distribution. I can't tell you which version I'm using, but can I tell you the versions of some packages:

CPU architecture: x86_64 Linux kernel: 5.3.6 Java Runtime Environment enabled: JRE OpendJDK 13.u33 LanguageTool: 4.7 VSCode OSS: 1.39.1 LanguageTool Linter extension: 0.3.2

damienflament commented 5 years ago

To launch the LanguageTool server on ArchLinux, I use the command provided. It's pointing to the script I shown you before:

$ languagetool --http --port 8000
Picked up JAVA_TOOL_OPTIONS:  -Djdk.gtk.version=3
2019-11-09 09:14:33 +0000 Not setting up database access, dbDriver is not configured
2019-11-09 09:14:33 +0000 WARNING: running in HTTP mode, consider using org.languagetool.server.HTTPSServer for encrypted connections
2019-11-09 09:14:34 +0000 Setting up thread pool with 10 threads
2019-11-09 09:14:34 +0000 Starting LanguageTool 4.7 (build date: 2019-09-28 10:09, 64f87c1) server on http://localhost:8000...
2019-11-09 09:14:34 +0000 Server started

That script launch the following command:

/bin/java \
  -cp /usr/share/languagetool:/usr/share/java/languagetool/aho-corasick-double-array-trie.jar:/usr/share/java/languagetool/akka-actor_2.11.jar:/usr/share/java/languagetool/annotations.jar:/usr/share/java/languagetool/asm.jar:/usr/share/java/languagetool/berkeleylm.jar:/usr/share/java/languagetool/catalan-pos-dict.jar:/usr/share/java/languagetool/cjftransform.jar:/usr/share/java/languagetool/commons-cli.jar:/usr/share/java/languagetool/commons-codec.jar:/usr/share/java/languagetool/commons-collections4.jar:/usr/share/java/languagetool/commons-csv.jar:/usr/share/java/languagetool/commons-io.jar:/usr/share/java/languagetool/commons-lang3.jar:/usr/share/java/languagetool/commons-logging.jar:/usr/share/java/languagetool/commons-pool2.jar:/usr/share/java/languagetool/commons-text.jar:/usr/share/java/languagetool/config.jar:/usr/share/java/languagetool/FastInfoset.jar:/usr/share/java/languagetool/german-pos-dict.jar:/usr/share/java/languagetool/guava.jar:/usr/share/java/languagetool/hamcrest-core.jar:/usr/share/java/languagetool/hppc.jar:/usr/share/java/languagetool/hunspell-native-libs.jar:/usr/share/java/languagetool/ictclas4j.jar:/usr/share/java/languagetool/icu4j.jar:/usr/share/java/languagetool/indriya.jar:/usr/share/java/languagetool/istack-commons-runtime.jar:/usr/share/java/languagetool/jackson-annotations.jar:/usr/share/java/languagetool/jackson-core.jar:/usr/share/java/languagetool/jackson-databind.jar:/usr/share/java/languagetool/jafama.jar:/usr/share/java/languagetool/java-jwt.jar:/usr/share/java/languagetool/javax.activation-api.jar:/usr/share/java/languagetool/jaxb-api.jar:/usr/share/java/languagetool/jaxb-core.jar:/usr/share/java/languagetool/jaxb-runtime.jar:/usr/share/java/languagetool/jcommander.jar:/usr/share/java/languagetool/jna.jar:/usr/share/java/languagetool/jsonic.jar:/usr/share/java/languagetool/junit.jar:/usr/share/java/languagetool/jwordsplitter.jar:/usr/share/java/languagetool/kryo.jar:/usr/share/java/languagetool/language-detector.jar:/usr/share/java/languagetool/languagetool-commandline.jar:/usr/share/java/languagetool/languagetool-core.jar:/usr/share/java/languagetool/languagetool-core-tests.jar:/usr/share/java/languagetool/languagetool-gui-commons.jar:/usr/share/java/languagetool/languagetool.jar:/usr/share/java/languagetool/languagetool-server.jar:/usr/share/java/languagetool/languagetool-tools.jar:/usr/share/java/languagetool/logback-classic.jar:/usr/share/java/languagetool/logback-core.jar:/usr/share/java/languagetool/lucene-backward-codecs.jar:/usr/share/java/languagetool/lucene-core.jar:/usr/share/java/languagetool/lucene-gosen-ipadic.jar:/usr/share/java/languagetool/mariadb-java-client.jar:/usr/share/java/languagetool/minlog.jar:/usr/share/java/languagetool/morfologik-fsa-builders.jar:/usr/share/java/languagetool/morfologik-fsa.jar:/usr/share/java/languagetool/morfologik-speller.jar:/usr/share/java/languagetool/morfologik-stemming.jar:/usr/share/java/languagetool/morfologik-tools.jar:/usr/share/java/languagetool/morfologik-ukrainian-lt.jar:/usr/share/java/languagetool/morphology-el.jar:/usr/share/java/languagetool/mybatis.jar:/usr/share/java/languagetool/objenesis.jar:/usr/share/java/languagetool/opennlp-chunk-models.jar:/usr/share/java/languagetool/opennlp-postag-models.jar:/usr/share/java/languagetool/opennlp-tokenize-models.jar:/usr/share/java/languagetool/opennlp-tools.jar:/usr/share/java/languagetool/openregex.jar:/usr/share/java/languagetool/reflectasm-shaded.jar:/usr/share/java/languagetool/scala-compiler.jar:/usr/share/java/languagetool/scala-parser-combinators_2.11.jar:/usr/share/java/languagetool/scala-reflect.jar:/usr/share/java/languagetool/scala-xml_2.11.jar:/usr/share/java/languagetool/segment.jar:/usr/share/java/languagetool/simpleclient_common.jar:/usr/share/java/languagetool/simpleclient_guava.jar:/usr/share/java/languagetool/simpleclient_hotspot.jar:/usr/share/java/languagetool/simpleclient_httpserver.jar:/usr/share/java/languagetool/simpleclient.jar:/usr/share/java/languagetool/slf4j-api.jar:/usr/share/java/languagetool/stax-ex.jar:/usr/share/java/languagetool/txw2.jar:/usr/share/java/languagetool/unit-api.jar:/usr/share/java/languagetool/uom-lib-common.jar:/usr/share/java/languagetool/xgboost4j.jar:/usr/share/java/languagetool/xgboost-predictor.jar  \
  org.languagetool.server.HTTPServer \
  --port 8000

As you can see, the paths of all the JAR files located in the /usr/share/java/languagetool directory are appended to the classpath. Putting this list in the languageToolLinter.managed.jarFile setting works. But it might break if the package change.

davidlday commented 5 years ago

I've decided to treat this as an enhancement. If the path is a directory, add all the jars in the directory to the classpath when starting. If the path is a jar, use current behavior. If it's something else, throw an error.

davidlday commented 5 years ago

@damienflament - I'm still going to pursue adding this as an enhancement, but there's an alternative on ArchLinux. The package provides a systemd service file so LanguageTool can be run as a service. If you have root access on the machine, you can enable it by:

sudo systemctl enable languagetool

And you can start it by:

sudo systemctl start languagetool

It starts on the default port, and the extension works with the default configuration. Would this be an option for you?

damienflament commented 5 years ago

Running a LanguageTool server system wide is the workaround actually.

Just a note about that, if someone looks at this issue and use ArchLinux:

The provided service is running a LanguageTool server which accept connections from the network. It launches the command /usr/bin/languagetool --http --allow-origin "*". So, by using it, its usage is NOT restricted to your machine.

I posted this issue ticket because the managed behavior of your extension seems to not work on my configuration.

I understand that relying on a portable package manager (Brew) makes your work easier because the package files location is expectable regardless of the operating system. But I can't use the package manager recommended by every software maintainer on my system, there are so many.

Thanks for your efforts.

davidlday commented 5 years ago

I'm glad you pointed this out. I was using the Jar File setting as a classpath anyhow. I think what I'll do is deprecate the Jar File setting and replace it with Class Path. That would provide better support across different ways of installing LanguageTool.

davidlday commented 5 years ago

Version 0.4.0 broke when published. Reverted to 0.3.2 and will implement when I figure out what happened.

davidlday commented 5 years ago

Feature added in 0.6.0.

davidlday commented 5 years ago

Broke on publication again.

davidlday commented 4 years ago

So embarrassed. I had the node-glob module as a dev dependency. I've built and installed locally to test. Will publish an updated version soon.

d4h0 commented 3 years ago

@damienflament: Thanks for reporting this!

@davidlday: Thanks for creating this project!

Regarding:

The provided service is running a LanguageTool server which accept connections from the network. It launches the command /usr/bin/languagetool --http --allow-origin "*". So, by using it, its usage is NOT restricted to your machine.

That doesn't seem to be correct, see output of languagetool --help:

[...]

  --public         allow this server process to be connected from anywhere; if not set,
                   it can only be connected from the computer it was started on
  --allow-origin   ORIGIN  set the Access-Control-Allow-Origin header in the HTTP response,
                         used for direct (non-proxy) JavaScript-based access from browsers;
                         example: --allow-origin "*"

[...]