/*******************************************************************************
* Copyright (c) 2006 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:
* IBM Corporation - initial API and implementation
******************************************************************************/
package org.eclipse.ui.internal.services;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.services.IDisposable;
import org.eclipse.ui.services.IServiceLocator;
/**
* @since 3.2
*
*/
public final class ServiceLocator implements IDisposable, INestable,
IServiceLocator {
/**
* The parent for this service locator. If a service can't be found in this
* locator, then the parent is asked. This value may be <code>null</code>
* if there is no parent.
*/
private final IServiceLocator parent;
/**
* The map of services maintained by the workbench window. These services
* are initialized during workbench window during the
* {@link #configureShell(Shell)}. This value is <code>null</code> until
* a service is registered.
*/
private Map services = null;
/**
* Constructs a service locator with no parent.
*/
public ServiceLocator() {
this(null);
}
/**
* Constructs a service locator with the given parent.
*
* @param parent
* The parent for this service locator; this value may be
* <code>null</code>.
*/
public ServiceLocator(final IServiceLocator parent) {
this.parent = parent;
}
public final void activate() {
if (services != null) {
final Iterator serviceItr = services.values().iterator();
while (serviceItr.hasNext()) {
final Object service = serviceItr.next();
if (service instanceof INestable) {
final INestable nestableService = (INestable) service;
nestableService.activate();
}
}
}
}
public final void deactivate() {
if (services != null) {
final Iterator serviceItr = services.values().iterator();
while (serviceItr.hasNext()) {
final Object service = serviceItr.next();
if (service instanceof INestable) {
final INestable nestableService = (INestable) service;
nestableService.deactivate();
}
}
}
}
public final void dispose() {
if (services != null) {
final Iterator serviceItr = services.values().iterator();
while (serviceItr.hasNext()) {
final Object object = serviceItr.next();
if (object instanceof IDisposable) {
final IDisposable service = (IDisposable) object;
service.dispose();
}
}
services = null;
}
}
public final Object getService(final Class key) {
final Object service;
if (services != null) {
service = services.get(key);
} else {
service = null;
}
if ((service == null) && (parent != null)) {
return parent.getService(key);
}
return service;
}
public final boolean hasService(final Class key) {
if (services != null) {
if (services.containsKey(key)) {
return true;
}
}
return false;
}
/**
* Registers a service with this locator. If there is an existing service
* matching the same <code>api</code> and it implements
* {@link IDisposable}, it will be disposed.
*
* @param api
* This is the interface that the service implements. Must not be
* <code>null</code>.
* @param service
* The service to register. This must be some implementation of
* <code>api</code>. This value must not be <code>null</code>.
*/
public final void registerService(final Class api, final Object service) {
if (api == null) {
throw new NullPointerException("The service key cannot be null"); //$NON-NLS-1$
}
if (!api.isInstance(service)) {
throw new IllegalArgumentException(
"The service does not implement the given interface"); //$NON-NLS-1$
}
if (services == null) {
services = new HashMap();
}
if (services.containsKey(api)) {
final Object currentService = services.remove(api);
if (currentService instanceof IDisposable) {
final IDisposable disposable = (IDisposable) currentService;
disposable.dispose();
}
}
if (service == null) {
if (services.isEmpty()) {
services = null;
}
} else {
services.put(api, service);
}
}
}