Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to `lsp-java-update-server` with custom Maven `settings.xml`? #140

Open
Alexander-Shukaev opened this issue Jun 4, 2019 · 7 comments

Comments

Projects
None yet
2 participants
@Alexander-Shukaev
Copy link

commented Jun 4, 2019

Apparently, I'm behind corporate proxy and with custom SSL certificates which cannot be verified properly:

--2019-06-04 10:36:48--  https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar
Resolving proxyeu.company.com (proxyeu.company.com)... 69.191.176.39
Connecting to proxyeu.company.com (proxyeu.company.com)|69.191.176.39|:81... connected.
WARNING: cannot verify repo.maven.apache.org's certificate, issued by ‘/C=US/ST=NEW YORK/L=NEW YORK/O=Company/OU=NDIS/CN=Company CLASS 1 SubCA V3’:
  Self-signed certificate encountered.
Proxy request sent, awaiting response... 200 OK
Length: 48336 (47K) [application/java-archive]
Saving to: ‘/tmp/lsp-java-install/.mvn/wrapper/maven-wrapper.jar’

     0K .......... .......... .......... .......... .......   100%  583K=0.08s

2019-06-04 10:36:49 (583 KB/s) - ‘/tmp/lsp-java-install/.mvn/wrapper/maven-wrapper.jar’ saved [48336/48336]

Exception in thread "main" javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching repo.maven.apache.org found
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1513)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
	at org.apache.maven.wrapper.DefaultDownloader.downloadInternal(DefaultDownloader.java:73)
	at org.apache.maven.wrapper.DefaultDownloader.download(DefaultDownloader.java:60)
	at org.apache.maven.wrapper.Installer.createDist(Installer.java:64)
	at org.apache.maven.wrapper.WrapperExecutor.execute(WrapperExecutor.java:121)
	at org.apache.maven.wrapper.MavenWrapperMain.main(MavenWrapperMain.java:55)
Caused by: java.security.cert.CertificateException: No name matching repo.maven.apache.org found
	at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:221)
	at sun.security.util.HostnameChecker.match(HostnameChecker.java:95)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:200)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
	... 17 more

Normally, what I do with other tools, I drop SSL certificate verification as there are always options to do so. For Maven, I found out that adding

  <mirrors>
    ...
    <mirror>
        <id>central-no-ssl</id>
        <name>Central without ssl</name>
        <url>http://repo.maven.apache.org/maven2</url>
        <mirrorOf>central</mirrorOf>
    </mirror>
    ...
  </mirrors>

to ~/.m2/settings.xml should be sufficient. Unfortunately, this does not seem to have any effect on lsp-java-update-server as per above output. Furthermore,

(setq-default lsp-java-configuration-maven-user-settings "~/.m2/settings.xml")

does not help either. Any ideas how to go about it?

@yyoncho

This comment has been minimized.

Copy link
Member

commented Jun 4, 2019

  1. Download https://github.com/emacs-lsp/lsp-java/blob/master/install/pom.xml

  2. Run (but first adjust the proper home dir).

mvn -Djdt.js.server.root=/home/kyoncho/.emacs.d/eclipse.jdt.ls/server/ -Djunit.runner.root=/home/kyoncho/.emacs.d/eclipse.jdt.ls/test-runner/ -Djunit.runner.fileName=junit-platform-console-standalone.jar -Djava.debug.root=/home/kyoncho/.emacs.d/eclipse.jdt.ls/server/bundles clean package -Djdt.download.url=http://download.eclipse.org/jdtls/snapshots/jdt-language-server-latest.tar.gz

lsp-java is doing pretty much the same but it does not rely on mvn being installed (it uses mvnw).

@Alexander-Shukaev

This comment has been minimized.

Copy link
Author

commented Jun 4, 2019

I can try this, thank you. However, is there a possibility to achieve the same with mvnw? My point is to make an improvement to the current state of affairs in the long run rather than expect people to know a manual workaround.

@yyoncho

This comment has been minimized.

Copy link
Member

commented Jun 4, 2019

Everything is possible but we have pretty limited resources and we often settle with the workaround, there are 100+ open issues in the organization and dozens of missing features and we have to prioritize.

Anyway, once you confirm that mvn solution works, you may download the content of https://github.com/emacs-lsp/lsp-java/tree/master/install and try to figure out why mvnw does not pick the ~/.m2/settings.xml.

@Alexander-Shukaev

This comment has been minimized.

Copy link
Author

commented Jun 4, 2019

I found out that mvnw does not respect settings.xml. There are two options:

  1. (setenv "MAVEN_OPTS" "-Dhttp.proxyHost=proxyhost -Dhttp.proxyPort=8080 -Dhttps.proxyHost=proxyhost -Dhttps.proxyPort=8080");
  2. .mvn/jvm.config:
-Dhttp.proxyHost=host 
-Dhttp.proxyPort=port 
-Dhttps.proxyHost=host 
-Dhttps.proxyPort=port 
-Dhttp.proxyUser=username 
-Dhttp.proxyPassword=password

Would you mind to add defcustom for lsp-java-mvnw-proxy-host (default nil) and lsp-java-mvnw-proxy-port (default nil) to be set by users of lsp-java optionally? If either of them is not nil, then perform (setenv "MAVEN_OPTS" ...) prior to calling mvnw.

