Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsboshev2009-04-27 13:57:37 +0000
committersboshev2009-04-27 13:57:37 +0000
commit19f95122eb41299dc4aec7e82e45a3293e9ac416 (patch)
tree144431b9d6995d93f7cc5849c35ad5b827c0fe04 /bundles
parent26caae2241dbf56f8810d0301509e4e62048faa0 (diff)
downloadrt.equinox.bundles-19f95122eb41299dc4aec7e82e45a3293e9ac416.tar.gz
rt.equinox.bundles-19f95122eb41299dc4aec7e82e45a3293e9ac416.tar.xz
rt.equinox.bundles-19f95122eb41299dc4aec7e82e45a3293e9ac416.zip
Bug 272599. [ds] Add support for new modified attribute on component elementv20090427-1030
Diffstat (limited to 'bundles')
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/InstanceProcess.java45
-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.java102
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/SCRManager.java143
-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/DeclarationParser.java10
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponent.java23
-rw-r--r--bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/model/ServiceComponentProp.java231
8 files changed, 492 insertions, 74 deletions
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 9202128f2..ef0a68fbb 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
@@ -459,7 +459,6 @@ public class InstanceProcess {
* the component instance created by ComponentFactoryImpl!
*/
private void registerService(ServiceComponentProp scp, boolean factory, ComponentInstanceImpl ci) {
-
// register the service using a ServiceFactory
ServiceRegistration reg = null;
Object service;
@@ -474,18 +473,7 @@ public class InstanceProcess {
service = new ServiceReg(scp, ci);
}
- //remove the private properties from the component properties before registering as service
- Hashtable props = scp.getProperties();
- Hashtable publicProps = (Hashtable) props.clone();
- Enumeration keys = props.keys();
- while (keys.hasMoreElements()) {
- String key = (String) keys.nextElement();
- if (key.startsWith(".")) { //$NON-NLS-1$
- publicProps.remove(key);
- }
- }
-
- reg = scp.bc.registerService(scp.serviceComponent.provides, service, publicProps);
+ reg = scp.bc.registerService(scp.serviceComponent.provides, service, scp.getPublicServiceProperties());
if (Activator.DEBUG) {
Activator.log.debug("InstanceProcess.registerService(): " + scp.name + " registered as " + ((factory) ? "*factory*" : "*service*"), null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
@@ -607,6 +595,37 @@ public class InstanceProcess {
}
}
+ public void modifyComponent(ServiceComponentProp scp, Dictionary newProps) throws ComponentException {
+ if (Activator.DEBUG) {
+ Activator.log.debug(NLS.bind(Messages.MODIFYING_COMPONENT, scp.name), null);
+ }
+ getLock();
+ long start = 0l;
+ try {
+ if (Activator.PERF) {
+ start = System.currentTimeMillis();
+ Activator.log.info(NLS.bind(Messages.MODIFYING_COMPONENT, scp));
+ }
+ try {
+ scp.modify(newProps);
+ } catch (ComponentException e) {
+ Activator.log.error(e.getMessage(), e.getCause());
+ throw e;
+ } catch (Throwable t) {
+ Activator.log.error(NLS.bind(Messages.ERROR_MODIFYING_COMPONENT, scp.serviceComponent), t);
+ throw new ComponentException(NLS.bind(Messages.ERROR_MODIFYING_COMPONENT, scp.serviceComponent), t);
+ } finally {
+ // keep track of how many times we have re-entered this method
+ if (Activator.PERF) {
+ start = System.currentTimeMillis() - start;
+ Activator.log.info(NLS.bind(Messages.COMPONENT_MODIFIED_FOR, scp, Long.toString(start)));
+ }
+ }
+ } finally {
+ freeLock();
+ }
+ }
+
/**
* Acquire a service object from a {@link ServiceReference}.
*
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 c61f5671b..423203165 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
@@ -20,6 +20,7 @@ public class Messages extends NLS {
public static String CANNOT_GET_LOGSERVICE;
public static String CANNOT_GET_REFERENCES;
public static String CANNOT_GET_SERVICE_BECAUSEOF_CIRCULARITY;
+ public static String CANNOT_MODIFY_INSTANCE__MODIFY_METHOD_NOT_FOUND;
public static String CANT_ACTIVATE_INSTANCE;
public static String CANT_GET_SERVICE;
public static String CANT_GET_SERVICE_OBJECT;
@@ -35,6 +36,7 @@ public class Messages extends NLS {
public static String COMPONENT_ID_DEFINIED_BY_LIST_COMMAND;
public static String COMPONENT_INSTANCE_BUILT;
public static String COMPONENT_LACKS_APPROPRIATE_PERMISSIONS;
+ public static String COMPONENT_MODIFIED_FOR;
public static String COMPONENT_NAME;
public static String COMPONENT_NAME_IS_NULL;
public static String COMPONENT_NOT_FOUND;
@@ -81,12 +83,14 @@ public class Messages extends NLS {
public static String ERROR_PROCESSING_PROPERTY;
public static String ERROR_PROCESSING_START_TAG;
public static String ERROR_UNBINDING_REFERENCE;
+ public static String ERROR_UNBINDING_REFERENCE2;
public static String EXCEPTION_ACTIVATING_INSTANCE;
public static String EXCEPTION_BUILDING_COMPONENT;
public static String EXCEPTION_CREATING_COMPONENT_INSTANCE;
public static String EXCEPTION_GETTING_METHOD;
public static String EXCEPTION_LOCATING_SERVICE;
public static String EXCEPTION_LOCATING_SERVICES;
+ public static String EXCEPTION_MODIFYING_COMPONENT;
public static String EXCEPTION_UNBINDING_REFERENCE;
public static String EXPECTED_PARAMETER_COMPONENT_ID;
public static String FACTORY_CONF_NOT_APPLICABLE_FOR_COMPONENT_FACTORY;
@@ -130,6 +134,7 @@ public class Messages extends NLS {
public static String LOCATED_IN_BUNDLE;
public static String METHOD_UNACCESSABLE;
public static String MISSING_CHARACTER;
+ public static String MODIFYING_COMPONENT;
public static String NEW_SERVICE_CREATED;
public static String NO_BUILT_COMPONENT_CONFIGURATIONS;
public static String NO_COMPONENT_INSTANCES;
@@ -179,6 +184,7 @@ public class Messages extends NLS {
public static String ERROR_READING_OBJECT;
public static String DBMANAGER_SERVICE_TRACKER_OPENED;
public static String ERROR_LOADING_COMPONENT_DEFINITIONS;
+ public static String ERROR_MODIFYING_COMPONENT;
public static String ERROR_SAVING_COMPONENT_DEFINITIONS;
public static String FILE_DOESNT_EXIST_OR_DIRECTORY;
static {
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 0881ff42d..fbd0b8f54 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 1997-2007 by ProSyst Software GmbH
+ * Copyright (c) 1997-2009 by ProSyst Software GmbH
* http://www.prosyst.com
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -12,8 +12,7 @@
*******************************************************************************/
package org.eclipse.equinox.internal.ds;
-import java.util.Dictionary;
-import java.util.Vector;
+import java.util.*;
import org.eclipse.equinox.internal.ds.model.*;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
@@ -29,7 +28,6 @@ import org.osgi.service.log.LogService;
* @author Valentin Valchev
* @author Stoyan Boshev
* @author Pavlin Dobrev
- * @version 1.1
*/
public final class Reference {
@@ -112,6 +110,10 @@ public final class Reference {
return target;
}
+ public void setTarget(String newTarget) {
+ target = newTarget;
+ }
+
// used in Resolver.resolveEligible()
final boolean hasProviders() {
// check whether the component's bundle has service GET permission
@@ -195,6 +197,91 @@ public final class Reference {
return false;
}
+ /**
+ * Called to determine if the specified new target filter will still satisfy the current state of the reference
+ * @param newTargetFilter the new target filter to be checked
+ * @return true if the reference will still be satisfied after the filter replacement
+ */
+ public boolean doSatisfy(String newTargetFilter) {
+ ServiceReference[] refs = null;
+ try {
+ refs = scp.bc.getServiceReferences(reference.interfaceName, newTargetFilter);
+ } catch (InvalidSyntaxException e) {
+ Activator.log(scp.bc, LogService.LOG_WARNING, "[SCR] " + NLS.bind(Messages.INVALID_TARGET_FILTER, newTargetFilter), e); //$NON-NLS-1$
+ return false;
+ }
+
+ if (refs == null) {
+ if (cardinalityLow > 0) {
+ //the reference is mandatory, but there are no matching services with the new target filter
+ return false;
+ }
+ if (policy == ComponentReference.POLICY_STATIC) {
+ if (this.reference.bind != null) {
+ if (this.reference.serviceReferences.size() > 0) {
+ //have bound services which are not matching the new filter
+ return false;
+ }
+ } else {
+ //custom case: static reference with no bind method - check its bound service references list
+ if (boundServiceReferences.size() > 0) {
+ //have bound services which are not matching the new filter
+ return false;
+ }
+ }
+ }
+ //the reference is not mandatory and the dynamic bound services can be unbound
+ return true;
+ }
+ if (policy == ComponentReference.POLICY_STATIC) {
+ if (this.reference.bind != null) {
+ Enumeration keys = this.reference.serviceReferences.keys();
+ while (keys.hasMoreElements()) {
+ Object serviceRef = keys.nextElement();
+ boolean found = false;
+ for (int i = 0; i < refs.length; i++) {
+ if (refs[i] == serviceRef) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ //the bound service reference is not already in the satisfied references set.
+ //since this is a static reference a restart of the component is required
+ return false;
+ }
+ }
+ if (cardinalityHigh > 1 && this.reference.serviceReferences.size() < refs.length) {
+ //there are more services to bind. this requires restart of the component since the reference is static
+ return false;
+ }
+ } else {
+ //custom case: static reference with no bind method
+ for (int i = 0; i < boundServiceReferences.size(); i++) {
+ Object serviceRef = boundServiceReferences.elementAt(i);
+ boolean found = false;
+ for (int j = 0; j < refs.length; j++) {
+ if (refs[j] == serviceRef) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ //the bound service reference is not already in the satisfied references set.
+ //since this is a static reference a restart of the component is required
+ return false;
+ }
+ }
+ if (cardinalityHigh > 1 && boundServiceReferences.size() < refs.length) {
+ //there are more services to bind. this requires restart of the component since the reference is static
+ return false;
+ }
+
+ }
+ }
+ return true;
+ }
+
// used in Resolver.selectDynamicUnBind();
final boolean dynamicUnbindReference(ServiceReference changedReference) {
// nothing dynamic to do if static
@@ -268,6 +355,13 @@ public final class Reference {
return res;
}
+ public boolean isBound() {
+ if (this.reference.bind != null) {
+ return (this.reference.serviceReferences.size() >= cardinalityLow);
+ }
+ return true;
+ }
+
public Vector getBoundServiceReferences() {
return boundServiceReferences;
}
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 f0409ef06..233bcfb05 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
@@ -15,8 +15,7 @@ import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
-import org.eclipse.equinox.internal.ds.model.ServiceComponent;
-import org.eclipse.equinox.internal.ds.model.ServiceComponentProp;
+import org.eclipse.equinox.internal.ds.model.*;
import org.eclipse.equinox.internal.util.event.Queue;
import org.eclipse.equinox.internal.util.ref.Log;
import org.eclipse.equinox.internal.util.threadpool.ThreadPoolManager;
@@ -24,6 +23,7 @@ import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
import org.osgi.service.cm.*;
import org.osgi.service.component.ComponentConstants;
+import org.osgi.service.component.ComponentException;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;
@@ -35,7 +35,6 @@ import org.osgi.util.tracker.ServiceTracker;
* @author Maria Ivanova
* @author Stoyan Boshev
* @author Pavlin Dobrev
- * @version 1.2
*/
public class SCRManager implements ServiceListener, SynchronousBundleListener, ConfigurationListener, WorkPerformer, PrivilegedAction {
@@ -348,15 +347,27 @@ public class SCRManager implements ServiceListener, SynchronousBundleListener, C
// if NOT a factory
if (fpid == null) {
- // there is only one SCP for this SC, so we can disable the SC
- Vector components = new Vector();
- components.addElement(sc);
- resolver.disableComponents(components, ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_MODIFIED);
+ // there is only one SCP for this SC
+ boolean requiresRestart = true;
+ if (sc.namespace11) {
+ if (sc.componentProps != null && sc.modifyMethodName != "") { //$NON-NLS-1$
+ ServiceComponentProp scp = (ServiceComponentProp) sc.componentProps.elementAt(0);
+ if (scp.getState() > ServiceComponentProp.SATISFIED) {
+ //process only built components
+ requiresRestart = processConfigurationChange(scp, config[0]);
+ }
+ }
+ }
+ if (requiresRestart) {
+ // there is only one SCP for this SC, so we can disable the SC
+ Vector components = new Vector();
+ components.addElement(sc);
+ resolver.disableComponents(components, ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_MODIFIED);
- // now re-enable the SC - the resolver will pick up the new
- // config
- sc.enabled = true;
- resolver.enableComponents(components);
+ // now re-enable the SC - the resolver will pick up the new config
+ sc.enabled = true;
+ resolver.enableComponents(components);
+ }
// If a MSF
// create a new SCP or update an existing one
@@ -369,20 +380,29 @@ public class SCRManager implements ServiceListener, SynchronousBundleListener, C
if (scp == null && sc.componentProps != null && sc.componentProps.size() == 1 && (((ServiceComponentProp) sc.componentProps.elementAt(0)).getProperties().get(Constants.SERVICE_PID) == null)) {
scp = (ServiceComponentProp) sc.componentProps.elementAt(0);
}
- // if old scp exists, dispose it
- if (scp != null) {
- // config already exists - dispose of it
- sc.componentProps.removeElement(scp);
- Vector components = new Vector();
- components.addElement(scp);
- resolver.disposeComponentConfigs(components, ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_MODIFIED);
+ boolean requiresRestart = true;
+ if (sc.namespace11 && sc.modifyMethodName != "" && scp != null) { //$NON-NLS-1$
+ if (scp.getState() > ServiceComponentProp.SATISFIED) {
+ //process only built components
+ requiresRestart = processConfigurationChange(scp, config[0]);
+ }
}
+ if (requiresRestart) {
+ // if old scp exists, dispose it
+ if (scp != null) {
+ // config already exists - dispose of it
+ sc.componentProps.removeElement(scp);
+ Vector components = new Vector();
+ components.addElement(scp);
+ resolver.disposeComponentConfigs(components, ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_MODIFIED);
+ }
- // create a new scp (adds to resolver enabledSCPs list)
- resolver.map(sc, config[0]);
+ // create a new scp (adds to resolver enabledSCPs list)
+ resolver.map(sc, config[0]);
- // kick the resolver to figure out if SCP is satisfied, etc
- resolver.enableComponents(null);
+ // kick the resolver to figure out if SCP is satisfied, etc
+ resolver.enableComponents(null);
+ }
}
break;
@@ -429,6 +449,85 @@ public class SCRManager implements ServiceListener, SynchronousBundleListener, C
}
}
+ /**
+ * Process the modification of the specified component.
+ * If it cannot be modified, the method will return <code>true</code> indicating the component has to be restarted.
+ * @param scp the component to modify
+ * @param config the configuration that brings the new properties
+ * @return true, if the component needs restart (to be deactivated and then eventually activated again)
+ */
+ private boolean processConfigurationChange(ServiceComponentProp scp, Configuration config) {
+ boolean result = false;
+ Hashtable currentProps = scp.properties;
+ Dictionary newProps = config.getProperties();
+ Enumeration keys = currentProps.keys();
+ Vector checkedFilters = new Vector();
+ while (keys.hasMoreElements() && !result) {
+ String key = (String) keys.nextElement();
+ if (key.endsWith(".target")) { //$NON-NLS-1$
+ checkedFilters.addElement(key);
+ String newFilter = (String) newProps.get(key);
+ Reference reference = null;
+ String refName = key.substring(0, key.length() - ".target".length()); //$NON-NLS-1$
+ Vector references = scp.references;
+ for (int i = 0; i < references.size(); i++) {
+ reference = (Reference) references.elementAt(i);
+ if (reference.reference.name.equals(refName)) {
+ break;
+ }
+ reference = null;
+ }
+ //check if there is a reference corresponding to the target property
+ if (reference != null) {
+ if (newFilter != null) {
+ if (!newFilter.equals(currentProps.get(key))) {
+ //the filter differs the old one
+ result = result || !reference.doSatisfy(newFilter);
+ }
+ } else {
+ //the target filter is removed. Using the default filter to check
+ if (reference.policy == ComponentReference.POLICY_STATIC) {
+ result = result || !reference.doSatisfy("(objectClass=" + reference.reference.interfaceName + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+ }
+ }
+
+ //now check the new properties if they have new target properties defined
+ keys = newProps.keys();
+ while (keys.hasMoreElements() && !result) {
+ String key = (String) keys.nextElement();
+ if (key.endsWith(".target") && !checkedFilters.contains(key)) { //$NON-NLS-1$
+ Reference reference = null;
+ String refName = key.substring(0, key.length() - ".target".length()); //$NON-NLS-1$
+ Vector references = scp.references;
+ for (int i = 0; i < references.size(); i++) {
+ reference = (Reference) references.elementAt(i);
+ if (reference.reference.name.equals(refName)) {
+ break;
+ }
+ reference = null;
+ }
+ //check if there is a reference corresponding to the target property
+ if (reference != null) {
+ result = result || !reference.doSatisfy((String) newProps.get(key));
+ }
+ }
+ }
+
+ if (!result) {
+ //do process component modification via the InstanceProcess
+ try {
+ InstanceProcess.staticRef.modifyComponent(scp, newProps);
+ } catch (ComponentException ce) {
+ //could happen if the modify method is not found
+ result = true;
+ }
+ }
+ return result;
+ }
+
private void disposeBundles() {
// dispose ALL bundles
if (bundleToServiceComponents != null) {
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 b6a48cd04..6f901fb91 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
@@ -14,6 +14,7 @@ CANNOT_GET_CONFIGURATION=[SCR] Cannot get configuration for component {0}
CANNOT_GET_LOGSERVICE=Cannot get LogService for bundle {0}
CANNOT_GET_REFERENCES=[SCR] Cannot get references for {0}
CANNOT_GET_SERVICE_BECAUSEOF_CIRCULARITY=InstanceProcess.getService(): cannot get service because of circularity\! Reference is: {0} ; The service reference is {1}
+CANNOT_MODIFY_INSTANCE__MODIFY_METHOD_NOT_FOUND=[SCR] Cannot modify instance {0} of component {1}\! The specified modify method was not found\!
CANT_ACTIVATE_INSTANCE=[SCR] Cannot activate instance {0} of component {1}
CANT_GET_SERVICE=FactoryReg.getService(): Cannot create instance of {0}
CANT_GET_SERVICE_OBJECT=[SCR] Could not get the service object relevant to the reference. A very possible reason is a circularity problem.
@@ -29,6 +30,7 @@ COMPONENT_HAS_ILLEGAL_REFERENCE=The component ''{0}'' defined at line {1} contai
COMPONENT_ID_DEFINIED_BY_LIST_COMMAND=The ID of the component as displayed by the list command
COMPONENT_INSTANCE_BUILT=[DS perf] The instance of component {0} is built for {1}ms
COMPONENT_LACKS_APPROPRIATE_PERMISSIONS=Resolver.resolveEligible(): Cannot satisfy component ''{0}'' because its bundle does not have permissions to register service with interface {1}
+COMPONENT_MODIFIED_FOR=Component {0} modified for {1}ms
COMPONENT_NAME=\t\t\tComponent Name
COMPONENT_NAME_IS_NULL=Component name must not be null
COMPONENT_NOT_FOUND=component {0} not found in bundle {1}
@@ -75,12 +77,14 @@ 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_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}
EXCEPTION_CREATING_COMPONENT_INSTANCE=Exception occurred while creating new instance of component {0}
EXCEPTION_GETTING_METHOD=[SCR] Exception occurred while getting method ''{0}'' of class {1}
EXCEPTION_LOCATING_SERVICE=Exception occurred while locating service for interface {0}
EXCEPTION_LOCATING_SERVICES=Exception occurred while locating services for interface {0}
+EXCEPTION_MODIFYING_COMPONENT=[SCR] Exception while modifying instance {0} of component {1}
EXCEPTION_UNBINDING_REFERENCE=[SCR] Exception occurred while unbinding reference {0}
EXPECTED_PARAMETER_COMPONENT_ID=This command expects a component ID as parameter\!
FACTORY_CONF_NOT_APPLICABLE_FOR_COMPONENT_FACTORY=[SCR - SCRManager] ComponentFactory {0} cannot be managed using factory configuration!
@@ -124,6 +128,7 @@ LIST_ALL_COMPONENTS=Lists all components; add -c to display the complete info fo
LOCATED_IN_BUNDLE=\t\t\tLocated in bundle
METHOD_UNACCESSABLE=[SCR] Method ''{0}'' is not public or protected and cannot be executed! The method is located in the class: {1}
MISSING_CHARACTER=Missing character
+MODIFYING_COMPONENT=Modifying component {0}
NEW_SERVICE_CREATED=FactoryReg.getService(): created new service for component {0}
NO_BUILT_COMPONENT_CONFIGURATIONS=\ \ *The component has NO built configurations\! The reason might be that it requires initialization by configuration provided by Configuration Admin but none was found
NO_COMPONENT_INSTANCES=InstanceProcess.dynamicBind(): null instances for component {0}
@@ -173,5 +178,6 @@ ERROR_WRITING_OBJECT=Error writing object!
ERROR_READING_OBJECT=Error reading object!
DBMANAGER_SERVICE_TRACKER_OPENED=DBManager service tracker opened for
ERROR_LOADING_COMPONENT_DEFINITIONS=Error while loading component's definitions!
+ERROR_MODIFYING_COMPONENT=Error modifying component {0}
ERROR_SAVING_COMPONENT_DEFINITIONS=Error while saving component's definitions!
FILE_DOESNT_EXIST_OR_DIRECTORY=File doesn't exist or is a directory!
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 e119c99a9..f90c3a4d4 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
@@ -48,7 +48,7 @@ public class DeclarationParser implements ExTagListener {
private static final String ATTR_CONF_POLICY = "configuration-policy"; //$NON-NLS-1$
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_MODIFY = "modify"; //$NON-NLS-1$
+ private static final String ATTR_MODIFIED = "modified"; //$NON-NLS-1$
private static final String TAG_IMPLEMENTATION = "implementation"; //$NON-NLS-1$
private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
@@ -512,8 +512,8 @@ public class DeclarationParser implements ExTagListener {
if (tmp != null) {
currentComponent.deactivateMethodName = tmp;
}
- //processing attribute modify
- tmp = tag.getAttribute(ATTR_MODIFY);
+ //processing attribute modified
+ tmp = tag.getAttribute(ATTR_MODIFIED);
if (tmp != null && tmp.length() == 0) {
tmp = null;
}
@@ -530,8 +530,8 @@ public class DeclarationParser implements ExTagListener {
if (tag.getAttribute(ATTR_DEACTIVATE) != null) {
throw new IllegalArgumentException(NLS.bind(Messages.INVALID_TAG_ACCORDING_TO_NAMESPACE1_0, ATTR_DEACTIVATE, Integer.toString(tag.getLine())));
}
- if (tag.getAttribute(ATTR_MODIFY) != null) {
- throw new IllegalArgumentException(NLS.bind(Messages.INVALID_TAG_ACCORDING_TO_NAMESPACE1_0, ATTR_MODIFY, Integer.toString(tag.getLine())));
+ if (tag.getAttribute(ATTR_MODIFIED) != null) {
+ throw new IllegalArgumentException(NLS.bind(Messages.INVALID_TAG_ACCORDING_TO_NAMESPACE1_0, ATTR_MODIFIED, Integer.toString(tag.getLine())));
}
}
}
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 ce7366932..57a5d7b01 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
@@ -12,6 +12,8 @@
*******************************************************************************/
package org.eclipse.equinox.internal.ds.model;
+import org.eclipse.equinox.internal.ds.Messages;
+
import java.io.*;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -49,7 +51,7 @@ public class ServiceComponent implements Externalizable {
String configurationPolicy = CONF_POLICY_OPTIONAL;
String activateMethodName = "activate"; //$NON-NLS-1$
String deactivateMethodName = "deactivate"; //$NON-NLS-1$
- String modifyMethodName = "modify"; //$NON-NLS-1$
+ public String modifyMethodName = ""; //$NON-NLS-1$
// service
public Vector serviceInterfaces; // all strings
@@ -243,12 +245,14 @@ public class ServiceComponent implements Externalizable {
}
}
- void modify(Object instance, ComponentContext context) throws ComponentException {
+ void modified(Object instance, ComponentContext context) throws ComponentException {
try {
if (namespace11) {
if (!modifyCached) {
modifyCached = true;
- modifyMethod = getMethod(instance, modifyMethodName, true);
+ if (modifyMethodName != "") { //$NON-NLS-1$
+ modifyMethod = getMethod(instance, modifyMethodName, true);
+ }
}
// invoke the method if any
if (modifyMethod != null) {
@@ -277,10 +281,10 @@ public class ServiceComponent implements Externalizable {
}
}
} else {
- if (modifyMethodName != "modify") { //$NON-NLS-1$
+ if (modifyMethodName != "") { //$NON-NLS-1$
//the modify method is specified in the component description XML by the user.
//It is expected to find it in the implementation class
- throw new ComponentException(NLS.bind("[SCR] Cannot modify instance {0} of component {1}! The specified modify method was not found!", instance, this));
+ throw new ComponentException(NLS.bind(Messages.CANNOT_MODIFY_INSTANCE__MODIFY_METHOD_NOT_FOUND, instance, this));
}
}
}
@@ -288,10 +292,7 @@ public class ServiceComponent implements Externalizable {
if (t instanceof ComponentException) {
throw (ComponentException) t;
}
- Activator.log(bc, LogService.LOG_ERROR, NLS.bind("[SCR] Cannot modify instance {0} of component {1}", instance, this), null);
- throw new ComponentException(NLS.bind("[SCR] Exception while modifying instance {0} of component {1}", instance, name), t);
- // rethrow exception so resolver is eventually notified that
- // the processed SCP is bad
+ Activator.log(bc, LogService.LOG_ERROR, NLS.bind(Messages.EXCEPTION_MODIFYING_COMPONENT, instance, this), t);
}
}
@@ -506,7 +507,7 @@ public class ServiceComponent implements Externalizable {
if (namespace11) {
buffer.append("\n\tactivate = ").append(activateMethodName); //$NON-NLS-1$
buffer.append("\n\tdeactivate = ").append(deactivateMethodName); //$NON-NLS-1$
- buffer.append("\n\tmodify = ").append(modifyMethodName); //$NON-NLS-1$
+ buffer.append("\n\tmodified = ").append(modifyMethodName); //$NON-NLS-1$
buffer.append("\n\tconfiguration-policy = ").append(configurationPolicy); //$NON-NLS-1$
}
buffer.append("\n\tfactory = ").append(factory); //$NON-NLS-1$
@@ -600,7 +601,7 @@ public class ServiceComponent implements Externalizable {
out.writeBoolean(true);
out.writeUTF(deactivateMethodName);
}
- if (modifyMethodName == "modify") { //$NON-NLS-1$
+ if (modifyMethodName == "") { //$NON-NLS-1$
//this is the default value. Do not write it. Just add a mark
out.writeBoolean(false);
} else {
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 ed01c6b88..cb131cab1 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 1997-2007 by ProSyst Software GmbH
+ * Copyright (c) 1997-2009 by ProSyst Software GmbH
* http://www.prosyst.com
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -36,7 +36,6 @@ import org.osgi.service.log.LogService;
* @author Valentin Valchev
* @author Stoyan Boshev
* @author Pavlin Dobrev
- * @version 1.2
*/
public class ServiceComponentProp implements PrivilegedExceptionAction {
@@ -85,7 +84,7 @@ public class ServiceComponentProp implements PrivilegedExceptionAction {
this.name = serviceComponent.name;
this.bc = serviceComponent.bc;
- initProperties(configProperties);
+ properties = initProperties(configProperties, null);
isComponentFactory = serviceComponent.factory != null;
@@ -122,10 +121,10 @@ public class ServiceComponentProp implements PrivilegedExceptionAction {
* This method will call the activate method on the specified object.
*
* @param usingBundle
- * the bundle that is using the component - this hase only means
+ * the bundle that is using the component - this has only means
* when the component is factory
* @param componentInstance
- * the component instance whcich will be activated.
+ * the component instance which will be activated.
* @throws Exception
* could be thrown if the activate fails for some reason but NOT
* in case, if the instance doesn't define an activate method.
@@ -157,6 +156,43 @@ public class ServiceComponentProp implements PrivilegedExceptionAction {
}
/**
+ * This method will update the properties of the component
+ *
+ * @param newProps
+ * the new properties
+ * @throws Exception
+ * could be thrown if the modify method fails for some reason but NOT
+ * in case, if the instance doesn't define modify method
+ */
+ public void modify(Dictionary newProps) throws Exception {
+ if (Activator.DEBUG) {
+ Activator.log.debug("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ServiceComponentProp.modify(): name: " + name, null); //$NON-NLS-1$
+ }
+ Hashtable oldProperties = null;
+ if (references != null && references.size() > 0) {
+ oldProperties = (Hashtable) properties.clone();
+ }
+ //1. update the properties
+ properties = initProperties(newProps, (Long) properties.get(ComponentConstants.COMPONENT_ID));
+ //2. call the modify method on the Service Component for all instances of this scp
+ for (int i = 0; i < instances.size(); i++) {
+ ComponentInstanceImpl componentInstance = (ComponentInstanceImpl) instances.elementAt(i);
+ Activator.log.debug("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ServiceComponentProp.modify(): instance: " + componentInstance.toString(), null); //$NON-NLS-1$
+ serviceComponent.modified(componentInstance.getInstance(), componentInstance.getComponentContext());
+ }
+ //3. modify the bound services if necessary
+ if (oldProperties != null) {
+ handleBoundServicesUpdate(oldProperties, properties);
+ }
+
+ //4. if the component configuration is registered as a service,
+ // modify the service’s service properties
+ if (registration != null) {
+ registration.setProperties(getPublicServiceProperties());
+ }
+ }
+
+ /**
* Call the bind method for each of the Referenced Services in this Service
* Component
*
@@ -165,16 +201,15 @@ public class ServiceComponentProp implements PrivilegedExceptionAction {
* @throws Exception
*/
public boolean bind(ComponentInstance componentInstance) throws Exception {
- // Get all the required service Reference Descriptions for this Service
- // Component
+ // Get all the required service Reference Descriptions for this ServiceComponent
// call the Bind method if the Reference Description includes one
if (references != null) {
for (int i = 0; i < references.size(); i++) {
Reference ref = (Reference) references.elementAt(i);
if (ref.reference.bind != null) {
bindReference(ref, componentInstance);
- if (ref.reference.bindMethod == null) {
- //the bind method is not found and called for some reason
+ if (ref.reference.bindMethod == 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) {
//unbind the already bound references
for (int j = i - 1; j >= 0; j--) {
@@ -400,6 +435,143 @@ public class ServiceComponentProp implements PrivilegedExceptionAction {
}
/**
+ * Handles the update of the bound services in case the target properties have changed
+ * @param oldProps the old component properties
+ * @param newProps the new component properties
+ */
+ private void handleBoundServicesUpdate(Hashtable oldProps, Dictionary newProps) {
+ Enumeration keys = oldProps.keys();
+ Vector checkedFilters = new Vector();
+ //check for changed target filters in the properties
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ if (key.endsWith(".target")) { //$NON-NLS-1$
+ checkedFilters.addElement(key);
+ String newFilter = (String) newProps.get(key);
+ Reference reference = null;
+ String refName = key.substring(0, key.length() - ".target".length()); //$NON-NLS-1$
+ for (int i = 0; i < references.size(); i++) {
+ reference = (Reference) references.elementAt(i);
+ if (reference.reference.name.equals(refName)) {
+ break;
+ }
+ reference = null;
+ }
+ //check if there is a reference corresponding to the target property
+ if (reference != null && reference.reference.policy == ComponentReference.POLICY_DYNAMIC) {
+ if (newFilter != null) {
+ if (!newFilter.equals(oldProps.get(key))) {
+ //the filter differs the old one - update the reference bound services
+ processReferenceBoundServices(reference, newFilter);
+ }
+ } else {
+ //the target filter is removed. using the default one
+ processReferenceBoundServices(reference, "(objectClass=" + reference.reference.interfaceName + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+ }
+ //now check for newly added target filters
+ keys = newProps.keys();
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ if (key.endsWith(".target") && !checkedFilters.contains(key)) { //$NON-NLS-1$
+ Reference reference = null;
+ String refName = key.substring(0, key.length() - ".target".length()); //$NON-NLS-1$
+ for (int i = 0; i < references.size(); i++) {
+ reference = (Reference) references.elementAt(i);
+ if (reference.reference.name.equals(refName)) {
+ break;
+ }
+ reference = null;
+ }
+ //check if there is a reference corresponding to the target property
+ if (reference != null && reference.reference.policy == ComponentReference.POLICY_DYNAMIC) {
+ processReferenceBoundServices(reference, (String) newProps.get(key));
+ }
+ }
+ }
+ }
+
+ private void processReferenceBoundServices(Reference reference, String newTargetFilter) {
+ reference.setTarget(newTargetFilter);
+ ServiceReference[] refs = null;
+ try {
+ refs = bc.getServiceReferences(reference.reference.interfaceName, newTargetFilter);
+ } catch (InvalidSyntaxException e) {
+ Activator.log(bc, LogService.LOG_WARNING, "[SCR] " + NLS.bind(Messages.INVALID_TARGET_FILTER, newTargetFilter), e); //$NON-NLS-1$
+ return;
+ }
+
+ if (refs == null) {
+ //must remove all currently bound services
+ if (reference.reference.bind != null) {
+ if (reference.reference.serviceReferences.size() > 0) {
+ for (int i = 0; i < instances.size(); i++) {
+ ComponentInstance componentInstance = (ComponentInstance) instances.elementAt(i);
+ unbindReference(reference, componentInstance);
+ }
+ }
+ }
+ } else {
+ //find out which services has to be bound and which unbound
+ if (reference.reference.bind != null) {
+ Vector servicesToUnbind = new Vector();
+ Enumeration keys = reference.reference.serviceReferences.keys();
+ while (keys.hasMoreElements()) {
+ Object serviceRef = keys.nextElement();
+ boolean found = false;
+ for (int i = 0; i < refs.length; i++) {
+ if (refs[i] == serviceRef) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ //the bound service reference is not already in the satisfied references set.
+ servicesToUnbind.addElement(serviceRef);
+ }
+ }
+ if ((reference.reference.cardinality == ComponentReference.CARDINALITY_0_N || reference.reference.cardinality == ComponentReference.CARDINALITY_1_N) && (reference.reference.serviceReferences.size() - servicesToUnbind.size()) < refs.length) {
+ //there are more services to bind
+ for (int i = 0; i < refs.length; i++) {
+ keys = reference.reference.serviceReferences.keys();
+ boolean found = false;
+ while (keys.hasMoreElements()) {
+ Object serviceRef = keys.nextElement();
+ if (serviceRef == refs[i]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ for (int j = 0; j < instances.size(); j++) {
+ ComponentInstance componentInstance = (ComponentInstance) instances.elementAt(j);
+ try {
+ reference.reference.bind(reference, componentInstance, refs[i]);
+ } catch (Exception e) {
+ Activator.log.error(NLS.bind(Messages.ERROR_BINDING_REFERENCE, reference), e);
+ }
+ }
+ }
+ }
+ }
+ //finally unbind all services that do not match the target filter
+ for (int i = 0; i < servicesToUnbind.size(); i++) {
+ for (int j = 0; j < instances.size(); j++) {
+ ComponentInstance componentInstance = (ComponentInstance) instances.elementAt(j);
+ try {
+ unbindDynamicReference(reference, componentInstance, (ServiceReference) servicesToUnbind.elementAt(i));
+ } catch (Exception e) {
+ Activator.log.error(NLS.bind(Messages.ERROR_UNBINDING_REFERENCE2, reference), e);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Call the unbind method for this Reference Description
*
* @param reference
@@ -456,17 +628,20 @@ public class ServiceComponentProp implements PrivilegedExceptionAction {
*
* @param configProperties
* the configuration properties
+ * @param componentId specifies the component ID. If null, a new one will be generated
+ * @return the fully initialized properties
*/
- private void initProperties(Dictionary configProperties) {
+ private Hashtable initProperties(Dictionary configProperties, Long componentId) {
+ Hashtable result = null;
// default component service properties
Properties propertyDescriptions = serviceComponent.properties;
if (propertyDescriptions != null && !propertyDescriptions.isEmpty()) {
- properties = (Hashtable) propertyDescriptions.clone();
+ result = (Hashtable) propertyDescriptions.clone();
}
// set the component.name
- if (properties == null) {
- properties = new Hashtable(7);
+ if (result == null) {
+ result = new Hashtable(7);
}
// put the references in the properties
@@ -475,7 +650,7 @@ public class ServiceComponentProp implements PrivilegedExceptionAction {
for (int i = 0; i < serviceComponent.references.size(); i++) {
ref = (ComponentReference) serviceComponent.references.elementAt(i);
if (ref.target != null) {
- properties.put(ref.name + ComponentConstants.REFERENCE_TARGET_SUFFIX, ref.target);
+ result.put(ref.name + ComponentConstants.REFERENCE_TARGET_SUFFIX, ref.target);
}
}
}
@@ -485,20 +660,21 @@ public class ServiceComponentProp implements PrivilegedExceptionAction {
for (Enumeration keys = configProperties.keys(); keys.hasMoreElements();) {
Object key = keys.nextElement();
Object val = configProperties.get(key);
- properties.put(key, val);
+ result.put(key, val);
}
}
// always set the component name & the id
- Long nextId = new Long(getNewComponentID());
- properties.put(ComponentConstants.COMPONENT_ID, nextId);
- properties.put(ComponentConstants.COMPONENT_NAME, serviceComponent.name);
+ Long nextId = (componentId == null) ? new Long(getNewComponentID()) : componentId;
+ result.put(ComponentConstants.COMPONENT_ID, nextId);
+ result.put(ComponentConstants.COMPONENT_NAME, serviceComponent.name);
if (serviceComponent.provides != null) {
String[] provides = new String[serviceComponent.provides.length];
System.arraycopy(serviceComponent.provides, 0, provides, 0, provides.length);
- properties.put(Constants.OBJECTCLASS, provides);
+ result.put(Constants.OBJECTCLASS, provides);
}
+ return result;
}
private void assertCreateSingleInstance() {
@@ -516,6 +692,23 @@ public class ServiceComponentProp implements PrivilegedExceptionAction {
}
/**
+ * Removes the private properties and returns the public properties that are set to the registered service provided by this component
+ * @return the public properties used in the registration of the service which is provided by this component
+ */
+ public Hashtable getPublicServiceProperties() {
+ //remove the private properties from the component properties before registering as service
+ Hashtable publicProps = (Hashtable) properties.clone();
+ Enumeration keys = properties.keys();
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ if (key.startsWith(".")) { //$NON-NLS-1$
+ publicProps.remove(key);
+ }
+ }
+ return publicProps;
+ }
+
+ /**
* Add a new Component Configuration name we should not activate in order to
* prevent a cycle.
*

Back to the top