2022-09-06 11:15:21 +02:00
package io.gitlab.jfronny.inceptum.common ;
2023-05-05 18:49:56 +02:00
import io.gitlab.jfronny.inceptum.common.model.inceptum.GC_UpdateMetadata ;
import io.gitlab.jfronny.inceptum.common.model.inceptum.GC_WrapperConfig ;
2022-09-06 11:15:21 +02:00
import io.gitlab.jfronny.commons.OSUtils ;
import io.gitlab.jfronny.inceptum.common.api.MavenApi ;
import io.gitlab.jfronny.inceptum.common.model.inceptum.* ;
2022-09-06 21:20:59 +02:00
import io.gitlab.jfronny.inceptum.common.model.maven.* ;
2022-09-06 11:15:21 +02:00
import org.jetbrains.annotations.Nullable ;
import org.xml.sax.SAXException ;
import javax.xml.stream.XMLStreamException ;
2022-11-04 12:41:41 +01:00
import java.io.* ;
2022-09-06 11:15:21 +02:00
import java.net.URISyntaxException ;
import java.nio.file.Files ;
import java.nio.file.Path ;
import java.util.* ;
import java.util.function.Consumer ;
2023-05-05 18:49:56 +02:00
import java.util.stream.Collectors ;
2022-09-06 11:15:21 +02:00
import java.util.stream.Stream ;
public class Updater {
2022-11-04 12:41:41 +01:00
public static final String PROJECT_MAVEN = " https://maven.frohnmeyer-wds.de/artifacts/ " ;
2022-11-03 17:07:55 +01:00
private static final String ARTIFACTS_URL = " https://pages.frohnmeyer-wds.de/JfMods/Inceptum/artifacts/ " ;
private static final String STABLE_URL = " https://pages.frohnmeyer-wds.de/JfMods/Inceptum/stable/ " ;
2022-09-06 11:15:21 +02:00
2022-11-04 13:00:37 +01:00
public static UpdateMetadata getUpdate ( boolean versionCompare , boolean checkEnv ) throws UpdateCheckException {
return Updater . check ( InceptumConfig . channel , versionCompare , checkEnv , channel - > {
2022-09-06 11:15:21 +02:00
Utils . LOGGER . error ( " No stable version was found, switching to experimental channel " ) ;
2022-09-07 18:06:34 +02:00
InceptumConfig . channel = channel ;
InceptumConfig . saveConfig ( ) ;
2022-09-06 11:15:21 +02:00
} ) ;
}
public static void update ( UpdateMetadata source , boolean relaunch ) throws IOException , URISyntaxException {
2023-05-05 18:49:56 +02:00
Utils . LOGGER . info ( " Downloading version " + source . version ( ) ) ;
2022-09-06 11:15:21 +02:00
2022-11-18 21:58:40 +01:00
WrapperConfig config = new WrapperConfig (
new LinkedHashSet < > ( ) ,
2023-05-05 18:49:56 +02:00
new LinkedHashSet < > ( source . repositories ( ) ) ,
2022-11-18 21:58:40 +01:00
new HashMap < > ( )
) ;
2023-05-05 18:49:56 +02:00
source . natives ( ) . forEach ( ( k , v ) - > config . natives ( ) . put ( k , new LinkedHashSet < > ( v ) ) ) ;
2022-09-06 11:15:21 +02:00
2023-05-05 18:49:56 +02:00
DependencyNode node = downloadLibrary ( source . repositories ( ) , " io.gitlab.jfronny.inceptum:launcher-dist: " + source . version ( ) , config . libraries ( ) ) ;
2022-09-06 21:20:59 +02:00
Utils . LOGGER . info ( " Downloaded Dependencies: \ n " + node ) ;
2022-09-06 11:15:21 +02:00
2023-05-05 18:49:56 +02:00
List < String > currentLibraries = new LinkedList < > ( config . libraries ( ) ) ;
if ( source . natives ( ) . containsKey ( Utils . getCurrentFlavor ( ) ) ) {
2022-09-06 21:20:59 +02:00
Set < String > natives = new LinkedHashSet < > ( ) ;
2023-05-05 18:49:56 +02:00
for ( String lib : source . natives ( ) . get ( Utils . getCurrentFlavor ( ) ) ) {
downloadLibrary ( source . repositories ( ) , lib , natives ) ;
2022-09-06 11:15:21 +02:00
}
currentLibraries . addAll ( natives ) ;
2023-05-05 18:49:56 +02:00
config . natives ( ) . put ( Utils . getCurrentFlavor ( ) , natives ) ;
2022-09-06 11:15:21 +02:00
}
2022-11-24 21:11:07 +01:00
GC_WrapperConfig . write ( config , MetaHolder . WRAPPER_CONFIG_PATH ) ;
2022-09-06 11:15:21 +02:00
if ( relaunch ) {
2023-05-05 18:49:56 +02:00
Runtime . getRuntime ( ) . addShutdownHook ( new Thread ( ( ) - > {
2022-09-06 11:15:21 +02:00
try {
2023-05-05 18:49:56 +02:00
new ProcessBuilder ( OSUtils . getJvmBinary ( ) ,
2022-09-06 11:15:21 +02:00
" -cp " ,
buildClasspath ( currentLibraries . stream ( ) )
. map ( Path : : toString )
2023-05-05 18:49:56 +02:00
. collect ( Collectors . joining ( String . valueOf ( File . pathSeparatorChar ) ) )
2022-09-06 11:15:21 +02:00
) . inheritIO ( ) . start ( ) ;
} catch ( IOException e ) {
Utils . LOGGER . error ( " Could not relaunch " , e ) ;
}
} ) ) ;
}
}
public static List < Path > getLaunchClasspath ( WrapperConfig wrapperConfig ) throws IOException , URISyntaxException {
2023-05-05 18:49:56 +02:00
Set < String > natives = wrapperConfig . natives ( ) . get ( Utils . getCurrentFlavor ( ) ) ;
2022-09-06 21:20:59 +02:00
if ( natives = = null ) natives = new LinkedHashSet < > ( ) ;
2023-05-05 18:49:56 +02:00
Set < String > libs = wrapperConfig . libraries ( ) ;
2022-09-06 21:20:59 +02:00
if ( libs = = null ) libs = new LinkedHashSet < > ( ) ;
2022-09-06 11:15:21 +02:00
boolean configChanged = false ;
for ( String lib : libs ) {
2023-05-05 18:49:56 +02:00
Path p = ArtifactMeta . parse ( lib ) . getLocalPath ( ) ;
2022-09-06 11:15:21 +02:00
if ( ! Files . exists ( p ) ) {
configChanged = true ;
2023-05-05 18:49:56 +02:00
downloadLibrary ( wrapperConfig . repositories ( ) , lib , libs ) ;
2022-09-06 11:15:21 +02:00
}
}
for ( String lib : natives ) {
2023-05-05 18:49:56 +02:00
Path p = ArtifactMeta . parse ( lib ) . getLocalPath ( ) ;
2022-09-06 11:15:21 +02:00
if ( ! Files . exists ( p ) ) {
configChanged = true ;
2023-05-05 18:49:56 +02:00
downloadLibrary ( wrapperConfig . repositories ( ) , lib , natives ) ;
2022-09-06 11:15:21 +02:00
}
}
2022-11-24 21:11:07 +01:00
if ( configChanged ) GC_WrapperConfig . write ( wrapperConfig , MetaHolder . WRAPPER_CONFIG_PATH ) ;
2022-09-06 11:15:21 +02:00
2023-05-05 18:49:56 +02:00
return buildClasspath ( Stream . concat ( libs . stream ( ) , natives . stream ( ) ) ) . toList ( ) ;
2022-09-06 11:15:21 +02:00
}
private static Stream < Path > buildClasspath ( Stream < String > libraries ) {
2022-11-04 12:41:41 +01:00
return libraries . map ( ArtifactMeta : : parse ) . map ( ArtifactMeta : : getLocalPath ) ;
2022-09-06 11:15:21 +02:00
}
2022-09-06 21:20:59 +02:00
private static DependencyNode downloadLibrary ( Set < String > repositories , final String artifact , Set < String > libraries ) throws IOException , URISyntaxException {
2022-11-04 12:41:41 +01:00
List < FileNotFoundException > suppressed = new LinkedList < > ( ) ;
2023-05-05 18:49:56 +02:00
for ( String repository : Stream . concat ( Stream . of ( PROJECT_MAVEN ) , repositories . stream ( ) ) . toList ( ) ) {
2022-11-04 12:41:41 +01:00
ArtifactMeta meta ;
try {
meta = MavenApi . getMetadata ( repository , artifact ) ;
} catch ( FileNotFoundException ignored ) {
meta = ArtifactMeta . parse ( artifact ) ;
} catch ( IOException | URISyntaxException | SAXException e ) {
throw new IOException ( " Could not download artifact from " + repository , e ) ;
}
2022-09-06 11:15:21 +02:00
Pom pom ;
try {
2022-11-04 12:41:41 +01:00
pom = MavenApi . getPom ( repository , meta ) ;
} catch ( FileNotFoundException notFound ) {
suppressed . add ( notFound ) ;
2022-09-06 11:15:21 +02:00
continue ;
2022-11-04 12:41:41 +01:00
} catch ( IOException | URISyntaxException | XMLStreamException | SAXException e ) {
2023-05-05 18:49:56 +02:00
throw new IOException ( " Could not download artifact " + meta . getMavenNotation ( ) + " from " + repository , e ) ;
2022-09-06 11:15:21 +02:00
}
2022-09-06 21:20:59 +02:00
Set < DependencyNode > dependencies = new LinkedHashSet < > ( ) ;
2023-05-05 18:49:56 +02:00
if ( pom . dependencies ( ) ! = null ) {
for ( MavenDependency dependency : pom . dependencies ( ) ) {
String mvnName = dependency . groupId ( ) + " : " + dependency . artifactId ( ) + " : " + dependency . version ( ) ;
2022-09-06 21:20:59 +02:00
dependencies . add ( downloadLibrary ( repositories , mvnName , libraries ) ) ;
2022-09-06 12:35:29 +02:00
}
2022-09-06 11:15:21 +02:00
}
2022-11-04 12:41:41 +01:00
MavenApi . downloadLibrary ( repository , meta ) ;
2022-09-06 11:15:21 +02:00
libraries . add ( artifact ) ;
2022-11-04 12:41:41 +01:00
return new DependencyNode ( artifact , dependencies ) ;
2022-09-06 12:35:29 +02:00
}
2022-11-04 12:41:41 +01:00
IOException e = new IOException ( " Could not find any repository containing the artifact " + artifact + " (searched: " + String . join ( " , " , repositories ) + " ) " ) ;
for ( FileNotFoundException ex : suppressed ) e . addSuppressed ( ex ) ;
throw e ;
2022-09-06 11:15:21 +02:00
}
2022-11-04 13:00:37 +01:00
public static @Nullable UpdateMetadata check ( UpdateChannel channel , boolean versionCompare , boolean checkEnv , Consumer < UpdateChannel > channelInvalid ) throws UpdateCheckException {
2022-09-06 11:15:21 +02:00
try {
2022-11-24 21:11:07 +01:00
UpdateMetadata experimental = Net . downloadObject ( ARTIFACTS_URL + " version.json " , json - > GC_UpdateMetadata . read ( json ) ) ;
2022-09-06 11:15:21 +02:00
UpdateMetadata stable = null ;
2022-11-03 17:07:55 +01:00
try {
2022-11-24 21:11:07 +01:00
stable = Net . downloadObject ( STABLE_URL + " version.json " , json - > GC_UpdateMetadata . read ( json ) ) ;
2022-11-03 17:07:55 +01:00
} catch ( Throwable ignored ) { }
if ( stable = = null & & channel = = UpdateChannel . Stable ) {
2022-09-06 11:15:21 +02:00
channel = UpdateChannel . CI ;
channelInvalid . accept ( channel ) ;
}
UpdateMetadata info = switch ( channel ) {
case CI - > experimental ;
case Stable - > stable ;
} ;
2022-11-04 13:00:37 +01:00
if ( checkEnv ) {
2023-05-05 18:49:56 +02:00
if ( info . jvm ( ) > Runtime . version ( ) . feature ( ) ) throw new UpdateCheckException ( " A newer JVM is required to use the latest inceptum version. Please update! " , " Outdated Java " ) ;
if ( info . wrapperVersion ( ) ! = BuildMetadata . WRAPPER_VERSION ) throw new UpdateCheckException ( " A different version of the Inceptum Wrapper is required for this update! " , " Mismatched Wrapper " ) ;
2022-09-06 11:15:21 +02:00
}
2022-11-03 17:07:55 +01:00
if ( versionCompare ) {
2023-05-05 18:49:56 +02:00
Utils . LOGGER . info ( " Latest version is " + info . version ( ) + " , current is " + BuildMetadata . VERSION ) ;
if ( BuildMetadata . BUILD_TIME > = info . buildTime ( ) ) {
2022-11-03 17:07:55 +01:00
Utils . LOGGER . info ( " Up-to-date " ) ;
return null ;
}
}
2022-09-06 11:15:21 +02:00
return info ;
2022-11-03 17:07:55 +01:00
} catch ( IOException e ) {
2022-09-06 11:15:21 +02:00
Utils . LOGGER . error ( " Could not check for updates " , e ) ;
}
return null ;
}
2022-11-03 17:07:55 +01:00
public static String getShadowJarUrl ( UpdateChannel channel ) {
return switch ( channel ) {
case CI - > ARTIFACTS_URL ;
case Stable - > STABLE_URL ;
2023-05-05 18:49:56 +02:00
} + " /Inceptum- " + Utils . getCurrentFlavor ( ) + " .jar " ;
2022-09-06 11:15:21 +02:00
}
2022-11-04 13:00:37 +01:00
public static class UpdateCheckException extends Exception {
public final String message ;
public final String title ;
public UpdateCheckException ( String message , String title ) {
super ( message ) ;
this . message = message ;
this . title = title ;
}
}
2022-09-06 11:15:21 +02:00
}