diff --git a/.travis.yml b/.travis.yml
index b2b362762e..3da0679c50 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,10 +1,18 @@
language: java
+env:
+ global:
+ - MAVEN_SKIP_RC=true
+ - MAVEN_OPTS="-Xms512m -Xmx2048m"
+
jdk:
- oraclejdk8
+before_script:
+ - export MAVEN_SKIP_RC=true
+
install:
- - travis_wait mvn install -Pdistribution -DskipTests=true -B -V -q
+ - mvn install -Pdistribution -DskipTests=true -B -V -q
script:
- mvn test -B
diff --git a/distribution/feature-packs/server-feature-pack/feature-pack-build.xml b/distribution/feature-packs/server-feature-pack/feature-pack-build.xml
index f9208857aa..6ef7e7bb6b 100644
--- a/distribution/feature-packs/server-feature-pack/feature-pack-build.xml
+++ b/distribution/feature-packs/server-feature-pack/feature-pack-build.xml
@@ -1,4 +1,26 @@
-
+
+
+
@@ -8,20 +30,31 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -33,4 +66,4 @@
-
\ No newline at end of file
+
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/domain/subsystems.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/domain/subsystems.xml
index 29c6e63889..bea2e10873 100644
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/domain/subsystems.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/domain/subsystems.xml
@@ -53,63 +53,4 @@
undertow.xml
keycloak-server.xml
-
-
- logging.xml
- bean-validation.xml
- keycloak-datasources.xml
- ee.xml
- ejb3.xml
- io.xml
- keycloak-infinispan.xml
- iiop-openjdk.xml
- jaxrs.xml
- jca.xml
- jdr.xml
- jmx.xml
- jpa.xml
- jsf.xml
- jsr77.xml
- mail.xml
- messaging.xml
- naming.xml
- remoting.xml
- request-controller.xml
- security.xml
- security-manager.xml
- transactions.xml
- undertow.xml
- keycloak-server.xml
-
-
-
- logging.xml
- bean-validation.xml
- keycloak-datasources.xml
- ee.xml
- ejb3.xml
- io.xml
- keycloak-infinispan.xml
- iiop-openjdk.xml
- jaxrs.xml
- jca.xml
- jdr.xml
- jgroups.xml
- jmx.xml
- jpa.xml
- jsf.xml
- jsr77.xml
- mail.xml
- messaging.xml
- mod_cluster.xml
- naming.xml
- remoting.xml
- resource-adapters.xml
- request-controller.xml
- security.xml
- security-manager.xml
- transactions.xml
- undertow.xml
- keycloak-server.xml
-
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/domain/template.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/domain/template.xml
index 8c4464c591..770d2619bd 100644
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/domain/template.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/domain/template.xml
@@ -24,18 +24,12 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/host-master.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/host-master.xml
new file mode 100644
index 0000000000..5d959bd093
--- /dev/null
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/host-master.xml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/host-slave.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/host-slave.xml
new file mode 100644
index 0000000000..4b79b0aedc
--- /dev/null
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/host-slave.xml
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/host.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/host.xml
new file mode 100644
index 0000000000..501fae8931
--- /dev/null
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/host.xml
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/subsystems.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/subsystems.xml
new file mode 100644
index 0000000000..3df2a95f79
--- /dev/null
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/host/subsystems.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+ jmx.xml
+
+
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/standalone/subsystems-ha.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/standalone/subsystems-ha.xml
index 151ab710de..bf84e794ee 100644
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/standalone/subsystems-ha.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/standalone/subsystems-ha.xml
@@ -1,30 +1,30 @@
-
- logging.xml
- bean-validation.xml
- keycloak-datasources.xml
- ee.xml
- ejb3.xml
- io.xml
- keycloak-infinispan.xml
- jaxrs.xml
- jca.xml
- jdr.xml
- jgroups.xml
- jmx.xml
- jpa.xml
- jsf.xml
- mail.xml
- mod_cluster.xml
- naming.xml
- remoting.xml
- request-controller.xml
- security-manager.xml
- security.xml
- transactions.xml
- undertow.xml
- keycloak-server.xml
-
+
+ logging.xml
+ bean-validation.xml
+ keycloak-datasources.xml
+ ee.xml
+ ejb3.xml
+ io.xml
+ keycloak-infinispan.xml
+ jaxrs.xml
+ jca.xml
+ jdr.xml
+ jgroups.xml
+ jmx.xml
+ jpa.xml
+ jsf.xml
+ mail.xml
+ mod_cluster.xml
+ naming.xml
+ remoting.xml
+ request-controller.xml
+ security-manager.xml
+ security.xml
+ transactions.xml
+ undertow.xml
+ keycloak-server.xml
+
\ No newline at end of file
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/standalone/template.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/standalone/template.xml
index 76fbe9e4a4..4df055c0ab 100644
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/standalone/template.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/configuration/standalone/template.xml
@@ -29,15 +29,15 @@
-
-
+
+
-
+
-
-
-
+
+
+
@@ -69,8 +69,9 @@
-
+
+
@@ -80,4 +81,4 @@
-
\ No newline at end of file
+
diff --git a/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java b/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java
index 0c1df9cc1f..f2acf49115 100755
--- a/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java
+++ b/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java
@@ -23,14 +23,12 @@ public interface UserSessionProvider extends Provider {
List getUserSessionByBrokerUserId(RealmModel realm, String brokerUserId);
UserSessionModel getUserSessionByBrokerSessionId(RealmModel realm, String brokerSessionId);
- List getUserSessionsByNote(RealmModel realm, String noteName, String noteValue);
-
- int getActiveUserSessions(RealmModel realm, ClientModel client);
+ long getActiveUserSessions(RealmModel realm, ClientModel client);
void removeUserSession(RealmModel realm, UserSessionModel session);
void removeUserSessions(RealmModel realm, UserModel user);
// Implementation should propagate removal of expired userSessions to userSessionPersister too
- void removeExpiredUserSessions(RealmModel realm);
+ void removeExpired(RealmModel realm);
void removeUserSessions(RealmModel realm);
void removeClientSession(RealmModel realm, ClientSessionModel clientSession);
@@ -56,7 +54,7 @@ public interface UserSessionProvider extends Provider {
// Don't remove userSession even if it's last userSession
void removeOfflineClientSession(RealmModel realm, String clientSessionId);
- int getOfflineSessionsCount(RealmModel realm, ClientModel client);
+ long getOfflineSessionsCount(RealmModel realm, ClientModel client);
List getOfflineUserSessions(RealmModel realm, ClientModel client, int first, int max);
// Triggered by persister during pre-load
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/CompatInfinispanUserSessionProvider.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/CompatInfinispanUserSessionProvider.java
new file mode 100644
index 0000000000..bcd72e79ef
--- /dev/null
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/CompatInfinispanUserSessionProvider.java
@@ -0,0 +1,387 @@
+package org.keycloak.models.sessions.infinispan;
+
+import org.infinispan.Cache;
+import org.infinispan.distexec.mapreduce.MapReduceTask;
+import org.jboss.logging.Logger;
+import org.keycloak.common.util.Time;
+import org.keycloak.models.*;
+import org.keycloak.models.session.UserSessionPersisterProvider;
+import org.keycloak.models.sessions.infinispan.entities.*;
+import org.keycloak.models.sessions.infinispan.mapreduce.*;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.RealmInfoUtil;
+
+import java.util.*;
+
+/**
+ * @author Stian Thorgersen
+ */
+public class CompatInfinispanUserSessionProvider extends InfinispanUserSessionProvider {
+
+ private static final Logger log = Logger.getLogger(CompatInfinispanUserSessionProvider.class);
+
+ public CompatInfinispanUserSessionProvider(KeycloakSession session, Cache sessionCache, Cache offlineSessionCache,
+ Cache loginFailureCache) {
+ super(session, sessionCache, offlineSessionCache, loginFailureCache);
+ }
+
+ @Override
+ public List getUserSessions(RealmModel realm, UserModel user) {
+ Map sessions = new MapReduceTask(sessionCache)
+ .mappedWith(UserSessionMapper.create(realm.getId()).user(user.getId()))
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ return wrapUserSessions(realm, sessions.values(), false);
+ }
+
+ @Override
+ public List getUserSessionByBrokerUserId(RealmModel realm, String brokerUserId) {
+ Map sessions = new MapReduceTask(sessionCache)
+ .mappedWith(UserSessionMapper.create(realm.getId()).brokerUserId(brokerUserId))
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ return wrapUserSessions(realm, sessions.values(), false);
+ }
+
+ @Override
+ public UserSessionModel getUserSessionByBrokerSessionId(RealmModel realm, String brokerSessionId) {
+ Map sessions = new MapReduceTask(sessionCache)
+ .mappedWith(UserSessionMapper.create(realm.getId()).brokerSessionId(brokerSessionId))
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ List userSessionModels = wrapUserSessions(realm, sessions.values(), false);
+ if (userSessionModels.isEmpty()) return null;
+ return userSessionModels.get(0);
+ }
+
+ @Override
+ public List getUserSessions(RealmModel realm, ClientModel client) {
+ return getUserSessions(realm, client, -1, -1);
+ }
+
+ @Override
+ public List getUserSessions(RealmModel realm, ClientModel client, int firstResult, int maxResults) {
+ return getUserSessions(realm, client, firstResult, maxResults, false);
+ }
+
+ protected List getUserSessions(RealmModel realm, ClientModel client, int firstResult, int maxResults, boolean offline) {
+ Cache cache = getCache(offline);
+
+ Map map = new MapReduceTask(cache)
+ .mappedWith(ClientSessionMapper.create(realm.getId()).client(client.getId()).emitUserSessionAndTimestamp())
+ .reducedWith(new LargestResultReducer())
+ .execute();
+
+ List> sessionTimestamps = new LinkedList>(map.entrySet());
+
+ Collections.sort(sessionTimestamps, new Comparator>() {
+ @Override
+ public int compare(Map.Entry e1, Map.Entry e2) {
+ return e1.getValue().compareTo(e2.getValue());
+ }
+ });
+
+ if (firstResult != -1 || maxResults == -1) {
+ if (firstResult == -1) {
+ firstResult = 0;
+ }
+
+ if (maxResults == -1) {
+ maxResults = Integer.MAX_VALUE;
+ }
+
+ if (firstResult > sessionTimestamps.size()) {
+ return Collections.emptyList();
+ }
+
+ int toIndex = (firstResult + maxResults) < sessionTimestamps.size() ? firstResult + maxResults : sessionTimestamps.size();
+ sessionTimestamps = sessionTimestamps.subList(firstResult, toIndex);
+ }
+
+ List userSessions = new LinkedList();
+ for (Map.Entry e : sessionTimestamps) {
+ UserSessionEntity userSessionEntity = (UserSessionEntity) cache.get(e.getKey());
+ if (userSessionEntity != null) {
+ userSessions.add(wrap(realm, userSessionEntity, offline));
+ }
+ }
+
+ return userSessions;
+ }
+
+ @Override
+ public long getActiveUserSessions(RealmModel realm, ClientModel client) {
+ return getUserSessionsCount(realm, client, false);
+ }
+
+ protected long getUserSessionsCount(RealmModel realm, ClientModel client, boolean offline) {
+ Cache cache = getCache(offline);
+
+ Map map = new MapReduceTask(cache)
+ .mappedWith(ClientSessionMapper.create(realm.getId()).client(client.getId()).emitUserSessionAndTimestamp())
+ .reducedWith(new LargestResultReducer()).execute();
+
+ return map.size();
+ }
+
+ @Override
+ public void removeUserSession(RealmModel realm, UserSessionModel session) {
+ removeUserSession(realm, session.getId());
+ }
+
+ @Override
+ public void removeUserSessions(RealmModel realm, UserModel user) {
+ removeUserSessions(realm, user, false);
+ }
+
+ protected void removeUserSessions(RealmModel realm, UserModel user, boolean offline) {
+ Cache cache = getCache(offline);
+
+ Map sessions = new MapReduceTask(cache)
+ .mappedWith(UserSessionMapper.create(realm.getId()).user(user.getId()).emitKey())
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ for (String id : sessions.keySet()) {
+ removeUserSession(realm, id, offline);
+ }
+ }
+
+ @Override
+ public void removeExpired(RealmModel realm) {
+ UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
+
+ int expired = Time.currentTime() - realm.getSsoSessionMaxLifespan();
+ int expiredRefresh = Time.currentTime() - realm.getSsoSessionIdleTimeout();
+ int expiredOffline = Time.currentTime() - realm.getOfflineSessionIdleTimeout();
+ int expiredDettachedClientSession = Time.currentTime() - RealmInfoUtil.getDettachedClientSessionLifespan(realm);
+
+ Map map = new MapReduceTask(sessionCache)
+ .mappedWith(UserSessionMapper.create(realm.getId()).expired(expired, expiredRefresh).emitKey())
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ for (String id : map.keySet()) {
+ removeUserSession(realm, id);
+ }
+
+ map = new MapReduceTask(sessionCache)
+ .mappedWith(ClientSessionMapper.create(realm.getId()).expiredRefresh(expiredDettachedClientSession).requireNullUserSession(true).emitKey())
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ for (String id : map.keySet()) {
+ tx.remove(sessionCache, id);
+ }
+
+ // Remove expired offline user sessions
+ Map map2 = new MapReduceTask(offlineSessionCache)
+ .mappedWith(UserSessionMapper.create(realm.getId()).expired(null, expiredOffline))
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ for (Map.Entry entry : map2.entrySet()) {
+ String userSessionId = entry.getKey();
+ tx.remove(offlineSessionCache, userSessionId);
+ // Propagate to persister
+ persister.removeUserSession(userSessionId, true);
+
+ UserSessionEntity entity = (UserSessionEntity) entry.getValue();
+ for (String clientSessionId : entity.getClientSessions()) {
+ tx.remove(offlineSessionCache, clientSessionId);
+ }
+ }
+
+ // Remove expired offline client sessions
+ map = new MapReduceTask(offlineSessionCache)
+ .mappedWith(ClientSessionMapper.create(realm.getId()).expiredRefresh(expiredOffline).emitKey())
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ for (String clientSessionId : map.keySet()) {
+ tx.remove(offlineSessionCache, clientSessionId);
+ persister.removeClientSession(clientSessionId, true);
+ }
+
+ // Remove expired client initial access
+ map = new MapReduceTask(sessionCache)
+ .mappedWith(ClientInitialAccessMapper.create(realm.getId()).expired(Time.currentTime()).emitKey())
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ for (String id : map.keySet()) {
+ tx.remove(sessionCache, id);
+ }
+ }
+
+ @Override
+ public void removeUserSessions(RealmModel realm) {
+ removeUserSessions(realm, false);
+ }
+
+ protected void removeUserSessions(RealmModel realm, boolean offline) {
+ Cache cache = getCache(offline);
+
+ Map ids = new MapReduceTask(cache)
+ .mappedWith(SessionMapper.create(realm.getId()).emitKey())
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ for (String id : ids.keySet()) {
+ cache.remove(id);
+ }
+ }
+
+ @Override
+ public void removeUserLoginFailure(RealmModel realm, String username) {
+ LoginFailureKey key = new LoginFailureKey(realm.getId(), username);
+ tx.remove(loginFailureCache, key);
+ }
+
+ @Override
+ public void removeAllUserLoginFailures(RealmModel realm) {
+ Map sessions = new MapReduceTask(loginFailureCache)
+ .mappedWith(UserLoginFailureMapper.create(realm.getId()).emitKey())
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ for (LoginFailureKey id : sessions.keySet()) {
+ tx.remove(loginFailureCache, id);
+ }
+ }
+
+ @Override
+ public void onRealmRemoved(RealmModel realm) {
+ removeUserSessions(realm, true);
+ removeUserSessions(realm, false);
+ removeAllUserLoginFailures(realm);
+ }
+
+ @Override
+ public void onClientRemoved(RealmModel realm, ClientModel client) {
+ onClientRemoved(realm, client, true);
+ onClientRemoved(realm, client, false);
+ }
+
+ private void onClientRemoved(RealmModel realm, ClientModel client, boolean offline) {
+ Cache cache = getCache(offline);
+
+ Map map = new MapReduceTask(cache)
+ .mappedWith(ClientSessionMapper.create(realm.getId()).client(client.getId()))
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ for (Map.Entry entry : map.entrySet()) {
+
+ // detach from userSession
+ ClientSessionAdapter adapter = wrap(realm, entry.getValue(), offline);
+ adapter.setUserSession(null);
+
+ tx.remove(cache, entry.getKey());
+ }
+ }
+
+ @Override
+ public void onUserRemoved(RealmModel realm, UserModel user) {
+ removeUserSessions(realm, user, true);
+ removeUserSessions(realm, user, false);
+
+ loginFailureCache.remove(new LoginFailureKey(realm.getId(), user.getUsername()));
+ loginFailureCache.remove(new LoginFailureKey(realm.getId(), user.getEmail()));
+ }
+
+ @Override
+ public void removeClientSession(RealmModel realm, ClientSessionModel clientSession) {
+ removeClientSession(realm, clientSession, false);
+ }
+
+ protected void removeClientSession(RealmModel realm, ClientSessionModel clientSession, boolean offline) {
+ Cache cache = getCache(offline);
+
+ UserSessionModel userSession = clientSession.getUserSession();
+ if (userSession != null) {
+ UserSessionEntity entity = ((UserSessionAdapter) userSession).getEntity();
+ if (entity.getClientSessions() != null) {
+ entity.getClientSessions().remove(clientSession.getId());
+
+ }
+ tx.replace(cache, entity.getId(), entity);
+ }
+ tx.remove(cache, clientSession.getId());
+ }
+
+ protected void removeUserSession(RealmModel realm, String userSessionId) {
+ removeUserSession(realm, userSessionId, false);
+ }
+
+ protected void removeUserSession(RealmModel realm, String userSessionId, boolean offline) {
+ Cache cache = getCache(offline);
+
+ tx.remove(cache, userSessionId);
+
+ // TODO: Isn't more effective to retrieve from userSessionEntity directly?
+ Map map = new MapReduceTask(cache)
+ .mappedWith(ClientSessionMapper.create(realm.getId()).userSession(userSessionId).emitKey())
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ for (String id : map.keySet()) {
+ tx.remove(cache, id);
+ }
+ }
+
+ @Override
+ public void removeOfflineUserSession(RealmModel realm, String userSessionId) {
+ removeUserSession(realm, userSessionId, true);
+ }
+
+ @Override
+ public List getOfflineClientSessions(RealmModel realm, UserModel user) {
+ Map sessions = new MapReduceTask(offlineSessionCache)
+ .mappedWith(UserSessionMapper.create(realm.getId()).user(user.getId()))
+ .reducedWith(new FirstResultReducer())
+ .execute();
+
+ List clientSessions = new LinkedList<>();
+ for (UserSessionEntity userSession : sessions.values()) {
+ Set currClientSessions = userSession.getClientSessions();
+ for (String clientSessionId : currClientSessions) {
+ ClientSessionEntity cls = (ClientSessionEntity) offlineSessionCache.get(clientSessionId);
+ if (cls != null) {
+ clientSessions.add(cls);
+ }
+ }
+ }
+
+ return wrapClientSessions(realm, clientSessions, true);
+ }
+
+ @Override
+ public void removeOfflineClientSession(RealmModel realm, String clientSessionId) {
+ ClientSessionModel clientSession = getOfflineClientSession(realm, clientSessionId);
+ removeClientSession(realm, clientSession, true);
+ }
+
+ @Override
+ public long getOfflineSessionsCount(RealmModel realm, ClientModel client) {
+ return getUserSessionsCount(realm, client, true);
+ }
+
+ @Override
+ public List getOfflineUserSessions(RealmModel realm, ClientModel client, int first, int max) {
+ return getUserSessions(realm, client, first, max, true);
+ }
+
+ @Override
+ public List listClientInitialAccess(RealmModel realm) {
+ Map entities = new MapReduceTask(sessionCache)
+ .mappedWith(ClientInitialAccessMapper.create(realm.getId()))
+ .reducedWith(new FirstResultReducer())
+ .execute();
+ return wrapClientInitialAccess(realm, entities.values());
+ }
+
+}
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/Consumers.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/Consumers.java
new file mode 100644
index 0000000000..0eed3308c4
--- /dev/null
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/Consumers.java
@@ -0,0 +1,66 @@
+package org.keycloak.models.sessions.infinispan;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.sessions.infinispan.entities.ClientSessionEntity;
+import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
+import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+
+/**
+ * @author Stian Thorgersen
+ */
+public class Consumers {
+
+ private Consumers() {
+ }
+
+ public static UserSessionModelsConsumer userSessionModels(InfinispanUserSessionProvider provider, RealmModel realm, boolean offline) {
+ return new UserSessionModelsConsumer(provider, realm, offline);
+ }
+
+ public static class UserSessionIdAndTimestampConsumer implements Consumer> {
+
+ private Map sessions = new HashMap<>();
+
+ @Override
+ public void accept(Map.Entry entry) {
+ SessionEntity e = entry.getValue();
+ if (e instanceof ClientSessionEntity) {
+ ClientSessionEntity ce = (ClientSessionEntity) e;
+ sessions.put(ce.getUserSession(), ce.getTimestamp());
+ }
+ }
+
+ }
+
+ public static class UserSessionModelsConsumer implements Consumer> {
+
+ private InfinispanUserSessionProvider provider;
+ private RealmModel realm;
+ private boolean offline;
+ private List sessions = new LinkedList<>();
+
+ private UserSessionModelsConsumer(InfinispanUserSessionProvider provider, RealmModel realm, boolean offline) {
+ this.provider = provider;
+ this.realm = realm;
+ this.offline = offline;
+ }
+
+ @Override
+ public void accept(Map.Entry entry) {
+ SessionEntity e = entry.getValue();
+ sessions.add(provider.wrap(realm, (UserSessionEntity) e, offline));
+ }
+
+ public List getSessions() {
+ return sessions;
+ }
+
+ }
+}
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
index d89f47b023..7e66b12b2a 100755
--- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
@@ -1,25 +1,21 @@
package org.keycloak.models.sessions.infinispan;
import org.infinispan.Cache;
-import org.infinispan.distexec.mapreduce.MapReduceTask;
+import org.infinispan.CacheStream;
import org.jboss.logging.Logger;
+import org.keycloak.common.util.Time;
import org.keycloak.models.*;
import org.keycloak.models.session.UserSessionPersisterProvider;
import org.keycloak.models.sessions.infinispan.entities.*;
-import org.keycloak.models.sessions.infinispan.mapreduce.*;
+import org.keycloak.models.sessions.infinispan.stream.*;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.RealmInfoUtil;
-import org.keycloak.common.util.Time;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* @author Stian Thorgersen
@@ -28,11 +24,11 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
private static final Logger log = Logger.getLogger(InfinispanUserSessionProvider.class);
- private final KeycloakSession session;
- private final Cache sessionCache;
- private final Cache offlineSessionCache;
- private final Cache loginFailureCache;
- private final InfinispanKeycloakTransaction tx;
+ protected final KeycloakSession session;
+ protected final Cache sessionCache;
+ protected final Cache offlineSessionCache;
+ protected final Cache loginFailureCache;
+ protected final InfinispanKeycloakTransaction tx;
public InfinispanUserSessionProvider(KeycloakSession session, Cache sessionCache, Cache offlineSessionCache,
Cache loginFailureCache) {
@@ -139,36 +135,31 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
return wrap(realm, entity, offline);
}
- @Override
- public List getUserSessions(RealmModel realm, UserModel user) {
- Map sessions = new MapReduceTask(sessionCache)
- .mappedWith(UserSessionMapper.create(realm.getId()).user(user.getId()))
- .reducedWith(new FirstResultReducer())
- .execute();
+ protected List getUserSessions(RealmModel realm, Predicate> predicate, boolean offline) {
+ CacheStream> cacheStream = getCache(offline).entrySet().stream();
+ Iterator> itr = cacheStream.filter(predicate).iterator();
+ List sessions = new LinkedList<>();
+ while (itr.hasNext()) {
+ UserSessionEntity e = (UserSessionEntity) itr.next().getValue();
+ sessions.add(wrap(realm, e, offline));
+ }
+ return sessions;
+ }
- return wrapUserSessions(realm, sessions.values(), false);
+ @Override
+ public List getUserSessions(final RealmModel realm, UserModel user) {
+ return getUserSessions(realm, UserSessionPredicate.create(realm.getId()).user(user.getId()), false);
}
@Override
public List getUserSessionByBrokerUserId(RealmModel realm, String brokerUserId) {
- Map sessions = new MapReduceTask(sessionCache)
- .mappedWith(UserSessionMapper.create(realm.getId()).brokerUserId(brokerUserId))
- .reducedWith(new FirstResultReducer())
- .execute();
-
- return wrapUserSessions(realm, sessions.values(), false);
+ return getUserSessions(realm, UserSessionPredicate.create(realm.getId()).brokerUserId(brokerUserId), false);
}
@Override
public UserSessionModel getUserSessionByBrokerSessionId(RealmModel realm, String brokerSessionId) {
- Map sessions = new MapReduceTask(sessionCache)
- .mappedWith(UserSessionMapper.create(realm.getId()).brokerSessionId(brokerSessionId))
- .reducedWith(new FirstResultReducer())
- .execute();
-
- List userSessionModels = wrapUserSessions(realm, sessions.values(), false);
- if (userSessionModels.isEmpty()) return null;
- return userSessionModels.get(0);
+ List userSessions = getUserSessions(realm, UserSessionPredicate.create(realm.getId()).brokerSessionId(brokerSessionId), false);
+ return userSessions.isEmpty() ? null : userSessions.get(0);
}
@Override
@@ -181,86 +172,58 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
return getUserSessions(realm, client, firstResult, maxResults, false);
}
- protected List getUserSessions(RealmModel realm, ClientModel client, int firstResult, int maxResults, boolean offline) {
- Cache cache = getCache(offline);
+ protected List getUserSessions(final RealmModel realm, ClientModel client, int firstResult, int maxResults, final boolean offline) {
+ final Cache cache = getCache(offline);
- Map map = new MapReduceTask(cache)
- .mappedWith(ClientSessionMapper.create(realm.getId()).client(client.getId()).emitUserSessionAndTimestamp())
- .reducedWith(new LargestResultReducer())
- .execute();
+ Iterator itr = cache.entrySet().stream()
+ .filter(ClientSessionPredicate.create(realm.getId()).client(client.getId()).requireUserSession())
+ .map(Mappers.clientSessionToUserSessionTimestamp())
+ .iterator();
- List> sessionTimestamps = new LinkedList>(map.entrySet());
+ Map m = new HashMap<>();
+ while(itr.hasNext()) {
+ UserSessionTimestamp next = itr.next();
+ if (!m.containsKey(next.getUserSessionId()) || m.get(next.getUserSessionId()).getClientSessionTimestamp() < next.getClientSessionTimestamp()) {
+ m.put(next.getUserSessionId(), next);
+ }
+ }
- Collections.sort(sessionTimestamps, new Comparator>() {
+ Stream stream = new LinkedList<>(m.values()).stream().sorted(Comparators.userSessionTimestamp());
+
+ if (firstResult > 0) {
+ stream = stream.skip(firstResult);
+ }
+
+ if (maxResults > 0) {
+ stream = stream.limit(maxResults);
+ }
+
+ final List sessions = new LinkedList<>();
+ stream.forEach(new Consumer() {
@Override
- public int compare(Map.Entry e1, Map.Entry e2) {
- return e1.getValue().compareTo(e2.getValue());
+ public void accept(UserSessionTimestamp userSessionTimestamp) {
+ SessionEntity entity = cache.get(userSessionTimestamp.getUserSessionId());
+ if (entity != null) {
+ sessions.add(wrap(realm, (UserSessionEntity) entity, offline));
+ }
}
});
- if (firstResult != -1 || maxResults == -1) {
- if (firstResult == -1) {
- firstResult = 0;
- }
-
- if (maxResults == -1) {
- maxResults = Integer.MAX_VALUE;
- }
-
- if (firstResult > sessionTimestamps.size()) {
- return Collections.emptyList();
- }
-
- int toIndex = (firstResult + maxResults) < sessionTimestamps.size() ? firstResult + maxResults : sessionTimestamps.size();
- sessionTimestamps = sessionTimestamps.subList(firstResult, toIndex);
- }
-
- List userSessions = new LinkedList();
- for (Map.Entry e : sessionTimestamps) {
- UserSessionEntity userSessionEntity = (UserSessionEntity) cache.get(e.getKey());
- if (userSessionEntity != null) {
- userSessions.add(wrap(realm, userSessionEntity, offline));
- }
- }
-
- return userSessions;
+ return sessions;
}
@Override
- public List getUserSessionsByNote(RealmModel realm, String noteName, String noteValue) {
- HashMap notes = new HashMap<>();
- notes.put(noteName, noteValue);
- return getUserSessionsByNotes(realm, notes);
- }
-
- public List getUserSessionsByNotes(RealmModel realm, Map notes) {
- Map sessions = new MapReduceTask(sessionCache)
- .mappedWith(UserSessionNoteMapper.create(realm.getId()).notes(notes))
- .reducedWith(new FirstResultReducer())
- .execute();
-
- return wrapUserSessions(realm, sessions.values(), false);
-
- }
-
- @Override
- public int getActiveUserSessions(RealmModel realm, ClientModel client) {
+ public long getActiveUserSessions(RealmModel realm, ClientModel client) {
return getUserSessionsCount(realm, client, false);
}
- protected int getUserSessionsCount(RealmModel realm, ClientModel client, boolean offline) {
- Cache cache = getCache(offline);
-
- Map map = new MapReduceTask(cache)
- .mappedWith(ClientSessionMapper.create(realm.getId()).client(client.getId()).emitUserSessionAndTimestamp())
- .reducedWith(new LargestResultReducer()).execute();
-
- return map.size();
+ protected long getUserSessionsCount(RealmModel realm, ClientModel client, boolean offline) {
+ return getCache(offline).entrySet().stream().filter(ClientSessionPredicate.create(realm.getId()).client(client.getId()).requireUserSession()).map(Mappers.clientSessionToUserSessionId()).distinct().count();
}
@Override
public void removeUserSession(RealmModel realm, UserSessionModel session) {
- removeUserSession(realm, session.getId());
+ removeUserSession(realm, session.getId(), false);
}
@Override
@@ -271,80 +234,81 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
protected void removeUserSessions(RealmModel realm, UserModel user, boolean offline) {
Cache cache = getCache(offline);
- Map sessions = new MapReduceTask(cache)
- .mappedWith(UserSessionMapper.create(realm.getId()).user(user.getId()).emitKey())
- .reducedWith(new FirstResultReducer())
- .execute();
-
- for (String id : sessions.keySet()) {
- removeUserSession(realm, id, offline);
+ Iterator itr = cache.entrySet().stream().filter(UserSessionPredicate.create(realm.getId()).user(user.getId())).map(Mappers.sessionId()).iterator();
+ while (itr.hasNext()) {
+ removeUserSession(realm, itr.next(), offline);
}
}
@Override
- public void removeExpiredUserSessions(RealmModel realm) {
- UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
+ public void removeExpired(RealmModel realm) {
+ removeExpiredUserSessions(realm);
+ removeExpiredClientSessions(realm);
+ removeExpiredOfflineUserSessions(realm);
+ removeExpiredOfflineClientSessions(realm);
+ removeExpiredClientInitialAccess(realm);
+ }
+ private void removeExpiredUserSessions(RealmModel realm) {
int expired = Time.currentTime() - realm.getSsoSessionMaxLifespan();
int expiredRefresh = Time.currentTime() - realm.getSsoSessionIdleTimeout();
- int expiredOffline = Time.currentTime() - realm.getOfflineSessionIdleTimeout();
+
+ Iterator> itr = sessionCache.entrySet().stream().filter(UserSessionPredicate.create(realm.getId()).expired(expired, expiredRefresh)).iterator();
+
+ while (itr.hasNext()) {
+ UserSessionEntity entity = (UserSessionEntity) itr.next().getValue();
+ tx.remove(sessionCache, entity.getId());
+
+ if (entity.getClientSessions() != null) {
+ for (String clientSessionId : entity.getClientSessions()) {
+ tx.remove(sessionCache, clientSessionId);
+ }
+ }
+ }
+ }
+
+ private void removeExpiredClientSessions(RealmModel realm) {
int expiredDettachedClientSession = Time.currentTime() - RealmInfoUtil.getDettachedClientSessionLifespan(realm);
- Map map = new MapReduceTask(sessionCache)
- .mappedWith(UserSessionMapper.create(realm.getId()).expired(expired, expiredRefresh).emitKey())
- .reducedWith(new FirstResultReducer())
- .execute();
-
- for (String id : map.keySet()) {
- removeUserSession(realm, id);
+ Iterator> itr = sessionCache.entrySet().stream().filter(ClientSessionPredicate.create(realm.getId()).expiredRefresh(expiredDettachedClientSession).requireNullUserSession()).iterator();
+ while (itr.hasNext()) {
+ tx.remove(sessionCache, itr.next().getKey());
}
+ }
- map = new MapReduceTask(sessionCache)
- .mappedWith(ClientSessionMapper.create(realm.getId()).expiredRefresh(expiredDettachedClientSession).requireNullUserSession(true).emitKey())
- .reducedWith(new FirstResultReducer())
- .execute();
+ private void removeExpiredOfflineUserSessions(RealmModel realm) {
+ UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
+ int expiredOffline = Time.currentTime() - realm.getOfflineSessionIdleTimeout();
- for (String id : map.keySet()) {
- tx.remove(sessionCache, id);
- }
+ Iterator> itr = offlineSessionCache.entrySet().stream().filter(UserSessionPredicate.create(realm.getId()).expired(null, expiredOffline)).iterator();
+ while (itr.hasNext()) {
+ UserSessionEntity entity = (UserSessionEntity) itr.next().getValue();
+ tx.remove(offlineSessionCache, entity.getId());
- // Remove expired offline user sessions
- Map map2 = new MapReduceTask(offlineSessionCache)
- .mappedWith(UserSessionMapper.create(realm.getId()).expired(null, expiredOffline))
- .reducedWith(new FirstResultReducer())
- .execute();
+ persister.removeUserSession(entity.getId(), true);
- for (Map.Entry entry : map2.entrySet()) {
- String userSessionId = entry.getKey();
- tx.remove(offlineSessionCache, userSessionId);
- // Propagate to persister
- persister.removeUserSession(userSessionId, true);
-
- UserSessionEntity entity = (UserSessionEntity) entry.getValue();
for (String clientSessionId : entity.getClientSessions()) {
tx.remove(offlineSessionCache, clientSessionId);
}
}
+ }
- // Remove expired offline client sessions
- map = new MapReduceTask(offlineSessionCache)
- .mappedWith(ClientSessionMapper.create(realm.getId()).expiredRefresh(expiredOffline).emitKey())
- .reducedWith(new FirstResultReducer())
- .execute();
+ private void removeExpiredOfflineClientSessions(RealmModel realm) {
+ UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
+ int expiredOffline = Time.currentTime() - realm.getOfflineSessionIdleTimeout();
- for (String clientSessionId : map.keySet()) {
- tx.remove(offlineSessionCache, clientSessionId);
- persister.removeClientSession(clientSessionId, true);
+ Iterator itr = offlineSessionCache.entrySet().stream().filter(ClientSessionPredicate.create(realm.getId()).expiredRefresh(expiredOffline)).map(Mappers.sessionId()).iterator();
+ while (itr.hasNext()) {
+ String sessionId = itr.next();
+ tx.remove(offlineSessionCache, sessionId);
+ persister.removeClientSession(sessionId, true);
}
+ }
- // Remove expired client initial access
- map = new MapReduceTask(sessionCache)
- .mappedWith(ClientInitialAccessMapper.create(realm.getId()).expired(Time.currentTime()).emitKey())
- .reducedWith(new FirstResultReducer())
- .execute();
-
- for (String id : map.keySet()) {
- tx.remove(sessionCache, id);
+ private void removeExpiredClientInitialAccess(RealmModel realm) {
+ Iterator itr = sessionCache.entrySet().stream().filter(ClientInitialAccessPredicate.create(realm.getId()).expired(Time.currentTime())).map(Mappers.sessionId()).iterator();
+ while (itr.hasNext()) {
+ tx.remove(sessionCache, itr.next());
}
}
@@ -356,13 +320,9 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
protected void removeUserSessions(RealmModel realm, boolean offline) {
Cache cache = getCache(offline);
- Map ids = new MapReduceTask(cache)
- .mappedWith(SessionMapper.create(realm.getId()).emitKey())
- .reducedWith(new FirstResultReducer())
- .execute();
-
- for (String id : ids.keySet()) {
- cache.remove(id);
+ Iterator itr = cache.entrySet().stream().filter(SessionPredicate.create(realm.getId())).map(Mappers.sessionId()).iterator();
+ while (itr.hasNext()) {
+ cache.remove(itr.next());
}
}
@@ -384,24 +344,18 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
@Override
public void removeUserLoginFailure(RealmModel realm, String username) {
- LoginFailureKey key = new LoginFailureKey(realm.getId(), username);
- tx.remove(loginFailureCache, key);
+ tx.remove(loginFailureCache, new LoginFailureKey(realm.getId(), username));
}
@Override
public void removeAllUserLoginFailures(RealmModel realm) {
- Map sessions = new MapReduceTask(loginFailureCache)
- .mappedWith(UserLoginFailureMapper.create(realm.getId()).emitKey())
- .reducedWith(new FirstResultReducer())
- .execute();
-
- for (LoginFailureKey id : sessions.keySet()) {
- tx.remove(loginFailureCache, id);
+ Iterator itr = loginFailureCache.entrySet().stream().filter(UserLoginFailurePredicate.create(realm.getId())).map(Mappers.loginFailureId()).iterator();
+ while (itr.hasNext()) {
+ LoginFailureKey key = itr.next();
+ tx.remove(loginFailureCache, key);
}
}
-
-
@Override
public void onRealmRemoved(RealmModel realm) {
removeUserSessions(realm, true);
@@ -418,18 +372,13 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
private void onClientRemoved(RealmModel realm, ClientModel client, boolean offline) {
Cache cache = getCache(offline);
- Map map = new MapReduceTask(cache)
- .mappedWith(ClientSessionMapper.create(realm.getId()).client(client.getId()))
- .reducedWith(new FirstResultReducer())
- .execute();
-
- for (Map.Entry entry : map.entrySet()) {
-
- // detach from userSession
- ClientSessionAdapter adapter = wrap(realm, entry.getValue(), offline);
+ Iterator> itr = cache.entrySet().stream().filter(ClientSessionPredicate.create(realm.getId()).client(client.getId())).iterator();
+ while (itr.hasNext()) {
+ ClientSessionEntity entity = (ClientSessionEntity) itr.next().getValue();
+ ClientSessionAdapter adapter = wrap(realm, entity, offline);
adapter.setUserSession(null);
- tx.remove(cache, entry.getKey());
+ tx.remove(cache, entity.getId());
}
}
@@ -491,27 +440,19 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
}
}
- protected void removeUserSession(RealmModel realm, String userSessionId) {
- removeUserSession(realm, userSessionId, false);
- }
-
protected void removeUserSession(RealmModel realm, String userSessionId, boolean offline) {
Cache cache = getCache(offline);
tx.remove(cache, userSessionId);
- // TODO: Isn't more effective to retrieve from userSessionEntity directly?
- Map map = new MapReduceTask(cache)
- .mappedWith(ClientSessionMapper.create(realm.getId()).userSession(userSessionId).emitKey())
- .reducedWith(new FirstResultReducer())
- .execute();
-
- for (String id : map.keySet()) {
- tx.remove(cache, id);
+ UserSessionEntity sessionEntity = (UserSessionEntity) cache.get(userSessionId);
+ if (sessionEntity.getClientSessions() != null) {
+ for (String clientSessionId : sessionEntity.getClientSessions()) {
+ tx.remove(cache, clientSessionId);
+ }
}
}
-
InfinispanKeycloakTransaction getTx() {
return tx;
}
@@ -522,7 +463,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
}
List wrapUserSessions(RealmModel realm, Collection entities, boolean offline) {
- List models = new LinkedList();
+ List models = new LinkedList<>();
for (UserSessionEntity e : entities) {
models.add(wrap(realm, e, offline));
}
@@ -553,7 +494,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
}
List wrapClientSessions(RealmModel realm, Collection entities, boolean offline) {
- List models = new LinkedList();
+ List models = new LinkedList<>();
for (ClientSessionEntity e : entities) {
models.add(wrap(realm, e, offline));
}
@@ -600,23 +541,21 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
@Override
public List getOfflineClientSessions(RealmModel realm, UserModel user) {
- Map sessions = new MapReduceTask(offlineSessionCache)
- .mappedWith(UserSessionMapper.create(realm.getId()).user(user.getId()))
- .reducedWith(new FirstResultReducer())
- .execute();
+ Iterator> itr = offlineSessionCache.entrySet().stream().filter(UserSessionPredicate.create(realm.getId()).user(user.getId())).iterator();
+ List clientSessions = new LinkedList<>();
- List clientSessions = new LinkedList<>();
- for (UserSessionEntity userSession : sessions.values()) {
- Set currClientSessions = userSession.getClientSessions();
+ while(itr.hasNext()) {
+ UserSessionEntity entity = (UserSessionEntity) itr.next().getValue();
+ Set currClientSessions = entity.getClientSessions();
for (String clientSessionId : currClientSessions) {
ClientSessionEntity cls = (ClientSessionEntity) offlineSessionCache.get(clientSessionId);
if (cls != null) {
- clientSessions.add(cls);
+ clientSessions.add(wrap(realm, cls, true));
}
}
}
- return wrapClientSessions(realm, clientSessions, true);
+ return clientSessions;
}
@Override
@@ -626,7 +565,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
}
@Override
- public int getOfflineSessionsCount(RealmModel realm, ClientModel client) {
+ public long getOfflineSessionsCount(RealmModel realm, ClientModel client) {
return getUserSessionsCount(realm, client, true);
}
@@ -721,18 +660,19 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
@Override
public List listClientInitialAccess(RealmModel realm) {
- Map entities = new MapReduceTask(sessionCache)
- .mappedWith(ClientInitialAccessMapper.create(realm.getId()))
- .reducedWith(new FirstResultReducer())
- .execute();
- return wrapClientInitialAccess(realm, entities.values());
+ Iterator> itr = sessionCache.entrySet().stream().filter(ClientInitialAccessPredicate.create(realm.getId())).iterator();
+ List list = new LinkedList<>();
+ while (itr.hasNext()) {
+ list.add(wrap(realm, (ClientInitialAccessEntity) itr.next().getValue()));
+ }
+ return list;
}
class InfinispanKeycloakTransaction implements KeycloakTransaction {
private boolean active;
private boolean rollback;
- private Map