/*
* Copyright 2016 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.util.cli;
import org.infinispan.AdvancedCache;
import org.infinispan.Cache;
import org.infinispan.context.Flag;
import org.keycloak.common.util.Time;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public abstract class AbstractOfflineCacheCommand extends AbstractCommand {
@Override
protected void doRunCommand(KeycloakSession session) {
InfinispanConnectionProvider provider = session.getProvider(InfinispanConnectionProvider.class);
Cache<String, SessionEntity> ispnCache = provider.getCache(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME);
doRunCacheCommand(session, ispnCache);
}
protected void printSession(String id, UserSessionEntity userSession) {
if (userSession == null) {
log.info("Not found session with Id: " + id);
} else {
log.info("Found session. ID: " + toString(userSession));
}
}
protected String toString(UserSessionEntity userSession) {
int clientSessionsSize = userSession.getAuthenticatedClientSessions()==null ? 0 : userSession.getAuthenticatedClientSessions().size();
return "ID: " + userSession.getId() + ", realm: " + userSession.getRealm() + ", lastAccessTime: " + Time.toDate(userSession.getLastSessionRefresh()) +
", authenticatedClientSessions: " + clientSessionsSize;
}
protected abstract void doRunCacheCommand(KeycloakSession session, Cache<String, SessionEntity> cache);
// IMPLS
public static class PutCommand extends AbstractOfflineCacheCommand {
@Override
public String getName() {
return "put";
}
@Override
protected void doRunCacheCommand(KeycloakSession session, Cache<String, SessionEntity> cache) {
UserSessionEntity userSession = new UserSessionEntity();
String id = getArg(0);
userSession.setId(id);
userSession.setRealm(getArg(1));
userSession.setLastSessionRefresh(Time.currentTime());
cache.put(id, userSession);
}
@Override
public String printUsage() {
return getName() + " <user-session-id> <realm-name>";
}
}
public static class GetCommand extends AbstractOfflineCacheCommand {
@Override
public String getName() {
return "get";
}
@Override
protected void doRunCacheCommand(KeycloakSession session, Cache<String, SessionEntity> cache) {
String id = getArg(0);
UserSessionEntity userSession = (UserSessionEntity) cache.get(id);
printSession(id, userSession);
}
@Override
public String printUsage() {
return getName() + " <user-session-id>";
}
}
// Just to check performance of multiple get calls. And comparing what's the change between the case when item is available locally or not.
public static class GetMultipleCommand extends AbstractOfflineCacheCommand {
@Override
public String getName() {
return "getMulti";
}
@Override
protected void doRunCacheCommand(KeycloakSession session, Cache<String, SessionEntity> cache) {
String id = getArg(0);
int count = getIntArg(1);
long start = System.currentTimeMillis();
for (int i=0 ; i<count ; i++) {
UserSessionEntity userSession = (UserSessionEntity) cache.get(id);
//printSession(id, userSession);
}
long took = System.currentTimeMillis() - start;
log.infof("Took %d milliseconds", took);
}
@Override
public String printUsage() {
return getName() + " <user-session-id> <count-of-gets>";
}
}
public static class RemoveCommand extends AbstractOfflineCacheCommand {
@Override
public String getName() {
return "remove";
}
@Override
protected void doRunCacheCommand(KeycloakSession session, Cache<String, SessionEntity> cache) {
String id = getArg(0);
cache.remove(id);
}
@Override
public String printUsage() {
return getName() + " <user-session-id>";
}
}
public static class ClearCommand extends AbstractOfflineCacheCommand {
@Override
public String getName() {
return "clear";
}
@Override
protected void doRunCacheCommand(KeycloakSession session, Cache<String, SessionEntity> cache) {
cache.clear();
}
}
public static class SizeCommand extends AbstractOfflineCacheCommand {
@Override
public String getName() {
return "size";
}
@Override
protected void doRunCacheCommand(KeycloakSession session, Cache<String, SessionEntity> cache) {
log.info("Size: " + cache.size());
}
}
public static class ListCommand extends AbstractOfflineCacheCommand {
@Override
public String getName() {
return "list";
}
@Override
protected void doRunCacheCommand(KeycloakSession session, Cache<String, SessionEntity> cache) {
for (String id : cache.keySet()) {
SessionEntity entity = cache.get(id);
if (!(entity instanceof UserSessionEntity)) {
continue;
}
UserSessionEntity userSession = (UserSessionEntity) cache.get(id);
log.info("list: key=" + id + ", value=" + toString(userSession));
}
}
}
public static class GetLocalCommand extends AbstractOfflineCacheCommand {
@Override
public String getName() {
return "getLocal";
}
@Override
protected void doRunCacheCommand(KeycloakSession session, Cache<String, SessionEntity> cache) {
String id = getArg(0);
cache = ((AdvancedCache) cache).withFlags(Flag.CACHE_MODE_LOCAL);
UserSessionEntity userSession = (UserSessionEntity) cache.get(id);
printSession(id, userSession);
}
@Override
public String printUsage() {
return getName() + " <user-session-id>";
}
}
public static class SizeLocalCommand extends AbstractOfflineCacheCommand {
@Override
public String getName() {
return "sizeLocal";
}
@Override
protected void doRunCacheCommand(KeycloakSession session, Cache<String, SessionEntity> cache) {
log.info("Size local: " + cache.getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL).size());
}
}
}