You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2023/08/22 15:53:29 UTC

[felix-dev] branch master updated: Unmaintained code removal - useradmin

This is an automated email from the ASF dual-hosted git repository.

cziegeler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/felix-dev.git


The following commit(s) were added to refs/heads/master by this push:
     new 84c6980882 Unmaintained code removal - useradmin
84c6980882 is described below

commit 84c6980882a4071e93609de64390bc3b83c4f379
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue Aug 22 17:53:23 2023 +0200

    Unmaintained code removal - useradmin
---
 useradmin/filestore/pom.xml                        |  96 ---
 .../felix/useradmin/filestore/ResettableTimer.java | 123 ---
 .../filestore/RoleRepositoryFileStore.java         | 263 -------
 .../filestore/RoleRepositoryMemoryStore.java       |  86 --
 .../filestore/RoleRepositorySerializer.java        | 471 -----------
 .../felix/useradmin/filestore/StubGroupImpl.java   | 184 -----
 .../felix/useradmin/filestore/osgi/Activator.java  |  54 --
 .../filestore/src/main/resources/DEPENDENCIES      |  21 -
 useradmin/filestore/src/main/resources/LICENSE     | 202 -----
 useradmin/filestore/src/main/resources/NOTICE      |   7 -
 useradmin/filestore/src/main/resources/README      |  38 -
 .../useradmin/filestore/ResettableTimerTest.java   | 201 -----
 .../RoleRepositoryFileStorePerformanceTest.java    | 168 ----
 .../filestore/RoleRepositoryFileStoreTest.java     | 189 -----
 .../filestore/RoleRepositorySerializerTest.java    | 405 ----------
 .../useradmin/filestore/StubGroupImplTest.java     | 125 ---
 useradmin/itest/pom.xml                            | 173 ----
 .../felix/useradmin/itest/BaseIntegrationTest.java | 191 -----
 .../itest/FileStoreInitializationTest.java         | 103 ---
 .../felix/useradmin/itest/MongoDBStoreTest.java    | 201 -----
 .../useradmin/itest/UserAdminIntegrationTest.java  | 146 ----
 useradmin/itest/src/test/resources/logback.xml     |  33 -
 useradmin/mongodb/pom.xml                          | 107 ---
 .../apache/felix/useradmin/mongodb/KeyCodec.java   | 143 ----
 .../apache/felix/useradmin/mongodb/MongoDB.java    | 155 ----
 .../felix/useradmin/mongodb/MongoDBStore.java      | 381 ---------
 .../useradmin/mongodb/MongoSerializerHelper.java   | 267 -------
 .../felix/useradmin/mongodb/RoleProvider.java      |  33 -
 .../felix/useradmin/mongodb/osgi/Activator.java    |  64 --
 .../useradmin/mongodb/osgi/LogServiceHelper.java   |  77 --
 useradmin/mongodb/src/main/resources/DEPENDENCIES  |  26 -
 useradmin/mongodb/src/main/resources/LICENSE       | 202 -----
 useradmin/mongodb/src/main/resources/NOTICE        |   6 -
 useradmin/mongodb/src/main/resources/README        |  38 -
 .../felix/useradmin/mongodb/KeyCodecTest.java      | 202 -----
 useradmin/pom.xml                                  |  37 -
 useradmin/useradmin/pom.xml                        | 111 ---
 .../apache/felix/useradmin/BackendException.java   |  53 --
 .../org/apache/felix/useradmin/RoleFactory.java    |  89 ---
 .../felix/useradmin/RoleRepositoryStore.java       |  82 --
 .../felix/useradmin/impl/AuthorizationImpl.java    |  95 ---
 .../felix/useradmin/impl/EventDispatcher.java      | 226 ------
 .../felix/useradmin/impl/RoleChangeListener.java   |  66 --
 .../apache/felix/useradmin/impl/RoleChecker.java   | 112 ---
 .../felix/useradmin/impl/RoleRepository.java       | 394 ----------
 .../apache/felix/useradmin/impl/UserAdminImpl.java | 187 -----
 .../useradmin/impl/UserAdminListenerList.java      |  33 -
 .../felix/useradmin/impl/role/GroupImpl.java       | 160 ----
 .../useradmin/impl/role/ObservableDictionary.java  | 255 ------
 .../felix/useradmin/impl/role/ObservableGroup.java | 111 ---
 .../useradmin/impl/role/ObservableProperties.java  |  84 --
 .../felix/useradmin/impl/role/ObservableRole.java  | 173 ----
 .../felix/useradmin/impl/role/ObservableUser.java  |  67 --
 .../apache/felix/useradmin/impl/role/RoleImpl.java | 131 ----
 .../apache/felix/useradmin/impl/role/UserImpl.java | 112 ---
 .../org/apache/felix/useradmin/osgi/Activator.java |  76 --
 .../felix/useradmin/osgi/EventAdminHelper.java     |  68 --
 .../useradmin/osgi/RoleRepositoryStoreHelper.java  |  87 --
 .../felix/useradmin/osgi/ServiceContext.java       |  66 --
 .../osgi/UserAdminListenerListHelper.java          |  57 --
 .../useradmin/src/main/resources/DEPENDENCIES      |  21 -
 useradmin/useradmin/src/main/resources/LICENSE     | 202 -----
 useradmin/useradmin/src/main/resources/NOTICE      |   7 -
 useradmin/useradmin/src/main/resources/README      |  25 -
 .../useradmin/impl/AuthorizationImplTest.java      | 285 -------
 .../felix/useradmin/impl/CustomRoleImplTest.java   | 484 ------------
 .../felix/useradmin/impl/EventDispatcherTest.java  | 300 -------
 .../useradmin/impl/MemoryRoleRepositoryStore.java  |  85 --
 .../felix/useradmin/impl/RoleCheckerTest.java      | 217 -----
 .../useradmin/impl/RoleRepositorySecurityTest.java | 144 ----
 .../felix/useradmin/impl/RoleRepositoryTest.java   | 532 -------------
 .../felix/useradmin/impl/UserAdminImplTest.java    | 872 ---------------------
 .../useradmin/impl/role/GroupImplSecurityTest.java | 160 ----
 .../felix/useradmin/impl/role/GroupImplTest.java   | 196 -----
 .../role/ObservableDictionarySecurityTest.java     | 173 ----
 .../impl/role/ObservableDictionaryTest.java        | 247 ------
 .../impl/role/ObservablePropertiesTest.java        | 119 ---
 .../felix/useradmin/impl/role/RoleImplTest.java    |  96 ---
 .../felix/useradmin/impl/role/UserImplTest.java    | 100 ---
 79 files changed, 12378 deletions(-)

