Bug 511469 - Memory Leak in AbstractConnectionManager
Reuse existing session IDs instead of assigning new ones
Change-Id: I35441a7ef9aa01900feb32c9abe13fc00727ab31
diff --git a/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/accesscontrol/AccessControl.java b/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/accesscontrol/AccessControl.java
index 187e581..b434fe6 100644
--- a/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/accesscontrol/AccessControl.java
+++ b/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/accesscontrol/AccessControl.java
@@ -53,7 +53,7 @@
private final ESAuthorizationService authorizationService;
private final ESOrgUnitResolver orgUnitResolver;
- private final ESSessions sessions;
+ private final EMFStoreSessions sessions;
private final LoginService loginService;
@@ -69,7 +69,7 @@
*/
public AccessControl(ServerSpace serverSpace) {
this.serverSpace = serverSpace;
- sessions = new ESSessions();
+ sessions = new EMFStoreSessions();
orgUnitProvider = initOrgUnitProviderService();
orgUnitResolver = initOrgUnitResolverService();
@@ -91,7 +91,7 @@
this.authenticationControlType = authenticationControlType;
this.serverSpace = serverSpace;
- sessions = new ESSessions();
+ sessions = new EMFStoreSessions();
orgUnitProvider = initOrgUnitProviderService();
orgUnitResolver = initOrgUnitResolverService();
diff --git a/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/accesscontrol/EMFStoreSessions.java b/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/accesscontrol/EMFStoreSessions.java
new file mode 100644
index 0000000..10de2b4
--- /dev/null
+++ b/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/accesscontrol/EMFStoreSessions.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2017 EclipseSource Muenchen GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * edgar - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emf.emfstore.internal.server.accesscontrol;
+
+import java.util.Map.Entry;
+
+import org.eclipse.emf.emfstore.internal.server.accesscontrol.authentication.ACUserContainer;
+import org.eclipse.emf.emfstore.internal.server.model.SessionId;
+import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACOrgUnitId;
+import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESUserImpl;
+import org.eclipse.emf.emfstore.server.auth.ESSessions;
+import org.eclipse.emf.emfstore.server.model.ESSessionId;
+import org.eclipse.emf.emfstore.server.model.ESUser;
+
+/**
+ * Internal {@link ESSessions} implementation.
+ */
+public class EMFStoreSessions extends ESSessions {
+
+ /**
+ * Given an user ID, tries to find a session.
+ *
+ * @param user the ID of the user whose session should be retrieved
+ * @return the session ID, if any, {@code null} otherwise
+ * @since 1.9
+ */
+ public ESSessionId resolveByUser(ESUser user) {
+ final ACOrgUnitId userId = ((ESUserImpl) user).toInternalAPI().getId();
+ for (final Entry<SessionId, ACUserContainer> entry : sessionUserMap.entrySet()) {
+ final ACUserContainer container = entry.getValue();
+ if (container.getRawUser().getId().equals(userId)) {
+ return entry.getKey().toAPI();
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/accesscontrol/LoginService.java b/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/accesscontrol/LoginService.java
index bafbd73..35ce4c9 100644
--- a/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/accesscontrol/LoginService.java
+++ b/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/accesscontrol/LoginService.java
@@ -24,6 +24,7 @@
import org.eclipse.emf.emfstore.internal.server.model.AuthenticationInformation;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACUser;
import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESAuthenticationInformationImpl;
+import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESSessionIdImpl;
import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESUserImpl;
import org.eclipse.emf.emfstore.server.auth.ESAuthenticationControlType;
import org.eclipse.emf.emfstore.server.auth.ESOrgUnitResolver;
@@ -45,7 +46,7 @@
private static final String USER_VERIFIER_SERVICE_CLASS = "userVerifierServiceClass"; //$NON-NLS-1$
private static final String MONITOR_NAME = "authentication"; //$NON-NLS-1$
private static final String ACCESSCONTROL_EXTENSION_ID = "org.eclipse.emf.emfstore.server.accessControl"; //$NON-NLS-1$
- private final ESSessions sessions;
+ private final EMFStoreSessions sessions;
private final ESOrgUnitResolver orgUnitResolver;
private final ESOrgUnitProvider orgUnitProvider;
private final ESAuthenticationControlType authenticationControlType;
@@ -67,7 +68,7 @@
*/
public LoginService(
ESAuthenticationControlType authenticationControlType,
- ESSessions sessions,
+ EMFStoreSessions sessions,
ESOrgUnitProvider orgUnitProvider,
ESOrgUnitResolver orgUnitResolver) {
@@ -125,16 +126,22 @@
username,
password,
clientVersionInfo);
+ final AuthenticationInformation authenticationInformation = ESAuthenticationInformationImpl.class.cast(
+ authInfo).toInternalAPI();
- sessions.add(authInfo);
+ final ESSessionId existingSession = sessions.resolveByUser(authInfo.getUser());
+
+ if (existingSession == null) {
+ sessions.add(authInfo);
+ } else {
+ authenticationInformation.setSessionId(
+ ESSessionIdImpl.class.cast(existingSession).toInternalAPI());
+ }
final ACUser resolvedUser = (ACUser) ESUserImpl.class.cast(
orgUnitResolver.resolveRoles(authInfo))
.toInternalAPI();
- final AuthenticationInformation authenticationInformation = ESAuthenticationInformationImpl.class.cast(
- authInfo).toInternalAPI();
-
authenticationInformation.setResolvedACUser(resolvedUser);
return authInfo;
}
diff --git a/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/server/auth/ESSessions.java b/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/server/auth/ESSessions.java
index 0f70a51..0a11acb 100644
--- a/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/server/auth/ESSessions.java
+++ b/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/server/auth/ESSessions.java
@@ -40,7 +40,12 @@
*/
public class ESSessions {
- private final Map<SessionId, ACUserContainer> sessionUserMap;
+ /**
+ * Map holding valid session IDs and the respective users.
+ *
+ * @since 1.9
+ */
+ protected final Map<SessionId, ACUserContainer> sessionUserMap;
/**
* Default constructor.
diff --git a/tests/org.eclipse.emf.emfstore.client.test/src/org/eclipse/emf/emfstore/internal/client/test/workspace/AllWorkspaceTests.java b/tests/org.eclipse.emf.emfstore.client.test/src/org/eclipse/emf/emfstore/internal/client/test/workspace/AllWorkspaceTests.java
index 14901c3..7d73961 100644
--- a/tests/org.eclipse.emf.emfstore.client.test/src/org/eclipse/emf/emfstore/internal/client/test/workspace/AllWorkspaceTests.java
+++ b/tests/org.eclipse.emf.emfstore.client.test/src/org/eclipse/emf/emfstore/internal/client/test/workspace/AllWorkspaceTests.java
@@ -16,6 +16,7 @@
@RunWith(Suite.class)
@Suite.SuiteClasses({
+ SessionTest.class,
WorkspaceTest.class,
ThreadLocalWorkSpaceTest.class
})
diff --git a/tests/org.eclipse.emf.emfstore.client.test/src/org/eclipse/emf/emfstore/internal/client/test/workspace/SessionTest.java b/tests/org.eclipse.emf.emfstore.client.test/src/org/eclipse/emf/emfstore/internal/client/test/workspace/SessionTest.java
new file mode 100644
index 0000000..df9697b
--- /dev/null
+++ b/tests/org.eclipse.emf.emfstore.client.test/src/org/eclipse/emf/emfstore/internal/client/test/workspace/SessionTest.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2017 EclipseSource Muenchen GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Edgar Mueller - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emf.emfstore.internal.client.test.workspace;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.emf.emfstore.client.test.common.cases.ESTestWithLoggedInUser;
+import org.eclipse.emf.emfstore.server.exceptions.ESException;
+import org.eclipse.emf.emfstore.server.model.ESSessionId;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SessionTest extends ESTestWithLoggedInUser {
+
+ @BeforeClass
+ public static void beforeClass() {
+ startEMFStore();
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ stopEMFStore();
+ }
+
+ @Test
+ public void stableSessionIdIfLoggedIn() throws ESException {
+ final ESSessionId sessionId = getUsersession().getSessionId();
+ getUsersession().refresh();
+ final ESSessionId sessionId2 = getUsersession().getSessionId();
+ assertEquals(sessionId, sessionId2);
+ }
+}