Translation support and publication to local maven repository

snapshot 1.0.1
Jonas Letzbor 2022-04-03 15:12:24 +02:00
parent 3ddf33803e
commit 17371561dd
10 changed files with 412 additions and 155 deletions

View File

@ -20,4 +20,33 @@
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>0</id>
<name></name>
<type>26</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-bin</arguments>
</matcher>
</filter>
<filter>
<id>0</id>
<name></name>
<type>26</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-release</arguments>
</matcher>
</filter>
<filter>
<id>1648988993992</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

View File

@ -50,7 +50,7 @@ System.out.println(installer.getResponseCode());
```
___
For a real life example you can take a look at the installer of [RPdb](https://git.rpjosh.tk/RPJosh/RPdb/src/branch/master/Program/Java/tk.rpjosh.rpdb.installer).
For a real life example you can take a look at the installer of [RPdb](https://git.rpjosh.de/RPJosh/RPdb/src/branch/master/Program/Java/tk.rpjosh.rpdb.installer).
# License
This project is licensed under the GPLv3. Please see the [LICENSE](LICENSE) file for an full license.

View File

@ -1,12 +1,13 @@
plugins {
// Apply the java-library plugin to add support for Java Library
id 'java-library'
id 'maven-publish'
}
// Set version of programm //
version = "1.0.0"
def version = "1.0.0"
version = "1.0.1"
def version = "1.0.1"
group = "de.rpjosh"
@ -18,7 +19,10 @@ targetCompatibility = 11
// create a single .jar with all dependencies //
task fatJar(type: Jar) {
classifier = ''
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes( 'Implementation-Title': 'installer',
'Implementation-Version': version,
@ -32,14 +36,16 @@ task fatJar(type: Jar) {
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
with jar
destinationDirectory.set(layout.buildDirectory.dir("dist"))
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
//sourceSets.main.resources { srcDirs = ["src/main/java"]; exclude "**/*.java" }
task javadocJar(type: Jar, dependsOn: javadoc) {
manifest {
@ -60,16 +66,52 @@ artifacts {
// the created jar file will be copied automatically into the release directory
task copyJar(type: Copy) {
from file("$buildDir/libs/installer-" + version + ".jar"), file("$buildDir/libs/installer-" + version + "-javadoc.jar"), file("$buildDir/libs/installer-" + version + "-sources.jar")
from file("$buildDir/dist/installer-" + version + ".jar"), file("$buildDir/dist/installer-" + version + "-javadoc.jar"), file("$buildDir/dist/installer-" + version + "-sources.jar")
into file("$buildDir/../release")
}
// build the maven repo file structure -> Javadoc can be used easily in eclipse
task copyJarToMaven (type: Copy) {
from file("$buildDir/libs/installer-" + version + ".jar"), file("$buildDir/libs/installer-" + version + "-javadoc.jar"), file("$buildDir/libs/installer-" + version + "-sources.jar")
from file("$buildDir/dist/installer-" + version + ".jar"), file("$buildDir/dist/installer-" + version + "-javadoc.jar"), file("$buildDir/dist/installer-" + version + "-sources.jar")
into file("$buildDir/../release/mavenRepo/de/rpjosh/installer/" + version)
}
// publish to local maven repo
java {
withJavadocJar()
withSourcesJar()
}
publishing {
publications {
mavenJava(MavenPublication) {
artifactId = 'installer'
from components.java
pom {
name = 'Java-Installer'
description = 'A simple installation routine for your Java application'
url = 'https://git.rpjosh.de/RPJosh/Java-Installer'
licenses {
license {
name = 'The GNU General Public License, Version 3'
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
}
}
developers {
developer {
id = 'RPJosh'
name = 'RPJosh'
email = 'RPjosh@rpjosh.de'
}
}
}
}
}
}
build.finalizedBy copyJar
build.finalizedBy copyJarToMaven

View File

@ -6,14 +6,13 @@ import java.io.File;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import de.rpjosh.installer.InstallConfig.OSType;
public class InstallConfig {
private String company;
@ -26,7 +25,7 @@ public class InstallConfig {
ArrayList<String> directorysInAppData = new ArrayList<String>();
Map<String, String> fontsToInstall = new HashMap<String, String>();
// Alle Pfade, die vom Programm genutzt werden //
// All paths used by the program //
private String desktopDir = null;
private String applicationDir = null;
private String configDir = null;
@ -39,25 +38,25 @@ public class InstallConfig {
private boolean offline = false;
private String portableMainDir = "";
private Data data;
private Logger logger;
/* Ordnerstruktur bei Portable:
/* File structure when portable:
.
+-- _Programm
| +-- _pics
| +-- BeMa.jar
| +-- portable <- Dadurch wird portable ersichtlich
| +-- MyProgram.jar
| +-- portable <- Through this file portable will be annotated
+-- _AppData
| +-- _config
| | +-- conf.txt
| +-- _logs
| | +-- BeMa.log
| | +-- BeMa_Simple.log
| | +-- MyProgram.log
| | +-- MyProgram_simple.log
+-- ShortcutToJar
*/
// Programm zum Downloaden //
// Settings for program download //
protected String downloadURL = null;
protected boolean addVersion = false;
protected String urlEnding = "";
@ -115,7 +114,7 @@ public class InstallConfig {
*/
public InstallConfig(String company, String version, String applicationNameShort, String applicationNameLong) {
data = new Data(this);
logger = new Logger();
this.company = company;
this.version = version;
this.applicationNameShort = applicationNameShort;
@ -160,7 +159,7 @@ public class InstallConfig {
protected String getApplicationNameShort() { return applicationNameShort; }
protected String getApplicationNameLong() { return applicationNameLong; }
protected Data getData() { return data; }
protected Logger getLogger() { return logger; }
protected boolean getIsUser() { return isUser; }
protected boolean getIsPortable() { return isPortable; }
@ -247,7 +246,7 @@ public class InstallConfig {
desktopWindowsICO = windowsICO;
desktopLinuxPNG = linuxPNG;
createProgramDirs(new ArrayList<String>() {{ add("pics/"); }});
createProgramDirs((List<String>) Arrays.asList(new String[] {"pics/"}));
desktopKeywords = keywords;
}
protected String getDesktopWindowsICO() { return desktopWindowsICO; }
@ -442,12 +441,12 @@ public class InstallConfig {
rtc = output + "/";
}
} catch (Exception ex) {
data.log("w", "Location of Desktop could not be determed. Using default Location: Desktop", "getDesktopDir");
logger.log("w", "Location of Desktop could not be determed. Using default Location: Desktop", "getDesktopDir");
rtc += "/Desktop/";
}
} else {
data.log("w", "Plattform is not supported", "getDesktopDir"); return null;
logger.log("w", "Plattform is not supported", "getDesktopDir"); return null;
}
this.desktopDir = rtc;
@ -483,9 +482,9 @@ public class InstallConfig {
/**
* Creates the given directory in the configuration directory
*
* @param directorys a list with all the directorys to create. This are relative paths -{@literal >} logs/ or config/
* @param directorys a list with all the directories to create. This are relative paths -{@literal >} logs/ or config/
*/
public void createConfigDirs(ArrayList<String> directorys) {
public void createConfigDirs(List<String> directorys) {
directorysInConfig.addAll(directorys);
directorysInConfig.add("");
@ -494,7 +493,7 @@ public class InstallConfig {
private void initConfigDir() {
if (!isInstallationStarted) return; // vor dem Start der Installation werden noch keine Ordner erstellt
if (!isInstallationStarted) return; // before the start of the installation no folders will be created
String rtc = this.configDir;
@ -503,7 +502,7 @@ public class InstallConfig {
File currentDirectory = new File(rtc + direcotory);
if (!currentDirectory.exists()) new File(rtc + direcotory).mkdirs();
}
} catch (Exception ex) { data.log("e", ex, "getConfigDir"); }
} catch (Exception ex) { logger.log("e", ex, "getConfigDir"); }
}
@ -539,9 +538,9 @@ public class InstallConfig {
/**
* Creates the given directory in the application directory
*
* @param directorys a list with all the directorys to create. This are relative paths -{@literal >} logs/ or config/
* @param directorys a list with all the directories to create. This are relative paths -{@literal >} logs/ or config/
*/
public void createProgramDirs(ArrayList<String> directorys) {
public void createProgramDirs(List<String> directorys) {
this.directorysInAppData.addAll(directorys);
directorysInAppData.add("");
@ -564,13 +563,13 @@ public class InstallConfig {
File currentDirectory = new File(rtc + directory);
if (!currentDirectory.exists()) new File(rtc + directory).mkdirs();
}
} catch (Exception ex) { data.log("e", ex, "initApplicationDir"); }
} catch (Exception ex) { logger.log("e", ex, "initApplicationDir"); }
}
/**
* Returns the main directory of the portable installation
*
* @return the path: C:/Users/de03710/BeMa/
* @return the path: C:/Users/de03710/RPdb/
*/
protected String getPortableDir() {
return this.portableMainDir;
@ -583,7 +582,7 @@ public class InstallConfig {
* @param pathToWrite the destination path
* @param logError if an error message should be displayed
*
* @return if the resource was sucessfully extracted
* @return if the resource was successfully extracted
*/
protected boolean getResource(String pathInJar, String pathToWrite, boolean logError) {
@ -599,7 +598,7 @@ public class InstallConfig {
return false;
} catch (Exception ex ) {
if (logError) data.log("w", ex, "getResource");
if (logError) logger.log("w", ex, "getResource");
return false;
}
@ -633,7 +632,7 @@ public class InstallConfig {
try {
location = new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getAbsolutePath();
} catch (URISyntaxException ex) {
data.log("w", ex, "getLocationOfJarFile");
logger.log("w", ex, "getLocationOfJarFile");
location = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath()).getAbsolutePath();
}
@ -655,7 +654,7 @@ public class InstallConfig {
* @param sizeInMb the maximum size in megabye
*/
public void setMaxHeapSize(int sizeInMb) {
if (sizeInMb < 2) data.log("w", "The maximum heap size must be greater or equal 2 megabyte", "setMaxHeapSize");
if (sizeInMb < 2) logger.log("w", "The maximum heap size must be greater or equal 2 megabyte", "setMaxHeapSize");
else this.maxHeapSize = sizeInMb;
}

View File

@ -6,7 +6,6 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.ObjectInputFilter.Config;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
@ -16,7 +15,9 @@ import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@ -36,36 +37,33 @@ import static java.util.prefs.Preferences.systemRoot;
public class Installer {
private InstallConfig conf;
private Data data;
private Logger logger;
public int error = 0;
public Installer(InstallConfig conf) {
this.conf = conf;
this.data = conf.getData();
this.logger = conf.getLogger();
}
/**
* Starts the installation of the program
*
* @param args If the program has to be restarted you can specify here the parameters with which the program should been restarted.
* @param args If the program has to be restarted you can specify the parameters with which the program should bee restarted.
* These are normally the parameters which were specified when launching your installer
*/
public void installProgramm(String[] args) {
conf.isInstallationStarted = true;
// überprüfe, ob Root rechte vorhanden sind
// check if the user has root rights
if (!conf.getIsPortable() && !conf.getIsUser()) {
if (!this.checkRoot()) {
System.out.println("Zur Installation dieses Programm werden Administrator / Root Rechte benötigt.\n\n"
+ "Falls du keine solchen Rechte hast, kann das Programm auch portable oder nur für diesen Benutzer installiert werden.\n"
+ "Für eine weitere Hilfe führe dieses Programm mit dem Parameter --help aus.");
System.out.println(Tr.get("root_rights_required"));
error = -1;
if ( (InstallConfig.getOsType() == OSType.WINDOWS || InstallConfig.getOsType() == OSType.LINUX) && !conf.getQuiet()) {
System.out.print("\nFalls du doch solche Rechte hast, kann das Programm automatisch versuchen, die Installation mit Administratorrechten zu starten.\n"
+ "Möchtest du das Programm mit Administratorrechten neustarten (Y/N)?: ");
System.out.println(Tr.get("root_askForRestart") + ": ");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
@ -83,7 +81,7 @@ public class Installer {
error = -2; return;
} catch (Exception ex) { data.log("e", ex, "installProgramm");
} catch (Exception ex) { logger.log("e", ex, "installProgramm");
error = -3; return;
}
}
@ -94,20 +92,20 @@ public class Installer {
try { Thread.sleep(10); } catch (Exception ex) { }
if (conf.getIsUser() && InstallConfig.getOsType() != OSType.WINDOWS) { System.out.println("A user installation is only available under windows"); error = -10; }
if (conf.getIsUser() && InstallConfig.getOsType() != OSType.WINDOWS) { System.out.println("userInstallation_notAvailable"); error = -10; }
System.out.println("\nStarting the installation of " + conf.getApplicationNameShort() + " (version " + conf.getVersion() + ").\n");
System.out.println("\n" + Tr.get("installation_start", conf.getApplicationNameShort(), conf.getVersion()) + "\n");
// all running instances will be killed
this.killRunningInstances();
System.out.print("Determine architekture and operating system: ");
System.out.print(Tr.get("installation_architekture") + ": ");
String aarch = this.getVersionOfProgramm();
System.out.println(aarch);
// copies or downloads the file
if (conf.downloadURL == null) {
data.log("w", "no file to download or copy specified", "installProgramm");
logger.log("w", "no file to download or copy specified", "installProgramm");
error = -5;
return;
}
@ -115,57 +113,58 @@ public class Installer {
String jarFile = "";
if (!conf.getOffline()) {
System.out.print("Downloading file: ");
System.out.print(Tr.get("installation_download") + ": ");
jarFile = this.downloadFile(conf.downloadURL, conf.addVersion, conf.urlEnding);
if (error < 0) return;
System.out.println("\rDownloading file: successful downloaded");
System.out.println("\r" + Tr.get("installation_download_success") + " ");
} else {
File fileOffline = new File(conf.downloadURL);
if (!fileOffline.exists() || fileOffline.length() < ( 1024 * 1024)) {
System.out.println("The given file is invalid!");
System.out.println(Tr.get("installation_download_invalid"));
error = -11; return;
}
jarFile = fileOffline.getAbsolutePath();
}
if (conf.getIsPortable()) {
System.out.println("\nProgram will be installed portable under: " + conf.getPortableDir());
System.out.println("\n" + Tr.get("installation_portable_start", conf.getPortableDir()));
File portableDir = new File(conf.getPortableDir());
if (!portableDir.exists()) {
System.out.print("Directory does not exist. Creating directory: ");
System.out.print(Tr.get("installation_portable_createDirectory") + ": ");
System.out.print(": ");
if (!portableDir.mkdirs()) {
System.out.print("No authorization!");
System.out.print(Tr.get("noAuthorization") + "!");
error = -12; return;
} else System.out.print("created");
} else System.out.print(Tr.get("created"));
}
conf.setPortable(portableDir.getAbsolutePath().replace("\\", "/") + "/");
}
System.out.print("\nCopy jar file: ");
System.out.print("\n" + Tr.get("installation_copyJar") + ": ");
try {
FileUtils.copyInputStreamToFile(new FileInputStream(new File(jarFile)), new File(conf.getApplicationDir() + conf.getApplicationNameShort() + ".jar"));
} catch (Exception ex) {
System.out.println("failed.\n\nError message: ");
System.out.println(Tr.get("failed") + ".\n\n" + Tr.get("errorMessage") + ": ");
ex.printStackTrace();
error = -13; return;
}
System.out.println("successful\n");
System.out.println(Tr.get("successful") + "\n");
// sets the path for the jar file for the shortcuts
// set the path for the jar file for the shortcuts
conf.setLocationOfJarFile(conf.getApplicationDir() + conf.getApplicationNameShort() + ".jar");
// Icon für die Systemsteuerung für die Deinstallation setzen -> wird immer gesetzt
// icon for the control panel for the uninstallation -> set always
if (conf.createIconForDeletion) {
conf.createProgramDirs(new ArrayList<String>() {{ add("pics/"); }});
conf.createProgramDirs((List<String>) Arrays.asList(new String[] {"pics/"}));
conf.getResource(conf.iconForDeletionPath, conf.getApplicationDir() + "pics/uninstall.ico");
}
if (conf.getIsPortable()) {
System.out.print("Creating required files: ");
System.out.print(Tr.get("installation_createFiles") + ": ");
try {
// creates a file "portable" in the application directory //
FileWriter fw = new FileWriter(conf.getApplicationDir() + "portable");
@ -179,7 +178,7 @@ public class Installer {
// create a launch script
this.createLauncher("Programm/" + conf.getApplicationNameShort() + ".jar", conf.getPortableDir() + conf.getApplicationNameShort(), false);
//Datei ausführbar machen
// make the file executable
Process p = new ProcessBuilder("bash", "-c", "chmod +x " + conf.getPortableDir() + conf.getApplicationNameShort()).start();
p.waitFor(5000, TimeUnit.SECONDS);
@ -188,12 +187,12 @@ public class Installer {
this.createDesktopShortcut(conf.getPortableDir() + conf.getApplicationNameShort() + ".lnk", "");
}
System.out.println("erfolgreich");
System.out.println(Tr.get("successful"));
} catch (Exception ex) { System.out.println("fehlgeschlagen"); error = -14; return; }
} catch (Exception ex) { System.out.println(Tr.get("failed")); error = -14; return; }
} else if (conf.getIsUser()) {
// erstelle eine Textdatei User im Programmverzeichnis, damit erkenbar ist, dass das Programm nur für den aktuellen Benutze instsalliert worden ist. //
// creates a file "userInstallation" in the application directory //
try {
FileWriter fw = new FileWriter(conf.getApplicationDir() + "userInstallation");
PrintWriter pw = new PrintWriter(fw);
@ -201,12 +200,12 @@ public class Installer {
pw.println("Therefore please do not delete this inconspicuous file!");
pw.flush();
pw.close();
System.out.println("Execute other commands...");
System.out.println(Tr.get("installation_executeOtherCommands") + "...");
this.registerApplication(conf.getIsUser());
} catch (Exception ex) { System.out.println("Creation of the files failed..."); error = -15; return; }
} catch (Exception ex) { System.out.println(Tr.get("installation_createFilesFailed") + "..."); error = -15; return; }
} else {
System.out.println("Execute other commands...");
System.out.println(Tr.get("installation_executeOtherCommands") + "...");
// the program will be created
this.registerApplication(conf.getIsUser());
@ -216,12 +215,12 @@ public class Installer {
if (error < 0) return;
System.out.println("\nInstallation was completed successfully\n");
System.out.println("\n" + Tr.get("installation_executionSuccessful") + "\n");
}
/**
* Beendet alle noch möglicherweise laufenden Instanzen des Programms (z.B. bei einem Update)
* Kills all running instances (for a update)
*/
private void killRunningInstances() {
@ -235,15 +234,16 @@ public class Installer {
Process p = new ProcessBuilder("bash", "-c", "pkill -9 -f '" + conf.getApplicationNameShort() + ".jar'").start();
p.waitFor(5, TimeUnit.SECONDS);
}
} catch (Exception ex) { /* nicht nötig */ }
} catch (Exception ex) { /* not required */ }
}
/**
* Erstellt eine Verknüpfung zur Jar-Datei
* @param target Wo die Verknüpfung erstellt werden soll, sowie dessen Dateinamen (z.B. /home/user/Desktop/BeMa.desktop oder C:/User/de03710/Desktop/hi.moin)
* @param args zusätzliche Parameter wie -u hi -p secret -w
* Creates a shortcut to the jar file
*
* @param target Where to create the shortcut and the filename (z.B. /home/user/Desktop/MyApp.desktop oder C:/User/de03710/Desktop/hi.moin)
* @param args Additional parameters how "--minimized"
*/
private void createDesktopShortcut(String target, String args) {
@ -286,7 +286,7 @@ public class Installer {
}
} catch (Exception ex) {
data.log("e", ex, "createDesktopShortcut");
logger.log("e", ex, "createDesktopShortcut");
}
}
@ -295,13 +295,13 @@ public class Installer {
if (InstallConfig.getOsType() == OSType.WINDOWS) {
// Erstellung eines Links, damit das Proramm von überall aufgerufen werden kann //
// Creates a Link that the program can be launched from everywhere //
this.createLauncher("", "", true);
// create also an link for the %PATH% variable
if (conf.createPathVariable) this.createLauncher("", conf.getApplicationDir() + "path/" + conf.getApplicationNameShort() + ".bat", true);
// zuerst wird eine Dekstopverknüpfung erstellt //
// in the first step a desktop shortcut will be created //
if (conf.getCreateDesktopEntry()) {
if (userInstallation) {
@ -309,21 +309,21 @@ public class Installer {
destination += conf.getApplicationNameShort() + ".lnk";
createDesktopShortcut(destination, "");
} else {
// es wird eine Verknknüpfung im Öffentlichen Desktop erstellt
// shortcut in the public desktop
String destination = System.getenv("public").replace("\\", "/") + "/Desktop/";
destination += conf.getApplicationNameShort() + ".lnk";
createDesktopShortcut(destination, "");
}
// im nächsten Schritt wird eine Verknüpfung in das Startmenü aufgenommenn //
// In the next step a shortcut in the start menu will be created //
String locationStartMenu = "";
if (userInstallation) {
locationStartMenu = System.getenv("APPDATA").replace("\\", "/") + "/Microsoft/Windows/Start Menu/Programs/";
locationStartMenu = System.getenv("APPlogger").replace("\\", "/") + "/Microsoft/Windows/Start Menu/Programs/";
} else {
locationStartMenu = System.getenv("ALLUSERSPROFILE").replace("\\", "/") + "/Microsoft/Windows/Start Menu/Programs/";
}
if (!new File(locationStartMenu).exists()) data.log("w", "Start Menu folder \"" + locationStartMenu + "\" does not exist!", "registerApplication");
if (!new File(locationStartMenu).exists()) logger.log("w", "Start Menu folder \"" + locationStartMenu + "\" does not exist!", "registerApplication");
else {
locationStartMenu += conf.getCompany() + "/";
new File(locationStartMenu).mkdirs();
@ -334,7 +334,7 @@ public class Installer {
}
// es muss noch ein uninstall Schlüssel in die Registry geschrieben werden, um über die Systemsteuerung alles deinstallieren zu können //
// an uninstall keys has to be written to the registry, for uninstallation purposes in the system control //
String iconPath = conf.getApplicationDir() + "pics/uninstall.ico";
String locationRegistry = "";
@ -356,7 +356,7 @@ public class Installer {
String locationRegistryPath = "";
if (conf.createPathVariable) {
// adding support for "start RPdb"
// adding support for "start MyProgram"
locationRegistryPath += "$REGISTRYPATH$" + conf.getApplicationNameShort() + ".exe";
String batchFilePath =
"reg add \"" + locationRegistryPath + "\" /f \n"
@ -384,7 +384,7 @@ public class Installer {
}
try {
// es wird die Batch-Datei erstellt, und anschließend ausgeführt
// creating a batch file and execute the commands
File batchMakeRegeditEntry = File.createTempFile("installApplication", ".bat");
FileWriter fwFile = new FileWriter(batchMakeRegeditEntry);
@ -395,17 +395,17 @@ public class Installer {
pwFile.close();
Process p = new ProcessBuilder("cmd.exe", "/C", batchMakeRegeditEntry.getAbsolutePath()).start();
if (!p.waitFor(10, TimeUnit.SECONDS)) data.log("w", "Batch File which adds some Registry Keys timed out", "registerApplication");
if (!p.waitFor(10, TimeUnit.SECONDS)) logger.log("w", "Batch File which adds some Registry Keys timed out", "registerApplication");
} catch (Exception ex) {
data.log("e", ex, "registerApplication (make regedit Entry)");
logger.log("e", ex, "registerApplication (make regedit Entry)");
}
// nun muss noch ein uninstall Skript zur Verfügung gestellt werden //
// create a uninstall script //
String batchFileUninstall = "@echo off \n"
+ "wmic PROCESS Where \"name Like '%%java%%' AND CommandLine like '%%" + conf.getApplicationNameShort() + "%%'\" Call Terminate \n";
if (userInstallation) batchFileUninstall += "del \"%LOCALAPPDATA%";
else batchFileUninstall += "del \"%ProgramData%";
if (userInstallation) batchFileUninstall += "del \"%LOCALAPPlogger%";
else batchFileUninstall += "del \"%Programlogger%";
batchFileUninstall +=
"\\Microsoft\\Windows\\Start Menu\\Programs\\" + conf.getCompany() + "\\" + conf.getApplicationNameShort() + "*\" /q \n"
+ "rd \"" + conf.getConfigDir().replace("/", "\\") + "\" /q /s \n"
@ -438,7 +438,7 @@ public class Installer {
+ "pause\n";
try {
// es wird die Batch-Datei erstellt
// creating the batch file
File uninstallFile = new File(conf.getApplicationDir() + "uninstall.bat");
FileWriter fwFile = new FileWriter(uninstallFile);
@ -449,30 +449,30 @@ public class Installer {
pwFile.close();
} catch (Exception ex) {
data.log("e", ex, "registerApplication (make uninstall Skript)");
logger.log("e", ex, "registerApplication (make uninstall Skript)");
}
}
if (InstallConfig.getOsType() == OSType.LINUX) {
// keine Erstellung einer Verknüpfung, da Installer als root ausgeführt wird //
// create a shortcut because the installer is always run as root //
if (!checkRoot()) { data.log("i", "Installer has to be run as a root user", "registerApplication" ); return; }
if (!checkRoot()) { logger.log("i", "Installer has to be run as a root user", "registerApplication" ); return; }
// Erstellung einer Verknüpfung für das StartMenü //
// create a shortcut in the start menu //
if (conf.getCreateDesktopEntry()) {
String pathMenu = "/usr/share/applications/" + conf.getApplicationNameShort() + ".desktop";
this.createDesktopShortcut(pathMenu, "");
}
// Erstellung eines Links, damit das Proramm von überall aufgerufen werden kann //
// create a link that the program can be executed from everywhere //
this.createLauncher("", "", true);
// Create a systemd unit file //
// create a systemd unit file //
if (conf.createUnitFile) this.createUnitFile();
// Create a uninstaller //
// create a uninstaller //
try {
String batchFileUninstall = "#!/bin/bash" + "\n"
+ "keepUserSettings=false" + "\n"
@ -537,17 +537,18 @@ public class Installer {
p.waitFor(5000, TimeUnit.SECONDS);
} catch (Exception ex) {
data.log("e", ex, "registerApplication (create Uninstall-Skript");
logger.log("e", ex, "registerApplication (create Uninstall-Skript");
}
}
}
/**
* Erstellt einen ausführbaren Link zum launcher unter Linux und Windows (unter Windows wird dieses auch in path folder gelegt.
* @param pathToLink Der Pfad zur .jar Datei. Ohne eine angabe wird der Aktuelle Pfad der Jar-Datei genommen
* @param pathToCreate Wo die Datei abgelegt werden soll. Standardmäßig wird /usr/bin/nameOfProgram genommen
* @param uninstaller Ob auch eine Uninstall-Option implementiert werden soll
* Creates an executable link to the launcher under Linux and Windows (in Windows the path will also be created)
*
* @param pathToLink the path to the .jar file. Is this parameter empty, the actual set path will be considered
* @param pathToCreate where the file should been placed. Defaulting to the path "/usr/bin/nameOfProgram"
* @param uninstaller if also an uninstall option should be implemented
*/
private void createLauncher(String pathToLink, String destination, boolean uninstaller) {
@ -631,7 +632,7 @@ public class Installer {
p.waitFor(5000, TimeUnit.SECONDS);
} catch (Exception ex) {
data.log("w", "Could not create Link to Programm", "registerApplication (create Link)");
logger.log("w", "Could not create Link to Programm", "registerApplication (create Link)");
}
}
else if (InstallConfig.getOsType() == OSType.WINDOWS) {
@ -756,7 +757,7 @@ public class Installer {
pwFile.close();
} catch (Exception ex) {
data.log("w", "Could not create Link to Programm", "registerApplication (create Link)");
logger.log("w", "Could not create Link to Programm", "registerApplication (create Link)");
}
}
}
@ -777,7 +778,7 @@ public class Installer {
p.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(p.getInputStream()));
String output = buf.readLine();
if (!output.equals("yes")) { data.log("d", "systemd was nout found on the machine -> don't create a service unit", "registerApplication (create Unit File)"); return; }
if (!output.equals("yes")) { logger.log("d", "systemd was nout found on the machine -> don't create a service unit", "registerApplication (create Unit File)"); return; }
// create the unit file
String s = "[Unit]\n";
@ -826,7 +827,7 @@ public class Installer {
}
} catch (Exception ex) {
data.log("w", "Could not create a systemd unit file", "registerApplication (create Unit File)");
logger.log("w", "Could not create a systemd unit file", "registerApplication (create Unit File)");
}
}
@ -844,15 +845,16 @@ public class Installer {
}
/**
* Überprüft, ob ein Nutzer unter Linux oder Windows root Rechte hat
* @return Ob de Nutzer Root Rechte hat
* Checks if the user has administrative privileges in Linux and Windows
*
* @return if the user has root privileges
*/
private boolean checkRoot() {
if (InstallConfig.getOsType() == OSType.WINDOWS) {
// als erstes wird überprüft, ob der Nutzer sich überhaupt in einer Admin-Grupper befindet (zweiter Abschnitt wirft eine unvermeidbare Warnung)
// kann nur vermiden werden, wenn der Schlüssel HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs in der Registry eingetragen wurde
// in the first step it will be check if the user is in the admin group (will print an unavoidable warning ...)
// only when setting the key HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs in the registry no warning would be printed
boolean isAdminGroup = false;
String groups[] = (new com.sun.security.auth.module.NTSystem()).getGroupIDs();
for (String group : groups) {
@ -861,8 +863,8 @@ public class Installer {
if (!isAdminGroup) return false;
// Um herauszufinden, ob ein Benutzer das Programm mit Administratorprivelegien gestartet hat, wird versucht, System-Preferences zu schreiben.
// Falls hierbei ein Fehler auftritt, kann davon ausgegeangen werden, dass der entsprechende Nutzer keine Administratorprivelegien hat / das Programm nicht mit diesen gestartet hat
// to check if the user has started the installer with administrative privileges, a system property will be tried to write
// when an error occurs, the user has no administrative privileges / has the installer not started with these rights
Preferences preferences = systemRoot();
synchronized (System.err) {
setErr(new PrintStream(new OutputStream() {
@ -898,17 +900,18 @@ public class Installer {
return false;
} catch (Exception ex) {
data.log("w", ex, "checkRoot");
logger.log("w", ex, "checkRoot");
return false;
}
}
/**
* Lädt eine Datei von einem Webserver herunter (mit Basic-Auth support -> config)
* @param url die URL
* @param addVersion ob das Betriebsystem und die Architektur der URL angehängt werden soll -> windows_x64
* @param end das Dateiende (die URL wird in diesem Fall ohne Dateiendung angegeben)
* @return Der Pfad der heruntergeladenen Datei (bei Fehler: null + data.error)
* Downloads a file from an Webserver (with bsic auth support -> set in config)
*
* @param url URL
* @param addVersion if the architecture and bs should be added to the given URL -> windows_x64 | linux_arm32
* @param end the file ending (the URL will be set without an file ending)
* @return the path of the downloaded file (when an error occurred: null + logger.error)
*/
private String downloadFile (String url2, boolean addVersion, String end) {
@ -939,14 +942,14 @@ public class Installer {
// es muss nun parallel die bereits heruntergeladene Dateigröße ermittelt werden
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
double lenghtTmp = lenght;
Future future = scheduler.scheduleWithFixedDelay(() -> {
Future<?> future = scheduler.scheduleWithFixedDelay(() -> {
double actualLenghtOfFile = download.length();
actualLenghtOfFile = Math.round(actualLenghtOfFile / 1048576 * 100) / 100.0;
double percent = Math.round(actualLenghtOfFile / lenghtTmp * 10000) / 100.0;
// add leading zeros
DecimalFormat f = new DecimalFormat("0.00");
System.out.print("\rDownloading file: " + f.format(percent) + "% (" + f.format(actualLenghtOfFile) + " MB / " + lenghtTmp + " MB)");
System.out.print("\r" + Tr.get("installation_download") + ": " + f.format(percent) + "% (" + f.format(actualLenghtOfFile) + " MB / " + lenghtTmp + " MB)");
;
}, 200, 450, TimeUnit.MILLISECONDS);
@ -961,12 +964,12 @@ public class Installer {
} catch (Exception ex) {
System.out.println("fehler");
System.out.println("\nA error occured while downloading the file.\nPlease check your internet connection and try again later (URL: " + serverURL + ")");
System.out.println("\n" + Tr.get("installation_download_failed", serverURL));
error = -20;
data.log("e", ex, "downloadFile");
logger.log("e", ex, "downloadFile");
}
} catch (Exception ex) {
System.out.println("The determined URL was not found" + "(URL: " + serverURL + ")");
System.out.println(Tr.get("installation_download_urlNotFound", serverURL));
error = -21;
}
@ -975,14 +978,15 @@ public class Installer {
}
/**
* Gibt die zu herunterladende Version des Programms aus
* @return den entsprechenden Dateinamen (z.B. windows_x64, linux_arm64)
* Return the version of the program to download
*
* @return filename how "windows_x64" or "linux_arm32"
*/
protected String getVersionOfProgramm() {
String rtc = "";
// Verwendetes Betriebssystem ermitteln //
// operating system //
if (InstallConfig.getOsType() == OSType.WINDOWS) rtc += "windows";
else if (InstallConfig.getOsType() == OSType.LINUX) rtc += "linux";
else if (InstallConfig.getOsType() == OSType.MACOS) rtc += "mac";
@ -993,13 +997,13 @@ public class Installer {
rtc += "_";
// Architektur der CPU ermitteln //
// architecture of the CPU //
String aarch = System.getProperty("os.arch").toLowerCase();
if (aarch.contains("amd64")) rtc += "x64";
else if (aarch.equals("x86")) rtc += "x86";
else if (aarch.equals("arm64") || aarch.equals("aarch64")) rtc += "arm64";
else if (aarch.equals("arm")) rtc += "arm32";
//fals nichts zutrifft, aber Prozessor mit 64 endet, wird amd64 erwartet
// if no architecture matched, but ending with "64", expect amd64
else if (aarch.endsWith("64")) rtc += "x64";
else {
System.out.println("CPU architecture could not been determined: " + aarch);
@ -1024,7 +1028,7 @@ public class Installer {
batchFile += "reg add \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\" /v \"" + entry.getKey() + " (TrueType)\" /t REG_SZ /d \"" + path + entry.getKey() + ".ttf\" /f \n";
}
try {
// es wird die Batch-Datei erstellt, und anschließend ausgeführt
// create the batch file and make it executable
File batchMakeRegeditEntry = File.createTempFile("installApplication", ".bat");
FileWriter fwFile = new FileWriter(batchMakeRegeditEntry);
@ -1035,11 +1039,11 @@ public class Installer {
pwFile.close();
Process p = new ProcessBuilder("cmd.exe", "/C", batchMakeRegeditEntry.getAbsolutePath()).start();
if (!p.waitFor(10, TimeUnit.SECONDS)) data.log("w", "Batch File which adds Registry Keys for uninstallation not fully executed (timeout)", "registerApplication");
} catch (Exception ex) { data.log("e", ex, "installFonts"); }
if (!p.waitFor(10, TimeUnit.SECONDS)) logger.log("w", "Batch File which adds Registry Keys for uninstallation not fully executed (timeout)", "registerApplication");
} catch (Exception ex) { logger.log("e", ex, "installFonts"); }
} else {
data.log("w", "Can't install fonts without admin privilegies in Windows -> skipping. You should mind a reinstall with Admin-Privelegis", "installFonts");
logger.log("w", "Can't install fonts without admin privilegies in Windows -> skipping. You should mind a reinstall with Admin-Privelegis", "installFonts");
}
} else if (InstallConfig.getOsType() == OSType.LINUX) {
@ -1048,7 +1052,7 @@ public class Installer {
if (this.checkRoot()) path = "/usr/share/fonts/truetype/";
else path = System.getProperty("user.home") + "/.local/share/fonts/";
// Verzeichnis erstellen, falls noch nicht vorhanden
// create directories when not present
new File(path).mkdirs();
final String path_ = path;

View File

@ -3,12 +3,11 @@ package de.rpjosh.installer;
import java.io.PrintWriter;
import java.io.StringWriter;
class Data {
public class Logger {
private InstallConfig conf;
private boolean debug = true;
Data(InstallConfig conf) {
this.conf = conf;
public Logger() {
}
/**
@ -24,29 +23,17 @@ class Data {
String commandLine = "";
// if the debug mode isn't enabled print only the first line of the message (without the location)
if (true) commandLine = anz + " - " + location;
if (debug) commandLine = anz + " - " + location;
else commandLine = anzSimple;
if (v.equals("d")) {
//logger.debug(anz); loggerSimple.debug(anzSimple);
System.out.println("[D] " + commandLine);
}
if (v.equals("d")) System.out.println("[D] " + commandLine);
if (v.equals("i")) {
//logger.info(anz); loggerSimple.info(anzSimple);
System.out.println("[I] " + commandLine);
}
if (v.equals("i")) System.out.println("[I] " + commandLine);
if (v.equals("w")) {
//logger.warn(anz); loggerSimple.warn(anzSimple);
System.out.println("[W] " + commandLine);
}
if (v.equals("w")) System.out.println("[W] " + commandLine);
if (v.equals("e")) {
//logger.error(anz); loggerSimple.error(anzSimple);
System.out.println("[E] " + commandLine);
}
if (v.equals("e")) System.out.println("[E] " + commandLine);
}
@ -63,4 +50,5 @@ class Data {
ex.printStackTrace(pw);
log("e", sw.toString(), location);
}
}

View File

@ -0,0 +1,17 @@
package de.rpjosh.installer;
/**
* A static class for the main translations
*/
public class Tr {
public final static TranslationService translationService = new TranslationService("translation.de-rpjosh-installer");
/**
* {@link de.rpjosh.installer.TranslationService#get(String, String...)}
*/
public static String get(String property, String... replaceStrings) {
return translationService.get(property, replaceStrings);
}
}

View File

@ -0,0 +1,112 @@
package de.rpjosh.installer;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
/**
* A class providing translation support of properties
*
*/
public class TranslationService {
private String resourceFile;
public enum Language {
GERMAN (new Locale("de", "DE")),
ENGLISH(new Locale("en", "US"));
public final Locale locale;
Language(Locale locale) {
this.locale = locale;
}
}
private static Logger logger = new Logger();
private ResourceBundle bundle;
private ResourceBundle defaultBundle;
/**
* Creates a new instance for translating support
*
* @param resourceFile the property file to use for the translations. For example translation.de.rpjosh.installer
*/
public TranslationService(String resourceFile) {
this.resourceFile = resourceFile;
this.defaultBundle = ResourceBundle.getBundle(resourceFile, Locale.ENGLISH);
Locale osLocale = Locale.getDefault();
List<Locale> supportedLanguages = (List<Locale>) Arrays.asList(
new Locale[] { Language.GERMAN.locale, Language.ENGLISH.locale }
);
if (supportedLanguages.contains(osLocale)) this.bundle = ResourceBundle.getBundle(resourceFile, osLocale);
else this.bundle = defaultBundle;
}
/**
* Creates a new instance for translating and forces the use of a specific language for the translations
* (defaulting to the language the operation system provides)
*
* @param resourceFile property file to use for the translations. For example translation.de.rpjosh.installer
* @param language language to force
*/
public TranslationService(String resourceFile, Language language) {
this.resourceFile = resourceFile;
this.defaultBundle = ResourceBundle.getBundle(resourceFile, Locale.ENGLISH);
this.bundle = ResourceBundle.getBundle(resourceFile, language.locale);
}
/**
* Force the use of a specific language for the translations (defaulting to
* the language the operation system provides)
*
* @param language language to force
*/
public void setLanguage(Language language) {
this.bundle = ResourceBundle.getBundle(resourceFile, language.locale);
}
/**
* Returns the translated value of the property
*
* @param property property to translate
* @param replaceStrings strings for replacing {0}, {1}, ... inside the property values starting by zero counting one by one
*
* @return translated string for the property
*/
public String get(String property, String... replaceStrings) {
try {
return replaceValues(property, bundle.getString(property), replaceStrings);
} catch (Exception ex) {
logger.log("d", "Cannot find property: \"" + property + "\" for language \"" + bundle.getLocale().getLanguage() + "\" in property file \"" + resourceFile + "\"", "Translations#get");
}
try {
return replaceValues(property, defaultBundle.getString(property), replaceStrings);
} catch (Exception ex) {
logger.log("e", "Cannot find property: \"" + property + "\" in default translation list from property file \"" + resourceFile + "\"", "Translations#get");
return property;
}
}
private String replaceValues(String property, String value, String... replaceStrings) {
if (replaceStrings.length == 0) return value;
for (int i = 0; i < replaceStrings.length; i++) {
if (value.contains("{" + i + "}")) {
value = value.replace("{" + i + "}", replaceStrings[i]);
} else {
logger.log("d", "No value matches for " + "{" + i + "}" + "in the property \"" + property + "\n: " + value, "Translations#replaceValue");
}
}
return value;
}
}

View File

@ -0,0 +1,33 @@
root_rights_required=\
Zur Installation dieses Programm werden Administrator / Root Rechte ben<65>tigt.\n\n\
Falls du keine solchen Rechte hast, kann das Programm auch portable oder nur f<>r den aktuell angemeldeten Benutzer installiert werden [Windows].\n\
F<EFBFBD>r eine weitere Hilfe f<>hre dieses Programm mit dem Parameter "--help" aus.
root_askForRestart=\
Falls du doch solche Rechte hast, kann das Programm automatisch versuchen, die Installation mit Administratorrechten zu starten.\n\
M<EFBFBD>chtest du das Programm mit Administratorrechten neustarten (Y/N)?
userInstallation_notAvailable=Eine Benutzerinstallation ist nur unter Windows verf<72>gbar
installation_start=Die Installation von {0} wird gestartet (Version {1})
installation_architekture=Ermittle Architektur und Betriebssystem
installation_download=Lade Datei herunter
installation_download_success=Lade Datei herunter: erfolgreich heruntergeladen
installation_download_invalid=Die angegebene Datei ist ung<6E>ltig!
installation_download_failed=Ein Fehler trat beim herunterladen der Datei auf.\nBitte <20>berpr<70>fe deine Internetverbindung und versuche es sp<73>ter erneut(URL: {0})
installation_download_urlNotFound=Die Ermittelte URL konnte nicht gefunden werden (URL: {0});
installation_portable_start=Das Programm wird portable installiert in: "{0}"
installation_portable_createDirectory=Verzeichnis existiert nicht. Erstelle Verzeichnis
installation_copyJar=Kopiere jar Datei
installation_createFiles=Erstelle ben<65>tigte Dateien
installation_createFilesFailed=Erstellung der Dateien ist fehlgeschlagen
installation_executeOtherCommands=F<EFBFBD>hre weitere Befehle aus
installation_executionSuccessful=Die Installation wurde erfolgreich abgeschlossen
notAuthorized=Keine Berechtigung
created=erstellt
failed=fehlgeschlagen
errorMessage=Fehlermeldung
successful=erfolgreich

View File

@ -0,0 +1,33 @@
root_rights_required=\
For the installation of the program administrator / root privileges are required.\n\n\
If you don't have these you can try to install the program portable or only for the currently logged in user [Windows].\n\
For further help execute the program over the command line with the parameter "--help".
root_askForRestart=\
If you do have such rights the installation can be restarted automatically with root privileges.\n\
Do you want to try to restart the program with root privileges (Y/N)?
userInstallation_notAvailable=A user installation is only available under windows
installation_start=Starting the installation of {0} (version {1})
installation_architekture=Determine architecture and operating system
installation_download=Downloading file
installation_download_success=Downloading file: successful downloaded
installation_download_invalid=The given file is invalid!
installation_download_failed=An error occured while downloading the file.\nPlease check your Internet connection and try again later (URL: {0})
installation_download_urlNotFound=The determined URL was not found (URL: {0});
installation_portable_start=Program will be installed in the directory: "{0}"
installation_portable_createDirectory=Directory does not exist. Creating directory
installation_copyJar=Copy jar file
installation_createFiles=Creating required files
installation_createFilesFailed=Creation of the files failed
installation_executeOtherCommands=Execute other commands
installation_executionSuccessful=Installation was completed successfully
notAuthorized=No authorization
created=created
failed=failed
errorMessage=Error Message
successful=successful