FELIX-3777: simplify RoleRepositoryStore API.
- allow any kind of exception to be thrown from the store implementation;
- remove the need for initialize() and close(). Stores needing to initialize
themselves do so by using the standard OSGi lifecycle methods;
- allow the store to directly filter for roles;
- several other dings and dents fixed.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1412574 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/ResettableTimer.java b/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/ResettableTimer.java
index b093e44..512e8a8 100644
--- a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/ResettableTimer.java
+++ b/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/ResettableTimer.java
@@ -76,6 +76,15 @@
}
/**
+ * Returns the state of this timer.
+ *
+ * @return <code>true</code> if this timer is shut down, <code>false</code> otherwise.
+ */
+ public boolean isShutDown() {
+ return m_executor.isShutdown();
+ }
+
+ /**
* Schedules the task for execution with the contained timeout. If a task
* is already pending or running, it will be cancelled (not interrupted).
* The new task will be scheduled to run in now + timeout.
diff --git a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStore.java b/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStore.java
index 115d223..071cbba 100644
--- a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStore.java
+++ b/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStore.java
@@ -86,10 +86,6 @@
}
}
- public void initialize() throws IOException {
- m_entries.putAll(retrieve());
- }
-
public void roleChanged(UserAdminEvent event) {
scheduleTask();
}
@@ -110,25 +106,30 @@
}
/**
+ * Starts this store by reading the latest version from disk.
+ *
+ * @throws IOException in case of I/O problems retrieving the store.
+ */
+ public void start() throws IOException {
+ m_entries.putAll(retrieve());
+ }
+
+ /**
* Stops this store service.
*/
- public void stop() {
+ public void stop() throws IOException {
ResettableTimer timer = (ResettableTimer) m_timerRef.get();
if (timer != null) {
- // Shutdown and await termination...
- timer.shutDown();
+ if (!timer.isShutDown()) {
+ // Shutdown and await termination...
+ timer.shutDown();
+ }
// Clear reference...
m_timerRef.compareAndSet(timer, null);
}
-
- try {
- // Write the latest version to disk...
- flush();
- }
- catch (IOException e) {
- // Nothing we can do about this here...
- e.printStackTrace();
- }
+
+ // Write the latest version to disk...
+ flush();
}
/**
@@ -198,6 +199,9 @@
} catch (FileNotFoundException exception) {
// Don't bother; file does not exist...
return Collections.emptyMap();
+ } catch (IOException exception) {
+ exception.printStackTrace();
+ throw exception;
} finally {
closeSafely(is);
}
@@ -251,7 +255,7 @@
*/
private void scheduleTask() {
ResettableTimer timer = (ResettableTimer) m_timerRef.get();
- if (timer != null) {
+ if (timer != null && !timer.isShutDown()) {
timer.schedule();
}
}
diff --git a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositoryMemoryStore.java b/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositoryMemoryStore.java
index f064f79..c89ecdb 100644
--- a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositoryMemoryStore.java
+++ b/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositoryMemoryStore.java
@@ -16,12 +16,16 @@
*/
package org.apache.felix.useradmin.filestore;
-import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import org.apache.felix.useradmin.RoleFactory;
import org.apache.felix.useradmin.RoleRepositoryStore;
+import org.osgi.framework.Filter;
import org.osgi.service.useradmin.Role;
@@ -32,39 +36,44 @@
protected final ConcurrentMap m_entries = new ConcurrentHashMap();
- public boolean addRole(Role role) throws IOException {
- if (role == null) {
- throw new IllegalArgumentException("Role cannot be null!");
+ public Role addRole(String roleName, int type) {
+ if (roleName == null) {
+ throw new IllegalArgumentException("Name cannot be null!");
}
- Object result = m_entries.putIfAbsent(role.getName(), role);
- return result == null;
+ Role role = RoleFactory.createRole(type, roleName);
+ Object result = m_entries.putIfAbsent(roleName, role);
+ return (result == null) ? role : null;
}
- public void close() throws IOException {
- // Nop
- }
-
- public Role[] getAllRoles() throws IOException {
+ public Role[] getRoles(Filter filter) {
Collection roles = m_entries.values();
- Role[] result = new Role[roles.size()];
- return (Role[]) roles.toArray(result);
+
+ List matchingRoles = new ArrayList();
+ Iterator rolesIter = roles.iterator();
+ while (rolesIter.hasNext()) {
+ Role role = (Role) rolesIter.next();
+ if ((filter == null) || filter.match(role.getProperties())) {
+ matchingRoles.add(role);
+ }
+ }
+
+ Role[] result = new Role[matchingRoles.size()];
+ return (Role[]) matchingRoles.toArray(result);
}
- public Role getRoleByName(String roleName) throws IOException {
+ public Role getRoleByName(String roleName) {
if (roleName == null) {
throw new IllegalArgumentException("Role name cannot be null!");
}
return (Role) m_entries.get(roleName);
}
-
- public void initialize() throws IOException {
- // Nop
- }
- public boolean removeRole(Role role) throws IOException {
- if (role == null) {
- throw new IllegalArgumentException("Role cannot be null!");
+ public Role removeRole(String roleName) {
+ if (roleName == null) {
+ throw new IllegalArgumentException("Name cannot be null!");
}
- return m_entries.remove(role.getName(), role);
+ Role role = getRoleByName(roleName);
+ boolean result = m_entries.remove(roleName, role);
+ return result ? role : null;
}
}
diff --git a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositorySerializer.java b/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositorySerializer.java
index 57aca3e..e4ecaad 100644
--- a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositorySerializer.java
+++ b/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositorySerializer.java
@@ -161,6 +161,23 @@
}
/**
+ * Returns the role with the given name from the given repository.
+ *
+ * @param repository the repository to obtain the roles from, cannot be <code>null</code>;
+ * @param name the name of the role to retrieve, cannot be <code>null</code>.
+ * @return a role matching the given name, or <code>null</code> if no such role exists.
+ */
+ private Role getRoleFromRepository(Map repository, String name) {
+ Role role;
+ if (Role.USER_ANYONE.equals(name)) {
+ role = RoleFactory.createRole(Role.USER_ANYONE);
+ } else {
+ role = (Role) repository.get(name);
+ }
+ return role;
+ }
+
+ /**
* Reads and fills a given dictionary.
*
* @param dict the dictionary to read & fill, cannot be <code>null</code>;
@@ -188,7 +205,7 @@
}
}
}
-
+
/**
* Reads a (stub) group from the given input stream.
*
@@ -254,7 +271,7 @@
return repository;
}
-
+
/**
* Reads a role from the given input stream.
*
@@ -269,7 +286,7 @@
return role;
}
-
+
/**
* Reads a user from the given input stream.
*
@@ -300,7 +317,7 @@
for (int i = 0; i < size; i++) {
String name = (String) names.get(i);
- Role role = (Role) repository.get(name);
+ Role role = getRoleFromRepository(repository, name);
if (role == null) {
throw new IOException("Unable to find referenced basic member: " + name);
}
@@ -312,7 +329,7 @@
for (int i = 0; i < size; i++) {
String name = (String) names.get(i);
- Role role = (Role) repository.get(name);
+ Role role = getRoleFromRepository(repository, name);
if (role == null) {
throw new IOException("Unable to find referenced required member: " + name);
}
diff --git a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/osgi/Activator.java b/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/osgi/Activator.java
index edef63c..a63223f 100644
--- a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/osgi/Activator.java
+++ b/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/osgi/Activator.java
@@ -35,6 +35,7 @@
public void start(BundleContext context) throws Exception {
m_store = new RoleRepositoryFileStore(context.getDataFile(""));
+ m_store.start();
String[] interfaces = { RoleRepositoryStore.class.getName(), UserAdminListener.class.getName(), ManagedService.class.getName() };
diff --git a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStorePerformanceTest.java b/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStorePerformanceTest.java
index c19699f..11bd35e 100644
--- a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStorePerformanceTest.java
+++ b/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStorePerformanceTest.java
@@ -22,9 +22,7 @@
import junit.framework.TestCase;
-import org.apache.felix.useradmin.impl.RoleRepository;
-import org.apache.felix.useradmin.impl.role.GroupImpl;
-import org.apache.felix.useradmin.impl.role.UserImpl;
+import org.apache.felix.useradmin.RoleFactory;
import org.osgi.service.useradmin.Group;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.User;
@@ -34,9 +32,10 @@
*/
public class RoleRepositoryFileStorePerformanceTest extends TestCase {
- private static final int USER_COUNT = 15000;
+ private static final int USER_COUNT = 25000;
private static final int GROUP_COUNT = 500;
+ private Role m_anyone;
private Group[] m_groups;
private User[] m_users;
@@ -60,14 +59,14 @@
* Does a very simple performance test for a large number of users spread over several groups.
*/
protected void readRepositoryPerformanceTest() throws Exception {
- long r_st = System.currentTimeMillis();
+ long r_st = System.nanoTime();
Map result = m_store.retrieve();
- long r_time = System.currentTimeMillis() - r_st;
+ long r_time = System.nanoTime() - r_st;
assertNotNull(result);
assertEquals(GROUP_COUNT + USER_COUNT + 1, result.size());
- System.out.println("Read time : " + (r_time / 1000.0) + "s.");
+ System.out.println("Read time : " + (r_time / 1.0e9) + "s.");
}
/**
@@ -79,19 +78,20 @@
m_store = new RoleRepositoryFileStore(new File(System.getProperty("java.io.tmpdir")), false /* disable background writes */);
m_repository = new HashMap(USER_COUNT + GROUP_COUNT + 1);
+ m_anyone = RoleFactory.createRole(Role.USER_ANYONE);
- addToRepository(RoleRepository.USER_ANYONE);
+ addToRepository(m_anyone);
}
/**
* Does a very simple performance test for writing a large number of users spread over several groups.
*/
protected void writeRepositoryPerformanceTest() throws Exception {
- long w_st = System.currentTimeMillis();
+ long w_st = System.nanoTime();
m_store.store(m_repository);
- long w_time = System.currentTimeMillis() - w_st;
+ long w_time = System.nanoTime() - w_st;
- System.out.println("Write time: " + (w_time / 1000.0) + "s.");
+ System.out.println("Write time: " + (w_time / 1.0e9) + "s.");
}
private void addToRepository(Role role) {
@@ -105,7 +105,7 @@
m_groups = new Group[GROUP_COUNT];
for (int i = 0; i < m_groups.length; i++) {
m_groups[i] = createGroup(i+1);
- m_groups[i].addRequiredMember(RoleRepository.USER_ANYONE);
+ m_groups[i].addRequiredMember(m_anyone);
addToRepository(m_groups[i]);
}
@@ -124,7 +124,7 @@
private Group createGroup(int idx) {
String name = "Group" + idx;
- Group result = new GroupImpl(name);
+ Group result = RoleFactory.createGroup(name);
setCredentials(result);
setProperties(result);
@@ -135,7 +135,7 @@
private User createUser(int idx) {
String name = "User" + idx;
- User result = new UserImpl(name);
+ User result = RoleFactory.createUser(name);
setCredentials(result);
setProperties(result);
diff --git a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositorySerializerTest.java b/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositorySerializerTest.java
index 5f1aadb..a6567ff 100644
--- a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositorySerializerTest.java
+++ b/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositorySerializerTest.java
@@ -31,9 +31,7 @@
import junit.framework.TestCase;
-import org.apache.felix.useradmin.impl.RoleRepository;
-import org.apache.felix.useradmin.impl.role.GroupImpl;
-import org.apache.felix.useradmin.impl.role.UserImpl;
+import org.apache.felix.useradmin.RoleFactory;
import org.osgi.service.useradmin.Group;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.User;
@@ -70,7 +68,6 @@
m_group3.addMember(m_user4);
m_group3.addRequiredMember(m_userAnyone);
- addToRepository(m_userAnyone);
addToRepository(m_user1);
addToRepository(m_user2);
addToRepository(m_user3);
@@ -90,8 +87,7 @@
Map result = m_serializer.deserialize(dis);
assertNotNull(result);
- assertEquals(8, result.size());
- assertEquals(m_userAnyone, (Role) result.get(m_userAnyone.getName()));
+ assertEquals(7, result.size());
assertEquals(m_user1, (User) result.get(m_user1.getName()));
assertEquals(m_user2, (User) result.get(m_user2.getName()));
assertEquals(m_user3, (User) result.get(m_user3.getName()));
@@ -124,11 +120,9 @@
}
/**
- * Tests that writing and reading a repository with a single role works as expected.
+ * Tests that writing and reading a repository without roles works as expected.
*/
- public void testRWRepositoryWithSingleRoleOk() throws Exception {
- addToRepository(m_userAnyone);
-
+ public void testRWRepositoryWithoutRolesOk() throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
@@ -140,9 +134,7 @@
Map result = m_serializer.deserialize(dis);
assertNotNull(result);
- assertEquals(1, result.size());
-
- assertEquals(m_userAnyone, (Role) result.get(m_userAnyone.getName()));
+ assertEquals(0, result.size());
}
/**
@@ -226,8 +218,7 @@
m_group1.addMember(m_userAnyone);
m_group1.addRequiredMember(m_user1);
- // "Forget" to add the user.anyone!
- addToRepository(m_user1);
+ // "Forget" to add the user1
addToRepository(m_group1);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -254,8 +245,7 @@
m_group1.addRequiredMember(m_userAnyone);
m_group1.addMember(m_user1);
- // "Forget" to add the user.anyone!
- addToRepository(m_user1);
+ // "Forget" to add the user1!
addToRepository(m_group1);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -285,7 +275,7 @@
m_repository = new HashMap();
- m_userAnyone = RoleRepository.USER_ANYONE;
+ m_userAnyone = RoleFactory.createRole(Role.USER_ANYONE);
setProperties(m_userAnyone);
@@ -307,7 +297,9 @@
}
private void addToRepository(Role role) {
- m_repository.put(role.getName(), role);
+ if (!Role.USER_ANYONE.equals(role.getName())) {
+ m_repository.put(role.getName(), role);
+ }
}
private void assertEquals(Dictionary expected, Dictionary obtained) {
@@ -380,7 +372,7 @@
private User createUser(int idx) {
String name = "User" + idx;
- User result = new UserImpl(name);
+ User result = RoleFactory.createUser(name);
setCredentials(result);
setProperties(result);
@@ -391,7 +383,7 @@
private Group createGroup(int idx) {
String name = "Group" + idx;
- Group result = new GroupImpl(name);
+ Group result = RoleFactory.createGroup(name);
setCredentials(result);
setProperties(result);
diff --git a/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/BaseIntegrationTest.java b/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/BaseIntegrationTest.java
index 6cf080a..39cc8e4 100644
--- a/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/BaseIntegrationTest.java
+++ b/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/BaseIntegrationTest.java
@@ -38,6 +38,7 @@
import org.ops4j.pax.exam.junit.Configuration;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.service.useradmin.UserAdmin;
import org.osgi.util.tracker.ServiceTracker;
/**
@@ -77,7 +78,7 @@
url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.framework.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
url("link:classpath:META-INF/links/org.apache.geronimo.specs.atinject.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
- mavenBundle("org.osgi", "org.osgi.core").version("4.2.0").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+// mavenBundle("org.osgi", "org.osgi.core").version("4.2.0").startLevel(START_LEVEL_SYSTEM_BUNDLES),
mavenBundle("org.osgi", "org.osgi.compendium").version("4.2.0").startLevel(START_LEVEL_SYSTEM_BUNDLES),
mavenBundle("org.apache.felix", "org.apache.felix.log").version("1.0.1").startLevel(START_LEVEL_SYSTEM_BUNDLES),
mavenBundle("org.apache.felix", ORG_APACHE_FELIX_USERADMIN).version("1.0.3-SNAPSHOT").startLevel(START_LEVEL_SYSTEM_BUNDLES),
@@ -130,6 +131,13 @@
}
return result;
}
+
+ /**
+ * @return the {@link UserAdmin} service instance.
+ */
+ protected UserAdmin getUserAdmin() throws Exception {
+ return getService(UserAdmin.class.getName());
+ }
/**
* @param bsn
diff --git a/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/FileStoreInitializationTest.java b/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/FileStoreInitializationTest.java
index bfb8529..0b712b8 100644
--- a/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/FileStoreInitializationTest.java
+++ b/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/FileStoreInitializationTest.java
@@ -21,17 +21,16 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
-import java.io.IOException;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.felix.useradmin.RoleRepositoryStore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.framework.Bundle;
-import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.useradmin.Group;
import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdmin;
/**
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
@@ -40,92 +39,62 @@
public class FileStoreInitializationTest extends BaseIntegrationTest {
/**
- * Provides a mock file store that does nothing but track the number of
- * times the {@link #initialize()} and {@link #close()} methods are called.
- */
- public static class MockRoleRepositoryStore implements RoleRepositoryStore {
-
- final AtomicInteger m_initCount = new AtomicInteger(0);
- final AtomicInteger m_closeCount = new AtomicInteger(0);
-
- @Override
- public boolean addRole(Role role) throws IOException {
- return false;
- }
-
- @Override
- public void close() throws IOException {
- m_closeCount.incrementAndGet();
- }
-
- @Override
- public Role[] getAllRoles() throws IOException {
- return null;
- }
-
- @Override
- public Role getRoleByName(String roleName) throws IOException {
- return null;
- }
-
- @Override
- public void initialize() throws IOException {
- m_initCount.incrementAndGet();
- }
-
- @Override
- public boolean removeRole(Role role) throws IOException {
- return false;
- }
- }
-
- /**
* Tests that initialization and closing of the repository store is
* performed correctly.
*/
@Test
public void testStoreIsInitializedAndClosedProperlyOk() throws Exception {
- final String serviceName = RoleRepositoryStore.class.getName();
- final MockRoleRepositoryStore mockStore = new MockRoleRepositoryStore();
+ UserAdmin ua = getUserAdmin();
+
+ // Create two roles...
+ User user = (User) ua.createRole("user1", Role.USER);
+ assertNotNull(user);
+
+ Group group = (Group) ua.createRole("group1", Role.GROUP);
+ assertNotNull(group);
+
+ group.addMember(user);
+ group.addRequiredMember(ua.getRole(Role.USER_ANYONE));
- // Stop the file store...
+ // Stop the file store; should persist the two roles...
Bundle fileStoreBundle = findBundle(ORG_APACHE_FELIX_USERADMIN_FILESTORE);
assertNotNull(fileStoreBundle);
fileStoreBundle.stop();
- // Manually register our mock store...
- ServiceRegistration serviceReg = m_context.registerService(serviceName, mockStore, null);
+ Thread.sleep(100); // Wait a little until the bundle is really stopped...
+
+ // Retrieve the roles again; should both yield null due to the store not being available...
+ user = (User) ua.getRole("user1");
+ assertNull(user);
- // Wait until it becomes available...
- awaitService(serviceName);
+ group = (Group) ua.getRole("group1");
+ assertNull(group);
+
+ // This will not succeed: no backend to store the user in...
+ assertNull(ua.createRole("user2", Role.USER));
- assertEquals(1, mockStore.m_initCount.get());
- assertEquals(0, mockStore.m_closeCount.get());
+ fileStoreBundle.start();
- serviceReg.unregister();
+ awaitService(ORG_APACHE_FELIX_USERADMIN_FILESTORE);
+
+ // Retrieve the roles again; should both yield valid values...
+ user = (User) ua.getRole("user1");
+ assertNotNull(user);
+
+ group = (Group) ua.getRole("group1");
+ assertNotNull(group);
- Thread.sleep(100); // sleep a tiny bit to allow service to be properly unregistered...
+ Role[] members = group.getMembers();
+ assertNotNull(members);
+ assertEquals(1, members.length);
+ assertEquals("user1", members[0].getName());
- assertEquals(1, mockStore.m_initCount.get());
- assertEquals(1, mockStore.m_closeCount.get());
-
- // Re-register the service again...
- serviceReg = m_context.registerService(serviceName, mockStore, null);
-
- assertEquals(2, mockStore.m_initCount.get());
- assertEquals(1, mockStore.m_closeCount.get());
-
- // Stop & start the UserAdmin bundle to verify the initialization is
- // still only performed once...
- Bundle userAdminBundle = findBundle(ORG_APACHE_FELIX_USERADMIN);
- assertNotNull(userAdminBundle);
- userAdminBundle.stop();
-
- Thread.sleep(100); // sleep a tiny bit to allow service to be properly unregistered...
-
- userAdminBundle.start();
-
- assertEquals(3, mockStore.m_initCount.get());
- assertEquals(2, mockStore.m_closeCount.get());
+ members = group.getRequiredMembers();
+ assertNotNull(members);
+ assertEquals(1, members.length);
+ assertEquals(Role.USER_ANYONE, members[0].getName());
+
+ user = (User) ua.getRole("user2");
+ assertNull(user);
}
}
diff --git a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoDBStore.java b/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoDBStore.java
index 5dc1719..8761ea6 100644
--- a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoDBStore.java
+++ b/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoDBStore.java
@@ -19,13 +19,13 @@
import static org.apache.felix.useradmin.mongodb.MongoSerializerHelper.NAME;
import static org.apache.felix.useradmin.mongodb.MongoSerializerHelper.TYPE;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.felix.useradmin.RoleRepositoryStore;
+import org.osgi.framework.Filter;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.log.LogService;
@@ -124,71 +124,57 @@
}
@Override
- public boolean addRole(Role role) throws IOException {
- if (role == null) {
+ public Role addRole(String roleName, int type) throws MongoException {
+ if (roleName == null) {
throw new IllegalArgumentException("Role cannot be null!");
}
- try {
- DBCollection coll = getCollection();
-
- DBCursor cursor = coll.find(getTemplateObject(role));
- try {
- if (cursor.hasNext()) {
- // Role already exists...
- return false;
- }
- } finally {
- cursor.close();
- }
-
- // Role does not exist; insert it...
- DBObject data = m_helper.serialize(role);
-
- WriteResult result = coll.insert(data);
-
- if (result.getLastError() != null) {
- result.getLastError().throwOnError();
- }
+ DBCollection coll = getCollection();
- return true;
+ Role role = getRole(roleName);
+ if (role != null) {
+ return null;
}
- catch (MongoException e) {
- m_log.log(LogService.LOG_WARNING, "Add role failed!", e);
- throw new IOException("AddRole failed!", e);
+
+ // Role does not exist; insert it...
+ DBObject data = m_helper.serialize(roleName, type);
+
+ WriteResult result = coll.insert(data);
+
+ if (result.getLastError() != null) {
+ result.getLastError().throwOnError();
}
+
+ return role;
}
- @Override
- public void close() throws IOException {
+ /**
+ * Closes this store and disconnects from the MongoDB backend.
+ */
+ public void close() {
MongoDB mongoDB = m_mongoDbRef.get();
if (mongoDB != null) {
mongoDB.disconnect();
}
+ m_mongoDbRef.set(null);
}
@Override
- public Role[] getAllRoles() throws IOException {
+ public Role[] getRoles(Filter filter) throws MongoException {
+ List<Role> roles = new ArrayList<Role>();
+
+ DBCollection coll = getCollection();
+
+ DBCursor cursor = coll.find();
try {
- List<Role> roles = new ArrayList<Role>();
-
- DBCollection coll = getCollection();
-
- DBCursor cursor = coll.find();
- try {
- while (cursor.hasNext()) {
- roles.add(m_helper.deserialize(cursor.next()));
- }
- } finally {
- cursor.close();
+ while (cursor.hasNext()) {
+ roles.add(m_helper.deserialize(cursor.next()));
}
+ } finally {
+ cursor.close();
+ }
- return roles.toArray(new Role[roles.size()]);
- }
- catch (MongoException e) {
- m_log.log(LogService.LOG_WARNING, "Get all roles failed!", e);
- throw new IOException("GetAllRoles failed!", e);
- }
+ return roles.toArray(new Role[roles.size()]);
}
@Override
@@ -208,56 +194,26 @@
}
@Override
- public Role getRoleByName(String name) throws IOException {
- try {
- return getRole(name);
- }
- catch (MongoException e) {
- m_log.log(LogService.LOG_WARNING, "Get role by name failed!", e);
- throw new IOException("GetRoleByName failed!", e);
- }
- }
-
- @Override
- public void initialize() throws IOException {
- // Check whether we need to connect to MongoDB, or that this is
- // already done by the #updated method...
- MongoDB oldMongoDB = m_mongoDbRef.get();
- if (oldMongoDB == null) {
- MongoDB mongoDB = new MongoDB(DEFAULT_MONGODB_SERVER, DEFAULT_MONGODB_DBNAME, DEFAULT_MONGODB_COLLECTION);
-
- do {
- oldMongoDB = m_mongoDbRef.get();
- }
- while (!m_mongoDbRef.compareAndSet(oldMongoDB, mongoDB));
-
- try {
- connectToDB(mongoDB, DEFAULT_MONGODB_USERNAME, DEFAULT_MONGODB_PASSWORD);
- }
- catch (MongoException e) {
- m_log.log(LogService.LOG_WARNING, "Initialization failed!", e);
- throw new IOException("Initialization failed!", e);
- }
- }
+ public Role getRoleByName(String name) throws MongoException {
+ return getRole(name);
}
@Override
- public boolean removeRole(Role role) throws IOException {
- try {
- DBCollection coll = getCollection();
-
- WriteResult result = coll.remove(getTemplateObject(role));
-
- if (result.getLastError() != null) {
- result.getLastError().throwOnError();
- }
-
- return true;
+ public Role removeRole(String roleName) throws MongoException {
+ DBCollection coll = getCollection();
+
+ Role role = getRole(roleName);
+ if (role == null) {
+ return null;
}
- catch (MongoException e) {
- m_log.log(LogService.LOG_WARNING, "Remove role failed!", e);
- throw new IOException("RemoveRole failed!", e);
+
+ WriteResult result = coll.remove(getTemplateObject(role));
+
+ if (result.getLastError() != null) {
+ result.getLastError().throwOnError();
}
+
+ return role;
}
@Override
@@ -394,8 +350,8 @@
*/
private DBObject getTemplateObject(Role role) {
BasicDBObject query = new BasicDBObject();
- query.put(TYPE, role.getType());
query.put(NAME, role.getName());
+ query.put(TYPE, role.getType());
return query;
}
diff --git a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoSerializerHelper.java b/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoSerializerHelper.java
index 31af118..48e48d8 100644
--- a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoSerializerHelper.java
+++ b/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoSerializerHelper.java
@@ -115,6 +115,22 @@
return data;
}
+
+ /**
+ * Creates a {@link DBObject} with the given role and name.
+ *
+ * @param roleName the name of the role to serialize, cannot be <code>null</code> or empty (unchecked!);
+ * @param type the type of the role to serialize.
+ * @return a {@link DBObject} representing the role with the given name and type, never <code>null</code>.
+ */
+ public DBObject serialize(String roleName, int type) {
+ BasicDBObject data = new BasicDBObject();
+
+ data.put(TYPE, type);
+ data.put(NAME, roleName);
+
+ return data;
+ }
/**
* Creates a serialized version of the given {@link Role} to be used in an update statement.
diff --git a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/osgi/Activator.java b/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/osgi/Activator.java
index 632af63..b2eeee9 100644
--- a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/osgi/Activator.java
+++ b/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/osgi/Activator.java
@@ -32,26 +32,30 @@
public class Activator implements BundleActivator {
private LogServiceHelper m_logServiceHelper;
+ private MongoDBStore m_store;
@Override
public void start(BundleContext context) throws Exception {
m_logServiceHelper = new LogServiceHelper(context);
m_logServiceHelper.open();
- MongoDBStore store = new MongoDBStore();
- store.setLogService(m_logServiceHelper);
+ m_store = new MongoDBStore();
+ m_store.setLogService(m_logServiceHelper);
Properties props = new Properties();
props.put(Constants.SERVICE_PID, MongoDBStore.PID);
- String[] serviceNames = { RoleRepositoryStore.class.getName(),
- UserAdminListener.class.getName(), ManagedService.class.getName() };
+ String[] serviceNames = { RoleRepositoryStore.class.getName(), UserAdminListener.class.getName(), ManagedService.class.getName() };
- context.registerService(serviceNames, store, props);
+ context.registerService(serviceNames, m_store, props);
}
@Override
public void stop(BundleContext context) throws Exception {
+ if (m_store != null) {
+ m_store.close();
+ m_store = null;
+ }
if (m_logServiceHelper != null) {
m_logServiceHelper.close();
m_logServiceHelper = null;
diff --git a/useradmin/useradmin/pom.xml b/useradmin/useradmin/pom.xml
index 7531d23..3c4576d 100644
--- a/useradmin/useradmin/pom.xml
+++ b/useradmin/useradmin/pom.xml
@@ -32,12 +32,6 @@
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- <version>4.0.0</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>4.0.0</version>
</dependency>
@@ -45,7 +39,6 @@
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>4.0.2</version>
- <scope>test</scope>
</dependency>
</dependencies>
<build>
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/RoleFactory.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/RoleFactory.java
index da54c9e..b145db6 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/RoleFactory.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/RoleFactory.java
@@ -20,7 +20,9 @@
import org.apache.felix.useradmin.impl.role.GroupImpl;
import org.apache.felix.useradmin.impl.role.RoleImpl;
import org.apache.felix.useradmin.impl.role.UserImpl;
+import org.osgi.service.useradmin.Group;
import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
/**
* Provides a factory for creating the various role instances, can be used by external
@@ -29,18 +31,21 @@
public final class RoleFactory {
/**
- * Creates a new instance of {@link RoleFactory}, not used.
+ * Creates a new group-role instance.
+ *
+ * @param name the name of the group to create.
+ * @return a new {@link Group} instance denoting the requested role, never <code>null</code>.
*/
- private RoleFactory() {
- // Nop
+ public static Group createGroup(String name) {
+ return (Group) createRole(Role.GROUP, name);
}
/**
- * Creates a new role instance.
+ * Creates a new role instance with the given type and name.
*
* @param type the type of the role to create;
* @param name the name of the role to create.
- * @return a new {@link RoleImpl} instance denoting the requested role, never <code>null</code>.
+ * @return a new {@link Role} instance denoting the requested role, never <code>null</code>.
*/
public static Role createRole(int type, String name) {
if (type == Role.USER) {
@@ -54,4 +59,32 @@
return result;
}
}
+
+ /**
+ * Creates a new role instance.
+ *
+ * @param type the type of the role to create;
+ * @param name the name of the role to create.
+ * @return a new {@link Role} instance denoting the requested role, never <code>null</code>.
+ */
+ public static Role createRole(String name) {
+ return createRole(Role.ROLE, name);
+ }
+
+ /**
+ * Creates a new user-role instance.
+ *
+ * @param name the name of the user to create.
+ * @return a new {@link User} instance denoting the requested role, never <code>null</code>.
+ */
+ public static User createUser(String name) {
+ return (User) createRole(Role.USER, name);
+ }
+
+ /**
+ * Creates a new instance of {@link RoleFactory}, not used.
+ */
+ private RoleFactory() {
+ // Nop
+ }
}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/RoleRepositoryStore.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/RoleRepositoryStore.java
index 3296f59..365e273 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/RoleRepositoryStore.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/RoleRepositoryStore.java
@@ -16,79 +16,68 @@
*/
package org.apache.felix.useradmin;
-import java.io.Closeable;
-import java.io.IOException;
-
+import org.osgi.framework.Filter;
import org.osgi.service.useradmin.Role;
/**
* Provides an abstraction to store and retrieve a role repository.
+ * <p>
+ * The role object returned by this backend <em>can</em> be a different
+ * implementation than <tt>org.apache.felix.useradmin.impl.role.RoleImpl</tt>,
+ * in which case the backend is made fully responsible for keeping track of the
+ * changes in the role object and persisting them!
+ * </p>
*/
-public interface RoleRepositoryStore extends Closeable {
-
+public interface RoleRepositoryStore {
+
/**
* Adds a given role to this backend.
* <p>
* If the given role is already contained by this backed, this method
- * should not do anything and return <code>false</code> to denote this.
+ * should not do anything and return <code>null</code> to denote this.
* </p>
*
- * @param role the role to add, cannot be <code>null</code>.
- * @return <code>true</code> if the role was successfully added, <code>false</code> otherwise.
- * @throws IllegalArgumentException in case the given argument was <code>null</code>;
- * @throws IOException in case of I/O problems.
+ * @param roleName the name of the role to add, cannot be <code>null</code>;
+ * @param type the type of role to add, either {@link Role#USER} or {@link Role#GROUP}.
+ * @return the role added, or <code>null</code> in case the role already
+ * exists.
+ * @throws IllegalArgumentException in case the given name was <code>null</code>;
+ * @throws Exception in case of problems adding the role.
*/
- boolean addRole(Role role) throws IOException;
+ Role addRole(String roleName, int type) throws Exception;
/**
- * Closes this store, allowing implementations to free up resources, close
- * connections, and so on.
+ * Returns all roles in this backend matching the given filter criteria.
*
- * @throws IOException in case of I/O problems.
- */
- void close() throws IOException;
-
- /**
- * Returns all available roles in this backend.
- *
+ * @param filter the optional filter to apply, can be <code>null</code> in which case all roles are to be returned.
* @return an array with all roles, never <code>null</code>, but can be empty.
- * @throws IOException in case of I/O problems.
+ * @throws Exception in case of problems retrieving the set of roles.
*/
- Role[] getAllRoles() throws IOException;
-
+ Role[] getRoles(Filter filter) throws Exception;
+
/**
* Returns a {@link Role} by its name.
*
* @param roleName the name of the role to return, cannot be <code>null</code>.
* @return the role with the given name, or <code>null</code> if no such role exists.
* @throws IllegalArgumentException in case the given argument was <code>null</code>;
- * @throws IOException in case of I/O problems.
+ * @throws Exception in case of problems retrieving the requested role.
*/
- Role getRoleByName(String roleName) throws IOException;
-
- /**
- * Called once before any other method of this interface is being called.
- * <p>
- * Implementations can use this method to create a connection to the
- * backend, or load the initial set of roles, and so on.
- * </p>
- *
- * @throws IOException in case of I/O problems.
- */
- void initialize() throws IOException;
+ Role getRoleByName(String roleName) throws Exception;
/**
* Removes a given role from this backend.
* <p>
* If the given role is not contained by this backed, this method
- * should not do anything and return <code>false</code> to denote this.
+ * should not do anything and return <code>null</code> to denote this.
* </p>
*
- * @param role the role to remove, cannot be <code>null</code>.
- * @return <code>true</code> if the role was successfully removed, <code>false</code> otherwise.
+ * @param roleName the name of the role to remove, cannot be <code>null</code>.
+ * @return the removed role, if it was successfully removed from this
+ * backend, or <code>null</code> if the role was not contained by
+ * this backend or could not be removed.
* @throws IllegalArgumentException in case the given argument was <code>null</code>;
- * @throws IOException in case of I/O problems.
+ * @throws Exception in case of problems removing the requested role.
*/
- boolean removeRole(Role role) throws IOException;
-
+ Role removeRole(String roleName) throws Exception;
}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/RoleRepository.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/RoleRepository.java
index b9666db..54c8f80 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/RoleRepository.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/RoleRepository.java
@@ -14,12 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.felix.useradmin.impl;
-import java.io.IOException;
import java.util.ArrayList;
-import java.util.Dictionary;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -27,8 +24,9 @@
import org.apache.felix.useradmin.BackendException;
import org.apache.felix.useradmin.RoleFactory;
import org.apache.felix.useradmin.RoleRepositoryStore;
-import org.apache.felix.useradmin.impl.role.RoleImpl;
+import org.apache.felix.useradmin.impl.role.ObservableRole;
import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
import org.osgi.service.useradmin.Group;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.UserAdminPermission;
@@ -94,7 +92,7 @@
}
/** The single predefined role. */
- public static final Role USER_ANYONE = RoleFactory.createRole(Role.ROLE, Role.USER_ANYONE);
+ private static final Role USER_ANYONE = RoleFactory.createRole(Role.USER_ANYONE);
private final RoleRepositoryStore m_store;
private final CopyOnWriteArrayList m_listeners;
@@ -118,26 +116,27 @@
* @param role the role to add, cannot be <code>null</code>. If it is already contained by this manager, this method will not do anything.
* @return the given role if added, <code>null</code> otherwise.
*/
- public Role addRole(Role role) {
- if (role == null) {
- throw new IllegalArgumentException("Role cannot be null!");
+ public Role addRole(String name, int type) {
+ if ((name == null) || "".equals(name.trim())) {
+ throw new IllegalArgumentException("Name cannot be null or empty!");
}
- if (!(role instanceof RoleImpl)) {
+ if (type != Role.GROUP && type != Role.USER) {
throw new IllegalArgumentException("Invalid role type!");
}
checkPermissions();
try {
- if (m_store.addRole(role)) {
- m_roleChangeReflector.roleAdded(role);
- return wireChangeListener(role);
+ Role result = m_store.addRole(name, type);
+ if (result != null) {
+ result = wireChangeListener(result);
+ m_roleChangeReflector.roleAdded(result);
}
- return null;
+ return result;
}
- catch (IOException e) {
- throw new BackendException("Adding role " + role.getName() + " failed!", e);
+ catch (Exception e) {
+ throw new BackendException("Adding role " + name + " failed!", e);
}
}
@@ -163,9 +162,15 @@
*/
public Role getRoleByName(String roleName) {
try {
- return wireChangeListener(m_store.getRoleByName(roleName));
+ Role result;
+ if (isPredefinedRole(roleName)) {
+ result = getPredefinedRole(roleName);
+ } else {
+ result = m_store.getRoleByName(roleName);
+ }
+ return wireChangeListener(result);
}
- catch (IOException e) {
+ catch (Exception e) {
throw new BackendException("Failed to get role by name: " + roleName + "!", e);
}
}
@@ -180,15 +185,15 @@
List matchingRoles = new ArrayList();
try {
- Role[] roles = m_store.getAllRoles();
+ Role[] roles = m_store.getRoles(filter);
for (int i = 0; i < roles.length; i++) {
Role role = roles[i];
- if (!isPredefinedRole(role) && ((filter == null) || filter.match(role.getProperties()))) {
+ if (!isPredefinedRole(role.getName())) {
matchingRoles.add(wireChangeListener(role));
}
}
}
- catch (IOException e) {
+ catch (Exception e) {
throw new BackendException("Failed to get roles!", e);
}
@@ -213,16 +218,18 @@
List matchingRoles = new ArrayList();
try {
- Role[] roles = m_store.getAllRoles();
+ String criteria = "(".concat(key).concat("=").concat(value).concat(")");
+ Filter filter = FrameworkUtil.createFilter(criteria);
+
+ Role[] roles = m_store.getRoles(filter);
for (int i = 0; i < roles.length; i++) {
Role role = roles[i];
- Dictionary dict = role.getProperties();
- if (!isPredefinedRole(role) && value.equals(dict.get(key))) {
+ if (!isPredefinedRole(role.getName())) {
matchingRoles.add(wireChangeListener(role));
}
}
}
- catch (IOException e) {
+ catch (Exception e) {
throw new BackendException("Failed to get roles!", e);
}
@@ -235,36 +242,34 @@
* @param role the role to remove, cannot be <code>null</code>.
* @return <code>true</code> if the role was removed (i.e., it was managed by this manager), or <code>false</code> if it was not found.
*/
- public boolean removeRole(Role role) {
- if (role == null) {
- throw new IllegalArgumentException("Role cannot be null!");
- }
- if (!(role instanceof RoleImpl)) {
- throw new IllegalArgumentException("Invalid role type!");
+ public boolean removeRole(String name) {
+ if (name == null) {
+ throw new IllegalArgumentException("Name cannot be null!");
}
checkPermissions();
// Cannot remove predefined roles...
- if (isPredefinedRole(role)) {
+ if (isPredefinedRole(name)) {
return false;
}
try {
- if (m_store.removeRole(role)) {
+ Role result = m_store.removeRole(name);
+ if (result != null) {
// FELIX-3755: Remove the role as (required)member from all groups...
- removeRoleFromAllGroups(role);
+ removeRoleFromAllGroups(result);
- unwireChangeListener(role);
- m_roleChangeReflector.roleRemoved(role);
+ unwireChangeListener(result);
+ m_roleChangeReflector.roleRemoved(result);
return true;
}
return false;
}
- catch (IOException e) {
- throw new BackendException("Failed to remove role " + role.getName() + "!", e);
+ catch (Exception e) {
+ throw new BackendException("Failed to remove role " + name + "!", e);
}
}
@@ -281,33 +286,6 @@
m_listeners.remove(listener);
}
-
- /**
- * Starts this repository.
- */
- public void start() {
- try {
- // The sole predefined role we've got...
- m_store.addRole(USER_ANYONE);
-
- m_store.initialize();
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Stops this repository, allowing it to clean up.
- */
- public void stop() {
- try {
- m_store.close();
- }
- catch (IOException e) {
- // Ignore; nothing we can do about this here...
- }
- }
/**
* Creates a new iterator for iterating over all listeners.
@@ -336,11 +314,22 @@
* Currently, there's only a single predefined role: {@link Role#USER_ANYONE}.
* </p>
*
- * @param role the role to check, may be <code>null</code>.
+ * @param roleName the role name to check, may be <code>null</code>.
* @return <code>true</code> if the given role is predefined, <code>false</code> otherwise.
*/
- private boolean isPredefinedRole(Role role) {
- return Role.USER_ANYONE.equals(role.getName());
+ private boolean isPredefinedRole(String roleName) {
+ return Role.USER_ANYONE.equals(roleName);
+ }
+
+ /**
+ * Returns the predefined role with the given name.
+ *
+ * @param roleName the name of the predefined role to return, cannot be <code>null</code>.
+ * @return a predefined role instance, never <code>null</code>.
+ * @see #isPredefinedRole(String)
+ */
+ private Role getPredefinedRole(String roleName) {
+ return USER_ANYONE;
}
/**
@@ -351,7 +340,7 @@
*/
private void removeRoleFromAllGroups(Role removedRole) {
try {
- Role[] roles = m_store.getAllRoles();
+ Role[] roles = m_store.getRoles(null);
for (int i = 0; i < roles.length; i++) {
if (roles[i].getType() == Role.GROUP) {
Group group = (Group) roles[i];
@@ -361,7 +350,7 @@
}
}
}
- catch (IOException e) {
+ catch (Exception e) {
throw new BackendException("Failed to get all roles!", e);
}
}
@@ -370,10 +359,11 @@
* Unwires the given role to this repository so it no longer listens for its changes.
*
* @param role the role to unwire, cannot be <code>null</code>.
- * @throws IllegalArgumentException in case the given object was not a {@link RoleImpl} instance.
*/
private void unwireChangeListener(Object role) {
- ((RoleImpl) role).setRoleChangeListener(null);
+ if (role instanceof ObservableRole) {
+ ((ObservableRole) role).setRoleChangeListener(null);
+ }
}
/**
@@ -381,12 +371,13 @@
*
* @param role the role to listen for its changes, cannot be <code>null</code>.
* @return the given role.
- * @throws IllegalArgumentException in case the given object was not a {@link RoleImpl} instance.
*/
- private Role wireChangeListener(Object role) {
- RoleImpl result = (RoleImpl) role;
- if (result != null) {
- result.setRoleChangeListener(m_roleChangeReflector);
+ private Role wireChangeListener(Role role) {
+ Role result = ObservableRole.wrap(role);
+ if (result instanceof ObservableRole) {
+ // Keep track of all changes made to the given role, to fire the
+ // proper events to everyone interested...
+ ((ObservableRole) result).setRoleChangeListener(m_roleChangeReflector);
}
return result;
}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/UserAdminImpl.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/UserAdminImpl.java
index 9e51c52..dce1081 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/UserAdminImpl.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/UserAdminImpl.java
@@ -19,7 +19,6 @@
import java.util.List;
-import org.apache.felix.useradmin.RoleFactory;
import org.osgi.framework.Bundle;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
@@ -69,14 +68,7 @@
* {@inheritDoc}
*/
public Role createRole(String name, int type) {
- if ((type != Role.USER) && (type != Role.GROUP)) {
- throw new IllegalArgumentException("Invalid type, must by either Role.USER or Role.GROUP!");
- }
- if (name == null) {
- throw new IllegalArgumentException("Invalid name, must be non-null and non-empty!");
- }
-
- return m_roleRepository.addRole(RoleFactory.createRole(type, name));
+ return m_roleRepository.addRole(name, type);
}
/**
@@ -154,12 +146,7 @@
* {@inheritDoc}
*/
public boolean removeRole(String name) {
- Role role = getRole(name);
- if (role == null) {
- return false;
- }
-
- return m_roleRepository.removeRole(role);
+ return m_roleRepository.removeRole(name);
}
/**
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/GroupImpl.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/GroupImpl.java
index 497cbce..a1a6117 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/GroupImpl.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/GroupImpl.java
@@ -25,14 +25,16 @@
import org.osgi.service.useradmin.UserAdminPermission;
/**
- * Provides an implementation of {@link Group}.
+ * Provides a default implementation of {@link Group} that is not security-aware
+ * and does not keep track of changes to its properties.
+ * <p>
+ * This implementation should be wrapped in an {@link ObservableGroup} when
+ * returned from the UserAdmin implementation.
+ * </p>
*/
public class GroupImpl extends UserImpl implements Group {
- private static final long serialVersionUID = 1515097730006454140L;
-
- private static final String BASIC_MEMBER = "basicMember";
- private static final String REQUIRED_MEMBER = "requiredMember";
+ private static final long serialVersionUID = 5543895177109398569L;
private final Object m_lock = new Object();
@@ -67,11 +69,6 @@
result = m_members.put(name, role);
}
- if (result == null) {
- // Notify our (optional) listener...
- entryAdded(BASIC_MEMBER, role);
- }
-
return (result == null);
}
@@ -91,11 +88,6 @@
result = m_requiredMembers.put(name, role);
}
- if (result == null) {
- // Notify our (optional) listener...
- entryAdded(REQUIRED_MEMBER, role);
- }
-
return (result == null);
}
@@ -133,25 +125,17 @@
String name = role.getName();
- String key = null;
Object result = null;
-
+
synchronized (m_lock) {
if (m_requiredMembers.containsKey(name)) {
- key = REQUIRED_MEMBER;
result = m_requiredMembers.remove(name);
}
else if (m_members.containsKey(name)) {
- key = BASIC_MEMBER;
result = m_members.remove(name);
}
}
- if (result != null) {
- // Notify our (optional) listener...
- entryRemoved(key);
- }
-
return result != null;
}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableDictionary.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableDictionary.java
index a41ae14..7d167c5 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableDictionary.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableDictionary.java
@@ -17,13 +17,9 @@
package org.apache.felix.useradmin.impl.role;
import java.io.Serializable;
-import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
+import java.util.Hashtable;
import org.osgi.service.useradmin.UserAdminPermission;
@@ -31,10 +27,13 @@
* Provides an observable {@link Dictionary} implementation that emits change
* events for the put and remove operations aside checking for security
* permissions for all accessor methods.
+ * <p>
+ * This class is <b>not</b> guaranteed to be thread-safe!
+ * </p>
*/
class ObservableDictionary extends Dictionary implements Serializable {
- private static final long serialVersionUID = 9223154895541178975L;
+ private static final long serialVersionUID = 3161552287666253189L;
/**
* Provides a listener for changes to a {@link ObservableDictionary}.
@@ -66,58 +65,7 @@
void entryRemoved(Object key);
}
- /**
- * Provides a wrapper to convert an {@link Iterator} to an {@link Enumeration} implementation.
- */
- static final class IteratorEnumeration implements Enumeration {
-
- private final Iterator m_iterator;
-
- /**
- * Creates a new {@link IteratorEnumeration}.
- *
- * @param iterator the {@link Iterator} to convert to a {@link Enumeration}, cannot be <code>null</code>.
- */
- public IteratorEnumeration(Iterator iterator) {
- m_iterator = iterator;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean hasMoreElements() {
- return m_iterator.hasNext();
- }
-
- /**
- * {@inheritDoc}
- */
- public Object nextElement() {
- return m_iterator.next();
- }
- }
-
- /**
- * Converts a given {@link Dictionary} implementation to a {@link Map} implementation.
- *
- * @param dictionary the dictionary to convert, cannot be <code>null</code>.
- * @return a {@link Map} instance with all the same key-value pairs as the given dictionary, never <code>null</code>.
- */
- private static ConcurrentMap convertToMap(Dictionary dictionary) {
- ConcurrentMap result = new ConcurrentHashMap();
- if (dictionary instanceof Map) {
- result.putAll((Map) dictionary);
- } else {
- Enumeration keyEnum = dictionary.keys();
- while (keyEnum.hasMoreElements()) {
- Object key = keyEnum.nextElement();
- result.put(key, dictionary.get(key));
- }
- }
- return result;
- }
-
- private final ConcurrentMap m_properties;
+ private final Dictionary m_dictionary;
private final String m_getAction;
private final String m_changeAction;
@@ -127,9 +75,7 @@
* Creates a new, empty, {@link ObservableDictionary} instance.
*/
public ObservableDictionary(String getAction, String changeAction) {
- m_getAction = getAction;
- m_changeAction = changeAction;
- m_properties = new ConcurrentHashMap();
+ this(getAction, changeAction, new Hashtable());
}
/**
@@ -143,15 +89,14 @@
}
m_getAction = getAction;
m_changeAction = changeAction;
- m_properties = convertToMap(dictionary);
+ m_dictionary = dictionary;
}
/**
* {@inheritDoc}
*/
public Enumeration elements() {
- Collection values = m_properties.values();
- return new IteratorEnumeration(values.iterator());
+ return m_dictionary.elements();
}
/**
@@ -166,11 +111,11 @@
}
ObservableDictionary other = (ObservableDictionary) object;
- if (m_properties == null) {
- if (other.m_properties != null) {
+ if (m_dictionary == null) {
+ if (other.m_dictionary != null) {
return false;
}
- } else if (!m_properties.equals(other.m_properties)) {
+ } else if (!m_dictionary.equals(other.m_dictionary)) {
return false;
}
@@ -189,7 +134,7 @@
checkPermissions(getAsPermissionKey(key), m_getAction);
}
- return m_properties.get(key);
+ return m_dictionary.get(key);
}
/**
@@ -198,7 +143,7 @@
public int hashCode() {
final int prime = 37;
int result = 1;
- result = prime * result + ((m_properties == null) ? 0 : m_properties.hashCode());
+ result = prime * result + ((m_dictionary == null) ? 0 : m_dictionary.hashCode());
return result;
}
@@ -206,15 +151,14 @@
* {@inheritDoc}
*/
public boolean isEmpty() {
- return m_properties.isEmpty();
+ return m_dictionary.isEmpty();
}
/**
* {@inheritDoc}
*/
public Enumeration keys() {
- Collection keys = m_properties.keySet();
- return new IteratorEnumeration(keys.iterator());
+ return m_dictionary.keys();
}
/**
@@ -232,7 +176,7 @@
checkPermissions(getAsPermissionKey(key), m_changeAction);
}
- Object oldValue = m_properties.put(key, value);
+ Object oldValue = m_dictionary.put(key, value);
final DictionaryChangeListener listener = m_listener;
if (listener != null) {
@@ -258,7 +202,7 @@
checkPermissions(getAsPermissionKey(key), m_changeAction);
}
- Object oldValue = m_properties.remove(key);
+ Object oldValue = m_dictionary.remove(key);
final DictionaryChangeListener listener = m_listener;
if (listener != null) {
listener.entryRemoved(key);
@@ -280,7 +224,7 @@
* {@inheritDoc}
*/
public int size() {
- return m_properties.size();
+ return m_dictionary.size();
}
/**
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableGroup.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableGroup.java
new file mode 100644
index 0000000..0042ade
--- /dev/null
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableGroup.java
@@ -0,0 +1,111 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.felix.useradmin.impl.role;
+
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+
+/**
+ * Provides an adapter for all {@link Group}s, allowing its changes to be
+ * externally observed.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ObservableGroup extends ObservableUser implements Group {
+
+ private static final long serialVersionUID = 4012536225870565500L;
+
+ private static final String BASIC_MEMBER = "basicMember";
+ private static final String REQUIRED_MEMBER = "requiredMember";
+
+ /**
+ * Creates a new {@link ObservableGroup} instance.
+ *
+ * @param group the group-role to observe for changes, cannot be <code>null</code>.
+ * @throws IllegalArgumentException in case the given group-role was <code>null</code>.
+ */
+ public ObservableGroup(Group group) {
+ super(group);
+ }
+
+ public boolean addMember(Role role) {
+ boolean result = ((Group) m_delegate).addMember(role);
+ if (result) {
+ // Notify our (optional) listener...
+ entryAdded(BASIC_MEMBER, role);
+ }
+ return result;
+ }
+
+ public boolean addRequiredMember(Role role) {
+ boolean result = ((Group) m_delegate).addRequiredMember(role);
+ if (result) {
+ // Notify our (optional) listener...
+ entryAdded(REQUIRED_MEMBER, role);
+ }
+
+ return result;
+ }
+
+ public boolean removeMember(Role role) {
+ // Take a snapshot of the current set of members...
+ Role[] members = getRequiredMembers();
+ boolean result = ((Group) m_delegate).removeMember(role);
+ if (result) {
+ // Notify our (optional) listener...
+ String key = BASIC_MEMBER;
+ for (int i = 0; (members != null) && (i < members.length); i++) {
+ if (members[i].equals(role)) {
+ key = REQUIRED_MEMBER;
+ break;
+ }
+ }
+ entryRemoved(key);
+ }
+ return result;
+ }
+
+ public Role[] getMembers() {
+ Role[] members = ((Group) m_delegate).getMembers();
+ if (members == null) {
+ return null;
+ }
+ Role[] result = new Role[members.length];
+ for (int i = 0; i < members.length; i++) {
+ result[i] = ObservableRole.wrap(members[i]);
+ }
+ return result;
+ }
+
+ public Role[] getRequiredMembers() {
+ Role[] requiredMembers = ((Group) m_delegate).getRequiredMembers();
+ if (requiredMembers == null) {
+ return null;
+ }
+ Role[] result = new Role[requiredMembers.length];
+ for (int i = 0; i < requiredMembers.length; i++) {
+ result[i] = ObservableRole.wrap(requiredMembers[i]);
+ }
+ return requiredMembers;
+ }
+
+ public String toString() {
+ return m_delegate.toString();
+ }
+}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableProperties.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableProperties.java
index de05dc9..f0d25f9 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableProperties.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableProperties.java
@@ -17,10 +17,14 @@
package org.apache.felix.useradmin.impl.role;
import java.util.Dictionary;
+import java.util.Properties;
/**
* Provides an stricter variant of the {@link ObservableDictionary} that only
* permits string keys and values of either String or byte[].
+ * <p>
+ * This class is <b>not</b> guaranteed to be thread-safe!
+ * </p>
*/
final class ObservableProperties extends ObservableDictionary {
@@ -30,7 +34,7 @@
* Creates a new, empty, {@link ObservableProperties} instance.
*/
public ObservableProperties(String getAction, String changeAction) {
- super(getAction, changeAction);
+ this(getAction, changeAction, new Properties());
}
/**
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableRole.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableRole.java
new file mode 100644
index 0000000..ee3ef45
--- /dev/null
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableRole.java
@@ -0,0 +1,173 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.felix.useradmin.impl.role;
+
+import java.io.Serializable;
+import java.util.Dictionary;
+
+import org.apache.felix.useradmin.impl.RoleChangeListener;
+import org.apache.felix.useradmin.impl.role.ObservableDictionary.DictionaryChangeListener;
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdminPermission;
+
+/**
+ * Provides an adapter for all {@link Role}s, allowing its changes to be
+ * externally observed.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ObservableRole implements Serializable, Role, DictionaryChangeListener {
+
+ private static final long serialVersionUID = -3706363718282775516L;
+
+ protected final Role m_delegate;
+
+ private final ObservableProperties m_properties;
+
+ private volatile RoleChangeListener m_listener;
+
+ /**
+ * Creates a new {@link ObservableRole} instance.
+ *
+ * @param role the role to observe for changes, cannot be <code>null</code>.
+ * @throws IllegalArgumentException in case the given role was <code>null</code>.
+ */
+ public ObservableRole(Role role) {
+ if (role == null) {
+ throw new IllegalArgumentException("Role cannot be null!");
+ }
+
+ m_delegate = role;
+ m_properties = new ObservableProperties(null, UserAdminPermission.CHANGE_PROPERTY, m_delegate.getProperties());
+ m_properties.setDictionaryChangeListener(this);
+ }
+
+ /**
+ * Wraps the given role as an (subclass of) {@link ObservableRole}.
+ * <p>
+ * If the given role is already an instance of {@link ObservableRole}, this
+ * method simply returns the given role.
+ * </p>
+ *
+ * @param role the role to wrap, can be <code>null</code>.
+ * @return an {@link ObservableRole} instance wrapping the given role, or
+ * <code>null</code> if the given role was <code>null</code>.
+ */
+ public static ObservableRole wrap(Role role) {
+ if (role == null) {
+ return null;
+ }
+ if (role instanceof ObservableRole) {
+ return (ObservableRole) role;
+ }
+ int type = role.getType();
+ switch (type) {
+ case Role.GROUP:
+ return new ObservableGroup((Group) role);
+
+ case Role.USER:
+ return new ObservableUser((User) role);
+
+ default:
+ return new ObservableRole(role);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void entryAdded(Object key, Object value) {
+ RoleChangeListener listener = m_listener;
+ if (listener != null) {
+ listener.propertyAdded(this, key, value);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void entryChanged(Object key, Object oldValue, Object newValue) {
+ RoleChangeListener listener = m_listener;
+ if (listener != null) {
+ listener.propertyChanged(this, key, oldValue, newValue);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void entryRemoved(Object key) {
+ RoleChangeListener listener = m_listener;
+ if (listener != null) {
+ listener.propertyRemoved(this, key);
+ }
+ }
+
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if ((object == null) || (getClass() != object.getClass())) {
+ return false;
+ }
+
+ ObservableRole other = (ObservableRole) object;
+ if (m_delegate == null) {
+ if (other.m_delegate != null) {
+ return false;
+ }
+ }
+ else if (!m_delegate.equals(other.m_delegate)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public String getName() {
+ return m_delegate.getName();
+ }
+
+ public Dictionary getProperties() {
+ return m_properties;
+ }
+
+ public int getType() {
+ return m_delegate.getType();
+ }
+
+ public int hashCode() {
+ return 31 + ((m_delegate == null) ? 0 : m_delegate.hashCode());
+ }
+
+ /**
+ * Sets the {@link RoleChangeListener} for this role implementation.
+ *
+ * @param listener the listener to set, may be <code>null</code> to stop listening.
+ */
+ public void setRoleChangeListener(RoleChangeListener listener) {
+ m_listener = listener;
+ }
+
+ public String toString() {
+ return m_delegate.toString();
+ }
+}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableUser.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableUser.java
new file mode 100644
index 0000000..64c0aec
--- /dev/null
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableUser.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.felix.useradmin.impl.role;
+
+import java.util.Dictionary;
+
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdminPermission;
+
+/**
+ * Provides an adapter for all {@link User}s, allowing its changes to be
+ * externally observed.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ObservableUser extends ObservableRole implements User {
+
+ private static final long serialVersionUID = 344574927109701877L;
+
+ private final ObservableProperties m_credentials;
+
+ /**
+ * Creates a new {@link ObservableUser} instance.
+ *
+ * @param user the user-role to observe for changes, cannot be <code>null</code>.
+ * @throws IllegalArgumentException in case the given user-role was <code>null</code>.
+ */
+ public ObservableUser(User user) {
+ super(user);
+
+ m_credentials = new ObservableProperties(UserAdminPermission.GET_CREDENTIAL, UserAdminPermission.CHANGE_CREDENTIAL, user.getCredentials());
+ m_credentials.setDictionaryChangeListener(this);
+ }
+
+ public Dictionary getCredentials() {
+ return m_credentials;
+ }
+
+ public boolean hasCredential(String key, Object value) {
+ // Will throw a SecurityException if we're not allowed to do this!
+ m_credentials.get(key);
+ // We're allowed to do this; let the original implementation figure out
+ // whether or not the test holds...
+ return ((User) m_delegate).hasCredential(key, value);
+ }
+
+ public String toString()
+ {
+ return m_delegate.toString();
+ }
+}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/RoleImpl.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/RoleImpl.java
index 576eee2..6d78d8e 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/RoleImpl.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/RoleImpl.java
@@ -18,25 +18,25 @@
import java.io.Serializable;
import java.util.Dictionary;
+import java.util.Properties;
-
-import org.apache.felix.useradmin.impl.RoleChangeListener;
-import org.apache.felix.useradmin.impl.role.ObservableDictionary.DictionaryChangeListener;
import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.UserAdminPermission;
/**
- * Provides an implementation of {@link Role}.
+ * Provides a default implementation of {@link Role} that is not security-aware
+ * and does not keep track of changes to its properties.
+ * <p>
+ * This implementation should be wrapped in an {@link ObservableRole} when
+ * returned from the UserAdmin implementation.
+ * </p>
*/
-public class RoleImpl implements Serializable, Role, DictionaryChangeListener {
-
- private static final long serialVersionUID = -6292833161748591485L;
+public class RoleImpl implements Serializable, Role {
- private final ObservableProperties m_properties;
+ private static final long serialVersionUID = 6403795608776837916L;
+
+ private final Properties m_properties;
private final String m_name;
private final int m_type;
-
- private volatile RoleChangeListener m_listener;
/**
* Creates a new {@link RoleImpl} instance of type {@link Role#ROLE} and a given name.
@@ -59,38 +59,7 @@
}
m_type = type;
m_name = name;
- m_properties = new ObservableProperties(null, UserAdminPermission.CHANGE_PROPERTY);
- m_properties.setDictionaryChangeListener(this);
- }
-
- /**
- * {@inheritDoc}
- */
- public final void entryAdded(Object key, Object value) {
- RoleChangeListener listener = m_listener;
- if (listener != null) {
- listener.propertyAdded(this, key, value);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public final void entryRemoved(Object key) {
- RoleChangeListener listener = m_listener;
- if (listener != null) {
- listener.propertyRemoved(this, key);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public final void entryChanged(Object key, Object oldValue, Object newValue) {
- RoleChangeListener listener = m_listener;
- if (listener != null) {
- listener.propertyChanged(this, key, oldValue, newValue);
- }
+ m_properties = new Properties();
}
/**
@@ -152,15 +121,6 @@
result = prime * result + m_type;
return result;
}
-
- /**
- * Sets the {@link RoleChangeListener} for this role implementation.
- *
- * @param listener the listener to set, may be <code>null</code> to stop listening.
- */
- public void setRoleChangeListener(RoleChangeListener listener) {
- m_listener = listener;
- }
/**
* {@inheritDoc}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/UserImpl.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/UserImpl.java
index d152af3..e19874c 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/UserImpl.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/UserImpl.java
@@ -18,19 +18,24 @@
import java.util.Arrays;
import java.util.Dictionary;
+import java.util.Properties;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdminPermission;
/**
- * Provides an implementation of {@link User}.
+ * Provides a default implementation of {@link User} that is not security-aware
+ * and does not keep track of changes to its properties.
+ * <p>
+ * This implementation should be wrapped in an {@link ObservableUser} when
+ * returned from the UserAdmin implementation.
+ * </p>
*/
public class UserImpl extends RoleImpl implements User {
- private static final long serialVersionUID = 8639414204247841034L;
-
- private final ObservableProperties m_credentials;
+ private static final long serialVersionUID = 7332249440557443008L;
+
+ private final Properties m_credentials;
/**
* Creates a new {@link UserImpl} instance with type {@link Role#USER}.
@@ -50,8 +55,7 @@
protected UserImpl(int type, String name) {
super(type, name);
- m_credentials = new ObservableProperties(UserAdminPermission.GET_CREDENTIAL, UserAdminPermission.CHANGE_CREDENTIAL);
- m_credentials.setDictionaryChangeListener(this);
+ m_credentials = new Properties();
}
/**
@@ -65,7 +69,6 @@
* {@inheritDoc}
*/
public boolean hasCredential(String key, Object value) {
- // Will throw a SecurityException if we're not allowed to do this!
Object result = m_credentials.get(key);
// Be a bit more lenient with the various results we can get...
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/RoleRepositoryStoreHelper.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/RoleRepositoryStoreHelper.java
index 824d520..26cde1a 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/RoleRepositoryStoreHelper.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/RoleRepositoryStoreHelper.java
@@ -16,12 +16,9 @@
*/
package org.apache.felix.useradmin.osgi;
-import java.io.IOException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
import org.apache.felix.useradmin.RoleRepositoryStore;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Filter;
import org.osgi.service.useradmin.Role;
import org.osgi.util.tracker.ServiceTracker;
@@ -34,8 +31,6 @@
*/
class RoleRepositoryStoreHelper extends ServiceTracker implements RoleRepositoryStore {
- private final AtomicBoolean m_initialized = new AtomicBoolean(false);
-
/**
* Creates a new {@link RoleRepositoryStoreHelper} instance.
*
@@ -45,50 +40,25 @@
super(context, RoleRepositoryStore.class.getName(), null /* customizer */);
}
- public Object addingService(ServiceReference reference) {
- // FELIX-3735: store can also become available *after* this bundle is started...
- RoleRepositoryStore store = (RoleRepositoryStore) super.addingService(reference);
- try {
- initializeStore(store);
- } catch (IOException e) {
- // Ignore; nothing we can do about this here...
- }
- return store;
- }
-
- public boolean addRole(Role role) throws IOException {
+ public Role addRole(String roleName, int type) throws Exception {
RoleRepositoryStore store = getStore();
if (store != null) {
- return store.addRole(role);
+ return store.addRole(roleName, type);
}
- return false;
- }
-
- public synchronized void close() {
- try {
- RoleRepositoryStore store = getStore();
- if (store != null) {
- closeStore(store);
- }
- }
- catch (IOException e) {
- // Ignore; nothing we can do about this here...
- } finally {
- super.close();
- }
+ return null;
}
- public Role[] getAllRoles() throws IOException {
+ public Role[] getRoles(Filter filter) throws Exception {
RoleRepositoryStore store = getStore();
if (store != null) {
- return store.getAllRoles();
+ return store.getRoles(filter);
}
return new Role[0];
}
- public Role getRoleByName(String roleName) throws IOException {
+ public Role getRoleByName(String roleName) throws Exception {
RoleRepositoryStore store = getStore();
if (store != null) {
return store.getRoleByName(roleName);
@@ -96,33 +66,15 @@
return null;
}
-
- public void initialize() throws IOException {
- RoleRepositoryStore store = getStore();
- if (store != null) {
- initializeStore(store);
- }
- }
- public void removedService(ServiceReference reference, Object service) {
- RoleRepositoryStore removedStore = (RoleRepositoryStore) service;
- try {
- closeStore(removedStore);
- }
- catch (IOException e) {
- // Ignore; nothing we can do about this here...
- }
- super.removedService(reference, service);
- }
-
- public boolean removeRole(Role role) throws IOException {
+ public Role removeRole(String roleName) throws Exception {
// and possibly also from our tracked store...
RoleRepositoryStore store = getStore();
if (store != null) {
- return store.removeRole(role);
+ return store.removeRole(roleName);
}
- return false;
+ return null;
}
/**
@@ -133,41 +85,4 @@
private RoleRepositoryStore getStore() {
return (RoleRepositoryStore) getService();
}
-
- /**
- * Closes the given store.
- *
- * @param store the store to close, cannot be <code>null</code>.
- * @throws IOException in case initialization failed.
- */
- private void closeStore(RoleRepositoryStore store) throws IOException {
- // Only close the store if its initialized...
- boolean initialized = m_initialized.get();
- if (initialized) {
- store.close();
-
- do {
- initialized = m_initialized.get();
- } while (!m_initialized.compareAndSet(initialized, false));
- }
- }
-
- /**
- * Initializes the given store.
- *
- * @param store the store to initialize, cannot be <code>null</code>.
- * @throws IOException in case initialization failed.
- */
- private void initializeStore(RoleRepositoryStore store) throws IOException {
- // FELIX-3735: store can also become available *after* this bundle is started;
- // hence we need to ensure we do not initialize the store twice...
- boolean initialized = m_initialized.get();
- if (!initialized) {
- store.initialize();
-
- do {
- initialized = m_initialized.get();
- } while (!m_initialized.compareAndSet(initialized, true));
- }
- }
}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/ServiceContext.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/ServiceContext.java
index 1d87ffd..79f7dbe 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/ServiceContext.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/ServiceContext.java
@@ -51,7 +51,6 @@
m_eventAdmin.open();
m_listenerList.open(true /* trackAllServices */);
m_eventDispatcher.start();
- m_roleRepository.start();
m_store.open();
}
@@ -59,7 +58,6 @@
* Stops/closes all helpers.
*/
public void stop() {
- m_roleRepository.stop();
m_eventDispatcher.stop();
m_listenerList.close();
m_eventAdmin.close();
diff --git a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/AuthorizationImplTest.java b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/AuthorizationImplTest.java
index 7cc1c39..766fab5 100644
--- a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/AuthorizationImplTest.java
+++ b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/AuthorizationImplTest.java
@@ -22,16 +22,18 @@
import junit.framework.TestCase;
-import org.apache.felix.useradmin.impl.role.GroupImpl;
-import org.apache.felix.useradmin.impl.role.UserImpl;
+import org.apache.felix.useradmin.RoleFactory;
import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
/**
* Test cases for {@link AuthorizationImpl}.
*/
public class AuthorizationImplTest extends TestCase {
- private RoleRepository m_roleManager;
+ private RoleRepository m_roleRepository;
+ private Role m_anyone;
/**
* {@inheritDoc}
@@ -39,7 +41,9 @@
protected void setUp() throws Exception {
super.setUp();
- m_roleManager = new RoleRepository(new MemoryRoleRepositoryStore());
+ m_roleRepository = new RoleRepository(new MemoryRoleRepositoryStore());
+
+ m_anyone = m_roleRepository.getRoleByName(Role.USER_ANYONE);
}
/**
@@ -62,26 +66,26 @@
Group residents = createGroup("Residents");
// Users
- UserImpl elmer = new UserImpl("Elmer");
- UserImpl fudd = new UserImpl("Fudd");
- UserImpl marvin = new UserImpl("Marvin");
- UserImpl pepe = new UserImpl("Pepe");
- UserImpl daffy = new UserImpl("Daffy");
- UserImpl foghorn = new UserImpl("Foghorn");
+ User elmer = RoleFactory.createUser("Elmer");
+ User fudd = RoleFactory.createUser("Fudd");
+ User marvin = RoleFactory.createUser("Marvin");
+ User pepe = RoleFactory.createUser("Pepe");
+ User daffy =RoleFactory.createUser("Daffy");
+ User foghorn = RoleFactory.createUser("Foghorn");
// Not explicitly mentioned; but needed to comply with the semantics
- alarmSystemControl.addRequiredMember(RoleRepository.USER_ANYONE);
- internetAccess.addRequiredMember(RoleRepository.USER_ANYONE);
- temperatureControl.addRequiredMember(RoleRepository.USER_ANYONE);
- photoAlbumEdit.addRequiredMember(RoleRepository.USER_ANYONE);
- photoAlbumView.addRequiredMember(RoleRepository.USER_ANYONE);
- portForwarding.addRequiredMember(RoleRepository.USER_ANYONE);
+ alarmSystemControl.addRequiredMember(m_anyone);
+ internetAccess.addRequiredMember(m_anyone);
+ temperatureControl.addRequiredMember(m_anyone);
+ photoAlbumEdit.addRequiredMember(m_anyone);
+ photoAlbumView.addRequiredMember(m_anyone);
+ portForwarding.addRequiredMember(m_anyone);
- administrators.addRequiredMember(RoleRepository.USER_ANYONE);
- buddies.addRequiredMember(RoleRepository.USER_ANYONE);
- children.addRequiredMember(RoleRepository.USER_ANYONE);
- adults.addRequiredMember(RoleRepository.USER_ANYONE);
- residents.addRequiredMember(RoleRepository.USER_ANYONE);
+ administrators.addRequiredMember(m_anyone);
+ buddies.addRequiredMember(m_anyone);
+ children.addRequiredMember(m_anyone);
+ adults.addRequiredMember(m_anyone);
+ residents.addRequiredMember(m_anyone);
// Table 107.1
residents.addMember(elmer);
@@ -121,7 +125,7 @@
portForwarding.addRequiredMember(administrators);
// Test with the user "foghorn"...
- AuthorizationImpl auth = new AuthorizationImpl(foghorn, m_roleManager);
+ AuthorizationImpl auth = new AuthorizationImpl(foghorn, m_roleRepository);
assertFalse(auth.hasRole(alarmSystemControl.getName()));
assertFalse(auth.hasRole(internetAccess.getName()));
@@ -131,7 +135,7 @@
assertFalse(auth.hasRole(portForwarding.getName()));
// Test with the user "fudd"...
- auth = new AuthorizationImpl(fudd, m_roleManager);
+ auth = new AuthorizationImpl(fudd, m_roleRepository);
assertFalse(auth.hasRole(alarmSystemControl.getName()));
assertTrue(auth.hasRole(internetAccess.getName()));
@@ -141,7 +145,7 @@
assertFalse(auth.hasRole(portForwarding.getName()));
// Test with the user "elmer"...
- auth = new AuthorizationImpl(elmer, m_roleManager);
+ auth = new AuthorizationImpl(elmer, m_roleRepository);
assertTrue(auth.hasRole(alarmSystemControl.getName()));
assertTrue(auth.hasRole(internetAccess.getName()));
@@ -155,54 +159,54 @@
* Test that the tests for membership work correctly.
*/
public void testHasRoleOk() {
- GroupImpl citizens = createGroup("citizen");
- citizens.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group citizens = createGroup("citizen");
+ citizens.addRequiredMember(m_anyone);
- GroupImpl adults = createGroup("adult");
- adults.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group adults = createGroup("adult");
+ adults.addRequiredMember(m_anyone);
- GroupImpl voters = createGroup("voter");
+ Group voters = createGroup("voter");
voters.addRequiredMember(citizens);
voters.addRequiredMember(adults);
- voters.addMember(RoleRepository.USER_ANYONE);
+ voters.addMember(m_anyone);
// Elmer belongs to the citizens and adults...
- UserImpl elmer = createUser("elmer");
+ User elmer = createUser("elmer");
citizens.addMember(elmer);
adults.addMember(elmer);
// Pepe belongs to the citizens, but is not an adult...
- UserImpl pepe = createUser("pepe");
+ User pepe = createUser("pepe");
citizens.addMember(pepe);
// Bugs is an adult, but is not a citizen...
- UserImpl bugs = createUser("bugs");
+ User bugs = createUser("bugs");
adults.addMember(bugs);
// Daffy is not an adult, neither a citizen...
- UserImpl daffy = createUser("daffy");
+ User daffy = createUser("daffy");
AuthorizationImpl auth;
- auth = new AuthorizationImpl(elmer, m_roleManager);
+ auth = new AuthorizationImpl(elmer, m_roleRepository);
assertTrue(auth.hasRole("adult"));
assertTrue(auth.hasRole("citizen"));
assertTrue(auth.hasRole("voter"));
assertFalse(auth.hasRole("non-existing-role"));
- auth = new AuthorizationImpl(pepe, m_roleManager);
+ auth = new AuthorizationImpl(pepe, m_roleRepository);
assertFalse(auth.hasRole("adult"));
assertTrue(auth.hasRole("citizen"));
assertFalse(auth.hasRole("voter"));
assertFalse(auth.hasRole("non-existing-role"));
- auth = new AuthorizationImpl(bugs, m_roleManager);
+ auth = new AuthorizationImpl(bugs, m_roleRepository);
assertTrue(auth.hasRole("adult"));
assertFalse(auth.hasRole("citizen"));
assertFalse(auth.hasRole("voter"));
assertFalse(auth.hasRole("non-existing-role"));
- auth = new AuthorizationImpl(daffy, m_roleManager);
+ auth = new AuthorizationImpl(daffy, m_roleRepository);
assertFalse(auth.hasRole("adult"));
assertFalse(auth.hasRole("citizen"));
assertFalse(auth.hasRole("voter"));
@@ -213,51 +217,51 @@
* Test that the tests for membership work correctly.
*/
public void testGetRolesOk() {
- GroupImpl citizens = createGroup("citizen");
- citizens.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group citizens = createGroup("citizen");
+ citizens.addRequiredMember(m_anyone);
- GroupImpl adults = createGroup("adult");
- adults.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group adults = createGroup("adult");
+ adults.addRequiredMember(m_anyone);
- GroupImpl voters = createGroup("voter");
+ Group voters = createGroup("voter");
voters.addRequiredMember(citizens);
voters.addRequiredMember(adults);
- voters.addMember(RoleRepository.USER_ANYONE);
+ voters.addMember(m_anyone);
// Elmer belongs to the citizens and adults...
- UserImpl elmer = createUser("elmer");
+ User elmer = createUser("elmer");
citizens.addMember(elmer);
adults.addMember(elmer);
// Pepe belongs to the citizens, but is not an adult...
- UserImpl pepe = createUser("pepe");
+ User pepe = createUser("pepe");
citizens.addMember(pepe);
// Bugs is an adult, but is not a citizen...
- UserImpl bugs = createUser("bugs");
+ User bugs = createUser("bugs");
adults.addMember(bugs);
// Daffy is not an adult, neither a citizen...
- UserImpl daffy = createUser("daffy");
+ User daffy = createUser("daffy");
- // Daffy is not an adult, neither a citizen...
- UserImpl donald = new UserImpl("donald");
+ // Donald is not an adult, neither a citizen...
+ User donald = RoleFactory.createUser("donald");
AuthorizationImpl auth;
- auth = new AuthorizationImpl(elmer, m_roleManager);
+ auth = new AuthorizationImpl(elmer, m_roleRepository);
assertSameRoles(new String[]{ "elmer", "adult", "citizen", "voter" }, auth.getRoles());
- auth = new AuthorizationImpl(pepe, m_roleManager);
+ auth = new AuthorizationImpl(pepe, m_roleRepository);
assertSameRoles(new String[]{ "pepe", "citizen" }, auth.getRoles());
- auth = new AuthorizationImpl(bugs, m_roleManager);
+ auth = new AuthorizationImpl(bugs, m_roleRepository);
assertSameRoles(new String[]{ "bugs", "adult" }, auth.getRoles());
- auth = new AuthorizationImpl(daffy, m_roleManager);
+ auth = new AuthorizationImpl(daffy, m_roleRepository);
assertSameRoles(new String[]{ "daffy" }, auth.getRoles());
- auth = new AuthorizationImpl(donald, m_roleManager);
+ auth = new AuthorizationImpl(donald, m_roleRepository);
assertNull(auth.getRoles());
}
@@ -271,15 +275,11 @@
assertTrue("Not seen: " + e, e.isEmpty());
}
- private GroupImpl createGroup(String name) {
- GroupImpl result = new GroupImpl(name);
- m_roleManager.addRole(result);
- return result;
+ private Group createGroup(String name) {
+ return (Group) m_roleRepository.addRole(name, Role.GROUP);
}
- private UserImpl createUser(String name) {
- UserImpl result = new UserImpl(name);
- m_roleManager.addRole(result);
- return result;
+ private User createUser(String name) {
+ return (User) m_roleRepository.addRole(name, Role.USER);
}
}
diff --git a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/CustomRoleImplTest.java b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/CustomRoleImplTest.java
new file mode 100644
index 0000000..ef4ae15
--- /dev/null
+++ b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/CustomRoleImplTest.java
@@ -0,0 +1,486 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.felix.useradmin.impl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.TestCase;
+
+import org.apache.felix.useradmin.RoleRepositoryStore;
+import org.osgi.framework.Filter;
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+
+/**
+ * Tests whether using custom roles in the backend work as expected and yield the proper events.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class CustomRoleImplTest extends TestCase
+{
+ static class MyGroupImpl extends MyUserImpl implements Group {
+ private final Map m_members;
+ private final Map m_requiredMembers;
+
+ public MyGroupImpl(String name) {
+ super(name, GROUP);
+ m_members = new HashMap();
+ m_requiredMembers = new HashMap();
+ }
+
+ public boolean addMember(Role role) {
+ String name = role.getName();
+ if (m_requiredMembers.containsKey(name) || m_members.containsKey(name)) {
+ return false;
+ }
+ return m_members.put(name, role) == null;
+ }
+
+ public boolean addRequiredMember(Role role) {
+ String name = role.getName();
+ if (m_requiredMembers.containsKey(name) || m_members.containsKey(name)) {
+ return false;
+ }
+ return m_requiredMembers.put(name, role) == null;
+ }
+
+ public Role[] getMembers() {
+ Role[] result = new Role[m_members.size()];
+ return (Role[]) m_members.values().toArray(result);
+ }
+
+ public Role[] getRequiredMembers() {
+ Role[] result = new Role[m_requiredMembers.size()];
+ return (Role[]) m_requiredMembers.values().toArray(result);
+ }
+
+ public boolean removeMember(Role role) {
+ String name = role.getName();
+ if (m_requiredMembers.remove(name) != null) {
+ return true;
+ } else if (m_members.remove(name) != null) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ static class MyRoleImpl implements Role {
+ private final String m_name;
+ private final int m_type;
+ private final Hashtable m_props;
+
+ public MyRoleImpl(String name, int type) {
+ m_name = name;
+ m_type = type;
+ m_props = new Hashtable();
+ }
+
+ public String getName() {
+ return m_name;
+ }
+
+ public Dictionary getProperties() {
+ return m_props;
+ }
+
+ public int getType() {
+ return m_type;
+ }
+ }
+
+ static class MyRoleRepositoryStore implements RoleRepositoryStore {
+ private final ConcurrentMap m_entries = new ConcurrentHashMap();
+
+ public Role addRole(String roleName, int type) throws IOException {
+ if (roleName == null) {
+ throw new IllegalArgumentException("Name cannot be null!");
+ }
+
+ Role role = createRole(roleName, type);
+
+ Object result = m_entries.putIfAbsent(roleName, role);
+ return (result == null) ? role : null;
+ }
+
+ public void close() throws IOException {
+ // Nop
+ }
+
+ public Role getRoleByName(String roleName) throws IOException {
+ if (roleName == null) {
+ throw new IllegalArgumentException("Role name cannot be null!");
+ }
+ return (Role) m_entries.get(roleName);
+ }
+
+ public Role[] getRoles(Filter filter) throws IOException {
+ Collection roles = m_entries.values();
+
+ List matchingRoles = new ArrayList();
+ Iterator rolesIter = roles.iterator();
+ while (rolesIter.hasNext()) {
+ Role role = (Role) rolesIter.next();
+ if ((filter == null) || filter.match(role.getProperties())) {
+ matchingRoles.add(role);
+ }
+ }
+
+ Role[] result = new Role[matchingRoles.size()];
+ return (Role[]) matchingRoles.toArray(result);
+ }
+
+ public void initialize() throws IOException {
+ // Nop
+ }
+
+ public Role removeRole(String roleName) throws IOException {
+ if (roleName == null) {
+ throw new IllegalArgumentException("Name cannot be null!");
+ }
+ Role role = getRoleByName(roleName);
+ boolean result = m_entries.remove(roleName, role);
+ return result ? role : null;
+ }
+
+ private Role createRole(String roleName, int type) {
+ Role role;
+ if (type == Role.USER) {
+ role = new MyUserImpl(roleName);
+ } else if (type == Role.GROUP) {
+ role = new MyGroupImpl(roleName);
+ } else {
+ throw new IllegalArgumentException("Invalid role type!");
+ }
+ return role;
+ }
+ }
+
+ static class MyUserImpl extends MyRoleImpl implements User {
+ private final Hashtable m_creds;
+
+ public MyUserImpl(String name) {
+ this(name, USER);
+ }
+
+ protected MyUserImpl(String name, int type) {
+ super(name, type);
+ m_creds = new Hashtable();
+ }
+
+ public Dictionary getCredentials() {
+ return m_creds;
+ }
+
+ public boolean hasCredential(String key, Object value) {
+ if (m_creds.containsKey(key)) {
+ Object v = m_creds.get(key);
+ return ((v == value) || ((v != null) && v.equals(value)));
+ }
+ return false;
+ }
+ }
+
+ private CountDownLatch m_latch;
+ private RoleRepository m_repository;
+
+ /**
+ * Tests that adding a basic member to a group-role yields an event.
+ */
+ public void testAddBasicGroupMemberYieldsEvent() throws Exception {
+ final Group role = (Group) m_repository.addRole("testGroup", Role.GROUP);
+ assertNotNull(role);
+
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ Role anyone = m_repository.getRoleByName(Role.USER_ANYONE);
+ assertTrue(role.addMember(anyone));
+ };
+ }).start();
+
+ assertTrue(m_latch.await(1, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that adding an existing role does not yield an event.
+ */
+ public void testAddExistingRoleDoesNotYieldEvent() throws Exception {
+ assertNotNull(m_repository.addRole("testUser", Role.USER));
+
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ assertNull(m_repository.addRole("testUser", Role.USER));
+ };
+ }).start();
+
+ assertFalse(m_latch.await(1, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that adding a new role yields an event.
+ */
+ public void testAddNewRoleYieldsEvent() throws Exception {
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ assertNotNull(m_repository.addRole("testUser", Role.USER));
+ };
+ }).start();
+
+ assertTrue(m_latch.await(1, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that adding a required member to a group-role yields an event.
+ */
+ public void testAddRequiredGroupMemberYieldsEvent() throws Exception {
+ final Group role = (Group) m_repository.addRole("testGroup", Role.GROUP);
+ assertNotNull(role);
+
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ Role anyone = m_repository.getRoleByName(Role.USER_ANYONE);
+ assertTrue(role.addRequiredMember(anyone));
+ };
+ }).start();
+
+ assertTrue(m_latch.await(100, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that changing the properties of a user-role yields an event.
+ */
+ public void testAddRolePropertiesYieldsEvent() throws Exception {
+ final Role role = m_repository.addRole("testUser", Role.USER);
+ assertNotNull(role);
+
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ role.getProperties().put("key", "value");
+ };
+ }).start();
+
+ assertTrue(m_latch.await(1, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that changing the credentials of a user-role yields an event.
+ */
+ public void testAddUserCredentialsYieldsEvent() throws Exception {
+ final User role = (User) m_repository.addRole("testUser", Role.USER);
+ assertNotNull(role);
+
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ role.getCredentials().put("key", "value");
+ };
+ }).start();
+
+ assertTrue(m_latch.await(1, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that changing the credentials of a user-role yields an event.
+ */
+ public void testChangePropertiesYieldsEvent() throws Exception {
+ final Role role = m_repository.addRole("testUser", Role.USER);
+ role.getProperties().put("key", "value1");
+ assertNotNull(role);
+
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ role.getProperties().put("key", "value2");
+ };
+ }).start();
+
+ assertTrue(m_latch.await(1, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that changing the credentials of a user-role yields an event.
+ */
+ public void testChangeUserCredentialsYieldsEvent() throws Exception {
+ final User role = (User) m_repository.addRole("testUser", Role.USER);
+ role.getCredentials().put("key", "value1");
+ assertNotNull(role);
+
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ role.getCredentials().put("key", "value2");
+ };
+ }).start();
+
+ assertTrue(m_latch.await(1, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that removing an existing role does yield an event.
+ */
+ public void testRemoveExistingRoleYieldsEvent() throws Exception {
+ assertNotNull(m_repository.addRole("testUser", Role.USER));
+
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ assertTrue(m_repository.removeRole("testUser"));
+ };
+ }).start();
+
+ assertTrue(m_latch.await(1, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that removing a non-existing role does not yield an event.
+ */
+ public void testRemoveNonExistingRoleDoesNotYieldEvent() throws Exception {
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ assertFalse(m_repository.removeRole("testUser"));
+ };
+ }).start();
+
+ assertFalse(m_latch.await(1, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that changing the properties of a user-role yields an event.
+ */
+ public void testRemoveRolePropertiesYieldsEvent() throws Exception {
+ final Role role = m_repository.addRole("testUser", Role.USER);
+ role.getProperties().put("key", "value");
+ assertNotNull(role);
+
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ role.getProperties().remove("key");
+ };
+ }).start();
+
+ assertTrue(m_latch.await(1, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that changing the credentials of a user-role yields an event.
+ */
+ public void testRemoveUserCredentialsYieldsEvent() throws Exception {
+ final User role = (User) m_repository.addRole("testUser", Role.USER);
+ role.getCredentials().put("key", "value");
+ assertNotNull(role);
+
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ role.getCredentials().remove("key");
+ };
+ }).start();
+
+ assertTrue(m_latch.await(1, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Tests that removing a member from a group-role yields an event.
+ */
+ public void testRemovingGroupMemberYieldsEvent() throws Exception {
+ final Role anyone = m_repository.getRoleByName(Role.USER_ANYONE);
+ final Group role = (Group) m_repository.addRole("testGroup", Role.GROUP);
+ assertNotNull(role);
+ role.addRequiredMember(anyone);
+
+ m_latch = new CountDownLatch(1);
+
+ new Thread(new Runnable() {
+ public void run() {
+ assertTrue(role.removeMember(anyone));
+ };
+ }).start();
+
+ assertTrue(m_latch.await(100, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Set up for all test cases.
+ */
+ protected void setUp() throws Exception
+ {
+ m_repository = new RoleRepository(new MyRoleRepositoryStore());
+ m_repository.addRoleChangeListener(new RoleChangeListener() {
+ public void propertyAdded(Role role, Object key, Object value) {
+ if (m_latch != null) {
+ m_latch.countDown();
+ }
+ }
+
+ public void propertyChanged(Role role, Object key, Object oldValue, Object newValue) {
+ if (m_latch != null) {
+ m_latch.countDown();
+ }
+ }
+
+ public void propertyRemoved(Role role, Object key) {
+ if (m_latch != null) {
+ m_latch.countDown();
+ }
+ }
+
+ public void roleAdded(Role role) {
+ if (m_latch != null) {
+ m_latch.countDown();
+ }
+ }
+
+ public void roleRemoved(Role role) {
+ if (m_latch != null) {
+ m_latch.countDown();
+ }
+ }
+ });
+ }
+}
diff --git a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/EventDispatcherTest.java b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/EventDispatcherTest.java
index 4f89d12..943d281 100644
--- a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/EventDispatcherTest.java
+++ b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/EventDispatcherTest.java
@@ -23,9 +23,9 @@
import junit.framework.TestCase;
+import org.apache.felix.useradmin.RoleFactory;
import org.apache.felix.useradmin.impl.EventDispatcher;
import org.apache.felix.useradmin.impl.UserAdminListenerList;
-import org.apache.felix.useradmin.impl.role.UserImpl;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
@@ -99,6 +99,10 @@
m_props.put(properties[i], properties[i + 1]);
}
}
+
+ public int compareTo(Object reference) {
+ return 0;
+ }
public Bundle getBundle() {
return null;
@@ -289,7 +293,7 @@
* @return
*/
private UserAdminEvent createMockEvent(int type) {
- Role user = new UserImpl("user-" + System.currentTimeMillis());
+ Role user = RoleFactory.createUser("user-" + System.currentTimeMillis());
ServiceReference ref = new FakeServiceReference();
return new UserAdminEvent(ref, type, user);
}
diff --git a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/MemoryRoleRepositoryStore.java b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/MemoryRoleRepositoryStore.java
index 8a0b7c3..80a4f50 100644
--- a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/MemoryRoleRepositoryStore.java
+++ b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/MemoryRoleRepositoryStore.java
@@ -17,11 +17,16 @@
package org.apache.felix.useradmin.impl;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import org.apache.felix.useradmin.RoleFactory;
import org.apache.felix.useradmin.RoleRepositoryStore;
+import org.osgi.framework.Filter;
import org.osgi.service.useradmin.Role;
@@ -30,28 +35,35 @@
*/
public class MemoryRoleRepositoryStore implements RoleRepositoryStore {
- protected final ConcurrentMap m_entries = new ConcurrentHashMap();
+ private final ConcurrentMap m_entries = new ConcurrentHashMap();
- public boolean addRole(Role role) throws IOException {
- if (role == null) {
- throw new IllegalArgumentException("Role cannot be null!");
+ public Role addRole(String roleName, int type) throws IOException {
+ if (roleName == null) {
+ throw new IllegalArgumentException("Name cannot be null!");
}
- Object result = m_entries.putIfAbsent(role.getName(), role);
- return result == null;
+ Role role = RoleFactory.createRole(type, roleName);
+ Object result = m_entries.putIfAbsent(roleName, role);
+ return (result == null) ? role : null;
}
public void close() throws IOException {
// Nop
}
- public void flush() throws IOException {
- // Nop
- }
-
- public Role[] getAllRoles() throws IOException {
+ public Role[] getRoles(Filter filter) throws IOException {
Collection roles = m_entries.values();
- Role[] result = new Role[roles.size()];
- return (Role[]) roles.toArray(result);
+
+ List matchingRoles = new ArrayList();
+ Iterator rolesIter = roles.iterator();
+ while (rolesIter.hasNext()) {
+ Role role = (Role) rolesIter.next();
+ if ((filter == null) || filter.match(role.getProperties())) {
+ matchingRoles.add(role);
+ }
+ }
+
+ Role[] result = new Role[matchingRoles.size()];
+ return (Role[]) matchingRoles.toArray(result);
}
public Role getRoleByName(String roleName) throws IOException {
@@ -65,10 +77,12 @@
// Nop
}
- public boolean removeRole(Role role) throws IOException {
- if (role == null) {
- throw new IllegalArgumentException("Role cannot be null!");
+ public Role removeRole(String roleName) throws IOException {
+ if (roleName == null) {
+ throw new IllegalArgumentException("Name cannot be null!");
}
- return m_entries.remove(role.getName(), role);
+ Role role = getRoleByName(roleName);
+ boolean result = m_entries.remove(roleName, role);
+ return result ? role : null;
}
}
diff --git a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleCheckerTest.java b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleCheckerTest.java
index 191f6f1..c656860 100644
--- a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleCheckerTest.java
+++ b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleCheckerTest.java
@@ -16,13 +16,13 @@
*/
package org.apache.felix.useradmin.impl;
-import org.apache.felix.useradmin.impl.RoleChecker;
-import org.apache.felix.useradmin.impl.RoleRepository;
-import org.apache.felix.useradmin.impl.role.GroupImpl;
-import org.apache.felix.useradmin.impl.role.UserImpl;
-
import junit.framework.TestCase;
+import org.apache.felix.useradmin.RoleFactory;
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+
/**
* Test cases for {@link RoleChecker}.
@@ -30,12 +30,13 @@
public class RoleCheckerTest extends TestCase {
private RoleChecker m_roleChecker;
+ private Role m_anyone;
/**
* Tests that a user always implies itself.
*/
public void testUserAlwaysImpliesItself() {
- UserImpl user = new UserImpl("foo");
+ User user = RoleFactory.createUser("foo");
assertTrue(m_roleChecker.isImpliedBy(user, user));
}
@@ -44,8 +45,8 @@
* Test that a user does never imply a group to which it is not a member.
*/
public void testUserDoesNotImplyNotImpliedGroup() {
- UserImpl user = new UserImpl("foo");
- GroupImpl group = new GroupImpl("bar");
+ User user = RoleFactory.createUser("foo");
+ Group group = RoleFactory.createGroup("bar");
assertFalse(m_roleChecker.isImpliedBy(user, group));
}
@@ -54,10 +55,10 @@
* Test that a user does never imply a group to which it is not a member.
*/
public void testUserImpliesImpliedGroup() {
- UserImpl user = new UserImpl("foo");
+ User user = RoleFactory.createUser("foo");
- GroupImpl group = new GroupImpl("bar");
- group.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group group = RoleFactory.createGroup("bar");
+ group.addRequiredMember(m_anyone);
group.addMember(user);
assertTrue(m_roleChecker.isImpliedBy(group, user));
@@ -67,9 +68,9 @@
* Test that a user does never imply a group to which it is not a member.
*/
public void testGroupDoesNotImplyNotImpliedUser() {
- UserImpl user = new UserImpl("foo");
+ User user = RoleFactory.createUser("foo");
- GroupImpl group = new GroupImpl("bar");
+ Group group = RoleFactory.createGroup("bar");
group.addMember(user);
assertFalse(m_roleChecker.isImpliedBy(user, group));
@@ -79,9 +80,9 @@
* Test that a group does never imply a group to which it is a required member.
*/
public void testGroupDoesNotImplySameRequiredGroup() {
- UserImpl user = new UserImpl("foo");
+ User user = RoleFactory.createUser("foo");
- GroupImpl group = new GroupImpl("bar");
+ Group group = RoleFactory.createGroup("bar");
group.addRequiredMember(group);
group.addMember(user);
@@ -92,9 +93,9 @@
* Test that a group does never imply a group to which it is a basic member.
*/
public void testGroupDoesNotImplySameGroup() {
- UserImpl user = new UserImpl("foo");
+ User user = RoleFactory.createUser("foo");
- GroupImpl group = new GroupImpl("bar");
+ Group group = RoleFactory.createGroup("bar");
group.addMember(group);
group.addMember(user);
@@ -105,25 +106,25 @@
* Test that a membership can be implied for users belonging to multiple required groups.
*/
public void testRequiredRolesMultipleRequiredGroupsOk() {
- UserImpl elmer = new UserImpl("elmer");
- UserImpl pepe = new UserImpl("pepe");
- UserImpl bugs = new UserImpl("bugs");
- UserImpl daffy = new UserImpl("daffy");
+ User elmer = RoleFactory.createUser("elmer");
+ User pepe = RoleFactory.createUser("pepe");
+ User bugs = RoleFactory.createUser("bugs");
+ User daffy = RoleFactory.createUser("daffy");
- GroupImpl administrators = new GroupImpl("administrators");
- administrators.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group administrators = RoleFactory.createGroup("administrators");
+ administrators.addRequiredMember(m_anyone);
administrators.addMember(elmer);
administrators.addMember(pepe);
administrators.addMember(bugs);
- GroupImpl family = new GroupImpl("family");
- family.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group family = RoleFactory.createGroup("family");
+ family.addRequiredMember(m_anyone);
family.addMember(elmer);
family.addMember(pepe);
family.addMember(daffy);
- GroupImpl alarmSystemActivation = new GroupImpl("alarmSystemActivation");
- alarmSystemActivation.addMember(RoleRepository.USER_ANYONE);
+ Group alarmSystemActivation = RoleFactory.createGroup("alarmSystemActivation");
+ alarmSystemActivation.addMember(m_anyone);
alarmSystemActivation.addRequiredMember(administrators);
alarmSystemActivation.addRequiredMember(family);
@@ -137,25 +138,25 @@
* Test that a membership can be implied for users belonging to multiple non-required groups.
*/
public void testRequiredRolesMultipleGroupsOk() {
- UserImpl elmer = new UserImpl("elmer");
- UserImpl pepe = new UserImpl("pepe");
- UserImpl bugs = new UserImpl("bugs");
- UserImpl daffy = new UserImpl("daffy");
+ User elmer = RoleFactory.createUser("elmer");
+ User pepe = RoleFactory.createUser("pepe");
+ User bugs = RoleFactory.createUser("bugs");
+ User daffy = RoleFactory.createUser("daffy");
- GroupImpl administrators = new GroupImpl("administrators");
- administrators.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group administrators = RoleFactory.createGroup("administrators");
+ administrators.addRequiredMember(m_anyone);
administrators.addMember(elmer);
administrators.addMember(pepe);
administrators.addMember(bugs);
- GroupImpl family = new GroupImpl("family");
- family.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group family = RoleFactory.createGroup("family");
+ family.addRequiredMember(m_anyone);
family.addMember(elmer);
family.addMember(pepe);
family.addMember(daffy);
- GroupImpl alarmSystemActivation = new GroupImpl("alarmSystemActivation");
- alarmSystemActivation.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group alarmSystemActivation = RoleFactory.createGroup("alarmSystemActivation");
+ alarmSystemActivation.addRequiredMember(m_anyone);
alarmSystemActivation.addMember(administrators);
alarmSystemActivation.addMember(family);
@@ -169,33 +170,33 @@
* Test that a membership can be implied for users belonging to multiple non-required groups.
*/
public void testVotersRequiredMembersOk() {
- GroupImpl citizens = new GroupImpl("citizen");
- citizens.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group citizens = RoleFactory.createGroup("citizen");
+ citizens.addRequiredMember(m_anyone);
- GroupImpl adults = new GroupImpl("adult");
- adults.addRequiredMember(RoleRepository.USER_ANYONE);
+ Group adults = RoleFactory.createGroup("adult");
+ adults.addRequiredMember(m_anyone);
- GroupImpl voters = new GroupImpl("voter");
+ Group voters = RoleFactory.createGroup("voter");
voters.addRequiredMember(citizens);
voters.addRequiredMember(adults);
- voters.addMember(RoleRepository.USER_ANYONE);
+ voters.addMember(m_anyone);
// Elmer belongs to the citizens and adults...
- UserImpl elmer = new UserImpl("elmer");
+ User elmer = RoleFactory.createUser("elmer");
citizens.addMember(elmer);
adults.addMember(elmer);
// Pepe belongs to the citizens, but is not an adult...
- UserImpl pepe = new UserImpl("pepe");
+ User pepe = RoleFactory.createUser("pepe");
citizens.addMember(pepe);
// Bugs is an adult, but is not a citizen...
- UserImpl bugs = new UserImpl("bugs");
+ User bugs = RoleFactory.createUser("bugs");
adults.addMember(bugs);
// Daffy is not an adult, neither a citizen...
- UserImpl daffy = new UserImpl("daffy");
+ User daffy = RoleFactory.createUser("daffy");
assertTrue(m_roleChecker.isImpliedBy(voters, elmer));
assertFalse(m_roleChecker.isImpliedBy(voters, pepe));
@@ -209,6 +210,8 @@
protected void setUp() throws Exception {
super.setUp();
+ m_anyone = RoleFactory.createRole(Role.USER_ANYONE);
+
m_roleChecker = new RoleChecker();
}
}
diff --git a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleRepositorySecurityTest.java b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleRepositorySecurityTest.java
index c6f1185..6ab743b 100644
--- a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleRepositorySecurityTest.java
+++ b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleRepositorySecurityTest.java
@@ -29,6 +29,8 @@
*/
public class RoleRepositorySecurityTest extends TestCase {
+ private static final String TEST_USER_NAME = "testUser";
+
private RoleRepository m_roleManager;
private TestSecurityManager m_securityManager;
@@ -37,8 +39,8 @@
*/
public void testAddRoleWithPermissionsOk() throws SecurityException {
m_securityManager.m_allowed = true;
-
- m_roleManager.addRole(RoleRepository.USER_ANYONE);
+
+ m_roleManager.addRole(TEST_USER_NAME, Role.USER);
}
/**
@@ -46,7 +48,7 @@
*/
public void testAddRoleWithoutPermissionsFails() throws SecurityException {
try {
- m_roleManager.addRole(RoleRepository.USER_ANYONE);
+ m_roleManager.addRole(TEST_USER_NAME, Role.USER);
fail("Expected SecurityException!");
} catch (SecurityException e) {
@@ -81,7 +83,7 @@
public void testRemoveRoleWithPermissionsOk() throws SecurityException {
m_securityManager.m_allowed = true;
- m_roleManager.removeRole(RoleRepository.USER_ANYONE);
+ m_roleManager.removeRole(TEST_USER_NAME);
}
/**
@@ -89,7 +91,7 @@
*/
public void testRemoveRoleWithoutPermissionsFails() throws SecurityException {
try {
- m_roleManager.removeRole(RoleRepository.USER_ANYONE);
+ m_roleManager.removeRole(TEST_USER_NAME);
fail("Expected SecurityException!");
} catch (SecurityException e) {
diff --git a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleRepositoryTest.java b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleRepositoryTest.java
index 1003bfa..6edd1c8 100644
--- a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleRepositoryTest.java
+++ b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/RoleRepositoryTest.java
@@ -20,39 +20,38 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Dictionary;
import java.util.List;
-import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import junit.framework.TestCase;
import org.apache.felix.framework.FilterImpl;
-import org.apache.felix.useradmin.impl.role.GroupImpl;
-import org.apache.felix.useradmin.impl.role.UserImpl;
import org.osgi.framework.Filter;
+import org.osgi.service.useradmin.Group;
import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
/**
* Test cases for {@link RoleRepository}.
*/
public class RoleRepositoryTest extends TestCase {
- private RoleRepository m_roleManager;
+ private RoleRepository m_roleRepository;
private CountDownLatch m_latch;
/**
* Tests whether adding a new role to a group causes an event to be emitted to the {@link RoleRepository}.
*/
public void testAddBasicRoleYieldsEventOk() throws Exception {
- final GroupImpl role = (GroupImpl) m_roleManager.addRole(new GroupImpl("foo"));
+ final Group role = (Group) m_roleRepository.addRole("foo", Role.GROUP);
m_latch = new CountDownLatch(1);
new Thread(new Runnable() {
public void run() {
- role.addMember(RoleRepository.USER_ANYONE);
+ Role anyone = m_roleRepository.getRoleByName(Role.USER_ANYONE);
+ role.addMember(anyone);
};
}).start();
@@ -64,7 +63,7 @@
*/
public void testAddNullRoleChangeListenerFail() throws Exception {
try {
- m_roleManager.addRoleChangeListener(null);
+ m_roleRepository.addRoleChangeListener(null);
fail("Expected IllegalArgumentException!");
} catch (IllegalArgumentException e) {
// Ok; expected...
@@ -75,22 +74,28 @@
* Tests that adding a predefined role is not allowed.
*/
public void testAddPredefineRoleFails() {
- Role role = RoleRepository.USER_ANYONE;
- assertNull(m_roleManager.addRole(role));
- assertEquals(0, m_roleManager.getRoles(null).size());
+ try {
+ assertNull(m_roleRepository.addRole(Role.USER_ANYONE, Role.ROLE));
+ fail("IllegalArgumentException expected!");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // Ok; expected
+ }
}
/**
* Tests whether adding a new role to a group causes an event to be emitted to the {@link RoleRepository}.
*/
public void testAddRequiredRoleYieldsEventOk() throws Exception {
- final GroupImpl role = (GroupImpl) m_roleManager.addRole(new GroupImpl("foo"));
+ final Group role = (Group) m_roleRepository.addRole("foo", Role.GROUP);
m_latch = new CountDownLatch(1);
new Thread(new Runnable() {
public void run() {
- role.addRequiredMember(RoleRepository.USER_ANYONE);
+ Role anyone = m_roleRepository.getRoleByName(Role.USER_ANYONE);
+ role.addRequiredMember(anyone);
};
}).start();
@@ -102,7 +107,7 @@
*/
public void testAddRoleChangeListenerOk() throws Exception {
// Should succeed...
- m_roleManager.addRoleChangeListener(new RoleChangeListener() {
+ m_roleRepository.addRoleChangeListener(new RoleChangeListener() {
public void propertyAdded(Role role, Object key, Object value) {
}
@@ -124,22 +129,19 @@
* Test method for {@link org.apache.felix.useradmin.impl.RoleRepository#addRole(Role)}.
*/
public void testAddRoleOfSameTypeTwiceFail() {
- UserImpl role = new UserImpl("foo");
+ assertNotNull(m_roleRepository.addRole("foo", Role.USER));
+ assertEquals(1, m_roleRepository.getRoles(null).size());
- assertSame(role, m_roleManager.addRole(role));
- assertEquals(1, m_roleManager.getRoles(null).size());
-
- assertNull(m_roleManager.addRole(role));
- assertEquals(1, m_roleManager.getRoles(null).size());
+ assertNull(m_roleRepository.addRole("foo", Role.USER));
+ assertEquals(1, m_roleRepository.getRoles(null).size());
}
/**
* Tests that adding a role works.
*/
public void testAddRoleOk() {
- UserImpl role = new UserImpl("foo");
- assertSame(role, m_roleManager.addRole(role));
- assertEquals(1, m_roleManager.getRoles(null).size());
+ assertNotNull(m_roleRepository.addRole("foo", Role.USER));
+ assertEquals(1, m_roleRepository.getRoles(null).size());
}
/**
@@ -148,7 +150,7 @@
public void testAddRolePropertyYieldsEventOk() throws Exception {
m_latch = new CountDownLatch(1);
- final Role role = m_roleManager.addRole(new UserImpl("john.doe"));
+ final Role role = m_roleRepository.addRole("john.doe", Role.USER);
new Thread(new Runnable() {
public void run() {
@@ -160,21 +162,11 @@
}
/**
- * Tests that adding a role that does not inherit from RoleImpl does not work and yields an exception.
+ * Tests that adding a null-role does not work and yields an exception.
*/
- public void testAddRoleWithInvalidRoleFail() {
+ public void testAddRoleWithNullRoleFail() {
try {
- m_roleManager.addRole(new Role() {
- public String getName() {
- return "A User";
- }
- public Dictionary getProperties() {
- return new Properties();
- }
- public int getType() {
- return Role.USER;
- }
- });
+ m_roleRepository.addRole(null, Role.USER);
fail("Exception expected!");
} catch (IllegalArgumentException e) {
@@ -183,11 +175,11 @@
}
/**
- * Tests that adding a null-role does not work and yields an exception.
+ * Tests that adding a role with an invalid type does not work and yields an exception.
*/
- public void testAddRoleWithNullRoleFail() {
+ public void testAddRoleWithInvalidRoleTypeFail() {
try {
- m_roleManager.addRole(null);
+ m_roleRepository.addRole("role", Role.ROLE);
fail("Exception expected!");
} catch (IllegalArgumentException e) {
@@ -199,14 +191,11 @@
* Test method for {@link org.apache.felix.useradmin.impl.RoleRepository#addRole(Role)}.
*/
public void testAddRoleWithSameNameTwiceFail() {
- UserImpl role1 = new UserImpl("foo");
- GroupImpl role2 = new GroupImpl("foo");
+ assertNotNull(m_roleRepository.addRole("foo", Role.USER));
+ assertEquals(1, m_roleRepository.getRoles(null).size());
- assertSame(role1, m_roleManager.addRole(role1));
- assertEquals(1, m_roleManager.getRoles(null).size());
-
- assertNull(m_roleManager.addRole(role2));
- assertEquals(1, m_roleManager.getRoles(null).size());
+ assertNull(m_roleRepository.addRole("foo", Role.GROUP));
+ assertEquals(1, m_roleRepository.getRoles(null).size());
}
/**
@@ -215,7 +204,7 @@
public void testAddUserCredentialYieldsEventOk() throws Exception {
m_latch = new CountDownLatch(1);
- final UserImpl role = (UserImpl) m_roleManager.addRole(new UserImpl("john.doe"));
+ final User role = (User) m_roleRepository.addRole("john.doe", Role.USER);
new Thread(new Runnable() {
public void run() {
@@ -230,7 +219,7 @@
* Tests whether changing an existing property to a role causes an event to be emitted to the {@link RoleRepository}.
*/
public void testChangeRolePropertyYieldsEventOk() throws Exception {
- final Role role = m_roleManager.addRole(new UserImpl("john.doe"));
+ final Role role = m_roleRepository.addRole("john.doe", Role.USER);
role.getProperties().put("key", "value");
m_latch = new CountDownLatch(1);
@@ -248,7 +237,7 @@
* Tests whether changing an existing credential for a user causes an event to be emitted to the {@link RoleRepository}.
*/
public void testChangeUserCredentialYieldsEventOk() throws Exception {
- final UserImpl role = (UserImpl) m_roleManager.addRole(new UserImpl("john.doe"));
+ final User role = (User) m_roleRepository.addRole("john.doe", Role.USER);
role.getCredentials().put("key", "value");
m_latch = new CountDownLatch(1);
@@ -266,85 +255,88 @@
* Test method for {@link org.apache.felix.useradmin.impl.RoleRepository#getRoleByName(java.lang.String)}.
*/
public void testGetRoleByName() {
- Role role1 = m_roleManager.addRole(new UserImpl("foo"));
- Role role2 = m_roleManager.addRole(new GroupImpl("bar"));
+ Role role1 = m_roleRepository.addRole("foo", Role.USER);
+ Role role2 = m_roleRepository.addRole("bar", Role.GROUP);
- assertSame(role1, m_roleManager.getRoleByName("foo"));
- assertSame(role2, m_roleManager.getRoleByName("bar"));
- assertNull(m_roleManager.getRoleByName("qux"));
+ assertEquals(role1, m_roleRepository.getRoleByName("foo"));
+ assertEquals(role2, m_roleRepository.getRoleByName("bar"));
+ assertNull(m_roleRepository.getRoleByName("qux"));
}
/**
* Test method for {@link org.apache.felix.useradmin.impl.RoleRepository#getRoles(org.osgi.framework.Filter)}.
*/
public void testGetRolesWithFilterOk() throws Exception {
- Role role1 = m_roleManager.addRole(new UserImpl("foo"));
+ Role role1 = m_roleRepository.addRole("foo", Role.USER);
role1.getProperties().put("key", "value1");
role1.getProperties().put("keyA", "valueA");
- Role role2 = m_roleManager.addRole(new GroupImpl("bar"));
+ Role role2 = m_roleRepository.addRole("bar", Role.GROUP);
role2.getProperties().put("key", "value2");
role2.getProperties().put("keyB", "value1");
Filter filter;
filter = new FilterImpl("(key=value1)");
- assertSameRoles(new Role[]{ role1 }, m_roleManager.getRoles(filter));
+ assertSameRoles(new Role[]{ role1 }, m_roleRepository.getRoles(filter));
filter = new FilterImpl("(key=value2)");
- assertSameRoles(new Role[]{ role2 }, m_roleManager.getRoles(filter));
+ assertSameRoles(new Role[]{ role2 }, m_roleRepository.getRoles(filter));
filter = new FilterImpl("(key=value*)");
- assertSameRoles(new Role[]{ role1, role2 }, m_roleManager.getRoles(filter));
+ assertSameRoles(new Role[]{ role1, role2 }, m_roleRepository.getRoles(filter));
filter = new FilterImpl("(|(key=value1)(keyB=value1))");
- assertSameRoles(new Role[]{ role1, role2 }, m_roleManager.getRoles(filter));
+ assertSameRoles(new Role[]{ role1, role2 }, m_roleRepository.getRoles(filter));
}
/**
* Test method for {@link org.apache.felix.useradmin.impl.RoleRepository#getRoles(String, String)}.
*/
public void testGetRolesWithKeyValuePairOk() throws Exception {
- Role role1 = m_roleManager.addRole(new UserImpl("foo"));
+ Role role1 = m_roleRepository.addRole("foo", Role.USER);
role1.getProperties().put("key", "value1");
role1.getProperties().put("keyA", "valueA");
- Role role2 = m_roleManager.addRole(new GroupImpl("bar"));
+ Role role2 = m_roleRepository.addRole("bar", Role.GROUP);
role2.getProperties().put("key", "value2");
role2.getProperties().put("keyB", "value1");
-
- assertSameRoles(new Role[]{ role1 }, m_roleManager.getRoles("key", "value1"));
- assertSameRoles(new Role[]{ role2 }, m_roleManager.getRoles("key", "value2"));
- assertSameRoles(new Role[0], m_roleManager.getRoles("key", "value"));
+
+ assertSameRoles(new Role[]{ role1 }, m_roleRepository.getRoles("key", "value1"));
+ assertSameRoles(new Role[]{ role2 }, m_roleRepository.getRoles("key", "value2"));
+ assertSameRoles(new Role[0], m_roleRepository.getRoles("key", "value"));
}
/**
* Test method for {@link org.apache.felix.useradmin.impl.RoleRepository#getRoles(org.osgi.framework.Filter)}.
*/
public void testGetRolesWithoutFilterOk() {
- Role role1 = m_roleManager.addRole(new UserImpl("foo"));
- Role role2 = m_roleManager.addRole(new GroupImpl("bar"));
+ Role role1 = m_roleRepository.addRole("foo", Role.USER);
+ Role role2 = m_roleRepository.addRole("bar", Role.GROUP);
- assertSameRoles(new Role[]{ role2, role1 }, m_roleManager.getRoles(null));
+ assertSameRoles(new Role[]{ role2, role1 }, m_roleRepository.getRoles(null));
}
/**
* Test method for {@link org.apache.felix.useradmin.impl.RoleRepository#getRoleByName(java.lang.String)}.
*/
public void testGetUserAnyoneRoleByName() {
- assertSame(RoleRepository.USER_ANYONE, m_roleManager.getRoleByName(Role.USER_ANYONE));
+ Role anyone = m_roleRepository.getRoleByName(Role.USER_ANYONE);
+ assertEquals(Role.USER_ANYONE, anyone.getName());
+ assertEquals(Role.ROLE, anyone.getType());
}
/**
* Tests whether removing a role from a group causes an event to be emitted to the {@link RoleRepository}.
*/
public void testRemoveBasicRoleYieldsEventOk() throws Exception {
- final GroupImpl role = (GroupImpl) m_roleManager.addRole(new GroupImpl("foo"));
- role.addMember(RoleRepository.USER_ANYONE);
+ final Role anyone = m_roleRepository.getRoleByName(Role.USER_ANYONE);
+ final Group role = (Group) m_roleRepository.addRole("bar", Role.GROUP);
+ role.addMember(anyone);
m_latch = new CountDownLatch(1);
new Thread(new Runnable() {
public void run() {
- role.removeMember(RoleRepository.USER_ANYONE);
+ role.removeMember(anyone);
};
}).start();
@@ -355,23 +347,20 @@
* Test method for {@link org.apache.felix.useradmin.impl.RoleRepository#removeRole(Role)}.
*/
public void testRemoveExistingRoleOk() {
- UserImpl role = new UserImpl("foo");
- assertSame(role, m_roleManager.addRole(role));
+ assertNotNull(m_roleRepository.addRole("foo", Role.USER));
- assertTrue(m_roleManager.removeRole(role));
- assertEquals(0, m_roleManager.getRoles(null).size());
+ assertTrue(m_roleRepository.removeRole("foo"));
+ assertEquals(0, m_roleRepository.getRoles(null).size());
}
/**
* Test method for {@link org.apache.felix.useradmin.impl.RoleRepository#removeRole(Role)}.
*/
public void testRemoveNonExistingRoleOk() {
- UserImpl role1 = new UserImpl("foo");
- UserImpl role2 = new UserImpl("bar");
- assertSame(role1, m_roleManager.addRole(role1));
+ assertNotNull(m_roleRepository.addRole("foo", Role.USER));
- assertFalse(m_roleManager.removeRole(role2));
- assertEquals(1, m_roleManager.getRoles(null).size());
+ assertFalse(m_roleRepository.removeRole("qux"));
+ assertEquals(1, m_roleRepository.getRoles(null).size());
}
/**
@@ -379,7 +368,7 @@
*/
public void testRemoveNullRoleChangeListenerFail() throws Exception {
try {
- m_roleManager.removeRoleChangeListener(null);
+ m_roleRepository.removeRoleChangeListener(null);
fail("Expected IllegalArgumentException!");
} catch (IllegalArgumentException e) {
// Ok; expected...
@@ -390,26 +379,26 @@
* Test method for {@link org.apache.felix.useradmin.impl.RoleRepository#removeRole(Role)}.
*/
public void testRemovePredefinedRoleFails() {
- m_roleManager.addRole(new UserImpl("foo"));
+ m_roleRepository.addRole("foo", Role.USER);
- Role role = RoleRepository.USER_ANYONE;
- assertFalse(m_roleManager.removeRole(role));
+ assertFalse(m_roleRepository.removeRole(Role.USER_ANYONE));
- assertEquals(1, m_roleManager.getRoles(null).size());
+ assertEquals(1, m_roleRepository.getRoles(null).size());
}
/**
* Tests whether removing a role from a group causes an event to be emitted to the {@link RoleRepository}.
*/
public void testRemoveRequiredRoleYieldsEventOk() throws Exception {
- final GroupImpl role = (GroupImpl) m_roleManager.addRole(new GroupImpl("foo"));
- role.addRequiredMember(RoleRepository.USER_ANYONE);
+ final Role anyone = m_roleRepository.getRoleByName(Role.USER_ANYONE);
+ final Group role = (Group) m_roleRepository.addRole("bar", Role.GROUP);
+ role.addRequiredMember(anyone);
m_latch = new CountDownLatch(1);
new Thread(new Runnable() {
public void run() {
- role.removeMember(RoleRepository.USER_ANYONE);
+ role.removeMember(anyone);
};
}).start();
@@ -421,7 +410,7 @@
*/
public void testRemoveRoleChangeListenerOk() throws Exception {
// Should succeed...
- m_roleManager.removeRoleChangeListener(new RoleChangeListener() {
+ m_roleRepository.removeRoleChangeListener(new RoleChangeListener() {
public void propertyAdded(Role role, Object key, Object value) {
}
@@ -443,7 +432,7 @@
* Tests whether removing a property from a role causes an event to be emitted to the {@link RoleRepository}.
*/
public void testRemoveRolePropertyYieldsEventOk() throws Exception {
- final Role role = m_roleManager.addRole(new UserImpl("john.doe"));
+ final Role role = m_roleRepository.addRole("john.doe", Role.USER);
role.getProperties().put("key", "value");
m_latch = new CountDownLatch(1);
@@ -458,34 +447,11 @@
}
/**
- * Tests that adding a role that does not inherit from RoleImpl does not work and yields an exception.
- */
- public void testRemoveRoleWithInvalidRoleFail() {
- try {
- m_roleManager.removeRole(new Role() {
- public String getName() {
- return "A User";
- }
- public Dictionary getProperties() {
- return new Properties();
- }
- public int getType() {
- return Role.USER;
- }
- });
-
- fail("Exception expected!");
- } catch (IllegalArgumentException e) {
- // Ok; expected
- }
- }
-
- /**
* Tests that removing a null-role does not work and yields an exception.
*/
public void testRemoveRoleWithNullRoleFail() {
try {
- m_roleManager.removeRole(null);
+ m_roleRepository.removeRole(null);
fail("Exception expected!");
} catch (IllegalArgumentException e) {
@@ -497,7 +463,7 @@
* Tests whether removing a credential from a user causes an event to be emitted to the {@link RoleRepository}.
*/
public void testRemoveUserCredentialYieldsEventOk() throws Exception {
- final UserImpl role = (UserImpl) m_roleManager.addRole(new UserImpl("john.doe"));
+ final User role = (User) m_roleRepository.addRole("john.doe", Role.USER);
role.getCredentials().put("key", "value");
m_latch = new CountDownLatch(1);
@@ -517,8 +483,8 @@
protected void setUp() throws Exception {
super.setUp();
- m_roleManager = new RoleRepository(new MemoryRoleRepositoryStore());
- m_roleManager.addRoleChangeListener(new RoleChangeListener() {
+ m_roleRepository = new RoleRepository(new MemoryRoleRepositoryStore());
+ m_roleRepository.addRoleChangeListener(new RoleChangeListener() {
public void propertyAdded(Role role, Object key, Object value) {
if (m_latch != null) {
m_latch.countDown();
@@ -549,8 +515,6 @@
}
}
});
-
- m_roleManager.start();
}
/**
diff --git a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/UserAdminImplTest.java b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/UserAdminImplTest.java
index 9bca211..610e7dd 100644
--- a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/UserAdminImplTest.java
+++ b/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/UserAdminImplTest.java
@@ -22,7 +22,7 @@
import junit.framework.TestCase;
import org.apache.felix.framework.FilterImpl;
-import org.apache.felix.useradmin.impl.role.UserImpl;
+import org.apache.felix.useradmin.RoleFactory;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.event.Event;
@@ -347,7 +347,8 @@
* Tests that obtaining the authorization for a non-existing user yields null.
*/
public void testGetAuthorizationForNonExistingUserOk() {
- Authorization auth = m_userAdmin.getAuthorization(new UserImpl("foo"));
+ User nonExistingUser = RoleFactory.createUser("non-existing-user");
+ Authorization auth = m_userAdmin.getAuthorization(nonExistingUser);
assertNotNull(auth);
@@ -865,8 +866,6 @@
return new FilterImpl(filter);
}
};
-
- m_roleRepository.start();
m_dispatcher.start();
}
@@ -874,7 +873,6 @@
* {@inheritDoc}
*/
protected void tearDown() throws Exception {
- m_roleRepository.stop();
m_dispatcher.stop();
super.tearDown();