diff --git a/useradmin/filestore/pom.xml b/useradmin/filestore/pom.xml
deleted file mode 100644
index b7f1005325..0000000000
--- a/useradmin/filestore/pom.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<!--
-    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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<artifactId>felix-parent</artifactId>
-		<groupId>org.apache.felix</groupId>
-        <version>2.1</version>
-        <relativePath>../../../pom/pom.xml</relativePath>
-	</parent>
-	<artifactId>org.apache.felix.useradmin.filestore</artifactId>
-	<version>1.0.3-SNAPSHOT</version>
-	<packaging>bundle</packaging>
-	<description>Provides a file-based repository store for the UserAdmin OSGi compendium service.</description>
-	<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>
-		<dependency>
-			<groupId>org.apache.felix</groupId>
-			<artifactId>org.apache.felix.useradmin</artifactId>
-			<version>1.0.7-SNAPSHOT</version>
-			<type>bundle</type>
-		</dependency>
-	</dependencies>
-	<build>
-		<plugins>
-            <plugin>
-                <groupId>org.apache.rat</groupId>
-                <artifactId>apache-rat-plugin</artifactId>
-                <configuration>
-                    <includes>
-                        <include>src/**</include>
-                    </includes>
-                    <excludes>
-                        <exclude>src/main/resources/**</exclude>
-                    </excludes>
-                </configuration>
-            </plugin>
-			<plugin>
-				<groupId>org.apache.felix</groupId>
-				<artifactId>maven-bundle-plugin</artifactId>
-				<extensions>true</extensions>
-				<configuration>
-					<instructions>
-						<Bundle-Name>Apache Felix User Admin file-based repository store</Bundle-Name>
-						<Bundle-Description>
-							A file-based repository store for User Admin Service of Apache Felix.
-						</Bundle-Description>
-						<Bundle-Activator>
-							${project.artifactId}.osgi.Activator
-						</Bundle-Activator>
-						<Bundle-SymbolicName>
-							${project.artifactId}
-						</Bundle-SymbolicName>
-						<Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
-						<Import-Package>
-							org.osgi.service.useradmin; version="[1.1,1.2)",
-							org.apache.felix.useradmin; version="[1.0,1.1)",
-							*
-						</Import-Package>
-						<Export-Package>
-						</Export-Package>
-						<Private-Package>
-							${project.artifactId}.*
-						</Private-Package>
-					</instructions>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-</project>
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
deleted file mode 100644
index 512e8a80e8..0000000000
--- a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/ResettableTimer.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- *  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.filestore;
-
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Provides a timer that can be reset.
- */
-final class ResettableTimer {
-    private final ScheduledExecutorService m_executor;
-    private final Runnable m_task;
-    private final long m_timeout;
-    private final TimeUnit m_timeUnit;
-    private final AtomicReference m_futureRef;
-    
-    /**
-     * Creates a new {@link ResettableTimer} calling a given task when a given 
-     * timeout exceeds.
-     * 
-     * @param task the task to execute upon timout, cannot be <code>null</code>;
-     * @param timeout the timeout value, > 0;
-     * @param unit the time unit of the timeout value, cannot be <code>null</code>.
-     */
-    public ResettableTimer(Runnable task, long timeout, TimeUnit unit) {
-        this(new ScheduledThreadPoolExecutor(1), task, timeout, unit);
-    }
-    
-    /**
-     * Creates a new {@link ResettableTimer} calling a given task when a given 
-     * timeout exceeds.
-     * 
-     * @param executor the executor to use to execute the task, cannot be <code>null</code>;
-     * @param task the task to execute upon timout, cannot be <code>null</code>;
-     * @param timeout the timeout value, > 0;
-     * @param unit the time unit of the timeout value, cannot be <code>null</code>.
-     */
-    public ResettableTimer(ScheduledExecutorService executor, Runnable task, long timeout, TimeUnit unit) {
-        if (executor == null) { 
-            throw new IllegalArgumentException("Executor cannot be null!");
-        }
-        if (task == null) {
-            throw new IllegalArgumentException("Task cannot be null!");
-        }
-        if (timeout <= 0) { 
-            throw new IllegalArgumentException("Timeout cannot be negative!");
-        }
-        if (unit == null) { 
-            throw new IllegalArgumentException("TimeUnit cannot be null!"); 
-        }
-        
-        m_executor = executor;
-        m_task = task;
-        m_timeout = timeout;
-        m_timeUnit = unit;
-        
-        m_futureRef = new AtomicReference();
-    }
-
-    /**
-     * 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.
-     */
-    public ScheduledFuture schedule() {
-        ScheduledFuture currentTask = cancelCurrentTask();
-        ScheduledFuture newTask = m_executor.schedule(m_task, m_timeout, m_timeUnit);
-        m_futureRef.compareAndSet(currentTask, newTask);
-        return newTask;
-    }
-    
-    /**
-     * Shuts down this timer, allowing any pending tasks to execute. After this 
-     * method is called, {@link #schedule()} may no longer be called.
-     */
-    public void shutDown() {
-        m_executor.shutdown();
-        try {
-            m_executor.awaitTermination(2 * m_timeout, m_timeUnit);
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt();
-        }
-    }
-
-    /**
-     * @return the current task, or <code>null</code> if no task is available.
-     */
-    private ScheduledFuture cancelCurrentTask() {
-        ScheduledFuture currentTask = (ScheduledFuture) m_futureRef.get();
-        if (currentTask != null) {
-            // Doesn't matter for completed tasks...
-            currentTask.cancel(false /* mayInterruptIfRunning */);
-        }
-        return currentTask;
-    }
-}
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
deleted file mode 100644
index fbcb766cf8..0000000000
--- a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStore.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/**
- *  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.filestore;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.felix.useradmin.RoleRepositoryStore;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedService;
-import org.osgi.service.useradmin.UserAdminEvent;
-import org.osgi.service.useradmin.UserAdminListener;
-
-
-/**
- * Provides an implementation of {@link RoleRepositoryStore} using Java Serialization.
- */
-public class RoleRepositoryFileStore extends RoleRepositoryMemoryStore implements Runnable, UserAdminListener, ManagedService {
-
-    /** The PID for this service to allow its configuration to be updated. */
-    public static final String PID = "org.apache.felix.useradmin.filestore";
-
-    static final String KEY_WRITE_DISABLED = "background.write.disabled";
-    static final String KEY_WRITE_DELAY_VALUE = "background.write.delay.value";
-    static final String KEY_WRITE_DELAY_TIMEUNIT = "background.write.delay.timeunit";
-
-    private static final String PREFIX = PID.concat(".");
-    private static final boolean DEFAULT_WRITE_DISABLED = Boolean.parseBoolean(System.getProperty(PREFIX.concat(KEY_WRITE_DISABLED), "false"));
-    private static final int DEFAULT_WRITE_DELAY_VALUE = Integer.parseInt(System.getProperty(PREFIX.concat(KEY_WRITE_DELAY_VALUE), "500"));
-    private static final TimeUnit DEFAULT_WRITE_DELAY_TIMEUNIT = TimeUnit.MILLISECONDS;
-
-    private static final String FILE_NAME = "ua_repo.dat";
-
-    private final File m_file;
-    private final AtomicReference m_timerRef;
-
-    /**
-     * Creates a new {@link RoleRepositoryStore} instance.
-     * 
-     * @param baseDir the base directory where we can store our serialized data, cannot be <code>null</code>.
-     */
-    public RoleRepositoryFileStore(File baseDir) {
-        this(baseDir, !DEFAULT_WRITE_DISABLED);
-    }
-    
-    /**
-     * Creates a new {@link RoleRepositoryStore} instance.
-     * 
-     * @param baseDir the base directory where we can store our serialized data, cannot be <code>null</code>;
-     * @param backgroundWriteEnabled <code>true</code> if background writing should be enabled, <code>false</code> to disable it. 
-     */
-    public RoleRepositoryFileStore(File baseDir, boolean backgroundWriteEnabled) {
-        m_file = new File(baseDir, FILE_NAME);
-        
-        m_timerRef = new AtomicReference();
-
-        if (backgroundWriteEnabled) {
-            m_timerRef.set(new ResettableTimer(this, DEFAULT_WRITE_DELAY_VALUE, DEFAULT_WRITE_DELAY_TIMEUNIT));
-        }
-    }
-    
-    public void roleChanged(UserAdminEvent event) {
-        scheduleTask();
-    }
-
-    /**
-     * {@inheritDoc}
-     * 
-     * <p>Will be called by m_timer!</p>
-     */
-    public void run() {
-        try {
-            // Persist everything to disk...
-            flush();
-        }
-        catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * 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() throws IOException {
-        ResettableTimer timer = (ResettableTimer) m_timerRef.get();
-        if (timer != null) {
-            if (!timer.isShutDown()) {
-                // Shutdown and await termination...
-                timer.shutDown();
-            }
-            // Clear reference...
-            m_timerRef.compareAndSet(timer, null);
-        }
-
-        // Write the latest version to disk...
-        flush();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void updated(Dictionary properties) throws ConfigurationException {
-        boolean writeDisabled = DEFAULT_WRITE_DISABLED;
-        int writeDelayValue = DEFAULT_WRITE_DELAY_VALUE;
-        TimeUnit writeDelayUnit = DEFAULT_WRITE_DELAY_TIMEUNIT;
-
-        if (properties != null) {
-            Object wd = properties.get(KEY_WRITE_DISABLED);
-            if (wd == null) {
-                throw new ConfigurationException(KEY_WRITE_DISABLED, "Missing write disabled value!");
-            }
-            try {
-                writeDisabled = Boolean.parseBoolean((String) wd);
-            } catch (Exception e) {
-                throw new ConfigurationException(KEY_WRITE_DISABLED, "Invalid write disabled value!");
-            }
-
-            if (!writeDisabled) {
-                Object wdv = properties.get(KEY_WRITE_DELAY_VALUE);
-                if (wdv == null) {
-                    throw new ConfigurationException(KEY_WRITE_DELAY_VALUE, "Missing write delay value!");
-                }
-                try {
-                    writeDelayValue = Integer.parseInt((String) wdv);
-                } catch (Exception e) {
-                    throw new ConfigurationException(KEY_WRITE_DELAY_VALUE, "Invalid write delay value!");
-                }
-                if (writeDelayValue <= 0) {
-                    throw new ConfigurationException(KEY_WRITE_DELAY_VALUE, "Invalid write delay value!");
-                }
-
-                Object wdu = properties.get(KEY_WRITE_DELAY_TIMEUNIT);
-                if (wdu != null) {
-                    try {
-                        writeDelayUnit = TimeUnit.valueOf(((String) wdu).toUpperCase());
-                    } catch (Exception e) {
-                        throw new ConfigurationException(KEY_WRITE_DELAY_TIMEUNIT, "Invalid write delay unit!");
-                    }
-                }
-            }
-        }
-
-        ResettableTimer timer = (ResettableTimer) m_timerRef.get();
-        if (timer != null) {
-            timer.shutDown();
-        }
-        m_timerRef.compareAndSet(timer, writeDisabled ? null : new ResettableTimer(this, writeDelayValue, writeDelayUnit));
-    }
-
-    /**
-     * Retrieves the serialized repository from disk.
-     * 
-     * @return the retrieved repository, never <code>null</code>.
-     * @throws IOException in case the retrieval of the repository failed.
-     */
-    protected Map retrieve() throws IOException {
-        InputStream is = null;
-
-        try {
-            is = new BufferedInputStream(new FileInputStream(m_file));
-
-            return new RoleRepositorySerializer().deserialize(is);
-        } catch (FileNotFoundException exception) {
-            // Don't bother; file does not exist...
-            return Collections.emptyMap();
-        } catch (IOException exception) {
-            exception.printStackTrace();
-            throw exception;
-        } finally {
-            closeSafely(is);
-        }
-    }
-
-    /**
-     * Stores the given repository to disk as serialized objects.
-     * 
-     * @param roleRepository the repository to store, cannot be <code>null</code>.
-     * @throws IOException in case storing the repository failed.
-     */
-    protected void store(Map roleRepository) throws IOException {
-        OutputStream os = null;
-
-        try {
-            os = new BufferedOutputStream(new FileOutputStream(m_file));
-
-            new RoleRepositorySerializer().serialize(roleRepository, os);
-        } finally {
-            closeSafely(os);
-        }
-    }
-
-    /**
-     * Closes a given resource, ignoring any exceptions that may come out of this.
-     * 
-     * @param resource the resource to close, can be <code>null</code>.
-     */
-    private void closeSafely(Closeable resource) {
-        if (resource != null) {
-            try {
-                resource.close();
-            } catch (IOException e) {
-                // Ignore
-            }
-        }
-    }
-
-    /**
-     * Flushes the current repository to disk.
-     * 
-     * @throws IOException in case of problems storing the repository.
-     */
-    private void flush() throws IOException {
-        store(new HashMap(m_entries));
-    }
-
-    /**
-     * Notifies the background timer to schedule a task for storing the 
-     * contents of this store to disk.
-     */
-    private void scheduleTask() {
-        ResettableTimer timer = (ResettableTimer) m_timerRef.get();
-        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
deleted file mode 100644
index 291b15ad38..0000000000
--- a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositoryMemoryStore.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- *  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.filestore;
-
-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.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.useradmin.Role;
-
-
-/**
- * Provides a thread-safe in-memory role repository store.
- */
-public class RoleRepositoryMemoryStore implements RoleRepositoryStore {
-    
-    protected final ConcurrentMap m_entries = new ConcurrentHashMap();
-
-    public Role addRole(String roleName, int type) {
-        if (roleName == null) {
-            throw new IllegalArgumentException("Name cannot be null!");
-        }
-        Role role = RoleFactory.createRole(type, roleName);
-        Object result = m_entries.putIfAbsent(roleName, role);
-        return (result == null) ? role : null;
-    }
-
-    public Role[] getRoles(String filterValue) throws InvalidSyntaxException {
-        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 getRoleByName(String roleName) {
-        if (roleName == null) {
-            throw new IllegalArgumentException("Role name cannot be null!");
-        }
-        return (Role) m_entries.get(roleName);
-    }
-
-    public Role removeRole(String roleName) {
-        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;
-    }
-}
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
deleted file mode 100644
index e4ecaad801..0000000000
--- a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/RoleRepositorySerializer.java
+++ /dev/null
@@ -1,471 +0,0 @@
-/**
- *  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.filestore;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-
-import org.apache.felix.useradmin.RoleFactory;
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-
-/**
- * Provides a serializer for a role repository.
- */
-final class RoleRepositorySerializer {
-    
-    private static final int VALUE_TYPE_STRING = 1;
-    private static final int VALUE_TYPE_BARRAY = 2; 
-
-    /**
-     * Deserializes a given input stream.
-     * 
-     * @param is the input stream to deserialize, cannot be <code>null</code>.
-     * @return a {@link Map} representing the role repository. It provides a 
-     *         mapping between the name of the role as key and the associated
-     *         role as value.
-     * @throws IOException in case of I/O problems;
-     * @throws IllegalArgumentException in case the given stream was <code>null</code>.
-     */
-    public Map deserialize(InputStream is) throws IOException {
-        if (is == null) {
-            throw new IllegalArgumentException("InputStream cannot be null!");
-        }
-        return readRepository(new DataInputStream(is));
-    }
-
-    /**
-     * Serializes a given map to the given output stream.
-     * 
-     * @param roleRepository the repository to serialize, cannot be <code>null</code>;
-     * @param os the output stream to serialize to, cannot be  <code>null</code>.
-     * @throws IOException in case of I/O problems;
-     * @throws IllegalArgumentException in case the given parameter was <code>null</code>.
-     */
-    public void serialize(Map roleRepository, OutputStream os) throws IOException {
-        if (roleRepository == null) {
-            throw new IllegalArgumentException("Map cannot be null!");
-        }
-        if (os == null) {
-            throw new IllegalArgumentException("OutputStream cannot be null!");
-        }
-        writeRepository(roleRepository, new DataOutputStream(os));
-    }
-    
-    /**
-     * Adds all groups, based on the given stub groups.
-     * 
-     * @param repository the repository to add the groups to, cannot be <code>null</code>;
-     * @param stubGroups the list with stub groups to replace, cannot be <code>null</code>.
-     * @throws IOException in case a referenced role was not found in the repository.
-     */
-    private void addGroups(Map repository, List stubGroups) throws IOException {
-        // First create "empty" groups in the repository; we'll fill them in later on...
-        Iterator sgIter = stubGroups.iterator();
-        while (sgIter.hasNext()) {
-            StubGroupImpl stubGroup = (StubGroupImpl) sgIter.next();
-
-            Group group = (Group) RoleFactory.createRole(Role.GROUP, stubGroup.getName());
-            copyDictionary(stubGroup.getProperties(), group.getProperties());
-            copyDictionary(stubGroup.getCredentials(), group.getCredentials());
-
-            repository.put(group.getName(), group);
-        }
-        
-        int origSize = stubGroups.size();
-        while (!stubGroups.isEmpty()) {
-            List copy = new ArrayList(stubGroups);
-            
-            int size = copy.size();
-            for (int i = 0; i < size; i++) {
-                StubGroupImpl stubGroup = (StubGroupImpl) copy.get(i);
-
-                Group group = (Group) repository.get(stubGroup.getName());
-                if (group != null) {
-                    resolveGroupMembers(stubGroup, group, repository);
-                    stubGroups.remove(stubGroup);
-                }
-            }
-
-            // In case we didn't resolve any groups; we should fail...
-            if (origSize == stubGroups.size()) {
-                throw new IOException("Failed to resolve groups: " + stubGroups);
-            }
-
-            origSize = stubGroups.size();
-        }
-    }
-    
-    /**
-     * 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 Map convertToMap(Dictionary dictionary) {
-        Map result = new HashMap();
-        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;
-    }
-    
-    /**
-     * Copies the contents of a given dictionary to a given other dictionary.
-     * 
-     * @param source the dictionary to copy from;
-     * @param dest the dictionary to copy to.
-     */
-    private void copyDictionary(Dictionary source, Dictionary dest) {
-        Enumeration keys = source.keys();
-        while (keys.hasMoreElements()) {
-            Object key = keys.nextElement();
-            Object value = source.get(key);
-            dest.put(key, value);
-        }
-    }
-
-    /**
-     * 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>;
-     * @param dis the input stream to read the data from, cannot be <code>null</code>.
-     * @throws IOException in case of I/O problems.
-     */
-    private void readDictionary(Dictionary dict, DataInputStream dis) throws IOException {
-        // Read the number of entries...
-        int count = dis.readInt();
-        while (count-- > 0) {
-            // Read the name of the key...
-            String key = dis.readUTF();
-            // Read the type of the value...
-            int type = dis.read();
-            // Read the value & add the actual entry...
-            if (VALUE_TYPE_BARRAY == type) {
-                int length = dis.readInt();
-                byte[] value = new byte[length];
-                if (dis.read(value, 0, length) != length) {
-                    throw new IOException("Invalid repository; failed to correctly read dictionary!");
-                }
-                dict.put(key, value);
-            } else if (VALUE_TYPE_STRING == type) {
-                dict.put(key, dis.readUTF());
-            }
-        }
-    }
-
-    /**
-     * Reads a (stub) group from the given input stream.
-     * 
-     * @param dis the input stream to read the data from, cannot be <code>null</code>.
-     * @return the read (stub) group, never <code>null</code>.
-     * @throws IOException in case of I/O problems.
-     */
-    private StubGroupImpl readGroup(DataInputStream dis) throws IOException {
-        StubGroupImpl group = new StubGroupImpl(dis.readUTF());
-        
-        readDictionary(group.getProperties(), dis);
-        readDictionary(group.getCredentials(), dis);
-        
-        // Read the number of basic members...
-        int count = dis.readInt();
-        while (count-- > 0) {
-            group.addMember(dis.readUTF());
-        }
-        
-        // Read the number of required members...
-        count = dis.readInt();
-        while (count-- > 0) {
-            group.addRequiredMember(dis.readUTF());
-        }
-        
-        return group;
-    }
-
-    /**
-     * Reads the entire repository from the given input stream.
-     * 
-     * @param dis the input stream to read the data from, cannot be <code>null</code>.
-     * @return the repository {@link Map}, never <code>null</code>.
-     * @throws IOException in case of I/O problems.
-     */
-    private Map readRepository(DataInputStream dis) throws IOException {
-        Map repository = new HashMap();
-        
-        int entryCount = dis.readInt();
-        
-        List stubGroups = new ArrayList();
-        
-        // Keep reading until no more types can be read...
-        while (entryCount-- > 0) {
-            int type = dis.readInt();
-            
-            Role role = null;
-            if (Role.GROUP == type) {
-                stubGroups.add(readGroup(dis));
-            } else if (Role.USER == type) {
-                role = readUser(dis);
-            } else {
-                role = readRole(dis);
-            }
-            
-            if (role != null) {
-                repository.put(role.getName(), role);
-            }
-        }
-        
-        // Post processing stage: replace all stub groups with real group implementations...
-        addGroups(repository, stubGroups);
-        
-        return repository;
-    }
-    
-    /**
-     * Reads a role from the given input stream.
-     * 
-     * @param dis the input stream to read the data from, cannot be <code>null</code>.
-     * @return the read role, never <code>null</code>.
-     * @throws IOException in case of I/O problems.
-     */
-    private Role readRole(DataInputStream dis) throws IOException {
-        Role role = RoleFactory.createRole(Role.ROLE, dis.readUTF());
-        
-        readDictionary(role.getProperties(), dis);
-        
-        return role;
-    }
-
-    /**
-     * Reads a user from the given input stream.
-     * 
-     * @param dis the input stream to read the data from, cannot be <code>null</code>.
-     * @return the read user, never <code>null</code>.
-     * @throws IOException in case of I/O problems.
-     */
-    private User readUser(DataInputStream dis) throws IOException {
-        User user = (User) RoleFactory.createRole(Role.USER, dis.readUTF());
-        
-        readDictionary(user.getProperties(), dis);
-        readDictionary(user.getCredentials(), dis);
-        
-        return user;
-    }
-
-    /**
-     * Resolves all basic and required group members for a given group, based on the names from the given stub group.
-     * 
-     * @param stubGroup the stub group to convert, cannot be <code>null</code>;
-     * @param repository the repository to take the roles from, cannot be <code>null</code>.
-     * @return a concrete {@link Group} instance with all members resolved, or <code>null</code> if not all members could be resolved.
-     * @throws IOException in case a referenced role was not found in the repository.
-     */
-    private void resolveGroupMembers(StubGroupImpl stubGroup, Group group, Map repository) throws IOException {
-        List names = stubGroup.getMemberNames();
-        int size = names.size();
-
-        for (int i = 0; i < size; i++) {
-            String name = (String) names.get(i);
-            Role role = getRoleFromRepository(repository, name);
-            if (role == null) {
-                throw new IOException("Unable to find referenced basic member: " + name);
-            }
-            group.addMember(role);
-        }
-        
-        names = stubGroup.getRequiredMemberNames();
-        size = names.size();
-        
-        for (int i = 0; i < size; i++) {
-            String name = (String) names.get(i);
-            Role role = getRoleFromRepository(repository, name);
-            if (role == null) {
-                throw new IOException("Unable to find referenced required member: " + name);
-            }
-            group.addRequiredMember(role);
-        }
-    }
-
-    /**
-     * Writes a given dictionary to the given output stream.
-     * 
-     * @param dict the dictionary to write, cannot be <code>null</code>;
-     * @param dos the output stream to write the data to, cannot be <code>null</code>.
-     * @throws IOException in case of I/O problems.
-     */
-    private void writeDictionary(Dictionary dict, DataOutputStream dos) throws IOException {
-        Map properties = convertToMap(dict);
-        
-        Set entries = properties.entrySet();
-        int size = entries.size();
-
-        // Write the number of entries...
-        dos.writeInt(size);
-        
-        Iterator entriesIter = entries.iterator();
-        while (entriesIter.hasNext()) {
-            Map.Entry entry = (Entry) entriesIter.next();
-            
-            dos.writeUTF((String) entry.getKey());
-            
-            Object value = entry.getValue();
-            if (value instanceof String) {
-                dos.write(VALUE_TYPE_STRING);
-                dos.writeUTF((String) value);
-            } else if (value instanceof byte[]) {
-                dos.write(VALUE_TYPE_BARRAY);
-                dos.writeInt(((byte[]) value).length);
-                dos.write((byte[]) value);
-            }
-        }
-    }
-
-    /**
-     * Writes a given group to the given output stream.
-     * 
-     * @param group the group to write, cannot be <code>null</code>.
-     * @param dos the output stream to write the data to, cannot be <code>null</code>.
-     * @throws IOException in case of I/O problems.
-     */
-    private void writeGroup(Group group, DataOutputStream dos) throws IOException {
-        dos.writeUTF(group.getName());
-
-        writeDictionary(group.getProperties(), dos);
-        writeDictionary(group.getCredentials(), dos);
-        
-        Role[] m = group.getMembers();
-
-        if (m == null) {
-            dos.writeInt(0);
-        } else {
-            // Write the number of basic members...
-            dos.writeInt(m.length);
-            // Write the names of the basic members...
-            for (int i = 0; i < m.length; i++) {
-                dos.writeUTF(m[i].getName());
-            }
-        }
-
-        m = group.getRequiredMembers();
-        
-        if (m == null) {
-            dos.writeInt(0);
-        } else {
-            // Write the number of required members...
-            dos.writeInt(m.length);
-            // Write the names of the required members...
-            for (int i = 0; i < m.length; i++) {
-                dos.writeUTF(m[i].getName());
-            }
-        }
-    }
-    
-    /**
-     * Writes the given repository to the given output stream.
-     * 
-     * @param repository the repository to write, cannot be <code>null</code>;
-     * @param dos the output stream to write the data to, cannot be <code>null</code>.
-     * @throws IOException in case of I/O problems.
-     */
-    private void writeRepository(Map repository, DataOutputStream dos) throws IOException {
-        Collection values = repository.values();
-        Iterator valuesIter = values.iterator();
-        
-        // Write the total number of entries in our repository first...
-        dos.writeInt(values.size());
-        
-        while (valuesIter.hasNext()) {
-            Role role = (Role) valuesIter.next();
-            
-            int type = role.getType();
-            
-            dos.writeInt(type);
-            
-            if (Role.GROUP == type) {
-                writeGroup((Group) role, dos);
-            } else if (Role.USER == type) {
-                writeUser((User) role, dos);
-            } else {
-                writeRole(role, dos);
-            }
-        }
-    }
-    
-    /**
-     * Writes a given role to the given output stream.
-     * 
-     * @param role the role to write, cannot be <code>null</code>.
-     * @param dos the output stream to write the data to, cannot be <code>null</code>.
-     * @throws IOException in case of I/O problems.
-     */
-    private void writeRole(Role role, DataOutputStream dos) throws IOException {
-        dos.writeUTF(role.getName());
-
-        writeDictionary(role.getProperties(), dos);
-    }
-    
-    /**
-     * Writes a given user to the given output stream.
-     * 
-     * @param user the user to write, cannot be <code>null</code>.
-     * @param dos the output stream to write the data to, cannot be <code>null</code>.
-     * @throws IOException in case of I/O problems.
-     */
-    private void writeUser(User user, DataOutputStream dos) throws IOException {
-        dos.writeUTF(user.getName());
-
-        writeDictionary(user.getProperties(), dos);
-        writeDictionary(user.getCredentials(), dos);
-    }
-}
diff --git a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/StubGroupImpl.java b/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/StubGroupImpl.java
deleted file mode 100644
index cb0a76833a..0000000000
--- a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/StubGroupImpl.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/**
- *  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.filestore;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.List;
-import java.util.Properties;
-
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-
-/**
- * Provides a stub group that has "weak" references (based on their names) to its basic/required members.
- */
-final class StubGroupImpl implements Group {
-    
-    private final String m_name;
-    private final List m_basicMembers;
-    private final List m_requiredMembers;
-    private final Dictionary m_credentials;
-    private final Dictionary m_properties;
-
-    /**
-     * Creates a new {@link StubGroupImpl} instance.
-     */
-    public StubGroupImpl(String name) {
-        m_name = name;
-        m_properties = new Properties();
-        m_credentials = new Properties();
-        m_basicMembers = new ArrayList();
-        m_requiredMembers = new ArrayList();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean addMember(Role role) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean addMember(String roleName) {
-        return m_basicMembers.add(roleName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean addRequiredMember(Role role) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean addRequiredMember(String roleName) {
-        return m_requiredMembers.add(roleName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((m_name == null) ? 0 : m_name.hashCode());
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        StubGroupImpl other = (StubGroupImpl) obj;
-        if (m_name == null) {
-            if (other.m_name != null) {
-                return false;
-            }
-        } else if (!m_name.equals(other.m_name)) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Dictionary getCredentials() {
-        return m_credentials;
-    }
-
-    /**
-     * Returns the names of all basic members.
-     * 
-     * @return a list with basic member names (as String!), never <code>null</code>.
-     */
-    public List getMemberNames() {
-        return m_basicMembers;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Role[] getMembers() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getName() {
-        return m_name;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Dictionary getProperties() {
-        return m_properties;
-    }
-
-    /**
-     * Returns the names of all required members.
-     * 
-     * @return a list with required member names (as String!), never <code>null</code>.
-     */
-    public List getRequiredMemberNames() {
-        return m_requiredMembers;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Role[] getRequiredMembers() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getType() {
-        return Role.GROUP;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean hasCredential(String key, Object value) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean removeMember(Role role) {
-        throw new UnsupportedOperationException();
-    }
-}
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
deleted file mode 100644
index a63223f5c7..0000000000
--- a/useradmin/filestore/src/main/java/org/apache/felix/useradmin/filestore/osgi/Activator.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- *  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.filestore.osgi;
-
-import java.util.Properties;
-
-import org.apache.felix.useradmin.RoleRepositoryStore;
-import org.apache.felix.useradmin.filestore.RoleRepositoryFileStore;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.service.cm.ManagedService;
-import org.osgi.service.useradmin.UserAdminListener;
-
-/**
- * Registers the {@link RoleRepositoryFileStore} as {@link RoleRepositoryStore} service.
- */
-public class Activator implements BundleActivator {
-
-    private RoleRepositoryFileStore m_store;
-
-    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() };
-        
-        Properties props = new Properties();
-        props.put(Constants.SERVICE_PID, RoleRepositoryFileStore.PID);
-
-        context.registerService(interfaces, m_store, props);
-    }
-
-    public void stop(BundleContext context) throws Exception {
-        if (m_store != null) {
-            m_store.stop();
-            m_store = null;
-        }
-    }
-}
diff --git a/useradmin/filestore/src/main/resources/DEPENDENCIES b/useradmin/filestore/src/main/resources/DEPENDENCIES
deleted file mode 100644
index 01bcec327a..0000000000
--- a/useradmin/filestore/src/main/resources/DEPENDENCIES
+++ /dev/null
@@ -1,21 +0,0 @@
-Apache Felix UserAdmin File-based Store
-Copyright 2012 The Apache Software Foundation
-
-This software was developed at the Apache Software Foundation
-(http://www.apache.org) and may have dependencies on other
-Apache software licensed under Apache License 2.0.
-
-I. Included Third-Party Software
-
-n/a
-
-II. Used Third-Party Software
-
-This product includes software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2009).
-Licensed under the Apache License 2.0.
-
-III. Overall License Summary
-- Apache License 2.0
-
diff --git a/useradmin/filestore/src/main/resources/LICENSE b/useradmin/filestore/src/main/resources/LICENSE
deleted file mode 100644
index d645695673..0000000000
--- a/useradmin/filestore/src/main/resources/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/useradmin/filestore/src/main/resources/NOTICE b/useradmin/filestore/src/main/resources/NOTICE
deleted file mode 100644
index a28164d024..0000000000
--- a/useradmin/filestore/src/main/resources/NOTICE
+++ /dev/null
@@ -1,7 +0,0 @@
-Apache Felix User Admin File-based store
-Copyright 2012 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
diff --git a/useradmin/filestore/src/main/resources/README b/useradmin/filestore/src/main/resources/README
deleted file mode 100644
index be57165aad..0000000000
--- a/useradmin/filestore/src/main/resources/README
+++ /dev/null
@@ -1,38 +0,0 @@
-Apache Felix User Admin File-based store
-Copyright 2012 The Apache Software Foundation
-
-This bundle provides a file-based store for use with the Felix UserAdmin
-service. It uses a binary file-format to persist the role information. This
-file will always be written in the data area of the bundle and be called
-"ua_repo.dat".
-
-The file-based store service this bundle provides can be configured at 
-runtime by using the service PID "org.apache.felix.useradmin.filestore". The 
-configuration options recognized by this service are:
-
-"background.write.disabled"
-   by default, all changes made to the UserAdmin repository are flushed to
-   disk. By setting this value to "false", this no longer will happen for each
-   change, but only upon stopping of the service. This value is optional and 
-   defaults to "false";
-"background.write.delay.value"
-   denotes the period after which the changes should be persisted to disk. If
-   other changes to the repository occur during this period, the period will
-   start over. This value is optional and defaults to "500";
-"background.write.delay.timeunit"
-   denotes the time unit for "background.write.delay.value". This value is
-   optional and defaults to "milliseconds". Possible values are: "days", 
-   "hours", "minutes", "seconds", "milliseconds", "microseconds" and 
-   "nanoseconds".
-
-Alternatively, one can also supply the above mentioned configuration keys 
-prefixed with "org.apache.felix.useradmin.filestore." as system properties. 
-For example by adding the following to your JVM arguments:
-
-  -Dorg.apache.felix.useradmin.filestore.background.write.disabled=true
-  
-will disable persisting the changes on each change of the UserAdmin roles.
-
-However, using system properties will imply that only a single store can be 
-configured on a system (which could be a sensible default for some 
-situations)!
diff --git a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/ResettableTimerTest.java b/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/ResettableTimerTest.java
deleted file mode 100644
index 9193054259..0000000000
--- a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/ResettableTimerTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/**
- *  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.filestore;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link ResettableTimer}.
- */
-public class ResettableTimerTest extends TestCase {
-
-    private ResettableTimer m_timer;
-    private CountDownLatch m_latch;
-
-    /**
-     * Tests that a executor service is mandatory.
-     */
-    public void testExecutorSerivceIsMandatory() throws Exception {
-        Runnable task = createStubTask();
-
-        try {
-            new ResettableTimer(null, task, 10, TimeUnit.HOURS);
-            fail("IllegalArgumentException expected!");
-        } catch (Exception e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that multiple calls to {@link ResettableTimer#schedule()} causes 
-     * pending tasks to be cancelled.
-     */
-    public void testScheduleCancelsPendingTasksOk() throws Exception {
-        final AtomicInteger m_counter = new AtomicInteger(0);
-
-        Runnable task = new Runnable() {
-            public void run() {
-                m_counter.incrementAndGet();
-            }
-        };
-        
-        m_timer = new ResettableTimer(task, 100, TimeUnit.MILLISECONDS);
-        m_timer.schedule();
-
-        TimeUnit.MILLISECONDS.sleep(75);
-        
-        Future f = m_timer.schedule();
-        f.get();
-
-        assertEquals(1, m_counter.get());
-    }
-
-    /**
-     * Test method for {@link org.apache.felix.useradmin.impl.ResettableTimer#schedule()}.
-     */
-    public void testScheduleMultipleTasksOk() throws Exception {
-        final AtomicInteger m_counter = new AtomicInteger(0);
-
-        Runnable task = new Runnable() {
-            public void run() {
-                m_counter.incrementAndGet();
-            }
-        };
-
-        m_timer = new ResettableTimer(task, 100, TimeUnit.MILLISECONDS);
-        
-        Future f = m_timer.schedule();
-        f.get();
-
-        f = m_timer.schedule();
-        f.get();
-
-        assertEquals(2, m_counter.get());
-    }
-
-    /**
-     * Tests that a task is invoked as single shot.
-     */
-    public void testScheduleSingleShotOk() throws Exception {
-        m_latch = new CountDownLatch(1);
-
-        Runnable task = new Runnable() {
-            public void run() {
-                m_latch.countDown();
-            }
-        };
-
-        m_timer = new ResettableTimer(task, 100, TimeUnit.MILLISECONDS);
-        m_timer.schedule();
-
-        assertTrue(m_latch.await(200, TimeUnit.MILLISECONDS));
-    }
-
-    /**
-     * Test method for {@link org.apache.felix.useradmin.impl.ResettableTimer#shutDown()}.
-     */
-    public void testShutDownOk() throws Exception {
-        final AtomicInteger m_counter = new AtomicInteger(0);
-
-        Runnable task = new Runnable() {
-            public void run() {
-                m_counter.incrementAndGet();
-            }
-        };
-        
-        m_timer = new ResettableTimer(task, 100, TimeUnit.MILLISECONDS);
-        m_timer.schedule();
-
-        TimeUnit.MILLISECONDS.sleep(75);
-        
-        m_timer.schedule();
-        m_timer.shutDown();
-
-        assertEquals(1, m_counter.get());
-    }
-
-    /**
-     * Tests that a task is mandatory.
-     */
-    public void testTaskIsMandatory() throws Exception {
-        try {
-            new ResettableTimer(null, 10, TimeUnit.HOURS);
-            fail("IllegalArgumentException expected!");
-        } catch (Exception e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that a timeout cannot be zero.
-     */
-    public void testTimeoutCannotBeNegative() throws Exception {
-        Runnable task = createStubTask();
-
-        try {
-            new ResettableTimer(task, -1, TimeUnit.MILLISECONDS);
-            fail("IllegalArgumentException expected!");
-        } catch (Exception e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that a timeout cannot be zero.
-     */
-    public void testTimeoutCannotBeZero() throws Exception {
-        Runnable task = createStubTask();
-
-        try {
-            new ResettableTimer(task, 0, TimeUnit.MILLISECONDS);
-            fail("IllegalArgumentException expected!");
-        } catch (Exception e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that a time unit is mandatory.
-     */
-    public void testTimeUnitIsMandatory() throws Exception {
-        Runnable task = createStubTask();
-
-        try {
-            new ResettableTimer(task, 10, null);
-            fail("IllegalArgumentException expected!");
-        } catch (Exception e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * @return a {@link Runnable} that does nothing, never <code>null</code>.
-     */
-    private Runnable createStubTask() {
-        return new Runnable() {
-            public void run() {
-                // No-op
-            }
-        };
-    }
-}
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
deleted file mode 100644
index 11bd35ed36..0000000000
--- a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStorePerformanceTest.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- *  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.filestore;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-
-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 case for {@link RoleRepositorySerializer}. 
- */
-public class RoleRepositoryFileStorePerformanceTest extends TestCase {
-
-    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;
-    
-    private Map m_repository;
-    private RoleRepositoryFileStore m_store;
-
-    /**
-     * Executes the performance test.
-     */
-    public void testPerformanceOk() throws Exception {
-        allocateMemory();
-
-        writeRepositoryPerformanceTest();
-
-        releaseMemory();
-        
-        readRepositoryPerformanceTest();
-    }
-
-    /**
-     * 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.nanoTime();
-        Map result = m_store.retrieve();
-        long r_time = System.nanoTime() - r_st;
-
-        assertNotNull(result);
-        assertEquals(GROUP_COUNT + USER_COUNT + 1, result.size());
-
-        System.out.println("Read time : " + (r_time / 1.0e9) + "s.");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        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(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.nanoTime();
-        m_store.store(m_repository);
-        long w_time = System.nanoTime() - w_st;
-
-        System.out.println("Write time: " + (w_time / 1.0e9) + "s.");
-    }
-
-    private void addToRepository(Role role) {
-        m_repository.put(role.getName(), role);
-    }
-
-    /**
-     * 
-     */
-    private void allocateMemory() {
-        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(m_anyone);
-
-            addToRepository(m_groups[i]);
-        }
-
-        m_users = new User[USER_COUNT];
-        for (int i = 0; i < m_users.length; i++) {
-            m_users[i] = createUser(i+1);
-            
-            int groupIdx = (i % m_groups.length);
-            m_groups[groupIdx].addMember(m_users[i]);
-            
-            addToRepository(m_users[i]);
-        }
-    }
-
-    private Group createGroup(int idx) {
-        String name = "Group" + idx;
-        
-        Group result = RoleFactory.createGroup(name);
-
-        setCredentials(result);
-        setProperties(result);
-        
-        return result;
-    }
-
-    private User createUser(int idx) {
-        String name = "User" + idx;
-        
-        User result = RoleFactory.createUser(name);
-
-        setCredentials(result);
-        setProperties(result);
-        
-        return result;
-    }
-
-    /**
-     * 
-     */
-    private void releaseMemory() {
-        m_groups = null;
-        m_users = null;
-
-        System.gc();
-        System.gc();
-        System.gc();
-    }
-
-    private void setCredentials(User user) {
-        user.getCredentials().put("name", user.getName());
-        user.getCredentials().put("password", "secret");
-        user.getCredentials().put("certificate", new byte[] { (byte) 0x55, (byte) 0xAA } );
-    }
-    
-    private void setProperties(Role role) {
-        role.getProperties().put("key1", "value1");
-        role.getProperties().put("key2", "hello world".getBytes());
-    }
-}
diff --git a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStoreTest.java b/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStoreTest.java
deleted file mode 100644
index 30754bfe1c..0000000000
--- a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositoryFileStoreTest.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/**
- *  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.filestore;
-
-import java.io.File;
-import java.util.Properties;
-
-import junit.framework.TestCase;
-
-import org.osgi.service.cm.ConfigurationException;
-
-/**
- * Test cases for {@link RoleRepositoryFileStore}.
- */
-public class RoleRepositoryFileStoreTest extends TestCase {
-
-    private RoleRepositoryFileStore m_store;
-    
-    /**
-     * Tests that calling updated without the key "background.write.disabled" fails.
-     */
-    public void testUpdateConfigurationWithoutKeyWriteDisabledFail() throws Exception {
-        try {
-            m_store.updated(new Properties());
-            fail("ConfigurationException expected!");
-        } catch (ConfigurationException e) {
-            // Ok; expected
-        }
-    }
-    
-    /**
-     * Tests that calling updated with the key "background.write.disabled" set to "false" succeeds.
-     */
-    public void testUpdateConfigurationWithKeyWriteDisabledOk() throws Exception {
-        Properties properties = new Properties();
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DISABLED, "true");
-
-        m_store.updated(properties);
-    }
-    
-    /**
-     * Tests that calling updated with the key "background.write.disabled" set to a numeric value fails.
-     */
-    public void testUpdateConfigurationWithKeyWriteDisabledInvalidValueFail() throws Exception {
-        Properties properties = new Properties();
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DISABLED, Integer.valueOf(1));
-
-        try {
-            m_store.updated(properties);
-            fail("ConfigurationException expected!");
-        } catch (ConfigurationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that calling updated without the key "background.write.delay.value" fails.
-     */
-    public void testUpdateConfigurationWithoutKeyWriteDelayValueFail() throws Exception {
-        Properties properties = new Properties();
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DISABLED, "false");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_TIMEUNIT, "seconds");
-
-        try {
-            m_store.updated(properties);
-            fail("ConfigurationException expected!");
-        } catch (ConfigurationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that calling updated with the key "background.write.delay.value" set to a non-numeric value fails.
-     */
-    public void testUpdateConfigurationWithKeyWriteDelayValueInvalidValueTypeFail() throws Exception {
-        Properties properties = new Properties();
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DISABLED, "false");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_VALUE, "seconds");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_TIMEUNIT, "seconds");
-
-        try {
-            m_store.updated(properties);
-            fail("ConfigurationException expected!");
-        } catch (ConfigurationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that calling updated with the key "background.write.delay.value" set to zero fails.
-     */
-    public void testUpdateConfigurationWithKeyWriteDelayValueZeroValueFail() throws Exception {
-        Properties properties = new Properties();
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DISABLED, "false");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_VALUE, "0");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_TIMEUNIT, "seconds");
-
-        try {
-            m_store.updated(properties);
-            fail("ConfigurationException expected!");
-        } catch (ConfigurationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that calling updated with the key "background.write.delay.value" set to a negative value fails.
-     */
-    public void testUpdateConfigurationWithKeyWriteDelayValueNegativeValueFail() throws Exception {
-        Properties properties = new Properties();
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DISABLED, "false");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_VALUE, "-1");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_TIMEUNIT, "seconds");
-
-        try {
-            m_store.updated(properties);
-            fail("ConfigurationException expected!");
-        } catch (ConfigurationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that calling updated without the key "background.write.delay.timeunit" succeeds as it is optional.
-     */
-    public void testUpdateConfigurationWithoutKeyWriteDelayTimeUnitOk() throws Exception {
-        Properties properties = new Properties();
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DISABLED, "false");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_VALUE, "1");
-
-        m_store.updated(properties);
-    }
-
-    /**
-     * Tests that calling updated with the key "background.write.delay.timeunit" set to an invalid value fails.
-     */
-    public void testUpdateConfigurationWithKeyWriteDelayTimeUnitInvalidValueFail() throws Exception {
-        Properties properties = new Properties();
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DISABLED, "false");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_VALUE, "1");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_TIMEUNIT, "1");
-
-        try {
-            m_store.updated(properties);
-            fail("ConfigurationException expected!");
-        } catch (ConfigurationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that calling updated with all keys succeeds.
-     */
-    public void testUpdateConfigurationWithAllKeysOk() throws Exception {
-        Properties properties = new Properties();
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DISABLED, "false");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_VALUE, "1");
-        properties.put(RoleRepositoryFileStore.KEY_WRITE_DELAY_TIMEUNIT, "seconds");
-
-        m_store.updated(properties);
-    }
-    
-    /**
-     * Tests that calling updated with a <code>null</code>-dictionary causes the default settings to be applied.
-     */
-    public void testUpdateConfigurationWithoutPropertiesOk() throws Exception {
-        m_store.updated(null);
-    }
-
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        m_store = new RoleRepositoryFileStore(new File(System.getProperty("java.io.tmpdir")), false /* disable background writes */);
-    }
-}
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
deleted file mode 100644
index a6567ffe1f..0000000000
--- a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/RoleRepositorySerializerTest.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/**
- *  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.filestore;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-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 case for {@link RoleRepositorySerializer}. 
- */
-public class RoleRepositorySerializerTest extends TestCase {
-
-    private Role m_userAnyone;
-    private User m_user1;
-    private User m_user2;
-    private User m_user3;
-    private User m_user4;
-    private Group m_group1;
-    private Group m_group2;
-    private Group m_group3;
-    private Map m_repository;
-    
-    private RoleRepositorySerializer m_serializer;
-
-    /**
-     * Tests that writing and reading a repository with a role, four users and a three group works as expected.
-     */
-    public void testRWRepositoryWithRolesUsersAndGroupsOk() throws Exception {
-        m_group1.addRequiredMember(m_userAnyone);
-        m_group1.addMember(m_user1);
-
-        m_group2.addMember(m_group1);
-        m_group2.addMember(m_user2);
-        m_group2.addRequiredMember(m_user1);
-        
-        m_group3.addMember(m_user3);
-        m_group3.addMember(m_user4);
-        m_group3.addRequiredMember(m_userAnyone);
-        
-        addToRepository(m_user1);
-        addToRepository(m_user2);
-        addToRepository(m_user3);
-        addToRepository(m_user4);
-        addToRepository(m_group1);
-        addToRepository(m_group2);
-        addToRepository(m_group3);
-        
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        DataOutputStream dos = new DataOutputStream(baos);
-        
-        m_serializer.serialize(m_repository, dos); // should succeed!
-        
-        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        DataInputStream dis = new DataInputStream(bais);
-        
-        Map result = m_serializer.deserialize(dis);
-        assertNotNull(result);
-
-        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()));
-        assertEquals(m_user4, (User) result.get(m_user4.getName()));
-        assertEquals(m_group1, (Group) result.get(m_group1.getName()));
-        assertEquals(m_group2, (Group) result.get(m_group2.getName()));
-        assertEquals(m_group3, (Group) result.get(m_group3.getName()));
-    }
-
-    /**
-     * Tests that writing and reading a repository with a single group works as expected.
-     */
-    public void testRWRepositoryWithSingleGroupOk() throws Exception {
-        addToRepository(m_group1);
-        
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        DataOutputStream dos = new DataOutputStream(baos);
-        
-        m_serializer.serialize(m_repository, dos); // should succeed!
-
-        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        DataInputStream dis = new DataInputStream(bais);
-        
-        Map result = m_serializer.deserialize(dis);
-        assertNotNull(result);
-        
-        assertEquals(1, result.size());
-
-        assertEquals(m_group1, (Role) result.get(m_group1.getName()));
-    }
-
-    /**
-     * Tests that writing and reading a repository without roles works as expected.
-     */
-    public void testRWRepositoryWithoutRolesOk() throws Exception {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        DataOutputStream dos = new DataOutputStream(baos);
-        
-        m_serializer.serialize(m_repository, dos); // should succeed!
-        
-        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        DataInputStream dis = new DataInputStream(bais);
-        
-        Map result = m_serializer.deserialize(dis);
-        assertNotNull(result);
-        
-        assertEquals(0, result.size());
-    }
-
-    /**
-     * Tests that writing and reading a repository with a single user role works as expected.
-     */
-    public void testRWRepositoryWithSingleUserOk() throws Exception {
-        addToRepository(m_user1);
-        
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        DataOutputStream dos = new DataOutputStream(baos);
-        
-        m_serializer.serialize(m_repository, dos); // should succeed!
-        
-        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        DataInputStream dis = new DataInputStream(bais);
-        
-        Map result = m_serializer.deserialize(dis);
-        assertNotNull(result);
-        
-        assertEquals(1, result.size());
-
-        assertEquals(m_user1, (User) result.get(m_user1.getName()));
-    }
-
-    /**
-     * Tests that writing and reading a repository with two user roles works as expected.
-     */
-    public void testRWRepositoryWithTwoUsersOk() throws Exception {
-        addToRepository(m_user1);
-        addToRepository(m_user2);
-        
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        DataOutputStream dos = new DataOutputStream(baos);
-        
-        m_serializer.serialize(m_repository, dos); // should succeed!
-        
-        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        DataInputStream dis = new DataInputStream(bais);
-        
-        Map result = m_serializer.deserialize(dis);
-        assertNotNull(result);
-        
-        assertEquals(2, result.size());
-        assertEquals(m_user1, (User) result.get(m_user1.getName()));
-        assertEquals(m_user2, (User) result.get(m_user2.getName()));
-    }
-
-    /**
-     * Tests that reading a repository that has a cyclic group reference can be read ok.
-     */
-    public void testRWRepositoryWithCyclicGroupReference() throws Exception {
-        m_group1.addMember(m_group2);
-        m_group2.addMember(m_group1);
-        m_group2.addMember(m_user1);
-
-        addToRepository(m_user1);
-        addToRepository(m_group2);
-        addToRepository(m_group1);
-
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        DataOutputStream dos = new DataOutputStream(baos);
-        
-        m_serializer.serialize(m_repository, dos); // should succeed!
-        
-        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        DataInputStream dis = new DataInputStream(bais);
-        
-        Map result = m_serializer.deserialize(dis);
-        assertNotNull(result);
-        
-        assertEquals(3, result.size());
-        assertEquals(m_group1, (Group) result.get(m_group1.getName()));
-        assertEquals(m_group2, (Group) result.get(m_group2.getName()));
-        assertEquals(m_user1, (User) result.get(m_user1.getName()));
-    }
-
-    /**
-     * Tests that reading a repository that is missing a referenced basic role from a group fails.
-     */
-    public void testRWRepositoryWithUnreferencedBasicRoleInGroupFail() throws Exception {
-        m_group1.addMember(m_userAnyone);
-        m_group1.addRequiredMember(m_user1);
-
-        // "Forget" to add the user1
-        addToRepository(m_group1);
-
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        DataOutputStream dos = new DataOutputStream(baos);
-        
-        m_serializer.serialize(m_repository, dos); // should succeed!
-        
-        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        DataInputStream dis = new DataInputStream(bais);
-        
-        try {
-            m_serializer.deserialize(dis);
-            
-            fail("IOException expected!");
-        } catch (IOException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that reading a repository that is missing a referenced required role from a group fails.
-     */
-    public void testRWRepositoryWithUnreferencedRequiredRoleInGroupFail() throws Exception {
-        m_group1.addRequiredMember(m_userAnyone);
-        m_group1.addMember(m_user1);
-        
-        // "Forget" to add the user1!
-        addToRepository(m_group1);
-
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        DataOutputStream dos = new DataOutputStream(baos);
-        
-        m_serializer.serialize(m_repository, dos); // should succeed!
-        
-        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        DataInputStream dis = new DataInputStream(bais);
-        
-        try {
-            m_serializer.deserialize(dis);
-            
-            fail("IOException expected!");
-        } catch (IOException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        m_serializer = new RoleRepositorySerializer();
-
-        m_repository = new HashMap();
-
-        m_userAnyone = RoleFactory.createRole(Role.USER_ANYONE);
-        
-        setProperties(m_userAnyone);
-        
-        m_user1 = createUser(1);
-        m_user2 = createUser(2);
-        m_user3 = createUser(3);
-        m_user4 = createUser(4);
-
-        m_group1 = createGroup(1);
-        m_group2 = createGroup(2);
-        m_group3 = createGroup(3);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-    
-    private void addToRepository(Role role) {
-        if (!Role.USER_ANYONE.equals(role.getName())) {
-            m_repository.put(role.getName(), role);
-        }
-    }
-    
-    private void assertEquals(Dictionary expected, Dictionary obtained) {
-        assertNotNull(expected);
-        assertNotNull(obtained);
-        
-        assertEquals(expected.size(), obtained.size());
-        
-        Enumeration enumeration = expected.keys();
-        while (enumeration.hasMoreElements()) {
-            Object expectedKey = enumeration.nextElement();
-            Object expectedValue = expected.get(expectedKey);
-
-            Object obtainedValue = obtained.get(expectedKey);
-            if (expectedValue == null) {
-                assertNull(obtainedValue);
-            } else if (expectedValue.getClass().isArray()) {
-                assertTrue(Arrays.equals((byte[]) expectedValue, (byte[]) obtainedValue));
-            } else {
-                assertEquals(expectedValue, obtainedValue);
-            }
-        }
-    }
-
-    private void assertEquals(Group expected, Group obtained) {
-        assertEquals((Object) expected, (Object) obtained);
-        
-        assertEquals(expected.getProperties(), obtained.getProperties());
-        assertEquals(expected.getCredentials(), obtained.getCredentials());
-        assertEquals(expected.getMembers(), obtained.getMembers());
-        assertEquals(expected.getRequiredMembers(), obtained.getRequiredMembers());
-    }
-
-    private void assertEquals(Role expected, Role obtained) {
-        assertEquals((Object) expected, (Object) obtained);
-        
-        assertEquals(expected.getProperties(), obtained.getProperties());
-    }
-
-    private void assertEquals(User expected, User obtained) {
-        assertEquals((Object) expected, (Object) obtained);
-        
-        assertEquals(expected.getProperties(), obtained.getProperties());
-        assertEquals(expected.getCredentials(), obtained.getCredentials());
-    }
-
-    private void assertEquals(Role[] expected, Role[] obtained) {
-        if (expected != null) {
-            assertNotNull(obtained);
-            assertEquals(expected.length, obtained.length);
-            
-            List e = new ArrayList(Arrays.asList(expected));
-            e.removeAll(Arrays.asList(obtained));
-            
-            assertTrue("Roles not obtained: " + e, e.isEmpty());
-            
-            Map m = new HashMap();
-            for (int i = 0; i < expected.length; i++) {
-                m.put(expected[i].getName(), expected[i]);
-            }
-            
-            for (int i = 0; i < obtained.length; i++) {
-                assertEquals(m.get(obtained[i].getName()), obtained[i]);
-            }
-        } else {
-            assertNull(obtained);
-        }
-    }
-
-    private User createUser(int idx) {
-        String name = "User" + idx;
-        
-        User result = RoleFactory.createUser(name);
-
-        setCredentials(result);
-        setProperties(result);
-        
-        return result;
-    }
-
-    private Group createGroup(int idx) {
-        String name = "Group" + idx;
-        
-        Group result = RoleFactory.createGroup(name);
-
-        setCredentials(result);
-        setProperties(result);
-        
-        return result;
-    }
-
-    private void setCredentials(User user) {
-        user.getCredentials().put(user.getName(), user.getName());
-        user.getCredentials().put("password", user.getName());
-        user.getCredentials().put("certificate", new byte[] { (byte) 0x55, (byte) 0xAA } );
-    }
-
-    private void setProperties(Role role) {
-        role.getProperties().put(role.getName(), role.getName());
-        role.getProperties().put("key1", role.getName());
-        role.getProperties().put("key2", "hello world".getBytes());
-    }
-}
diff --git a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/StubGroupImplTest.java b/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/StubGroupImplTest.java
deleted file mode 100644
index b19d53e426..0000000000
--- a/useradmin/filestore/src/test/java/org/apache/felix/useradmin/filestore/StubGroupImplTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/**
- *  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.filestore;
-
-import junit.framework.TestCase;
-
-import org.osgi.service.useradmin.Role;
-
-/**
- * Test cases for {@link StubGroupImpl}.
- */
-public class StubGroupImplTest extends TestCase {
-
-    /**
-     * Tests that {@link StubGroupImpl#addMember(Role)} always fails.
-     */
-    public void testAddMemberRoleAlwaysFails() {
-        try {
-            new StubGroupImpl("test").addMember((Role) null);
-            fail("Expected UnsupportedOperationException!");
-        } catch (UnsupportedOperationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that {@link StubGroupImpl#addRequiredMember(Role)} always fails.
-     */
-    public void testAddRequiredMemberRoleAlwaysFails() {
-        try {
-            new StubGroupImpl("test").addRequiredMember((Role) null);
-            fail("Expected UnsupportedOperationException!");
-        } catch (UnsupportedOperationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that {@link StubGroupImpl#getMembers()} always fails.
-     */
-    public void testGetMembersAlwaysFails() {
-        try {
-            new StubGroupImpl("test").getMembers();
-            fail("Expected UnsupportedOperationException!");
-        } catch (UnsupportedOperationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that {@link StubGroupImpl#getRequiredMembers()} always fails.
-     */
-    public void testGetRequiredMembersAlwaysFails() {
-        try {
-            new StubGroupImpl("test").getRequiredMembers();
-            fail("Expected UnsupportedOperationException!");
-        } catch (UnsupportedOperationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that {@link StubGroupImpl#hasCredential(String, Object)} always fails.
-     */
-    public void testHasCredentialAlwaysFails() {
-        try {
-            new StubGroupImpl("test").hasCredential("foo", "bar");
-            fail("Expected UnsupportedOperationException!");
-        } catch (UnsupportedOperationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that {@link StubGroupImpl#removeMember(Role)} always fails.
-     */
-    public void testRemoveMemberAlwaysFails() {
-        try {
-            new StubGroupImpl("test").removeMember((Role) null);
-            fail("Expected UnsupportedOperationException!");
-        } catch (UnsupportedOperationException e) {
-            // Ok; expected
-        }
-    }
-
-    /**
-     * Tests that {@link StubGroupImpl#hashCode()} and {@link StubGroupImpl#equals(Object)} works.
-     */
-    public void testHashCodeAndEqualsOk() {
-        StubGroupImpl g1 = new StubGroupImpl("foo");
-        StubGroupImpl g2 = new StubGroupImpl("bar");
-        StubGroupImpl g3 = new StubGroupImpl("foo");
-        StubGroupImpl g4 = new StubGroupImpl(null);
-
-        assertTrue(g1.hashCode() == g3.hashCode());
-        assertFalse(g1.hashCode() == g2.hashCode());
-        assertFalse(g1.hashCode() == g4.hashCode());
-
-        assertTrue(g1.equals(g3));
-        assertTrue(g3.equals(g1));
-        assertFalse(g1.equals(g2));
-        assertFalse(g1.equals(g4));
-
-        assertTrue(g4.equals(g4));
-        assertFalse(g4.equals(g1));
-
-        assertFalse(g1.equals(null));
-        assertFalse(g1.equals("qux"));
-    }
-}
diff --git a/useradmin/itest/pom.xml b/useradmin/itest/pom.xml
deleted file mode 100644
index 3de6b1e3da..0000000000
--- a/useradmin/itest/pom.xml
+++ /dev/null
@@ -1,173 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>felix-parent</artifactId>
-        <version>2.1</version>
-        <relativePath>../../../pom/pom.xml</relativePath>
-    </parent>
-    <properties>
-        <osgi.version>4.0.0</osgi.version>
-        <pax.exam.version>2.4.0</pax.exam.version>
-        <pax.exam.plugin.version>1.2.4</pax.exam.plugin.version>
-        <pax.url.aether.version>1.4.0</pax.url.aether.version>
-        <pax.swissbox.version>1.3.1</pax.swissbox.version>
-        <pax.runner.version>1.9.0</pax.runner.version>
-    </properties>
-    <artifactId>org.apache.felix.useradmin.itest</artifactId>
-    <version>1.0.0-SNAPSHOT</version>
-    <packaging>jar</packaging>
-    <description>Integration tests for the UserAdmin OSGi compendium service.</description>
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <version>${osgi.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.useradmin</artifactId>
-            <version>1.0.7-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.useradmin.filestore</artifactId>
-            <version>1.0.3-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.useradmin.mongodb</artifactId>
-            <version>1.0.2-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mongodb</groupId>
-            <artifactId>mongo-java-driver</artifactId>
-            <version>2.13.3</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.dependencymanager</artifactId>
-            <version>3.0.0</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.10</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-junit4</artifactId>
-            <version>${pax.exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-container-forked</artifactId>
-            <version>${pax.exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.runner</groupId>
-            <artifactId>pax-runner-no-jcl</artifactId>
-            <version>${pax.runner.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-link-assembly</artifactId>
-            <version>${pax.exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.exam</groupId>
-            <artifactId>pax-exam-link-mvn</artifactId>
-            <version>${pax.exam.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.url</groupId>
-            <artifactId>pax-url-aether</artifactId>
-            <version>${pax.url.aether.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.url</groupId>
-            <artifactId>pax-url-wrap</artifactId>
-            <version>${pax.url.aether.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>javax.inject</groupId>
-            <artifactId>javax.inject</artifactId>
-            <version>1</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.framework</artifactId>
-            <version>4.0.2</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
-            <version>1.6.0</version>
-            <scope>compile</scope>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <target>1.6</target>
-                    <source>1.6</source>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-            </plugin>
-            <plugin>
-                <groupId>org.ops4j.pax.exam</groupId>
-                <artifactId>maven-paxexam-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>generate-config</id>
-                        <goals>
-                            <goal>generate-depends-file</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-</project>
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
deleted file mode 100644
index 3adf4fbe74..0000000000
--- a/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/BaseIntegrationTest.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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.itest;
-
-import static org.junit.Assert.assertNotNull;
-import static org.ops4j.pax.exam.Constants.START_LEVEL_SYSTEM_BUNDLES;
-import static org.ops4j.pax.exam.Constants.START_LEVEL_TEST_BUNDLE;
-import static org.ops4j.pax.exam.CoreOptions.bootDelegationPackage;
-import static org.ops4j.pax.exam.CoreOptions.cleanCaches;
-import static org.ops4j.pax.exam.CoreOptions.felix;
-import static org.ops4j.pax.exam.CoreOptions.frameworkProperty;
-import static org.ops4j.pax.exam.CoreOptions.frameworkStartLevel;
-import static org.ops4j.pax.exam.CoreOptions.junitBundles;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.options;
-import static org.ops4j.pax.exam.CoreOptions.systemPackages;
-import static org.ops4j.pax.exam.CoreOptions.url;
-
-import javax.inject.Inject;
-
-import org.junit.Before;
-import org.ops4j.pax.exam.CoreOptions;
-import org.ops4j.pax.exam.Option;
-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;
-
-/**
- * Base class for integration tests.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public abstract class BaseIntegrationTest
-{
-
-    private static final int DEFAULT_TIMEOUT = 10000;
-
-    protected static final String ORG_APACHE_FELIX_USERADMIN = "org.apache.felix.useradmin";
-    protected static final String ORG_APACHE_FELIX_USERADMIN_FILESTORE = "org.apache.felix.useradmin.filestore";
-    protected static final String ORG_APACHE_FELIX_USERADMIN_MONGODBSTORE = "org.apache.felix.useradmin.mongodb";
-    protected static final String ORG_MONGODB_MONGO_JAVA_DRIVER = "org.mongodb.mongo-java-driver";
-
-    @Inject
-    protected volatile BundleContext m_context;
-
-    @Configuration
-    public Option[] config()
-    {
-        return options(
-            bootDelegationPackage("sun.*"),
-            systemPackages("javax.naming", "javax.net.ssl", "javax.xml.parsers", "org.w3c.dom", "org.xml.sax", "org.xml.sax.helpers"),
-            frameworkProperty("org.osgi.framework.system.capabilities.extra").value(
-                "osgi.ee;osgi.ee=JavaSE;version=1.6,osgi.ee;osgi.ee=JavaSE;version=1.5,osgi.ee;osgi.ee=JavaSE;version=1.4,osgi.ee;osgi.ee=JavaSE;version=1.3"),
-            cleanCaches(),
-            CoreOptions.systemProperty("logback.configurationFile").value("file:src/test/resources/logback.xml"), //
-//            CoreOptions.vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8787"),
-
-            mavenBundle("org.slf4j", "slf4j-api").version("1.7.25").startLevel(START_LEVEL_SYSTEM_BUNDLES),
-            mavenBundle("ch.qos.logback", "logback-core").version("1.2.3").startLevel(START_LEVEL_SYSTEM_BUNDLES),
-            mavenBundle("ch.qos.logback", "logback-classic").version("1.2.3").startLevel(START_LEVEL_SYSTEM_BUNDLES),
-
-            url("link:classpath:META-INF/links/org.ops4j.pax.exam.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
-            url("link:classpath:META-INF/links/org.ops4j.pax.exam.inject.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
-            url("link:classpath:META-INF/links/org.ops4j.pax.extender.service.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
-            url("link:classpath:META-INF/links/org.ops4j.base.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
-            url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.core.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
-            url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.extender.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
-            url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.lifecycle.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
-            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.apache.felix", ORG_APACHE_FELIX_USERADMIN).versionAsInProject().startLevel(START_LEVEL_SYSTEM_BUNDLES),
-            mavenBundle("org.apache.felix", ORG_APACHE_FELIX_USERADMIN_FILESTORE).versionAsInProject().noStart(),
-            mavenBundle("org.apache.felix", ORG_APACHE_FELIX_USERADMIN_MONGODBSTORE).versionAsInProject().noStart(), mavenBundle("org.mongodb", "mongo-java-driver").versionAsInProject().noStart(),
-
-            junitBundles(), frameworkStartLevel(START_LEVEL_TEST_BUNDLE), felix().version("6.0.3"));
-    }
-
-    @Before
-    public void setUp() throws Exception
-    {
-        assertNotNull("No bundle context?!", m_context);
-    }
-
-    /**
-     * Waits for a service to become available in certain time interval.
-     * @param serviceName
-     * @return
-     * @throws Exception
-     */
-    protected <T> T awaitService(String serviceName) throws Exception
-    {
-        ServiceTracker tracker = new ServiceTracker(m_context, serviceName, null);
-        tracker.open();
-        T result;
-        try
-        {
-            result = (T) tracker.waitForService(DEFAULT_TIMEOUT);
-        }
-        finally
-        {
-            tracker.close();
-        }
-        return result;
-    }
-
-    /**
-     * @param bsn
-     * @return
-     */
-    protected Bundle findBundle(String bsn)
-    {
-        for (Bundle bundle : m_context.getBundles())
-        {
-            if (bsn.equals(bundle.getSymbolicName()))
-            {
-                return bundle;
-            }
-        }
-        return null;
-    }
-
-    protected Bundle getFileStoreBundle()
-    {
-        Bundle b = findBundle(ORG_APACHE_FELIX_USERADMIN_FILESTORE);
-        assertNotNull("Filestore bundle not found?!", b);
-        return b;
-    }
-
-    protected Bundle getMongoDBStoreBundle()
-    {
-        Bundle b = findBundle(ORG_APACHE_FELIX_USERADMIN_MONGODBSTORE);
-        assertNotNull("MongoDB store bundle not found?!", b);
-        return b;
-    }
-
-    protected Bundle getMongoDBBundle()
-    {
-        Bundle b = findBundle(ORG_MONGODB_MONGO_JAVA_DRIVER);
-        assertNotNull("MongoDB bundle not found?!", b);
-        return b;
-    }
-
-    /**
-     * Obtains a service without waiting for it to become available.
-     * @param serviceName
-     * @return
-     * @throws Exception
-     */
-    protected <T> T getService(String serviceName) throws Exception
-    {
-        ServiceTracker tracker = new ServiceTracker(m_context, serviceName, null);
-        tracker.open();
-        T result;
-        try
-        {
-            result = (T) tracker.getService();
-        }
-        finally
-        {
-            tracker.close();
-        }
-        return result;
-    }
-
-    /**
-     * @return the {@link UserAdmin} service instance.
-     */
-    protected UserAdmin getUserAdmin() throws Exception
-    {
-        return getService(UserAdmin.class.getName());
-    }
-}
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
deleted file mode 100644
index fd854e0970..0000000000
--- a/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/FileStoreInitializationTest.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.itest;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.ops4j.pax.exam.junit.JUnit4TestRunner;
-import org.osgi.framework.Bundle;
-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>
- */
-@RunWith(JUnit4TestRunner.class)
-public class FileStoreInitializationTest extends BaseIntegrationTest
-{
-
-    /**
-     * Tests that initialization and closing of the repository store is
-     * performed correctly.
-     */
-    @Test
-    public void testStoreIsInitializedAndClosedProperlyOk() throws Exception
-    {
-        UserAdmin ua = getUserAdmin();
-        // Start the file store bundle...
-        Bundle fileStoreBundle = getFileStoreBundle();
-        fileStoreBundle.start();
-
-        // 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; should persist the two roles...
-        fileStoreBundle.stop();
-
-        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);
-
-        group = (Group) ua.getRole("group1");
-        assertNull(group);
-
-        // This will not succeed: no backend to store the user in...
-        assertNull(ua.createRole("user2", Role.USER));
-
-        fileStoreBundle.start();
-
-        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);
-
-        Role[] members = group.getMembers();
-        assertNotNull(members);
-        assertEquals(1, members.length);
-        assertEquals("user1", members[0].getName());
-
-        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/itest/src/test/java/org/apache/felix/useradmin/itest/MongoDBStoreTest.java b/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/MongoDBStoreTest.java
deleted file mode 100644
index 371d096086..0000000000
--- a/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/MongoDBStoreTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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.itest;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-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.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.cm.ManagedService;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdmin;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.CommandResult;
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.Mongo;
-import com.mongodb.WriteConcern;
-
-/**
- * Main integration test for the user admin service.
- * 
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-@RunWith(JUnit4TestRunner.class)
-public class MongoDBStoreTest extends BaseIntegrationTest
-{
-    /**
-     * Tests that fetching an empty role without properties or other roles does not cause a NPE.
-     */
-    @Test
-    public void testFelix4399_FetchEmptyRoleOk() throws Exception
-    {
-        UserAdmin ua = getUserAdmin();
-
-        String roleName = "emptyRole";
-
-        if (canRunTest())
-        {
-            Role emptyRole = ua.createRole(roleName, Role.USER);
-            assertNotNull("Collection not empty?!", emptyRole);
-
-            Role readRole = ua.getRole(roleName);
-
-            assertNotNull("Unable to read back created empty role?!", readRole);
-            assertEquals("Names not equal?!", emptyRole.getName(), readRole.getName());
-            assertEquals("Types not equal?!", emptyRole.getType(), readRole.getType());
-
-            Role[] readRoles = ua.getRoles(null);
-
-            assertNotNull("Unable to read back created empty role?!", readRoles);
-            assertEquals(1, readRoles.length);
-        }
-    }
-
-    /**
-     * Tests that creating a new role returns the actual created role.
-     */
-    @Test
-    public void testFelix4400_CreateRoleReturnsNonNullOk() throws Exception
-    {
-        UserAdmin ua = getUserAdmin();
-
-        String roleName = "newRole";
-
-        if (canRunTest())
-        {
-            Role newRole = ua.createRole(roleName, Role.USER);
-            assertNotNull("Felix-4400 not resolved?!", newRole);
-
-            assertEquals("Names not equal?!", roleName, newRole.getName());
-            assertEquals("Types not equal?!", Role.USER, newRole.getType());
-        }
-    }
-
-    /**
-     * Tests that removing a role works correctly.
-     */
-    @Test
-    public void testRemoveRoleOk() throws Exception
-    {
-        UserAdmin ua = getUserAdmin();
-
-        String roleName = "newRole";
-        Role[] readRoles;
-
-        if (canRunTest())
-        {
-            Role role = ua.createRole(roleName, Role.USER);
-            assertNotNull("Collection not empty?!", role);
-
-            readRoles = ua.getRoles(null);
-
-            assertNotNull("No roles stored?!", readRoles);
-            assertEquals(1, readRoles.length);
-
-            ua.removeRole(roleName);
-
-            readRoles = ua.getRoles(null);
-
-            assertNull("Still roles stored?!", readRoles);
-        }
-    }
-
-    /**
-     * Tests that removing a role works correctly.
-     */
-    @Test
-    public void testUpdateRoleOk() throws Exception
-    {
-        UserAdmin ua = getUserAdmin();
-
-        String roleName = "role1";
-        Role[] readRoles;
-
-        if (canRunTest())
-        {
-            User role = (User) ua.createRole(roleName, Role.USER);
-            assertNotNull("Collection not empty?!", role);
-
-            readRoles = ua.getRoles(null);
-
-            assertNotNull("No roles stored?!", readRoles);
-            assertEquals(1, readRoles.length);
-
-            role.getProperties().put("key", "value");
-
-            Thread.sleep(100); // Wait a little to ensure everything is written...
-
-            readRoles = ua.getRoles("(key=value)");
-
-            assertNotNull("Role not updated?!", readRoles);
-            assertEquals(1, readRoles.length);
-        }
-    }
-
-    /**
-     * Sets up MongoDB and tries to clear the useradmin collection. When this fails, it is assumed that no MongoDB service is available.
-     */
-    private boolean canRunTest() throws BundleException
-    {
-        Bundle mongoBundle = getMongoDBBundle();
-        mongoBundle.start();
-
-        Bundle mongoStoreBundle = getMongoDBStoreBundle();
-        mongoStoreBundle.start();
-
-        // Provision an empty configuration...
-        BundleContext context = mongoStoreBundle.getBundleContext();
-
-        ServiceReference serviceRef = context.getServiceReference(ManagedService.class.getName());
-        assertNotNull(serviceRef);
-
-        ManagedService service = (ManagedService) context.getService(serviceRef);
-        try
-        {
-            service.updated(null);
-
-            Mongo mongo = new Mongo();
-            DB db = mongo.getDB("ua_repo");
-            DBCollection collection = db.getCollection("useradmin");
-            // we always get a collection back, regardless if there is an actual MongoDB listening, hence we should do
-            // some actual calls that cause a connection to MongoDB to be created...
-            collection.remove(new BasicDBObject(), WriteConcern.SAFE);
-
-            CommandResult lastError = db.getLastError();
-
-            return (lastError.getException() == null && collection.getCount() == 0L);
-        }
-        catch (Exception e)
-        {
-            // Ignore; apparently, we failed to connect to MongoDB...
-        }
-
-        return false;
-    }
-}
diff --git a/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/UserAdminIntegrationTest.java b/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/UserAdminIntegrationTest.java
deleted file mode 100644
index c09916e8bd..0000000000
--- a/useradmin/itest/src/test/java/org/apache/felix/useradmin/itest/UserAdminIntegrationTest.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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.itest;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.ops4j.pax.exam.junit.JUnit4TestRunner;
-import org.osgi.framework.Bundle;
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdmin;
-
-/**
- * Main integration test for the user admin service.
- * 
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-@RunWith(JUnit4TestRunner.class)
-public class UserAdminIntegrationTest extends BaseIntegrationTest
-{
-    /**
-     * Tests that stopping a filled store and starting it again will cause it to
-     * properly restore its state.
-     */
-    @Test
-    public void testFelix3735_StopRunningStoreRetainsDataOk() throws Exception
-    {
-        final String userName = "testUser";
-        final String groupName = "testGroup";
-
-        UserAdmin userAdmin = awaitService(UserAdmin.class.getName());
-        Bundle fileStoreBundle = getFileStoreBundle();
-        // Start a suitable storage service...
-        fileStoreBundle.start();
-
-        // Fill the user admin with some data...
-        User testUser = (User) userAdmin.createRole(userName, Role.USER);
-        testUser.getProperties().put("key", "value");
-
-        Group testGroup = (Group) userAdmin.createRole(groupName, Role.GROUP);
-        testGroup.addMember(testUser);
-
-        // Stop the file store...
-        fileStoreBundle.stop();
-
-        // retrieve the useradmin again...
-        userAdmin = awaitService(UserAdmin.class.getName());
-
-        // Verify the user + group are gone (no store available)...
-        assertNull(userAdmin.getRole(userName));
-        assertNull(userAdmin.getRole(groupName));
-
-        // Start the file store...
-        fileStoreBundle.start();
-
-        // Verify the user + group are gone (no store available)...
-        User readUser = (User) userAdmin.getRole(userName);
-        assertNotNull(readUser);
-        assertEquals(userName, readUser.getName());
-        assertEquals("value", readUser.getProperties().get("key"));
-
-        Group readGroup = (Group) userAdmin.getRole(groupName);
-        assertNotNull(readGroup);
-        assertEquals(groupName, readGroup.getName());
-        assertEquals(1, readGroup.getMembers().length);
-        assertEquals(readUser, readGroup.getMembers()[0]);
-    }
-
-    /**
-     * Tests that starting the file store <em>after</em> the user admin service
-     * is started will cause it to be properly initialized.
-     */
-    @Test
-    public void testFelix3735_StartStoreAfterUserAdminInitializesOk() throws Exception
-    {
-        final String userName = "anotherTestUser";
-        final String groupName = "anotherTestGroup";
-
-        UserAdmin userAdmin = awaitService(UserAdmin.class.getName());
-        Bundle fileStoreBundle = getFileStoreBundle();
-        // Start a suitable storage service...
-        fileStoreBundle.start();
-
-        // Fill the user admin with some data...
-        User testUser = (User) userAdmin.createRole(userName, Role.USER);
-        testUser.getProperties().put("key", "value");
-
-        Group testGroup = (Group) userAdmin.createRole(groupName, Role.GROUP);
-        testGroup.addMember(testUser);
-
-        // Stop the file store...
-        fileStoreBundle.stop();
-
-        Bundle userAdminBundle = findBundle(ORG_APACHE_FELIX_USERADMIN);
-        assertNotNull(userAdminBundle);
-        userAdminBundle.stop();
-
-        // Obtain user admin service again; shouldn't be available...
-        userAdmin = getService(UserAdmin.class.getName());
-        assertNull(userAdmin);
-
-        userAdminBundle.start();
-
-        // Obtain user admin service again; should be available now...
-        userAdmin = awaitService(UserAdmin.class.getName());
-        assertNotNull(userAdmin);
-
-        // Verify the user + group are gone (no store available)...
-        assertNull(userAdmin.getRole(userName));
-        assertNull(userAdmin.getRole(groupName));
-
-        // Start the file store...
-        fileStoreBundle.start();
-
-        // Verify the user + group are gone (no store available)...
-        User readUser = (User) userAdmin.getRole(userName);
-        assertNotNull(readUser);
-        assertEquals(userName, readUser.getName());
-        assertEquals("value", readUser.getProperties().get("key"));
-
-        Group readGroup = (Group) userAdmin.getRole(groupName);
-        assertNotNull(readGroup);
-        assertEquals(groupName, readGroup.getName());
-        assertEquals(1, readGroup.getMembers().length);
-        assertEquals(readUser, readGroup.getMembers()[0]);
-    }
-}
diff --git a/useradmin/itest/src/test/resources/logback.xml b/useradmin/itest/src/test/resources/logback.xml
deleted file mode 100644
index 03dedea376..0000000000
--- a/useradmin/itest/src/test/resources/logback.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<configuration>
-	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-		<encoder>
-			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
-			</pattern>
-		</encoder>
-	</appender>
-
-	<root level="WARN">
-		<appender-ref ref="STDOUT" />
-	</root>
-
-	<logger name="org.ops4j" level="WARN" />
-</configuration>
diff --git a/useradmin/mongodb/pom.xml b/useradmin/mongodb/pom.xml
deleted file mode 100644
index 89b2f2ec61..0000000000
--- a/useradmin/mongodb/pom.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<!--
-    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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>felix-parent</artifactId>
-        <groupId>org.apache.felix</groupId>
-        <version>2.1</version>
-        <relativePath>../../../pom/pom.xml</relativePath>
-    </parent>
-    <artifactId>org.apache.felix.useradmin.mongodb</artifactId>
-    <version>1.0.2-SNAPSHOT</version>
-    <packaging>bundle</packaging>
-    <description>Provides a MongoDB store implementation for the User Admin service.</description>
-    <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>
-        <dependency>
-            <groupId>org.mongodb</groupId>
-            <artifactId>mongo-java-driver</artifactId>
-            <version>2.13.3</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.useradmin</artifactId>
-            <version>1.0.7-SNAPSHOT</version>
-            <type>bundle</type>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>1.6</source>
-                    <target>1.6</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.rat</groupId>
-                <artifactId>apache-rat-plugin</artifactId>
-                <configuration>
-                    <includes>
-                        <include>src/**</include>
-                    </includes>
-                    <excludes>
-                        <exclude>src/main/resources/**</exclude>
-                    </excludes>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <configuration>
-                    <instructions>
-                        <Bundle-Name>Apache Felix User Admin Service MongoDB repository</Bundle-Name>
-                        <Bundle-Description>
-                            A MongoDB repository implementation for User Admin Compendium Service
-                        </Bundle-Description>
-                        <Bundle-Activator>
-                            ${project.artifactId}.osgi.Activator
-                        </Bundle-Activator>
-                        <Bundle-SymbolicName>
-                            ${project.artifactId}
-                        </Bundle-SymbolicName>
-                        <Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
-                        <Import-Package>
-                             org.osgi.service.useradmin; version="[1.1,1.2)",
-                             *
-                        </Import-Package>
-                        <Export-Package>
-                        </Export-Package>
-                        <Private-Package>
-                            ${project.artifactId}.*
-                        </Private-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
diff --git a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/KeyCodec.java b/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/KeyCodec.java
deleted file mode 100644
index fe6cdec319..0000000000
--- a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/KeyCodec.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- *  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.mongodb;
-
-
-/**
- * Provides a small utility class for encoding/decoding keys used directly in 
- * MongoDB.
- * <p>
- * MongoDB does not allow keys to have '.' and '$' (amongst others?) in their 
- * name, so we need to ensure that those characters are somehow encoded.
- * </p>
- * 
- * @see http://www.mongodb.org/display/DOCS/Legal+Key+Names
- * @see http://www.yoyobrain.com/flashcards/show/261984
- */
-final class KeyCodec {
-    
-    private static final String ENCODED_NULL = "%00";
-    private static final String ENCODED_UNDERSCORE = "%5F";
-    private static final String ENCODED_DOT = "%2E";
-    private static final String ENCODED_DOLLAR = "%24"; 
-    
-    /**
-     * Encodes a given key by replacing all '.' and '$' with their URL encoded variants.
-     * 
-     * @param input the input to encode, may be <code>null</code>.
-     * @return the encoded input, can be <code>null</code>.
-     */
-    public static String encode(String input) {
-        if (input == null) {
-            return null;
-        }
-        StringBuilder sb = new StringBuilder(input.length());
-        for (int i = 0; i < input.length(); i++) {
-            char c = input.charAt(i);
-            if (c == 0) {
-                sb.append(ENCODED_NULL);
-            } else if (c == '_') {
-                sb.append(ENCODED_UNDERSCORE);
-            } else if (c == '.') {
-                sb.append(ENCODED_DOT);
-            } else if (c == '$') {
-                sb.append(ENCODED_DOLLAR);
-            } else if (c == '%') {
-                // escape all '%' as well...
-                sb.append("%%");
-            } else {
-                sb.append((char) c);
-            }
-        }
-        return sb.toString();
-    }
-    
-    /**
-     * Decodes a given key by replacing all URL encoded '.' and '$' entities with their real characters.
-     * 
-     * @param input the input to decode, may be <code>null</code>.
-     * @return the decoded input, can be <code>null</code>.
-     */
-    public static String decode(String input) {
-        if (input == null) {
-            return null;
-        }
-        
-        boolean percentSeen = false;
-        int length = input.length();
-        char oldC = input.charAt(0);
-        
-        StringBuilder sb = new StringBuilder(input.length());
-        for (int i = 1; i < length; i++) {
-            char c = input.charAt(i);
-            if (oldC == '%') {
-                if (c == '%') {
-                    // Escaped percent...
-                    sb.append("%");
-                    c = 0; // erase percent...
-                    percentSeen = false;
-                } else {
-                    percentSeen = true;
-                }
-            } else if (c == '%') {
-                percentSeen = true;
-            } else if (percentSeen) {
-                if (oldC == '0' && c == '0') {
-                    // Encoded null-character
-                    sb.append((char) 0);
-                    percentSeen = false;
-                } else if (oldC == '2' && c == '4') {
-                    // Encoded dollar...
-                    sb.append("$");
-                    percentSeen = false;
-                } else if (oldC == '2' && c == 'E') {
-                    // Encoded dot...
-                    sb.append(".");
-                    percentSeen = false;
-                } else if (oldC == '5' && c == 'F') {
-                    // Encoded underscore...
-                    sb.append("_");
-                    percentSeen = false;
-                } else {
-                    // Unknown encoded entity...
-                    sb.append("%").append(oldC).append(c);
-                    percentSeen = false;
-                }
-            } else {
-                if (i == 1) {
-                    sb.append(oldC);
-                }
-                sb.append(c);
-            }
-
-            if (percentSeen && (i == length - 1)) {
-                // At the end; incomplete entity found...
-                if (oldC != '%' && c != '%') {
-                    sb.append("%").append(oldC).append(c);
-                } else if (oldC == '%' && c != '%') {
-                    sb.append("%").append(c);
-                } else if (c == '%') {
-                    sb.append("%");
-                }
-            }
-
-            oldC = c;
-        }
-
-        return sb.toString();
-    }
-}
diff --git a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoDB.java b/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoDB.java
deleted file mode 100644
index 4eafab3031..0000000000
--- a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoDB.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/**
- *  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.mongodb;
-
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.Mongo;
-import com.mongodb.MongoException;
-import com.mongodb.ServerAddress;
-
-/**
- * Provides a simple facade for accessing MongoDB.
- */
-final class MongoDB {
-
-    private final List<ServerAddress> m_servers;
-    private final String m_dbName;
-    private final String m_collectionName;
-    
-    private final AtomicReference<Mongo> m_mongoRef;
-    
-    /**
-     * Creates a new {@link MongoDB} instance.
-     * 
-     * @param serverNames the space separated list of Mongo servers, cannot be <code>null</code> or empty;
-     * @param dbName the name of the MongoDB to connect to, cannot be <code>null</code> or empty; 
-     * @param collectionName the name of the collection to use, cannot be <code>null</code> or empty.
-     */
-    public MongoDB(String serverNames, String dbName, String collectionName) {
-        if (serverNames == null || "".equals(serverNames.trim())) {
-            throw new IllegalArgumentException("ServerNames cannot be null or empty!");
-        }
-        if (dbName == null || "".equals(dbName.trim())) {
-            throw new IllegalArgumentException("DbName cannot be null or empty!");
-        }
-        if (collectionName == null || "".equals(collectionName.trim())) {
-            throw new IllegalArgumentException("CollectionName cannot be null or empty!");
-        }
-        
-        m_mongoRef = new AtomicReference<Mongo>();
-
-        m_servers = parseServers(serverNames);
-        m_dbName = dbName;
-        m_collectionName = collectionName;
-    }
-
-    /**
-     * Parses the space separated list of server names.
-     * 
-     * @param serverNames the server names, cannot be <code>null</code>.
-     * @return a list of {@link ServerAddress}es to connect to, never <code>null</code>.
-     * @throws IllegalArgumentException in case the given server names was invalid.
-     */
-    private static List<ServerAddress> parseServers(String serverNames) {
-        String[] parts = serverNames.split("\\s+");
-
-        List<ServerAddress> servers = new ArrayList<ServerAddress>();
-        for (int i = 0; i < parts.length; i++) {
-            String part = parts[i];
-            try {
-                int colonPos = part.indexOf(":");
-                if (colonPos > 0 && (colonPos < part.length() - 1)) {
-                    String name = part.substring(0, colonPos);
-                    String portStr = part.substring(colonPos + 1);
-                    servers.add(new ServerAddress(name, Integer.valueOf(portStr)));
-                }
-            }
-            catch (NumberFormatException e) {
-                throw new IllegalArgumentException("Illegal port number in: " + part);
-            }
-            catch (UnknownHostException e) {
-                throw new IllegalArgumentException("Unknown host: " + part);
-            }
-        }
-
-        if (servers.isEmpty()) {
-            throw new IllegalArgumentException("No (valid) servers defined!");
-        }
-
-        return servers;
-    }
-
-    /**
-     * Connects to the MongoDB with the supplied credentials.
-     * 
-     * @param userName the optional user name to use;
-     * @param password the optional password to use.
-     * @return <code>true</code> if the connection was succesful, <code>false</code> otherwise.
-     */
-    public boolean connect(String userName, String password) {
-        Mongo newMongo = new Mongo(m_servers);
-
-        Mongo oldMongo;
-        do {
-            oldMongo = m_mongoRef.get();
-        } while (!m_mongoRef.compareAndSet(oldMongo, newMongo));
-        
-        DB db = newMongo.getDB(m_dbName);
-        if ((userName != null) && (password != null)) {
-            if (!db.authenticate(userName, password.toCharArray())) {
-                return false;
-            }
-        }
-        
-        return true;
-    }
-    
-    /**
-     * Returns the database collection to work in.
-     * 
-     * @return the {@link DBCollection}, never <code>null</code>.
-     * @throws MongoException in case no connection to Mongo exists.
-     */
-    public DBCollection getCollection() {
-        Mongo mongo = m_mongoRef.get();
-        if (mongo == null) {
-            throw new MongoException("Not connected to MongoDB!");
-        }
-        DB db = mongo.getDB(m_dbName);
-        return db.getCollection(m_collectionName);
-    }
-
-    /**
-     * Disconnects from the MongoDB.
-     */
-    public void disconnect() {
-        Mongo mongo = m_mongoRef.get();
-        if (mongo != null) {
-            try {
-                mongo.close();
-            } finally {
-                m_mongoRef.compareAndSet(mongo, null);
-            }
-        }
-    }
-}
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
deleted file mode 100644
index fd80e86e69..0000000000
--- a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoDBStore.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/**
- *  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.mongodb;
-
-import static org.apache.felix.useradmin.mongodb.MongoSerializerHelper.NAME;
-import static org.apache.felix.useradmin.mongodb.MongoSerializerHelper.TYPE;
-
-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.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedService;
-import org.osgi.service.log.LogService;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.UserAdminEvent;
-import org.osgi.service.useradmin.UserAdminListener;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBCollection;
-import com.mongodb.DBCursor;
-import com.mongodb.DBObject;
-import com.mongodb.MongoException;
-import com.mongodb.WriteResult;
-
-/**
- * Provides a repository store that uses MongoDB for storing the role information.
- * <p>
- * This service can also be configured at runtime by using the PID {@value #PID}.<br/>
- * The configuration options recognized by this service are:
- * </p>
- * <dl>
- * <dt>server</dt>
- * <dd>A space separated string containing the MongoDB servers. The format for this string is: "<code>&lt;host1:port1&gt; &lt;host2:port2&gt;</code>". This value is optional;</dd>
- * <dt>dbname</dt>
- * <dd>A string value containing the name of the database to use for this store. This value is optional;</dd>
- * <dt>collection</dt>
- * <dd>The name of the database collection to use for this store. This value is optional;</dd>
- * <dt>username</dt>
- * <dd>A string value representing the name of the user to authenticate against MongoDB. This value is optional;</dd>
- * <dt>password</dt>
- * <dd>A string value representing the password to authenticate against MongoDB. This value is optional.</dd>
- * </dl>
- * <p>
- * Alternatively, one can also supply the above mentioned configuration keys prefixed with 
- * "<tt>org.apache.felix.useradmin.mongodb.</tt>" as system properties (e.g.: 
- * <tt>-Dorg.apache.felix.useradmin.mongodb.server=my.mongo.server:27017</tt>). However, this 
- * implies that only a single store can be configured on a system (which could be a sensible
- * default for some situations)!
- * </p>
- * <p>
- * By default, the following values are used:
- * </p>
- * <table>
- * <tr><td><tt>server</tt></td><td>"<tt>localhost:27017</tt>"</td></tr>
- * <tr><td><tt>dbname</tt></td><td>"<tt>ua_repo</tt>"</td></tr>
- * <tr><td><tt>collection</tt></td><td>"<tt>useradmin</tt>"</td></tr>
- * <tr><td><tt>username</tt></td><td>&lt;none&gt;</td></tr>
- * <tr><td><tt>password</tt></td><td>&lt;none&gt;</td></tr>
- * </table>
- * <p>
- * This class is thread-safe.
- * </p>
- */
-public class MongoDBStore implements RoleProvider, RoleRepositoryStore, UserAdminListener, ManagedService {
-    
-    /** The PID for the managed service reference. */
-    public static final String PID = "org.apache.felix.useradmin.mongodb"; 
-                    
-    /** 
-     * A space-separated array with server definitions to access MongoDB. 
-     * Format = "&lt;host1:port1&gt; &lt;host2:port2&gt;". 
-     * */
-    private static final String KEY_MONGODB_SERVER = "server";
-    /** The name of the MongoDB database instance. */
-    private static final String KEY_MONGODB_DBNAME = "dbname";
-    /** The username of the MongoDB database instance. */
-    private static final String KEY_MONGODB_USERNAME = "username";
-    /** The password of the MongoDB database instance. */
-    private static final String KEY_MONGODB_PASSWORD = "password";
-    /** The name of the MongoDB collection to use. */
-    private static final String KEY_MONGODB_COLLECTION_NAME = "collection";
-
-    private static final String PREFIX = PID.concat(".");
-    /** Default MongoDB server; first checks a system property */
-    private static final String DEFAULT_MONGODB_SERVER = System.getProperty(PREFIX.concat(KEY_MONGODB_SERVER), "localhost:27017");
-    /** Default MongoDB name */
-    private static final String DEFAULT_MONGODB_DBNAME = System.getProperty(PREFIX.concat(KEY_MONGODB_DBNAME), "ua_repo");
-    /** Default MongoDB collection */
-    private static final String DEFAULT_MONGODB_COLLECTION = System.getProperty(PREFIX.concat(KEY_MONGODB_COLLECTION_NAME), "useradmin");
-    /** Default MongoDB username */
-    private static final String DEFAULT_MONGODB_USERNAME = System.getProperty(PREFIX.concat(KEY_MONGODB_USERNAME));
-    /** Default MongoDB password */
-    private static final String DEFAULT_MONGODB_PASSWORD = System.getProperty(PREFIX.concat(KEY_MONGODB_PASSWORD));
-
-    private final AtomicReference<MongoDB> m_mongoDbRef;
-    private final MongoSerializerHelper m_helper;
-    
-    private volatile LogService m_log;
-
-    /**
-     * Creates a new {@link MongoDBStore} instance.
-     */
-    public MongoDBStore() {
-        m_mongoDbRef = new AtomicReference<MongoDB>();
-        m_helper = new MongoSerializerHelper(this);
-    }
-
-    @Override
-    public Role addRole(String roleName, int type) throws MongoException {
-        if (roleName == null) {
-            throw new IllegalArgumentException("Role cannot be null!");
-        }
-        
-        DBCollection coll = getCollection();
-
-        Role role = getRole(roleName);
-        if (role != null) {
-            return null;
-        }
-
-        // 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();
-        }
-
-        // FELIX-4400: ensure we return the correct role...
-        return getRole(roleName);
-    }
-
-    /**
-     * 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[] getRoles(String filterValue) throws InvalidSyntaxException, MongoException {
-        List<Role> roles = new ArrayList<Role>();
-
-        Filter filter = null;
-        if (filterValue != null) {
-            filter = FrameworkUtil.createFilter(filterValue);
-        }
-
-        DBCollection coll = getCollection();
-
-        DBCursor cursor = coll.find();
-        try {
-            while (cursor.hasNext()) {
-                // Hmm, there might be a more clever way of doing this...
-                Role role = m_helper.deserialize(cursor.next());
-                if ((filter == null) || filter.match(role.getProperties())) {
-                    roles.add(role);
-                }
-            }
-        } finally {
-            cursor.close();
-        }
-
-        return roles.toArray(new Role[roles.size()]);
-    }
-
-    @Override
-    public Role getRole(String name) {
-        DBCollection coll = getCollection();
-
-        DBCursor cursor = coll.find(getTemplateObject(name));
-        try {
-            if (cursor.hasNext()) {
-                return m_helper.deserialize(cursor.next());
-            }
-        } finally {
-            cursor.close();
-        }
-
-        return null;
-    }
-
-    @Override
-    public Role getRoleByName(String name) throws MongoException {
-        return getRole(name);
-    }
-
-    @Override
-    public Role removeRole(String roleName) throws MongoException {
-        DBCollection coll = getCollection();
-        
-        Role role = getRole(roleName);
-        if (role == null) {
-            return null;
-        }
-
-        WriteResult result = coll.remove(getTemplateObject(role));
-
-        if (result.getLastError() != null) {
-            result.getLastError().throwOnError();
-        }
-
-        return role;
-    }
-    
-    @Override
-    public void roleChanged(UserAdminEvent event) {
-        if (UserAdminEvent.ROLE_CHANGED == event.getType()) {
-            // Only the changes are interesting, as the creation and 
-            // removal are already caught by #addRole and #removeRole.... 
-            Role changedRole = event.getRole();
-
-            try {
-                DBCollection coll = getCollection();
-
-                DBObject query = getTemplateObject(changedRole);
-                DBObject update = m_helper.serializeUpdate(changedRole);
-
-                WriteResult result = coll.update(query, update, false /* upsert */, false /* multi */);
-
-                if (result.getLastError() != null) {
-                    result.getLastError().throwOnError();
-                }
-            }
-            catch (MongoException e) {
-                m_log.log(LogService.LOG_WARNING, "Failed to update changed role: " + changedRole.getName(), e);
-            }
-        }
-    }
-    
-    /**
-     * @param log the log-service to set, cannot be <code>null</code>.
-     */
-    public void setLogService(LogService log) {
-        m_log = log;
-    }
-    
-    @Override
-    public void updated(Dictionary properties) throws ConfigurationException {
-        // Defaults to "ua_repo"
-        String newDbName = getProperty(properties, KEY_MONGODB_DBNAME, DEFAULT_MONGODB_DBNAME);
-        // Defaults to "localhost:27017"
-        String newServers = getProperty(properties, KEY_MONGODB_SERVER, DEFAULT_MONGODB_SERVER);
-        // Defaults to "useradmin"
-        String newCollectionName = getProperty(properties, KEY_MONGODB_COLLECTION_NAME, DEFAULT_MONGODB_COLLECTION);
-        // Defaults to null
-        String newUsername = getProperty(properties, KEY_MONGODB_USERNAME, DEFAULT_MONGODB_USERNAME);
-        // Defaults to null. FELIX-3774; use correct property name...
-        String newPassword = getProperty(properties, KEY_MONGODB_PASSWORD, DEFAULT_MONGODB_PASSWORD); 
-
-        MongoDB newMongoDb = new MongoDB(newServers, newDbName, newCollectionName);
-
-        MongoDB oldMongoDb;
-        do {
-            oldMongoDb = m_mongoDbRef.get();
-        }
-        while (!m_mongoDbRef.compareAndSet(oldMongoDb, newMongoDb));
-
-        try {
-            // FELIX-3775: oldMongoDb can be null when supplying the configuration for the first time...
-            if (oldMongoDb != null) {
-                oldMongoDb.disconnect();
-            }
-        }
-        catch (MongoException e) {
-            m_log.log(LogService.LOG_WARNING, "Failed to disconnect from (old) MongoDB!", e);
-        }
-
-        try {
-            connectToDB(newMongoDb, newUsername, newPassword);
-        }
-        catch (MongoException e) {
-            m_log.log(LogService.LOG_WARNING, "Failed to connect to (new) MongoDB!", e);
-            throw new ConfigurationException(DEFAULT_MONGODB_USERNAME, "Failed to connect!", e);
-        }
-    }
-
-    /**
-     * Creates a connection to MongoDB using the given credentials.
-     * 
-     * @param mongoDB the {@link MongoDB} facade to connect to;
-     * @param userName the (optional) user name to use;
-     * @param password the (optional) password to use.
-     * @throws MongoException in case the connection or authentication failed.
-     */
-    private void connectToDB(MongoDB mongoDB, String userName, String password) throws MongoException {
-        if (!mongoDB.connect(userName, password)) {
-            throw new MongoException("Failed to connect to MongoDB! Authentication failed!");
-        }
-
-        DBCollection collection = mongoDB.getCollection();
-        if (collection == null) {
-            throw new MongoException("Failed to connect to MongoDB! No collection returned!");
-        }
-
-        collection.ensureIndex(new BasicDBObject(NAME, 1).append("unique", true));
-    }
-    
-    /**
-     * Returns the current database collection.
-     * 
-     * @return the database collection to work with, cannot be <code>null</code>.
-     * @throws MongoException in case no connection to MongoDB exists.
-     */
-    private DBCollection getCollection() {
-        MongoDB mongoDB = m_mongoDbRef.get();
-        if (mongoDB == null) {
-            throw new MongoException("No connection to MongoDB?!");
-        }
-        return mongoDB.getCollection();
-    }
-    
-    /**
-     * Returns the value for the given key from the given properties.
-     * 
-     * @param properties the properties to get the value from, may be <code>null</code>;
-     * @param key the key to retrieve the value for, cannot be <code>null</code>;
-     * @param defaultValue the default value to use in case no value is present in the given dictionary, the value is not a string, or the dictionary itself was <code>null</code>.
-     * @return the value, can be <code>null</code> in case the given key lead to a null value, or a null value was supplied as default value.
-     */
-    private String getProperty(Dictionary properties, String key, String defaultValue) {
-        String result = defaultValue;
-        if (properties != null) {
-            Object value = properties.get(key);
-            if (value != null && (value instanceof String)) {
-                result = (String) value;
-            }
-        }
-        return result;
-    }
-    
-    /**
-     * Creates a template object for the given role.
-     * 
-     * @param role the role to create a template object for, cannot be <code>null</code>.
-     * @return a template object for MongoDB, never <code>null</code>.
-     */
-    private DBObject getTemplateObject(Role role) {
-        BasicDBObject query = new BasicDBObject();
-        query.put(NAME, role.getName());
-        query.put(TYPE, role.getType());
-        return query;
-    }
-    
-    /**
-     * Creates a template object for the given (role)name.
-     * 
-     * @param name the name of the role to create a template object for, cannot be <code>null</code>.
-     * @return a template object for MongoDB, never <code>null</code>.
-     */
-    private DBObject getTemplateObject(String name) {
-        BasicDBObject query = new BasicDBObject();
-        query.put(NAME, name);
-        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
deleted file mode 100644
index 06a80052ed..0000000000
--- a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/MongoSerializerHelper.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/**
- *  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.mongodb;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.List;
-
-import org.apache.felix.useradmin.RoleFactory;
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-
-import com.mongodb.BasicDBList;
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
-import com.mongodb.MongoException;
-
-/**
- * Provides a helper class for (de)serializing data to/from MongoDB.
- */
-final class MongoSerializerHelper
-{
-
-    static final String TYPE = "type";
-    static final String NAME = "name";
-
-    static final String PROPERTIES = "properties";
-    static final String CREDENTIALS = "credentials";
-    static final String MEMBERS = "members";
-    static final String REQUIRED_MEMBERS = "requiredMembers";
-
-    static final String SET = "$set";
-
-    private final RoleProvider m_roleProvider;
-
-    /**
-     * Creates a new {@link MongoSerializerHelper} instance.
-     * 
-     * @param roleProvider the role provider to use, cannot be <code>null</code>.
-     */
-    public MongoSerializerHelper(RoleProvider roleProvider)
-    {
-        m_roleProvider = roleProvider;
-    }
-
-    /**
-     * Converts a given {@link DBObject} to a {@link Role} instance.
-     * 
-     * @param object the {@link DBObject} to convert, cannot be <code>null</code>.
-     * @return a {@link Role} instance, never <code>null</code>.
-     */
-    public Role deserialize(DBObject object)
-    {
-        int type = ((Integer) object.get(TYPE)).intValue();
-        String name = (String) object.get(NAME);
-
-        Role result = RoleFactory.createRole(type, name);
-        // Read the generic properties of the role...
-        deserializeDictionary(result.getProperties(), (DBObject) object.get(PROPERTIES));
-
-        if ((Role.GROUP == type) || (Role.USER == type))
-        {
-            // This is safe, as Group extends from User...
-            deserializeDictionary(((User) result).getCredentials(), (DBObject) object.get(CREDENTIALS));
-
-            if (Role.GROUP == type)
-            {
-                for (Role member : getRoles((BasicDBList) object.get(MEMBERS)))
-                {
-                    ((Group) result).addMember(member);
-                }
-
-                for (Role member : getRoles((BasicDBList) object.get(REQUIRED_MEMBERS)))
-                {
-                    ((Group) result).addRequiredMember(member);
-                }
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * Serializes the given {@link Role} to a {@link DBObject} instance.
-     * 
-     * @param role the {@link Role} to serialize, cannot be <code>null</code> (unchecked!).
-     * @return a {@link DBObject} representing the given {@link Role}, never <code>null</code>.
-     */
-    public DBObject serialize(Role role)
-    {
-        BasicDBObject data = new BasicDBObject();
-
-        int type = role.getType();
-
-        data.put(TYPE, type);
-        data.put(NAME, role.getName());
-
-        data.put(PROPERTIES, serializeDictionary(role.getProperties()));
-        if ((Role.GROUP == type) || (Role.USER == type))
-        {
-            data.put(CREDENTIALS, serializeDictionary(((User) role).getCredentials()));
-
-            if (Role.GROUP == type)
-            {
-                data.put(MEMBERS, getRoleNames(((Group) role).getMembers()));
-                data.put(REQUIRED_MEMBERS, getRoleNames(((Group) role).getRequiredMembers()));
-            }
-        }
-
-        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.
-     * 
-     * @param role the {@link Role} to update, cannot be <code>null</code>.
-     * @return a {@link DBObject} representing an update statement for the given {@link Role}.
-     */
-    public DBObject serializeUpdate(Role role)
-    {
-        int type = role.getType();
-
-        BasicDBObject changeSet = new BasicDBObject();
-
-        changeSet.put(PROPERTIES, serializeDictionary(role.getProperties()));
-        if ((Role.GROUP == type) || (Role.USER == type))
-        {
-            changeSet.put(CREDENTIALS, serializeDictionary(((User) role).getCredentials()));
-
-            if (Role.GROUP == type)
-            {
-                changeSet.put(MEMBERS, getRoleNames(((Group) role).getMembers()));
-                changeSet.put(REQUIRED_MEMBERS, getRoleNames(((Group) role).getRequiredMembers()));
-            }
-        }
-
-        return new BasicDBObject(SET, changeSet);
-    }
-
-    /**
-     * Finds an existing member by its name.
-     * 
-     * @param name the name of the member to return, cannot be <code>null</code>.
-     * @return a member instance, never <code>null</code>.
-     * @throws MongoException in case the requested member was not found (or any other MongoDB exception).
-     */
-    final Role findExistingMember(String name)
-    {
-        Role result = m_roleProvider.getRole(name);
-        if (result == null)
-        {
-            throw new MongoException("No such role: " + name);
-        }
-        return result;
-    }
-
-    /**
-     * Deserializes the given {@link DBObject} into the given {@link Dictionary}.
-     * 
-     * @param dictionary the dictionary to fill, cannot be <code>null</code>;
-     * @param object the {@link DBObject} to deserialize, can be <code>null</code>.
-     */
-    private void deserializeDictionary(Dictionary dictionary, DBObject object)
-    {
-        // FELIX-4399: MongoDB does return null for empty properties...
-        if (object != null)
-        {
-            for (String key : object.keySet())
-            {
-                dictionary.put(KeyCodec.decode(key), object.get(key));
-            }
-        }
-    }
-
-    /**
-     * Serializes a given array of {@link Role}s to an list for storing in a {@link DBObject}.
-     * 
-     * @param members the {@link Role}s to serialize, cannot be <code>null</code>.
-     * @return the "serialized" array, never <code>null</code>.
-     */
-    private List<String> getRoleNames(Role[] members)
-    {
-        List<String> result = new ArrayList<String>();
-        if (members != null)
-        {
-            for (Role member : members)
-            {
-                result.add(member.getName());
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Returns all roles mentioned in the given list.
-     * 
-     * @param list the list with role names to convert, can be <code>null</code>.
-     * @return a list with {@link Role}s, never <code>null</code>.
-     */
-    private List<Role> getRoles(BasicDBList list)
-    {
-        List<Role> result = new ArrayList<Role>();
-        // FELIX-4399: MongoDB does return null for empty properties...
-        int size = (list == null) ? 0 : list.size();
-        for (int i = 0; i < size; i++)
-        {
-            final String memberName = (String) list.get(i);
-            result.add(findExistingMember(memberName));
-        }
-        return result;
-    }
-
-    /**
-     * Serializes a given {@link Dictionary} into a {@link DBObject}.
-     * 
-     * @param properties the {@link Dictionary} to serialize, cannot be <code>null</code>.
-     * @return the serialized dictionary, never <code>null</code>. 
-     */
-    private DBObject serializeDictionary(Dictionary properties)
-    {
-        BasicDBObject result = new BasicDBObject();
-
-        Enumeration<String> keysEnum = properties.keys();
-        while (keysEnum.hasMoreElements())
-        {
-            String key = keysEnum.nextElement();
-            Object value = properties.get(key);
-
-            result.append(KeyCodec.encode(key), value);
-        }
-
-        return result;
-    }
-}
diff --git a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/RoleProvider.java b/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/RoleProvider.java
deleted file mode 100644
index 82f8b2376e..0000000000
--- a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/RoleProvider.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- *  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.mongodb;
-
-import org.osgi.service.useradmin.Role;
-
-/**
- * Provides access to a {@link Role}.
- */
-public interface RoleProvider {
-
-    /**
-     * Returns the {@link Role} with the given name.
-     * 
-     * @param name the name of the role to return, cannot be <code>null</code>.
-     * @return a {@link Role} with the given name, or <code>null</code> if no such role exists.
-     */
-    Role getRole(String name);
-}
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
deleted file mode 100644
index b2eeee9d3c..0000000000
--- a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/osgi/Activator.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- *  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.mongodb.osgi;
-
-import java.util.Properties;
-
-import org.apache.felix.useradmin.RoleRepositoryStore;
-import org.apache.felix.useradmin.mongodb.MongoDBStore;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.service.cm.ManagedService;
-import org.osgi.service.useradmin.UserAdminListener;
-
-/**
- * Registers {@link MongoDBStore} as service.
- */
-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();
-        
-        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() };
-
-        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/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/osgi/LogServiceHelper.java b/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/osgi/LogServiceHelper.java
deleted file mode 100644
index 5397cf97e0..0000000000
--- a/useradmin/mongodb/src/main/java/org/apache/felix/useradmin/mongodb/osgi/LogServiceHelper.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- *  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.mongodb.osgi;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.log.LogService;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * Provides a facade for {@link LogService} allowing it to be not 
- * available as actual service without its users knowing about this.
- */
-public class LogServiceHelper extends ServiceTracker implements LogService {
-
-    /**
-     * Creates a new {@link LogServiceHelper} instance.
-     * 
-     * @param context the bundle context to use, cannot be <code>null</code>.
-     */
-    public LogServiceHelper(BundleContext context) {
-        super(context, LogService.class.getName(), null);
-    }
-    
-    @Override
-    public void log(int level, String message) {
-        LogService logService = getLogService();
-        if (logService != null) {
-            logService.log(level, message);
-        }
-    }
-
-    @Override
-    public void log(int level, String message, Throwable exception) {
-        LogService logService = getLogService();
-        if (logService != null) {
-            logService.log(level, message, exception);
-        }
-    }
-
-    @Override
-    public void log(ServiceReference sr, int level, String message) {
-        LogService logService = getLogService();
-        if (logService != null) {
-            logService.log(sr, level, message);
-        }
-    }
-
-    @Override
-    public void log(ServiceReference sr, int level, String message, Throwable exception) {
-        LogService logService = getLogService();
-        if (logService != null) {
-            logService.log(sr, level, message, exception);
-        }
-    }
-    
-    /**
-     * @return a {@link LogService} instance, or <code>null</code> if not available.
-     */
-    private LogService getLogService() {
-        return (LogService) getService();
-    }
-}
diff --git a/useradmin/mongodb/src/main/resources/DEPENDENCIES b/useradmin/mongodb/src/main/resources/DEPENDENCIES
deleted file mode 100644
index 995ebb9554..0000000000
--- a/useradmin/mongodb/src/main/resources/DEPENDENCIES
+++ /dev/null
@@ -1,26 +0,0 @@
-Apache Felix UserAdmin MongoDB-based store
-Copyright 2012 The Apache Software Foundation
-
-This software was developed at the Apache Software Foundation
-(http://www.apache.org) and may have dependencies on other
-Apache software licensed under Apache License 2.0.
-
-I. Included Third-Party Software
-
-n/a
-
-II. Used Third-Party Software
-
-This product includes software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2009).
-Licensed under the Apache License 2.0.
-
-This product depends on:
-MongoDB Java Driver (http://mongodb.org/).
-Copyright (c) 10gen (2009).
-Licensed under the Apache License 2.0.
-
-III. Overall License Summary
-- Apache License 2.0
-
diff --git a/useradmin/mongodb/src/main/resources/LICENSE b/useradmin/mongodb/src/main/resources/LICENSE
deleted file mode 100644
index d645695673..0000000000
--- a/useradmin/mongodb/src/main/resources/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/useradmin/mongodb/src/main/resources/NOTICE b/useradmin/mongodb/src/main/resources/NOTICE
deleted file mode 100644
index 7333ec4823..0000000000
--- a/useradmin/mongodb/src/main/resources/NOTICE
+++ /dev/null
@@ -1,6 +0,0 @@
-Apache Felix User Admin MongoDB-based store
-Copyright 2012 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
diff --git a/useradmin/mongodb/src/main/resources/README b/useradmin/mongodb/src/main/resources/README
deleted file mode 100644
index d3ae6ef3bf..0000000000
--- a/useradmin/mongodb/src/main/resources/README
+++ /dev/null
@@ -1,38 +0,0 @@
-Apache Felix UserAdmin MongoDB-based store
-Copyright 2012 The Apache Software Foundation
-
-This project provides a MongoDB-based store for use with the Felix UserAdmin
-service. It uses MongoDB to persist the role information.
-
-The MongoDB-based store service this bundle provides can be configured at 
-runtime by using the service PID "org.apache.felix.useradmin.mongodb". The 
-configuration options recognized by this service are:
-
-"server"
-   A space separated string containing the MongoDB servers. The format for 
-   this string is: "<host1:port1> <host2:port2>". This value is optional and
-   defaults to "localhost:27017";
-"dbname"
-   A string value containing the name of the database to use for this store. 
-   This value is optional and defaults to "ua_repo";
-"collection"
-   The name of the database collection to use for this store. This value is 
-   optional and defaults to "useradmin";
-"username"
-   A string value representing the name of the user to authenticate against 
-   MongoDB. This value is optional and defaults to "" (empty string);
-"password"
-   A string value representing the password to authenticate against MongoDB. 
-   This value is optional and defaults to "" (empty string). 
-
-Alternatively, one can also supply the above mentioned configuration keys 
-prefixed with "org.apache.felix.useradmin.mongodb." as system properties. For
-example by adding the following to your JVM arguments:
-
-  -Dorg.apache.felix.useradmin.mongodb.server=my.mongo.server:27017
-
-will let this service use the MongoDB server at "my.mongo.server".
-
-However, using system properties will imply that only a single store can be 
-configured on a system (which could be a sensible default for some 
-situations)!
diff --git a/useradmin/mongodb/src/test/java/org/apache/felix/useradmin/mongodb/KeyCodecTest.java b/useradmin/mongodb/src/test/java/org/apache/felix/useradmin/mongodb/KeyCodecTest.java
deleted file mode 100644
index ca9ba58f1d..0000000000
--- a/useradmin/mongodb/src/test/java/org/apache/felix/useradmin/mongodb/KeyCodecTest.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/**
- *  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.mongodb;
-
-import junit.framework.TestCase;
-
-/**
- * Test cases for {@link KeyCodec}.
- */
-public class KeyCodecTest extends TestCase {
-
-    /**
-     * Tests that we can decode a string with an encoded dollar.
-     */
-    public void testDecodeDollarOk() {
-        String input = "%24hello %24world";
-        assertEquals("$hello $world", KeyCodec.decode(input));
-    }
-
-    /**
-     * Tests that we can decode a string with encoded dot and dollars.
-     */
-    public void testDecodeDotAndDollarsOk() {
-        String input = "%24hello %24world%2E";
-        assertEquals("$hello $world.", KeyCodec.decode(input));
-    }
-
-    /**
-     * Tests that we can decode a string with an encoded dot.
-     */
-    public void testDecodeDotOk() {
-        String input = "hello world%2E";
-        assertEquals("hello world.", KeyCodec.decode(input));
-    }
-
-    /**
-     * Tests that encoding a string with a dot works.
-     */
-    public void testDecodeEncodeOk() {
-        String key = "%25hello world.";
-        assertEquals(key, KeyCodec.decode(KeyCodec.encode(key)));
-    }
-
-    /**
-     * Tests that we can decode a string with an incorrect entity at the end.
-     */
-    public void testDecodeIncorrectEntityAtEndOk() {
-        String input = "hello world%1";
-        assertEquals("hello world%1", KeyCodec.decode(input));
-    }
-
-    /**
-     * Tests that we can decode a string with an incorrect entity at the end.
-     */
-    public void testDecodeIncorrectEntityOk() {
-        String input = "hello%1world";
-        assertEquals("hello%1world", KeyCodec.decode(input));
-    }
-
-    /**
-     * Tests that we can decode a string with an encoded null.
-     */
-    public void testDecodeNullEntityOk() {
-        String input = "%00hello%00world";
-        assertEquals("\0hello\0world", KeyCodec.decode(input));
-    }
-
-    /**
-     * Tests that we can decode a null value.
-     */
-    public void testDecodeNullOk() {
-        assertNull(KeyCodec.decode(null));
-    }
-
-    /**
-     * Tests that we can decode a string with a percent sign at the end.
-     */
-    public void testDecodePercentAtEndOk() {
-        String input = "hello world%";
-        assertEquals("hello world%", KeyCodec.decode(input));
-    }
-
-    /**
-     * Tests that we can decode a string with an escaped percent.
-     */
-    public void testDecodePercentOk() {
-        String input = "%%1%%%2E";
-        assertEquals("%1%.", KeyCodec.decode(input));
-        
-        input = "%%Hello %%World%2E";
-        assertEquals("%Hello %World.", KeyCodec.decode(input));
-    }
-
-    /**
-     * Tests that we can decode a string with an encoded underscore.
-     */
-    public void testDecodeUnderscoreOk() {
-        String input = "%5Fhello%5Fworld";
-        assertEquals("_hello_world", KeyCodec.decode(input));
-    }
-
-    /**
-     * Tests that we can decode a string with an unknown entity at the end.
-     */
-    public void testDecodeUnknownEntityAtEndOk() {
-        String input = "hello world%10";
-        assertEquals("hello world%10", KeyCodec.decode(input));
-    }
-
-    /**
-     * Tests that we can decode a string with an unknown entity.
-     */
-    public void testDecodeUnknownEntityOk() {
-        String input = "%25hello %25world%2F";
-        assertEquals("%25hello %25world%2F", KeyCodec.decode(input));
-    }
-
-    /**
-     * Tests that encoding a string with dollars works.
-     */
-    public void testEncodeDollarOk() {
-        String key = "$hello $world";
-        assertEquals("%24hello %24world", KeyCodec.encode(key));
-    }
-
-    /**
-     * Tests that encoding a string with dollars and a dot works.
-     */
-    public void testEncodeDotAndDollarOk() {
-        String key = "$hello $world.";
-        assertEquals("%24hello %24world%2E", KeyCodec.encode(key));
-    }
-
-    /**
-     * Tests that encoding a string with a dot works.
-     */
-    public void testEncodeDotOk() {
-        String key = "hello world.";
-        assertEquals("hello world%2E", KeyCodec.encode(key));
-    }
-
-    /**
-     * Tests that encoding a string with null-characters works.
-     */
-    public void testEncodeNullEntityOk() {
-        String key = "\0hello\0world";
-        assertEquals("%00hello%00world", KeyCodec.encode(key));
-    }
-
-    /**
-     * Tests that we can encode a null value.
-     */
-    public void testEncodeNullInputOk() {
-        assertNull(KeyCodec.encode(null));
-    }
-
-    /**
-     * Tests that encoding a string with percents works.
-     */
-    public void testEncodePercentOk() {
-        String key = "%hello %world.";
-        assertEquals("%%hello %%world%2E", KeyCodec.encode(key));
-    }
-
-    /**
-     * Tests that encoding a string without dots or dollars works.
-     */
-    public void testEncodePlainStringOk() {
-        String key = "hello world!";
-        assertEquals(key, KeyCodec.encode(key));
-    }
-
-    /**
-     * Tests that encoding a string with underscores works.
-     */
-    public void testEncodeUnderscoreOk() {
-        String key = "_hello_world";
-        assertEquals("%5Fhello%5Fworld", KeyCodec.encode(key));
-    }
-
-    /**
-     * Tests that encoding a string with a dot works.
-     */
-    public void testEncodeUnknownEntitiesOk() {
-        String key = "%25hello world.";
-        assertEquals("%%25hello world%2E", KeyCodec.encode(key));
-    }
-}
diff --git a/useradmin/pom.xml b/useradmin/pom.xml
deleted file mode 100644
index 80bff5d0bf..0000000000
--- a/useradmin/pom.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<!--
-    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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>felix-parent</artifactId>
-        <version>2.1</version>
-        <relativePath>../../pom/pom.xml</relativePath>
-    </parent>
-    <packaging>pom</packaging>
-    <artifactId>useradmin-reactor</artifactId>
-	<description>UserAdmin OSGi compendium service subproject.</description>
-    <version>1</version>
-    <modules>
-        <module>useradmin</module>
-        <module>filestore</module>
-        <module>mongodb</module>
-        <module>itest</module>
-    </modules>
-</project>
diff --git a/useradmin/useradmin/pom.xml b/useradmin/useradmin/pom.xml
deleted file mode 100644
index b6a37f46bb..0000000000
--- a/useradmin/useradmin/pom.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<!--
-    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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<parent>
-		<artifactId>felix-parent</artifactId>
-		<groupId>org.apache.felix</groupId>
-        <version>6</version>
-        <relativePath />
-	</parent>
-    <modelVersion>4.0.0</modelVersion>
-    <packaging>bundle</packaging>
-    <name>Apache Felix User Admin</name>
-    <description>
-        Provides an implementation for the UserAdmin OSGi
-        compendium service.
-    </description>
-	<artifactId>org.apache.felix.useradmin</artifactId>
-    <version>1.0.7-SNAPSHOT</version>
-    <scm>
-        <connection>scm:git:https://github.com/apache/felix-dev.git</connection>
-        <developerConnection>scm:git:https://github.com/apache/felix-dev.git</developerConnection>
-        <url>https://gitbox.apache.org/repos/asf?p=felix-dev.git</url>
-    </scm>
-	<dependencies>
-		<dependency>
-			<groupId>org.osgi</groupId>
-			<artifactId>org.osgi.compendium</artifactId>
-			<version>4.0.0</version>
-		</dependency>
-		<dependency>
-            <groupId>org.apache.felix</groupId>
-			<artifactId>org.apache.felix.framework</artifactId>
-			<version>4.0.2</version>
-		</dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.12</version>
-            <scope>test</scope>
-        </dependency>
-	</dependencies>
-	<build>
-		<plugins>
-            <plugin>
-                <groupId>org.apache.rat</groupId>
-                <artifactId>apache-rat-plugin</artifactId>
-                <configuration>
-                    <includes>
-                        <include>src/**</include>
-                    </includes>
-                    <excludes>
-                        <exclude>src/main/resources/**</exclude>
-                    </excludes>
-                </configuration>
-            </plugin>
-			<plugin>
-				<groupId>org.apache.felix</groupId>
-				<artifactId>maven-bundle-plugin</artifactId>
-                <version>3.2.0</version>
-				<extensions>true</extensions>
-				<configuration>
-					<instructions>
-						<Bundle-Name>Apache Felix User Admin Service</Bundle-Name>
-						<Bundle-Description>
-							An implementation of the OSGi User Admin Compendium Service
-						</Bundle-Description>
-						<Bundle-Activator>
-							${project.artifactId}.osgi.Activator
-						</Bundle-Activator>
-						<Bundle-SymbolicName>
-							${project.artifactId}
-						</Bundle-SymbolicName>
-						<Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
-						<Import-Package>
-							org.osgi.framework;version="[1.5,2.0)",
-						    org.osgi.service.useradmin; version="[1.1,1.2)",
-						    org.osgi.service.event; version="[1.0,2)"; resolution:=optional,
-						    *
-						</Import-Package>
-						<Export-Package>
-					        org.osgi.service.useradmin; version="1.1",
-							${project.artifactId}; version="1.0.0"
-						</Export-Package>
-						<Private-Package>
-							${project.artifactId}.*
-						</Private-Package>
-                                                <Provide-Capability>
-					                osgi.service;objectClass:List&lt;String&gt;="org.osgi.service.useradmin.UserAdmin"
-						</Provide-Capability>
-					</instructions>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-</project>
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/BackendException.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/BackendException.java
deleted file mode 100644
index eb411f220c..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/BackendException.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- *  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;
-
-/**
- * Represents a runtime exception for {@link RoleRepositoryStore}s.
- */
-public class BackendException extends RuntimeException {
-
-    private static final long serialVersionUID = 5566633157189079557L;
-
-    /**
-     * Creates a new {@link BackendException} instance.
-     * 
-     * @param cause the originating cause of this exception.
-     */
-    public BackendException(Exception cause) {
-        super(cause);
-    }
-
-    /**
-     * Creates a new {@link BackendException} instance.
-     * 
-     * @param message the message of this exception.
-     */
-    public BackendException(String message) {
-        super(message);
-    }
-
-    /**
-     * Creates a new {@link BackendException} instance.
-     * 
-     * @param message the message of this exception;
-     * @param cause the originating cause of this exception.
-     */
-    public BackendException(String message, Exception cause) {
-        super(message, cause);
-    }
-}
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
deleted file mode 100644
index ec4595c1bf..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/RoleFactory.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- *  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;
-
-
-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 
- * implementations to create new role instances.
- */
-public final class RoleFactory {
-
-    /**
-     * 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>.
-     */
-    public static Group createGroup(String name) {
-        return (Group) createRole(Role.GROUP, name);
-    }
-
-    /**
-     * 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 Role} instance denoting the requested role, never <code>null</code>.
-     */
-    public static Role createRole(int type, String name) {
-        if (type == Role.USER) {
-            UserImpl result = new UserImpl(name);
-            return result;
-        } else if (type == Role.GROUP) {
-            GroupImpl result = new GroupImpl(name);
-            return result;
-        } else {
-            RoleImpl result = new RoleImpl(name);
-            return result;
-        }
-    }
-
-    /**
-     * Creates a new role instance.
-     * 
-     * @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
deleted file mode 100644
index f32e5de408..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/RoleRepositoryStore.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- *  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;
-
-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 {
-
-    /**
-     * 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>null</code> to denote this.
-     * </p>
-     * 
-     * @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.
-     */
-    Role addRole(String roleName, int type) throws Exception;
-
-    /**
-     * Returns all roles in this backend matching the given filter criteria.
-     * 
-     * @param filter the (optional) filter to apply, can be <code>null</code> in which case all roles will be returned.
-     * @return an array with all roles, never <code>null</code>, but can be empty.
-     * @throws Exception in case of problems retrieving the set of roles.
-     */
-    Role[] getRoles(String 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 Exception in case of problems retrieving the requested role.
-     */
-    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>null</code> to denote this.
-     * </p>
-     * 
-     * @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 Exception in case of problems removing the requested role.
-     */
-    Role removeRole(String roleName) throws Exception;
-}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/AuthorizationImpl.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/AuthorizationImpl.java
deleted file mode 100644
index 0c93c191de..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/AuthorizationImpl.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- *  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.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.osgi.service.useradmin.Authorization;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-
-/**
- * Provides an implementation for {@link Authorization}.
- */
-public class AuthorizationImpl implements Authorization {
-
-    private final String m_name;
-    private final User m_user;
-    private final RoleRepository m_roleManager;
-    private final RoleChecker m_roleChecker;
-
-    /**
-     * Creates a new {@link AuthorizationImpl} instance for the given {@link User}.
-     * 
-     * @param roleManager the role manager to use for obtaining the roles, cannot be <code>null</code>.
-     */
-    public AuthorizationImpl(RoleRepository roleManager) {
-        this(null, roleManager);
-    }
-
-    /**
-     * Creates a new {@link AuthorizationImpl} instance for the given {@link User}.
-     * 
-     * @param user the {@link User} to authorize, may be <code>null</code> for the anonymous user;
-     * @param roleManager the role manager to use for obtaining the roles, cannot be <code>null</code>.
-     */
-    public AuthorizationImpl(User user, RoleRepository roleManager) {
-        m_user = user;
-        m_roleManager = roleManager;
-        m_name = (user != null) ? user.getName() : null;
-        m_roleChecker = new RoleChecker();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getName() {
-        return m_name;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean hasRole(String name) {
-        Role role = m_roleManager.getRoleByName(name);
-        if (role == null) {
-            // No role found, so it is never implied...
-            return false;
-        }
-        return m_roleChecker.isImpliedBy(role, m_user);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String[] getRoles() {
-        List result = new ArrayList();
-
-        Iterator rolesIter = m_roleManager.getRoles(null /* filter */).iterator();
-        while (rolesIter.hasNext()) {
-            Role role = (Role) rolesIter.next();
-            if (!Role.USER_ANYONE.equals(role.getName()) && m_roleChecker.isImpliedBy(role, m_user)) {
-                result.add(role.getName());
-            }
-        }
-
-        return result.isEmpty() ? null : (String[]) result.toArray(new String[result.size()]);
-    }
-}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/EventDispatcher.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/EventDispatcher.java
deleted file mode 100644
index d769bee491..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/EventDispatcher.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/**
- *  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.util.Properties;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.service.event.EventConstants;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.UserAdminEvent;
-import org.osgi.service.useradmin.UserAdminListener;
-
-/**
- * Provides an event dispatcher for delivering {@link UserAdminEvent}s asynchronously. 
- */
-public final class EventDispatcher implements Runnable {
-    
-    private static final String TOPIC_BASE = "org/osgi/service/useradmin/UserAdmin/";
-
-    private final EventAdmin m_eventAdmin;
-    private final UserAdminListenerList m_listenerList;
-    private final BlockingQueue m_eventQueue;
-    private final Thread m_backgroundThread;
-
-    /**
-     * Creates a new {@link EventDispatcher} instance, and starts a background thread to deliver all events.
-     * 
-     * @param eventAdmin the event admin to use, cannot be <code>null</code>;
-     * @param listenerList the list with {@link UserAdminListener}s, cannot be <code>null</code>.
-     * @throws IllegalArgumentException in case one of the given parameters was <code>null</code>.
-     */
-    public EventDispatcher(EventAdmin eventAdmin, UserAdminListenerList listenerList) {
-        if (eventAdmin == null) {
-            throw new IllegalArgumentException("EventAdmin cannot be null!");
-        }
-        if (listenerList == null) {
-            throw new IllegalArgumentException("ListenerList cannot be null!");
-        }
-
-        m_eventAdmin = eventAdmin;
-        m_listenerList = listenerList;
-        m_eventQueue = new LinkedBlockingQueue();
-
-        m_backgroundThread = new Thread(this, "UserAdmin event dispatcher");
-    }
-
-    /**
-     * Dispatches a given event for asynchronous delivery to all interested listeners, 
-     * including those using the {@link EventAdmin} service.
-     * <p>
-     * This method will perform a best-effort to dispatch the event to all listeners, i.e., 
-     * there is no guarantee that the listeners will actually obtain the event, nor any
-     * notification is given in case delivery fails.
-     * </p>
-     * 
-     * @param event the event to dispatch, cannot be <code>null</code>.
-     * @throws IllegalStateException in case this dispatcher is already stopped.
-     */
-    public void dispatch(UserAdminEvent event) {
-        if (!isRunning()) {
-            return;
-        }
-
-        try {
-            m_eventQueue.put(event);
-        } catch (InterruptedException e) {
-            // Restore interrupt flag...
-            Thread.currentThread().interrupt();
-        }
-    }
-    
-    /**
-     * Starts this event dispatcher, allowing it to pick up events and deliver them.
-     */
-    public void start() {
-        if (!isRunning()) {
-            m_backgroundThread.start();
-        }
-    }
-
-    /**
-     * Signals this event dispatcher to stop its work and clean up all running threads.
-     */
-    public void stop() {
-        if (!isRunning()) {
-            return;
-        }
-
-        // Add poison object to queue to let the background thread terminate...
-        m_eventQueue.add(EventDispatcher.this);
-
-        try {
-            m_backgroundThread.join();
-        } catch (InterruptedException e) {
-            // We're already stopping; so don't bother... 
-        }
-    }
-
-    /**
-     * Returns whether or not the background thread is running.
-     * 
-     * @return <code>true</code> if the background thread is running (alive), <code>false</code> otherwise.
-     */
-    final boolean isRunning() {
-        return m_backgroundThread.isAlive();
-    }
-    
-    /**
-     * Provides the main event loop, which waits until an event is enqueued in order 
-     * to deliver it to any interested listener.
-     */
-    public void run() {
-        try {
-            while (true) {
-                // Blocks until a event is dispatched...
-                Object event = m_eventQueue.take();
-
-                if (event instanceof UserAdminEvent) {
-                    // Got a "normal" user admin event; lets dispatch it further...
-                    deliverEventSynchronously((UserAdminEvent) event);
-                } else {
-                    // Got a "poison" object; this means we must stop running...
-                    return;
-                }
-            }
-        } catch (InterruptedException e) {
-            // Restore interrupt flag, and terminate thread...
-            Thread.currentThread().interrupt();
-        }
-    }
-
-    /**
-     * Converts a given {@link UserAdminEvent} to a {@link Event} that can be
-     * dispatched through the {@link EventAdmin} service.
-     * 
-     * @param event
-     *            the event to convert, cannot be <code>null</code>.
-     * @return a new {@link Event} instance containing the same set of
-     *         information as the given event, never <code>null</code>.
-     */
-    private Event convertEvent(UserAdminEvent event) {
-        String topic = getTopicName(event.getType());
-        Role role = event.getRole();
-        ServiceReference serviceRef = event.getServiceReference();
-
-        Properties props = new Properties();
-        props.put(EventConstants.EVENT_TOPIC, TOPIC_BASE.concat(topic));
-        props.put(EventConstants.EVENT, event);
-        props.put("role", role);
-        props.put("role.name", role.getName());
-        props.put("role.type", new Integer(role.getType()));
-        if (serviceRef != null) {
-            props.put(EventConstants.SERVICE, serviceRef);
-            Object property;
-            
-            property = serviceRef.getProperty(Constants.SERVICE_ID);
-            if (property != null) {
-                props.put(EventConstants.SERVICE_ID, property);
-            }
-            property = serviceRef.getProperty(Constants.OBJECTCLASS);
-            if (property != null) {
-                props.put(EventConstants.SERVICE_OBJECTCLASS, property);
-            }
-            property = serviceRef.getProperty(Constants.SERVICE_PID);
-            if (property != null) {
-                props.put(EventConstants.SERVICE_PID, property);
-            }
-        }
-
-        return new Event(topic, props);
-    }
-
-    /**
-     * Delivers the given event synchronously to all interested listeners.
-     * 
-     * @param event the event to deliver, cannot be <code>null</code>.
-     */
-    private void deliverEventSynchronously(UserAdminEvent event) {
-        // Asynchronously deliver an event to the EventAdmin service...
-        m_eventAdmin.postEvent(convertEvent(event));
-
-        // Synchronously call all UserAdminListeners to deliver the event...
-        UserAdminListener[] listeners = m_listenerList.getListeners();
-        for (int i = 0; i < listeners.length; i++) {
-            listeners[i].roleChanged(event);
-        }
-    }
-    
-    /**
-     * Converts a topic name for the given event-type.
-     * 
-     * @param type the type of event to get the topic name for.
-     * @return a topic name, never <code>null</code>.
-     */
-    private String getTopicName(int type) {
-        switch (type) {
-            case UserAdminEvent.ROLE_CREATED:
-                return "ROLE_CREATED";
-            case UserAdminEvent.ROLE_CHANGED:
-                return "ROLE_CHANGED";
-            case UserAdminEvent.ROLE_REMOVED:
-                return "ROLE_REMOVED";
-            default:
-                return null;
-        }
-    }
-}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/RoleChangeListener.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/RoleChangeListener.java
deleted file mode 100644
index f9a914bfad..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/RoleChangeListener.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- *  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 org.osgi.service.useradmin.Role;
-
-/**
- * Provides a callback for listening to role changes.
- */
-public interface RoleChangeListener {
-
-    /**
-     * Called when a new role is added.
-     * 
-     * @param role the role that is added.
-     */
-    void roleAdded(Role role);
-    
-    /**
-     * Called when a role is removed.
-     * 
-     * @param role the role that is removed.
-     */
-    void roleRemoved(Role role);
-    
-    /**
-     * Called when a new property-entry is added to a role.
-     * 
-     * @param role the role that changed;
-     * @param key the key of the entry;
-     * @param value the value associated to the key.
-     */
-    void propertyAdded(Role role, Object key, Object value);
-
-    /**
-     * Called when an property-entry is removed from a role.
-     * 
-     * @param role the role that changed;
-     * @param key the key of the entry.
-     */
-    void propertyRemoved(Role role, Object key);
-
-    /**
-     * Called when an property-entry is changed for a role.
-     * 
-     * @param role the role that changed;
-     * @param key the key of the entry;
-     * @param oldValue the old value associated to the key;
-     * @param newValue the new value associated to the key.
-     */
-    void propertyChanged(Role role, Object key, Object oldValue, Object newValue);
-}
\ No newline at end of file
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/RoleChecker.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/RoleChecker.java
deleted file mode 100644
index f0c41881fc..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/RoleChecker.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- *  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.util.ArrayList;
-import java.util.List;
-
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-
-/**
- * Helper class to check for implied role memberships.
- */
-final class RoleChecker {
-
-    /**
-     * Verifies whether the given role is implied by the memberships of the given user.
-     * 
-     * @param user the user to check the roles for, cannot be <code>null</code>;
-     * @param impliedRole the implied role to check for, cannot be <code>null</code>.
-     * @return <code>true</code> if the given user has the implied role, <code>false</code> otherwise.
-     */
-    public boolean isImpliedBy(Role role, Role impliedRole) {
-        if (role instanceof Group) {
-            return isGroupImpliedBy((Group) role, impliedRole, new ArrayList());
-        } else /* if ((role instanceof User) || (role instanceof Role)) */ {
-            return isRoleImpliedBy(role, impliedRole);
-        }
-    }
-
-    /**
-     * Verifies whether the given group is implied by the given role.
-     * 
-     * @param group the group to check, cannot be <code>null</code>;
-     * @param impliedRole the implied role to check for, cannot be <code>null</code>;
-     * @param seenGroups a list of all seen groups, used for detecting cycles in groups, cannot be <code>null</code>.
-     * @return <code>true</code> if the given group has the implied role, <code>false</code> otherwise.
-     */
-    private boolean isGroupImpliedBy(Group group, Role impliedRole, List seenGroups) {
-        Role[] basicRoles = group.getMembers();
-        Role[] requiredRoles = group.getRequiredMembers();
-
-        boolean isImplied = true;
-        
-        // Check whether all required roles are implied...
-        for (int i = 0; (requiredRoles != null) && isImplied && (i < requiredRoles.length); i++) {
-            Role requiredRole = requiredRoles[i];
-            if (seenGroups.contains(requiredRole)) {
-                // Found a cycle between groups; always yield false!
-                return false;
-            }
-            
-            if (requiredRole instanceof Group) {
-                seenGroups.add(requiredRole);
-                isImplied = isGroupImpliedBy((Group) requiredRole, impliedRole, seenGroups);
-            } else /* if ((requiredRole instanceof User) || (requiredRole instanceof Role)) */ {
-                isImplied  = isRoleImpliedBy(requiredRole, impliedRole);
-            }
-        }
-
-        // Required role is not implied by the given role; we can stop now...
-        if (!isImplied) {
-            return false;
-        }
-
-        // Ok; all required roles are implied, let's verify whether a least one basic role is implied...
-        isImplied = false;
-
-        // Check whether at least one basic role is implied...
-        for (int i = 0; (basicRoles != null) && !isImplied && (i < basicRoles.length); i++) {
-            Role basicRole = (Role) basicRoles[i];
-            if (seenGroups.contains(basicRole)) {
-                // Found a cycle between groups; always yield false!
-                return false;
-            }
-
-            if (basicRole instanceof Group) {
-                seenGroups.add(basicRole);
-                isImplied = isGroupImpliedBy((Group) basicRole, impliedRole, seenGroups);
-            } else /* if ((basicRole instanceof User) || (basicRole instanceof Role)) */ {
-                isImplied = isRoleImpliedBy(basicRole, impliedRole);
-            }
-        }
-
-        return isImplied;
-    }
-
-    /**
-     * Verifies whether the given role is implied by the given role.
-     * 
-     * @param role the role to check, cannot be <code>null</code>;
-     * @param impliedRole the implied role to check for, cannot be <code>null</code>;
-     * @return <code>true</code> if the given role is implied by the given role, <code>false</code> otherwise.
-     */
-    private boolean isRoleImpliedBy(Role role, Role impliedRole) {
-        return Role.USER_ANYONE.equals(role.getName()) || (impliedRole != null && impliedRole.getName().equals(role.getName()));
-    }
-}
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
deleted file mode 100644
index cf49c04910..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/RoleRepository.java
+++ /dev/null
@@ -1,394 +0,0 @@
-/**
- *  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.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-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.ObservableRole;
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.UserAdminPermission;
-
-/**
- * Provides a manager and entry-point for accessing {@link Role}s.
- */
-public final class RoleRepository {
-
-    /**
-     * Hands off all obtained role change event to a local set of listeners.
-     */
-    final class RoleChangeReflector implements RoleChangeListener {
-        /**
-         * {@inheritDoc}
-         */
-        public void propertyAdded(Role role, Object key, Object value) {
-            Iterator iterator = createListenerIterator();
-            while (iterator.hasNext()) {
-                ((RoleChangeListener) iterator.next()).propertyAdded(role, key, value);
-            }
-        }
-        
-        /**
-         * {@inheritDoc}
-         */
-        public void propertyChanged(Role role, Object key, Object oldValue, Object newValue) {
-            Iterator iterator = createListenerIterator();
-            while (iterator.hasNext()) {
-                ((RoleChangeListener) iterator.next()).propertyChanged(role, key, oldValue, newValue);
-            }
-        }
-        
-        /**
-         * {@inheritDoc}
-         */
-        public void propertyRemoved(Role role, Object key) {
-            Iterator iterator = createListenerIterator();
-            while (iterator.hasNext()) {
-                ((RoleChangeListener) iterator.next()).propertyRemoved(role, key);
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void roleAdded(Role role) {
-            Iterator iterator = createListenerIterator();
-            while (iterator.hasNext()) {
-                ((RoleChangeListener) iterator.next()).roleAdded(role);
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void roleRemoved(Role role) {
-            Iterator iterator = createListenerIterator();
-            while (iterator.hasNext()) {
-                ((RoleChangeListener) iterator.next()).roleRemoved(role);
-            }
-        }
-    }
-
-    /** The single predefined role. */
-    private static final Role USER_ANYONE = RoleFactory.createRole(Role.USER_ANYONE);
-
-    private final RoleRepositoryStore m_store;
-    private final CopyOnWriteArrayList m_listeners;
-    private final RoleChangeReflector m_roleChangeReflector;
-    
-    /**
-     * Creates a new {@link RoleRepository} instance.
-     * 
-     * @param store the {@link RoleRepositoryStore} to use, cannot be <code>null</code>.
-     */
-    public RoleRepository(RoleRepositoryStore store) {
-        m_store = store;
-        
-        m_listeners = new CopyOnWriteArrayList();
-        m_roleChangeReflector = new RoleChangeReflector();
-    }
-
-    /**
-     * Adds a given role to this manager.
-     * 
-     * @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(String name, int type) {
-        if ((name == null) || "".equals(name.trim())) {
-            throw new IllegalArgumentException("Name cannot be null or empty!");
-        }
-        if (type != Role.GROUP && type != Role.USER) {
-            throw new IllegalArgumentException("Invalid role type!");
-        }
-
-        checkPermissions();
-
-        try {
-            Role result = m_store.addRole(name, type);
-            if (result != null) {
-                result = wireChangeListener(result);
-                m_roleChangeReflector.roleAdded(result);
-            }
-
-            return result;
-        }
-        catch (Exception e) {
-            throw new BackendException("Adding role " + name + " failed!", e);
-        }
-    }
-
-    /**
-     * Adds the given role change listener to be called for upcoming changes in roles.
-     * 
-     * @param listener the listener to register, cannot be <code>null</code>.
-     * @throws IllegalArgumentException in case the given listener was <code>null</code>.
-     */
-    public void addRoleChangeListener(RoleChangeListener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("RoleChangeListener cannot be null!");
-        }
-
-        m_listeners.addIfAbsent(listener);
-    }
-
-    /**
-     * Returns the by its given name.
-     * 
-     * @param roleName the name of the role to return, cannot be <code>null</code>.
-     * @return the role matching the given name, or <code>null</code> if no role matched the given name.
-     */
-    public Role getRoleByName(String roleName) {
-        try {
-            Role result;
-            if (isPredefinedRole(roleName)) {
-                result = getPredefinedRole(roleName);
-            } else {
-                result = m_store.getRoleByName(roleName);
-            }
-            return wireChangeListener(result);
-        }
-        catch (Exception e) {
-            throw new BackendException("Failed to get role by name: " + roleName + "!", e);
-        }
-    }
-
-    /**
-     * Returns a collection with all roles matching a given filter.
-     * 
-     * @param filter the filter to match the individual roles against, can be <code>null</code> if all roles should be returned.
-     * @return a list with all matching roles, can be empty, but never <code>null</code>.
-     */
-    public List getRoles(String filter) {
-        List matchingRoles = new ArrayList();
-
-        try {
-            Role[] roles = m_store.getRoles(sanitizeFilter(filter));
-            for (int i = 0; i < roles.length; i++) {
-                Role role = roles[i];
-                if (!isPredefinedRole(role.getName())) {
-                    matchingRoles.add(wireChangeListener(role));
-                }
-            }
-        }
-        catch (Exception e) {
-            throw new BackendException("Failed to get roles!", e);
-        }
-
-        return matchingRoles;
-    }
-
-    /**
-     * Returns a collection with all roles matching a given key-value pair.
-     * 
-     * @param key the key to search for;
-     * @param value the value to search for.
-     * @return a list with all matching roles, can be empty, but never <code>null</code>.
-     */
-    public List getRoles(String key, String value) {
-        if (key == null) {
-            throw new IllegalArgumentException("Key cannot be null!");
-        }
-        if (value == null) {
-            throw new IllegalArgumentException("Value cannot be null!");
-        }
-
-        List matchingRoles = new ArrayList();
-
-        try {
-            String criteria = "(".concat(key).concat("=").concat(value).concat(")");
-
-            Role[] roles = m_store.getRoles(criteria);
-            for (int i = 0; i < roles.length; i++) {
-                Role role = roles[i];
-                if (!isPredefinedRole(role.getName())) {
-                    matchingRoles.add(wireChangeListener(role));
-                }
-            }
-        }
-        catch (Exception e) {
-            throw new BackendException("Failed to get roles!", e);
-        }
-
-        return matchingRoles;
-    }
-
-    /**
-     * Removes a given role from this manager.
-     * 
-     * @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(String name) {
-        if (name == null) {
-            throw new IllegalArgumentException("Name cannot be null!");
-        }
-
-        checkPermissions();
-
-        // Cannot remove predefined roles...
-        if (isPredefinedRole(name)) {
-            return false;
-        }
-
-        try {
-            Role result = m_store.removeRole(name);
-            if (result !=  null) {
-            	// FELIX-3755: Remove the role as (required)member from all groups...
-            	removeRoleFromAllGroups(result);
-            	
-                unwireChangeListener(result);
-                m_roleChangeReflector.roleRemoved(result);
-                
-                return true;
-            }
-
-            return false;
-        }
-        catch (Exception e) {
-            throw new BackendException("Failed to remove role " + name + "!", e);
-        }
-    }
-
-    /**
-     * Removes the given role change listener from be called for changes in roles.
-     * 
-     * @param listener the listener to unregister, cannot be <code>null</code>.
-     * @throws IllegalArgumentException in case the given listener was <code>null</code>.
-     */
-    public void removeRoleChangeListener(RoleChangeListener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("RoleChangeListener cannot be null!");
-        }
-
-        m_listeners.remove(listener);
-    }
-    
-    /**
-     * Creates a new iterator for iterating over all listeners.
-     * 
-     * @return a new {@link Iterator} instance, never <code>null</code>. 
-     */
-    final Iterator createListenerIterator() {
-        return m_listeners.iterator();
-    }
-
-    /**
-     * Verifies whether the caller has the right permissions to add or remove roles.
-     * 
-     * @throws SecurityException in case the caller has not the right permissions to perform the action.
-     */
-    private void checkPermissions() throws SecurityException {
-        SecurityManager securityManager = System.getSecurityManager();
-        if (securityManager != null) {
-            securityManager.checkPermission(new UserAdminPermission(UserAdminPermission.ADMIN, null));
-        }
-    }
-
-    /**
-     * Returns whether or not the given role is a predefined role.
-     * <p>
-     * Currently, there's only a single predefined role: {@link Role#USER_ANYONE}.
-     * </p>
-     * 
-     * @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(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;
-    }
-    
-    /**
-     * Removes a given role as (required)member from any groups it is member of.
-     * 
-	 * @param removedRole the role that is removed from the store already, cannot be <code>null</code>.
-	 * @throws BackendException in case of problems accessing the store.
-	 */
-	private void removeRoleFromAllGroups(Role removedRole) {
-        try {
-            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];
-                	// Don't check whether the given role is actually a member 
-                	// of the group, but let the group itself figure this out...
-                	group.removeMember(removedRole);
-                }
-            }
-        }
-        catch (Exception e) {
-            throw new BackendException("Failed to get all roles!", e);
-        }
-	}
-	
-	/**
-	 * Sanitizes the given filter string.
-	 * 
-	 * @param filter the filter string to sanitize, can be <code>null</code>.
-	 * @return the sanitized filter, or <code>null</code> if the given filter was <code>null</code> or empty.
-	 */
-	private String sanitizeFilter(String filter) {
-	    if (filter == null || "".equals(filter.trim())) {
-	        return null;
-	    }
-	    return filter.trim();
-	}
-
-    /**
-     * 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>.
-     */
-    private void unwireChangeListener(Object role) {
-        if (role instanceof ObservableRole) {
-            ((ObservableRole) role).setRoleChangeListener(null);
-        }
-    }
-
-    /**
-     * Wires the given role to this repository so it can listen for its changes.
-     * 
-     * @param role the role to listen for its changes, cannot be <code>null</code>.
-     * @return the given role.
-     */
-    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
deleted file mode 100644
index 4f105eef10..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/UserAdminImpl.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/**
- *  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.util.List;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.useradmin.Authorization;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdmin;
-import org.osgi.service.useradmin.UserAdminEvent;
-
-/**
- * Provides the implementation for {@link UserAdmin}.
- */
-public class UserAdminImpl implements ServiceFactory, UserAdmin, RoleChangeListener {
-    
-    private final RoleRepository m_roleRepository;
-    private final EventDispatcher m_eventDispatcher;
-
-    private volatile ServiceReference m_serviceRef;
-    
-    /**
-     * Creates a new {@link UserAdminImpl} implementation.
-     * 
-     * @param roleRepository the repository with roles to use for this service;
-     * @param eventDispatcher the event dispatcher to use for this service.
-     * 
-     * @throws IllegalArgumentException in case one of the given parameters was <code>null</code>.
-     */
-    public UserAdminImpl(RoleRepository roleRepository, EventDispatcher eventDispatcher) {
-        if (roleRepository == null) {
-            throw new IllegalArgumentException("RoleRepository cannot be null!");
-        }
-        if (eventDispatcher == null) {
-            throw new IllegalArgumentException("EventDispatcher cannot be null!");
-        }
-
-        m_roleRepository = roleRepository;
-        m_eventDispatcher = eventDispatcher;
-
-        m_roleRepository.addRoleChangeListener(this);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Role createRole(String name, int type) {
-        return m_roleRepository.addRole(name, type);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Authorization getAuthorization(User user) {
-        return new AuthorizationImpl(user, m_roleRepository);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Role getRole(String name) {
-        return m_roleRepository.getRoleByName(name);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Role[] getRoles(String filter) throws InvalidSyntaxException {
-        // Do a sanity check on the given filter...
-        if (filter != null && !"".equals(filter.trim())) {
-            FrameworkUtil.createFilter(filter);
-        }
-
-        List roles = m_roleRepository.getRoles(filter);
-        if (roles.isEmpty()) {
-            return null;
-        }
-        return (Role[]) roles.toArray(new Role[roles.size()]);
-    }
-    
-    /**
-     * {@inheritDoc}
-     * 
-     * <p>Overridden in order to get hold of our service reference.</p>
-     */
-    public Object getService(Bundle bundle, ServiceRegistration registration) {
-        m_serviceRef = registration.getReference();
-        return this;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public User getUser(String key, String value) {
-        User result = null;
-        List roles = m_roleRepository.getRoles(key, value);
-        if (roles.size() == 1) {
-            Role foundRole = (Role) roles.get(0);
-            if (foundRole.getType() == Role.USER) {
-                result = (User) foundRole;
-            }
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void propertyAdded(Role role, Object key, Object value) {
-        m_eventDispatcher.dispatch(createUserAdminEvent(UserAdminEvent.ROLE_CHANGED, role));
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public void propertyChanged(Role role, Object key, Object oldValue, Object newValue) {
-        m_eventDispatcher.dispatch(createUserAdminEvent(UserAdminEvent.ROLE_CHANGED, role));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void propertyRemoved(Role role, Object key) {
-        m_eventDispatcher.dispatch(createUserAdminEvent(UserAdminEvent.ROLE_CHANGED, role));
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public boolean removeRole(String name) {
-        return m_roleRepository.removeRole(name);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void roleAdded(Role role) {
-        m_eventDispatcher.dispatch(createUserAdminEvent(UserAdminEvent.ROLE_CREATED, role));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void roleRemoved(Role role) {
-        m_eventDispatcher.dispatch(createUserAdminEvent(UserAdminEvent.ROLE_REMOVED, role));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
-        // Nop; we leave the service as-is...
-    }
-
-    /**
-     * Creates a new {@link UserAdminEvent} instance for the given type and role.
-     * 
-     * @param type the type of event to create;
-     * @param role the role to create the event for.
-     * @return a new {@link UserAdminEvent} instance, never <code>null</code>.
-     */
-    private UserAdminEvent createUserAdminEvent(int type, Role role) {
-        return new UserAdminEvent(m_serviceRef, type, role);
-    }
-}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/UserAdminListenerList.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/UserAdminListenerList.java
deleted file mode 100644
index 9afa6a0235..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/UserAdminListenerList.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- *  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 org.osgi.service.useradmin.UserAdminListener;
-
-/**
- * Provides an abstraction for a list of {@link UserAdminListener}s.
- */
-public interface UserAdminListenerList {
-
-    /**
-     * Returns all current listeners.
-     * 
-     * @return an array of {@link UserAdminListener}s, never <code>null</code>,
-     *         but can be an empty array.
-     */
-    UserAdminListener[] getListeners();
-}
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
deleted file mode 100644
index a1a611757f..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/GroupImpl.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/**
- *  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.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.UserAdminPermission;
-
-/**
- * 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 = 5543895177109398569L;
-
-    private final Object m_lock = new Object();
-
-    private final Map m_members;
-    private final Map m_requiredMembers;
-
-    /**
-     * Creates a new {@link GroupImpl} instance of type {@link Role#GROUP}.
-     * 
-     * @param name the name of this group role, cannot be <code>null</code> or empty.
-     */
-    public GroupImpl(String name) {
-        super(Role.GROUP, name);
-        
-        m_members = new HashMap();
-        m_requiredMembers = new HashMap();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean addMember(Role role) {
-        checkPermissions();
-        
-        String name = role.getName();
-
-        Object result;
-        synchronized (m_lock) {
-			if (m_members.containsKey(name) || m_requiredMembers.containsKey(name)) {
-                return false;
-            }
-            result = m_members.put(name, role);
-        }
-
-        return (result == null);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean addRequiredMember(Role role) {
-        checkPermissions();
-
-        String name = role.getName();
-
-        Object result;
-        synchronized (m_lock) {
-			if (m_requiredMembers.containsKey(name) || m_members.containsKey(name)) {
-                return false;
-            }
-            result = m_requiredMembers.put(name, role);
-        }
-
-        return (result == null);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Role[] getMembers() {
-        Role[] roles;
-        synchronized (m_lock) {
-            Collection values = m_members.values();
-            roles = (Role[]) values.toArray(new Role[values.size()]);
-        }
-
-        return (roles.length == 0) ? null : roles;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Role[] getRequiredMembers() {
-        Role[] roles;
-        synchronized (m_lock) {
-            Collection values = m_requiredMembers.values();
-            roles = (Role[]) values.toArray(new Role[values.size()]);
-        }
-
-        return (roles.length == 0) ? null : roles;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean removeMember(Role role) {
-        checkPermissions();
-
-        String name = role.getName();
-
-        Object result = null;
-
-        synchronized (m_lock) {
-			if (m_requiredMembers.containsKey(name)) {
-                result = m_requiredMembers.remove(name);
-            }
-            else if (m_members.containsKey(name)) {
-                result = m_members.remove(name);
-            }
-        }
-
-        return result != null;
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public String toString() {
-        return "Group(" + getName() + "): R{" + m_requiredMembers + "}, B{" + m_members + "}";
-    }
-
-    /**
-     * Verifies whether the caller has the right permissions to get or change the given key.
-     * 
-     * @throws SecurityException in case the caller has not the right permissions to perform the action.
-     */
-    private void checkPermissions() throws SecurityException {
-        SecurityManager securityManager = System.getSecurityManager();
-        if (securityManager != null) {
-            securityManager.checkPermission(new UserAdminPermission(UserAdminPermission.ADMIN, 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
deleted file mode 100644
index 7d167c5905..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableDictionary.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/**
- *  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 java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.osgi.service.useradmin.UserAdminPermission;
-
-/**
- * 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 = 3161552287666253189L;
-
-    /**
-     * Provides a listener for changes to a {@link ObservableDictionary}.
-     */
-    static interface DictionaryChangeListener {
-
-        /**
-         * Called when a new entry is added.
-         * 
-         * @param key the key of the entry;
-         * @param value the value associated to the key.
-         */
-        void entryAdded(Object key, Object value);
-        
-        /**
-         * Called when an entry is changed.
-         * 
-         * @param key the key of the entry;
-         * @param oldValue the old value associated to the key;
-         * @param newValue the new value associated to the key.
-         */
-        void entryChanged(Object key, Object oldValue, Object newValue);
-        
-        /**
-         * Called when an entry is removed.
-         * 
-         * @param key the key of the entry.
-         */
-        void entryRemoved(Object key);
-    }
-
-    private final Dictionary m_dictionary;
-    private final String m_getAction;
-    private final String m_changeAction;
-
-    private transient volatile DictionaryChangeListener m_listener;
-
-    /**
-     * Creates a new, empty, {@link ObservableDictionary} instance.
-     */
-    public ObservableDictionary(String getAction, String changeAction) {
-        this(getAction, changeAction, new Hashtable());
-    }
-
-    /**
-     * Creates a new {@link ObservableDictionary} instance with the given dictionary as defaults.
-     * 
-     * @param dictionary the defaults to set for this properties, cannot be <code>null</code>.
-     */
-    public ObservableDictionary(String getAction, String changeAction, Dictionary dictionary) {
-        if (dictionary == null) {
-            throw new IllegalArgumentException("Dictionary cannot be null!");
-        }
-        m_getAction = getAction;
-        m_changeAction = changeAction;
-        m_dictionary = dictionary;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Enumeration elements() {
-        return m_dictionary.elements();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean equals(Object object) {
-        if (this == object) {
-            return true;
-        }
-        if (object == null || (getClass() != object.getClass())) {
-            return false;
-        }
-
-        ObservableDictionary other = (ObservableDictionary) object;
-        if (m_dictionary == null) {
-            if (other.m_dictionary != null) {
-                return false;
-            }
-        } else if (!m_dictionary.equals(other.m_dictionary)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object get(Object key) {
-        if (key == null) {
-            throw new IllegalArgumentException("Key cannot be null!");
-        }
-
-        if (m_getAction != null) {
-            checkPermissions(getAsPermissionKey(key), m_getAction);
-        }
-
-        return m_dictionary.get(key);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int hashCode() {
-        final int prime = 37;
-        int result = 1;
-        result = prime * result + ((m_dictionary == null) ? 0 : m_dictionary.hashCode());
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isEmpty() {
-        return m_dictionary.isEmpty();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Enumeration keys() {
-        return m_dictionary.keys();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object put(Object key, Object value) {
-        if (key == null) {
-            throw new IllegalArgumentException("Key cannot be null!");
-        }
-        if (value == null) {
-            throw new IllegalArgumentException("Value cannot be null!");
-        }
-
-        if (m_changeAction != null) {
-            checkPermissions(getAsPermissionKey(key), m_changeAction);
-        }
-
-        Object oldValue = m_dictionary.put(key, value);
-        
-        final DictionaryChangeListener listener = m_listener;
-        if (listener != null) {
-            if (oldValue == null) {
-                listener.entryAdded(key, value);
-            } else {
-                listener.entryChanged(key, oldValue, value);
-            }
-        }
-
-        return oldValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object remove(Object key) {
-        if (key == null) {
-            throw new IllegalArgumentException("Key cannot be null!");
-        }
-
-        if (m_changeAction != null) {
-            checkPermissions(getAsPermissionKey(key), m_changeAction);
-        }
-
-        Object oldValue = m_dictionary.remove(key);
-        final DictionaryChangeListener listener = m_listener;
-        if (listener != null) {
-            listener.entryRemoved(key);
-        }
-        
-        return oldValue;
-    }
-
-    /**
-     * Sets a new {@link DictionaryChangeListener} to observe changes to this dictionary.
-     * 
-     * @param listener the listener to add, can be <code>null</code> to stop listening for changes.
-     */
-    public void setDictionaryChangeListener(DictionaryChangeListener listener) {
-        m_listener = listener;
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public int size() {
-        return m_dictionary.size();
-    }
-
-    /**
-     * @param key
-     * @return
-     */
-    protected String getAsPermissionKey(Object key) {
-        String k = UserAdminPermission.ADMIN;
-        if (key instanceof String) {
-            k = (String) key;
-        }
-        return k;
-    }
-
-    /**
-     * Verifies whether the caller has the right permissions to get or change the given key.
-     * 
-     * @param key the name of the property that is to be accessed or changed, cannot be <code>null</code>;
-     * @param action the action name to perform, cannot be <code>null</code>.
-     * @throws SecurityException in case the caller has not the right permissions to perform the action.
-     */
-    private void checkPermissions(String key, String action) throws SecurityException {
-        SecurityManager securityManager = System.getSecurityManager();
-        if (securityManager != null) {
-            securityManager.checkPermission(new UserAdminPermission(key, action));
-        }
-    }
-}
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
deleted file mode 100644
index 0042ade965..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableGroup.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * 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
deleted file mode 100644
index f0d25f9843..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableProperties.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- *  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 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 {
-
-    private static final long serialVersionUID = -2513082903921734796L;
-
-    /**
-     * Creates a new, empty, {@link ObservableProperties} instance.
-     */
-    public ObservableProperties(String getAction, String changeAction) {
-        this(getAction, changeAction, new Properties());
-    }
-
-    /**
-     * Creates a new {@link ObservableProperties} instance with the given dictionary as defaults.
-     * 
-     * @param dictionary the defaults to set for this properties, cannot be <code>null</code>.
-     */
-    public ObservableProperties(String getAction, String changeAction, Dictionary dictionary) {
-        super(getAction, changeAction, dictionary);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object get(Object key) {
-        if (!(key instanceof String)) {
-            throw new IllegalArgumentException("Key must be of type String!");
-        }
-
-        return super.get(key);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Object put(Object key, Object value) {
-        if (!(key instanceof String)) {
-            throw new IllegalArgumentException("Key must be of type String!");
-        }
-        if (!(value instanceof String) && !(value instanceof byte[])) {
-            throw new IllegalArgumentException("Value must be of type String or byte[]!");
-        }
-
-        return super.put(key, value);
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public Object remove(Object key) {
-        if (!(key instanceof String)) {
-            throw new IllegalArgumentException("Key must be of type String!");
-        }
-
-        return super.remove(key);
-    }
-}
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
deleted file mode 100644
index ee3ef45387..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableRole.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/**
- * 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
deleted file mode 100644
index 64c0aec60f..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/ObservableUser.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * 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
deleted file mode 100644
index 6d78d8eb50..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/RoleImpl.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
- *  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 java.util.Properties;
-
-import org.osgi.service.useradmin.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 {
-
-	private static final long serialVersionUID = 6403795608776837916L;
-	
-    private final Properties m_properties;
-    private final String m_name;
-    private final int m_type;
-
-    /**
-     * Creates a new {@link RoleImpl} instance of type {@link Role#ROLE} and a given name.
-     * 
-     * @param name the name of this role, cannot be <code>null</code> or empty.
-     */
-    public RoleImpl(String name) {
-        this(Role.ROLE, name);
-    }
-
-    /**
-     * Creates a new {@link RoleImpl} instance with a given type and name.
-     * 
-     * @param type the type of this role, should be {@link Role#ROLE}, {@link Role#USER} or {@link Role#GROUP};
-     * @param name the name of this role, cannot be <code>null</code> or empty.
-     */
-    protected RoleImpl(int type, String name) {
-        if (name == null || "".equals(name.trim())) {
-            throw new IllegalArgumentException("Name cannot be null or empty!");
-        }
-        m_type = type;
-        m_name = name;
-        m_properties = new Properties();
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-
-        if ((obj == null) || (getClass() != obj.getClass())) {
-            return false;
-        }
-
-        RoleImpl other = (RoleImpl) obj;
-        if (m_name == null) {
-            if (other.m_name != null) {
-                return false;
-            }
-        } else if (!m_name.equals(other.m_name)) {
-            return false;
-        }
-
-        if (m_type != other.m_type) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getName() {
-        return m_name;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Dictionary getProperties() {
-        return m_properties;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int getType() {
-        return m_type;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((m_name == null) ? 0 : m_name.hashCode());
-        result = prime * result + m_type;
-        return result;
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public String toString() {
-        return "Role(" + getName() + ")";
-    }
-}
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
deleted file mode 100644
index e19874c128..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/impl/role/UserImpl.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- *  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.Arrays;
-import java.util.Dictionary;
-import java.util.Properties;
-
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.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 = 7332249440557443008L;
-	
-    private final Properties m_credentials;
-
-    /**
-     * Creates a new {@link UserImpl} instance with type {@link Role#USER}.
-     * 
-     * @param name the name of this user role, cannot be <code>null</code> or empty.
-     */
-    public UserImpl(String name) {
-        this(Role.USER, name);
-    }
-
-    /**
-     * Creates a new {@link UserImpl} instance with a given type.
-     *
-     * @param type the type of this role;
-     * @param name the name of this role, cannot be <code>null</code> or empty.
-     */
-    protected UserImpl(int type, String name) {
-        super(type, name);
-
-        m_credentials = new Properties();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Dictionary getCredentials() {
-        return m_credentials;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean hasCredential(String key, Object value) {
-        Object result = m_credentials.get(key);
-
-        // Be a bit more lenient with the various results we can get...
-        if (result instanceof String) {
-            String s1 = (String) result;
-            String s2;
-            if (value instanceof byte[]) {
-                s2 = new String((byte[]) value);
-            } else if (value instanceof String) {
-                s2 = (String) value;
-            } else {
-                // Not a string, nor a byte-array!
-                return false;
-            }
-            
-            return s1.equals(s2);
-        } else if (result instanceof byte[]) {
-            byte[] b1 = (byte[]) result;
-            byte[] b2;
-            if (value instanceof byte[]) {
-                b2 = (byte[]) value;
-            } else if (value instanceof String) {
-                b2 = ((String) value).getBytes();
-            } else {
-                // Not a string, nor a byte-array!
-                return false;
-            }
-
-            return Arrays.equals(b1, b2);
-        }
-
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String toString() {
-        return "User(" + getName() + ")";
-    }
-}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/Activator.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/Activator.java
deleted file mode 100644
index 1b99b89298..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/Activator.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- *  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.osgi;
-
-import org.apache.felix.useradmin.impl.EventDispatcher;
-import org.apache.felix.useradmin.impl.RoleRepository;
-import org.apache.felix.useradmin.impl.UserAdminImpl;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.useradmin.UserAdmin;
-
-/**
- * Provides the bundle activator for the UserAdmin service.
- */
-public class Activator implements BundleActivator {
-
-    private volatile ServiceContext m_context;
-
-    /**
-     * {@inheritDoc}
-     */
-    public void start(BundleContext context) throws Exception {
-        m_context = createServiceContext(context);
-        
-        // The actual service itself...
-        UserAdminImpl service = new UserAdminImpl(m_context.m_roleRepository, m_context.m_eventDispatcher);
-        
-        // Register the actual service...
-        context.registerService(UserAdmin.class.getName(), service, null);
-        
-        // Start/open all helper classes...
-        m_context.start();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void stop(BundleContext context) throws Exception {
-        if (m_context != null) {
-            // Stop/close all helper classes...
-            m_context.stop();
-        }
-    }
-    
-    /**
-     * Creates a new service context in which all helper classes are kept.
-     * 
-     * @param context the bundle context to use, cannot be <code>null</code>.
-     * @return a new, initialized, ServiceContext instance, never <code>null</code>.
-     */
-    private ServiceContext createServiceContext(BundleContext context) {
-        // Create all services...
-        EventAdminHelper eventAdmin = new EventAdminHelper(context);
-        UserAdminListenerListHelper listenerList = new UserAdminListenerListHelper(context);
-        EventDispatcher eventDispatcher = new EventDispatcher(eventAdmin, listenerList);
-        RoleRepositoryStoreHelper store = new RoleRepositoryStoreHelper(context);
-
-        RoleRepository roleRepository = new RoleRepository(store);
-
-        return new ServiceContext(eventAdmin, listenerList, eventDispatcher, roleRepository, store);
-    }
-}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/EventAdminHelper.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/EventAdminHelper.java
deleted file mode 100644
index fc73e3ff5a..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/EventAdminHelper.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- *  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.osgi;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * Wraps a {@link ServiceTracker} as an {@link EventAdmin} allowing it to be 
- * used as a "normal" service without having to worry about the actual presence 
- * of the {@link EventAdmin} service itself. 
- */
-final class EventAdminHelper extends ServiceTracker implements EventAdmin {
-
-    /**
-     * Creates a new {@link EventAdminHelper} instance.
-     * 
-     * @param context the bundle context to use, cannot be <code>null</code>.
-     */
-    public EventAdminHelper(BundleContext context) {
-        super(context, EventAdmin.class.getName(), null /* customizer */);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void postEvent(Event event) {
-        EventAdmin eventAdmin = getEventAdmin();
-        if (eventAdmin != null) {
-            eventAdmin.postEvent(event);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void sendEvent(Event event) {
-        EventAdmin eventAdmin = getEventAdmin();
-        if (eventAdmin != null) {
-            eventAdmin.sendEvent(event);
-        }
-    }
-
-    /**
-     * Returns the event admin service, if available.
-     * 
-     * @return the current event admin service, or <code>null</code> if it is not present.
-     */
-    private EventAdmin getEventAdmin() {
-        return (EventAdmin) getService();
-    }
-}
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
deleted file mode 100644
index e7af265517..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/RoleRepositoryStoreHelper.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- *  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.osgi;
-
-import org.apache.felix.useradmin.RoleRepositoryStore;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.useradmin.Role;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * Provides an OSGi service tracker for {@link RoleRepositoryStore}.
- * <p>
- * This helper allows us to use {@link RoleRepositoryStore} without having to 
- * worry about the possible absence of the actual store implementation.
- * </p>
- */
-class RoleRepositoryStoreHelper extends ServiceTracker implements RoleRepositoryStore {
-	
-    /**
-     * Creates a new {@link RoleRepositoryStoreHelper} instance.
-     * 
-     * @param context the bundle context to use, cannot be <code>null</code>.
-     */
-    public RoleRepositoryStoreHelper(BundleContext context) {
-        super(context, RoleRepositoryStore.class.getName(), null /* customizer */);
-    }
-
-    public Role addRole(String roleName, int type) throws Exception {
-        RoleRepositoryStore store = getStore();
-        if (store != null) {
-            return store.addRole(roleName, type);
-        }
-
-        return null;
-    }
-
-    public Role[] getRoles(String filter) throws Exception {
-        RoleRepositoryStore store = getStore();
-        if (store != null) {
-            return store.getRoles(filter);
-        }
-
-        return new Role[0];
-    }
-
-    public Role getRoleByName(String roleName) throws Exception {
-        RoleRepositoryStore store = getStore();
-        if (store != null) {
-            return store.getRoleByName(roleName);
-        }
-
-        return null;
-    }
-
-    public Role removeRole(String roleName) throws Exception {
-        // and possibly also from our tracked store...
-        RoleRepositoryStore store = getStore();
-        if (store != null) {
-            return store.removeRole(roleName);
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns the tracked {@link RoleRepositoryStore}.
-     * 
-     * @return the {@link RoleRepositoryStore}, can be <code>null</code>.
-     */
-    private RoleRepositoryStore getStore() {
-        return (RoleRepositoryStore) getService();
-    }
-}
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
deleted file mode 100644
index 79f7dbe4a4..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/ServiceContext.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- *  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.osgi;
-
-
-import org.apache.felix.useradmin.impl.EventDispatcher;
-import org.apache.felix.useradmin.impl.RoleRepository;
-import org.osgi.service.useradmin.UserAdmin;
-
-/**
- * Provides a convenience class for all helpers that are used for this
- * implementation of the {@link UserAdmin} service.
- */
-final class ServiceContext {
-
-    final EventAdminHelper m_eventAdmin;
-    final UserAdminListenerListHelper m_listenerList;
-    final EventDispatcher m_eventDispatcher;
-    final RoleRepository m_roleRepository;
-    final RoleRepositoryStoreHelper m_store;
-
-    /**
-     * Creates a new ServiceContext instance.
-     */
-    public ServiceContext(EventAdminHelper eventAdmin, UserAdminListenerListHelper listenerList, EventDispatcher eventDispatcher, RoleRepository roleRepository, RoleRepositoryStoreHelper store) {
-        m_eventAdmin = eventAdmin;
-        m_listenerList = listenerList;
-        m_eventDispatcher = eventDispatcher;
-        m_roleRepository = roleRepository;
-        m_store = store;
-    }
-
-    /**
-     * Starts/opens all helpers.
-     */
-    public void start() {
-        m_eventAdmin.open();
-        m_listenerList.open(true /* trackAllServices */);
-        m_eventDispatcher.start();
-        m_store.open();
-    }
-    
-    /**
-     * Stops/closes all helpers.
-     */
-    public void stop() {
-        m_eventDispatcher.stop();
-        m_listenerList.close();
-        m_eventAdmin.close();
-        m_store.close();
-    }
-}
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/UserAdminListenerListHelper.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/UserAdminListenerListHelper.java
deleted file mode 100644
index 1b19f744e6..0000000000
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/UserAdminListenerListHelper.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- *  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.osgi;
-
-
-import org.apache.felix.useradmin.impl.UserAdminListenerList;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.useradmin.UserAdminListener;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * Wraps a {@link ServiceTracker} as an {@link UserAdminListenerList} to allow 
- * it to be used as a "normal" service without having to worry about the 
- * existence of any {@link UserAdminListener}s.
- */
-final class UserAdminListenerListHelper extends ServiceTracker implements UserAdminListenerList {
-
-    /**
-     * Creates a new {@link UserAdminListenerListHelper} instance.
-     * 
-     * @param context the bundle context to use, cannot be <code>null</code>.
-     */
-    public UserAdminListenerListHelper(BundleContext context) {
-        super(context, UserAdminListener.class.getName(), null /* customizer */);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public UserAdminListener[] getListeners() {
-        Object[] services = getServices();
-        if (services == null) {
-            return new UserAdminListener[0];
-        }
-
-        UserAdminListener[] result = new UserAdminListener[services.length];
-        for (int i = 0; i < services.length; i++) {
-            result[i] = (UserAdminListener) services[i];
-        }
-
-        return result;
-    }
-}
diff --git a/useradmin/useradmin/src/main/resources/DEPENDENCIES b/useradmin/useradmin/src/main/resources/DEPENDENCIES
deleted file mode 100644
index 02ab173730..0000000000
--- a/useradmin/useradmin/src/main/resources/DEPENDENCIES
+++ /dev/null
@@ -1,21 +0,0 @@
-Apache Felix UserAdmin
-Copyright 2012 The Apache Software Foundation
-
-This software was developed at the Apache Software Foundation
-(http://www.apache.org) and may have dependencies on other
-Apache software licensed under Apache License 2.0.
-
-I. Included Third-Party Software
-
-n/a
-
-II. Used Third-Party Software
-
-This product includes software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2009).
-Licensed under the Apache License 2.0.
-
-III. Overall License Summary
-- Apache License 2.0
-
diff --git a/useradmin/useradmin/src/main/resources/LICENSE b/useradmin/useradmin/src/main/resources/LICENSE
deleted file mode 100644
index d645695673..0000000000
--- a/useradmin/useradmin/src/main/resources/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/useradmin/useradmin/src/main/resources/NOTICE b/useradmin/useradmin/src/main/resources/NOTICE
deleted file mode 100644
index 2a7a9f598c..0000000000
--- a/useradmin/useradmin/src/main/resources/NOTICE
+++ /dev/null
@@ -1,7 +0,0 @@
-Apache Felix User Admin Service
-Copyright 2012 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
diff --git a/useradmin/useradmin/src/main/resources/README b/useradmin/useradmin/src/main/resources/README
deleted file mode 100644
index 2163a34429..0000000000
--- a/useradmin/useradmin/src/main/resources/README
+++ /dev/null
@@ -1,25 +0,0 @@
-Apache Felix User Admin Service
-Copyright 2012 The Apache Software Foundation
-
-This project provides the main implementation of the OSGi UserAdmin compendium
-service, version 1.1 as specified in the OSGi Compendium v4. 
-
-The resulting bundle needs a repository store in order to function properly. 
-There are two implementations for such stores available: a file-based one, and
-a MongoDB-based on. This service currently expects only a single repository 
-store to be available.
-
-It is possible to create your own repository store for this user admin 
-service. To do this, you need to implement "org.apache.felix.useradmin.
-RoleRepositoryStore" and register your implementation under this service name.
-
-Repository stores can implement their own variants of "Role", "User" and 
-"Group" and return it to the user admin service. Alternatively, stores can 
-also use the "org.apache.felix.useradmin.RoleFactory" to use the default 
-implementations instead.
-
-The user admin service this bundle provides does not need additional 
-configuration to function properly.
-
-When present, this bundle will emit events to the EventAdmin service about all
-changes made to the repository of this service.
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
deleted file mode 100644
index 766fab58b4..0000000000
--- a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/AuthorizationImplTest.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/**
- *  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.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-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 AuthorizationImpl}.
- */
-public class AuthorizationImplTest extends TestCase {
-
-    private RoleRepository m_roleRepository;
-    private Role m_anyone;
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void setUp() throws Exception {
-        super.setUp();
-        
-        m_roleRepository = new RoleRepository(new MemoryRoleRepositoryStore());
-        
-        m_anyone = m_roleRepository.getRoleByName(Role.USER_ANYONE);
-    }
-    
-    /**
-     * Test for example presented in section 107.3.2 of OSGi compendium v4.2.
-     */
-    public void testAuthorizationExampleOk() {
-        // Action groups...
-        Group alarmSystemControl = createGroup("AlarmSystemControl");
-        Group internetAccess = createGroup("InternetAccess");
-        Group temperatureControl = createGroup("TemperatureControl");
-        Group photoAlbumEdit = createGroup("PhotoAlbumEdit");
-        Group photoAlbumView = createGroup("PhotoAlbumView");
-        Group portForwarding = createGroup("PortForwarding");
-        
-        // System user groups...
-        Group administrators = createGroup("Administrators");
-        Group buddies = createGroup("Buddies");
-        Group children = createGroup("Children");
-        Group adults = createGroup("Adults");
-        Group residents = createGroup("Residents");
-        
-        // Users
-        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(m_anyone);
-        internetAccess.addRequiredMember(m_anyone);
-        temperatureControl.addRequiredMember(m_anyone);
-        photoAlbumEdit.addRequiredMember(m_anyone);
-        photoAlbumView.addRequiredMember(m_anyone);
-        portForwarding.addRequiredMember(m_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);
-        residents.addMember(fudd);
-        residents.addMember(marvin);
-        residents.addMember(pepe);
-        
-        buddies.addMember(daffy);
-        buddies.addMember(foghorn);
-        
-        children.addMember(marvin);
-        children.addMember(pepe);
-        
-        adults.addMember(elmer);
-        adults.addMember(fudd);
-        
-        administrators.addMember(elmer);
-        
-        // Table 107.2
-        alarmSystemControl.addMember(residents);
-        alarmSystemControl.addRequiredMember(administrators);
-        
-        internetAccess.addMember(residents);
-        internetAccess.addRequiredMember(adults);
-        
-        temperatureControl.addMember(residents);
-        temperatureControl.addRequiredMember(adults);
-        
-        photoAlbumEdit.addMember(residents);
-        photoAlbumEdit.addMember(children);
-        photoAlbumEdit.addMember(adults);
-        
-        photoAlbumView.addMember(residents);
-        photoAlbumView.addMember(buddies);
-        
-        portForwarding.addMember(residents);
-        portForwarding.addRequiredMember(administrators);
-
-        // Test with the user "foghorn"...
-        AuthorizationImpl auth = new AuthorizationImpl(foghorn, m_roleRepository);
-
-        assertFalse(auth.hasRole(alarmSystemControl.getName()));
-        assertFalse(auth.hasRole(internetAccess.getName()));
-        assertFalse(auth.hasRole(temperatureControl.getName()));
-        assertFalse(auth.hasRole(photoAlbumEdit.getName()));
-        assertTrue(auth.hasRole(photoAlbumView.getName()));
-        assertFalse(auth.hasRole(portForwarding.getName()));
-
-        // Test with the user "fudd"...
-        auth = new AuthorizationImpl(fudd, m_roleRepository);
-
-        assertFalse(auth.hasRole(alarmSystemControl.getName()));
-        assertTrue(auth.hasRole(internetAccess.getName()));
-        assertTrue(auth.hasRole(temperatureControl.getName()));
-        assertTrue(auth.hasRole(photoAlbumEdit.getName()));
-        assertTrue(auth.hasRole(photoAlbumView.getName()));
-        assertFalse(auth.hasRole(portForwarding.getName()));
-
-        // Test with the user "elmer"...
-        auth = new AuthorizationImpl(elmer, m_roleRepository);
-
-        assertTrue(auth.hasRole(alarmSystemControl.getName()));
-        assertTrue(auth.hasRole(internetAccess.getName()));
-        assertTrue(auth.hasRole(temperatureControl.getName()));
-        assertTrue(auth.hasRole(photoAlbumEdit.getName()));
-        assertTrue(auth.hasRole(photoAlbumView.getName()));
-        assertTrue(auth.hasRole(portForwarding.getName()));
-    }
-
-    /**
-     * Test that the tests for membership work correctly. 
-     */
-    public void testHasRoleOk() {
-        Group citizens = createGroup("citizen");
-        citizens.addRequiredMember(m_anyone);
-        
-        Group adults = createGroup("adult");
-        adults.addRequiredMember(m_anyone);
-        
-        Group voters = createGroup("voter");
-        voters.addRequiredMember(citizens);
-        voters.addRequiredMember(adults);
-        voters.addMember(m_anyone);
-        
-        // Elmer belongs to the citizens and adults...
-        User elmer = createUser("elmer");
-        citizens.addMember(elmer);
-        adults.addMember(elmer);
-        
-        // Pepe belongs to the citizens, but is not an adult...
-        User pepe = createUser("pepe");
-        citizens.addMember(pepe);
-        
-        // Bugs is an adult, but is not a citizen...
-        User bugs = createUser("bugs");
-        adults.addMember(bugs);
-        
-        // Daffy is not an adult, neither a citizen...
-        User daffy = createUser("daffy");
-        
-        AuthorizationImpl auth;
-
-        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_roleRepository);
-        assertFalse(auth.hasRole("adult"));
-        assertTrue(auth.hasRole("citizen"));
-        assertFalse(auth.hasRole("voter"));
-        assertFalse(auth.hasRole("non-existing-role"));
-
-        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_roleRepository);
-        assertFalse(auth.hasRole("adult"));
-        assertFalse(auth.hasRole("citizen"));
-        assertFalse(auth.hasRole("voter"));
-        assertFalse(auth.hasRole("non-existing-role"));
-    }
-
-    /**
-     * Test that the tests for membership work correctly. 
-     */
-    public void testGetRolesOk() {
-        Group citizens = createGroup("citizen");
-        citizens.addRequiredMember(m_anyone);
-        
-        Group adults = createGroup("adult");
-        adults.addRequiredMember(m_anyone);
-        
-        Group voters = createGroup("voter");
-        voters.addRequiredMember(citizens);
-        voters.addRequiredMember(adults);
-        voters.addMember(m_anyone);
-        
-        // Elmer belongs to the citizens and adults...
-        User elmer = createUser("elmer");
-        citizens.addMember(elmer);
-        adults.addMember(elmer);
-        
-        // Pepe belongs to the citizens, but is not an adult...
-        User pepe = createUser("pepe");
-        citizens.addMember(pepe);
-        
-        // Bugs is an adult, but is not a citizen...
-        User bugs = createUser("bugs");
-        adults.addMember(bugs);
-
-        // Daffy is not an adult, neither a citizen...
-        User daffy = createUser("daffy");
-
-        // Donald is not an adult, neither a citizen...
-        User donald = RoleFactory.createUser("donald");
-        
-        AuthorizationImpl auth;
-
-        auth = new AuthorizationImpl(elmer, m_roleRepository);
-        assertSameRoles(new String[]{ "elmer", "adult", "citizen", "voter" }, auth.getRoles());
-
-        auth = new AuthorizationImpl(pepe, m_roleRepository);
-        assertSameRoles(new String[]{ "pepe", "citizen" }, auth.getRoles());
-
-        auth = new AuthorizationImpl(bugs, m_roleRepository);
-        assertSameRoles(new String[]{ "bugs", "adult" }, auth.getRoles());
-
-        auth = new AuthorizationImpl(daffy, m_roleRepository);
-        assertSameRoles(new String[]{ "daffy" }, auth.getRoles());
-
-        auth = new AuthorizationImpl(donald, m_roleRepository);
-        assertNull(auth.getRoles());
-    }
-
-    private void assertSameRoles(String[] expected, String[] roles) {
-        assertTrue("Expected " + expected.length + " roles, got " + roles.length + "!", expected.length == roles.length);
-        
-        List e = new ArrayList(Arrays.asList(expected));
-        List r = new ArrayList(Arrays.asList(roles));
-        e.removeAll(r);
-        
-        assertTrue("Not seen: " + e, e.isEmpty());
-    }
-
-    private Group createGroup(String name) {
-        return (Group) m_roleRepository.addRole(name, Role.GROUP);
-    }
-
-    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
deleted file mode 100644
index 155084e356..0000000000
--- a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/CustomRoleImplTest.java
+++ /dev/null
@@ -1,484 +0,0 @@
-/**
- *  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();
-                }
-            }
-        });
-    }
-}
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
deleted file mode 100644
index 943d2819eb..0000000000
--- a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/EventDispatcherTest.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/**
- *  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.util.Properties;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-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.osgi.framework.Bundle;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.UserAdminEvent;
-import org.osgi.service.useradmin.UserAdminListener;
-
-/**
- * Test case for {@link EventDispatcher}.
- */
-public class EventDispatcherTest extends TestCase {
-    
-    /**
-     * Provides a {@link EventAdmin} that counts the number of times 
-     * {@link #postEvent(Event)} is called.
-     */
-    static class CountingEventAdmin implements EventAdmin {
-        
-        private final CountDownLatch m_latch;
-        
-        public CountingEventAdmin(CountDownLatch latch) {
-            m_latch = latch;
-        }
-        
-        public void postEvent(Event event) {
-            if (m_latch != null) {
-                m_latch.countDown();
-            }
-        }
-
-        public void sendEvent(Event event) {
-            throw new RuntimeException("Should not be called for asynchronous delivery!");
-        }
-    }
-    
-    /**
-     * Provides a {@link UserAdminListener} that counts the number of times 
-     * {@link #roleChanged(UserAdminEvent)} is called.
-     */
-    static class CountingUserAdminListener implements UserAdminListener {
-        
-        private final CountDownLatch m_latch;
-        
-        public CountingUserAdminListener(CountDownLatch latch) {
-            m_latch = latch;
-        }
-
-        public void roleChanged(UserAdminEvent event) {
-            if (m_latch != null) {
-                m_latch.countDown();
-            }
-        }
-    }
-
-    /**
-     * Implements a fake service reference.
-     */
-    static class FakeServiceReference implements ServiceReference {
-        
-        private final Properties m_props;
-
-        public FakeServiceReference() {
-            this(new String[0]);
-        }
-
-        public FakeServiceReference(String[] properties) {
-            m_props = new Properties();
-            
-            for (int i = 0; i < properties.length; i += 2) {
-                m_props.put(properties[i], properties[i + 1]);
-            }
-        }
-        
-        public int compareTo(Object reference) {
-            return 0;
-        }
-
-        public Bundle getBundle() {
-            return null;
-        }
-
-        public Object getProperty(String key) {
-            return key;
-        }
-
-        public String[] getPropertyKeys() {
-            return new String[0];
-        }
-
-        public Bundle[] getUsingBundles() {
-            return null;
-        }
-
-        public boolean isAssignableTo(Bundle bundle, String className) {
-            return false;
-        }
-    }
-
-    private EventDispatcher m_dispatcher;
-
-    /**
-     * Test method for {@link org.apache.felix.useradmin.impl.EventDispatcher#dispatch(org.osgi.service.useradmin.UserAdminEvent)}.
-     */
-    public void testDispatchEventCallsEventAdminOk() throws Exception {
-        final CountDownLatch latch = new CountDownLatch(5);
-        
-        m_dispatcher = createEventDispatcher(new CountingEventAdmin(latch));
-        m_dispatcher.start();
-
-        for (int i = 0; i < 5; i++) {
-            m_dispatcher.dispatch(createMockEvent(UserAdminEvent.ROLE_CHANGED));
-        }
-
-        assertTrue(latch.await(5, TimeUnit.SECONDS));
-    }
-
-    /**
-     * Test method for {@link org.apache.felix.useradmin.impl.EventDispatcher#dispatch(org.osgi.service.useradmin.UserAdminEvent)}.
-     */
-    public void testDispatchEventCallsUserAdminListenersOk() throws Exception {
-        final CountDownLatch latch = new CountDownLatch(5);
-        
-        m_dispatcher = createEventDispatcher(new CountingUserAdminListener(latch));
-        m_dispatcher.start();
-
-        for (int i = 0; i < 5; i++) {
-            m_dispatcher.dispatch(createMockEvent(UserAdminEvent.ROLE_CHANGED));
-        }
-
-        assertTrue(latch.await(5, TimeUnit.SECONDS));
-    }
-
-    /**
-     * Test method for {@link org.apache.felix.useradmin.impl.EventDispatcher#start()}.
-     */
-    public void testStartTwiceDoesNotMatter() throws Exception {
-        final CountDownLatch latch = new CountDownLatch(1);
-        
-        m_dispatcher = createEventDispatcher(new CountingUserAdminListener(latch));
-        m_dispatcher.start();
-        
-        assertTrue(m_dispatcher.isRunning());
-
-        m_dispatcher.start();
-            
-        assertTrue(m_dispatcher.isRunning());
-
-        assertEquals("Latch should not be decremented?!", 1L, latch.getCount());
-    }
-
-    /**
-     * Test method for {@link org.apache.felix.useradmin.impl.EventDispatcher#stop()}.
-     */
-    public void testStopOk() {
-        final CountDownLatch latch = new CountDownLatch(1);
-        
-        m_dispatcher = createEventDispatcher(new CountingUserAdminListener(latch));
-        m_dispatcher.start();
-
-        m_dispatcher.stop();
-
-        m_dispatcher.dispatch(createMockEvent(UserAdminEvent.ROLE_CHANGED));
-        
-        assertFalse(m_dispatcher.isRunning());
-
-        assertEquals("Latch should not be decremented?!", 1L, latch.getCount());
-    }
-
-    /**
-     * Test method for {@link org.apache.felix.useradmin.impl.EventDispatcher#stop()}.
-     */
-    public void testStopUnstartedDoesNotMatter() {
-        final CountDownLatch latch = new CountDownLatch(1);
-        
-        m_dispatcher = createEventDispatcher(new CountingUserAdminListener(latch));
-        
-        assertFalse(m_dispatcher.isRunning());
-
-        m_dispatcher.stop();
-        
-        assertFalse(m_dispatcher.isRunning());
-
-        assertEquals("Latch should not be decremented?!", 1L, latch.getCount());
-    }
-
-    /**
-     * Test method for {@link org.apache.felix.useradmin.impl.EventDispatcher#stop()}.
-     */
-    public void testStopTwiceDoesNotMatter() {
-        final CountDownLatch latch = new CountDownLatch(1);
-        
-        m_dispatcher = createEventDispatcher(new CountingUserAdminListener(latch));
-        m_dispatcher.start();
-        
-        assertTrue(m_dispatcher.isRunning());
-
-        m_dispatcher.stop();
-        
-        assertFalse(m_dispatcher.isRunning());
-        
-        m_dispatcher.stop();
-
-        assertEquals("Latch should not be decremented?!", 1L, latch.getCount());
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void tearDown() throws Exception {
-        if (m_dispatcher != null) {
-            try {
-                m_dispatcher.stop();
-                m_dispatcher = null;
-            } catch (IllegalStateException e) {
-                // Not a problem; already stopped...
-            }
-        }
-    }
-
-    /**
-     * @param eventAdmin
-     * @param listenerList
-     * @return
-     */
-    private EventDispatcher createEventDispatcher(EventAdmin eventAdmin) {
-        return new EventDispatcher(eventAdmin, createListenerList());        
-    }
-
-    /**
-     * @param eventAdmin
-     * @param listenerList
-     * @return
-     */
-    private EventDispatcher createEventDispatcher(UserAdminListener listener) {
-        return new EventDispatcher(new CountingEventAdmin(null), createListenerList(listener));        
-    }
-    
-    /**
-     * @param listener
-     * @return
-     */
-    private UserAdminListenerList createListenerList() {
-        return new UserAdminListenerList() {
-            public UserAdminListener[] getListeners() {
-                return new UserAdminListener[0];
-            }
-        };
-    }
-
-    /**
-     * @param listener
-     * @return
-     */
-    private UserAdminListenerList createListenerList(final UserAdminListener listener) {
-        return new UserAdminListenerList() {
-            public UserAdminListener[] getListeners() {
-                return new UserAdminListener[] { listener };
-            }
-        };
-    }
-    
-    /**
-     * @param type
-     * @return
-     */
-    private UserAdminEvent createMockEvent(int type) {
-        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
deleted file mode 100644
index cbdd6f4461..0000000000
--- a/useradmin/useradmin/src/test/java/org/apache/felix/useradmin/impl/MemoryRoleRepositoryStore.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- *  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.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.framework.FrameworkUtil;
-import org.osgi.service.useradmin.Role;
-
-
-/**
- * Provides a simple in-memory role repository store.
- */
-public class MemoryRoleRepositoryStore implements RoleRepositoryStore {
-    
-    private final ConcurrentMap m_entries = new ConcurrentHashMap();
-
-    public Role addRole(String roleName, int type) throws Exception {
-        if (roleName == null) {
-            throw new IllegalArgumentException("Name cannot be null!");
-        }
-        Role role = RoleFactory.createRole(type, roleName);
-        Object result = m_entries.putIfAbsent(roleName, role);
-        return (result == null) ? role : null;
-    }
-
-    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);
-            }
... 2944 lines suppressed ...