diff --git a/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java b/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java index e011e114f34..d5bfdcbe5c5 100755 --- a/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java +++ b/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java @@ -1,18 +1,5 @@ package org.keycloak.connections.jpa; -import org.hibernate.ejb.AvailableSettings; -import org.jboss.logging.Logger; -import org.keycloak.Config; -import org.keycloak.connections.jpa.updater.JpaUpdaterProvider; -import org.keycloak.connections.jpa.util.JpaUtils; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.KeycloakSessionFactory; - -import javax.naming.InitialContext; -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.Persistence; -import javax.sql.DataSource; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; @@ -22,10 +9,25 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; +import javax.naming.InitialContext; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.sql.DataSource; + +import org.hibernate.ejb.AvailableSettings; +import org.jboss.logging.Logger; +import org.keycloak.Config; +import org.keycloak.connections.jpa.updater.JpaUpdaterProvider; +import org.keycloak.connections.jpa.util.JpaUtils; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.provider.ServerInfoAwareProviderFactory; + /** * @author Stian Thorgersen */ -public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory { +public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory, ServerInfoAwareProviderFactory { private static final Logger logger = Logger.getLogger(DefaultJpaConnectionProviderFactory.class); diff --git a/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java b/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java index 288e403335a..2fc645d752d 100644 --- a/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java +++ b/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java @@ -1,10 +1,10 @@ package org.keycloak.connections.jpa; -import org.keycloak.provider.ServerInfoAwareProviderFactory; +import org.keycloak.provider.ProviderFactory; /** * @author Stian Thorgersen */ -public interface JpaConnectionProviderFactory extends ServerInfoAwareProviderFactory { +public interface JpaConnectionProviderFactory extends ProviderFactory { } diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java index 00f338667e4..ae9701b4753 100755 --- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java +++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java @@ -1,11 +1,12 @@ package org.keycloak.connections.mongo; -import com.mongodb.DB; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; -import com.mongodb.MongoClientURI; -import com.mongodb.MongoCredential; -import com.mongodb.ServerAddress; +import java.lang.reflect.Method; +import java.net.UnknownHostException; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.net.ssl.SSLSocketFactory; import org.jboss.logging.Logger; import org.keycloak.Config; @@ -15,18 +16,19 @@ import org.keycloak.connections.mongo.impl.context.TransactionMongoStoreInvocati import org.keycloak.connections.mongo.updater.MongoUpdaterProvider; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.provider.ServerInfoAwareProviderFactory; -import javax.net.ssl.SSLSocketFactory; -import java.lang.reflect.Method; -import java.net.UnknownHostException; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; +import com.mongodb.DB; +import com.mongodb.MongoClient; +import com.mongodb.MongoClientOptions; +import com.mongodb.MongoClientURI; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; /** * @author Stian Thorgersen */ -public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory { +public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory, ServerInfoAwareProviderFactory { // TODO Make it dynamic private String[] entities = new String[]{ diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java index bce5fe4b9cf..e787ce63825 100644 --- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java +++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java @@ -1,9 +1,9 @@ package org.keycloak.connections.mongo; -import org.keycloak.provider.ServerInfoAwareProviderFactory; +import org.keycloak.provider.ProviderFactory; /** * @author Stian Thorgersen */ -public interface MongoConnectionProviderFactory extends ServerInfoAwareProviderFactory { +public interface MongoConnectionProviderFactory extends ProviderFactory { } diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml b/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml index eda5acacc4f..71c2919441e 100755 --- a/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml +++ b/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml @@ -16,7 +16,7 @@ For example to implement the Event Listener SPI you start by implementing EventListenerProviderFactory: - +]]> The example uses an imagined MaxList which has a maximum size and is concurrency safe. When the maximum size is reached and new entries are added the oldest entry is removed. Keycloak creates a single instance of EventListenerProviderFactory which makes it possible to store state for multiple requests. EventListenerProvider @@ -51,7 +51,7 @@ public class MyEventListenerProviderFactory implements EventListenerProviderFact Next you would implement EventListenerProvider: - +]]> The file META-INF/services/org.keycloak.events.EventListenerProviderFactory should contain the full name of your ProviderFactory implementation: + +
+ Show info from you SPI implementation in Keycloak admin console + + Sometimes it is useful to show additional info about your Provider to a Keycloak administrator. + You can show provider build time informations (eg. version of custom provider currently installed), + current configuration of the provider (eg. url of remote system your provider talks to) or some operational + info (average time of response from remote system your provider talks to). + Keycloak admin console provides Server Info page to show this kind of information. + + + To show info from your provider it is enough to implement + org.keycloak.provider.ServerInfoAwareProviderFactory interface in your ProviderFactory. + Example implementation for MyEventListenerProviderFactory from previous example: + events; + private int max; + +... + + @Override + public void init(Config.Scope config) { + max = config.getInt("max"); + events = new MaxList(max); + } + +... + + @Override + public Map getOperationalInfo() { + Map ret = new LinkedHashMap<>(); + ret.put("version", "1.0"); + ret.put("listSizeMax", max + ""); + ret.put("listSizeCurrent", events.size() + ""); + return ret; + } + +} +]]> + + +
@@ -98,13 +146,13 @@ public class MyEventListenerProvider implements EventListenerProvider { To register a provider using Modules first create a module. To do this you can either use the jboss-cli script or manually create a folder inside KEYCLOAK_HOME/modules and add your jar and a module.xml. For example to add the event listener sysout example provider using the jboss-cli script execute: - +]]> Or to manually create it start by creating the folder KEYCLOAK_HOME/modules/org/keycloak/examples/event-sysout/main. Then copy event-listener-sysout-example.jar to this folder and create module.xml with the following content: - @@ -116,7 +164,7 @@ public class MyEventListenerProvider implements EventListenerProvider { -}]]> +]]> Once you've created the module you need to register this module with Keycloak. This is done by editing diff --git a/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java b/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java index 97d17b1dcc0..7674047ac4a 100644 --- a/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java +++ b/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java @@ -3,15 +3,15 @@ package org.keycloak.provider; import java.util.Map; /** - * Marker interface for ProviderFactory of Provider which wants to show some info on "Server Info" page in Admin console. + * Marker interface for {@link ProviderFactory} of Provider which wants to show some info on "Server Info" page in Admin console. * * @author Vlastimil Elias (velias at redhat dot com) */ -public interface ServerInfoAwareProviderFactory extends ProviderFactory { +public interface ServerInfoAwareProviderFactory { /** - * Get operational info about given provider. This info contains informations about providers configuration and operational conditions (eg. errors in connection to remote systems etc) which is - * shown on "Server Info" page. + * Return actual info about the provider. This info contains informations about providers configuration and operational conditions (eg. errors in connection to remote systems etc) which is + * shown on "Server Info" page then. * * @return Map with keys describing value and relevant values itself */ diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java index 4ef2a630e1c..660b1c43963 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java @@ -1,5 +1,17 @@ package org.keycloak.services.resources.admin.info; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; + +import javax.ws.rs.GET; +import javax.ws.rs.core.Context; + import org.keycloak.broker.provider.IdentityProvider; import org.keycloak.broker.provider.IdentityProviderFactory; import org.keycloak.events.EventType; @@ -21,10 +33,6 @@ import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation; import org.keycloak.social.SocialIdentityProvider; -import javax.ws.rs.GET; -import javax.ws.rs.core.Context; -import java.util.*; - /** * @author Stian Thorgersen */ @@ -73,7 +81,6 @@ public class ServerInfoAdminResource { for (Spi spi : spis) { SpiInfoRepresentation spiRep = new SpiInfoRepresentation(); spiRep.setInternal(spi.isInternal()); - spiRep.setSystemInfo(ServerInfoAwareProviderFactory.class.isAssignableFrom(spi.getProviderFactoryClass())); List providerIds = new LinkedList<>(session.listProviderIds(spi.getProviderClass())); Collections.sort(providerIds); @@ -83,8 +90,9 @@ public class ServerInfoAdminResource { if (providerIds != null) { for (String name : providerIds) { ProviderRepresentation provider = new ProviderRepresentation(); - if (spiRep.isSystemInfo()) { - provider.setOperationalInfo(((ServerInfoAwareProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(spi.getProviderClass(), name)).getOperationalInfo()); + ProviderFactory pi = session.getKeycloakSessionFactory().getProviderFactory(spi.getProviderClass(), name); + if (ServerInfoAwareProviderFactory.class.isAssignableFrom(pi.getClass())) { + provider.setOperationalInfo(((ServerInfoAwareProviderFactory) pi).getOperationalInfo()); } providers.put(name, provider); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java b/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java index 3f94a5a9f33..1277f8c949a 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java @@ -8,7 +8,6 @@ import java.util.Map; public class SpiInfoRepresentation { private boolean internal; - private boolean systemInfo; private Map providers; @@ -20,14 +19,6 @@ public class SpiInfoRepresentation { this.internal = internal; } - public boolean isSystemInfo() { - return systemInfo; - } - - public void setSystemInfo(boolean systemInfo) { - this.systemInfo = systemInfo; - } - public Map getProviders() { return providers; }