/*******************************************************************************
* Mission Control Technologies, Copyright (c) 2009-2012, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* The MCT platform is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* MCT includes source code licensed under additional open source licenses. See
* the MCT Open Source Licenses file included with this distribution or the About
* MCT Licenses dialog available at runtime from the MCT Help menu for additional
* information.
*******************************************************************************/
package gov.nasa.arc.mct.table.access;
import java.util.HashMap;
import java.util.Map;
/**
* Implements an accessor class for an OSGi service. This class is designed
* to be used as an OSGi declarative services component. Instances of this
* component may have references to more than one service. The services are
* looked up by class. However, each class of service is limited to a
* cardinality of 1, because the services are stored in a map.
*/
public class ServiceAccess {
private static final Map<Class<?>, Object> services = new HashMap<Class<?>, Object>();
/**
* Returns the service instance, cast to the desired type. This method must
* take an argument of the desired type, because of a limitation of Java
* generic types: static methods cannot return the exact type desired, because
* they must have the same signature when type erasure is applied. In the case
* of this method, the only class we can return is the parameterized type of
* the derived class. But we can't force the return type to be that type
* after type erasure.
*
* <p>The first matching service is found. A service matches if the desired class
* is a superclass of a bound service. If more then one service might match, the
* actual service returned is implementation-specific. (Depends on the order of
* the hash key set.)
*
* @param <T> the service type desired
* @param clazz the class to cast the service to
* @return the bound instance of the service, cast to the desired type,
* or null if the service has not yet been bound
* @throws ClassCastException if the service is not of the desired type
*/
public final static <T> T getService(Class<T> clazz) {
synchronized(services) {
for (Class<?> actualClass : services.keySet()) {
if (clazz.isAssignableFrom(actualClass)) {
return clazz.cast(services.get(actualClass));
}
}
}
return null;
}
/**
* Sets the active instance of the service.
*
* @param serviceInstance the instance of the service
*/
public final void bind(Object serviceInstance) {
synchronized (services) {
services.put(serviceInstance.getClass(), serviceInstance);
}
}
/**
* Releases the instance of the service.
*
* @param serviceInstance the service instance to remove from the set of bindings
*/
public final void unbind(Object serviceInstance) {
synchronized (services) {
services.remove(serviceInstance.getClass());
}
}
}