/*******************************************************************************
* Copyright (c) 2008, 2010 VMware Inc.
* 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:
* VMware Inc. - initial contribution
*******************************************************************************/
package org.eclipse.virgo.shell.internal.converters;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.virgo.shell.Converter;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
/**
* A registry of {@link Converter Converters} backed by the OSGi service registry.
*
* <p />
*
* <strong>Concurrent Semantics</strong><br />
*
* Thread-safe.
*
*/
final class ServiceRegistryConverterRegistry implements ConverterRegistry {
private final ServiceListener converterRegistryServiceListener = new ConverterRegistryServiceListener();
private final Map<String, Converter> converters = new HashMap<String, Converter>();
private final Object monitor = new Object();
private final BundleContext bundleContext;
ServiceRegistryConverterRegistry(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
/**
* {@inheritDoc}
*/
public Converter getConverter(Class<?> clazz) {
synchronized(this.monitor) {
return this.converters.get(clazz.getName());
}
}
void initialize() {
try {
this.bundleContext.addServiceListener(this.converterRegistryServiceListener, "(objectClass=" + Converter.class.getName() + ")");
ServiceReference<?>[] serviceReferences = this.bundleContext.getServiceReferences(Converter.class.getName(), null);
if (serviceReferences != null) {
for (ServiceReference<?> serviceReference : serviceReferences) {
serviceRegistered(serviceReference);
}
}
} catch (InvalidSyntaxException e) {
throw new RuntimeException("Unexpected InvalidSyntaxException", e);
}
}
private void serviceRegistered(ServiceReference<?> serviceReference) {
Converter converter = (Converter)bundleContext.getService(serviceReference);
if (converter != null) {
String[] converterClasses = getConverterClasses(serviceReference);
for (String converterClass : converterClasses) {
this.converters.put(converterClass, converter);
}
}
}
private String[] getConverterClasses(ServiceReference<?> serviceReference) {
Object converterClassesProperty = serviceReference.getProperty(Converter.CONVERTER_CLASSES);
String[] converterClasses;
if (converterClassesProperty instanceof String[]) {
converterClasses = (String[])converterClassesProperty;
} else if (converterClassesProperty instanceof String) {
converterClasses = new String[] {(String)converterClassesProperty};
} else {
converterClasses = new String[0];
}
return converterClasses;
}
private void serviceUnregistering(ServiceReference<?> serviceReference) {
Object converter = this.bundleContext.getService(serviceReference);
if (converter != null) {
synchronized (monitor) {
Iterator<Entry<String, Converter>> iterator = this.converters.entrySet().iterator();
while (iterator.hasNext()) {
Converter candidate = iterator.next().getValue();
if (converter.equals(candidate)) {
iterator.remove();
}
}
}
}
}
private final class ConverterRegistryServiceListener implements ServiceListener {
public void serviceChanged(ServiceEvent event) {
if (ServiceEvent.REGISTERED == event.getType()) {
serviceRegistered(event.getServiceReference());
} else if (ServiceEvent.UNREGISTERING == event.getType()) {
serviceUnregistering(event.getServiceReference());
}
}
}
}