aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStoyan Boshev2012-01-10 08:36:50 (EST)
committerStoyan Boshev2012-01-10 08:36:50 (EST)
commit6c0ac46a5c1824eef44ae09d3c2d35a791e5d21e (patch)
tree39d6ce140eb28a97a4e6823153c45215abee199f
parentbafee66a1833f49fc24a3096af383a1e65ef77b2 (diff)
downloadrt.equinox.bundles-6c0ac46a5c1824eef44ae09d3c2d35a791e5d21e.zip
rt.equinox.bundles-6c0ac46a5c1824eef44ae09d3c2d35a791e5d21e.tar.gz
rt.equinox.bundles-6c0ac46a5c1824eef44ae09d3c2d35a791e5d21e.tar.bz2
Bug 358108. [ds] Implement new functionality for R4.3 compendium (RFC
176)
-rw-r--r--bundles/org.eclipse.equinox.ds/META-INF/MANIFEST.MF2
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/InstanceProcess.java35
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Messages.java6
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Reference.java40
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Resolver.java136
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRManager.java13
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRUtil.java4
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRmessages.properties6
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ComponentReference.java145
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/DeclarationParser.java104
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponent.java99
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponentProp.java31
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/storage/file/FileStorage.java70
13 files changed, 571 insertions, 120 deletions
diff --git a/bundles/org.eclipse.equinox.ds/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.ds/META-INF/MANIFEST.MF
index bfc36b7..9abad81 100644
--- a/bundles/org.eclipse.equinox.ds/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.ds/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %bundleName
Bundle-SymbolicName: org.eclipse.equinox.ds;singleton:=true
-Bundle-Version: 1.3.100.qualifier
+Bundle-Version: 1.4.0.qualifier
Bundle-Vendor: %bundleVendor
Bundle-Activator: org.eclipse.equinox.internal.ds.Activator
Bundle-Description: This bundle provides support for OSGi
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/InstanceProcess.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/InstanceProcess.java
index 09c9e90..81e7762 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/InstanceProcess.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/InstanceProcess.java
@@ -227,12 +227,12 @@ public class InstanceProcess {
// check if MSF
try {
- Configuration config = Activator.getConfiguration(sc.name);
+ Configuration config = Activator.getConfiguration(sc.getConfigurationPID());
if (config != null) {
factoryPid = config.getFactoryPid();
}
} catch (Exception e) {
- Activator.log(null, LogService.LOG_ERROR, NLS.bind(Messages.CANNOT_GET_CONFIGURATION, sc.name), e);
+ Activator.log(null, LogService.LOG_ERROR, NLS.bind(Messages.CANNOT_GET_CONFIGURATION, sc.getConfigurationPID()), e);
}
// if MSF throw exception - can't be
@@ -478,6 +478,37 @@ public class InstanceProcess {
}
/**
+ * Called by dispatcher ( Resolver) when service properties have been modified for some reference
+ *
+ * @param serviceReferenceTable Map of <Reference>:<Map of <ServiceComponentProp>:<ServiceReference>>
+ */
+ final void referencePropertiesUpdated(Hashtable serviceReferenceTable) {
+ // for each element in the table
+ Enumeration e = serviceReferenceTable.keys();
+ while (e.hasMoreElements()) {
+ Reference ref = (Reference) e.nextElement();
+ Hashtable serviceSubTable = (Hashtable) serviceReferenceTable.get(ref);
+ Enumeration sub = serviceSubTable.keys();
+ while (sub.hasMoreElements()) {
+ ServiceComponentProp scp = (ServiceComponentProp) sub.nextElement();
+ ServiceReference serviceReference = (ServiceReference) serviceSubTable.get(scp);
+ // get the list of instances created
+ Vector instances = scp.instances;
+ for (int i = 0; i < instances.size(); i++) {
+ ComponentInstance compInstance = (ComponentInstance) instances.elementAt(i);
+ if (compInstance != null) {
+ try {
+ scp.updatedReference(ref, compInstance, serviceReference);
+ } catch (Throwable t) {
+ Activator.log(null, LogService.LOG_ERROR, NLS.bind(Messages.ERROR_UPDATING_REFERENCE, ref.reference, compInstance.getInstance()), t);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
* registerService
*
* @param scp
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Messages.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Messages.java
index bbc3c0e..2e7d6d5 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Messages.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Messages.java
@@ -18,6 +18,8 @@ public class Messages extends NLS {
public static String ALL_COMPONENTS;
public static String ALL_REFERENCES_RESOLVED;
public static String BIND_METHOD_NOT_FOUND_OR_NOT_ACCESSIBLE;
+ public static String UPDATED_METHOD_NOT_FOUND_OR_NOT_ACCESSIBLE;
+ public static String UPDATED_METHOD_NOT_CALLED;
public static String BUNDLE_NOT_FOUND;
public static String CANNOT_BUILD_COMPONENT;
public static String CANNOT_CREATE_INSTANCE;
@@ -63,6 +65,7 @@ public class Messages extends NLS {
public static String ENABLING_ALL_BUNDLE_COMPONENTS;
public static String ENABLING_ALL_COMPONENTS;
public static String ERROR_BINDING_REFERENCE;
+ public static String ERROR_UPDATING_REFERENCE;
public static String ERROR_BUILDING_COMPONENT_INSTANCE;
public static String ERROR_CREATING_SCP;
public static String ERROR_DEACTIVATING_INSTANCE;
@@ -112,6 +115,7 @@ public class Messages extends NLS {
public static String INVALID_COMPONENT_TAG__NO_CLASS_ATTR;
public static String INVALID_OBJECT;
public static String INVALID_POLICY_ATTR;
+ public static String INVALID_POLICY_OPTION_ATTR;
public static String INVALID_PROPERTIES_TAG__INVALID_ENTRY_VALUE;
public static String INVALID_PROPERTIES_TAG__NO_ENTRY_ATTR;
public static String INVALID_PROPERTY_TAG__NO_BODY_CONTENT;
@@ -121,9 +125,11 @@ public class Messages extends NLS {
public static String INVALID_REFERENCE_TAG__BIND_ATTR_EMPTY;
public static String INVALID_REFERENCE_TAG__BIND_EQUALS_UNBIND;
public static String INVALID_REFERENCE_TAG__UNBIND_ATTR_EMPTY;
+ public static String INVALID_REFERENCE_TAG__UPDATED_ATTR_EMPTY;
public static String INVALID_SERVICE_REFERENCE;
public static String INVALID_SERVICE_TAG__NO_PROVIDE_TAG;
public static String INVALID_TAG_ACCORDING_TO_NAMESPACE1_0;
+ public static String INVALID_TAG_ACCORDING_TO_NAMESPACE1_2;
public static String INVALID_TARGET_FILTER;
public static String LIST_ALL_BUNDLE_COMPONENTS;
public static String LIST_ALL_COMPONENTS;
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Reference.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Reference.java
index c38adb8..0e61483 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Reference.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Reference.java
@@ -30,10 +30,6 @@ import org.osgi.service.log.LogService;
* @author Stoyan Boshev
* @author Pavlin Dobrev
*/
-/**
- * @author stoyan
- *
- */
public final class Reference implements org.apache.felix.scr.Reference {
public ComponentReference reference;
@@ -98,7 +94,7 @@ public final class Reference implements org.apache.felix.scr.Reference {
break;
case ComponentReference.CARDINALITY_0_N :
cardinalityLow = 0;
- cardinalityHigh = 999999999;
+ cardinalityHigh = Integer.MAX_VALUE;
break;
case ComponentReference.CARDINALITY_1_1 :
cardinalityLow = 1;
@@ -106,7 +102,7 @@ public final class Reference implements org.apache.felix.scr.Reference {
break;
case ComponentReference.CARDINALITY_1_N :
cardinalityLow = 1;
- cardinalityHigh = 999999999;
+ cardinalityHigh = Integer.MAX_VALUE;
}
}
@@ -174,7 +170,11 @@ public final class Reference implements org.apache.felix.scr.Reference {
if (policy == ComponentReference.POLICY_DYNAMIC) {
return false;
}
+ if (this.reference.policy_option == ComponentReference.POLICY_OPTION_RELUCTANT) {
+ return false;
+ }
}
+
String[] serviceNames = (String[]) referenceToBind.getProperty(Constants.OBJECTCLASS);
boolean hasName = false;
for (int i = 0; i < serviceNames.length; i++) {
@@ -186,16 +186,36 @@ public final class Reference implements org.apache.felix.scr.Reference {
if (!hasName) {
return false;
}
+
if (this.reference.bind != null) {
if (this.reference.serviceReferences.size() >= cardinalityHigh) {
- return false;
+ if (this.reference.policy_option == ComponentReference.POLICY_OPTION_RELUCTANT) {
+ return false;
+ } else if (this.reference.policy_option == ComponentReference.POLICY_OPTION_GREEDY) {
+ //check if the single bound service needs replacement with higher ranked service
+ Object currentBoundServiceReference = this.reference.serviceReferences.keys().nextElement();
+ int res = referenceToBind.compareTo(currentBoundServiceReference);
+ if (res <= 0) {
+ // bound service shall not be replaced
+ return false;
+ }
+ }
}
} else if (!dynamicBind) {
//custom case: static reference with no bind method - check its bound service references list
if (boundServiceReferences.size() >= cardinalityHigh) {
- return false;
+ if (this.reference.policy_option == ComponentReference.POLICY_OPTION_GREEDY) {
+ //check if the single bound service needs replacement with higher ranked service
+ Object currentBoundServiceReference = boundServiceReferences.elementAt(0);
+ int res = referenceToBind.compareTo(currentBoundServiceReference);
+ if (res <= 0) {
+ // bound service shall not be replaced
+ return false;
+ }
+ }
}
}
+
// check target filter
try {
Filter filter = FrameworkUtil.createFilter(target);
@@ -464,7 +484,9 @@ public final class Reference implements org.apache.felix.scr.Reference {
* @see org.apache.felix.scr.Reference#getUpdatedMethodName()
*/
public String getUpdatedMethodName() {
- // DS specification does not specify this method yet
+ if (reference.component.isNamespaceAtLeast12()) {
+ return reference.updated;
+ }
return null;
}
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Resolver.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Resolver.java
index cdcb43f..1d6bdfb 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Resolver.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Resolver.java
@@ -159,7 +159,7 @@ public final class Resolver implements WorkPerformer {
// check for a Configuration properties for this component
try {
- String filter = "(|(" + Constants.SERVICE_PID + '=' + current.name + ")(" + ConfigurationAdmin.SERVICE_FACTORYPID + '=' + current.name + "))"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ String filter = "(|(" + Constants.SERVICE_PID + '=' + current.getConfigurationPID() + ")(" + ConfigurationAdmin.SERVICE_FACTORYPID + '=' + current.getConfigurationPID() + "))"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
configs = Activator.listConfigurations(filter);
} catch (Exception e) {
Activator.log(null, LogService.LOG_ERROR, NLS.bind(Messages.CANT_LIST_CONFIGURATIONS, current.name), e);
@@ -178,7 +178,7 @@ public final class Resolver implements WorkPerformer {
} else {
// if ManagedServiceFactory
Configuration config = configs[0];
- if (config.getFactoryPid() != null && config.getFactoryPid().equals(current.name)) {
+ if (config.getFactoryPid() != null && config.getFactoryPid().equals(current.getConfigurationPID())) {
// if ComponentFactory is specified
if (current.factory != null) {
Activator.log(current.bc, LogService.LOG_ERROR, NLS.bind(Messages.REGISTERED_AS_COMPONENT_AND_MANAGED_SERVICE_FACORY, current.name), null);
@@ -305,11 +305,22 @@ public final class Resolver implements WorkPerformer {
Vector resolvedComponents = null;
switch (event.getType()) {
case ServiceEvent.REGISTERED :
+
synchronized (syncLock) {
serviceReferenceTable.put(event.getServiceReference(), Boolean.TRUE);
if (scpEnabled.isEmpty())
return; // check for any enabled configurations
+ //check for any static references with policy option "greedy" that need to be bound with this service reference
+ target = selectStaticBind(scpEnabled, event.getServiceReference());
+ }
+
+ if (target != null) {
+ //dispose instances of components with static reference that needs to be bound with the service reference
+ instanceProcess.disposeInstances((Vector) target, ComponentConstants.DEACTIVATION_REASON_REFERENCE);
+ }
+
+ synchronized (syncLock) {
resolvedComponents = getComponentsToBuild();
target = selectDynamicBind(scpEnabled, event.getServiceReference());
}
@@ -393,18 +404,35 @@ public final class Resolver implements WorkPerformer {
}
if (componentsToDispose != null) {
- instanceProcess.disposeInstances(componentsToDispose, ComponentConstants.DEACTIVATION_REASON_UNSPECIFIED);
+ instanceProcess.disposeInstances(componentsToDispose, ComponentConstants.DEACTIVATION_REASON_REFERENCE);
}
synchronized (syncLock) {
+ //check for any static references with policy option "greedy" that need to be bound with this service reference
+ componentsToDispose = selectStaticBind(scpEnabled, event.getServiceReference());
+ }
+
+ if (componentsToDispose != null) {
+ //dispose instances of components with static reference that needs to be bound with the modified service reference
+ instanceProcess.disposeInstances(componentsToDispose, ComponentConstants.DEACTIVATION_REASON_REFERENCE);
+ }
+
+ Hashtable referencesToUpdate = null;
+ synchronized (syncLock) {
// dynamic unbind
// check each satisfied scp - do we need to unbind
target = selectDynamicUnBind(scpEnabled, event.getServiceReference(), true);
+
+ //check references that need to be updated
+ referencesToUpdate = selectReferencesToUpdate(scpEnabled, event.getServiceReference());
}
if (target != null) {
instanceProcess.dynamicUnBind((Hashtable) target);
}
+ if (referencesToUpdate != null) {
+ instanceProcess.referencePropertiesUpdated(referencesToUpdate);
+ }
synchronized (syncLock) {
// dynamic bind
@@ -765,6 +793,52 @@ public final class Resolver implements WorkPerformer {
}
}
+ //Returns the components with static reference that needs to be bound with the service reference.
+ //This can happen if the static reference has policy option "greedy"
+ private Vector selectStaticBind(Vector scps, ServiceReference serviceReference) {
+ try {
+ Vector toBind = null;
+ for (int i = 0, size = scps.size(); i < size; i++) {
+ ServiceComponentProp scp = (ServiceComponentProp) scps.elementAt(i);
+ if (scp.isUnsatisfied()) {
+ //do not check disposed components
+ continue;
+ }
+ Vector references = scp.references;
+ if (references != null) {
+ for (int j = 0; j < references.size(); j++) {
+ Reference reference = (Reference) references.elementAt(j);
+ if (reference.bindNewReference(serviceReference, false)) {
+ if (toBind == null) {
+ toBind = new Vector(2);
+ }
+ toBind.addElement(reference);
+ }
+ }
+ }
+ }
+ Vector result = null;
+ Reference ref = null;
+ if (toBind != null) {
+ result = new Vector();
+ for (int i = 0; i < toBind.size(); i++) {
+ ref = (Reference) toBind.elementAt(i);
+ if (!result.contains(ref.scp)) {
+ result.addElement(ref.scp);
+ }
+ }
+ }
+
+ if (result != null && Activator.DEBUG) {
+ Activator.log.debug("Resolver.selectStaticBind(): selected = " + result.toString(), null); //$NON-NLS-1$
+ }
+ return result;
+ } catch (Throwable t) {
+ Activator.log(null, LogService.LOG_ERROR, Messages.UNEXPECTED_EXCEPTION, t);
+ return null;
+ }
+ }
+
private Vector selectStaticUnBind(Vector scpsToCheck, ServiceReference serviceReference, boolean checkSatisfied) {
try {
Vector toUnbind = null;
@@ -870,6 +944,62 @@ public final class Resolver implements WorkPerformer {
}
}
+ /**
+ * Determine which component references needs to be updated by their specified updated method due to the current service references properties change
+ *
+ * @param scps
+ * @param serviceReference
+ * @return Map of <Reference>:<Map of <ServiceComponentProp>:<ServiceReference>>
+ *
+ */
+ private Hashtable selectReferencesToUpdate(Vector scps, ServiceReference serviceReference) {
+ try {
+ if (Activator.DEBUG) {
+ Activator.log.debug("Resolver.selectReferencesToUpdate(): entered", null); //$NON-NLS-1$
+ }
+ Hashtable referencesTable = null;
+ for (int i = 0; i < scps.size(); i++) {
+ Hashtable updateSubTable = null;
+ ServiceComponentProp scp = (ServiceComponentProp) scps.elementAt(i);
+
+ if (scp.isUnsatisfied() || !scp.serviceComponent.isNamespaceAtLeast12()) {
+ //do not check deactivated components or components which are not DS 1.2 compliant
+ continue;
+ }
+ Vector references = scp.references;
+ if (references != null) {
+ for (int j = 0; j < references.size(); j++) {
+ Reference reference = (Reference) references.elementAt(j);
+ if (reference.reference.updated == null) {
+ //the reference does not have updated method specified
+ continue;
+ }
+ if (reference.isStatic() ? reference.staticUnbindReference(serviceReference) : reference.dynamicUnbindReference(serviceReference)) {
+ if (Activator.DEBUG) {
+ Activator.log.debug("Resolver.selectReferencesToUpdate(): selected for update reference " + reference.reference.name + " of component " + scp.toString(), null); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (updateSubTable == null) {
+ updateSubTable = new Hashtable(11);
+ }
+ updateSubTable.put(scp, serviceReference);
+ if (referencesTable == null) {
+ referencesTable = new Hashtable(11);
+ }
+ referencesTable.put(reference, updateSubTable);
+ }
+ }
+ }
+ }
+ if (referencesTable != null && Activator.DEBUG) {
+ Activator.log.debug("Resolver.selectReferencesToUpdate(): referencesTable is " + referencesTable.toString(), null); //$NON-NLS-1$
+ }
+ return referencesTable;
+ } catch (Throwable t) {
+ Activator.log(null, LogService.LOG_ERROR, Messages.UNEXPECTED_EXCEPTION, t);
+ return null;
+ }
+ }
+
// used by the ComponentFactoryImpl to build new Component configurations
public ServiceComponentProp mapNewFactoryComponent(ServiceComponent component, Dictionary configProperties) {
synchronized (syncLock) {
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRManager.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRManager.java
index 6ca9b2d..df69386 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRManager.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRManager.java
@@ -289,10 +289,10 @@ public class SCRManager implements ServiceListener, SynchronousBundleListener, C
//skip processing of this component - it is not interested in configuration changes
continue;
}
- String name = sc.name;
+ String name = sc.getConfigurationPID();
if (name.equals(pid) || name.equals(fpid)) {
if (name.equals(fpid) && sc.factory != null) {
- Activator.log(sc.bc, LogService.LOG_ERROR, NLS.bind(Messages.FACTORY_CONF_NOT_APPLICABLE_FOR_COMPONENT_FACTORY, name), null);
+ Activator.log(sc.bc, LogService.LOG_ERROR, NLS.bind(Messages.FACTORY_CONF_NOT_APPLICABLE_FOR_COMPONENT_FACTORY, sc.name), null);
return;
}
if (sc.enabled) {
@@ -344,7 +344,7 @@ public class SCRManager implements ServiceListener, SynchronousBundleListener, C
if (fpid == null) {
// there is only one SCP for this SC
boolean requiresRestart = true;
- if (sc.namespace11 && sc.modifyMethodName != "") { //$NON-NLS-1$
+ if (sc.isNamespaceAtLeast11() && sc.modifyMethodName != "") { //$NON-NLS-1$
ServiceComponentProp scp = sc.getServiceComponentProp();
if (scp != null && scp.isBuilt()) {
//process only built components
@@ -378,7 +378,7 @@ public class SCRManager implements ServiceListener, SynchronousBundleListener, C
}
}
boolean requiresRestart = true;
- if (sc.namespace11 && sc.modifyMethodName != "" && scp != null) { //$NON-NLS-1$
+ if (sc.isNamespaceAtLeast11() && sc.modifyMethodName != "" && scp != null) { //$NON-NLS-1$
if (scp.isBuilt()) {
//process only built components
requiresRestart = processConfigurationChange(scp, config[0]);
@@ -837,9 +837,10 @@ public class SCRManager implements ServiceListener, SynchronousBundleListener, C
continue;
}
if (sc.enabled) {
+ String componentPID = sc.getConfigurationPID();
for (int j = 0; j < configs.length; j++) {
- if (configs[j].getPid().equals(sc.name) || sc.name.equals(configs[j].getFactoryPid())) {
- if (sc.name.equals(configs[j].getFactoryPid()) && sc.factory != null) {
+ if (configs[j].getPid().equals(componentPID) || componentPID.equals(configs[j].getFactoryPid())) {
+ if (componentPID.equals(configs[j].getFactoryPid()) && sc.factory != null) {
Activator.log(sc.bc, LogService.LOG_ERROR, NLS.bind(Messages.FACTORY_CONF_NOT_APPLICABLE_FOR_COMPONENT_FACTORY, sc.name), null);
break;
}
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRUtil.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRUtil.java
index 5315dbf..05dad5a 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRUtil.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRUtil.java
@@ -71,9 +71,9 @@ public final class SCRUtil implements ObjectCreator {
/**
* Checks whether the method can be accessed according to the DS v1.1 specification rules (112.8.4 Locating Component Methods)
* @param implClass the component implementation class
- * @param currentClass the class where the method is located. This class is in the component imlpementation class hierarchy
+ * @param currentClass the class where the method is located. This class is in the component implementation class hierarchy
* @param methodToCheck the method to be checked
- * @param isComponent11 specifies whether the component is according to schema 1.1 or 1.0. Its value is true in case it is a v1.1 component
+ * @param isComponent11 specifies whether the component is according to schema 1.1 or higher. Its value is true in case the component version is v1.1 or higher
* @return true, if the method can be executed
*/
public static boolean checkMethodAccess(Class implClass, Class currentClass, Method methodToCheck, boolean isComponent11) {
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRmessages.properties b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRmessages.properties
index 2ab77c6..19d2a48 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRmessages.properties
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRmessages.properties
@@ -12,6 +12,8 @@
ALL_COMPONENTS=All Components:
ALL_REFERENCES_RESOLVED=\ \ All component references are satisfied
BIND_METHOD_NOT_FOUND_OR_NOT_ACCESSIBLE=[SCR] ComponentReference.bind(): bind method ''{0}'' is not found or it is not accessible!
+UPDATED_METHOD_NOT_FOUND_OR_NOT_ACCESSIBLE=[SCR] Updated method ''{0}'' is not found or it is not accessible!
+UPDATED_METHOD_NOT_CALLED=[SCR] Updated method of reference {0} of component {1} cannot be called because its parameter service object cannot be retrieved!
BUNDLE_NOT_FOUND=Bundle with ID {0} was not found!
CANNOT_BUILD_COMPONENT=[SCR] Cannot build component {0}
CANNOT_CREATE_INSTANCE=ServiceReg.getService(): Could not create instance of {0}
@@ -73,6 +75,7 @@ ERROR_PROCESSING_END_TAG=[SCR] Error occurred while processing end tag of XML ''
ERROR_PROCESSING_PROPERTY=[SCR - DeclarationParser.doProperty()] Error while processing property ''{0}'' in XML {1}!
ERROR_PROCESSING_START_TAG=[SCR] Error occurred while processing start tag of XML ''{0}'' in bundle {1}!
ERROR_UNBINDING_REFERENCE=[SCR] Error while dynamically unbinding reference ''{0}'' of component instance {1}
+ERROR_UPDATING_REFERENCE=[SCR] Error while updating reference ''{0}'' of component instance {1}
ERROR_UNBINDING_REFERENCE2=Exception while unbinding reference {0}
EXCEPTION_ACTIVATING_INSTANCE=[SCR] Exception while activating instance {0} of component {1}
EXCEPTION_BUILDING_COMPONENT=[SCR] Exception occurred while building component configuration of component {0}
@@ -106,6 +109,7 @@ INVALID_COMPONENT_TAG__MULTIPLE_IMPL_ATTRIBS=The ''component'' tag must have exa
INVALID_COMPONENT_TAG__NO_CLASS_ATTR=The ''implementation'' element must have ''class'' attribute set at line {0}
INVALID_OBJECT=The Object ''{0}'' is not created by the component named {1}
INVALID_POLICY_ATTR=The ''policy'' attribute has invalid value ''{0}'' at line {1}
+INVALID_POLICY_OPTION_ATTR=The ''policy-option'' attribute has invalid value ''{0}'' at line {1}
INVALID_PROPERTIES_TAG__INVALID_ENTRY_VALUE=The specified ''entry'' for the ''properties'' tag at line {0} doesn''t contain valid reference to a property file: {1}
INVALID_PROPERTIES_TAG__NO_ENTRY_ATTR=The ''properties'' tag must include ''entry'' attribute, at line {0}
INVALID_PROPERTY_TAG__NO_BODY_CONTENT=The 'property' tag must have body content if 'value' attribute is not specified\!
@@ -115,9 +119,11 @@ INVALID_PROVIDE_TAG__NO_INTERFACE_ATTR=The ''provide'' tag must have ''interface
INVALID_REFERENCE_TAG__BIND_ATTR_EMPTY=The ''reference'' tag at line {0} is invalid: ''bind'' attribute is empty!
INVALID_REFERENCE_TAG__BIND_EQUALS_UNBIND=The ''reference'' tag at line {0} is invalid: ''bind'' and ''unbind'' values are equal!
INVALID_REFERENCE_TAG__UNBIND_ATTR_EMPTY=The ''reference'' tag at line {0} is invalid: ''unbind'' attribute is empty!
+INVALID_REFERENCE_TAG__UPDATED_ATTR_EMPTY=The ''reference'' tag at line {0} is invalid: ''updated'' attribute is empty!
INVALID_SERVICE_REFERENCE=[SCR] ComponentReference.unbind(): invalid service reference {0}
INVALID_SERVICE_TAG__NO_PROVIDE_TAG=The ''service'' tag must have one ''provide'' tag set at line {0}
INVALID_TAG_ACCORDING_TO_NAMESPACE1_0=The component is according to namespace v1.0.0 and must not have ''{0}'' tag set, at line {1}
+INVALID_TAG_ACCORDING_TO_NAMESPACE1_2=The component must have namespace v1.2.0 in order to accept attribute ''{0}'' set, at line {1}
INVALID_TARGET_FILTER=invalid target filter {0}
LIST_ALL_BUNDLE_COMPONENTS=use [bundle id] to list the components of the specified bundle
LIST_ALL_COMPONENTS=Lists all components; add -c to display the complete info for each component;
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ComponentReference.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ComponentReference.java
index 6652973..7e03957 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ComponentReference.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ComponentReference.java
@@ -39,22 +39,30 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
public static final int POLICY_STATIC = 0;
public static final int POLICY_DYNAMIC = 1;
+ public static final int POLICY_OPTION_RELUCTANT = 0; // default
+ public static final int POLICY_OPTION_GREEDY = 1;
+
// --- begin: XML def
- public String name; // required
+ public String name;
public String interfaceName; // required
public int cardinality = CARDINALITY_1_1;
public int policy = POLICY_STATIC;
public String target;
public String bind;
public String unbind;
- public ServiceComponent component;
+ //defined by DS specification v1.2 - schema v1.2.0
+ public String updated;
+ public int policy_option = POLICY_OPTION_RELUCTANT;
// --- end: XML def
+ public ServiceComponent component;
// --- begin: cache
private boolean bindCached;
private boolean unbindCached;
+ private boolean updatedCached;
Method bindMethod;
Method unbindMethod;
+ Method updatedMethod;
// --- end: cache
// --- begin: model
@@ -101,7 +109,7 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
logWarning(NLS.bind(Messages.EXCEPTION_GETTING_METHOD, methodName, consumerClass.getName()), err, reference);
}
- if (method != null && SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.namespace11))
+ if (method != null && SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.isNamespaceAtLeast11()))
break;
// we need a serviceObject to keep looking, create one if necessary
@@ -157,7 +165,7 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
// this may happen on skelmir VM or in case of class loading problems
logWarning(NLS.bind(Messages.EXCEPTION_GETTING_METHOD, methodName, consumerClass.getName()), err, reference);
}
- if (method != null && SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.namespace11))
+ if (method != null && SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.isNamespaceAtLeast11()))
break;
// 3) check for bind(class.isAssignableFrom(serviceObjectClass))
@@ -171,11 +179,11 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
break;
}
}
- if (method != null && SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.namespace11))
+ if (method != null && SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.isNamespaceAtLeast11()))
break;
//implement search for bind/unbind methods according to schema v1.1.0
- if (component.namespace11) {
+ if (component.isNamespaceAtLeast11()) {
for (int i = 0; i < methods.length; i++) {
Class[] params = methods[i].getParameterTypes();
if (params.length == 2 && methods[i].getName().equals(methodName) && params[0] == interfaceClass && params[1] == Map.class) {
@@ -206,7 +214,7 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
return null;
}
- if (!SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.namespace11)) {
+ if (!SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.isNamespaceAtLeast11())) {
// if method is not visible, log error message
logMethodNotVisible(componentInstance, reference, methodName, method.getParameterTypes());
return null;
@@ -299,8 +307,9 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
return new StringBuffer(400);
}
- final void bind(Reference reference, ComponentInstance instance, ServiceReference serviceReference) throws Exception {
+ final boolean bind(Reference reference, ComponentInstance instance, ServiceReference serviceReference) throws Exception {
if (bind != null) {
+ boolean bound = false;
// DON'T rebind the same object again
synchronized (serviceReferences) {
Vector instances = (Vector) serviceReferences.get(serviceReference);
@@ -312,7 +321,7 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
if (reference.isUnary()) {
logWarning(NLS.bind(Messages.SERVICE_REFERENCE_ALREADY_BOUND, serviceReference, instance), null, reference);
}
- return;
+ return false;
} else {
instances.addElement(instance);
}
@@ -345,7 +354,7 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
//remove the component instance marked as bound
removeServiceReference(serviceReference, instance);
- return;
+ return false;
}
}
@@ -365,6 +374,7 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
try {
bindMethod.invoke(instance.getInstance(), params);
+ bound = true;
} catch (Throwable t) {
logError(NLS.bind(Messages.ERROR_BINDING_REFERENCE, this), t, reference);
//remove the component instance marked as bound
@@ -380,7 +390,9 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
// could be also circularity break
logWarning(NLS.bind(Messages.BIND_METHOD_NOT_FOUND_OR_NOT_ACCESSIBLE, bind), null, reference);
}
+ return bound;
}
+ return false;
}
private void removeServiceReference(ServiceReference serviceReference, ComponentInstance instance) {
@@ -491,9 +503,78 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
}
}
+ final void updated(Reference reference, ComponentInstance instance, ServiceReference serviceReference) {
+ if (updated != null) {
+ synchronized (serviceReferences) {
+ Vector instances = (Vector) serviceReferences.get(serviceReference);
+ if (instances == null || !instances.contains(instance)) {
+ //this instance is not bound to the passed service reference
+ return;
+ }
+ }
+ // retrieve the method from cache
+ if (!updatedCached) {
+ updatedMethod = getMethod((ComponentInstanceImpl) instance, reference, updated, serviceReference);
+ // updatedMethod can be null in case of circularity
+ if (updatedMethod != null) {
+ updatedCached = true;
+ }
+ }
+ // invoke the method
+ if (updatedMethod != null) {
+ Object methodParam = null;
+ Class[] paramTypes = updatedMethod.getParameterTypes();
+ if (paramTypes.length == 1 && paramTypes[0].equals(ServiceReference.class)) {
+ methodParam = serviceReference;
+ } else {
+ // bindedServices is filled by the getMethod function
+ methodParam = ((ComponentInstanceImpl) instance).bindedServices.get(serviceReference);
+ if (methodParam == null) {
+ methodParam = InstanceProcess.staticRef.getService(reference, serviceReference);
+ if (methodParam != null) {
+ ((ComponentInstanceImpl) instance).bindedServices.put(serviceReference, methodParam);
+ }
+ }
+ if (methodParam == null) {
+ // cannot get serviceObject because of circularity
+ Activator.log(null, LogService.LOG_WARNING, NLS.bind(Messages.UPDATED_METHOD_NOT_CALLED, name, component.name), null);
+ return;
+ }
+ }
+
+ Object[] params = null;
+ if (paramTypes.length == 1) {
+ params = SCRUtil.getObjectArray();
+ params[0] = methodParam;
+ } else {
+ //this is the case where we have 2 parameters: a service object and a Map, holding the service properties
+ HashMap map = new HashMap();
+ String[] keys = serviceReference.getPropertyKeys();
+ for (int i = 0; i < keys.length; i++) {
+ map.put(keys[i], serviceReference.getProperty(keys[i]));
+ }
+ params = new Object[] {methodParam, map};
+ }
+
+ try {
+ updatedMethod.invoke(instance.getInstance(), params);
+ } catch (Throwable t) {
+ logError(NLS.bind(Messages.ERROR_UPDATING_REFERENCE, this, instance.getInstance()), t, reference);
+ } finally {
+ if (params.length == 1) {
+ SCRUtil.release(params);
+ }
+ }
+ } else {
+ // could be also circularity break
+ logWarning(NLS.bind(Messages.UPDATED_METHOD_NOT_FOUND_OR_NOT_ACCESSIBLE, updated), null, reference);
+ }
+ }
+ }
+
public final void dispose() {
- bindCached = unbindCached = false;
- bindMethod = unbindMethod = null;
+ bindCached = unbindCached = updatedCached = false;
+ bindMethod = unbindMethod = updatedMethod = null;
serviceReferences = null;
}
@@ -510,6 +591,16 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
case POLICY_STATIC :
buffer.append("static"); //$NON-NLS-1$
}
+ if (component.isNamespaceAtLeast12()) {
+ buffer.append(", policy-option = "); //$NON-NLS-1$
+ switch (policy_option) {
+ case POLICY_OPTION_RELUCTANT :
+ buffer.append("reluctant"); //$NON-NLS-1$
+ break;
+ case POLICY_OPTION_GREEDY :
+ buffer.append("greedy"); //$NON-NLS-1$
+ }
+ }
buffer.append(", cardinality = "); //$NON-NLS-1$
switch (cardinality) {
@@ -528,6 +619,9 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
buffer.append(", target = ").append(target); //$NON-NLS-1$
buffer.append(", bind = ").append(bind); //$NON-NLS-1$
buffer.append(", unbind = ").append(unbind); //$NON-NLS-1$
+ if (component.isNamespaceAtLeast12()) {
+ buffer.append(", updated = ").append(updated); //$NON-NLS-1$
+ }
buffer.append("]"); //$NON-NLS-1$
return buffer.toString();
}
@@ -565,8 +659,20 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
out.writeBoolean(flag);
if (flag)
out.writeUTF(unbind);
+
+ // DS 1.2 support
+ out.writeBoolean(component.isNamespaceAtLeast12());
+ if (component.isNamespaceAtLeast12()) {
+ flag = updated != null;
+ out.writeBoolean(flag);
+ if (flag)
+ out.writeUTF(updated);
+
+ out.writeInt(policy_option);
+ }
} catch (Exception e) {
Activator.log(null, LogService.LOG_ERROR, Messages.ERROR_WRITING_OBJECT, e);
+ throw e;
}
}
@@ -599,8 +705,19 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
flag = in.readBoolean();
if (flag)
unbind = in.readUTF();
+
+ // DS 1.2 support
+ flag = in.readBoolean();
+ if (flag) {
+ //This is a DS 1.2 component
+ flag = in.readBoolean();
+ if (flag)
+ updated = in.readUTF();
+ policy_option = in.readInt();
+ }
} catch (Exception e) {
Activator.log(null, LogService.LOG_ERROR, Messages.ERROR_READING_OBJECT, e);
+ throw e;
}
}
@@ -674,7 +791,9 @@ public class ComponentReference implements Externalizable, org.apache.felix.scr.
* @see org.apache.felix.scr.Reference#getUpdatedMethodName()
*/
public String getUpdatedMethodName() {
- // DS specification does not specify this method yet
+ if (component.isNamespaceAtLeast12()) {
+ return updated;
+ }
return null;
}
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/DeclarationParser.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/DeclarationParser.java
index 86444a8..8f4f295 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/DeclarationParser.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/DeclarationParser.java
@@ -35,6 +35,7 @@ public class DeclarationParser implements ExTagListener {
private static final String XMLNS_1_0 = "http://www.osgi.org/xmlns/scr/v1.0.0"; //$NON-NLS-1$
private static final String XMLNS_1_1 = "http://www.osgi.org/xmlns/scr/v1.1.0"; //$NON-NLS-1$
+ private static final String XMLNS_1_2 = "http://www.osgi.org/xmlns/scr/v1.2.0"; //$NON-NLS-1$
private static final String ATTR_XMLNS = "xmlns"; //$NON-NLS-1$
private static final String COMPONENT_TAG_NAME = "component"; //$NON-NLS-1$
@@ -49,6 +50,8 @@ public class DeclarationParser implements ExTagListener {
private static final String ATTR_ACTIVATE = "activate"; //$NON-NLS-1$
private static final String ATTR_DEACTIVATE = "deactivate"; //$NON-NLS-1$
private static final String ATTR_MODIFIED = "modified"; //$NON-NLS-1$
+ //component attributes according to schema v1.2
+ private static final String ATTR_CONFIGURATION_PID = "configuration-pid"; //$NON-NLS-1$
private static final String TAG_IMPLEMENTATION = "implementation"; //$NON-NLS-1$
private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
@@ -71,6 +74,9 @@ public class DeclarationParser implements ExTagListener {
private static final String ATTR_TARGET = "target"; //$NON-NLS-1$
private static final String ATTR_BIND = "bind"; //$NON-NLS-1$
private static final String ATTR_UNBIND = "unbind"; //$NON-NLS-1$
+ //reference attributes according to schema v1.2
+ private static final String ATTR_UPDATED = "updated"; //$NON-NLS-1$
+ private static final String ATTR_POLICY_OPTION = "policy-option"; //$NON-NLS-1$
/** Constant for String property type */
public static final int STRING = 1;
@@ -202,7 +208,7 @@ public class DeclarationParser implements ExTagListener {
// if component factory then immediate by default is false
currentComponent.setImmediate(currentComponent.serviceInterfaces == null);
}
- currentComponent.validate(tag.getLine(), isNamespace11(tag.getName()));
+ currentComponent.validate(tag.getLine(), getNamespace(tag.getName()));
if (components == null) {
components = new Vector(1, 1);
}
@@ -268,11 +274,6 @@ public class DeclarationParser implements ExTagListener {
private void doReference(Tag tag) throws InvalidSyntaxException {
String name = tag.getAttribute(ATTR_NAME);
- // if (name == null) {
- // IllegalArgumentException e = new IllegalArgumentException("The 'reference' tag must have 'name' attribute, at line " + tag.getLine());
- // throw e;
- // }
-
String iface = tag.getAttribute(ATTR_INTERFACE);
if (iface == null) {
IllegalArgumentException e = new IllegalArgumentException(NLS.bind(Messages.NO_INTERFACE_ATTR_IN_REFERENCE_TAG, Integer.toString(tag.getLine())));
@@ -294,10 +295,10 @@ public class DeclarationParser implements ExTagListener {
int policy = ComponentReference.POLICY_STATIC; // default
if (policyS != null) {
// verify the policy attribute values
- if (policyS.equals("static")) { //$NON-NLS-1$
- policy = ComponentReference.POLICY_STATIC;
- } else if (policyS.equals("dynamic")) { //$NON-NLS-1$
+ if (policyS.equals("dynamic")) { //$NON-NLS-1$
policy = ComponentReference.POLICY_DYNAMIC;
+ } else if (policyS.equals("static")) { //$NON-NLS-1$
+ policy = ComponentReference.POLICY_STATIC;
} else {
IllegalArgumentException e = new IllegalArgumentException(NLS.bind(Messages.INVALID_POLICY_ATTR, policyS, Integer.toString(tag.getLine())));
throw e;
@@ -321,6 +322,35 @@ public class DeclarationParser implements ExTagListener {
throw e;
}
+ String updated = tag.getAttribute(ATTR_UPDATED);
+ if (updated != null && updated.equals("")) { //$NON-NLS-1$
+ IllegalArgumentException e = new IllegalArgumentException(NLS.bind(Messages.INVALID_REFERENCE_TAG__UPDATED_ATTR_EMPTY, Integer.toString(tag.getLine())));
+ throw e;
+ }
+
+ String policyOption = tag.getAttribute(ATTR_POLICY_OPTION);
+ int policyOptionProcessed = ComponentReference.POLICY_OPTION_RELUCTANT; //default
+ if (policyOption != null) {
+ if (policyOption.equals("greedy")) { //$NON-NLS-1$
+ policyOptionProcessed = ComponentReference.POLICY_OPTION_GREEDY;
+ } else if (policyOption.equals("reluctant")) { //$NON-NLS-1$
+ policyOptionProcessed = ComponentReference.POLICY_OPTION_RELUCTANT;
+ } else {
+ IllegalArgumentException e = new IllegalArgumentException(NLS.bind(Messages.INVALID_POLICY_OPTION_ATTR, policyOption, Integer.toString(tag.getLine())));
+ throw e;
+ }
+ }
+
+ //check if the current component namespace is suitable for the latest reference attributes
+ if (!isNamespaceAtLeast12(closeTag)) {
+ if (updated != null) {
+ throw new IllegalArgumentException(NLS.bind(Messages.INVALID_TAG_ACCORDING_TO_NAMESPACE1_2, ATTR_UPDATED, Integer.toString(tag.getLine())));
+ }
+ if (policyOption != null) {
+ throw new IllegalArgumentException(NLS.bind(Messages.INVALID_TAG_ACCORDING_TO_NAMESPACE1_2, ATTR_POLICY_OPTION, Integer.toString(tag.getLine())));
+ }
+ }
+
// the reference is autoadded in the ServiceComponent's list of
// references
// in its constructor
@@ -330,8 +360,9 @@ public class DeclarationParser implements ExTagListener {
ref.cardinality = cardinality;
ref.policy = policy;
ref.bind = bind;
-
ref.unbind = unbind;
+ ref.updated = updated;
+ ref.policy_option = policyOptionProcessed;
ref.target = tag.getAttribute(ATTR_TARGET);
// validate the target filter
if (ref.target != null) {
@@ -537,7 +568,7 @@ public class DeclarationParser implements ExTagListener {
currentComponent.immediate = Boolean.valueOf(tmp).booleanValue();
immediateSet = true;
}
- if (isNamespace11(tagName)) {
+ if (isNamespaceAtLeast11(tagName)) {
//processing attribute configuration-policy
tmp = tag.getAttribute(ATTR_CONF_POLICY);
if (tmp != null && tmp.length() == 0) {
@@ -586,6 +617,22 @@ public class DeclarationParser implements ExTagListener {
throw new IllegalArgumentException(NLS.bind(Messages.INVALID_TAG_ACCORDING_TO_NAMESPACE1_0, ATTR_MODIFIED, Integer.toString(tag.getLine())));
}
}
+
+ if (isNamespaceAtLeast12(tagName)) {
+ //processing attribute configuration-policy
+ tmp = tag.getAttribute(ATTR_CONFIGURATION_PID);
+ if (tmp != null && tmp.length() == 0) {
+ tmp = null;
+ }
+ if (tmp != null) {
+ currentComponent.configurationPID = tmp;
+ }
+ } else {
+ if (tag.getAttribute(ATTR_CONFIGURATION_PID) != null) {
+ throw new IllegalArgumentException(NLS.bind(Messages.INVALID_TAG_ACCORDING_TO_NAMESPACE1_2, ATTR_CONFIGURATION_PID, Integer.toString(tag.getLine())));
+ }
+ }
+
}
private boolean isCorrectComponentTag(String tagName) {
@@ -596,10 +643,10 @@ public class DeclarationParser implements ExTagListener {
}
String namespace = getCurrentNamespace(qualifier);
if (!rootPassed) { // this is the root element
- return namespace.length() == 0 || namespace.equals(XMLNS_1_0) || namespace.equals(XMLNS_1_1);
- } else { // not a root element
- return namespace.equals(XMLNS_1_0) || namespace.equals(XMLNS_1_1);
+ return namespace.length() == 0 || namespace.equals(XMLNS_1_1) || namespace.equals(XMLNS_1_2) || namespace.equals(XMLNS_1_0);
}
+ // not a root element
+ return namespace.equals(XMLNS_1_1) || namespace.equals(XMLNS_1_2) || namespace.equals(XMLNS_1_0);
}
/**
@@ -736,14 +783,35 @@ public class DeclarationParser implements ExTagListener {
}
}
- private boolean isNamespace11(String tagName) {
+ private int getNamespace(String tagName) {
String qualifier = getNamespaceQualifier(tagName);
String namespace = getCurrentNamespace(qualifier);
if (!rootPassed) { // this is the root element
- return namespace.length() != 0 && namespace.equals(XMLNS_1_1);
- } else { // not a root element
- return namespace.equals(XMLNS_1_1);
+ if (namespace.length() == 0) {
+ return ServiceComponent.NAMESPACE_1_0;
+ }
}
+ // not a root element
+ if (namespace.equals(XMLNS_1_0)) {
+ return ServiceComponent.NAMESPACE_1_0;
+ } else if (namespace.equals(XMLNS_1_1)) {
+ return ServiceComponent.NAMESPACE_1_1;
+ } else if (namespace.equals(XMLNS_1_2)) {
+ return ServiceComponent.NAMESPACE_1_2;
+ }
+
+ //namespace is not known
+ return -1;
+ }
+
+ private boolean isNamespaceAtLeast11(String tagName) {
+ int namespace = getNamespace(tagName);
+ return (namespace >= ServiceComponent.NAMESPACE_1_1);
+ }
+
+ private boolean isNamespaceAtLeast12(String tagName) {
+ int namespace = getNamespace(tagName);
+ return (namespace >= ServiceComponent.NAMESPACE_1_2);
}
private void processNamespacesEnter(Tag tag) {
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponent.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponent.java
index f059617..1cd041c 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponent.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponent.java
@@ -38,9 +38,14 @@ import org.osgi.service.log.LogService;
*/
public class ServiceComponent implements Externalizable, Component {
- public static String CONF_POLICY_OPTIONAL = "optional"; //$NON-NLS-1$
- public static String CONF_POLICY_REQUIRE = "require"; //$NON-NLS-1$
- public static String CONF_POLICY_IGNORE = "ignore"; //$NON-NLS-1$
+ //constants defining possible SCR namespaces XML schemas
+ public static final int NAMESPACE_1_0 = 0;
+ public static final int NAMESPACE_1_1 = 1;
+ public static final int NAMESPACE_1_2 = 2;
+
+ public static final String CONF_POLICY_OPTIONAL = "optional"; //$NON-NLS-1$
+ public static final String CONF_POLICY_REQUIRE = "require"; //$NON-NLS-1$
+ public static final String CONF_POLICY_IGNORE = "ignore"; //$NON-NLS-1$
public Vector componentProps = null;
@@ -54,6 +59,9 @@ public class ServiceComponent implements Externalizable, Component {
String deactivateMethodName = "deactivate"; //$NON-NLS-1$
public String modifyMethodName = ""; //$NON-NLS-1$
+ //Since DS 1.2
+ public String configurationPID;
+
// service
public Vector serviceInterfaces; // all strings
public String[] provides; // the same as above, but as String[]
@@ -63,7 +71,7 @@ public class ServiceComponent implements Externalizable, Component {
public boolean autoenable = true;
public boolean immediate = false;
- public boolean namespace11 = false;
+ public int namespace = NAMESPACE_1_0;
// --- end: XML def
// --- begin: cache
@@ -114,7 +122,7 @@ public class ServiceComponent implements Externalizable, Component {
Class clazz = instance != null ? instance.getClass() : null;
while (method == null && clazz != null) {
- if (namespace11) {
+ if (isNamespaceAtLeast11()) {
Method[] methods = clazz.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals(methodName)) {
@@ -199,7 +207,7 @@ public class ServiceComponent implements Externalizable, Component {
void activate(Object instance, ComponentContext context) throws ComponentException {
try {
- if (namespace11) {
+ if (isNamespaceAtLeast11()) {
if (!activateCached) {
activateCached = true;
activateMethod = getMethod(instance, activateMethodName, true);
@@ -272,7 +280,7 @@ public class ServiceComponent implements Externalizable, Component {
void modified(Object instance, ComponentContext context) throws ComponentException {
try {
- if (namespace11) {
+ if (isNamespaceAtLeast11()) {
if (!modifyCached) {
modifyCached = true;
if (modifyMethodName != "") { //$NON-NLS-1$
@@ -323,7 +331,7 @@ public class ServiceComponent implements Externalizable, Component {
void deactivate(Object instance, ComponentContext context, int deactivateReason) {
try {
- if (namespace11) {
+ if (isNamespaceAtLeast11()) {
if (!deactivateCached) {
deactivateCached = true;
deactivateMethod = getMethod(instance, deactivateMethodName, false);
@@ -388,28 +396,35 @@ public class ServiceComponent implements Externalizable, Component {
}
/**
- * this method is called from the xml parser to validate the component once
+ * This method is called from the XML parser to validate the component once
* it is fully loaded!
*
* @param line
* the line at which the the component definition ends
- * @param namespace11 specify whether the namespace of the component is according to XML SCR schema v1.1
+ * @param _namespace specify the namespace of the component according to XML SCR schema
*/
- void validate(int line, boolean namespace11) {
+ void validate(int line, int _namespace) {
// System.out.println("Validating component " + name + " with namespace " + (namespace11 ? "1.1" : "1.0"));
+ this.namespace = _namespace;
if (name == null) {
- if (namespace11) {
+ if (isNamespaceAtLeast11()) {
name = implementation;
} else {
throw new IllegalArgumentException(NLS.bind(Messages.NO_NAME_ATTRIBUTE, Integer.toString(line)));
}
}
- if (namespace11) {
+ if (isNamespaceAtLeast11()) {
if (!(configurationPolicy == CONF_POLICY_OPTIONAL || configurationPolicy == CONF_POLICY_REQUIRE || configurationPolicy == CONF_POLICY_IGNORE)) {
throw new IllegalArgumentException(NLS.bind(Messages.INCORRECT_ACTIVATION_POLICY, name, Integer.toString(line)));
}
}
+ if (isNamespaceAtLeast12()) {
+ if (configurationPID == null) {
+ configurationPID = name;
+ }
+ }
+
if (implementation == null) {
throw new IllegalArgumentException(NLS.bind(Messages.NO_IMPLEMENTATION_ATTRIBUTE, name, Integer.toString(line)));
}
@@ -435,13 +450,13 @@ public class ServiceComponent implements Externalizable, Component {
for (int i = 0; i < references.size(); i++) {
ComponentReference r = (ComponentReference) references.elementAt(i);
if (r.name == null) {
- if (namespace11) {
+ if (isNamespaceAtLeast11()) {
r.name = r.interfaceName;
} else {
throw new IllegalArgumentException(NLS.bind(Messages.COMPONENT_HAS_ILLEGAL_REFERENCE, new Object[] {name, Integer.toString(line), r}));
}
}
- if (r.interfaceName == null || r.name.equals("") || r.interfaceName.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$
+ if (r.interfaceName == null || r.name.length() == 0 || r.interfaceName.length() == 0) {
throw new IllegalArgumentException(NLS.bind(Messages.COMPONENT_HAS_ILLEGAL_REFERENCE, new Object[] {name, Integer.toString(line), r}));
}
for (int j = i + 1; j < references.size(); j++) {
@@ -459,8 +474,6 @@ public class ServiceComponent implements Externalizable, Component {
serviceInterfaces.copyInto(provides);
}
- this.namespace11 = namespace11;
-
// make sure that the component will get automatically enabled!
enabled = autoenable;
}
@@ -520,6 +533,13 @@ public class ServiceComponent implements Externalizable, Component {
return serviceInterfaces != null && serviceInterfaces.contains(interfaceName);
}
+ public String getConfigurationPID() {
+ if (isNamespaceAtLeast12()) {
+ return configurationPID;
+ }
+ return name;
+ }
+
/*
* (non-Javadoc)
*
@@ -529,12 +549,15 @@ public class ServiceComponent implements Externalizable, Component {
StringBuffer buffer = new StringBuffer();
buffer.append("Component["); //$NON-NLS-1$
buffer.append("\n\tname = ").append(name); //$NON-NLS-1$
- if (namespace11) {
+ if (isNamespaceAtLeast11()) {
buffer.append("\n\tactivate = ").append(activateMethodName); //$NON-NLS-1$
buffer.append("\n\tdeactivate = ").append(deactivateMethodName); //$NON-NLS-1$
buffer.append("\n\tmodified = ").append(modifyMethodName); //$NON-NLS-1$
buffer.append("\n\tconfiguration-policy = ").append(configurationPolicy); //$NON-NLS-1$
}
+ if (isNamespaceAtLeast12()) {
+ buffer.append("\n\tconfiguration-pid = ").append(configurationPID); //$NON-NLS-1$
+ }
buffer.append("\n\tfactory = ").append(factory); //$NON-NLS-1$
buffer.append("\n\tautoenable = ").append(autoenable); //$NON-NLS-1$
buffer.append("\n\timmediate = ").append(immediate); //$NON-NLS-1$
@@ -617,8 +640,8 @@ public class ServiceComponent implements Externalizable, Component {
dictionary.writeObject(out);
}
- out.writeBoolean(namespace11);
- if (namespace11) {
+ out.writeInt(namespace);
+ if (isNamespaceAtLeast11()) {
if (configurationPolicy == CONF_POLICY_OPTIONAL) {
//this is the default value. Do not write it. Just add a mark
out.writeBoolean(false);
@@ -648,8 +671,17 @@ public class ServiceComponent implements Externalizable, Component {
out.writeUTF(modifyMethodName);
}
}
+ if (isNamespaceAtLeast12()) {
+ if (configurationPID == name) {
+ out.writeBoolean(false);
+ } else {
+ out.writeBoolean(true);
+ out.writeUTF(configurationPID);
+ }
+ }
} catch (Exception e) {
Activator.log(null, LogService.LOG_ERROR, Messages.ERROR_WRITING_OBJECT, e);
+ throw e;
}
}
@@ -713,8 +745,8 @@ public class ServiceComponent implements Externalizable, Component {
}
properties = props;
}
- namespace11 = in.readBoolean();
- if (namespace11) {
+ namespace = in.readInt();
+ if (isNamespaceAtLeast11()) {
flag = in.readBoolean();
if (flag) {
configurationPolicy = in.readUTF();
@@ -738,8 +770,17 @@ public class ServiceComponent implements Externalizable, Component {
if (flag)
modifyMethodName = in.readUTF();
}
+ if (isNamespaceAtLeast12()) {
+ flag = in.readBoolean();
+ if (flag) {
+ configurationPID = in.readUTF();
+ } else {
+ configurationPID = name;
+ }
+ }
} catch (Exception e) {
Activator.log(null, LogService.LOG_ERROR, Messages.ERROR_READING_OBJECT, e);
+ throw e;
}
}
@@ -780,6 +821,14 @@ public class ServiceComponent implements Externalizable, Component {
return null;
}
+ public boolean isNamespaceAtLeast11() {
+ return namespace >= NAMESPACE_1_1;
+ }
+
+ public boolean isNamespaceAtLeast12() {
+ return namespace >= NAMESPACE_1_2;
+ }
+
public boolean isImmediate() {
return immediate;
}
@@ -850,7 +899,7 @@ public class ServiceComponent implements Externalizable, Component {
}
public String getModified() {
- if (!namespace11) {
+ if (!isNamespaceAtLeast11()) {
return null;
}
return modifyMethodName;
@@ -895,14 +944,14 @@ public class ServiceComponent implements Externalizable, Component {
}
public boolean isActivateDeclared() {
- if (!namespace11) {
+ if (!isNamespaceAtLeast11()) {
return false;
}
return activateMethodDeclared;
}
public boolean isDeactivateDeclared() {
- if (!namespace11) {
+ if (!isNamespaceAtLeast11()) {
return false;
}
return deactivateMethodDeclared;
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponentProp.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponentProp.java
index d6d444a..49509e1 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponentProp.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponentProp.java
@@ -223,6 +223,7 @@ public class ServiceComponentProp implements Component, PrivilegedExceptionActio
if (ref.reference.bindMethod == null || ccError != null || !ref.isBound()) {
//the bind method is not found and called for some reason or it has thrown exception
if (ref.reference.cardinality == ComponentReference.CARDINALITY_1_1 || ref.reference.cardinality == ComponentReference.CARDINALITY_1_N) {
+ Activator.log(null, LogService.LOG_WARNING, "Could not bind a reference of component " + name + ". The reference is: " + ref.reference, null); //$NON-NLS-1$ //$NON-NLS-2$
//unbind the already bound references
for (int j = i - 1; j >= 0; j--) {
ref = (Reference) references.elementAt(i);
@@ -427,9 +428,13 @@ public class ServiceComponentProp implements Component, PrivilegedExceptionActio
case ComponentReference.CARDINALITY_1_1 :
case ComponentReference.CARDINALITY_0_1 :
for (int i = 0; i < serviceReferences.length; i++) {
- reference.reference.bind(reference, componentInstance, serviceReferences[i]);
- if (reference.reference.bindMethod != null) {
- //bind method for this reference was found
+ ServiceReference oldBoundService = (reference.reference.policy_option == ComponentReference.POLICY_OPTION_GREEDY && reference.reference.serviceReferences.size() > 0 ? (ServiceReference) reference.reference.serviceReferences.keys().nextElement() : null);
+ boolean bound = reference.reference.bind(reference, componentInstance, serviceReferences[i]);
+ if (bound) {
+ if (oldBoundService != null) {
+ //unbind the previous bound service reference in case we are handling service reference update due to greedy policy option
+ reference.reference.unbind(reference, componentInstance, oldBoundService);
+ }
break;
}
}
@@ -638,6 +643,20 @@ public class ServiceComponentProp implements Component, PrivilegedExceptionActio
ref.reference.unbind(ref, instance, serviceReference);
}
+ /**
+ * Call the updated method for this Reference
+ *
+ * @param ref the reference
+ * @param instance the component instance
+ * @param serviceReference the service reference which properties have changed
+ */
+ public void updatedReference(Reference ref, ComponentInstance instance, ServiceReference serviceReference) {
+ if (Activator.DEBUG) {
+ Activator.log.debug("ServiceComponentProp.updatedReference(): component = " + name + ", reference = " + ref.reference.name, null); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ ref.reference.updated(ref, instance, serviceReference);
+ }
+
// -- begin helper methods
/**
* Initialize Properties for this Component
@@ -850,7 +869,7 @@ public class ServiceComponentProp implements Component, PrivilegedExceptionActio
}
public String getModified() {
- if (!serviceComponent.namespace11) {
+ if (!serviceComponent.isNamespaceAtLeast11()) {
return null;
}
return serviceComponent.modifyMethodName;
@@ -874,14 +893,14 @@ public class ServiceComponentProp implements Component, PrivilegedExceptionActio
}
public boolean isActivateDeclared() {
- if (!serviceComponent.namespace11) {
+ if (!serviceComponent.isNamespaceAtLeast11()) {
return false;
}
return serviceComponent.activateMethodDeclared;
}
public boolean isDeactivateDeclared() {
- if (!serviceComponent.namespace11) {
+ if (!serviceComponent.isNamespaceAtLeast11()) {
return false;
}
return serviceComponent.deactivateMethodDeclared;
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/storage/file/FileStorage.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/storage/file/FileStorage.java
index dbad5fa..2886c0b 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/storage/file/FileStorage.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/storage/file/FileStorage.java
@@ -89,23 +89,19 @@ public class FileStorage extends ComponentStorage {
String lastModifiedValue = (String) data.get(getPath(dbBundlePath));
if (lastModifiedValue == null) {
- components = parseXMLDeclaration(bundle, dsHeader);
- if (components != null && components.size() != 0) {
- data.put(getPath(dbBundlePath), "" + lastModified); //$NON-NLS-1$
- saveComponentDefinitions(components, bundle.getBundleId());
- }
-
+ components = processXMLDeclarations(bundle, dsHeader, dbBundlePath, lastModified);
} else {
long dbLastModified = Long.parseLong(lastModifiedValue);
if (lastModified != dbLastModified) {
- components = parseXMLDeclaration(bundle, dsHeader);
- if (components != null && components.size() != 0) {
- data.put(getPath(dbBundlePath), "" + lastModified); //$NON-NLS-1$
- saveComponentDefinitions(components, bundle.getBundleId());
- }
-
+ components = processXMLDeclarations(bundle, dsHeader, dbBundlePath, lastModified);
} else {
- components = loadComponentsFromDB(bundle);
+ try {
+ components = loadComponentsFromDB(bundle);
+ } catch (Throwable t) {
+ Activator.log(null, LogService.LOG_ERROR, Messages.ERROR_LOADING_COMPONENTS, t);
+ //backup plan - parse the bundle's component XML declarations
+ components = processXMLDeclarations(bundle, dsHeader, dbBundlePath, lastModified);
+ }
}
}
return components;
@@ -115,30 +111,34 @@ public class FileStorage extends ComponentStorage {
}
}
+ private Vector processXMLDeclarations(Bundle bundle, String dsHeader, String[] dbBundlePath, long lastModified) throws Exception {
+ Vector components = parseXMLDeclaration(bundle, dsHeader);
+ if (components != null && components.size() != 0) {
+ data.put(getPath(dbBundlePath), "" + lastModified); //$NON-NLS-1$
+ saveComponentDefinitions(components, bundle.getBundleId());
+ }
+ return components;
+ }
+
private Vector loadComponentsFromDB(Bundle bundle) throws Exception {
- try {
- String[] dbCompPath = new String[] {null, "COMPONENTS"}; //$NON-NLS-1$
- ServiceComponent currentComponent = null;
- long bundleId = bundle.getBundleId();
- dbCompPath[0] = String.valueOf(bundleId);
- DBObject value = new DBObject();
- byte[] byteArr = (byte[]) data.get(getPath(dbCompPath));
- ByteArrayInputStream tmpIn = new ByteArrayInputStream(byteArr);
- value.readObject(tmpIn);
- Vector components = value.components;
- if (components == null) {
- return null;
- }
- for (int i = 0; i < components.size(); i++) {
- currentComponent = (ServiceComponent) components.elementAt(i);
- currentComponent.bundle = bundle;
- currentComponent.bc = bundle.getBundleContext();
- }
- return components;
- } catch (Throwable t) {
- Activator.log(null, LogService.LOG_ERROR, Messages.ERROR_LOADING_COMPONENTS, t);
+ String[] dbCompPath = new String[] {null, "COMPONENTS"}; //$NON-NLS-1$
+ ServiceComponent currentComponent = null;
+ long bundleId = bundle.getBundleId();
+ dbCompPath[0] = String.valueOf(bundleId);
+ DBObject value = new DBObject();
+ byte[] byteArr = (byte[]) data.get(getPath(dbCompPath));
+ ByteArrayInputStream tmpIn = new ByteArrayInputStream(byteArr);
+ value.readObject(tmpIn);
+ Vector components = value.components;
+ if (components == null) {
+ return null;
+ }
+ for (int i = 0; i < components.size(); i++) {
+ currentComponent = (ServiceComponent) components.elementAt(i);
+ currentComponent.bundle = bundle;
+ currentComponent.bc = bundle.getBundleContext();
}
- return null;
+ return components;
}
public void deleteComponentDefinitions(long bundleID) {