blob: 67b378d68ff72bb0ef8400b3755c9af509168a41 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2008 Cognos Incorporated, IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Cognos Incorporated - initial API and implementation
* IBM Corporation - bug fixes and enhancements
*******************************************************************************/
package org.eclipse.equinox.internal.cm;
import java.util.*;
import java.util.Map.Entry;
import org.osgi.framework.*;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedServiceFactory;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;
/**
* ManagedServiceFactoryTracker tracks... ManagedServiceFactory(s) and notifies them about related configuration changes
*/
class ManagedServiceFactoryTracker extends ServiceTracker {
final ConfigurationAdminFactory configurationAdminFactory;
private final ConfigurationStore configurationStore;
// managedServiceFactoryReferences guards both managedServiceFactories and managedServiceFactoryReferences
private final Map managedServiceFactories = new HashMap();
private final Map managedServiceFactoryReferences = new HashMap();
private final SerializedTaskQueue queue = new SerializedTaskQueue("ManagedServiceFactory Update Queue"); //$NON-NLS-1$
public ManagedServiceFactoryTracker(ConfigurationAdminFactory configurationAdminFactory, ConfigurationStore configurationStore, BundleContext context) {
super(context, ManagedServiceFactory.class.getName(), null);
this.configurationAdminFactory = configurationAdminFactory;
this.configurationStore = configurationStore;
}
protected void notifyDeleted(ConfigurationImpl config) {
config.checkLocked();
String factoryPid = config.getFactoryPid(false);
ServiceReference reference = getManagedServiceFactoryReference(factoryPid);
if (reference != null && config.bind(reference.getBundle()))
asynchDeleted(getManagedServiceFactory(factoryPid), config.getPid(false));
}
protected void notifyUpdated(ConfigurationImpl config) {
config.checkLocked();
String factoryPid = config.getFactoryPid();
ServiceReference reference = getManagedServiceFactoryReference(factoryPid);
if (reference != null && config.bind(reference.getBundle())) {
Dictionary properties = config.getProperties();
configurationAdminFactory.modifyConfiguration(reference, properties);
asynchUpdated(getManagedServiceFactory(factoryPid), config.getPid(), properties);
}
}
public Object addingService(ServiceReference reference) {
String factoryPid = (String) reference.getProperty(Constants.SERVICE_PID);
if (factoryPid == null)
return null;
ManagedServiceFactory service = (ManagedServiceFactory) context.getService(reference);
if (service == null)
return null;
synchronized (configurationStore) {
add(reference, factoryPid, service);
}
return service;
}
public void modifiedService(ServiceReference reference, Object service) {
String factoryPid = (String) reference.getProperty(Constants.SERVICE_PID);
synchronized (configurationStore) {
if (getManagedServiceFactory(factoryPid) == service)
return;
String previousPid = getPidForManagedServiceFactory(service);
remove(reference, previousPid);
addingService(reference);
}
}
public void removedService(ServiceReference reference, Object service) {
String factoryPid = (String) reference.getProperty(Constants.SERVICE_PID);
synchronized (configurationStore) {
remove(reference, factoryPid);
}
context.ungetService(reference);
}
private void add(ServiceReference reference, String factoryPid, ManagedServiceFactory service) {
ConfigurationImpl[] configs = configurationStore.getFactoryConfigurations(factoryPid);
try {
for (int i = 0; i < configs.length; ++i)
configs[i].lock();
if (trackManagedServiceFactory(factoryPid, reference, service)) {
for (int i = 0; i < configs.length; ++i) {
if (configs[i].isDeleted()) {
// ignore this config
} else if (configs[i].bind(reference.getBundle())) {
Dictionary properties = configs[i].getProperties();
configurationAdminFactory.modifyConfiguration(reference, properties);
asynchUpdated(service, configs[i].getPid(), properties);
} else {
configurationAdminFactory.log(LogService.LOG_WARNING, "Configuration for " + Constants.SERVICE_PID + "=" + configs[i].getPid() + " could not be bound to " + reference.getBundle().getLocation()); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
}
}
}
} finally {
for (int i = 0; i < configs.length; ++i)
configs[i].unlock();
}
}
private void remove(ServiceReference reference, String factoryPid) {
ConfigurationImpl[] configs = configurationStore.getFactoryConfigurations(factoryPid);
try {
for (int i = 0; i < configs.length; ++i)
configs[i].lock();
untrackManagedServiceFactory(factoryPid, reference);
} finally {
for (int i = 0; i < configs.length; ++i)
configs[i].unlock();
}
}
private boolean trackManagedServiceFactory(String factoryPid, ServiceReference reference, ManagedServiceFactory service) {
synchronized (managedServiceFactoryReferences) {
if (managedServiceFactoryReferences.containsKey(factoryPid)) {
configurationAdminFactory.log(LogService.LOG_WARNING, ManagedServiceFactory.class.getName() + " already registered for " + Constants.SERVICE_PID + "=" + factoryPid); //$NON-NLS-1$ //$NON-NLS-2$
return false;
}
managedServiceFactoryReferences.put(factoryPid, reference);
managedServiceFactories.put(factoryPid, service);
return true;
}
}
private void untrackManagedServiceFactory(String factoryPid, ServiceReference reference) {
synchronized (managedServiceFactoryReferences) {
managedServiceFactoryReferences.remove(factoryPid);
managedServiceFactories.remove(factoryPid);
}
}
private ManagedServiceFactory getManagedServiceFactory(String factoryPid) {
synchronized (managedServiceFactoryReferences) {
return (ManagedServiceFactory) managedServiceFactories.get(factoryPid);
}
}
private ServiceReference getManagedServiceFactoryReference(String factoryPid) {
synchronized (managedServiceFactoryReferences) {
return (ServiceReference) managedServiceFactoryReferences.get(factoryPid);
}
}
private String getPidForManagedServiceFactory(Object service) {
synchronized (managedServiceFactoryReferences) {
for (Iterator it = managedServiceFactories.entrySet().iterator(); it.hasNext();) {
Entry entry = (Entry) it.next();
if (entry.getValue() == service)
return (String) entry.getKey();
}
return null;
}
}
private void asynchDeleted(final ManagedServiceFactory service, final String pid) {
queue.put(new Runnable() {
public void run() {
try {
service.deleted(pid);
} catch (Throwable t) {
configurationAdminFactory.log(LogService.LOG_ERROR, t.getMessage(), t);
}
}
});
}
private void asynchUpdated(final ManagedServiceFactory service, final String pid, final Dictionary properties) {
queue.put(new Runnable() {
public void run() {
try {
service.updated(pid, properties);
} catch (ConfigurationException e) {
// we might consider doing more for ConfigurationExceptions
Throwable cause = e.getCause();
configurationAdminFactory.log(LogService.LOG_ERROR, e.getMessage(), cause != null ? cause : e);
} catch (Throwable t) {
configurationAdminFactory.log(LogService.LOG_ERROR, t.getMessage(), t);
}
}
});
}
}