You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ja...@apache.org on 2016/01/28 14:29:17 UTC
svn commit: r1727343 - in /ace/trunk:
org.apache.ace.repository.itest/src/org/apache/ace/it/repository/
org.apache.ace.repository/src/org/apache/ace/repository/impl/
org.apache.ace.test/src/org/apache/ace/it/
Author: jawi
Date: Thu Jan 28 13:29:17 2016
New Revision: 1727343
URL: http://svn.apache.org/viewvc?rev=1727343&view=rev
Log:
ACE-425 - remove the use of the PreferenceService:
- use a simple in-memory index to check whether the customer + name is unique
across all instantiated repositories;
- added a test case to verify we cannot instantiate a repository with the same
customer and name twice.
Modified:
ace/trunk/org.apache.ace.repository.itest/src/org/apache/ace/it/repository/RepositoryTest.java
ace/trunk/org.apache.ace.repository/src/org/apache/ace/repository/impl/RepositoryFactory.java
ace/trunk/org.apache.ace.test/src/org/apache/ace/it/IntegrationTestBase.java
ace/trunk/org.apache.ace.test/src/org/apache/ace/it/packageinfo
Modified: ace/trunk/org.apache.ace.repository.itest/src/org/apache/ace/it/repository/RepositoryTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.repository.itest/src/org/apache/ace/it/repository/RepositoryTest.java?rev=1727343&r1=1727342&r2=1727343&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.repository.itest/src/org/apache/ace/it/repository/RepositoryTest.java (original)
+++ ace/trunk/org.apache.ace.repository.itest/src/org/apache/ace/it/repository/RepositoryTest.java Thu Jan 28 13:29:17 2016
@@ -46,6 +46,8 @@ import org.osgi.util.tracker.ServiceTrac
* Integration test for our repositories, and the replication thereof.
*/
public class RepositoryTest extends IntegrationTestBase {
+ private static final String REPOSITORY_FACTORY_PID = "org.apache.ace.server.repository.factory";
+
private static final String REPOSITORY_NAME = "name";
private static final String REPOSITORY_CUSTOMER = "customer";
private static final String REPOSITORY_MASTER = "master";
@@ -169,6 +171,49 @@ public class RepositoryTest extends Inte
removeRepository("testInstance");
}
+ /**
+ * ACE-425
+ */
+ public void testCannotAddDuplicateRepository() throws Exception {
+ String customer = "apache";
+ String name = "testRepo";
+
+ int initialSize = countServices(Repository.class);
+
+ // Publish configuration for a repository instance
+ Dictionary<String, Object> props = new Hashtable<>();
+ props.put(REPOSITORY_CUSTOMER, customer);
+ props.put(REPOSITORY_NAME, name);
+ props.put(REPOSITORY_BASE_DIR, "");
+ props.put(REPOSITORY_FILE_EXTENSION, "");
+ props.put(REPOSITORY_MASTER, "true");
+ props.put("factory.instance.pid", "instance1");
+
+ Configuration config1 = createFactoryConfiguration(REPOSITORY_FACTORY_PID);
+ config1.update(props); // should succeed.
+
+ Thread.sleep(500);
+
+ assertEquals(initialSize + 1, countServices(Repository.class));
+
+ props.put(REPOSITORY_FILE_EXTENSION, ".gz");
+ config1.update(props); // still should succeed.
+
+ Thread.sleep(500);
+
+ // Not updated...
+ assertEquals(initialSize + 1, countServices(Repository.class));
+
+ Configuration config2 = createFactoryConfiguration(REPOSITORY_FACTORY_PID);
+ props.put("factory.instance.pid", "instance2");
+ config2.update(props); // should fail.
+
+ Thread.sleep(500);
+
+ // Not updated...
+ assertEquals(initialSize + 1, countServices(Repository.class));
+ }
+
public void testInitialContent() throws Exception {
addRepository("testInstance", "apache", "test", null, null, "somecontent", true);
@@ -235,7 +280,7 @@ public class RepositoryTest extends Inte
props.put(REPOSITORY_INITIAL_CONTENT, initial);
}
props.put("factory.instance.pid", instanceName);
- Configuration config = createFactoryConfiguration("org.apache.ace.server.repository.factory");
+ Configuration config = createFactoryConfiguration(REPOSITORY_FACTORY_PID);
config.update(props);
try {
@@ -280,14 +325,7 @@ public class RepositoryTest extends Inte
}
private void removeRepository(String instanceName) throws IOException, InterruptedException, InvalidSyntaxException {
- Configuration[] configs = null;
- try {
- configs = listConfigurations("(factory.instance.pid=" + instanceName + ")");
- }
- catch (InvalidSyntaxException e) {
- // should not happen
- }
-
+ Configuration[] configs = listConfigurations("(factory.instance.pid=" + instanceName + ")");
if ((configs != null) && (configs.length > 0)) {
final Semaphore sem = new Semaphore(0);
ServiceTracker<Object, Object> tracker = new ServiceTracker<Object, Object>(m_bundleContext, m_bundleContext.createFilter("(factory.instance.pid=" + instanceName + ")"), null) {
Modified: ace/trunk/org.apache.ace.repository/src/org/apache/ace/repository/impl/RepositoryFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.repository/src/org/apache/ace/repository/impl/RepositoryFactory.java?rev=1727343&r1=1727342&r2=1727343&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.repository/src/org/apache/ace/repository/impl/RepositoryFactory.java (original)
+++ ace/trunk/org.apache.ace.repository/src/org/apache/ace/repository/impl/RepositoryFactory.java Thu Jan 28 13:29:17 2016
@@ -30,6 +30,8 @@ import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -41,9 +43,6 @@ import org.osgi.framework.BundleContext;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedServiceFactory;
import org.osgi.service.log.LogService;
-import org.osgi.service.prefs.BackingStoreException;
-import org.osgi.service.prefs.Preferences;
-import org.osgi.service.prefs.PreferencesService;
/**
* A <code>ManagedServiceFactory</code> responsible for creating a (<code>Replication</code>)<code>Repository</code>
@@ -51,14 +50,56 @@ import org.osgi.service.prefs.Preference
*/
public class RepositoryFactory implements ManagedServiceFactory {
+ public static class Entry {
+ private final String m_customer;
+ private final String m_name;
+
+ public Entry(String customer, String name) {
+ m_customer = customer;
+ m_name = name;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ Entry other = (Entry) obj;
+ if (!m_customer.equals(other.m_customer)) {
+ return false;
+ }
+ if (!m_name.equals(other.m_name)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 37;
+ int result = 1;
+ result = prime * result + ((m_customer == null) ? 0 : m_customer.hashCode());
+ result = prime * result + ((m_name == null) ? 0 : m_name.hashCode());
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s :: %s", m_customer, m_name);
+ }
+ }
+
private final ConcurrentMap<String, Component> m_instances = new ConcurrentHashMap<String, Component>();
+ private final ConcurrentMap<Entry, String> m_index = new ConcurrentHashMap<>();
private final DependencyManager m_manager;
/* injected by dependency manager */
private volatile LogService m_log;
private volatile BundleContext m_context;
- private volatile PreferencesService m_prefsService;
-
+ // locally managed
private File m_tempDir;
public RepositoryFactory(DependencyManager manager) {
@@ -69,13 +110,21 @@ public class RepositoryFactory implement
// remove repository service...
Component service = m_instances.remove(pid);
if (service != null) {
- File repoDir = ((RepositoryImpl) service.getInstance()).getDir();
+ RepositoryImpl repository = (RepositoryImpl) service.getInstance();
+ File repoDir = repository.getDir();
m_manager.remove(service);
+
+ // update our local index...
+ Map<Entry, String> index = new HashMap<>(m_index);
+ for (Map.Entry<Entry, String> entry : index.entrySet()) {
+ if (pid.equals(entry.getValue())) {
+ m_index.remove(entry.getKey(), entry.getValue());
+ }
+ }
// remove persisted data...
deleteRepositoryStore(pid, repoDir);
- deleteRepositoryPrefs(pid);
}
}
@@ -84,7 +133,10 @@ public class RepositoryFactory implement
return "RepositoryFactory";
}
- public void init() {
+ /**
+ * Called by Felix DM.
+ */
+ public void init() throws IOException {
m_tempDir = ensureDirectoryAvailable(m_context.getDataFile("tmp"));
}
@@ -113,6 +165,13 @@ public class RepositoryFactory implement
if ((name == null) || "".equals(name)) {
throw new ConfigurationException(REPOSITORY_NAME, "Repository name has to be specified.");
}
+
+ // Check whether the combination of customer and name is unique...
+ Entry newEntry = new Entry(customer, name);
+ String oldPid = m_index.putIfAbsent(newEntry, pid);
+ if (oldPid != null && !pid.equals(oldPid)) {
+ throw new ConfigurationException(null, "Name and customer combination already exists");
+ }
String master = (String) dict.get(REPOSITORY_MASTER);
if (!("false".equalsIgnoreCase(master.trim()) || "true".equalsIgnoreCase(master.trim()))) {
@@ -158,8 +217,6 @@ public class RepositoryFactory implement
Component oldService = m_instances.putIfAbsent(pid, service);
if (oldService == null) {
// new instance...
- createRepositoryPrefs(pid, customer, name);
-
m_manager.add(service);
}
else {
@@ -178,36 +235,6 @@ public class RepositoryFactory implement
}
}
- private void createRepositoryPrefs(String pid, String customer, String name) throws ConfigurationException {
- Preferences systemPrefs = m_prefsService.getSystemPreferences();
-
- String[] nodes;
- try {
- nodes = systemPrefs.childrenNames();
- }
- catch (BackingStoreException e) {
- throw new ConfigurationException(null, "Internal error while validating configuration.");
- }
- for (String nodeName : nodes) {
- if (pid.equals(nodeName)) {
- // avoid failing on our own node (in case we're updating)...
- continue;
- }
-
- Preferences prefs = systemPrefs.node(nodeName);
- String repoName = prefs.get(REPOSITORY_NAME, "");
- String repoCustomer = prefs.get(REPOSITORY_CUSTOMER, "");
-
- if (name.equalsIgnoreCase(repoName) && name.equalsIgnoreCase(repoCustomer)) {
- throw new ConfigurationException(null, "Name and customer combination already exists");
- }
- }
-
- Preferences node = systemPrefs.node(pid);
- node.put(REPOSITORY_NAME, name);
- node.put(REPOSITORY_CUSTOMER, customer);
- }
-
private RepositoryImpl createRepositoryStore(String pid, File baseDir, boolean isMaster, long limitValue, String fileExtension, String initialContents) {
File dir = ensureDirectoryAvailable(new File(baseDir, pid));
RepositoryImpl store = new RepositoryImpl(dir, m_tempDir, fileExtension, isMaster, limitValue);
@@ -225,18 +252,6 @@ public class RepositoryFactory implement
return store;
}
- private void deleteRepositoryPrefs(String pid) {
- try {
- Preferences prefs = m_prefsService.getSystemPreferences();
-
- prefs.node(pid).removeNode();
- prefs.sync();
- }
- catch (BackingStoreException e) {
- // Not much we can do
- }
- }
-
private void deleteRepositoryStore(String pid, File repoDir) {
if (repoDir.exists() && repoDir.isDirectory()) {
File[] files = repoDir.listFiles();
Modified: ace/trunk/org.apache.ace.test/src/org/apache/ace/it/IntegrationTestBase.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.test/src/org/apache/ace/it/IntegrationTestBase.java?rev=1727343&r1=1727342&r2=1727343&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.test/src/org/apache/ace/it/IntegrationTestBase.java (original)
+++ ace/trunk/org.apache.ace.test/src/org/apache/ace/it/IntegrationTestBase.java Thu Jan 28 13:29:17 2016
@@ -556,6 +556,33 @@ public class IntegrationTestBase extends
}
/**
+ * @param filter
+ * @return the number of configurations that match the given filter, >= 0.
+ */
+ protected int countConfigurations(String filter) throws IOException, InvalidSyntaxException {
+ ConfigurationAdmin admin = getService(ConfigurationAdmin.class);
+ Configuration[] configs = admin.listConfigurations(filter);
+ return configs == null ? 0 : configs.length;
+ }
+
+ /**
+ * @param type
+ * @return the number of services are registered with the given type, >= 0.
+ */
+ protected int countServices(Class<?> type) throws IOException, InvalidSyntaxException {
+ return countServices(String.format("(%s=%s)", Constants.OBJECTCLASS, type.getName()));
+ }
+
+ /**
+ * @param filter
+ * @return the number of services that match the given filter, >= 0.
+ */
+ protected int countServices(String filter) throws IOException, InvalidSyntaxException {
+ ServiceReference<?>[] serviceRefs = m_bundleContext.getServiceReferences((String) null, filter);
+ return serviceRefs == null ? 0 : serviceRefs.length;
+ }
+
+ /**
* Sets whether or not any of the tracked configurations should be automatically be deleted when ending a test.
*
* @param aClean
Modified: ace/trunk/org.apache.ace.test/src/org/apache/ace/it/packageinfo
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.test/src/org/apache/ace/it/packageinfo?rev=1727343&r1=1727342&r2=1727343&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.test/src/org/apache/ace/it/packageinfo (original)
+++ ace/trunk/org.apache.ace.test/src/org/apache/ace/it/packageinfo Thu Jan 28 13:29:17 2016
@@ -1 +1 @@
-version 1.1.0
\ No newline at end of file
+version 1.2.0
\ No newline at end of file