Furthermore, the main change is to support both jvm.config (if user has one, potentially with proxies defined) and settings.xml for further Maven invocations (if user has one, potentially with proxies defined). To do that change lsp-java--prepare-mvnw to:

(defun lsp-java--prepare-mvnw ()
  "Download mvnw."
  (let ((mvn-executable (if (string-equal system-type "windows-nt")
                            "mvnw.cmd"
                          "mvnw"))
        (downloader ".mvn/wrapper/MavenWrapperDownloader.java")
        (properties ".mvn/wrapper/maven-wrapper.properties"))
    (mkdir ".mvn/wrapper/" t)
    (copy-file "~/.m2/jvm.config" ".mvn/jvm.config")
    (copy-file "~/.m2/settings.xml" ".mvn/settings.xml")
    (f-write-text "-s .mvn/settings.xml" 'utf-8 ".mvn/maven.config")
    (url-copy-file (concat lsp-java--download-root mvn-executable)
                   mvn-executable
                   t)
    (url-copy-file (concat lsp-java--download-root downloader) downloader t)
    (url-copy-file (concat lsp-java--download-root properties) properties t)
    (if (string= system-type "windows-nt")
        mvn-executable
      (concat "sh " mvn-executable))))

Finally, snippet

(or (lsp-java--prepare-mvnw) (executable-find "mvn"))

seems to be ill-formed. This logic will never use mvn because lsp-java--prepare-mvnw returns always non-nil. Please, give a defcustom to choose using mvn explicitly instead of mvnw. Also real falling back to mvn should be done if mvnw is somehow not available but for that, lsp-java--prepare-mvnw has to be changed.

@yyoncho

This comment has been minimized.

Copy link
Member

commented Jun 4, 2019

This logic will never use mvn because lsp-java--prepare-mvnw returns always non-nil. Please, give a defcustom to choose using mvn explicitly instead of mvnw. Also real falling back to mvn should be done if mvnw is somehow not available but for that, lsp-java--prepare-mvnw has to be changed.

It is a typo - it should be - use mvn if present otherwise fallback to downloading and configuring mvnw. Fixed with 1502492 . I was thinking also about packaging mvnw as part lsp-java. I might be wrong but this will fix this issue too since you will be able to define .mvn/jvm-settings file since it will be in a well-known location. Also, I was planning to create a job which will package and publish all lsp-java dependencies so the manual installation will be download and unzip in case the automatic download does not work.

For your suggestion, it will probably work but requires more work in order to be generic. E. g. ...

    (copy-file "~/.m2/jvm.config" ".mvn/jvm.config")
    (copy-file "~/.m2/settings.xml" ".mvn/settings.xml")

... but user settings might not be located on this location, etc. I am a bit concerned that this will increase the overall complexity of the installation.

@Alexander-Shukaev

This comment has been minimized.

Copy link
Author

commented Jun 4, 2019

I was thinking of it to be more like a best effort approach:

    (copy-file "~/.m2/jvm.config" ".mvn/jvm.config")
    (copy-file "~/.m2/settings.xml" ".mvn/settings.xml")

That is copy them if any of them are there because this is what one would expect probably not to notice any difference between mvn and mvnw. Of course it should not throw any error if they are not there.

For future visitors and/or for your consideration, sharing my generic snippet to generate MAVEN_OPTS:

  (when (zerop (length (getenv "MAVEN_OPTS")))
    (let (maven-opts)
      (dolist (scheme '("http" "https"))
        (url-scheme-register-proxy scheme)
        (let ((proxy  (cdr (assoc scheme url-proxy-services)))
              (urlobj nil))
          (unless (zerop (length proxy))
            (save-match-data
              (cond ((string-match "^\\([^:]+\\):\\([0-9]+\\)$" proxy)
                     (setq urlobj (url-generic-parse-url nil))
                     (setf (url-type urlobj) scheme)
                     (setf (url-host urlobj) (match-string 1 proxy))
                     (setf (url-port urlobj)
                           (string-to-number (match-string 2 proxy))))
                    ((string-match url-nonrelative-link proxy)
                     (setq urlobj (url-generic-parse-url proxy))
                     (setf (url-type   urlobj) scheme)
                     (setf (url-target urlobj) nil))
                    (t
                     (setq urlobj (url-generic-parse-url nil))
                     (setf (url-type urlobj) scheme)
                     (setf (url-host urlobj) proxy))))
            (setq maven-opts (nconc maven-opts
                                    `(,(format "-D%s.proxyHost=%s"
                                               (url-type urlobj)
                                               (url-host urlobj))
                                      ,(format "-D%s.proxyPort=%d"
                                               (url-type urlobj)
                                               (url-port urlobj))))))))
      (setenv "MAVEN_OPTS" (mapconcat #'identity maven-opts " "))))

All of this works well with standard http_proxy and https_proxy environment variables for proxy configuration.
See Info node `(url) Proxies'.

@yyoncho

This comment has been minimized.

Copy link
Member

commented Jun 4, 2019

Thank you. If you want to prepare a PR from that(or if you are interested in contributing to any other emacs-lsp project) I will be happy to review/merge it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.