/*******************************************************************************
* 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.kernel.osgi.framework;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
/**
* Utility methods for working the OSGi framework and {@link Bundle Bundles}.
* <p/>
*
* <strong>Concurrent Semantics</strong><br />
*
* Threadsafe.
*
*/
public final class OsgiFrameworkUtils {
private static final String HEADER_MODULE_SCOPE = "Module-Scope";
/**
* Gets the scope for the supplied {@link Bundle}.
*
* @param bundle the <code>Bundle</code>.
* @return the scope, or <code>null</code> if no scope is specified.
*/
public static String getScopeName(Bundle bundle) {
return (String) bundle.getHeaders().get(HEADER_MODULE_SCOPE);
}
/**
* Queries whether the supplied {@link Bundle} is scoped.
*
* @param bundle the <code>Bundle</code>.
* @return <code>true</code> if the <code>Bundle</code> is scoped, otherwise <code>false</code>.
*/
public static boolean isScoped(Bundle bundle) {
String scope = getScopeName(bundle);
return scope != null && scope.length() > 0;
}
/**
* Queries whether both supplied {@link Bundle Bundles} are in the same scope.
*
* @param a the first <code>Bundle</code>.
* @param b the second <code>Bundle</code>.
* @return <code>true</code> if both <code>Bundles</code> are in the same scope.
*/
public static boolean sameScope(Bundle a, Bundle b) {
String scopeA = getScopeName(a);
if (scopeA == null || scopeA.length() == 0) {
return false;
} else {
return scopeA.equals(getScopeName(b));
}
}
/**
* Indicates whether or not the supplied {@link Bundle} is active.
*
* @param bundle The bundle to query
* @return <code>true</code> if the supplied bundle is active, otherwise <code>false</code>.
* @see Bundle#getState()
* @see Bundle#ACTIVE
*/
public static boolean isBundleActive(Bundle bundle) {
return bundle.getState() == Bundle.ACTIVE;
}
@SuppressWarnings("unchecked")
public static <T> OsgiServiceHolder<T> getService(BundleContext bundleContext, Class<T> clazz) {
final ServiceReference<T> reference = (ServiceReference<T>) bundleContext.getServiceReference(clazz.getName());
if (reference != null) {
final T service = (T) bundleContext.getService(reference);
return new StandardOsgiServiceHolder<T>(service, reference);
} else {
return null;
}
}
/**
* Returns an ordered list of {@link OsgiServiceHolder OsgiServiceHolders}, one for each service in the service
* registry which was published under the supplied <code>serviceType</code>. The service lookup is performed using
* the supplied <code>bundleContext</code>.
* <p/>
* The ordering of the <code>OsgiServiceHolder</code>s is determined by the
* {@link ServiceReference#compareTo(Object) ordering} of the encapsulated {@link ServiceReference
* ServiceReferences}.
* <p/>
* @param bundleContext in which to lookup services
* @param serviceType of service to look for
* @param <T> of service
* @return list of {@link OsgiServiceHolder}s
*/
@SuppressWarnings("unchecked")
public static <T> List<OsgiServiceHolder<T>> getServices(BundleContext bundleContext, Class<T> serviceType) {
List<OsgiServiceHolder<T>> serviceHolders = new ArrayList<OsgiServiceHolder<T>>();
try {
ServiceReference<T>[] serviceReferences = (ServiceReference<T>[]) bundleContext.getServiceReferences(serviceType.getName(), null);
if (serviceReferences != null) {
for (ServiceReference<T> serviceReference : serviceReferences) {
T service = (T) bundleContext.getService(serviceReference);
if (service != null) {
serviceHolders.add(new StandardOsgiServiceHolder<T>(service, serviceReference));
}
}
Collections.sort(serviceHolders);
}
} catch (InvalidSyntaxException ise) {
throw new OsgiFrameworkException(ise);
}
return serviceHolders;
}
private static class StandardOsgiServiceHolder<T> implements OsgiServiceHolder<T>, Comparable<OsgiServiceHolder<?>> {
private final T service;
private final ServiceReference<T> serviceReference;
private StandardOsgiServiceHolder(T service, ServiceReference<T> serviceReference) {
this.service = service;
this.serviceReference = serviceReference;
}
/**
* {@inheritDoc}
*/
public T getService() {
return this.service;
}
/**
* {@inheritDoc}
*/
public ServiceReference<T> getServiceReference() {
return this.serviceReference;
}
/**
* {@inheritDoc}
*/
public int compareTo(OsgiServiceHolder<?> o) {
return this.serviceReference.compareTo(o.getServiceReference());
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (this.serviceReference == null ? 0 : this.serviceReference.hashCode());
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
StandardOsgiServiceHolder<?> other = (StandardOsgiServiceHolder<?>) obj;
if (this.serviceReference == null) {
if (other.serviceReference != null) {
return false;
}
} else if (!this.serviceReference.equals(other.serviceReference)) {
return false;
}
return true;
}
}
}