[FEATURE] Раширение pipeline на EXE

This commit is contained in:
Gravit 2019-10-27 23:51:48 +07:00
parent f3c7f57e50
commit 5446142e6a
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
9 changed files with 259 additions and 198 deletions

View file

@ -396,18 +396,6 @@ private LauncherBinary binary() {
LogHelper.error(e);
}
}
if (config.launch4j.alternative != null) {
switch (config.launch4j.alternative) {
case "simple":
return new SimpleEXELauncherBinary(this);
case "no":
//None
break;
default:
LogHelper.warning("Alternative %s not found", config.launch4j.alternative);
break;
}
}
try {
Class.forName("net.sf.launch4j.Builder");
if (config.launch4j.enabled) return new EXEL4JLauncherBinary(this);

View file

@ -0,0 +1,112 @@
package pro.gravit.launchserver.binary;
import pro.gravit.launchserver.binary.tasks.LauncherBuildTask;
import pro.gravit.utils.helper.CommonHelper;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.LogHelper;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class BinaryPipeline {
public final List<LauncherBuildTask> tasks = new ArrayList<>();
public final AtomicLong count = new AtomicLong(0);
public final Path buildDir;
public final String nameFormat;
public BinaryPipeline(Path buildDir, String nameFormat) {
this.buildDir = buildDir;
this.nameFormat = nameFormat;
}
public void addCounted(int count, Predicate<LauncherBuildTask> pred, LauncherBuildTask taskAdd) {
List<LauncherBuildTask> indexes = new ArrayList<>();
tasks.stream().filter(pred).forEach(indexes::add);
indexes.forEach(e -> tasks.add(tasks.indexOf(e) + count, taskAdd));
}
public void replaceCounted(int count, Predicate<LauncherBuildTask> pred, LauncherBuildTask taskRep) {
List<LauncherBuildTask> indexes = new ArrayList<>();
tasks.stream().filter(pred).forEach(indexes::add);
indexes.forEach(e -> tasks.set(tasks.indexOf(e) + count, taskRep));
}
public void addPre(Predicate<LauncherBuildTask> pred, LauncherBuildTask taskAdd) {
addCounted(-1, pred, taskAdd);
}
public void add(Predicate<LauncherBuildTask> pred, LauncherBuildTask taskAdd) {
addCounted(0, pred, taskAdd);
}
public void addAfter(Predicate<LauncherBuildTask> pred, LauncherBuildTask taskAdd) {
addCounted(1, pred, taskAdd);
}
public void replacePre(Predicate<LauncherBuildTask> pred, LauncherBuildTask taskRep) {
replaceCounted(-1, pred, taskRep);
}
public void replace(Predicate<LauncherBuildTask> pred, LauncherBuildTask taskRep) {
replaceCounted( 0, pred, taskRep);
}
public void replaceAfter(Predicate<LauncherBuildTask> pred, LauncherBuildTask taskRep) {
replaceCounted(1, pred, taskRep);
}
public <T extends LauncherBuildTask> List<T> getTasksByClass(Class<T> taskClass) {
return tasks.stream().filter(taskClass::isInstance).map(taskClass::cast).collect(Collectors.toList());
}
public <T extends LauncherBuildTask> Optional<T> getTaskByClass(Class<T> taskClass) {
return tasks.stream().filter(taskClass::isInstance).map(taskClass::cast).findFirst();
}
public void build(Path target, boolean deleteTempFiles) throws IOException {
LogHelper.info("Building launcher binary file");
count.set(0); // set jar number
Path thisPath = null;
boolean isNeedDelete = false;
long time_start = System.currentTimeMillis();
long time_this = time_start;
for (LauncherBuildTask task : tasks) {
LogHelper.subInfo("Task %s", task.getName());
Path oldPath = thisPath;
thisPath = task.process(oldPath);
long time_task_end = System.currentTimeMillis();
long time_task = time_task_end - time_this;
time_this = time_task_end;
if (isNeedDelete && deleteTempFiles) Files.deleteIfExists(oldPath);
isNeedDelete = task.allowDelete();
LogHelper.subInfo("Task %s processed from %d millis", task.getName(), time_task);
}
long time_end = System.currentTimeMillis();
if (isNeedDelete && deleteTempFiles) IOHelper.move(thisPath, target);
else IOHelper.copy(thisPath, target);
LogHelper.info("Build successful from %d millis", time_end - time_start);
}
public String nextName(String taskName) {
return String.format(nameFormat, taskName, count.getAndIncrement());
}
public Path nextPath(String taskName) {
return buildDir.resolve(nextName(taskName));
}
public Path nextPath(LauncherBuildTask task) {
return nextPath(task.getName());
}
public Path nextLowerPath(LauncherBuildTask task) {
return nextPath(CommonHelper.low(task.getName()));
}
}

View file

@ -1,119 +1,17 @@
package pro.gravit.launchserver.binary;
import net.sf.launch4j.Builder;
import net.sf.launch4j.Log;
import net.sf.launch4j.config.*;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.utils.Version;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.LogHelper;
import java.io.IOException;
import java.nio.file.Path;
import pro.gravit.launchserver.binary.tasks.exe.Launch4JTask;
public final class EXEL4JLauncherBinary extends LauncherBinary {
private final static class Launch4JLog extends Log {
private static final Launch4JLog INSTANCE = new Launch4JLog();
@Override
public void append(String s) {
LogHelper.subInfo(s);
}
@Override
public void clear() {
// Do nothing
}
}
// URL constants
private static final String DOWNLOAD_URL = "http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html"; // Oracle
// JRE 8
// File constants
private final Path faviconFile;
public EXEL4JLauncherBinary(LaunchServer server) {
super(server, LauncherBinary.resolve(server, ".exe"));
faviconFile = server.dir.resolve("favicon.ico");
super(server, LauncherBinary.resolve(server, ".exe"), "Launcher-%s-%d.exe");
}
@Override
public void build() throws IOException {
LogHelper.info("Building launcher EXE binary file (Using Launch4J)");
setConfig();
// Set favicon path
Config config = ConfigPersister.getInstance().getConfig();
if (IOHelper.isFile(faviconFile))
config.setIcon(faviconFile.toFile());
else {
config.setIcon(null);
LogHelper.warning("Missing favicon.ico file");
}
// Start building
Builder builder = new Builder(Launch4JLog.INSTANCE);
try {
builder.build();
} catch (Throwable e) {
throw new IOException(e);
}
}
private void setConfig() {
Config config = new Config();
// Set file options
config.setChdir(".");
config.setErrTitle("JVM Error");
config.setDownloadUrl(DOWNLOAD_URL);
// Set boolean options
config.setPriorityIndex(0);
config.setHeaderType(Config.GUI_HEADER);
config.setStayAlive(false);
config.setRestartOnCrash(false);
// Prepare JRE
Jre jre = new Jre();
jre.setMinVersion("1.8.0");
if (server.config.launch4j.setMaxVersion)
jre.setMaxVersion(server.config.launch4j.maxVersion);
jre.setRuntimeBits(Jre.RUNTIME_BITS_64_AND_32);
jre.setJdkPreference(Jre.JDK_PREFERENCE_PREFER_JRE);
config.setJre(jre);
// Prepare version info (product)
VersionInfo info = new VersionInfo();
info.setProductName(server.config.launch4j.productName);
info.setProductVersion(formatVars(server.config.launch4j.productVer));
info.setFileDescription(server.config.launch4j.fileDesc);
info.setFileVersion(formatVars(server.config.launch4j.fileVer));
info.setCopyright(server.config.launch4j.copyright);
info.setTrademarks(server.config.launch4j.trademarks);
info.setInternalName(formatVars(server.config.launch4j.internalName));
// Prepare version info (file)
info.setTxtFileVersion(formatVars(server.config.launch4j.txtFileVersion));
info.setTxtProductVersion(formatVars(server.config.launch4j.txtProductVersion));
// Prepare version info (misc)
info.setOriginalFilename(syncBinaryFile.getFileName().toString());
info.setLanguage(LanguageID.RUSSIAN);
config.setVersionInfo(info);
// Set JAR wrapping options
config.setDontWrapJar(false);
config.setJar(server.launcherBinary.syncBinaryFile.toFile());
config.setOutfile(syncBinaryFile.toFile());
// Return prepared config
ConfigPersister.getInstance().setAntConfig(config, null);
}
private static final String VERSION = Version.getVersion().getVersionString();
private static final int BUILD = Version.getVersion().build;
public static String formatVars(String mask) {
return String.format(mask, VERSION, BUILD);
public void init() {
tasks.add(new Launch4JTask(server));
}
}

View file

@ -10,7 +10,7 @@
public class EXELauncherBinary extends LauncherBinary {
public EXELauncherBinary(LaunchServer server) {
super(server, LauncherBinary.resolve(server, ".exe"));
super(server, LauncherBinary.resolve(server, ".exe"), "Launcher-%s-%d.exe");
}
@Override

View file

@ -19,17 +19,15 @@ public final class JARLauncherBinary extends LauncherBinary {
public final Path runtimeDir;
public final Path guardDir;
public final Path buildDir;
public final List<LauncherBuildTask> tasks;
public final List<Path> coreLibs;
public final List<Path> addonLibs;
public JARLauncherBinary(LaunchServer server) throws IOException {
super(server, resolve(server, ".jar"));
super(server, resolve(server, ".jar"), "Launcher-%s-%d.jar");
count = new AtomicLong(0);
runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR);
guardDir = server.dir.resolve(Launcher.GUARD_DIR);
buildDir = server.dir.resolve("build");
tasks = new ArrayList<>();
coreLibs = new ArrayList<>();
addonLibs = new ArrayList<>();
if (!Files.isDirectory(buildDir)) {
@ -50,45 +48,4 @@ public void init() {
if (server.config.launcher.compress) tasks.add(new CompressBuildTask(server));
tasks.add(new SignJarTask(server.config.sign, server));
}
@Override
public void build() throws IOException {
LogHelper.info("Building launcher binary file");
count.set(0); // set jar number
Path thisPath = null;
boolean isNeedDelete = false;
long time_start = System.currentTimeMillis();
long time_this = time_start;
for (LauncherBuildTask task : tasks) {
LogHelper.subInfo("Task %s", task.getName());
Path oldPath = thisPath;
thisPath = task.process(oldPath);
long time_task_end = System.currentTimeMillis();
long time_task = time_task_end - time_this;
time_this = time_task_end;
if (isNeedDelete && server.config.launcher.deleteTempFiles) Files.deleteIfExists(oldPath);
isNeedDelete = task.allowDelete();
LogHelper.subInfo("Task %s processed from %d millis", task.getName(), time_task);
}
long time_end = System.currentTimeMillis();
if (isNeedDelete && server.config.launcher.deleteTempFiles) IOHelper.move(thisPath, syncBinaryFile);
else IOHelper.copy(thisPath, syncBinaryFile);
LogHelper.info("Build successful from %d millis", time_end - time_start);
}
public String nextName(String taskName) {
return String.format("Launcher-%s-%d.jar", taskName, count.getAndIncrement());
}
public Path nextPath(String taskName) {
return buildDir.resolve(nextName(taskName));
}
public Path nextPath(LauncherBuildTask task) {
return nextPath(task.getName());
}
public Path nextLowerPath(LauncherBuildTask task) {
return nextPath(CommonHelper.low(task.getName()));
}
}

View file

@ -7,18 +7,22 @@
import java.io.IOException;
import java.nio.file.Path;
public abstract class LauncherBinary {
public abstract class LauncherBinary extends BinaryPipeline {
public final LaunchServer server;
public final Path syncBinaryFile;
private volatile byte[] digest;
private volatile byte[] sign;
protected LauncherBinary(LaunchServer server, Path binaryFile) {
protected LauncherBinary(LaunchServer server, Path binaryFile, String nameFormat) {
super(server.dir.resolve("build"), nameFormat);
this.server = server;
syncBinaryFile = binaryFile;
}
public abstract void build() throws IOException;
public void build() throws IOException
{
build(syncBinaryFile, server.config.launcher.deleteTempFiles);
}
public final boolean exists() {

View file

@ -1,30 +0,0 @@
package pro.gravit.launchserver.binary;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.LogHelper;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;
public class SimpleEXELauncherBinary extends LauncherBinary {
public final Path exeTemplate;
public SimpleEXELauncherBinary(LaunchServer server) {
super(server, LauncherBinary.resolve(server, ".exe"));
exeTemplate = server.dir.resolve("SimpleTemplate.exe");
}
@Override
public void build() throws IOException {
if (!IOHelper.isFile(exeTemplate)) {
LogHelper.warning("[SimpleEXEBinary] File %s not found. %s not created", exeTemplate.toString(), syncBinaryFile.toString());
return;
}
try (OutputStream output = IOHelper.newOutput(syncBinaryFile)) {
IOHelper.transfer(exeTemplate, output);
IOHelper.transfer(server.launcherBinary.syncBinaryFile, output);
}
}
}

View file

@ -0,0 +1,134 @@
package pro.gravit.launchserver.binary.tasks.exe;
import net.sf.launch4j.Builder;
import net.sf.launch4j.Log;
import net.sf.launch4j.config.*;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.binary.EXEL4JLauncherBinary;
import pro.gravit.launchserver.binary.tasks.LauncherBuildTask;
import pro.gravit.utils.Version;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.LogHelper;
import java.io.IOException;
import java.nio.file.Path;
public class Launch4JTask implements LauncherBuildTask {
private final static class Launch4JLog extends Log {
private static final Launch4JLog INSTANCE = new Launch4JLog();
@Override
public void append(String s) {
LogHelper.subInfo(s);
}
@Override
public void clear() {
// Do nothing
}
}
// URL constants
private static final String DOWNLOAD_URL = "http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html"; // Oracle
// JRE 8
// File constants
private final Path faviconFile;
// File constants
private final LaunchServer server;
public Launch4JTask(LaunchServer launchServer) {
this.server = launchServer;
faviconFile = launchServer.dir.resolve("favicon.ico");
}
@Override
public String getName() {
return "launch4j";
}
@Override
public Path process(Path inputFile) throws IOException {
LogHelper.info("Building launcher EXE binary file (Using Launch4J)");
Path output = setConfig();
// Set favicon path
Config config = ConfigPersister.getInstance().getConfig();
if (IOHelper.isFile(faviconFile))
config.setIcon(faviconFile.toFile());
else {
config.setIcon(null);
LogHelper.warning("Missing favicon.ico file");
}
// Start building
Builder builder = new Builder(Launch4JLog.INSTANCE);
try {
builder.build();
} catch (Throwable e) {
throw new IOException(e);
}
return output;
}
@Override
public boolean allowDelete() {
return true;
}
private Path setConfig() {
Path path = server.launcherEXEBinary.nextPath(getName());
Config config = new Config();
// Set file options
config.setChdir(".");
config.setErrTitle("JVM Error");
config.setDownloadUrl(DOWNLOAD_URL);
// Set boolean options
config.setPriorityIndex(0);
config.setHeaderType(Config.GUI_HEADER);
config.setStayAlive(false);
config.setRestartOnCrash(false);
// Prepare JRE
Jre jre = new Jre();
jre.setMinVersion("1.8.0");
if (server.config.launch4j.setMaxVersion)
jre.setMaxVersion(server.config.launch4j.maxVersion);
jre.setRuntimeBits(Jre.RUNTIME_BITS_64_AND_32);
jre.setJdkPreference(Jre.JDK_PREFERENCE_PREFER_JRE);
config.setJre(jre);
// Prepare version info (product)
VersionInfo info = new VersionInfo();
info.setProductName(server.config.launch4j.productName);
info.setProductVersion(formatVars(server.config.launch4j.productVer));
info.setFileDescription(server.config.launch4j.fileDesc);
info.setFileVersion(formatVars(server.config.launch4j.fileVer));
info.setCopyright(server.config.launch4j.copyright);
info.setTrademarks(server.config.launch4j.trademarks);
info.setInternalName(formatVars(server.config.launch4j.internalName));
// Prepare version info (file)
info.setTxtFileVersion(formatVars(server.config.launch4j.txtFileVersion));
info.setTxtProductVersion(formatVars(server.config.launch4j.txtProductVersion));
// Prepare version info (misc)
info.setOriginalFilename(path.getFileName().toString());
info.setLanguage(LanguageID.RUSSIAN);
config.setVersionInfo(info);
// Set JAR wrapping options
config.setDontWrapJar(false);
config.setJar(server.launcherBinary.syncBinaryFile.toFile());
config.setOutfile(path.toFile());
// Return prepared config
ConfigPersister.getInstance().setAntConfig(config, null);
return path;
}
private static final String VERSION = Version.getVersion().getVersionString();
private static final int BUILD = Version.getVersion().build;
public static String formatVars(String mask) {
return String.format(mask, VERSION, BUILD);
}
}

View file

@ -207,7 +207,6 @@ public void close(LaunchServer.ReloadType type) {
public static class ExeConf {
public boolean enabled;
public String alternative;
public boolean setMaxVersion;
public String maxVersion;
public String productName;
@ -291,7 +290,6 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
newConfig.launch4j = new LaunchServerConfig.ExeConf();
newConfig.launch4j.enabled = true;
newConfig.launch4j.copyright = "© GravitLauncher Team";
newConfig.launch4j.alternative = "no";
newConfig.launch4j.fileDesc = "GravitLauncher ".concat(Version.getVersion().getVersionString());
newConfig.launch4j.fileVer = Version.getVersion().getVersionString().concat(".").concat(String.valueOf(Version.getVersion().patch));
newConfig.launch4j.internalName = "Launcher";