Fix AdminApiTest. Fix distribution. Try to prevent InMemoryModel leaks.
This commit is contained in:
1 parent
e0f670768f
commit
b1d341155d
17 files changed
+100
-19
No files matched your search
@@ -32,7 +32,7 @@ import org.keycloak.models.entities.RealmEntity;
|
||||
|
||||
/**
|
||||
* Realm Provider for JSON persistence.
|
||||
*
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
|
||||
*/
|
||||
public class FileRealmProvider implements RealmProvider {
|
||||
@@ -42,6 +42,7 @@ public class FileRealmProvider implements RealmProvider {
|
||||
|
||||
public FileRealmProvider(KeycloakSession session, InMemoryModel inMemoryModel) {
|
||||
this.session = session;
|
||||
session.enlistForClose(this);
|
||||
this.inMemoryModel = inMemoryModel;
|
||||
}
|
||||
|
||||
@@ -86,6 +87,7 @@ public class FileRealmProvider implements RealmProvider {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
inMemoryModel.sessionClosed(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -53,11 +53,13 @@ public class FileUserProvider implements UserProvider {
|
||||
|
||||
public FileUserProvider(KeycloakSession session, InMemoryModel inMemoryModel) {
|
||||
this.session = session;
|
||||
session.enlistForClose(this);
|
||||
this.inMemoryModel = inMemoryModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
inMemoryModel.sessionClosed(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -219,8 +221,7 @@ public class FileUserProvider implements UserProvider {
|
||||
|
||||
@Override
|
||||
public Set<FederatedIdentityModel> getFederatedIdentities(UserModel userModel, RealmModel realm) {
|
||||
UserModel user = getUserById(userModel.getId(), realm);
|
||||
UserEntity userEntity = ((UserAdapter) user).getUserEntity();
|
||||
UserEntity userEntity = ((UserAdapter) userModel).getUserEntity();
|
||||
List<FederatedIdentityEntity> linkEntities = userEntity.getFederatedIdentities();
|
||||
|
||||
if (linkEntities == null) {
|
||||
@@ -391,12 +392,31 @@ public class FileUserProvider implements UserProvider {
|
||||
|
||||
@Override
|
||||
public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
federatedUser = getUserById(federatedUser.getId(), realm);
|
||||
UserEntity userEntity = ((UserAdapter) federatedUser).getUserEntity();
|
||||
FederatedIdentityEntity federatedIdentityEntity = findFederatedIdentityLink(userEntity, federatedIdentityModel.getIdentityProvider());
|
||||
|
||||
federatedIdentityEntity.setToken(federatedIdentityModel.getToken());
|
||||
}
|
||||
|
||||
private FederatedIdentityEntity findFederatedIdentityLink(UserEntity userEntity, String identityProvider) {
|
||||
List<FederatedIdentityEntity> linkEntities = userEntity.getFederatedIdentities();
|
||||
if (linkEntities == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (FederatedIdentityEntity federatedIdentityEntity : linkEntities) {
|
||||
if (federatedIdentityEntity.getIdentityProvider().equals(identityProvider)) {
|
||||
return federatedIdentityEntity;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
return null; // not supported yet
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,7 +41,8 @@ import org.keycloak.util.JsonSerialization;
|
||||
/**
|
||||
* This class provides an in-memory copy of the entire model for each
|
||||
* Keycloak session. At the start of the session, the model is read
|
||||
* from JSON. When the session's transaction ends, the model is written.
|
||||
* from JSON. When the session's transaction ends, the model is written back
|
||||
* out.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
|
||||
*/
|
||||
@@ -83,6 +84,7 @@ public class InMemoryModel implements KeycloakTransaction {
|
||||
allModels.put(session, model);
|
||||
session.getTransaction().enlist(model);
|
||||
model.readModelFile();
|
||||
logger.info("Added session " + session.hashCode() + " total sessions=" + allModels.size());
|
||||
}
|
||||
|
||||
return model;
|
||||
@@ -104,6 +106,7 @@ public class InMemoryModel implements KeycloakTransaction {
|
||||
} catch (IOException ioe) {
|
||||
logger.error("Unable to read model file " + kcdata.getAbsolutePath(), ioe);
|
||||
} finally {
|
||||
logger.info("Read model file for session=" + session.hashCode());
|
||||
try {
|
||||
if (fis != null) fis.close();
|
||||
} catch (IOException e) {
|
||||
@@ -121,6 +124,7 @@ public class InMemoryModel implements KeycloakTransaction {
|
||||
} catch (IOException e) {
|
||||
logger.error("Unable to write model file " + keycloakModelFile.getAbsolutePath(), e);
|
||||
} finally {
|
||||
logger.info("Wrote model file for session=" + session.hashCode());
|
||||
try {
|
||||
if (outStream != null) outStream.close();
|
||||
} catch (IOException e) {
|
||||
@@ -195,17 +199,25 @@ public class InMemoryModel implements KeycloakTransaction {
|
||||
return (realmUsers(realmId).remove(userId) != null);
|
||||
}
|
||||
|
||||
void sessionClosed(KeycloakSession session) {
|
||||
synchronized (allModels) {
|
||||
allModels.remove(session);
|
||||
logger.info("Removed session " + session.hashCode());
|
||||
logger.info("sessionClosed: Session count=" + allModels.size());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void begin() {
|
||||
}
|
||||
|
||||
// commitCount is used for debugging. This allows you to easily run a test
|
||||
// to a particular point and then examine the JSON file.
|
||||
// private static int commitCount = 0;
|
||||
private static int commitCount = 0;
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
// commitCount++;
|
||||
commitCount++;
|
||||
synchronized (allModels) {
|
||||
// in case commit was somehow called twice on the same session
|
||||
if (!allModels.containsKey(session)) return;
|
||||
@@ -214,10 +226,12 @@ public class InMemoryModel implements KeycloakTransaction {
|
||||
writeModelFile();
|
||||
} finally {
|
||||
allModels.remove(session);
|
||||
// System.out.println("*** commitCount=" + commitCount);
|
||||
logger.info("Removed session " + session.hashCode());
|
||||
logger.info("*** commitCount=" + commitCount);
|
||||
logger.info("commit(): Session count=" + allModels.size());
|
||||
}
|
||||
|
||||
// if (commitCount == 61) System.exit(0);
|
||||
// if (commitCount == 16) {Thread.dumpStack();System.exit(0);}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,6 +239,7 @@ public class InMemoryModel implements KeycloakTransaction {
|
||||
public void rollback() {
|
||||
synchronized (allModels) {
|
||||
allModels.remove(session);
|
||||
System.out.println("rollback(): Session count=" + allModels.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode
|
||||
|
||||
private boolean appNameExists(String name) {
|
||||
for (ApplicationModel app : realm.getApplications()) {
|
||||
if (app == this) continue;
|
||||
if (app.getName().equals(name)) return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1033,7 +1033,7 @@ public class RealmAdapter implements RealmModel {
|
||||
@Override
|
||||
public boolean isIdentityFederationEnabled() {
|
||||
//TODO: not sure if we will support identity federation storage for file
|
||||
return true;
|
||||
return getIdentityProviders() != null && !getIdentityProviders().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -73,6 +73,7 @@ public class RoleAdapter implements RoleModel {
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
RealmAdapter realmAdapter = (RealmAdapter)realm;
|
||||
if (role.getName().equals(name)) return;
|
||||
if (realmAdapter.hasRoleWithName(name)) throw new ModelDuplicateException("Role name " + name + " already exists.");
|
||||
role.setName(name);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user