summaryrefslogtreecommitdiffstats
path: root/dozentenmodul/src
diff options
context:
space:
mode:
authorSimon Rettberg2023-02-09 15:13:55 +0100
committerSimon Rettberg2023-02-09 15:13:55 +0100
commite18e0730a9d60e3a1a93de2a1248294e1dc6cd9a (patch)
tree8f61148a1c882378ee1b0153835b3255720f1b40 /dozentenmodul/src
parent[client] Warn if destination directory can't be created on download (diff)
downloadtutor-module-e18e0730a9d60e3a1a93de2a1248294e1dc6cd9a.tar.gz
tutor-module-e18e0730a9d60e3a1a93de2a1248294e1dc6cd9a.tar.xz
tutor-module-e18e0730a9d60e3a1a93de2a1248294e1dc6cd9a.zip
[client] Allow Branding in external locations
Allow customizing the client via external properties and resources, instead of just the built-in resources. Built-in configuration takes highest priority, as usual, but built-in resources (images, text) take lowest priority. Any config file in the current working directory will be the first fallback. Finally, a system-wide path will be considered. On Windows, this is %ProgramData%\bwlp\, on Linux /etc/bwlp/. If a config was found in either of those places, the app will also try to load any resources (images, text) from there, only falling back to the resources withing the jar if they don't exist. You can still use --dump and --pack with these changes, but --dump will only ever dump the active configuration and the resources found within the jar, not those from the file system.
Diffstat (limited to 'dozentenmodul/src')
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/Branding.java128
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/util/ResourceLoader.java42
-rw-r--r--dozentenmodul/src/main/properties/branding.properties8
3 files changed, 144 insertions, 34 deletions
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/Branding.java b/dozentenmodul/src/main/java/org/openslx/dozmod/Branding.java
index 8ff3a584..34dceee3 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/Branding.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/Branding.java
@@ -1,6 +1,8 @@
package org.openslx.dozmod;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
@@ -19,61 +21,141 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Properties;
-import org.openslx.dozmod.Config.ProxyMode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.openslx.dozmod.Config.ProxyMode;
+import org.openslx.dozmod.util.OsHelper;
+import org.openslx.util.Util;
public final class Branding {
private final static Logger LOGGER = LogManager.getLogger(Branding.class);
+ private static final String VIRTUALIZER_WEBSITE = "virtualizer.website";
+ private static final String SERVICE_EMAIL = "service.email";
+ private static final String CONFIG_DIRECTORY = "config.directory";
+ private static final String SERVICE_NAME = "service.name";
+ private static final String SERVICE_FAQ_WEBSITE = "service.faq.website";
+ private static final String APPLICATION_NAME = "application.name";
+ private static final String MASTERSERVER_IDM = "masterserver.idm";
+ private static final String MASTERSERVER_ADDRESS = "masterserver.address";
+
private final static String PROPERTIES_FILE = "branding.properties";
private final static Properties PROPERTIES = new Properties();
private final static List<Path> RESOURCES = new ArrayList<Path>();
+ public static final String RESOURCE_FS_DIR;
+
+ private final static Map<String, String> DEFAULTS = new HashMap<String, String>() {
+ private static final long serialVersionUID = -5625624201188857134L;
+
+ {
+ put(MASTERSERVER_ADDRESS, "bwlp-masterserver.ruf.uni-freiburg.de");
+ put(MASTERSERVER_IDM, "bwIDM");
+ put(APPLICATION_NAME, "bwLehrpool-Suite");
+ put(SERVICE_FAQ_WEBSITE, "https://www.bwLehrpool.de");
+ put(SERVICE_NAME, "bwLehrpool");
+ put(CONFIG_DIRECTORY, "bwSuite");
+ put(SERVICE_EMAIL, "support@bwlehrpool.de");
+ put(VIRTUALIZER_WEBSITE, "https://www.bwlehrpool.de/doku.php/allgemein/virtualisierer");
+ }
+ };
+
static {
- try (InputStream in = App.class.getClassLoader().getResourceAsStream(PROPERTIES_FILE)) {
- PROPERTIES.load(in);
- } catch (Exception e) {
- LOGGER.error("Failed to read '" + PROPERTIES_FILE + "': ", e);
+ String path = null;
+ try {
+ RESOURCES.add(Paths.get(PROPERTIES_FILE));
+ RESOURCES.add(Paths.get("img"));
+ RESOURCES.add(Paths.get("txt"));
+ // Built-in properties file takes precedence
+ boolean ok = false;
+ try (InputStream in = App.class.getClassLoader().getResourceAsStream(PROPERTIES_FILE)) {
+ PROPERTIES.load(in);
+ LOGGER.info("Loaded branding from jar");
+ ok = true;
+ } catch (Exception e) {
+ LOGGER.debug("Failed to read 'jar:" + PROPERTIES_FILE + "': ");
+ }
+ if (!ok) {
+ // Try CWD
+ try (InputStream in = new FileInputStream(PROPERTIES_FILE)) {
+ PROPERTIES.load(in);
+ LOGGER.info("Loaded branding from current working directory");
+ path = "./";
+ ok = true;
+ } catch (Exception e) {
+ LOGGER.debug("Failed to read './" + PROPERTIES_FILE + "': ");
+ }
+ }
+ if (!ok) {
+ // Try system-wide defaults
+ if (OsHelper.isWindows()) {
+ path = System.getenv("ProgramData");
+ if (Util.isEmptyString(path)) {
+ path = "C:\\ProgramData";
+ }
+ } else {
+ path = "/etc";
+ }
+ path = path + "/bwlp/";
+ try (InputStream in = new FileInputStream(path + PROPERTIES_FILE)) {
+ PROPERTIES.load(in);
+ LOGGER.info("Loaded system-wide branding");
+ ok = true;
+ } catch (Exception e) {
+ LOGGER.debug("Failed to read '" + path + PROPERTIES_FILE + "': ");
+ path = null;
+ }
+ }
+ // Fill in missing fields
+ PROPERTIES.store(System.out, "");
+ for (Entry<String, String> it : DEFAULTS.entrySet()) {
+ if (!PROPERTIES.containsKey(it.getKey())) {
+ PROPERTIES.setProperty(it.getKey(), it.getValue());
+ }
+ }
+ PROPERTIES.store(System.out, "");
+ } catch (Throwable t) {
+ t.printStackTrace();
+ System.exit(1);
}
- RESOURCES.add(Paths.get(PROPERTIES_FILE));
- RESOURCES.add(Paths.get("img"));
- RESOURCES.add(Paths.get("txt"));
+ RESOURCE_FS_DIR = path;
}
public final static String getMasterServerAddress() {
- return PROPERTIES.getProperty("masterserver.address", "bwlp-masterserver.ruf.uni-freiburg.de");
+ return PROPERTIES.getProperty(MASTERSERVER_ADDRESS);
}
public final static String getMasterServerIdm() {
- return PROPERTIES.getProperty("masterserver.idm", "bwIDM");
+ return PROPERTIES.getProperty(MASTERSERVER_IDM);
}
public final static String getApplicationName() {
- return PROPERTIES.getProperty("application.name", "bwLehrpool-Suite");
+ return PROPERTIES.getProperty(APPLICATION_NAME);
}
public final static String getServiceFAQWebsite() {
- return PROPERTIES.getProperty("service.faq.website", "https://www.bwLehrpool.de");
+ return PROPERTIES.getProperty(SERVICE_FAQ_WEBSITE);
}
public final static String getServiceName() {
- return PROPERTIES.getProperty("service.name", "bwLehrpool");
+ return PROPERTIES.getProperty(SERVICE_NAME);
}
public final static String getConfigDirectory() {
- return PROPERTIES.getProperty("config.directory", "bwSuite");
+ return PROPERTIES.getProperty(CONFIG_DIRECTORY);
}
public final static String getServiceEmail() {
- return PROPERTIES.getProperty("service.email", "support@bwlehrpool.de");
+ return PROPERTIES.getProperty(SERVICE_EMAIL);
}
public final static String getVirtualizerWebsite() {
- return PROPERTIES.getProperty("virtualizer.website", "https://www.bwlehrpool.de/doku.php/allgemein/virtualisierer");
+ return PROPERTIES.getProperty(VIRTUALIZER_WEBSITE);
}
public final static String getProxyMode() {
@@ -128,9 +210,6 @@ public final class Branding {
private static void copyBranding(final URI jarUri, final String localDir, final boolean pack) {
try (FileSystem fs = FileSystems.newFileSystem(URI.create("jar:" + jarUri),
new HashMap<String, String>() {
- /**
- * Version for serialization.
- */
private static final long serialVersionUID = -5625624201188857134L;
{
@@ -160,8 +239,15 @@ public final class Branding {
dst = rootPathLocal.resolve(res);
}
if (!Files.isReadable(src)) {
- LOGGER.error("Failed to find or read '" + src + "'.");
- return;
+ if (!pack && res.endsWith(PROPERTIES_FILE)) {
+ // Missing properties file is OK, just dump current state
+ try (FileOutputStream fos = new FileOutputStream(dst.toFile())) {
+ PROPERTIES.store(fos, "");
+ }
+ } else {
+ LOGGER.error("Failed to find or read '" + src + "'.");
+ }
+ continue;
}
if (Files.isDirectory(src)) {
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ResourceLoader.java b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ResourceLoader.java
index 02004cc0..a6e932cc 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ResourceLoader.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ResourceLoader.java
@@ -9,7 +9,10 @@ import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.InputStream;
+import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
@@ -21,6 +24,7 @@ import javax.swing.ImageIcon;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.openslx.dozmod.Branding;
import org.openslx.dozmod.Config;
/**
@@ -49,7 +53,20 @@ public class ResourceLoader
*/
public static ImageIcon getIcon( String path, String description )
{
- URL url = ResourceLoader.class.getResource( path );
+ URL url = null;
+ if ( Branding.RESOURCE_FS_DIR != null ) {
+ File file = new File( Branding.RESOURCE_FS_DIR + path );
+ try {
+ if ( file.exists() && file.isFile() && file.canRead() ) {
+ url = file.toURI().toURL();
+ }
+ } catch ( MalformedURLException e ) {
+ LOGGER.warn( "Malformed URL: " + file.toString(), e );
+ }
+ }
+ if ( url == null ) {
+ url = ResourceLoader.class.getResource( path );
+ }
if ( url == null ) {
LOGGER.error( "Resource not found: " + path );
} else {
@@ -60,6 +77,7 @@ public class ResourceLoader
icon.getImage().getScaledInstance(Math.round(icon.getIconWidth() * scalingFactor),
Math.round(icon.getIconHeight() * scalingFactor), java.awt.Image.SCALE_SMOOTH),
description);
+ // Success ^^
} catch ( Exception e ) {
LOGGER.error( "Resource not loadable: " + path );
}
@@ -135,10 +153,18 @@ public class ResourceLoader
public static String getTextFile( String path )
{
String fileContent = null;
- try ( InputStream stream = ResourceLoader.class.getResourceAsStream( path ) ) {
- fileContent = IOUtils.toString( stream, StandardCharsets.UTF_8 );
- } catch ( Exception e ) {
- LOGGER.error( "IO error while trying to load resource '" + path + "'. See trace: ", e );
+ if ( Branding.RESOURCE_FS_DIR != null ) {
+ try ( InputStream stream = new FileInputStream( Branding.RESOURCE_FS_DIR + path ) ) {
+ fileContent = IOUtils.toString( stream, StandardCharsets.UTF_8 );
+ } catch ( Exception e ) {
+ }
+ }
+ if ( fileContent == null ) {
+ try ( InputStream stream = ResourceLoader.class.getResourceAsStream( path ) ) {
+ fileContent = IOUtils.toString( stream, StandardCharsets.UTF_8 );
+ } catch ( Exception e ) {
+ LOGGER.error( "IO error while trying to load resource '" + path + "'. See trace: ", e );
+ }
}
if ( fileContent != null ) {
@@ -150,6 +176,12 @@ public class ResourceLoader
public static InputStream getStream( String path )
{
+ if ( Branding.RESOURCE_FS_DIR != null ) {
+ try {
+ return new FileInputStream( Branding.RESOURCE_FS_DIR + path );
+ } catch (Exception e) {
+ }
+ }
return ResourceLoader.class.getResourceAsStream( path );
}
diff --git a/dozentenmodul/src/main/properties/branding.properties b/dozentenmodul/src/main/properties/branding.properties
deleted file mode 100644
index 652fae5a..00000000
--- a/dozentenmodul/src/main/properties/branding.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-masterserver.address=bwlp-masterserver.ruf.uni-freiburg.de
-masterserver.idm=bwIDM
-application.name=bwLehrpool-Suite
-service.name=bwLehrpool
-service.faq.website=www.bwlehrpool.de
-service.email=support@bwlehrpool.de
-config.directory=bwSuite
-proxy.mode=AUTO