/*******************************************************************************
* 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.completers;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.virgo.shell.CommandCompleter;
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 dynamic registry of {@link CommandCompleter CommandCompleters} backed by the OSGi
* service registry.
* <p />
*
* <strong>Concurrent Semantics</strong><br />
*
* Thread-safe.
*
*/
final class ServiceRegistryCommandCompleterRegistry implements CommandCompleterRegistry {
private final ServiceListener commandCompleterRegistryServiceListener = new ConverterRegistryServiceListener();
private final Map<String, CommandCompleter> completers = new HashMap<String, CommandCompleter>();
private final Object monitor = new Object();
private final BundleContext bundleContext;
ServiceRegistryCommandCompleterRegistry(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
/**
* {@inheritDoc}
*/
public CommandCompleter getCommandCompleter(String commandName) {
synchronized(this.monitor) {
return this.completers.get(commandName);
}
}
void initialize() {
try {
this.bundleContext.addServiceListener(this.commandCompleterRegistryServiceListener, "(objectClass=" + CommandCompleter.class.getName() + ")");
ServiceReference<?>[] serviceReferences = this.bundleContext.getServiceReferences(CommandCompleter.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) {
CommandCompleter completer = (CommandCompleter)bundleContext.getService(serviceReference);
if (completer != null) {
String[] commandNames = getCommandNames(serviceReference);
for (String commandName : commandNames) {
this.completers.put(commandName, completer);
}
}
}
private String[] getCommandNames(ServiceReference<?> serviceReference) {
Object commandNamesProperty = serviceReference.getProperty(CommandCompleter.SERVICE_PROPERTY_COMPLETER_COMMAND_NAMES);
String[] commandNames;
if (commandNamesProperty instanceof String[]) {
commandNames = (String[])commandNamesProperty;
} else if (commandNamesProperty instanceof String) {
commandNames = new String[] {(String)commandNamesProperty};
} else {
commandNames = new String[0];
}
return commandNames;
}
private void serviceUnregistering(ServiceReference<?> serviceReference) {
Object converter = this.bundleContext.getService(serviceReference);
if (converter != null) {
String[] commandNames = getCommandNames(serviceReference);
synchronized (monitor) {
for (String commandName : commandNames) {
this.completers.remove(commandName);
}
}
}
}
private final class ConverterRegistryServiceListener implements ServiceListener {
/**
* {@inheritDoc}
*/
public void serviceChanged(ServiceEvent event) {
if (ServiceEvent.REGISTERED == event.getType()) {
serviceRegistered(event.getServiceReference());
} else if (ServiceEvent.UNREGISTERING == event.getType()) {
serviceUnregistering(event.getServiceReference());
}
}
}
}