| /** |
| * 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.framework.FrameworkUtil; |
| 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 Role getRoleByName(String roleName) throws Exception { |
| if (roleName == null) { |
| throw new IllegalArgumentException("Role name cannot be null!"); |
| } |
| return (Role) m_entries.get(roleName); |
| } |
| |
| public Role[] getRoles(String filterValue) throws Exception { |
| Collection roles = m_entries.values(); |
| |
| Filter filter = null; |
| if (filterValue != null) { |
| filter = FrameworkUtil.createFilter(filterValue); |
| } |
| |
| 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 removeRole(String roleName) throws Exception { |
| 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(); |
| } |
| } |
| }); |
| } |
| } |