Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.eclipse.osgi.internal.framework.BundleContextImpl Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2003, 2013 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.osgi.internal.framework;
import java.io.*;
import java.net.URLConnection;
import java.security.*;
import java.util.*;
import org.eclipse.osgi.container.Module;
import org.eclipse.osgi.container.ModuleWiring;
import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
import org.eclipse.osgi.framework.eventmgr.EventDispatcher;
import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.loader.BundleLoader;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.internal.serviceregistry.*;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
import org.osgi.framework.hooks.bundle.FindHook;
import org.osgi.resource.Capability;
/**
* Bundle's execution context.
*
* This object is given out to bundles and provides the
* implementation to the BundleContext for a host bundle.
* It is destroyed when a bundle is stopped.
*/
public class BundleContextImpl implements BundleContext, EventDispatcher {
static final String findHookName = FindHook.class.getName();
/** true if the bundle context is still valid */
private volatile boolean valid;
/** Bundle object this context is associated with. */
// This slot is accessed directly by the Framework instead of using
// the getBundle() method because the Framework needs access to the bundle
// even when the context is invalid while the close method is being called.
final EquinoxBundle bundle;
/** Internal equinox container object. */
final EquinoxContainer container;
final Debug debug;
/** Services that bundle is using. Key is ServiceRegistrationImpl,
Value is ServiceUse */
/* @GuardedBy("contextLock") */
private HashMap, ServiceUse>> servicesInUse;
/** The current instantiation of the activator. */
private BundleActivator activator;
/** private object for locking */
private final Object contextLock = new Object();
/**
* Construct a BundleContext which wrappers the framework for a
* bundle
*
* @param bundle The bundle we are wrapping.
*/
public BundleContextImpl(EquinoxBundle bundle, EquinoxContainer container) {
this.bundle = bundle;
this.container = container;
this.debug = container.getConfiguration().getDebug();
valid = true;
synchronized (contextLock) {
servicesInUse = null;
}
activator = null;
}
/**
* Destroy the wrapper. This is called when the bundle is stopped.
*
*/
protected void close() {
valid = false; /* invalidate context */
final ServiceRegistry registry = container.getServiceRegistry();
registry.removeAllServiceListeners(this);
container.getEventPublisher().removeAllListeners(this);
/* service's registered by the bundle, if any, are unregistered. */
registry.unregisterServices(this);
/* service's used by the bundle, if any, are released. */
registry.releaseServicesInUse(this);
synchronized (contextLock) {
servicesInUse = null;
}
}
/**
* Retrieve the value of the named environment property.
*
* @param key The name of the requested property.
* @return The value of the requested property, or null
if
* the property is undefined.
*/
public String getProperty(String key) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
return (container.getConfiguration().getProperty(key));
}
/**
* Retrieve the Bundle object for the context bundle.
*
* @return The context bundle's Bundle object.
*/
public Bundle getBundle() {
checkValid();
return getBundleImpl();
}
public EquinoxBundle getBundleImpl() {
return bundle;
}
public Bundle installBundle(String location) throws BundleException {
return installBundle(location, null);
}
public Bundle installBundle(String location, InputStream in) throws BundleException {
checkValid();
try {
URLConnection content = container.getStorage().getContentConnection(null, location, in);
Generation generation = container.getStorage().install(bundle.getModule(), location, content);
return generation.getRevision().getBundle();
} catch (IOException e) {
throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
}
}
/**
* Retrieve the bundle that has the given unique identifier.
*
* @param id The identifier of the bundle to retrieve.
* @return A Bundle object, or null
* if the identifier doesn't match any installed bundle.
*/
public Bundle getBundle(long id) {
Module m = container.getStorage().getModuleContainer().getModule(id);
if (m == null) {
return null;
}
List bundles = new ArrayList(1);
bundles.add(m.getBundle());
notifyFindHooks(this, bundles);
if (bundles.isEmpty()) {
return null;
}
return m.getBundle();
}
public Bundle getBundle(String location) {
Module m = container.getStorage().getModuleContainer().getModule(location);
return m == null ? null : m.getBundle();
}
/**
* Retrieve a list of all installed bundles.
* The list is valid at the time
* of the call to getBundles, but the framework is a very dynamic
* environment and bundles can be installed or uninstalled at anytime.
*
* @return An array of {@link Bundle} objects, one
* object per installed bundle.
*/
public Bundle[] getBundles() {
List modules = container.getStorage().getModuleContainer().getModules();
List bundles = new ArrayList(modules.size());
for (Module module : modules) {
bundles.add(module.getBundle());
}
notifyFindHooks(this, bundles);
return bundles.toArray(new Bundle[bundles.size()]);
}
private void notifyFindHooks(final BundleContextImpl context, List allBundles) {
if (context.getBundleImpl().getBundleId() == 0) {
// Make a copy for the purposes of calling the hooks;
// The the removals from the hooks are ignored
allBundles = new ArrayList(allBundles);
}
final Collection shrinkable = new ShrinkableCollection(allBundles);
if (System.getSecurityManager() == null) {
notifyFindHooksPriviledged(context, shrinkable);
} else {
AccessController.doPrivileged(new PrivilegedAction() {
public Void run() {
notifyFindHooksPriviledged(context, shrinkable);
return null;
}
});
}
}
void notifyFindHooksPriviledged(final BundleContextImpl context, final Collection allBundles) {
if (debug.DEBUG_HOOKS) {
Debug.println("notifyBundleFindHooks(" + allBundles + ")"); //$NON-NLS-1$ //$NON-NLS-2$
}
container.getServiceRegistry().notifyHooksPrivileged(new HookContext() {
public void call(Object hook, ServiceRegistration> hookRegistration) throws Exception {
if (hook instanceof FindHook) {
((FindHook) hook).find(context, allBundles);
}
}
public String getHookClassName() {
return findHookName;
}
public String getHookMethodName() {
return "find"; //$NON-NLS-1$
}
});
}
public void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException {
checkValid();
if (listener == null) {
throw new IllegalArgumentException();
}
container.getServiceRegistry().addServiceListener(this, listener, filter);
}
/**
* Add a service listener.
*
* This method is the same as calling
* {@link #addServiceListener(ServiceListener, String)}
* with filter set to null
.
*
* @see #addServiceListener(ServiceListener, String)
*/
public void addServiceListener(ServiceListener listener) {
try {
addServiceListener(listener, null);
} catch (InvalidSyntaxException e) {
if (debug.DEBUG_GENERAL) {
Debug.println("InvalidSyntaxException w/ null filter" + e.getMessage()); //$NON-NLS-1$
Debug.printStackTrace(e);
}
}
}
/**
* Remove a service listener.
* The listener is removed from the context bundle's list of listeners.
* See {@link #getBundle() getBundle()}
* for a definition of context bundle.
*
*
If this method is called with a listener which is not registered,
* then this method does nothing.
*
* @param listener The service listener to remove.
* @exception java.lang.IllegalStateException
* If the bundle context has stopped.
*/
public void removeServiceListener(ServiceListener listener) {
checkValid();
if (listener == null) {
throw new IllegalArgumentException();
}
container.getServiceRegistry().removeServiceListener(this, listener);
}
/**
* Add a bundle listener.
* {@link BundleListener}s are notified when a bundle has a lifecycle
* state change.
* The listener is added to the context bundle's list of listeners.
* See {@link #getBundle() getBundle()}
* for a definition of context bundle.
*
* @param listener The bundle listener to add.
* @exception java.lang.IllegalStateException
* If the bundle context has stopped.
* @see BundleEvent
* @see BundleListener
*/
public void addBundleListener(BundleListener listener) {
checkValid();
if (listener == null) {
throw new IllegalArgumentException();
}
if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("addBundleListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
container.getEventPublisher().addBundleListener(listener, this);
}
/**
* Remove a bundle listener.
* The listener is removed from the context bundle's list of listeners.
* See {@link #getBundle() getBundle()}
* for a definition of context bundle.
*
*
If this method is called with a listener which is not registered,
* then this method does nothing.
*
* @param listener The bundle listener to remove.
* @exception java.lang.IllegalStateException
* If the bundle context has stopped.
*/
public void removeBundleListener(BundleListener listener) {
checkValid();
if (listener == null) {
throw new IllegalArgumentException();
}
if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("removeBundleListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
container.getEventPublisher().removeBundleListener(listener, this);
}
/**
* Add a general framework listener.
* {@link FrameworkListener}s are notified of general framework events.
* The listener is added to the context bundle's list of listeners.
* See {@link #getBundle() getBundle()}
* for a definition of context bundle.
*
* @param listener The framework listener to add.
* @exception java.lang.IllegalStateException
* If the bundle context has stopped.
* @see FrameworkEvent
* @see FrameworkListener
*/
public void addFrameworkListener(FrameworkListener listener) {
checkValid();
if (listener == null) {
throw new IllegalArgumentException();
}
if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("addFrameworkListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
container.getEventPublisher().addFrameworkListener(listener, this);
}
/**
* Remove a framework listener.
* The listener is removed from the context bundle's list of listeners.
* See {@link #getBundle() getBundle()}
* for a definition of context bundle.
*
*
If this method is called with a listener which is not registered,
* then this method does nothing.
*
* @param listener The framework listener to remove.
* @exception java.lang.IllegalStateException
* If the bundle context has stopped.
*/
public void removeFrameworkListener(FrameworkListener listener) {
checkValid();
if (listener == null) {
throw new IllegalArgumentException();
}
if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("removeFrameworkListener[" + bundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
container.getEventPublisher().removeFrameworkListener(listener, this);
}
/**
* Register a service with multiple names.
* This method registers the given service object with the given properties
* under the given class names.
* A {@link ServiceRegistration} object is returned.
* The {@link ServiceRegistration} object is for the private use of the bundle
* registering the service and should not be shared with other bundles.
* The registering bundle is defined to be the context bundle.
* See {@link #getBundle()} for a definition of context bundle.
* Other bundles can locate the service by using either the
* {@link #getServiceReferences getServiceReferences} or
* {@link #getServiceReference getServiceReference} method.
*
*
A bundle can register a service object that implements the
* {@link ServiceFactory} interface to
* have more flexiblity in providing service objects to different
* bundles.
*
*
The following steps are followed to register a service:
*
* If the service parameter is not a {@link ServiceFactory},
* an IllegalArgumentException
is thrown if the
* service parameter is not an instanceof
* all the classes named.
* The service is added to the framework's service registry
* and may now be used by other bundles.
* A {@link ServiceEvent} of type {@link ServiceEvent#REGISTERED}
* is synchronously sent.
* A {@link ServiceRegistration} object for this registration
* is returned.
*
*
* @param clazzes The class names under which the service can be located.
* The class names in this array will be stored in the service's
* properties under the key "objectClass".
* @param service The service object or a {@link ServiceFactory} object.
* @param properties The properties for this service.
* The keys in the properties object must all be Strings.
* Changes should not be made to this object after calling this method.
* To update the service's properties call the
* {@link ServiceRegistration#setProperties ServiceRegistration.setProperties}
* method.
* This parameter may be null
if the service has no properties.
* @return A {@link ServiceRegistration} object for use by the bundle
* registering the service to update the
* service's properties or to unregister the service.
* @exception java.lang.IllegalArgumentException If one of the following is true:
*
* The service parameter is null.
* The service parameter is not a {@link ServiceFactory} and is not an
* instanceof
all the named classes in the clazzes parameter.
*
* @exception java.lang.SecurityException If the caller does not have
* {@link ServicePermission} permission to "register" the service for
* all the named classes
* and the Java runtime environment supports permissions.
* @exception java.lang.IllegalStateException
* If the bundle context has stopped.
* @see ServiceRegistration
* @see ServiceFactory
*/
public ServiceRegistration> registerService(String[] clazzes, Object service, Dictionary properties) {
checkValid();
return container.getServiceRegistry().registerService(this, clazzes, service, properties);
}
/**
* Register a service with a single name.
* This method registers the given service object with the given properties
* under the given class name.
*
* This method is otherwise identical to
* {@link #registerService(java.lang.String[], java.lang.Object, java.util.Dictionary)}
* and is provided as a convenience when the service parameter will only be registered
* under a single class name.
*
* @see #registerService(java.lang.String[], java.lang.Object, java.util.Dictionary)
*/
public ServiceRegistration> registerService(String clazz, Object service, Dictionary properties) {
String[] clazzes = new String[] {clazz};
return registerService(clazzes, service, properties);
}
/**
* Returns a list of ServiceReference objects. This method returns a list of
* ServiceReference objects for services which implement and were registered under
* the specified class and match the specified filter criteria.
*
* The list is valid at the time of the call to this method, however as the Framework is
* a very dynamic environment, services can be modified or unregistered at anytime.
*
*
filter is used to select the registered service whose
* properties objects contain keys and values which satisfy the filter.
* See {@link Filter}for a description of the filter string syntax.
*
*
If filter is null , all registered services
* are considered to match the filter.
*
If filter cannot be parsed, an {@link InvalidSyntaxException} will
* be thrown with a human readable message where the filter became unparsable.
*
*
The following steps are required to select a service:
*
* If the Java Runtime Environment supports permissions, the caller is checked for the
* ServicePermission to get the service with the specified class.
* If the caller does not have the correct permission, null is returned.
* If the filter string is not null , the filter string is
* parsed and the set of registered services which satisfy the filter is
* produced.
* If the filter string is null , then all registered services
* are considered to satisfy the filter.
* If clazz
is not null , the set is further reduced to
* those services which are an instanceof and were registered under the specified class.
* The complete list of classes of which a service is an instance and which
* were specified when the service was registered is available from the
* service's {@link Constants#OBJECTCLASS}property.
* An array of ServiceReference to the selected services is returned.
*
*
* @param clazz The class name with which the service was registered, or
* null for all services.
* @param filter The filter criteria.
* @return An array of ServiceReference objects, or
* null if no services are registered which satisfy the search.
* @exception InvalidSyntaxException If filter contains
* an invalid filter string which cannot be parsed.
*/
public ServiceReference>[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
checkValid();
return container.getServiceRegistry().getServiceReferences(this, clazz, filter, false);
}
public ServiceReference>[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
checkValid();
return container.getServiceRegistry().getServiceReferences(this, clazz, filter, true);
}
/**
* Get a service reference.
* Retrieves a {@link ServiceReference} for a service
* which implements the named class.
*
* This reference is valid at the time
* of the call to this method, but since the framework is a very dynamic
* environment, services can be modified or unregistered at anytime.
*
*
This method is provided as a convenience for when the caller is
* interested in any service which implements a named class. This method is
* the same as calling {@link #getServiceReferences getServiceReferences}
* with a null
filter string but only a single {@link ServiceReference}
* is returned.
*
* @param clazz The class name which the service must implement.
* @return A {@link ServiceReference} object, or null
* if no services are registered which implement the named class.
* @see #getServiceReferences
*/
public ServiceReference> getServiceReference(String clazz) {
checkValid();
return container.getServiceRegistry().getServiceReference(this, clazz);
}
/**
* Get a service's service object.
* Retrieves the service object for a service.
* A bundle's use of a service is tracked by a
* use count. Each time a service's service object is returned by
* {@link #getService}, the context bundle's use count for the service
* is incremented by one. Each time the service is release by
* {@link #ungetService}, the context bundle's use count
* for the service is decremented by one.
* When a bundle's use count for a service
* drops to zero, the bundle should no longer use the service.
* See {@link #getBundle()} for a definition of context bundle.
*
*
This method will always return null
when the
* service associated with this reference has been unregistered.
*
*
The following steps are followed to get the service object:
*
* If the service has been unregistered,
* null
is returned.
* The context bundle's use count for this service is incremented by one.
* If the context bundle's use count for the service is now one and
* the service was registered with a {@link ServiceFactory},
* the {@link ServiceFactory#getService ServiceFactory.getService} method
* is called to create a service object for the context bundle.
* This service object is cached by the framework.
* While the context bundle's use count for the service is greater than zero,
* subsequent calls to get the services's service object for the context bundle
* will return the cached service object.
* If the service object returned by the {@link ServiceFactory}
* is not an instanceof
* all the classes named when the service was registered or
* the {@link ServiceFactory} throws an exception,
* null
is returned and a
* {@link FrameworkEvent} of type {@link FrameworkEvent#ERROR} is broadcast.
* The service object for the service is returned.
*
*
* @param reference A reference to the service whose service object is desired.
* @return A service object for the service associated with this
* reference, or null
if the service is not registered.
* @exception java.lang.SecurityException If the caller does not have
* {@link ServicePermission} permission to "get" the service
* using at least one of the named classes the service was registered under
* and the Java runtime environment supports permissions.
* @exception java.lang.IllegalStateException
* If the bundle context has stopped.
* @see #ungetService
* @see ServiceFactory
*/
public S getService(ServiceReference reference) {
checkValid();
if (reference == null)
throw new NullPointerException("A null service reference is not allowed."); //$NON-NLS-1$
provisionServicesInUseMap();
S service = container.getServiceRegistry().getService(this, (ServiceReferenceImpl) reference);
return service;
}
/**
* Unget a service's service object.
* Releases the service object for a service.
* If the context bundle's use count for the service is zero, this method
* returns false
. Otherwise, the context bundle's use count for the
* service is decremented by one.
* See {@link #getBundle()} for a definition of context bundle.
*
* The service's service object
* should no longer be used and all references to it should be destroyed
* when a bundle's use count for the service
* drops to zero.
*
*
The following steps are followed to unget the service object:
*
* If the context bundle's use count for the service is zero or
* the service has been unregistered,
* false
is returned.
* The context bundle's use count for this service is decremented by one.
* If the context bundle's use count for the service is now zero and
* the service was registered with a {@link ServiceFactory},
* the {@link ServiceFactory#ungetService ServiceFactory.ungetService} method
* is called to release the service object for the context bundle.
* true
is returned.
*
*
* @param reference A reference to the service to be released.
* @return false
if the context bundle's use count for the service
* is zero or if the service has been unregistered,
* otherwise true
.
* @exception java.lang.IllegalStateException
* If the bundle context has stopped.
* @see #getService
* @see ServiceFactory
*/
public boolean ungetService(ServiceReference> reference) {
checkValid();
return container.getServiceRegistry().ungetService(this, (ServiceReferenceImpl>) reference);
}
/**
* Creates a File
object for a file in the
* persistent storage area provided for the bundle by the framework.
* If the adaptor does not have file system support, this method will
* return null
.
*
* A File
object for the base directory of the
* persistent storage area provided for the context bundle by the framework
* can be obtained by calling this method with the empty string ("")
* as the parameter.
* See {@link #getBundle()} for a definition of context bundle.
*
*
If the Java runtime environment supports permissions,
* the framework the will ensure that the bundle has
* java.io.FilePermission
with actions
* "read","write","execute","delete" for all files (recursively) in the
* persistent storage area provided for the context bundle by the framework.
*
* @param filename A relative name to the file to be accessed.
* @return A File
object that represents the requested file or
* null
if the adaptor does not have file system support.
* @exception java.lang.IllegalStateException
* If the bundle context has stopped.
*/
public File getDataFile(String filename) {
checkValid();
Generation generation = (Generation) bundle.getModule().getCurrentRevision().getRevisionInfo();
return generation.getBundleInfo().getDataFile(filename);
}
/**
* Call bundle's BundleActivator.start()
* This method is called by Bundle.startWorker to start the bundle.
*
* @exception BundleException if
* the bundle has a class that implements the BundleActivator interface,
* but Framework couldn't instantiate it, or the BundleActivator.start()
* method failed
*/
protected void start() throws BundleException {
try {
activator = loadBundleActivator();
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new BundleException(Msg.BundleContextImpl_LoadActivatorError, BundleException.ACTIVATOR_ERROR, e);
}
if (activator != null) {
long start = 0;
if (debug.DEBUG_BUNDLE_TIME) {
start = System.currentTimeMillis();
Debug.println("Starting " + bundle); //$NON-NLS-1$
}
try {
startActivator(activator);
} catch (BundleException be) {
activator = null;
throw be;
} finally {
if (debug.DEBUG_BUNDLE_TIME) {
Debug.println("End starting " + bundle + " " + (System.currentTimeMillis() - start)); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
/* activator completed successfully. We must use this
same activator object when we stop this bundle. */
}
private BundleActivator loadBundleActivator() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
ModuleWiring wiring = bundle.getModule().getCurrentRevision().getWiring();
if (wiring == null) {
return null;
}
BundleLoader loader = (BundleLoader) wiring.getModuleLoader();
if (loader == null) {
return null;
}
List metadata = wiring.getRevision().getCapabilities(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE);
if (metadata.isEmpty()) {
return null;
}
String activatorName = (String) metadata.get(0).getAttributes().get(EquinoxModuleDataNamespace.CAPABILITY_ACTIVATOR);
if (activatorName == null) {
return null;
}
Class> activatorClass = loader.findClass(activatorName);
return (BundleActivator) activatorClass.newInstance();
}
/**
* Calls the start method of a BundleActivator.
* @param bundleActivator that activator to start
*/
private void startActivator(final BundleActivator bundleActivator) throws BundleException {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Void run() throws Exception {
if (bundleActivator != null) {
// make sure the context class loader is set correctly
Object previousTCCL = setContextFinder();
/* Start the bundle synchronously */
try {
bundleActivator.start(BundleContextImpl.this);
} finally {
if (previousTCCL != Boolean.FALSE)
Thread.currentThread().setContextClassLoader((ClassLoader) previousTCCL);
}
}
return null;
}
});
} catch (Throwable t) {
if (t instanceof PrivilegedActionException) {
t = ((PrivilegedActionException) t).getException();
}
if (debug.DEBUG_GENERAL) {
Debug.printStackTrace(t);
}
String clazz = null;
clazz = bundleActivator.getClass().getName();
throw new BundleException(NLS.bind(Msg.BUNDLE_ACTIVATOR_EXCEPTION, new Object[] {clazz, "start", bundle.getSymbolicName() == null ? "" + bundle.getBundleId() : bundle.getSymbolicName()}), BundleException.ACTIVATOR_ERROR, t); //$NON-NLS-1$ //$NON-NLS-2$
}
}
Object setContextFinder() {
if (!container.getConfiguration().BUNDLE_SET_TCCL)
return Boolean.FALSE;
Thread currentThread = Thread.currentThread();
ClassLoader previousTCCL = currentThread.getContextClassLoader();
ClassLoader contextFinder = container.getContextFinder();
if (previousTCCL != contextFinder) {
currentThread.setContextClassLoader(container.getContextFinder());
return previousTCCL;
}
return Boolean.FALSE;
}
/**
* Call bundle's BundleActivator.stop()
* This method is called by Bundle.stopWorker to stop the bundle.
*
* @exception BundleException if
* the bundle has a class that implements the BundleActivator interface,
* and the BundleActivator.stop() method failed
*/
protected void stop() throws BundleException {
try {
final BundleActivator bundleActivator = activator;
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Void run() throws Exception {
if (bundleActivator != null) {
// make sure the context class loader is set correctly
Object previousTCCL = setContextFinder();
try {
/* Stop the bundle synchronously */
bundleActivator.stop(BundleContextImpl.this);
} finally {
if (previousTCCL != Boolean.FALSE)
Thread.currentThread().setContextClassLoader((ClassLoader) previousTCCL);
}
}
return null;
}
});
} catch (Throwable t) {
if (t instanceof PrivilegedActionException) {
t = ((PrivilegedActionException) t).getException();
}
if (debug.DEBUG_GENERAL) {
Debug.printStackTrace(t);
}
String clazz = (activator == null) ? "" : activator.getClass().getName(); //$NON-NLS-1$
throw new BundleException(NLS.bind(Msg.BUNDLE_ACTIVATOR_EXCEPTION, new Object[] {clazz, "stop", bundle.getSymbolicName() == null ? "" + bundle.getBundleId() : bundle.getSymbolicName()}), BundleException.ACTIVATOR_ERROR, t); //$NON-NLS-1$ //$NON-NLS-2$
} finally {
activator = null;
}
}
/**
* Return the map of ServiceRegistrationImpl to ServiceUse for services being
* used by this context.
* @return A map of ServiceRegistrationImpl to ServiceUse for services in use by
* this context.
*/
public Map, ServiceUse>> getServicesInUseMap() {
synchronized (contextLock) {
return servicesInUse;
}
}
/**
* Provision the map of ServiceRegistrationImpl to ServiceUse for services being
* used by this context.
*/
public void provisionServicesInUseMap() {
synchronized (contextLock) {
if (servicesInUse == null)
// Cannot predict how many services a bundle will use, start with a small table.
servicesInUse = new HashMap, ServiceUse>>(10);
}
}
/**
* Bottom level event dispatcher for the BundleContext.
*
* @param originalListener listener object registered under.
* @param l listener to call (may be filtered).
* @param action Event class type
* @param object Event object
*/
public void dispatchEvent(Object originalListener, Object l, int action, Object object) {
// save the bundle ref to a local variable
// to avoid interference from another thread closing this context
EquinoxBundle tmpBundle = bundle;
Object previousTCCL = setContextFinder();
try {
if (isValid()) /* if context still valid */{
switch (action) {
case EquinoxEventPublisher.BUNDLEEVENT :
case EquinoxEventPublisher.BUNDLEEVENTSYNC : {
BundleListener listener = (BundleListener) l;
if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("dispatchBundleEvent[" + tmpBundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
listener.bundleChanged((BundleEvent) object);
break;
}
case ServiceRegistry.SERVICEEVENT : {
ServiceEvent event = (ServiceEvent) object;
ServiceListener listener = (ServiceListener) l;
if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("dispatchServiceEvent[" + tmpBundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
listener.serviceChanged(event);
break;
}
case EquinoxEventPublisher.FRAMEWORKEVENT : {
FrameworkListener listener = (FrameworkListener) l;
if (debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("dispatchFrameworkEvent[" + tmpBundle + "](" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
listener.frameworkEvent((FrameworkEvent) object);
break;
}
default : {
throw new InternalError();
}
}
}
} catch (Throwable t) {
if (debug.DEBUG_GENERAL) {
Debug.println("Exception in bottom level event dispatcher: " + t.getMessage()); //$NON-NLS-1$
Debug.printStackTrace(t);
}
// allow the adaptor to handle this unexpected error
container.handleRuntimeError(t);
publisherror: {
if (action == EquinoxEventPublisher.FRAMEWORKEVENT) {
FrameworkEvent event = (FrameworkEvent) object;
if (event.getType() == FrameworkEvent.ERROR) {
break publisherror; // avoid infinite loop
}
}
container.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, tmpBundle, t);
}
} finally {
if (previousTCCL != Boolean.FALSE)
Thread.currentThread().setContextClassLoader((ClassLoader) previousTCCL);
}
}
/**
* Construct a Filter object. This filter object may be used
* to match a ServiceReference or a Dictionary.
* See Filter
* for a description of the filter string syntax.
*
* @param filter The filter string.
* @return A Filter object encapsulating the filter string.
* @exception InvalidSyntaxException If the filter parameter contains
* an invalid filter string which cannot be parsed.
*/
public Filter createFilter(String filter) throws InvalidSyntaxException {
checkValid();
return FilterImpl.newInstance(filter, container.getConfiguration().getDebug().DEBUG_FILTER);
}
/**
* This method checks that the context is still valid. If the context is
* no longer valid, an IllegalStateException is thrown.
*
* @exception java.lang.IllegalStateException
* If the context bundle has stopped.
*/
public void checkValid() {
if (!isValid()) {
throw new IllegalStateException(Msg.BUNDLE_CONTEXT_INVALID_EXCEPTION);
}
}
/**
* This method checks that the context is still valid.
*
* @return true if the context is still valid; false otherwise
*/
protected boolean isValid() {
return valid;
}
public ServiceRegistration registerService(Class clazz, S service, Dictionary properties) {
@SuppressWarnings("unchecked")
ServiceRegistration registration = (ServiceRegistration) registerService(clazz.getName(), service, properties);
return registration;
}
public ServiceRegistration registerService(Class clazz, ServiceFactory factory, Dictionary properties) {
@SuppressWarnings("unchecked")
ServiceRegistration registration = (ServiceRegistration) registerService(clazz.getName(), factory, properties);
return registration;
}
public ServiceReference getServiceReference(Class clazz) {
@SuppressWarnings("unchecked")
ServiceReference reference = (ServiceReference) getServiceReference(clazz.getName());
return reference;
}
public Collection> getServiceReferences(Class clazz, String filter) throws InvalidSyntaxException {
@SuppressWarnings("unchecked")
ServiceReference[] refs = (ServiceReference[]) getServiceReferences(clazz.getName(), filter);
if (refs == null) {
Collection> empty = Collections.> emptyList();
return empty;
}
List> result = new ArrayList>(refs.length);
for (ServiceReference b : refs) {
result.add(b);
}
return result;
}
public EquinoxContainer getContainer() {
return container;
}
@Override
public ServiceObjects getServiceObjects(ServiceReference reference) {
checkValid();
if (reference == null)
throw new NullPointerException("A null service reference is not allowed."); //$NON-NLS-1$
provisionServicesInUseMap();
ServiceObjects serviceObjects = container.getServiceRegistry().getServiceObjects(this, (ServiceReferenceImpl) reference);
return serviceObjects;
}
}