1+ const axios = require ( "axios" ) ;
12const gulp = require ( "gulp" ) ;
23const download = require ( "gulp-download2" ) ;
34const cp = require ( "child_process" ) ;
5+ const { XMLParser } = require ( 'fast-xml-parser' ) ;
6+
7+ const fs = require ( 'fs' ) ;
8+ const path = require ( 'path' ) ;
9+
10+ const { finished } = require ( 'stream' ) ;
11+ const { promisify } = require ( 'util' ) ;
12+ const finishedAsync = promisify ( finished ) ;
13+
14+ const MC_BASE_URL = "https://repo1.maven.org/maven2" ;
15+ const MC_SNAPSHOT_BASE_URL = "https://central.sonatype.com/repository/maven-snapshots" ;
416
517const libertyGroupId = "io.openliberty.tools" ;
6- const libertyVersion = "2.2.1" ;
18+ const libertyLemminxArtifactId = "liberty-langserver-lemminx" ;
19+ const libertyLSArtifactId = "liberty-langserver" ;
20+ const libertyVersion = "2.3.1" ;
721const jakartaGroupId = "org.eclipse.lsp4jakarta" ;
822const jakartaVersion = "0.2.3" ;
9- var releaseLevel = "releases" ; //"snapshots"; //snapshots or releases
23+ var lclsReleaseLevel = "releases" ; //snapshots or releases
24+ var jakartaReleaseLevel = "releases" ;
1025
1126const libertyLemminxName = "liberty-langserver-lemminx-" + libertyVersion + "-jar-with-dependencies.jar" ;
1227const libertyLemminxDir = "../liberty-language-server/lemminx-liberty" ;
@@ -53,35 +68,28 @@ gulp.task("buildJakartaLs", (done) => {
5368 done ( ) ;
5469} ) ;
5570
56- //https://oss.sonatype.org/service/local/artifact/maven/content?r=snapshots&g=io.openliberty.tools&a=liberty-langserver-lemminx&c=jar-with-dependencies&v=1.0-SNAPSHOT
57- //https://oss.sonatype.org/service/local/artifact/maven/content?r=snapshots&g=io.openliberty.tools&a=liberty-langserver&c=jar-with-dependencies&v=1.0-SNAPSHOT
58- const sonatypeURL = "https://oss.sonatype.org/service/local/artifact/maven/content" ;
59- const releaseLevelString = "?r=" + releaseLevel ;
60- const libertyGroupIdString = "&g=" + libertyGroupId ;
61- const libertyVersionString = "&v=" + libertyVersion ;
62- const classifierString = "&c=jar-with-dependencies" ;
71+ gulp . task ( "downloadLibertyLSJars" , async function ( ) {
72+ var libertyLemminxURL ;
73+ var libertyLSURL ;
6374
64- const libertyLemminxURL = sonatypeURL + releaseLevelString + libertyGroupIdString + "&a=liberty-langserver-lemminx" + classifierString + libertyVersionString ;
65- const libertyLSURL = sonatypeURL + releaseLevelString + libertyGroupIdString + "&a=liberty-langserver" + classifierString + libertyVersionString ;
75+ if ( lclsReleaseLevel === "snapshots" ) {
76+ libertyLemminxURL = await generateSnapshotJarURL ( libertyGroupId , libertyLemminxArtifactId , libertyVersion , "jar-with-dependencies" ) ;
77+ libertyLSURL = await generateSnapshotJarURL ( libertyGroupId , libertyLSArtifactId , libertyVersion , "jar-with-dependencies" ) ;
78+ } else {
79+ libertyLemminxURL = getMavenCentralJarURL ( libertyGroupId , libertyLemminxArtifactId , libertyVersion , "jar-with-dependencies" ) ;
80+ libertyLSURL = getMavenCentralJarURL ( libertyGroupId , libertyLSArtifactId , libertyVersion , "jar-with-dependencies" ) ;
81+ }
6682
67- gulp . task ( "downloadLibertyLSJars" , ( done ) => {
68- download ( {
69- url : libertyLemminxURL ,
70- file : libertyLemminxName ,
71- } )
72- . pipe ( gulp . dest ( "./jars" , { encoding : false } ) ) ;
73- download ( {
74- url : libertyLSURL ,
75- file : libertyLSName ,
76- } )
77- . pipe ( gulp . dest ( "./jars" , { encoding : false } ) ) ;
78- done ( ) ;
83+ await Promise . all ( [
84+ downloadJar ( libertyLemminxURL , libertyLemminxName , "./jars" ) ,
85+ downloadJar ( libertyLSURL , libertyLSName , "./jars" )
86+ ] ) ;
7987} ) ;
8088
8189//https://repo.eclipse.org/service/local/artifact/maven/content?r=snapshots&g=org.eclipse.lsp4jakarta&a=org.eclipse.lsp4jakarta.jdt.core&v=0.0.1-SNAPSHOT
8290//https://repo.eclipse.org/service/local/artifact/maven/content?r=snapshots&g=org.eclipse.lsp4jakarta&a=org.eclipse.lsp4jakarta.ls&c=jar-with-dependencies&v=0.0.1-SNAPSHOT
8391const eclipseRepoURL = "https://repo.eclipse.org/service/local/artifact/maven/content" ;
84- const jakartaReleaseLevelString = "?r=" + releaseLevel ;
92+ const jakartaReleaseLevelString = "?r=" + jakartaReleaseLevel ;
8593const jakartaGroupIdString = "&g=" + jakartaGroupId ;
8694const jakartaVersionString = "&v=" + jakartaVersion ;
8795const jakartaClassifierString = "&c=jar-with-dependencies" ;
@@ -95,7 +103,7 @@ gulp.task("downloadLSP4JakartaJars", (done) => {
95103 file : jakartaJdtName ,
96104 } )
97105 . pipe ( gulp . dest ( "./jars" , { encoding : false } ) ) ;
98- download ( {
106+ download ( {
99107 url : jakartaLSURL ,
100108 file : jakartaLSName ,
101109 } )
@@ -110,3 +118,75 @@ function mvnw() {
110118function isWin ( ) {
111119 return / ^ w i n / . test ( process . platform ) ;
112120}
121+
122+ // Handle jar download through axios, gulp download failed with 403 on Maven Central snapshot repo
123+ async function downloadJar ( url , fileName , destDir ) {
124+ const response = await axios . get ( url , {
125+ headers : {
126+ 'User-Agent' : 'Mozilla/5.0 (Node.js downloader)' ,
127+ 'Accept' : `*/*`
128+ } ,
129+ responseType : 'stream'
130+ } ) ;
131+
132+ console . log ( `Downloading ${ url } ` ) ;
133+ const fullPath = path . join ( destDir , fileName ) ;
134+ const writer = fs . createWriteStream ( fullPath ) ;
135+ response . data . pipe ( writer ) ;
136+ await finishedAsync ( writer ) ;
137+ console . log ( `Downloaded ${ fileName } ` ) ;
138+ }
139+
140+ // Generate Maven Central artifact URL for specified GAV coordinates
141+ // Example: https://repo1.maven.org/maven2/io/openliberty/tools/liberty-langserver/2.3.1/liberty-langserver-2.3.1-jar-with-dependencies.jar
142+ function getMavenCentralJarURL ( groupId , artifactId , version , classifier ) {
143+ const classifierString = classifier ? `-${ classifier } ` : '' ;
144+ const mavenCentralJarURL = `${ MC_BASE_URL } /${ groupId . replace ( / \. / g, '/' ) } /${ artifactId } /${ version } /${ artifactId } -${ version } ${ classifierString } .jar` ;
145+ return mavenCentralJarURL ;
146+ }
147+
148+ // No API provided to retrieve snapshot artifacts hosted on https://central.sonatype.com/repository/maven-snapshots
149+ // Can access maven-metadata.xml using GAV coordinates for artifacts
150+ // Will parse retrieved maven-metadata.xml for full artifact version, including timestamp
151+ // Example: https://central.sonatype.com/repository/maven-snapshots/io/openliberty/tools/liberty-langserver/2.3.1-SNAPSHOT/maven-metadata.xml -> 2.3.1-20250714.163135-2
152+ async function resolveSnapshotVersionFromMetadata ( groupId , artifactId , snapshotVersion , classifier ) {
153+ // Generate maven-metadata.xml URL
154+ const metadataURL = `${ MC_SNAPSHOT_BASE_URL } /${ groupId . replace ( / \. / g, '/' ) } /${ artifactId } /${ snapshotVersion } /maven-metadata.xml` ;
155+ console . log ( `Fetching maven-metadata.xml: ${ metadataURL } ` ) ;
156+
157+ // Fetch and parse maven-metadata.xml
158+ const response = await axios . get ( metadataURL ) ;
159+ // console.log(response.data);
160+ const parser = new XMLParser ( ) ;
161+ const parsedXML = parser . parse ( response . data ) ;
162+
163+ // Get all <snapshotVersion> entries
164+ const versions = parsedXML ?. metadata ?. versioning ?. snapshotVersions . snapshotVersion || [ ] ;
165+
166+ const targetClassifier = classifier || null ;
167+
168+ // Filter entries, only list jar files, match classifier if provided
169+ const snapshotVersionEntry = versions . find ( v => {
170+ const extensionMatch = v . extension === 'jar' ;
171+ const classifierValue = v . classifier || null ;
172+
173+ return extensionMatch && classifierValue === targetClassifier ;
174+ } ) ;
175+
176+ if ( ! snapshotVersionEntry ) {
177+ throw new Error ( `No snapshot JAR found matching parameters: ${ groupId } :${ artifactId } :${ classifier || '(no classifier)' } :${ snapshotVersion } ` ) ;
178+ }
179+
180+ console . log ( `Resolved full snapshot version for ${ artifactId } : ${ snapshotVersionEntry . value } ` ) ;
181+ return snapshotVersionEntry . value ;
182+ }
183+
184+ // Generate Maven Central artifact URL for a SNAPSHOT dependency with provided GAV coordinates
185+ // LCLS 2.3.1-SNAPSHOT jar-with-dependencies: <MC_SNAPSHOT_BASE_URL>/io/openliberty/tools/liberty-langserver/2.3.1-SNAPSHOT/liberty-langserver-2.3.1-20250714.163135-2-jar-with-dependencies.jar
186+ async function generateSnapshotJarURL ( groupId , artifactId , snapshotVersion , classifier ) {
187+ const snapshotJarVersion = await resolveSnapshotVersionFromMetadata ( groupId , artifactId , snapshotVersion , classifier ) ;
188+ const classifierString = classifier ? `-${ classifier } ` : '' ; //Format classifier for URL if defined
189+ const snapshotJarURL = `${ MC_SNAPSHOT_BASE_URL } /${ groupId . replace ( / \. / g, '/' ) } /${ artifactId } /${ snapshotVersion } /${ artifactId } -${ snapshotJarVersion } ${ classifierString } .jar` ;
190+ console . log ( `${ groupId } :${ artifactId } :${ snapshotVersion } :${ classifier } URL: ${ snapshotJarURL } ` ) ;
191+ return snapshotJarURL ;
192+ }
0 commit comments