Skip to content

Commit 0053724

Browse files
committed
fix: add jdts Download
1 parent bb007cc commit 0053724

3 files changed

Lines changed: 173 additions & 170 deletions

File tree

lang/java/java_env_setup_README.md

Lines changed: 0 additions & 83 deletions
This file was deleted.

lang/java/lib.go

Lines changed: 173 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@
1515
package java
1616

1717
import (
18+
"archive/tar"
19+
"compress/gzip"
1820
"fmt"
21+
"io"
22+
"log"
23+
"net/http"
1924
"os"
2025
"path/filepath"
2126
"runtime"
@@ -26,25 +31,188 @@ import (
2631
"github.com/cloudwego/abcoder/lang/utils"
2732
)
2833

29-
const MaxWaitDuration = 5 * time.Second
34+
const (
35+
MaxWaitDuration = 5 * time.Second
36+
jdtlsVersion = "1.39.0-202408291433"
37+
jdtlsURL = "https://download.eclipse.org/jdtls/milestones/1.39.0/jdt-language-server-1.39.0-202408291433.tar.gz"
38+
)
39+
40+
// untar takes a destination path and a reader; a tar reader loops over the tar file
41+
// and writes each file to the destination path.
42+
func untar(dst string, r io.Reader) error {
43+
gzr, err := gzip.NewReader(r)
44+
if err != nil {
45+
return err
46+
}
47+
defer gzr.Close()
48+
49+
tr := tar.NewReader(gzr)
50+
51+
for {
52+
header, err := tr.Next()
53+
54+
switch {
55+
// if no more files are found return
56+
case err == io.EOF:
57+
return nil
58+
// return any other error
59+
case err != nil:
60+
return err
61+
// if the header is nil, just skip it (not sure how this happens)
62+
case header == nil:
63+
continue
64+
}
65+
66+
// the target location where the dir/file should be created
67+
target := filepath.Join(dst, header.Name)
68+
69+
// check the file type
70+
switch header.Typeflag {
71+
72+
// if its a dir and it doesn't exist create it
73+
case tar.TypeDir:
74+
if _, err := os.Stat(target); err != nil {
75+
if err := os.MkdirAll(target, 0755); err != nil {
76+
return err
77+
}
78+
}
79+
80+
// if it's a file create it
81+
case tar.TypeReg:
82+
// make sure the directory for the file exists
83+
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
84+
return err
85+
}
86+
87+
f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
88+
if err != nil {
89+
return err
90+
}
91+
92+
// copy over contents
93+
if _, err := io.Copy(f, tr); err != nil {
94+
f.Close()
95+
return err
96+
}
97+
98+
// manually close here after each file operation; defering would cause each file close
99+
// to wait until all operations have completed.
100+
f.Close()
101+
}
102+
}
103+
}
104+
105+
func setupJDTLS() (string, error) {
106+
_, currentFile, _, ok := runtime.Caller(0)
107+
if !ok {
108+
return "", fmt.Errorf("failed to get current file path")
109+
}
110+
javaDir := filepath.Dir(currentFile)
111+
installDir := filepath.Join(javaDir, "lsp", "jdtls")
112+
113+
// Check for any existing JDTLS installation
114+
existingDirs, err := filepath.Glob(filepath.Join(installDir, "jdt-language-server-*"))
115+
if err == nil && len(existingDirs) > 0 {
116+
for _, dir := range existingDirs {
117+
info, err := os.Stat(dir)
118+
if err == nil && info.IsDir() {
119+
// Check if launcher jar exists in this directory
120+
launcherPattern := filepath.Join(dir, "plugins", "org.eclipse.equinox.launcher_*.jar")
121+
matches, err := filepath.Glob(launcherPattern)
122+
if err == nil && len(matches) > 0 {
123+
log.Printf("Found existing JDT Language Server at %s. Skipping installation.", dir)
124+
return dir, nil
125+
}
126+
}
127+
}
128+
}
129+
130+
log.Printf("JDT Language Server not found locally. Downloading and installing version %s...", jdtlsVersion)
131+
jdtlsDir := filepath.Join(installDir, "jdt-language-server-"+jdtlsVersion)
132+
133+
// Create download directory
134+
downloadDir := filepath.Join(installDir, "download")
135+
if err := os.MkdirAll(downloadDir, 0755); err != nil {
136+
return "", fmt.Errorf("failed to create download directory: %w", err)
137+
}
138+
139+
// Download
140+
tarballName := "jdt-language-server-" + jdtlsVersion + ".tar.gz"
141+
tarballPath := filepath.Join(downloadDir, tarballName)
142+
log.Printf("Downloading from %s...", jdtlsURL)
143+
resp, err := http.Get(jdtlsURL)
144+
if err != nil {
145+
return "", fmt.Errorf("failed to download JDTLS: %w", err)
146+
}
147+
defer resp.Body.Close()
148+
149+
if resp.StatusCode != http.StatusOK {
150+
return "", fmt.Errorf("failed to download JDTLS: received status code %d", resp.StatusCode)
151+
}
152+
153+
out, err := os.Create(tarballPath)
154+
if err != nil {
155+
return "", fmt.Errorf("failed to create tarball file: %w", err)
156+
}
157+
//defer os.Remove(tarballPath) // Clean up tarball after function returns
158+
159+
_, err = io.Copy(out, resp.Body)
160+
if err != nil {
161+
out.Close()
162+
return "", fmt.Errorf("failed to save tarball: %w", err)
163+
}
164+
out.Close() // Close file before untarring
165+
166+
// Extract
167+
log.Printf("Extracting to %s...", installDir)
168+
file, err := os.Open(tarballPath)
169+
if err != nil {
170+
return "", fmt.Errorf("failed to open tarball: %w", err)
171+
}
172+
defer file.Close()
173+
174+
if err := untar(jdtlsDir, file); err != nil {
175+
return "", fmt.Errorf("failed to extract JDTLS: %w", err)
176+
}
177+
178+
log.Printf("JDT Language Server installed successfully in %s.", jdtlsDir)
179+
return jdtlsDir, nil
180+
}
30181

