keycloak-aplcache

Merge pull request #1805 from velias/KEYCLOAK-2033 KEYCLOAK-2033

11/12/2015 6:21:38 AM

Details

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 e011e11..d5bfdcb 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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-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 288e403..2fc645d 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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-public interface JpaConnectionProviderFactory extends ServerInfoAwareProviderFactory<JpaConnectionProvider> {
+public interface JpaConnectionProviderFactory extends ProviderFactory<JpaConnectionProvider> {
 
 }
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 00f3386..ae9701b 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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-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 bce5fe4..e787ce6 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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-public interface MongoConnectionProviderFactory extends ServerInfoAwareProviderFactory<MongoConnectionProvider> {
+public interface MongoConnectionProviderFactory extends ProviderFactory<MongoConnectionProvider> {
 }
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 eda5aca..71c2919 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 @@
         </para>
         <para>
             For example to implement the Event Listener SPI you start by implementing EventListenerProviderFactory:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
 package org.acme.provider;
 
 import ...
@@ -43,7 +43,7 @@ public class MyEventListenerProviderFactory implements EventListenerProviderFact
     }
 
 }
-}]]></programlisting>
+]]></programlisting>
             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
         </para>
         <para>
             Next you would implement EventListenerProvider:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
 package org.acme.provider;
 
 import ...
@@ -75,13 +75,61 @@ public class MyEventListenerProvider implements EventListenerProvider {
     }
 
 }
-}]]></programlisting>
+]]></programlisting>
         </para>
         <para>
             The file <literal>META-INF/services/org.keycloak.events.EventListenerProviderFactory</literal> should
             contain the full name of your ProviderFactory implementation:
 <programlisting><![CDATA[org.acme.provider.MyEventListenerProviderFactory]]></programlisting>
         </para>
+        
+        <section>
+            <title>Show info from you SPI implementation in Keycloak admin console</title>
+            <para>
+                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.
+             </para>
+             <para>   
+                To show info from your provider it is enough to implement 
+                <literal>org.keycloak.provider.ServerInfoAwareProviderFactory</literal> interface in your ProviderFactory. 
+                Example implementation for MyEventListenerProviderFactory from previous example:
+                <programlisting><![CDATA[
+package org.acme.provider;
+
+import ...
+
+public class MyEventListenerProviderFactory implements EventListenerProviderFactory, ServerInfoAwareProviderFactory {
+
+    private List<Event> events;
+    private int max;
+     
+...
+
+    @Override
+    public void init(Config.Scope config) {
+        max = config.getInt("max");
+        events = new MaxList(max);
+    }
+
+...
+
+    @Override
+    public Map<String, String> getOperationalInfo() {
+        Map<String, String> ret = new LinkedHashMap<>();
+        ret.put("version", "1.0");
+        ret.put("listSizeMax", max + "");
+        ret.put("listSizeCurrent", events.size() + "");
+        return ret;
+    }
+
+}
+]]></programlisting>
+            
+            </para>
+        </section>    
     </section>
 
     <section>
@@ -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 <literal>module.xml</literal>.
                 For example to add the event listener sysout example provider using the jboss-cli script execute:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
     KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.event-sysout --resources=target/event-listener-sysout-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-model-api,org.keycloak.keycloak-events-api"
-}]]></programlisting>
+]]></programlisting>
                 Or to manually create it start by creating the folder <literal>KEYCLOAK_HOME/modules/org/keycloak/examples/event-sysout/main</literal>.
                 Then copy <literal>event-listener-sysout-example.jar</literal> to this folder and create <literal>module.xml</literal>
                 with the following content:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
 <?xml version="1.0" encoding="UTF-8"?>
 <module xmlns="urn:jboss:module:1.1" name="org.keycloak.examples.event-sysout">
     <resources>
@@ -116,7 +164,7 @@ public class MyEventListenerProvider implements EventListenerProvider {
         <module name="org.keycloak.keycloak-events-api"/>
     </dependencies>
 </module>
-}]]></programlisting>
+]]></programlisting>
             </para>
             <para>
                 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 97d17b1..7674047 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<T extends Provider> extends ProviderFactory<T> {
+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 4ef2a63..660b1c4 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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
@@ -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<String> 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 3f94a5a..1277f8c 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<String, ProviderRepresentation> 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<String, ProviderRepresentation> getProviders() {
         return providers;
     }