You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2011/10/20 14:39:38 UTC
svn commit: r1186765 [2/2] - in /felix/trunk/configadmin: ./
src/main/java/org/apache/felix/cm/impl/ src/main/java/org/osgi/
src/main/java/org/osgi/service/ src/main/java/org/osgi/service/cm/
src/test/java/org/apache/felix/cm/integration/
Added: felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationPermission.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationPermission.java?rev=1186765&view=auto
==============================================================================
--- felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationPermission.java (added)
+++ felix/trunk/configadmin/src/main/java/org/osgi/service/cm/ConfigurationPermission.java Thu Oct 20 12:39:38 2011
@@ -0,0 +1,638 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2011). All Rights Reserved.
+ *
+ * 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.
+ */
+
+package org.osgi.service.cm;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.security.BasicPermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Indicates a bundle's authority to configure bundles or be updated by
+ * Configuration Admin.
+ *
+ * @ThreadSafe
+ * @version $Id: 0d700c494f2dc2bbe05165bf5c79fe185c9f0a4a $
+ * @since 1.2
+ */
+
+public final class ConfigurationPermission extends BasicPermission {
+ static final long serialVersionUID = 5716868734811965383L;
+ /**
+ * Provides permission to create new configurations for other bundles as
+ * well as manipulate them. The action string {@value #CONFIGURE}.
+ */
+ public final static String CONFIGURE = "configure";
+
+ /**
+ * The permission to be updated, that is, act as a Managed Service or
+ * Managed Service Factory. The action string {@value #TARGET}.
+ *
+ * @since 1.4
+ */
+ public final static String TARGET = "target";
+
+ private final static int ACTION_CONFIGURE = 0x00000001;
+ private final static int ACTION_TARGET = 0x00000002;
+ private final static int ACTION_ALL = ACTION_CONFIGURE
+ | ACTION_TARGET;
+ final static int ACTION_NONE = 0;
+
+ /**
+ * The actions mask.
+ */
+ transient int action_mask;
+
+ /**
+ * The actions in canonical form.
+ *
+ * @serial
+ */
+ private volatile String actions = null;
+
+ /**
+ * Parsed name if it includes wildcards: "*"
+ */
+ private transient List substrings;
+
+ /**
+ * Create a new ConfigurationPermission.
+ *
+ * @param name Name of the permission. Wildcards ({@code '*'}) are allowed
+ * in the name. During {@link #implies(Permission)}, the name is
+ * matched to the requested permission using the substring matching
+ * rules used by {@link Filter}s.
+ * @param actions Comma separated list of {@link #CONFIGURE},
+ * {@link #TARGET}.
+ */
+
+ public ConfigurationPermission(String name, String actions) {
+ this(name, parseActions(actions));
+ }
+
+ /**
+ * Package private constructor used by ConfigurationPermissionCollection.
+ *
+ * @param name location string
+ * @param mask action mask
+ */
+ ConfigurationPermission(String name, int mask) {
+ super(name);
+ setTransients(mask);
+ }
+
+ /**
+ * Called by constructors and when deserialized.
+ *
+ * @param mask action mask
+ */
+ private void setTransients(int mask) {
+ if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
+ throw new IllegalArgumentException("invalid action string");
+ }
+ action_mask = mask;
+ substrings = parseSubstring(getName());
+ }
+
+ /**
+ * Parse action string into action mask.
+ *
+ * @param actions Action string.
+ * @return action mask.
+ */
+ private static int parseActions(String actions) {
+ boolean seencomma = false;
+
+ int mask = ACTION_NONE;
+
+ if (actions == null) {
+ return mask;
+ }
+
+ char[] a = actions.toCharArray();
+
+ int i = a.length - 1;
+ if (i < 0)
+ return mask;
+
+ while (i != -1) {
+ char c;
+
+ // skip whitespace
+ while ((i != -1)
+ && ((c = a[i]) == ' ' || c == '\r' || c == '\n'
+ || c == '\f' || c == '\t'))
+ i--;
+
+ // check for the known strings
+ int matchlen;
+
+ if (i >= 5 && (a[i - 5] == 't' || a[i - 5] == 'T')
+ && (a[i - 4] == 'a' || a[i - 4] == 'A')
+ && (a[i - 3] == 'r' || a[i - 3] == 'R')
+ && (a[i - 2] == 'g' || a[i - 2] == 'G')
+ && (a[i - 1] == 'e' || a[i - 1] == 'E')
+ && (a[i] == 't' || a[i] == 'T')) {
+ matchlen = 6;
+ mask |= ACTION_TARGET;
+
+ }
+ else
+ if (i >= 8 && (a[i - 8] == 'c' || a[i - 8] == 'C')
+ && (a[i - 7] == 'o' || a[i - 7] == 'O')
+ && (a[i - 6] == 'n' || a[i - 6] == 'N')
+ && (a[i - 5] == 'f' || a[i - 5] == 'F')
+ && (a[i - 4] == 'i' || a[i - 4] == 'I')
+ && (a[i - 3] == 'g' || a[i - 3] == 'G')
+ && (a[i - 2] == 'u' || a[i - 2] == 'U')
+ && (a[i - 1] == 'r' || a[i - 1] == 'R')
+ && (a[i] == 'e' || a[i] == 'E')) {
+ matchlen = 9;
+ mask |= ACTION_CONFIGURE;
+
+ }
+ else {
+ // parse error
+ throw new IllegalArgumentException("invalid actions: "
+ + actions);
+ }
+
+ // make sure we didn't just match the tail of a word
+ // like "ackbarftarget". Also, skip to the comma.
+ seencomma = false;
+ while (i >= matchlen && !seencomma) {
+ switch (a[i - matchlen]) {
+ case ',' :
+ seencomma = true;
+ /* FALLTHROUGH */
+ case ' ' :
+ case '\r' :
+ case '\n' :
+ case '\f' :
+ case '\t' :
+ break;
+ default :
+ throw new IllegalArgumentException(
+ "invalid permission: " + actions);
+ }
+ i--;
+ }
+
+ // point i at the location of the comma minus one (or -1).
+ i -= matchlen;
+ }
+
+ if (seencomma) {
+ throw new IllegalArgumentException("invalid actions: " + actions);
+ }
+
+ return mask;
+ }
+
+ /**
+ * Parse the name for wildcard processing.
+ *
+ * @param name The name of the permission.
+ * @return {@code null} is the name has no wildcards or a
+ * {@code List<String>} where element is a substring to match or
+ * null for {@code '*'}.
+ */
+ private static List parseSubstring(String name) {
+ if (name.indexOf('*') < 0) {
+ return null;
+ }
+ char[] chars = name.toCharArray();
+ StringBuffer sb = new StringBuffer(chars.length);
+
+ List sub = new ArrayList(10);
+
+ for (int pos = 0; pos < chars.length; pos++) {
+ char c = chars[pos];
+
+ switch (c) {
+ case '*' : {
+ if (sb.length() > 0) {
+ sub.add(sb.toString());
+ }
+ sb.setLength(0);
+ sub.add(null);
+ break;
+ }
+
+ case '\\' : {
+ pos++;
+ if (pos < chars.length) {
+ c = chars[pos];
+ }
+ /* fall through into default */
+ }
+
+ default : {
+ sb.append(c);
+ break;
+ }
+ }
+ }
+ if (sb.length() > 0) {
+ sub.add(sb.toString());
+ }
+
+ int size = sub.size();
+
+ if (size == 0) {
+ return null;
+ }
+
+ if (size == 1) {
+ if (sub.get(0) != null) {
+ return null;
+ }
+ }
+ return sub;
+ }
+
+ /**
+ * Determines if a {@code ConfigurationPermission} object "implies" the
+ * specified permission.
+ *
+ * @param p The target permission to check.
+ * @return {@code true} if the specified permission is implied by this
+ * object; {@code false} otherwise.
+ */
+
+ public boolean implies(Permission p) {
+ if (!(p instanceof ConfigurationPermission)) {
+ return false;
+ }
+ ConfigurationPermission requested = (ConfigurationPermission) p;
+ return implies0(requested, ACTION_NONE);
+ }
+
+ /**
+ * Internal implies method. Used by the implies and the permission
+ * collection implies methods.
+ *
+ * @param requested The requested ConfigurationPermission which has already
+ * be validated as a proper argument.
+ * @param effective The effective actions with which to start.
+ * @return {@code true} if the specified permission is implied by this
+ * object; {@code false} otherwise.
+ */
+ boolean implies0(ConfigurationPermission requested, int effective) {
+ /* check actions first - much faster */
+ effective |= action_mask;
+ final int desired = requested.action_mask;
+ if ((effective & desired) != desired) {
+ return false;
+ }
+ String requestedName = requested.getName();
+ if (substrings == null) {
+ return getName().equals(requestedName);
+ }
+ for (int i = 0, pos = 0, size = substrings.size(); i < size; i++) {
+ String substr = (String) substrings.get(i);
+
+ if (i + 1 < size) /* if this is not that last substr */{
+ if (substr == null) /* * */{
+ String substr2 = (String) substrings.get(i + 1);
+
+ if (substr2 == null) /* ** */
+ continue; /* ignore first star */
+ /* xxx */
+ int index = requestedName.indexOf(substr2, pos);
+ if (index == -1) {
+ return false;
+ }
+
+ pos = index + substr2.length();
+ if (i + 2 < size) // if there are more
+ // substrings, increment
+ // over the string we just
+ // matched; otherwise need
+ // to do the last substr
+ // check
+ i++;
+ }
+ else /* xxx */{
+ int len = substr.length();
+ if (requestedName.regionMatches(pos, substr, 0, len)) {
+ pos += len;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ else /* last substr */{
+ if (substr == null) /* * */{
+ return true;
+ }
+ /* xxx */
+ return requestedName.endsWith(substr);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines the equality of two {@code ConfigurationPermission} objects.
+ * <p>
+ * Two {@code ConfigurationPermission} objects are equal.
+ *
+ * @param obj The object being compared for equality with this object.
+ * @return {@code true} if {@code obj} is equivalent to this
+ * {@code ConfigurationPermission}; {@code false} otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (!(obj instanceof ConfigurationPermission)) {
+ return false;
+ }
+
+ ConfigurationPermission cp = (ConfigurationPermission) obj;
+
+ return (action_mask == cp.action_mask)
+ && getName().equals(cp.getName());
+ }
+
+ /**
+ * Returns the hash code value for this object.
+ *
+ * @return Hash code value for this object.
+ */
+
+ public int hashCode() {
+ int h = 31 * 17 + getName().hashCode();
+ h = 31 * h + getActions().hashCode();
+ return h;
+ }
+
+ /**
+ * Returns the canonical string representation of the
+ * {@code ConfigurationPermission} actions.
+ *
+ * <p>
+ * Always returns present {@code ConfigurationPermission} actions in the
+ * following order: {@value #CONFIGURE}, {@value #TARGET}
+ *
+ * @return Canonical string representation of the
+ * {@code ConfigurationPermission} actions.
+ */
+ public String getActions() {
+ String result = actions;
+ if (result == null) {
+ StringBuffer sb = new StringBuffer();
+ boolean comma = false;
+
+ int mask = action_mask;
+ if ((mask & ACTION_CONFIGURE) == ACTION_CONFIGURE) {
+ sb.append(CONFIGURE);
+ comma = true;
+ }
+
+ if ((mask & ACTION_TARGET) == ACTION_TARGET) {
+ if (comma)
+ sb.append(',');
+ sb.append(TARGET);
+ }
+
+ actions = result = sb.toString();
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns a new {@code PermissionCollection} object suitable for storing
+ * {@code ConfigurationPermission}s.
+ *
+ * @return A new {@code PermissionCollection} object.
+ */
+ public PermissionCollection newPermissionCollection() {
+ return new ConfigurationPermissionCollection();
+ }
+
+ /**
+ * WriteObject is called to save the state of this permission object to a
+ * stream. The actions are serialized, and the superclass takes care of the
+ * name.
+ */
+ private synchronized void writeObject(java.io.ObjectOutputStream s)
+ throws IOException {
+ // Write out the actions. The superclass takes care of the name
+ // call getActions to make sure actions field is initialized
+ if (actions == null)
+ getActions();
+ s.defaultWriteObject();
+ }
+
+ /**
+ * readObject is called to restore the state of this permission from a
+ * stream.
+ */
+ private synchronized void readObject(java.io.ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+ // Read in the data, then initialize the transients
+ s.defaultReadObject();
+ setTransients(parseActions(actions));
+ }
+}
+
+/**
+ * Stores a set of {@code ConfigurationPermission} permissions.
+ *
+ * @see java.security.Permission
+ * @see java.security.Permissions
+ * @see java.security.PermissionCollection
+ */
+final class ConfigurationPermissionCollection extends PermissionCollection {
+ static final long serialVersionUID = -6917638867081695839L;
+ /**
+ * Collection of permissions.
+ *
+ * @serial
+ * @GuardedBy this
+ */
+ private Map permissions;
+
+ /**
+ * Boolean saying if "*" is in the collection.
+ *
+ * @serial
+ * @GuardedBy this
+ */
+ private boolean all_allowed;
+
+ /**
+ * Creates an empty {@code ConfigurationPermissionCollection} object.
+ *
+ */
+ public ConfigurationPermissionCollection() {
+ permissions = new HashMap();
+ all_allowed = false;
+ }
+
+ /**
+ * Adds the specified permission to the
+ * {@code ConfigurationPermissionCollection}. The key for the hash is the
+ * interface name of the service.
+ *
+ * @param permission The {@code Permission} object to add.
+ *
+ * @exception IllegalArgumentException If the permission is not an
+ * {@code ConfigurationPermission}.
+ *
+ * @exception SecurityException If this ConfigurationPermissionCollection
+ * object has been marked read-only.
+ */
+
+ public void add(Permission permission) {
+ if (!(permission instanceof ConfigurationPermission)) {
+ throw new IllegalArgumentException("invalid permission: "
+ + permission);
+ }
+
+ if (isReadOnly())
+ throw new SecurityException("attempt to add a Permission to a "
+ + "readonly PermissionCollection");
+
+ final ConfigurationPermission cp = (ConfigurationPermission) permission;
+ final String name = cp.getName();
+ synchronized (this) {
+ Map pc = permissions;
+ final ConfigurationPermission existing = (ConfigurationPermission) pc.get(name);
+ if (existing != null) {
+ final int oldMask = existing.action_mask;
+ final int newMask = cp.action_mask;
+ if (oldMask != newMask) {
+ pc.put(name, new ConfigurationPermission(name, oldMask
+ | newMask));
+ }
+ }
+ else {
+ pc.put(name, cp);
+ }
+
+ if (!all_allowed) {
+ if (name.equals("*")) {
+ all_allowed = true;
+ }
+ }
+ }
+ }
+
+ /**
+ * Determines if the specified permissions implies the permissions expressed
+ * in {@code permission}.
+ *
+ * @param permission The Permission object to compare with this
+ * {@code ConfigurationPermission} object.
+ * @return {@code true} if {@code permission} is a proper subset of a
+ * permission in the set; {@code false} otherwise.
+ */
+ public boolean implies(Permission permission) {
+ if (!(permission instanceof ConfigurationPermission)) {
+ return false;
+ }
+ final ConfigurationPermission requested = (ConfigurationPermission) permission;
+ int effective = ConfigurationPermission.ACTION_NONE;
+
+ Collection perms;
+ synchronized (this) {
+ Map pc = permissions;
+ /* short circuit if the "*" Permission was added */
+ if (all_allowed) {
+ ConfigurationPermission cp = (ConfigurationPermission) pc.get("*");
+ if (cp != null) {
+ effective |= cp.action_mask;
+ final int desired = requested.action_mask;
+ if ((effective & desired) == desired) {
+ return true;
+ }
+ }
+ }
+ perms = pc.values();
+ }
+ /* iterate one by one over permissions */
+ for (Iterator permI = perms.iterator(); permI.hasNext(); ) {
+ ConfigurationPermission perm = (ConfigurationPermission) permI.next();
+ if (perm.implies0(requested, effective)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns an enumeration of all {@code ConfigurationPermission} objects in
+ * the container.
+ *
+ * @return Enumeration of all {@code ConfigurationPermission} objects.
+ */
+ public synchronized Enumeration elements() {
+ List all = new ArrayList(permissions.values());
+ return Collections.enumeration(all);
+ }
+
+ /* serialization logic */
+ private static final ObjectStreamField[] serialPersistentFields = {
+ new ObjectStreamField("hasElement", Boolean.TYPE),
+ new ObjectStreamField("permissions", HashMap.class),
+ new ObjectStreamField("all_allowed", Boolean.TYPE) };
+
+ private synchronized void writeObject(ObjectOutputStream out)
+ throws IOException {
+ ObjectOutputStream.PutField pfields = out.putFields();
+ pfields.put("hasElement", false);
+ pfields.put("permissions", permissions);
+ pfields.put("all_allowed", all_allowed);
+ out.writeFields();
+ }
+
+ private synchronized void readObject(java.io.ObjectInputStream in)
+ throws IOException, ClassNotFoundException {
+ ObjectInputStream.GetField gfields = in.readFields();
+ boolean hasElement = gfields.get("hasElement", false);
+ if (hasElement) { // old format
+ permissions = new HashMap();
+ permissions.put("*", new ConfigurationPermission("*",
+ ConfigurationPermission.CONFIGURE));
+ all_allowed = true;
+ }
+ else {
+ permissions = (HashMap) gfields
+ .get("permissions",
+ new HashMap());
+ all_allowed = gfields.get("all_allowed", false);
+ }
+ }
+}
Modified: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java?rev=1186765&r1=1186764&r2=1186765&view=diff
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java (original)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java Thu Oct 20 12:39:38 2011
@@ -40,6 +40,12 @@ import org.osgi.service.cm.Configuration
public class ConfigurationBaseTest extends ConfigurationTestBase
{
+ static
+ {
+ // uncomment to enable debugging of this test class
+ // paxRunnerVmOption = DEBUG_VM_OPTION;
+ }
+
@Test
public void test_basic_configuration_configure_then_start() throws BundleException, IOException
{
Modified: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBindingTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBindingTest.java?rev=1186765&r1=1186764&r2=1186765&view=diff
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBindingTest.java (original)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBindingTest.java Thu Oct 20 12:39:38 2011
@@ -39,6 +39,13 @@ import org.osgi.service.cm.Configuration
public class ConfigurationBindingTest extends ConfigurationTestBase
{
+ static
+ {
+ // uncomment to enable debugging of this test class
+ // paxRunnerVmOption = DEBUG_VM_OPTION;
+ }
+
+
@Test
public void test_configuration_unbound_on_uninstall() throws BundleException
{
@@ -445,6 +452,7 @@ public class ConfigurationBindingTest ex
// remove the static binding and assert still bound
config.setBundleLocation( null );
+ delay();
TestCase.assertEquals( location, config.getBundleLocation() );
// uninstall bundle and assert configuration unbound
@@ -580,33 +588,13 @@ public class ConfigurationBindingTest ex
// ==> configuration is bound to locationB
TestCase.assertEquals( locationB, config.getBundleLocation() );
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // ==> configuration removed from service ms1
- TestCase.assertNull( testerA1.props );
- TestCase.assertEquals( 2, testerA1.numManagedServiceUpdatedCalls );
-
- // ==> configuration supplied to the service ms2
- TestCase.assertNotNull( testerB1.props );
- TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
- }
- else
- {
- // ==> configuration remains for service ms1
- TestCase.assertNotNull( testerA1.props );
- TestCase.assertEquals( 1, testerA1.numManagedServiceUpdatedCalls );
-
- // ==> configuration not supplied to the service ms2
- TestCase.assertNull( testerB1.props );
- TestCase.assertEquals( 0, testerB1.numManagedServiceUpdatedCalls );
- }
+ // ==> configuration removed from service ms1
+ TestCase.assertNull( testerA1.props );
+ TestCase.assertEquals( 2, testerA1.numManagedServiceUpdatedCalls );
+
+ // ==> configuration supplied to the service ms2
+ TestCase.assertNotNull( testerB1.props );
+ TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
}
@@ -650,33 +638,13 @@ public class ConfigurationBindingTest ex
// ==> configuration is bound to locationB
TestCase.assertEquals( locationB, config.getBundleLocation() );
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // ==> configuration removed from service ms1
- TestCase.assertNull( testerA1.props );
- TestCase.assertEquals( 2, testerA1.numManagedServiceUpdatedCalls );
-
- // ==> configuration supplied to the service ms2
- TestCase.assertNotNull( testerB1.props );
- TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
- }
- else
- {
- // ==> configuration remains for service ms1
- TestCase.assertNotNull( testerA1.props );
- TestCase.assertEquals( 1, testerA1.numManagedServiceUpdatedCalls );
-
- // ==> configuration not supplied to the service ms2
- TestCase.assertNull( testerB1.props );
- TestCase.assertEquals( 0, testerB1.numManagedServiceUpdatedCalls );
- }
+ // ==> configuration removed from service ms1
+ TestCase.assertNull( testerA1.props );
+ TestCase.assertEquals( 2, testerA1.numManagedServiceUpdatedCalls );
+
+ // ==> configuration supplied to the service ms2
+ TestCase.assertNotNull( testerB1.props );
+ TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
// 6. Update configuration now
config.update();
@@ -684,7 +652,7 @@ public class ConfigurationBindingTest ex
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.props );
- TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
+ TestCase.assertEquals( 2, testerB1.numManagedServiceUpdatedCalls );
}
@@ -726,35 +694,14 @@ public class ConfigurationBindingTest ex
// ==> configuration is bound to locationB
TestCase.assertEquals( locationB, config.getBundleLocation() );
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // ==> configuration removed from service ms1
- TestCase.assertNull( testerA1.configs.get( pid ));
- TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
- TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryDeleteCalls );
-
- // ==> configuration supplied to the service ms2
- TestCase.assertNotNull( testerB1.configs.get( pid ) );
- TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
- }
- else
- {
- // ==> configuration not removed from service ms1
- TestCase.assertNotNull( testerA1.configs.get( pid ));
- TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
- TestCase.assertEquals( 0, testerA1.numManagedServiceFactoryDeleteCalls );
-
- // ==> configuration not supplied to the service ms2
- TestCase.assertNull( testerB1.configs.get( pid ) );
- TestCase.assertEquals( 0, testerB1.numManagedServiceFactoryUpdatedCalls );
- }
+ // ==> configuration removed from service ms1
+ TestCase.assertNull( testerA1.configs.get( pid ));
+ TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
+ TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryDeleteCalls );
+
+ // ==> configuration supplied to the service ms2
+ TestCase.assertNotNull( testerB1.configs.get( pid ) );
+ TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
// 6. Update configuration now
config.update();
@@ -762,7 +709,7 @@ public class ConfigurationBindingTest ex
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.configs.get( pid ) );
- TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
+ TestCase.assertEquals( 2, testerB1.numManagedServiceFactoryUpdatedCalls );
}
@@ -808,35 +755,14 @@ public class ConfigurationBindingTest ex
// ==> configuration is bound to locationB
TestCase.assertEquals( locationB, config.getBundleLocation() );
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // ==> configuration removed from service ms1
- TestCase.assertNull( testerA1.configs.get( pid ));
- TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
- TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryDeleteCalls );
-
- // ==> configuration supplied to the service ms2
- TestCase.assertNotNull( testerB1.configs.get( pid ) );
- TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
- }
- else
- {
- // ==> configuration not removed from service ms1
- TestCase.assertNotNull( testerA1.configs.get( pid ));
- TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
- TestCase.assertEquals( 0, testerA1.numManagedServiceFactoryDeleteCalls );
-
- // ==> configuration not supplied to the service ms2
- TestCase.assertNull( testerB1.configs.get( pid ) );
- TestCase.assertEquals( 0, testerB1.numManagedServiceFactoryUpdatedCalls );
- }
+ // ==> configuration removed from service ms1
+ TestCase.assertNull( testerA1.configs.get( pid ));
+ TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
+ TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryDeleteCalls );
+
+ // ==> configuration supplied to the service ms2
+ TestCase.assertNotNull( testerB1.configs.get( pid ) );
+ TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
// 6. Update configuration now
config.update();
@@ -844,7 +770,7 @@ public class ConfigurationBindingTest ex
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.configs.get( pid ) );
- TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
+ TestCase.assertEquals( 2, testerB1.numManagedServiceFactoryUpdatedCalls );
}
@@ -887,31 +813,12 @@ public class ConfigurationBindingTest ex
bundleA.uninstall();
delay();
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // ==> configuration is bound to locationB
- TestCase.assertEquals( locationB, config.getBundleLocation() );
-
- // ==> configuration supplied to the service ms2
- TestCase.assertNotNull( testerB1.props );
- TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
- }
- else
- {
- // ==> configuration is unbound
- TestCase.assertNull( config.getBundleLocation() );
-
- // ==> configuration not supplied to the service ms2
- TestCase.assertNull( testerB1.props );
- TestCase.assertEquals( 0, testerB1.numManagedServiceUpdatedCalls );
- }
+ // ==> configuration is bound to locationB
+ TestCase.assertEquals( locationB, config.getBundleLocation() );
+
+ // ==> configuration supplied to the service ms2
+ TestCase.assertNotNull( testerB1.props );
+ TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
// 6. Update configuration now
config.update();
@@ -919,7 +826,7 @@ public class ConfigurationBindingTest ex
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.props );
- TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
+ TestCase.assertEquals( 2, testerB1.numManagedServiceUpdatedCalls );
}
@@ -962,31 +869,12 @@ public class ConfigurationBindingTest ex
bundleA.uninstall();
delay();
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // ==> configuration is bound to locationB
- TestCase.assertEquals( locationB, config.getBundleLocation() );
-
- // ==> configuration supplied to the service ms2
- TestCase.assertNotNull( testerB1.configs.get( pid ) );
- TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
- }
- else
- {
- // ==> configuration is unbound
- TestCase.assertNull( config.getBundleLocation() );
-
- // ==> configuration not supplied to the service ms2
- TestCase.assertNull( testerB1.configs.get( pid ) );
- TestCase.assertEquals( 0, testerB1.numManagedServiceFactoryUpdatedCalls );
- }
+ // ==> configuration is bound to locationB
+ TestCase.assertEquals( locationB, config.getBundleLocation() );
+
+ // ==> configuration supplied to the service ms2
+ TestCase.assertNotNull( testerB1.configs.get( pid ) );
+ TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
// 6. Update configuration now
config.update();
@@ -994,6 +882,6 @@ public class ConfigurationBindingTest ex
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.configs.get( pid ) );
- TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
+ TestCase.assertEquals( 2, testerB1.numManagedServiceFactoryUpdatedCalls );
}
}
Modified: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationTestBase.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationTestBase.java?rev=1186765&r1=1186764&r2=1186765&view=diff
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationTestBase.java (original)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationTestBase.java Thu Oct 20 12:39:38 2011
@@ -29,7 +29,9 @@ import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Dictionary;
+import java.util.HashSet;
import java.util.Hashtable;
+import java.util.Set;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
@@ -60,24 +62,6 @@ import org.osgi.util.tracker.ServiceTrac
public abstract class ConfigurationTestBase
{
- /**
- * There is currently an open issue in the specification in whether a
- * call to Configuration.setBundleLocation() might trigger a configuration
- * update or not.
- * We have test cases in our integration test suite for both cases. To
- * enable the respective tests set this field accordingly:
- * <dl>
- * <dt>false</dt>
- * <dd>Expect configuration to <b>NOT</b> be redispatched. That is existing
- * configurations are kept and other services are not updated</dd>
- * <dt>true</dt>
- * <dd>Expect configuration to be redispatched. That is existing configuration
- * is revoked (update(null) or delete calls) and new matching services are
- * updated.</dd>
- * </dl>
- */
- public static final boolean REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION = false;
-
// the name of the system property providing the bundle file to be installed and tested
protected static final String BUNDLE_JAR_SYS_PROP = "project.bundle.file";
@@ -99,6 +83,8 @@ public abstract class ConfigurationTestB
protected ServiceTracker configAdminTracker;
+ private Set<String> configurations = new HashSet<String>();
+
protected static final String PROP_NAME = "theValue";
protected static final Dictionary<String, String> theConfig;
@@ -121,6 +107,7 @@ public abstract class ConfigurationTestB
}
final Option[] base = options(
+ /* CoreOptions.allFrameworks(), */
provision(
CoreOptions.bundle( bundleFile.toURI().toString() ),
mavenBundle( "org.ops4j.pax.swissbox", "pax-swissbox-tinybundles", "1.0.0" )
@@ -148,6 +135,11 @@ public abstract class ConfigurationTestB
bundle.uninstall();
}
+ for ( String pid : configurations )
+ {
+ deleteConfig( pid );
+ }
+
configAdminTracker.close();
configAdminTracker = null;
}
@@ -299,7 +291,7 @@ public abstract class ConfigurationTestB
final ConfigurationAdmin ca = getConfigurationAdmin();
try
{
- final Configuration config = ca.createFactoryConfiguration( factoryPid, null );
+ final Configuration config = ca.createFactoryConfiguration( factoryPid, location );
if ( withProps )
{
config.update( theConfig );
@@ -345,6 +337,7 @@ public abstract class ConfigurationTestB
final ConfigurationAdmin ca = getConfigurationAdmin();
try
{
+ configurations.remove( pid );
final Configuration config = ca.getConfiguration( pid );
config.delete();
}
@@ -366,6 +359,7 @@ public abstract class ConfigurationTestB
{
for ( Configuration configuration : configs )
{
+ configurations.remove( configuration.getPid() );
configuration.delete();
}
}
Modified: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/MultiServiceFactoryPIDTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/MultiServiceFactoryPIDTest.java?rev=1186765&r1=1186764&r2=1186765&view=diff
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/MultiServiceFactoryPIDTest.java (original)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/MultiServiceFactoryPIDTest.java Thu Oct 20 12:39:38 2011
@@ -39,6 +39,11 @@ import org.osgi.service.cm.Configuration
@RunWith(JUnit4TestRunner.class)
public class MultiServiceFactoryPIDTest extends ConfigurationTestBase
{
+ static
+ {
+ // uncomment to enable debugging of this test class
+ // paxRunnerVmOption = DEBUG_VM_OPTION;
+ }
@Test
public void test_two_services_same_pid_in_same_bundle_configure_before_registration() throws BundleException
@@ -61,7 +66,7 @@ public class MultiServiceFactoryPIDTest
// assert activater has configuration (two calls, one per pid)
TestCase.assertNotNull( "Expect Properties after Service Registration", tester.configs.get( pid ) );
- TestCase.assertEquals( "Expect a single update call", 2, tester.numManagedServiceFactoryUpdatedCalls );
+ TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceFactoryUpdatedCalls );
TestCase.assertEquals( bundle.getLocation(), config.getBundleLocation() );
@@ -165,23 +170,10 @@ public class MultiServiceFactoryPIDTest
delay();
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // expect configuration reassigned
- TestCase.assertEquals( bundle2.getLocation(), config.getBundleLocation() );
- }
- else
- {
- // expected configuration unbound
- TestCase.assertNull( config.getBundleLocation() );
- }
+ // expect configuration reassigned
+ TestCase.assertEquals( bundle2.getLocation(), config.getBundleLocation() );
+ TestCase.assertNotNull( "Expect Properties after Configuration Redispatch", tester2.configs.get( pid ) );
+ TestCase.assertEquals( "Expect update call after Configuration Redispatch", 1, tester2.numManagedServiceFactoryUpdatedCalls );
// remove the configuration for good
deleteConfig( pid );
@@ -230,78 +222,27 @@ public class MultiServiceFactoryPIDTest
delay();
TestCase.assertEquals( factoryPid, config.getFactoryPid() );
- TestCase.assertNotNull( config.getBundleLocation() );
- if ( bundle.getLocation().equals( config.getBundleLocation() ) )
- {
- // configuration assigned to the first bundle
- TestCase.assertNotNull( "Expect Properties after Service Registration", tester.configs.get( pid ) );
- TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceFactoryUpdatedCalls );
-
- TestCase.assertTrue( "Expect Properties after Service Registration", tester2.configs.isEmpty() );
- TestCase.assertEquals( "Expect a single update call", 0, tester2.numManagedServiceFactoryUpdatedCalls );
-
- bundle.uninstall();
- bundle = null;
-
- delay();
-
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // expect configuration reassigned
- TestCase.assertEquals( bundle2.getLocation(), config.getBundleLocation() );
- }
- else
- {
- // expected configuration unbound
- TestCase.assertNull( config.getBundleLocation() );
- }
- }
- else if ( bundle2.getLocation().equals( config.getBundleLocation() ) )
- {
- // configuration assigned to the second bundle
- // assert activater has configuration (two calls, one per pid)
- TestCase.assertNotNull( "Expect Properties after Service Registration", tester2.configs.get( pid ) );
- TestCase.assertEquals( "Expect a single update call", 1, tester2.numManagedServiceFactoryUpdatedCalls );
+ TestCase.assertEquals(
+ "Configuration must be bound to second bundle because the service has higher ranking",
+ bundle.getLocation(), config.getBundleLocation() );
- TestCase.assertTrue( "Expect Properties after Service Registration", tester.configs.isEmpty() );
- TestCase.assertEquals( "Expect a single update call", 0, tester.numManagedServiceFactoryUpdatedCalls );
+ // configuration assigned to the first bundle
+ TestCase.assertNotNull( "Expect Properties after Service Registration", tester.configs.get( pid ) );
+ TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceFactoryUpdatedCalls );
- bundle2.uninstall();
- bundle2 = null;
+ TestCase.assertTrue( "Expect Properties after Service Registration", tester2.configs.isEmpty() );
+ TestCase.assertEquals( "Expect a single update call", 0, tester2.numManagedServiceFactoryUpdatedCalls );
+
+ bundle.uninstall();
+ bundle = null;
- delay();
+ delay();
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // expect configuration reassigned
- TestCase.assertEquals( bundle.getLocation(), config.getBundleLocation() );
- }
- else
- {
- // expected configuration unbound
- TestCase.assertNull( config.getBundleLocation() );
- }
- }
- else
- {
- // configuration assigned to some other bundle ... fail
- TestCase.fail( "Configuration assigned to unexpected bundle " + config.getBundleLocation() );
- }
+ // expect configuration reassigned
+ TestCase.assertEquals( bundle2.getLocation(), config.getBundleLocation() );
+ TestCase.assertNotNull( "Expect Properties after Configuration Redispatch", tester2.configs.get( pid ) );
+ TestCase.assertEquals( "Expect a single update call after Configuration Redispatch", 1, tester2.numManagedServiceFactoryUpdatedCalls );
// remove the configuration for good
deleteConfig( pid );
Modified: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/MultiServicePIDTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/MultiServicePIDTest.java?rev=1186765&r1=1186764&r2=1186765&view=diff
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/MultiServicePIDTest.java (original)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/MultiServicePIDTest.java Thu Oct 20 12:39:38 2011
@@ -39,6 +39,11 @@ import org.osgi.service.cm.Configuration
@RunWith(JUnit4TestRunner.class)
public class MultiServicePIDTest extends ConfigurationTestBase
{
+ static
+ {
+ // uncomment to enable debugging of this test class
+ // paxRunnerVmOption = DEBUG_VM_OPTION;
+ }
@Test
public void test_two_services_same_pid_in_same_bundle_configure_before_registration() throws BundleException
@@ -150,7 +155,7 @@ public class MultiServicePIDTest extends
// expect first activator to have received properties
- // assert first bundle has configuration (two calls, one per srv)
+ // assert first bundle has configuration (one calls, one per srv)
TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );
@@ -166,23 +171,16 @@ public class MultiServicePIDTest extends
delay();
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // expect configuration reassigned
- TestCase.assertEquals( bundle2.getLocation(), config.getBundleLocation() );
- }
- else
- {
- // expected configuration unbound
- TestCase.assertNull( config.getBundleLocation() );
- }
+ // after uninstallation, the configuration is redispatched
+ // due to the dynamic binding being removed
+
+ // expect configuration reassigned
+ TestCase.assertEquals( bundle2.getLocation(), config.getBundleLocation() );
+
+ // assert second bundle now has the configuration
+ TestCase.assertNotNull( "Expect Properties after Configuration redispatch", tester2.props );
+ TestCase.assertEquals( "Expect a single update call after Configuration redispatch", 1,
+ tester2.numManagedServiceUpdatedCalls );
// remove the configuration for good
deleteConfig( pid );
@@ -231,78 +229,33 @@ public class MultiServicePIDTest extends
final Configuration config = getConfiguration( pid );
TestCase.assertEquals( pid, config.getPid() );
- TestCase.assertNotNull( config.getBundleLocation() );
- if ( bundle.getLocation().equals( config.getBundleLocation() ) )
- {
- // configuration assigned to the first bundle
- TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
- TestCase.assertEquals( "Expect a single update call", 2, tester.numManagedServiceUpdatedCalls );
-
- TestCase.assertNull( "Expect Properties after Service Registration", tester2.props );
- TestCase.assertEquals( "Expect a single update call", 1, tester2.numManagedServiceUpdatedCalls );
-
- bundle.uninstall();
- bundle = null;
-
- delay();
-
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // expect configuration reassigned
- TestCase.assertEquals( bundle2.getLocation(), config.getBundleLocation() );
- }
- else
- {
- // expected configuration unbound
- TestCase.assertNull( config.getBundleLocation() );
- }
- }
- else if ( bundle2.getLocation().equals( config.getBundleLocation() ) )
- {
- // configuration assigned to the second bundle
- // assert activater has configuration (two calls, one per pid)
- TestCase.assertNotNull( "Expect Properties after Service Registration", tester2.props );
- TestCase.assertEquals( "Expect a single update call", 2, tester2.numManagedServiceUpdatedCalls );
+ TestCase.assertEquals(
+ "Configuration must be bound to first bundle because the service has higher ranking",
+ bundle.getLocation(), config.getBundleLocation() );
+
+ // configuration assigned to the first bundle
+ TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
+ TestCase.assertEquals( "Expect a single update call", 2, tester.numManagedServiceUpdatedCalls );
- TestCase.assertNull( "Expect Properties after Service Registration", tester.props );
- TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );
+ TestCase.assertNull( "Expect Properties after Service Registration", tester2.props );
+ TestCase.assertEquals( "Expect a single update call", 1, tester2.numManagedServiceUpdatedCalls );
- bundle2.uninstall();
- bundle2 = null;
+ bundle.uninstall();
+ bundle = null;
- delay();
+ delay();
- /*
- * According to BJ Hargrave configuration is not re-dispatched
- * due to setting the bundle location.
- * <p>
- * Therefore, we have two sets one with re-dispatch expectation and
- * one without re-dispatch expectation.
- */
- if ( REDISPATCH_CONFIGURATION_ON_SET_BUNDLE_LOCATION )
- {
- // expect configuration reassigned
- TestCase.assertEquals( bundle.getLocation(), config.getBundleLocation() );
- }
- else
- {
- // expected configuration unbound
- TestCase.assertNull( config.getBundleLocation() );
- }
- }
- else
- {
- // configuration assigned to some other bundle ... fail
- TestCase.fail( "Configuration assigned to unexpected bundle " + config.getBundleLocation() );
- }
+ // after uninstallation, the configuration is redispatched
+ // due to the dynamic binding being removed
+
+ // expect configuration reassigned
+ TestCase.assertEquals( bundle2.getLocation(), config.getBundleLocation() );
+
+ // assert second bundle now has the configuration
+ TestCase.assertNotNull( "Expect Properties after Configuration redispatch", tester2.props );
+ TestCase.assertEquals( "Expect a single update call after Configuration redispatch", 2,
+ tester2.numManagedServiceUpdatedCalls );
// remove the configuration for good
deleteConfig( pid );