31182
func GetDefaultLSP(LspOptions map[string]string) (lang uniast.Language, name string) {
32183
return uniast.Java, generateExecuteCmd(LspOptions)
33184
}
34185

35186
func generateExecuteCmd(LspOptions map[string]string) string {
187+
var jdtRootPATH string
188+
// First, check environment variable
189+
if envPath := os.Getenv("JDTLS_ROOT_PATH"); len(envPath) != 0 {
190+
jdtRootPATH = envPath
191+
log.Printf("Using JDTLS_ROOT_PATH from environment: %s", jdtRootPATH)
192+
} else {
193+
// If env var is not set, run auto-setup
194+
var err error
195+
jdtRootPATH, err = setupJDTLS()
196+
if err != nil {
197+
panic(fmt.Sprintf("Failed to setup JDT Language Server: %v", err))
198+
}
199+
}
200+
36201
// Get the absolute path to the current file
37202
_, currentFile, _, ok := runtime.Caller(0)
38203
if !ok {
39204
panic("Failed to get current file path")
40205
}
41206
javaDir := filepath.Dir(currentFile)
42207

43-
jdtRootPATH := filepath.Join(javaDir, "lsp", "jdtls", "jdt-language-server-1.39.0-202408291433")
44-
if len(os.Getenv("JDTlS_ROOT_PATH")) != 0 {
45-
jdtRootPATH = os.Getenv("JDTlS_ROOT_PATH")
208+
// Find launcher jar
209+
launcherPattern := filepath.Join(jdtRootPATH, "plugins", "org.eclipse.equinox.launcher_*.jar")
210+
matches, err := filepath.Glob(launcherPattern)
211+
if err != nil || len(matches) == 0 {
212+
panic(fmt.Sprintf("Could not find org.eclipse.equinox.launcher_*.jar in %s/plugins", jdtRootPATH))
46213
}
47-
jdtLsPath := filepath.Join(jdtRootPATH, "plugins", "org.eclipse.equinox.launcher_1.6.900.v20240613-2009.jar")
214+
jdtLsPath := matches[0]
215+
48216
// Determine the configuration path based on OS and architecture
49217
var osName string
50218
switch runtime.GOOS {

lang/java/lsp/setup_java_env.sh

Lines changed: 0 additions & 82 deletions
This file was deleted.

0 commit comments

Comments
 (0)