Author: marrs
Date: Thu Sep 18 14:13:20 2008
New Revision: 696805
URL: http://svn.apache.org/viewvc?rev=696805&view=rev
Log:
Added initial support for externally querying the status of services managed by
the dependency manager. Added initial support for supplying your own default
implementation. Made null object creation more robust. Added support for
specifying the name of the property in case you're injecting dependencies so
you can inject multiple instances of a service to specific properties.
Added:
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceComponent.java
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceComponentDependency.java
Modified:
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
Modified:
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java
URL:
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java?rev=696805&r1=696804&r2=696805&view=diff
==============================================================================
---
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java
(original)
+++
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java
Thu Sep 18 14:13:20 2008
@@ -47,7 +47,7 @@
*
* @author <a href="mailto:[EMAIL PROTECTED]">Felix Project Team</a>
*/
-public class ConfigurationDependency implements Dependency, ManagedService {
+public class ConfigurationDependency implements Dependency, ManagedService,
ServiceComponentDependency {
private BundleContext m_context;
private String m_pid;
private ServiceRegistration m_registration;
@@ -171,4 +171,16 @@
public String toString() {
return "ConfigurationDependency[" + m_pid + "]";
}
+
+ public String getName() {
+ return m_pid;
+ }
+
+ public int getState() {
+ return (isAvailable() ? 1 : 0) + (isRequired() ? 2 : 0);
+ }
+
+ public String getType() {
+ return "configuration";
+ }
}
Modified:
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
URL:
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java?rev=696805&r1=696804&r2=696805&view=diff
==============================================================================
---
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
(original)
+++
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
Thu Sep 18 14:13:20 2008
@@ -95,7 +95,7 @@
* @return the new service
*/
public Service createService() {
- return new ServiceImpl(m_context, m_logger);
+ return new ServiceImpl(m_context, m_manager, m_logger);
}
/**
Modified:
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
URL:
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java?rev=696805&r1=696804&r2=696805&view=diff
==============================================================================
---
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
(original)
+++
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
Thu Sep 18 14:13:20 2008
@@ -73,7 +73,7 @@
* @return the new service
*/
public Service createService() {
- return new ServiceImpl(m_context, m_logger);
+ return new ServiceImpl(m_context, this, m_logger);
}
/**
Added:
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceComponent.java
URL:
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceComponent.java?rev=696805&view=auto
==============================================================================
---
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceComponent.java
(added)
+++
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceComponent.java
Thu Sep 18 14:13:20 2008
@@ -0,0 +1,10 @@
+package org.apache.felix.dependencymanager;
+
+public interface ServiceComponent {
+ public static final String[] STATE_NAMES = { "unregistered", "registered"
};
+ public static final int STATE_UNREGISTERED = 0;
+ public static final int STATE_REGISTERED = 1;
+ public ServiceComponentDependency[] getComponentDependencies();
+ public String getName();
+ public int getState();
+}
Added:
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceComponentDependency.java
URL:
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceComponentDependency.java?rev=696805&view=auto
==============================================================================
---
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceComponentDependency.java
(added)
+++
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceComponentDependency.java
Thu Sep 18 14:13:20 2008
@@ -0,0 +1,12 @@
+package org.apache.felix.dependencymanager;
+
+public interface ServiceComponentDependency {
+ public static final String[] STATE_NAMES = { "unavailable optional",
"available optional", "unavailable required", "available required" };
+ public static final int STATE_UNAVAILABLE_OPTIONAL = 0;
+ public static final int STATE_AVAILABLE_OPTIONAL = 1;
+ public static final int STATE_UNAVAILABLE_REQUIRED = 2;
+ public static final int STATE_AVAILABLE_REQUIRED = 3;
+ public String getName();
+ public String getType();
+ public int getState();
+}
Modified:
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
URL:
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java?rev=696805&r1=696804&r2=696805&view=diff
==============================================================================
---
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
(original)
+++
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
Thu Sep 18 14:13:20 2008
@@ -32,7 +32,7 @@
*
* @author <a href="mailto:[EMAIL PROTECTED]">Felix Project Team</a>
*/
-public class ServiceDependency implements Dependency, ServiceTrackerCustomizer
{
+public class ServiceDependency implements Dependency,
ServiceTrackerCustomizer, ServiceComponentDependency {
private boolean m_isRequired;
private Service m_service;
private ServiceTracker m_tracker;
@@ -51,6 +51,9 @@
private ServiceReference m_reference;
private Object m_serviceInstance;
private final Logger m_logger;
+ private String m_autoConfigInstance;
+ private Object m_defaultImplementation;
+ private Object m_defaultImplementationInstance;
/**
* Creates a new service dependency.
@@ -82,7 +85,10 @@
service = m_tracker.getService();
}
if (service == null) {
- service = getNullObject();
+ service = getDefaultImplementation();
+ if (service == null) {
+ service = getNullObject();
+ }
}
return service;
}
@@ -93,11 +99,33 @@
synchronized (this) {
trackedServiceName = m_trackedServiceName;
}
- m_nullObject =
Proxy.newProxyInstance(trackedServiceName.getClassLoader(), new Class[]
{trackedServiceName}, new DefaultNullObject());
+ try {
+ m_nullObject =
Proxy.newProxyInstance(trackedServiceName.getClassLoader(), new Class[]
{trackedServiceName}, new DefaultNullObject());
+ }
+ catch (Exception e) {
+ m_logger.log(Logger.LOG_ERROR, "Could not create null object
for " + trackedServiceName + ".", e);
+ }
}
return m_nullObject;
}
+ private Object getDefaultImplementation() {
+ if (m_defaultImplementation != null) {
+ if (m_defaultImplementation instanceof Class) {
+ try {
+ m_defaultImplementationInstance = ((Class)
m_defaultImplementation).newInstance();
+ }
+ catch (Exception e) {
+ m_logger.log(Logger.LOG_ERROR, "Could not create default
implementation instance of class " + m_defaultImplementation + ".", e);
+ }
+ }
+ else {
+ m_defaultImplementationInstance = m_defaultImplementation;
+ }
+ }
+ return m_defaultImplementationInstance;
+ }
+
public synchronized Class getInterface() {
return m_trackedServiceName;
}
@@ -373,6 +401,22 @@
m_trackedServiceFilter = null;
return this;
}
+
+ /**
+ * Sets the default implementation for this service dependency. You can
use this to supply
+ * your own implementation that will be used instead of a Null Object when
the dependency is
+ * not available. This is also convenient if the service dependency is not
an interface
+ * (which would cause the Null Object creation to fail) but a class.
+ *
+ * @param implementation the instance to use or the class to instantiate
if you want to lazily
+ * instantiate this implementation
+ * @return this service dependency
+ */
+ public synchronized ServiceDependency setDefaultImplementation(Object
implementation) {
+ ensureNotActive();
+ m_defaultImplementation = implementation;
+ return this;
+ }
/**
* Sets the required flag which determines if this service is required or
not.
@@ -401,6 +445,21 @@
}
/**
+ * Sets auto configuration for this service. Auto configuration allows the
+ * dependency to fill in the attribute in the service implementation that
+ * has the same type and instance name.
+ *
+ * @param instanceName the name of attribute to auto config
+ * @return this service dependency
+ */
+ public synchronized ServiceDependency setAutoConfig(String instanceName) {
+ ensureNotActive();
+ m_autoConfig = (instanceName != null);
+ m_autoConfigInstance = instanceName;
+ return this;
+ }
+
+ /**
* Sets the callbacks for this service. These callbacks can be used as
hooks whenever
* a dependency is added or removed. They are called on the service
implementation.
*
@@ -447,4 +506,20 @@
public synchronized String toString() {
return "ServiceDependency[" + m_trackedServiceName + " " +
m_trackedServiceFilter + "]";
}
+
+ public String getAutoConfigName() {
+ return m_autoConfigInstance;
+ }
+
+ public String getName() {
+ return m_trackedServiceName.getName();
+ }
+
+ public int getState() {
+ return (isAvailable() ? 1 : 0) + (isRequired() ? 2 : 0);
+ }
+
+ public String getType() {
+ return "service";
+ }
}
Modified:
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
URL:
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java?rev=696805&r1=696804&r2=696805&view=diff
==============================================================================
---
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
(original)
+++
felix/trunk/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
Thu Sep 18 14:13:20 2008
@@ -39,12 +39,13 @@
*
* @author <a href="mailto:[EMAIL PROTECTED]">Felix Project Team</a>
*/
-public class ServiceImpl implements Service {
+public class ServiceImpl implements Service, ServiceComponent {
private static final Class[] VOID = new Class[] {};
private static final ServiceRegistration NULL_REGISTRATION;
private static final ServiceStateListener[] SERVICE_STATE_LISTENER_TYPE =
new ServiceStateListener[] {};
private final BundleContext m_context;
+ private final DependencyManager m_manager;
// configuration (static)
private String m_callbackInit;
@@ -84,11 +85,13 @@
// internal logging
private final Logger m_logger;
+ private ServiceRegistration m_serviceRegistration;
- public ServiceImpl(BundleContext context, Logger logger) {
+ public ServiceImpl(BundleContext context, DependencyManager manager,
Logger logger) {
m_logger = logger;
m_state = new State((List) m_dependencies.clone(), false);
m_context = context;
+ m_manager = manager;
m_callbackInit = "init";
m_callbackStart = "start";
m_callbackStop = "stop";
@@ -237,6 +240,7 @@
}
public synchronized void start() {
+ m_serviceRegistration =
m_context.registerService(ServiceComponent.class.getName(), this, null);
State oldState, newState;
synchronized (m_dependencies) {
oldState = m_state;
@@ -254,6 +258,7 @@
m_state = newState;
}
calculateStateChanges(oldState, newState);
+ m_serviceRegistration.unregister();
}
public synchronized Service setInterface(String serviceName, Dictionary
properties) {
@@ -588,6 +593,7 @@
// configure the bundle context
configureImplementation(BundleContext.class, m_context);
configureImplementation(ServiceRegistration.class,
NULL_REGISTRATION);
+ configureImplementation(DependencyManager.class, m_manager);
}
}
@@ -676,7 +682,7 @@
// update the dependency in the service instance (it will use
// a null object if necessary)
if (sd.isAutoConfig()) {
- configureImplementation(sd.getInterface(), sd.getService());
+ configureImplementation(sd.getInterface(), sd.getService(),
sd.getAutoConfigName());
}
}
else if (dependency instanceof ConfigurationDependency) {
@@ -696,8 +702,9 @@
*
* @param clazz the class to search for
* @param instance the instance to fill in
+ * @param instanceName the name of the instance to fill in, or
<code>null</code> if not used
*/
- private void configureImplementation(Class clazz, Object instance) {
+ private void configureImplementation(Class clazz, Object instance, String
instanceName) {
Object[] instances = null;
if (m_compositionManagerGetMethod != null) {
if (m_compositionManager != null) {
@@ -728,7 +735,7 @@
while (serviceClazz != null) {
Field[] fields = serviceClazz.getDeclaredFields();
for (int j = 0; j < fields.length; j++) {
- if (fields[j].getType().equals(clazz)) {
+ if (fields[j].getType().equals(clazz) &&
(instanceName == null || fields[j].getName().equals(instanceName))) {
try {
fields[j].setAccessible(true);
// synchronized makes sure the field is
actually written to immediately
@@ -747,6 +754,10 @@
}
}
}
+
+ private void configureImplementation(Class clazz, Object instance) {
+ configureImplementation(clazz, instance, null);
+ }
private void configureServices(State state) {
Iterator i = state.getDependencies().iterator();
@@ -755,7 +766,7 @@
if (dependency instanceof ServiceDependency) {
ServiceDependency sd = (ServiceDependency) dependency;
if (sd.isAutoConfig()) {
- configureImplementation(sd.getInterface(),
sd.getService());
+ configureImplementation(sd.getInterface(),
sd.getService(), sd.getAutoConfigName());
}
// for required dependencies, we invoke any callbacks here
if (sd.isRequired()) {
@@ -796,6 +807,58 @@
return (state.isTrackingOptional());
}
+ // ServiceComponent interface
+
+ static class SCDImpl implements ServiceComponentDependency {
+ private final String m_name;
+ private final int m_state;
+ private final String m_type;
+
+ public SCDImpl(String name, int state, String type) {
+ m_name = name;
+ m_state = state;
+ m_type = type;
+ }
+
+ public String getName() {
+ return m_name;
+ }
+
+ public int getState() {
+ return m_state;
+ }
+
+ public String getType() {
+ return m_type;
+ }
+ }
+
+ public ServiceComponentDependency[] getComponentDependencies() {
+ List deps = getDependencies();
+ if (deps != null) {
+ ServiceComponentDependency[] result = new
ServiceComponentDependency[deps.size()];
+ for (int i = 0; i < result.length; i++) {
+ Dependency dep = (Dependency) deps.get(i);
+ if (dep instanceof ServiceComponentDependency) {
+ result[i] = (ServiceComponentDependency) dep;
+ }
+ else {
+ result[i] = new SCDImpl(dep.toString(), (dep.isAvailable()
? 1 : 0) + (dep.isRequired() ? 2 : 0), dep.getClass().getName());
+ }
+ }
+ return result;
+ }
+ return null;
+ }
+
+ public String getName() {
+ return (String) (m_serviceName != null ? m_serviceName :
m_serviceInstance);
+ }
+
+ public int getState() {
+ return (isRegistered() ? 1 : 0);
+ }
+
static {
NULL_REGISTRATION = (ServiceRegistration)
Proxy.newProxyInstance(ServiceImpl.class.getClassLoader(), new Class[]
{ServiceRegistration.class}, new DefaultNullObject());
}