From eb378af2fab2b35dad95fe1b954d9e2fab9dacc0 Mon Sep 17 00:00:00 2001
From: gnaegi <none@none>
Date: Wed, 3 Jul 2013 21:48:58 +0200
Subject: [PATCH] OO-650 support for custom themes directory outside of web app
 eg in olatdata

---
 .../admin/layout/LayoutAdminController.java   | 16 +++++++++++
 .../dispatcher/StaticMediaDispatcher.java     |  9 ++++++
 .../java/org/olat/core/helpers/Settings.java  | 28 ++++++++++++++++++-
 .../core/util/_spring/utilCorecontext.xml     |  6 ++++
 .../resources/serviceconfig/olat.properties   |  2 ++
 5 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/olat/admin/layout/LayoutAdminController.java b/src/main/java/org/olat/admin/layout/LayoutAdminController.java
index fb92789ee4d..0f4d5b9259e 100644
--- a/src/main/java/org/olat/admin/layout/LayoutAdminController.java
+++ b/src/main/java/org/olat/admin/layout/LayoutAdminController.java
@@ -21,7 +21,9 @@ package org.olat.admin.layout;
 
 import java.io.File;
 import java.io.FilenameFilter;
+import java.util.Arrays;
 
+import org.apache.commons.lang.ArrayUtils;
 import org.olat.admin.SystemAdminMainController;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
@@ -95,6 +97,20 @@ public class LayoutAdminController extends FormBasicController {
 			File theme = themes[i];
 			themesStr[i] = theme.getName();
 		}
+		
+		// add custom themes from configuration if available
+		File customThemesDir = Settings.getGuiCustomThemePath();
+		if (customThemesDir != null) {
+			File[] customThemes = customThemesDir.listFiles(new ThemesFileNameFilter());
+			String[] customThemesStr = new String[customThemes.length];
+			for (int i = 0; i < customThemes.length; i++) {
+				File theme = customThemes[i];
+				customThemesStr[i] = theme.getName();
+			}
+			themesStr = (String[]) ArrayUtils.addAll(themesStr, customThemesStr);
+			Arrays.sort(themesStr);
+		}
+		
 		return themesStr;
 	}
 	
diff --git a/src/main/java/org/olat/core/defaults/dispatcher/StaticMediaDispatcher.java b/src/main/java/org/olat/core/defaults/dispatcher/StaticMediaDispatcher.java
index abb680df397..c40106012ad 100644
--- a/src/main/java/org/olat/core/defaults/dispatcher/StaticMediaDispatcher.java
+++ b/src/main/java/org/olat/core/defaults/dispatcher/StaticMediaDispatcher.java
@@ -119,6 +119,15 @@ public class StaticMediaDispatcher extends LogDelegator implements Dispatcher {
 			staticAbsPath = WebappHelper.getContextRoot() + STATIC_DIR_NAME;
 		}
 		File staticFile = new File(staticAbsPath, normalizedRelPath);
+		
+		// try loading themes from custom themes folder if configured 
+		if (!staticFile.exists() && normalizedRelPath.contains("/themes/") && Settings.getGuiCustomThemePath() != null) {
+			File customThemesDir = Settings.getGuiCustomThemePath();
+			String path = staticFile.getAbsolutePath();
+			path = path.substring(path.indexOf("/static/themes/") + 15);
+			staticFile = new File(customThemesDir, path);
+		}
+
 		// only serve if file exists
 		if (!staticFile.exists()) {
 			if (isLogDebugEnabled()) {
diff --git a/src/main/java/org/olat/core/helpers/Settings.java b/src/main/java/org/olat/core/helpers/Settings.java
index 235257dd1fe..24abdf97c92 100644
--- a/src/main/java/org/olat/core/helpers/Settings.java
+++ b/src/main/java/org/olat/core/helpers/Settings.java
@@ -28,6 +28,7 @@
 */
 package org.olat.core.helpers;
 
+import java.io.File;
 import java.io.IOException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -84,8 +85,8 @@ public class Settings implements Initializable, Destroyable, GenericEventListene
 	private static String clusterMode;
 	private static Date buildDate;
 	private static String repoRevision;
-	private static String patchRepoRevision;
 	private static String crossOriginFilter;
+	private static File guiCustomThemePath;
 	
 	/**
 	 * [used by spring]
@@ -364,6 +365,31 @@ public class Settings implements Initializable, Destroyable, GenericEventListene
 		Settings.guiThemeIdentifyer = guiThemeIdentifyer;
 	}
 
+	/**
+	 * @return the File object pointing to the custom themes folder or null if
+	 *         no custom themes folder configured
+	 */
+	public static File getGuiCustomThemePath() {
+		return guiCustomThemePath;			
+	}
+
+	/**
+	 * Set the custom CSS themes folder (optional). Only used by spring.
+	 * 
+	 * @param guiCustomThemePath
+	 *            Absolute path pointing to the custom themes directory
+	 */
+	public void setGuiCustomThemePath(String guiCustomThemePath) {
+		File newPath = new File(guiCustomThemePath);
+		if (newPath.exists()) {
+			Settings.guiCustomThemePath = newPath;
+		} else {
+			log.info("No custom theme directory configured, path::"
+					+ guiCustomThemePath
+					+ " invalid. Configure property layout.custom.themes.dir if you want to use a custom themes directory.");
+		}
+	}	
+	
 	/**
 	 * Set the CSS theme used for this webapp. The configuration is stored in
 	 * the olatdata/system/configuration properties file and overrides the
diff --git a/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml b/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml
index 02e7092cc9e..64fb55b9a2d 100644
--- a/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml
+++ b/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml
@@ -97,6 +97,12 @@
 			Set a specific theme.
 		-->				
 		<property name="guiThemeIdentifyer" value="${layout.theme}" />				
+		<!-- 
+			Optional path to a directory which contains custom themes. This is an alternative to placing the theme
+			into the webapp, default is to have your custom themes in olatdata/customizing/themes
+			Note that this must be an absolute path.
+		 -->
+		<property name="guiCustomThemePath" value="${layout.custom.themes.dir}" />						
 		<!-- the versionid is prepended to various dynamically linked sources like css and js lib includes.
 			the prepending guarantees that all browsers are forced to reload the new files, since e.g. css cache invalidation
 			based on lastmodified http headers is broken on some browsers. this here is the only safe way.
diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties
index bd485c48e06..60676c79aeb 100644
--- a/src/main/resources/serviceconfig/olat.properties
+++ b/src/main/resources/serviceconfig/olat.properties
@@ -315,6 +315,8 @@ instance.id=myopenolat
 # you can also configure a theme via the admin GUI which takes precedence
 layout.theme=openolat
 layout.coursetemplates.blacklist=
+# Absolute path to directory where custom themes are loaded from (optional)
+layout.custom.themes.dir=${userdata.dir}/customizing/themes
 
 # test user generation
 user.generateTestUsers=false
-- 
GitLab