Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
import com.vaadin.flow.server.communication.IndexHtmlRequestListener;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Optional;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Service initialization listener that automatically applies a dynamic theme.
Expand All @@ -19,23 +24,51 @@
@SuppressWarnings("serial")
public class DynamicThemeInitializer implements VaadinServiceInitListener {

private static final Logger logger = LoggerFactory.getLogger(DynamicThemeInitializer.class);

private static final String PROPERTIES_PATH = "META-INF/dynamic-theme.properties";

@Override
public void serviceInit(ServiceInitEvent event) {
if (DynamicTheme.isFeatureSupported()) {
try (InputStream in = getClass().getResourceAsStream("/META-INF/dynamic-theme.properties")) {
if (in != null) {
Properties props = new Properties();
props.load(in);
String themeName = props.getProperty("theme");
if (themeName != null) {
DynamicTheme theme = DynamicTheme.valueOf(themeName.trim());
try {
Enumeration<URL> resources = getClass().getClassLoader().getResources(PROPERTIES_PATH);
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
String source = getSourceName(url);
readTheme(url).ifPresent(theme -> {
logger.info("Applying dynamic theme '{}' from {}", theme, source);
event.addIndexHtmlRequestListener(theme::initialize);
}
});
}
} catch (IOException e) {
throw new RuntimeException("Error reading dynamic-theme.properties", e);
}
}
}

private Optional<DynamicTheme> readTheme(URL url) throws IOException {
try (InputStream in = url.openStream()) {
Properties props = new Properties();
props.load(in);
String themeName = props.getProperty("theme");
return Optional.ofNullable(themeName).map(String::trim).map(DynamicTheme::valueOf);
}
}

// Extracts a short, readable source name from the URL.
private String getSourceName(URL url) {
String path = url.getPath();
// JAR URLs look like: file:/path/to/file.jar!/META-INF/...
int jarSeparator = path.indexOf("!/");
if (jarSeparator > 0) {
path = path.substring(0, jarSeparator);
int lastSlash = path.lastIndexOf('/');
if (lastSlash >= 0) {
return path.substring(lastSlash + 1);
}
}
return url.toString();
}

}