[FELIX-3735] Fixed issue with initialization of repository store; added integration tests to verify this behavior in the future.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1402139 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/useradmin/pom.xml b/useradmin/pom.xml
index 7ddf619..0c27652 100644
--- a/useradmin/pom.xml
+++ b/useradmin/pom.xml
@@ -32,5 +32,6 @@
<module>useradmin</module>
<module>filestore</module>
<module>mongodb</module>
+ <module>itest</module>
</modules>
</project>
diff --git a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/RoleRepositoryStoreHelper.java b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/RoleRepositoryStoreHelper.java
index d817ca7..824d520 100644
--- a/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/RoleRepositoryStoreHelper.java
+++ b/useradmin/useradmin/src/main/java/org/apache/felix/useradmin/osgi/RoleRepositoryStoreHelper.java
@@ -17,6 +17,7 @@
package org.apache.felix.useradmin.osgi;
import java.io.IOException;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.felix.useradmin.RoleRepositoryStore;
import org.osgi.framework.BundleContext;
@@ -32,6 +33,8 @@
* </p>
*/
class RoleRepositoryStoreHelper extends ServiceTracker implements RoleRepositoryStore {
+
+ private final AtomicBoolean m_initialized = new AtomicBoolean(false);
/**
* Creates a new {@link RoleRepositoryStoreHelper} instance.
@@ -42,6 +45,17 @@
super(context, RoleRepositoryStore.class.getName(), null /* customizer */);
}
+ public Object addingService(ServiceReference reference) {
+ // FELIX-3735: store can also become available *after* this bundle is started...
+ RoleRepositoryStore store = (RoleRepositoryStore) super.addingService(reference);
+ try {
+ initializeStore(store);
+ } catch (IOException e) {
+ // Ignore; nothing we can do about this here...
+ }
+ return store;
+ }
+
public boolean addRole(Role role) throws IOException {
RoleRepositoryStore store = getStore();
if (store != null) {
@@ -55,7 +69,7 @@
try {
RoleRepositoryStore store = getStore();
if (store != null) {
- store.close();
+ closeStore(store);
}
}
catch (IOException e) {
@@ -64,7 +78,7 @@
super.close();
}
}
-
+
public Role[] getAllRoles() throws IOException {
RoleRepositoryStore store = getStore();
if (store != null) {
@@ -82,23 +96,22 @@
return null;
}
-
+
public void initialize() throws IOException {
RoleRepositoryStore store = getStore();
if (store != null) {
- store.initialize();
+ initializeStore(store);
}
}
public void removedService(ServiceReference reference, Object service) {
RoleRepositoryStore removedStore = (RoleRepositoryStore) service;
try {
- removedStore.close();
+ closeStore(removedStore);
}
catch (IOException e) {
// Ignore; nothing we can do about this here...
}
-
super.removedService(reference, service);
}
@@ -120,4 +133,41 @@
private RoleRepositoryStore getStore() {
return (RoleRepositoryStore) getService();
}
+
+ /**
+ * Closes the given store.
+ *
+ * @param store the store to close, cannot be <code>null</code>.
+ * @throws IOException in case initialization failed.
+ */
+ private void closeStore(RoleRepositoryStore store) throws IOException {
+ // Only close the store if its initialized...
+ boolean initialized = m_initialized.get();
+ if (initialized) {
+ store.close();
+
+ do {
+ initialized = m_initialized.get();
+ } while (!m_initialized.compareAndSet(initialized, false));
+ }
+ }
+
+ /**
+ * Initializes the given store.
+ *
+ * @param store the store to initialize, cannot be <code>null</code>.
+ * @throws IOException in case initialization failed.
+ */
+ private void initializeStore(RoleRepositoryStore store) throws IOException {
+ // FELIX-3735: store can also become available *after* this bundle is started;
+ // hence we need to ensure we do not initialize the store twice...
+ boolean initialized = m_initialized.get();
+ if (!initialized) {
+ store.initialize();
+
+ do {
+ initialized = m_initialized.get();
+ } while (!m_initialized.compareAndSet(initialized, true));
+ }
+ }
}