KEYCLOAK-17774 Implement equals method for work cache events

Co-Authored-By: stianst <stianst@gmail.com>
Co-Authored-By: Michal Hajas <mhajas@redhat.com>
This commit is contained in:
Hynek Mlnarik 2021-04-22 09:23:37 +02:00 committed by Hynek Mlnařík
parent 5a33ec2244
commit 32fb45eb5b
39 changed files with 678 additions and 3 deletions

View file

@ -21,6 +21,8 @@ import org.keycloak.cluster.ClusterEvent;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Objects;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.commons.marshall.MarshallUtil;
import org.infinispan.commons.marshall.SerializeWith;
@ -86,6 +88,19 @@ public class WrapperClusterEvent implements ClusterEvent {
this.delegateEvent = delegateEvent;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WrapperClusterEvent that = (WrapperClusterEvent) o;
return ignoreSender == that.ignoreSender && ignoreSenderSite == that.ignoreSenderSite && Objects.equals(eventKey, that.eventKey) && Objects.equals(sender, that.sender) && Objects.equals(senderSite, that.senderSite) && Objects.equals(delegateEvent, that.delegateEvent);
}
@Override
public int hashCode() {
return Objects.hash(eventKey, sender, senderSite, ignoreSender, ignoreSenderSite, delegateEvent);
}
@Override
public String toString() {
return String.format("WrapperClusterEvent [ eventKey=%s, sender=%s, senderSite=%s, delegateEvent=%s ]", eventKey, sender, senderSite, delegateEvent.toString());

View file

@ -310,7 +310,9 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
configureRemoteCacheStore(replicationConfigBuilder, async, InfinispanConnectionProvider.WORK_CACHE_NAME, false);
}
Configuration replicationEvictionCacheConfiguration = replicationConfigBuilder.build();
Configuration replicationEvictionCacheConfiguration = replicationConfigBuilder
.expiration().enableReaper().wakeUpInterval(15, TimeUnit.SECONDS)
.build();
cacheManager.defineConfiguration(InfinispanConnectionProvider.WORK_CACHE_NAME, replicationEvictionCacheConfiguration);
cacheManager.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME, true);

View file

