diff --git a/bundled-war-example/src/main/webapp/WEB-INF/web.xml b/bundled-war-example/src/main/webapp/WEB-INF/web.xml
index 5d17437..b1e4d3d 100755
--- a/bundled-war-example/src/main/webapp/WEB-INF/web.xml
+++ b/bundled-war-example/src/main/webapp/WEB-INF/web.xml
@@ -10,16 +10,21 @@
<param-value>localhost:8080</param-value>
</context-param>
+ <context-param>
+ <param-name>keycloak.import.realm.resources</param-name>
+ <param-value>/WEB-INF/testrealm.json</param-value>
+ </context-param>
+
<servlet>
<servlet-name>Keycloak REST Interface</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
- <param-value>org.keycloak.server.KeycloakServerApplication</param-value>
+ <param-value>org.keycloak.services.resources.KeycloakApplication</param-value>
</init-param>
<init-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
- <param-value>/rest</param-value>
+ <param-value>/</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
@@ -40,19 +45,10 @@
<async-supported>true</async-supported>
</servlet>
- <servlet>
- <servlet-name>TmpAdminRedirectServlet</servlet-name>
- <servlet-class>org.keycloak.services.tmp.TmpAdminRedirectServlet</servlet-class>
- </servlet>
-
<listener>
<listener-class>org.keycloak.services.listeners.KeycloakSessionDestroyListener</listener-class>
</listener>
- <welcome-file-list>
- <welcome-file>index.html</welcome-file>
- </welcome-file-list>
-
<filter>
<filter-name>Keycloak Client Connection Filter</filter-name>
<filter-class>org.keycloak.services.filters.ClientConnectionFilter</filter-class>
@@ -75,32 +71,22 @@
<servlet-mapping>
<servlet-name>Keycloak REST Interface</servlet-name>
- <url-pattern>/rest/*</url-pattern>
+ <url-pattern>/*</url-pattern>
</servlet-mapping>
+
+ <!-- -->
+
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
<servlet-mapping>
<servlet-name>Customer REST Interface</servlet-name>
<url-pattern>/database/*</url-pattern>
</servlet-mapping>
- <servlet-mapping>
- <servlet-name>TmpAdminRedirectServlet</servlet-name>
- <url-pattern>/admin</url-pattern>
- <url-pattern>/admin/</url-pattern>
- </servlet-mapping>
-
- <!--
-
- <security-constraint>
- <web-resource-collection>
- <url-pattern>/*</url-pattern>
- </web-resource-collection>
- <user-data-constraint>
- <transport-guarantee>CONFIDENTIAL</transport-guarantee>
- </user-data-constraint>
- </security-constraint>
- -->
-
<security-constraint>
<web-resource-collection>
<web-resource-name>Customers</web-resource-name>
diff --git a/server/src/main/webapp/WEB-INF/web.xml b/server/src/main/webapp/WEB-INF/web.xml
index 356425f..76b4932 100755
--- a/server/src/main/webapp/WEB-INF/web.xml
+++ b/server/src/main/webapp/WEB-INF/web.xml
@@ -7,11 +7,11 @@
<module-name>auth</module-name>
<servlet>
- <servlet-name>Resteasy</servlet-name>
+ <servlet-name>Keycloak REST Interface</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
- <param-value>org.keycloak.server.KeycloakServerApplication</param-value>
+ <param-value>org.keycloak.services.resources.KeycloakApplication</param-value>
</init-param>
<init-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
@@ -46,7 +46,7 @@
</filter-mapping>
<servlet-mapping>
- <servlet-name>Resteasy</servlet-name>
+ <servlet-name>Keycloak REST Interface</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index 7c8371b..2cab3d0 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -18,27 +18,35 @@ import org.keycloak.models.RealmModel;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.ProviderFactoryLoader;
import org.keycloak.provider.ProviderSession;
+import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.DefaultProviderSessionFactory;
import org.keycloak.picketlink.IdentityManagerProvider;
import org.keycloak.picketlink.IdentityManagerProviderFactory;
import org.keycloak.provider.ProviderSessionFactory;
import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.managers.BruteForceProtector;
+import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.SocialRequestManager;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.resources.admin.AdminService;
import org.keycloak.models.utils.ModelProviderUtils;
import org.keycloak.timer.TimerProvider;
import org.keycloak.timer.TimerProviderFactory;
+import org.keycloak.util.JsonSerialization;
import javax.servlet.ServletContext;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
import java.net.URI;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
+import java.util.StringTokenizer;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -66,7 +74,6 @@ public class KeycloakApplication extends Application {
context.setAttribute(BruteForceProtector.class.getName(), protector);
this.providerSessionFactory = createProviderSessionFactory();
context.setAttribute(KeycloakSessionFactory.class.getName(), factory);
- //classes.add(KeycloakSessionCleanupFilter.class);
context.setAttribute(ProviderSessionFactory.class.getName(), this.providerSessionFactory);
@@ -86,6 +93,7 @@ public class KeycloakApplication extends Application {
setupDefaultRealm(context.getContextPath());
setupScheduledTasks(providerSessionFactory, factory);
+ importRealms(context);
}
public String getContextPath() {
@@ -184,4 +192,75 @@ public class KeycloakApplication extends Application {
return singletons;
}
+ public void importRealms(ServletContext context) {
+ importRealmFile();
+ importRealmResources(context);
+
+ }
+
+ public void importRealmResources(ServletContext context) {
+ String resources = context.getInitParameter("keycloak.import.realm.resources");
+ if (resources != null) {
+ StringTokenizer tokenizer = new StringTokenizer(resources, ",");
+ while (tokenizer.hasMoreTokens()) {
+ String resource = tokenizer.nextToken().trim();
+ InputStream is = context.getResourceAsStream(resource);
+ if (is == null) {
+ log.warn("Could not find realm resource to import: " + resource);
+ }
+ RealmRepresentation rep = loadJson(is, RealmRepresentation.class);
+ importRealm(rep, "resource " + resource);
+ }
+ }
+ }
+
+ public void importRealmFile() {
+ String file = System.getProperty("keycloak.import");
+ if (file != null) {
+ RealmRepresentation rep = null;
+ try {
+ rep = loadJson(new FileInputStream(file), RealmRepresentation.class);
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ importRealm(rep, "file " + file);
+ }
+ }
+
+ public void importRealm(RealmRepresentation rep, String from) {
+ KeycloakSession session = factory.createSession();
+ try {
+ session.getTransaction().begin();
+ RealmManager manager = new RealmManager(session);
+
+ if (rep.getId() != null && manager.getRealm(rep.getId()) != null) {
+ log.info("Not importing realm " + rep.getRealm() + " from " + from + ". It already exists.");
+ return;
+ }
+
+ if (manager.getRealmByName(rep.getRealm()) != null) {
+ log.info("Not importing realm " + rep.getRealm() + " from " + from + ". It already exists.");
+ return;
+ }
+
+ RealmModel realm = manager.createRealm(rep.getId(), rep.getRealm());
+ manager.importRealm(rep, realm);
+
+ log.info("Imported realm " + realm.getName() + " from " + from);
+
+ session.getTransaction().commit();
+ } finally {
+ session.close();
+ }
+ }
+
+ private static <T> T loadJson(InputStream is, Class<T> type) {
+ try {
+ return JsonSerialization.readValue(is, type);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to parse json", e);
+ }
+ }
+
+
}