KEYCLOAK-8818 Support message bundle in theme resources

This commit is contained in:
Cédric Couralet 2019-09-03 14:13:57 +02:00 committed by Stian Thorgersen
parent c2f3350f8a
commit 9c37da0ee9
5 changed files with 66 additions and 10 deletions

View file

@ -17,12 +17,13 @@
package org.keycloak.theme; package org.keycloak.theme;
import org.keycloak.provider.Provider;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.Set; import java.util.Locale;
import java.util.Properties;
import org.keycloak.provider.Provider;
/** /**
* A theme resource provider can be used to load additional templates and resources. An example use of this would be * A theme resource provider can be used to load additional templates and resources. An example use of this would be
@ -53,4 +54,17 @@ public interface ThemeResourceProvider extends Provider {
*/ */
InputStream getResourceAsStream(String path) throws IOException; InputStream getResourceAsStream(String path) throws IOException;
/**
* Load the message bundle for the specific name and locale
*
* @param baseBundlename The base name of the bundle, such as "messages" in
* messages_en.properties.
* @param locale The locale of the desired message bundle.
* @return The localized messages from the bundle.
* @throws IOException If bundle can not be read.
*/
default Properties getMessages(String baseBundlename, Locale locale) throws IOException{
return new Properties();
}
} }

View file

@ -1,17 +1,24 @@
package org.keycloak.theme; package org.keycloak.theme;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Locale;
import java.util.Properties;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class ClasspathThemeResourceProviderFactory implements ThemeResourceProviderFactory, ThemeResourceProvider { public class ClasspathThemeResourceProviderFactory implements ThemeResourceProviderFactory, ThemeResourceProvider {
public static final String THEME_RESOURCES_TEMPLATES = "theme-resources/templates/"; public static final String THEME_RESOURCES_TEMPLATES = "theme-resources/templates/";
public static final String THEME_RESOURCES_RESOURCES = "theme-resources/resources/"; public static final String THEME_RESOURCES_RESOURCES = "theme-resources/resources/";
public static final String THEME_RESOURCES_MESSAGES = "theme-resources/messages/";
private final String id; private final String id;
private final ClassLoader classLoader; private final ClassLoader classLoader;
@ -35,6 +42,21 @@ public class ClasspathThemeResourceProviderFactory implements ThemeResourceProvi
return classLoader.getResourceAsStream(THEME_RESOURCES_RESOURCES + path); return classLoader.getResourceAsStream(THEME_RESOURCES_RESOURCES + path);
} }
@Override
public Properties getMessages(String baseBundlename, Locale locale) throws IOException {
Properties m = new Properties();
InputStream in = classLoader.getResourceAsStream(THEME_RESOURCES_MESSAGES + baseBundlename + "_" + locale.toString() + ".properties");
if(in != null){
Charset encoding = PropertiesUtil.detectEncoding(in);
// detectEncoding closes the stream
try (Reader reader = new InputStreamReader(
classLoader.getResourceAsStream(THEME_RESOURCES_MESSAGES + baseBundlename + "_" + locale.toString() + ".properties"), encoding)) {
m.load(reader);
}
}
return m;
}
@Override @Override
public String getId() { public String getId() {
return id; return id;

View file

@ -257,6 +257,10 @@ public class ExtendingThemeManager implements ThemeProvider {
messages.putAll(getMessages(baseBundlename, Locale.ENGLISH)); messages.putAll(getMessages(baseBundlename, Locale.ENGLISH));
} }
for (ThemeResourceProvider t : themeResourceProviders ){
messages.putAll(t.getMessages(baseBundlename, locale));
}
ListIterator<Theme> itr = themes.listIterator(themes.size()); ListIterator<Theme> itr = themes.listIterator(themes.size());
while (itr.hasPrevious()) { while (itr.hasPrevious()) {
Properties m = itr.previous().getMessages(baseBundlename, locale); Properties m = itr.previous().getMessages(baseBundlename, locale);
@ -264,7 +268,7 @@ public class ExtendingThemeManager implements ThemeProvider {
messages.putAll(m); messages.putAll(m);
} }
} }
this.messages.putIfAbsent(baseBundlename, new ConcurrentHashMap<Locale, Properties>()); this.messages.putIfAbsent(baseBundlename, new ConcurrentHashMap<Locale, Properties>());
this.messages.get(baseBundlename).putIfAbsent(locale, messages); this.messages.get(baseBundlename).putIfAbsent(locale, messages);

View file

@ -0,0 +1,2 @@
test.keycloak-8818= Hello from theme-resources
fullName=Full name (Theme-resources)

View file

@ -1,5 +1,8 @@
package org.keycloak.testsuite.theme; package org.keycloak.testsuite.theme;
import java.io.IOException;
import java.util.Locale;
import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.shrinkwrap.api.spec.WebArchive; import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Assert; import org.junit.Assert;
@ -10,8 +13,6 @@ import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import org.keycloak.theme.Theme; import org.keycloak.theme.Theme;
import org.keycloak.theme.ThemeProvider; import org.keycloak.theme.ThemeProvider;
import java.io.IOException;
public class ThemeResourceProviderTest extends AbstractTestRealmKeycloakTest { public class ThemeResourceProviderTest extends AbstractTestRealmKeycloakTest {
@Deployment @Deployment
@ -50,4 +51,17 @@ public class ThemeResourceProviderTest extends AbstractTestRealmKeycloakTest {
}); });
} }
@Test
public void getMessages() {
testingClient.server().run(session -> {
try {
ThemeProvider extending = session.getProvider(ThemeProvider.class, "extending");
Theme theme = extending.getTheme("base", Theme.Type.LOGIN);
Assert.assertNotNull(theme.getMessages("messages", Locale.ENGLISH).get("test.keycloak-8818"));
Assert.assertNotEquals("Full name (Theme-resources)", theme.getMessages("messages", Locale.ENGLISH).get("fullName"));
} catch (IOException e) {
Assert.fail(e.getMessage());
}
});
}
} }