@ -23,4 +23,14 @@ import org.keycloak.cluster.ClusterEvent;
* @version $Revision: 1 $
*/
public class ClearCacheEvent implements ClusterEvent {
@Override
public boolean equals(Object obj) {
return obj instanceof ClearCacheEvent;
}
@Override
public int hashCode() {
return 1;
}
}

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.authorization.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
@ -52,6 +53,20 @@ public class PermissionTicketRemovedEvent extends InvalidationEvent implements A
return id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
PermissionTicketRemovedEvent that = (PermissionTicketRemovedEvent) o;
return Objects.equals(id, that.id) && Objects.equals(resource, that.resource) && Objects.equals(serverId, that.serverId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id, resource, serverId);
}
@Override
public String toString() {
return String.format("PermissionTicketRemovedEvent [ id=%s, name=%s]", id, resource);

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.authorization.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
@ -52,6 +53,22 @@ public class PermissionTicketUpdatedEvent extends InvalidationEvent implements A
return id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
PermissionTicketUpdatedEvent that = (PermissionTicketUpdatedEvent) o;
return Objects.equals(id, that.id) && Objects.equals(resource, that.resource) && Objects.equals(serverId, that.serverId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id, resource, serverId);
}
@Override
public String toString() {
return String.format("PermissionTicketUpdatedEvent [ id=%s, name=%s]", id, resource);

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.authorization.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.authorization.StoreFactoryCacheManager;
@ -59,6 +60,20 @@ public class PolicyRemovedEvent extends InvalidationEvent implements Authorizati
return id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
PolicyRemovedEvent that = (PolicyRemovedEvent) o;
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(serverId, that.serverId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id, name, serverId);
}
@Override
public String toString() {
return String.format("PolicyRemovedEvent [ id=%s, name=%s]", id, name);

View file

@ -25,6 +25,7 @@ import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.commons.marshall.MarshallUtil;
@ -59,6 +60,20 @@ public class PolicyUpdatedEvent extends InvalidationEvent implements Authorizati
return id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
PolicyUpdatedEvent that = (PolicyUpdatedEvent) o;
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(serverId, that.serverId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id, name, serverId);
}
@Override
public String toString() {
return String.format("PolicyUpdatedEvent [ id=%s, name=%s ]", id, name);

View file

@ -25,6 +25,7 @@ import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.commons.marshall.MarshallUtil;
@ -61,6 +62,20 @@ public class ResourceRemovedEvent extends InvalidationEvent implements Authoriza
return id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ResourceRemovedEvent that = (ResourceRemovedEvent) o;
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(owner, that.owner) && Objects.equals(serverId, that.serverId) && Objects.equals(type, that.type);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id, name, owner, serverId, type);
}
@Override
public String toString() {
return String.format("ResourceRemovedEvent [ id=%s, name=%s ]", id, name);

View file

@ -23,6 +23,7 @@ import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Objects;
import java.util.Set;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.commons.marshall.MarshallUtil;
@ -49,6 +50,20 @@ public class ResourceServerRemovedEvent extends InvalidationEvent implements Aut
return id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ResourceServerRemovedEvent that = (ResourceServerRemovedEvent) o;
return Objects.equals(id, that.id) && Objects.equals(clientId, that.clientId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id, clientId);
}
@Override
public String toString() {
return String.format("ResourceServerRemovedEvent [ id=%s, clientId=%s ]", id, clientId);

View file

@ -25,6 +25,7 @@ import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.commons.marshall.MarshallUtil;
@ -61,6 +62,20 @@ public class ResourceUpdatedEvent extends InvalidationEvent implements Authoriza
return id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ResourceUpdatedEvent that = (ResourceUpdatedEvent) o;
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(serverId, that.serverId) && Objects.equals(type, that.type) && Objects.equals(owner, that.owner);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id, name, serverId, type, owner);
}
@Override
public String toString() {
return String.format("ResourceUpdatedEvent [ id=%s, name=%s ]", id, name);

View file

@ -23,6 +23,7 @@ import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Objects;
import java.util.Set;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.commons.marshall.MarshallUtil;
@ -56,6 +57,20 @@ public class ScopeRemovedEvent extends InvalidationEvent implements Authorizatio
return String.format("ScopeRemovedEvent [ id=%s, name=%s]", id, name);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ScopeRemovedEvent that = (ScopeRemovedEvent) o;
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(serverId, that.serverId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id, name, serverId);
}
@Override
public void addInvalidations(StoreFactoryCacheManager cache, Set<String> invalidations) {
cache.scopeRemoval(id, name, serverId, invalidations);

View file

@ -23,6 +23,7 @@ import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Objects;
import java.util.Set;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.commons.marshall.MarshallUtil;
@ -51,6 +52,20 @@ public class ScopeUpdatedEvent extends InvalidationEvent implements Authorizatio
return id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ScopeUpdatedEvent that = (ScopeUpdatedEvent) o;
return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(serverId, that.serverId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id, name, serverId);
}
@Override
public String toString() {
return String.format("ScopeUpdatedEvent [ id=%s, name=%s ]", id, name);

View file

@ -23,6 +23,8 @@ import java.io.ObjectOutput;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.commons.marshall.MarshallUtil;
import org.infinispan.commons.marshall.SerializeWith;
@ -71,6 +73,20 @@ public class AuthenticationSessionAuthNoteUpdateEvent implements ClusterEvent {
return authNotesFragment;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AuthenticationSessionAuthNoteUpdateEvent that = (AuthenticationSessionAuthNoteUpdateEvent) o;
return Objects.equals(authSessionId, that.authSessionId) && Objects.equals(tabId, that.tabId) && Objects.equals(clientUUID, that.clientUUID);
}
@Override
public int hashCode() {
return Objects.hash(authSessionId, tabId, clientUUID);
}
@Override
public String toString() {
return String.format("AuthenticationSessionAuthNoteUpdateEvent [ authSessionId=%s, tabId=%s, clientUUID=%s, authNotesFragment=%s ]",

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -60,6 +61,20 @@ public class ClientAddedEvent extends InvalidationEvent implements RealmCacheInv
realmCache.clientAdded(realmId, clientUuid, clientId, invalidations);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ClientAddedEvent that = (ClientAddedEvent) o;
return Objects.equals(clientUuid, that.clientUuid) && Objects.equals(clientId, that.clientId) && Objects.equals(realmId, that.realmId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), clientUuid, clientId, realmId);
}
public static class ExternalizerImpl implements Externalizer<ClientAddedEvent> {
private static final int VERSION_1 = 1;

View file

@ -18,8 +18,10 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.jboss.logging.Logger;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -45,8 +47,11 @@ public class ClientRemovedEvent extends InvalidationEvent implements RealmCacheI
private String realmId;
// roleId -> roleName
private Map<String, String> clientRoles;
private static final Logger log = Logger.getLogger(ClientRemovedEvent.class);
public static ClientRemovedEvent create(ClientModel client) {
log.tracev("Created; clientId={0}", client.getClientId());
ClientRemovedEvent event = new ClientRemovedEvent();
event.realmId = client.getRealm().getId();
@ -57,6 +62,12 @@ public class ClientRemovedEvent extends InvalidationEvent implements RealmCacheI
return event;
}
@Override
protected void finalize() throws Throwable {
log.tracev("Finalized; clientId={0}", clientId);
super.finalize();
}
@Override
public String getId() {
return clientUuid;
@ -79,6 +90,25 @@ public class ClientRemovedEvent extends InvalidationEvent implements RealmCacheI
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ClientRemovedEvent that = (ClientRemovedEvent) o;
boolean equals = Objects.equals(clientUuid, that.clientUuid) &&
Objects.equals(clientId, that.clientId) &&
Objects.equals(realmId, that.realmId) &&
Objects.equals(clientRoles, that.clientRoles);
log.tracev("Equals; clientId={0}, equals={1}", clientId, equals);
return equals;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), clientUuid, clientId, realmId, clientRoles);
}
public static class ExternalizerImpl implements Externalizer<ClientRemovedEvent> {
private static final int VERSION_1 = 1;
@ -91,6 +121,8 @@ public class ClientRemovedEvent extends InvalidationEvent implements RealmCacheI
MarshallUtil.marshallString(obj.clientId, output);
MarshallUtil.marshallString(obj.realmId, output);
KeycloakMarshallUtil.writeMap(obj.clientRoles, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT, output);
log.tracev("Write; clientId={0}", obj.clientId);
}
@Override
@ -111,6 +143,8 @@ public class ClientRemovedEvent extends InvalidationEvent implements RealmCacheI
res.clientRoles = KeycloakMarshallUtil.readMap(input, KeycloakMarshallUtil.STRING_EXT, KeycloakMarshallUtil.STRING_EXT,
size -> new ConcurrentHashMap<>(size));
log.tracev("Read; clientId={0}", res.clientId);
return res;
}
}

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -45,6 +46,20 @@ public class ClientScopeAddedEvent extends InvalidationEvent implements RealmCac
return clientScopeId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ClientScopeAddedEvent that = (ClientScopeAddedEvent) o;
return Objects.equals(clientScopeId, that.clientScopeId) && Objects.equals(realmId, that.realmId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), clientScopeId, realmId);
}
@Override
public String toString() {
return String.format("ClientScopeAddedEvent [ clientScopeId=%s, realmId=%s ]", clientScopeId, realmId);

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -46,6 +47,20 @@ public class ClientScopeRemovedEvent extends InvalidationEvent implements RealmC
return clientScopeId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ClientScopeRemovedEvent that = (ClientScopeRemovedEvent) o;
return Objects.equals(clientScopeId, that.clientScopeId) && Objects.equals(realmId, that.realmId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), clientScopeId, realmId);
}
@Override
public String toString() {
return String.format("ClientScopeRemovedEvent [ clientScopeId=%s, realmId=%s ]", clientScopeId, realmId);

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -60,6 +61,20 @@ public class ClientTemplateEvent extends InvalidationEvent implements RealmCache
// Nothing. ID was already invalidated
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ClientTemplateEvent that = (ClientTemplateEvent) o;
return Objects.equals(clientTemplateId, that.clientTemplateId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), clientTemplateId);
}
public static class ExternalizerImpl implements Externalizer<ClientTemplateEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -60,6 +61,20 @@ public class ClientUpdatedEvent extends InvalidationEvent implements RealmCacheI
realmCache.clientUpdated(realmId, clientUuid, clientId, invalidations);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ClientUpdatedEvent that = (ClientUpdatedEvent) o;
return Objects.equals(clientUuid, that.clientUuid) && Objects.equals(clientId, that.clientId) && Objects.equals(realmId, that.realmId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), clientUuid, clientId, realmId);
}
public static class ExternalizerImpl implements Externalizer<ClientUpdatedEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -64,6 +65,20 @@ public class GroupAddedEvent extends InvalidationEvent implements RealmCacheInva
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
GroupAddedEvent that = (GroupAddedEvent) o;
return Objects.equals(groupId, that.groupId) && Objects.equals(realmId, that.realmId) && Objects.equals(parentId, that.parentId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), groupId, realmId, parentId);
}
public static class ExternalizerImpl implements Externalizer<GroupAddedEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.GroupModel;
@ -69,6 +70,20 @@ public class GroupMovedEvent extends InvalidationEvent implements RealmCacheInva
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
GroupMovedEvent that = (GroupMovedEvent) o;
return Objects.equals(groupId, that.groupId) && Objects.equals(newParentId, that.newParentId) && Objects.equals(oldParentId, that.oldParentId) && Objects.equals(realmId, that.realmId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), groupId, newParentId, oldParentId, realmId);
}
public static class ExternalizerImpl implements Externalizer<GroupMovedEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.GroupModel;
@ -64,6 +65,20 @@ public class GroupRemovedEvent extends InvalidationEvent implements RealmCacheIn
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
GroupRemovedEvent that = (GroupRemovedEvent) o;
return Objects.equals(groupId, that.groupId) && Objects.equals(parentId, that.parentId) && Objects.equals(realmId, that.realmId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), groupId, parentId, realmId);
}
public static class ExternalizerImpl implements Externalizer<GroupRemovedEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -58,6 +59,20 @@ public class RealmRemovedEvent extends InvalidationEvent implements RealmCacheIn
realmCache.realmRemoval(realmId, realmName, invalidations);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
RealmRemovedEvent that = (RealmRemovedEvent) o;
return Objects.equals(realmId, that.realmId) && Objects.equals(realmName, that.realmName);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), realmId, realmName);
}
public static class ExternalizerImpl implements Externalizer<RealmRemovedEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -58,6 +59,20 @@ public class RealmUpdatedEvent extends InvalidationEvent implements RealmCacheIn
realmCache.realmUpdated(realmId, realmName, invalidations);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
RealmUpdatedEvent that = (RealmUpdatedEvent) o;
return Objects.equals(realmId, that.realmId) && Objects.equals(realmName, that.realmName);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), realmId, realmName);
}
public static class ExternalizerImpl implements Externalizer<RealmUpdatedEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -58,6 +59,20 @@ public class RoleAddedEvent extends InvalidationEvent implements RealmCacheInval
realmCache.roleAdded(containerId, invalidations);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
RoleAddedEvent that = (RoleAddedEvent) o;
return Objects.equals(roleId, that.roleId) && Objects.equals(containerId, that.containerId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), roleId, containerId);
}
public static class ExternalizerImpl implements Externalizer<RoleAddedEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -60,6 +61,20 @@ public class RoleRemovedEvent extends InvalidationEvent implements RealmCacheInv
realmCache.roleRemoval(roleId, roleName, containerId, invalidations);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
RoleRemovedEvent that = (RoleRemovedEvent) o;
return Objects.equals(roleId, that.roleId) && Objects.equals(roleName, that.roleName) && Objects.equals(containerId, that.containerId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), roleId, roleName, containerId);
}
public static class ExternalizerImpl implements Externalizer<RoleRemovedEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.RealmCacheManager;
@ -60,6 +61,20 @@ public class RoleUpdatedEvent extends InvalidationEvent implements RealmCacheInv
realmCache.roleUpdated(containerId, roleName, invalidations);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
RoleUpdatedEvent that = (RoleUpdatedEvent) o;
return Objects.equals(roleId, that.roleId) && Objects.equals(roleName, that.roleName) && Objects.equals(containerId, that.containerId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), roleId, roleName, containerId);
}
public static class ExternalizerImpl implements Externalizer<RoleUpdatedEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.FederatedIdentityModel;
@ -77,6 +78,20 @@ public class UserFederationLinkRemovedEvent extends InvalidationEvent implements
userCache.federatedIdentityLinkRemovedInvalidation(userId, realmId, identityProviderId, socialUserId, invalidations);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
UserFederationLinkRemovedEvent that = (UserFederationLinkRemovedEvent) o;
return Objects.equals(userId, that.userId) && Objects.equals(realmId, that.realmId) && Objects.equals(identityProviderId, that.identityProviderId) && Objects.equals(socialUserId, that.socialUserId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), userId, realmId, identityProviderId, socialUserId);
}
public static class ExternalizerImpl implements Externalizer<UserFederationLinkRemovedEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,9 +17,9 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.FederatedIdentityModel;
@ -85,6 +85,20 @@ public class UserFullInvalidationEvent extends InvalidationEvent implements User
userCache.fullUserInvalidation(userId, username, email, realmId, identityFederationEnabled, federatedIdentities, invalidations);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
UserFullInvalidationEvent that = (UserFullInvalidationEvent) o;
return identityFederationEnabled == that.identityFederationEnabled && Objects.equals(userId, that.userId) && Objects.equals(username, that.username) && Objects.equals(email, that.email) && Objects.equals(realmId, that.realmId) && Objects.equals(federatedIdentities, that.federatedIdentities);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), userId, username, email, realmId, identityFederationEnabled, federatedIdentities);
}
public static class ExternalizerImpl implements Externalizer<UserFullInvalidationEvent> {
private static final int VERSION_1 = 1;

View file

@ -17,6 +17,7 @@
package org.keycloak.models.cache.infinispan.events;
import java.util.Objects;
import java.util.Set;
import org.keycloak.models.cache.infinispan.UserCacheManager;
@ -62,6 +63,20 @@ public class UserUpdatedEvent extends InvalidationEvent implements UserCacheInva
userCache.userUpdatedInvalidations(userId, username, email, realmId, invalidations);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
UserUpdatedEvent that = (UserUpdatedEvent) o;
return Objects.equals(userId, that.userId) && Objects.equals(username, that.username) && Objects.equals(email, that.email) && Objects.equals(realmId, that.realmId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), userId, username, email, realmId);
}
public static class ExternalizerImpl implements Externalizer<UserUpdatedEvent> {
private static final int VERSION_1 = 1;

View file

@ -22,6 +22,7 @@ import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.commons.marshall.MarshallUtil;
@ -44,6 +45,15 @@ public class LastSessionRefreshEvent implements ClusterEvent {
return lastSessionRefreshes;
}
@Override
public boolean equals(Object o) {
return o instanceof LastSessionRefreshEvent;
}
@Override
public int hashCode() {
return 1;
}
public static class ExternalizerImpl implements Externalizer<LastSessionRefreshEvent> {

View file

@ -21,6 +21,8 @@ import org.keycloak.models.KeycloakSession;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Objects;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.commons.marshall.MarshallUtil;
import org.infinispan.commons.marshall.SerializeWith;
@ -39,6 +41,21 @@ public class ClientRemovedSessionEvent extends SessionClusterEvent {
return event;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ClientRemovedSessionEvent that = (ClientRemovedSessionEvent) o;
return Objects.equals(clientUuid, that.clientUuid);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), clientUuid);
}
@Override
public String toString() {
return String.format("ClientRemovedSessionEvent [ realmId=%s , clientUuid=%s ]", getRealmId(), clientUuid);

View file

@ -24,6 +24,8 @@ import org.keycloak.models.sessions.infinispan.util.InfinispanUtil;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Objects;
import org.infinispan.commons.marshall.MarshallUtil;
/**
@ -79,6 +81,19 @@ public abstract class SessionClusterEvent implements ClusterEvent {
return nodeId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SessionClusterEvent that = (SessionClusterEvent) o;
return Objects.equals(realmId, that.realmId) && Objects.equals(eventKey, that.eventKey);
}
@Override
public int hashCode() {
return Objects.hash(realmId, eventKey);
}
@Override
public String toString() {
String simpleClassName = getClass().getSimpleName();

View file

@ -20,6 +20,7 @@ import org.keycloak.cluster.ClusterEvent;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
/**
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
@ -64,6 +65,19 @@ public class MapAuthenticationSessionAuthNoteUpdateEvent implements ClusterEvent
return authNotesFragment;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MapAuthenticationSessionAuthNoteUpdateEvent that = (MapAuthenticationSessionAuthNoteUpdateEvent) o;
return Objects.equals(authSessionId, that.authSessionId) && Objects.equals(tabId, that.tabId) && Objects.equals(clientUUID, that.clientUUID);
}
@Override
public int hashCode() {
return Objects.hash(authSessionId, tabId, clientUUID);
}
@Override
public String toString() {
return String.format("AuthenticationSessionAuthNoteUpdateEvent [ authSessionId=%s, tabId=%s, clientUUID=%s, authNotesFragment=%s ]",

View file

@ -340,6 +340,19 @@ public class UserStorageSyncManager {
notification.setStorageProvider(provider);
return notification;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserStorageProviderClusterEvent that = (UserStorageProviderClusterEvent) o;
return removed == that.removed && Objects.equals(realmId, that.realmId) && Objects.equals(storageProvider.getId(), that.storageProvider.getId());
}
@Override
public int hashCode() {
return Objects.hash(removed, realmId, storageProvider.getId());
}
}
}

View file

@ -77,6 +77,7 @@ import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
@ -175,6 +176,19 @@ public abstract class KeycloakModelTest {
}
};
@Rule
public final TestRule watcher = new TestWatcher() {
@Override
protected void starting(Description description) {
log.infof("%s STARTED", description.getMethodName());
}
@Override
protected void finished(Description description) {
log.infof("%s FINISHED\n\n", description.getMethodName());
}
};
private static final Set<Class<? extends Spi>> ALLOWED_SPIS = ImmutableSet.<Class<? extends Spi>>builder()
.add(AuthorizationSpi.class)
.add(ClientScopeSpi.class)

View file

@ -0,0 +1,137 @@
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model.infinispan;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
import org.keycloak.models.cache.infinispan.events.AuthenticationSessionAuthNoteUpdateEvent;
import org.keycloak.testsuite.model.KeycloakModelTest;
import org.keycloak.testsuite.model.RequireProvider;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.hamcrest.Matchers;
import org.infinispan.Cache;
import org.junit.Assume;
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assume.assumeThat;
/**
*
* @author hmlnarik
*/
@RequireProvider(InfinispanConnectionProvider.class)
public class CacheExpirationTest extends KeycloakModelTest {
@Test
public void testCacheExpiration() throws Exception {
AtomicLong putTime = new AtomicLong();
inComittedTransaction(session -> {
InfinispanConnectionProvider provider = session.getProvider(InfinispanConnectionProvider.class);
Cache<String, Object> cache = provider.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME);
cache.entrySet().stream()
.filter(me -> me.getValue() instanceof AuthenticationSessionAuthNoteUpdateEvent)
.forEach((c, me) -> c.remove(me.getKey()));
putTime.set(System.currentTimeMillis());
cache.put("1-2", AuthenticationSessionAuthNoteUpdateEvent.create("g1", "p1", "r1", Collections.emptyMap()), 20000, TimeUnit.MILLISECONDS);
cache.put("1-2-3", AuthenticationSessionAuthNoteUpdateEvent.create("g2", "p2", "r2", Collections.emptyMap()), 20000, TimeUnit.MILLISECONDS);
});
assumeThat("jmap output format unsupported", getNumberOfInstancesOfClass(AuthenticationSessionAuthNoteUpdateEvent.class), notNullValue());
assertThat(getNumberOfInstancesOfClass(AuthenticationSessionAuthNoteUpdateEvent.class), is(2));
AtomicInteger maxCountOfInstances = new AtomicInteger();
AtomicInteger minCountOfInstances = new AtomicInteger(100);
inIndependentFactories(4, 5 * 60, () -> {
log.debug("Joining the cluster");
inComittedTransaction(session -> {
InfinispanConnectionProvider provider = session.getProvider(InfinispanConnectionProvider.class);
Cache<String, Object> cache = provider.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME);
do {
try { Thread.sleep(1000); } catch (InterruptedException ex) {}
} while (! cache.getAdvancedCache().getDistributionManager().isJoinComplete());
cache.keySet().forEach(s -> {});
});
log.debug("Cluster joined");
int c = getNumberOfInstancesOfClass(AuthenticationSessionAuthNoteUpdateEvent.class);
maxCountOfInstances.getAndAccumulate(c, Integer::max);
assumeThat("Seems we're running on a way too slow a computer", System.currentTimeMillis() - putTime.get(), Matchers.lessThan(20000L));
// Wait for at most 3 minutes which is much more than 15 seconds expiration set in DefaultInfinispanConnectionProviderFactory
for (int i = 0; i < 3 * 60; i++) {
try { Thread.sleep(1000); } catch (InterruptedException ex) {}
if (getNumberOfInstancesOfClass(AuthenticationSessionAuthNoteUpdateEvent.class) == 0) {
break;
}
}
c = getNumberOfInstancesOfClass(AuthenticationSessionAuthNoteUpdateEvent.class);
minCountOfInstances.getAndAccumulate(c, Integer::min);
});
assertThat(maxCountOfInstances.get(), is(10));
assertThat(minCountOfInstances.get(), is(0));
}
private static final Pattern JMAP_HOTSPOT_PATTERN = Pattern.compile("\\s*\\d+:\\s+(\\d+)\\s+(\\d+)\\s+(\\S+)\\s*");
public Integer getNumberOfInstancesOfClass(Class<?> c) {
String name = ManagementFactory.getRuntimeMXBean().getName();
String[] str = name.split("@");
return getNumberOfInstancesOfClass(c, str[0]);
}
public Integer getNumberOfInstancesOfClass(Class<?> c, String pid) {
Process proc;
try {
proc = Runtime.getRuntime().exec("jmap -histo:live " + pid);
try (BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
AtomicInteger matchingLines = new AtomicInteger();
String className = c.getName();
return stdInput.lines()
.peek(log::trace)
.map(JMAP_HOTSPOT_PATTERN::matcher)
.filter(Matcher::matches)
.peek(m -> matchingLines.incrementAndGet())
.filter(m -> Objects.equals(m.group(3), className))
.peek(m -> log.debugf("jmap: %s", m.group()))
.findAny()
.map(m -> Integer.valueOf(m.group(1)))
.orElseGet(() -> matchingLines.get() == 0 ? null : 0);
}
} catch (IOException ex) {
log.debug(ex);
Assume.assumeTrue("jmap not found or unsupported", false);
return null;
}
}
}

View file

@ -42,7 +42,7 @@ import java.util.stream.Collectors;
import org.keycloak.testsuite.model.KeycloakModelTest;
import org.keycloak.testsuite.model.RequireProvider;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>

View file

@ -48,6 +48,8 @@ log4j.logger.org.keycloak.connections.jpa.DefaultJpaConnectionProviderFactory=de
#log4j.logger.org.keycloak.STACK_TRACE=trace
#log4j.logger.org.keycloak.models.sessions.infinispan=trace
#log4j.logger.org.infinispan.expiration.impl.ClusterExpirationManager=trace
#
#log4j.logger.org.hibernate.type=trace
#log4j.logger.org.hibernate.SQL=debug