You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2015/02/20 01:21:19 UTC
svn commit: r1661040 - in /sling/trunk/testing/mocks/sling-mock: ./
src/main/java/org/apache/sling/testing/mock/sling/
src/test/java/org/apache/sling/testing/mock/sling/
Author: sseifert
Date: Fri Feb 20 00:21:18 2015
New Revision: 1661040
URL: http://svn.apache.org/r1661040
Log:
SLING-4433 use real AdapterManagerImpl implementation with support for ADAPTER_CLASSES/ADAPTABLE_CLASSES
Added:
sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java (with props)
Removed:
sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManager.java
sling/trunk/testing/mocks/sling-mock/src/test/java/org/apache/sling/testing/mock/sling/MockAdapterManagerTest.java
Modified:
sling/trunk/testing/mocks/sling-mock/pom.xml
sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java
Modified: sling/trunk/testing/mocks/sling-mock/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/testing/mocks/sling-mock/pom.xml?rev=1661040&r1=1661039&r2=1661040&view=diff
==============================================================================
--- sling/trunk/testing/mocks/sling-mock/pom.xml (original)
+++ sling/trunk/testing/mocks/sling-mock/pom.xml Fri Feb 20 00:21:18 2015
@@ -86,6 +86,12 @@
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.adapter</artifactId>
+ <version>2.1.0</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.resourceresolver</artifactId>
<version>1.1.0</version>
<scope>compile</scope>
Added: sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java?rev=1661040&view=auto
==============================================================================
--- sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java (added)
+++ sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java Fri Feb 20 00:21:18 2015
@@ -0,0 +1,437 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.sling.testing.mock.sling;
+
+import static org.apache.sling.api.adapter.AdapterFactory.ADAPTABLE_CLASSES;
+import static org.apache.sling.api.adapter.AdapterFactory.ADAPTER_CLASSES;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.adapter.internal.AdapterFactoryDescriptor;
+import org.apache.sling.adapter.internal.AdapterFactoryDescriptorMap;
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.adapter.AdapterFactory;
+import org.apache.sling.api.adapter.AdapterManager;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is a copy of org.apache.sling.adapter.internal.AdpaterManagerImpl from Sling Adapter 2.1.0,
+ * with all calls to SyntheticResource.setAdapterManager/unsetAdapterManager disabled, because this would
+ * break the {@link ThreadsafeMockAdapterManagerWrapper} concept.
+ */
+@Component(immediate=true)
+@Service
+@Properties({
+ @Property(name=Constants.SERVICE_DESCRIPTION, value="Sling Adapter Manager"),
+ @Property(name=Constants.SERVICE_VENDOR, value="The Apache Software Foundation")
+})
+@Reference(name="AdapterFactory", referenceInterface=AdapterFactory.class,
+cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE, policy=ReferencePolicy.DYNAMIC)
+public class MockAdapterManagerImpl implements AdapterManager {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ /**
+ * The OSGi <code>ComponentContext</code> to retrieve
+ * {@link AdapterFactory} service instances.
+ */
+ private volatile ComponentContext context;
+
+ /**
+ * A list of {@link AdapterFactory} services bound to this manager before
+ * the manager has been activated. These bound services will be accessed as
+ * soon as the manager is being activated.
+ */
+ private final List<ServiceReference> boundAdapterFactories = new LinkedList<ServiceReference>();
+
+ /**
+ * A map of {@link AdapterFactoryDescriptorMap} instances. The map is
+ * indexed by the fully qualified class names listed in the
+ * {@link AdapterFactory#ADAPTABLE_CLASSES} property of the
+ * {@link AdapterFactory} services.
+ *
+ * @see AdapterFactoryDescriptorMap
+ */
+ private final Map<String, AdapterFactoryDescriptorMap> descriptors = new HashMap<String, AdapterFactoryDescriptorMap>();
+
+ /**
+ * Matrix of {@link AdapterFactoryDescriptor} instances primarily indexed by the fully
+ * qualified name of the class to be adapted and secondarily indexed by the
+ * fully qualified name of the class to adapt to (the target class).
+ * <p>
+ * This cache is built on demand by calling the
+ * {@link #getAdapterFactories(Class)} method. It is cleared
+ * whenever an adapter factory is registered on unregistered.
+ */
+ private final ConcurrentMap<String, Map<String, List<AdapterFactoryDescriptor>>> factoryCache
+ = new ConcurrentHashMap<String, Map<String, List<AdapterFactoryDescriptor>>>();
+
+ /**
+ * The service tracker for the event admin
+ */
+ @Reference(cardinality=ReferenceCardinality.OPTIONAL_UNARY, policy=ReferencePolicy.DYNAMIC)
+ private volatile EventAdmin eventAdmin;
+
+ // ---------- AdapterManager interface -------------------------------------
+
+ /**
+ * Returns the adapted <code>adaptable</code> or <code>null</code> if
+ * the object cannot be adapted.
+ *
+ * @see org.apache.sling.api.adapter.AdapterManager#getAdapter(java.lang.Object, java.lang.Class)
+ */
+ public <AdapterType> AdapterType getAdapter(final Object adaptable,
+ final Class<AdapterType> type) {
+
+ // get the adapter factories for the type of adaptable object
+ final Map<String, List<AdapterFactoryDescriptor>> factories = getAdapterFactories(adaptable.getClass());
+
+ // get the factory for the target type
+ final List<AdapterFactoryDescriptor> descList = factories.get(type.getName());
+
+ if (descList != null && descList.size() > 0) {
+ for (AdapterFactoryDescriptor desc : descList) {
+ final AdapterFactory factory = desc == null ? null : desc.getFactory();
+
+ // have the factory adapt the adaptable if the factory exists
+ if (factory != null) {
+ log.debug("Trying adapter factory {} to map {} to {}",
+ new Object [] { factory, adaptable, type });
+
+ AdapterType adaptedObject = factory.getAdapter(adaptable, type);
+ if (adaptedObject != null) {
+ log.debug("Using adapter factory {} to map {} to {}",
+ new Object [] { factory, adaptable, type });
+ return adaptedObject;
+ }
+ }
+ }
+ }
+
+ // no factory has been found, so we cannot adapt
+ log.debug("No adapter factory found to map {} to {}", adaptable, type);
+
+ return null;
+ }
+
+ // ----------- SCR integration ---------------------------------------------
+
+ /**
+ * Activate the manager.
+ * Bind all already registered factories
+ * @param context Component context
+ */
+ protected void activate(final ComponentContext context) {
+ this.context = context;
+
+ // register all adapter factories bound before activation
+ final List<ServiceReference> refs;
+ synchronized ( this.boundAdapterFactories ) {
+ refs = new ArrayList<ServiceReference>(this.boundAdapterFactories);
+ boundAdapterFactories.clear();
+ }
+ for (final ServiceReference reference : refs) {
+ registerAdapterFactory(context, reference);
+ }
+
+ // final "enable" this manager by setting the instance
+ // DISABLED IN THIS COPY OF CLASS
+ //SyntheticResource.setAdapterManager(this);
+ }
+
+ /**
+ * Deactivate
+ * @param context Not used
+ */
+ protected void deactivate(final ComponentContext context) {
+ // DISABLED IN THIS COPY OF CLASS
+ //SyntheticResource.unsetAdapterManager(this);
+ this.context = null;
+ }
+
+ /**
+ * Bind a new adapter factory.
+ */
+ protected void bindAdapterFactory(final ServiceReference reference) {
+ boolean create = true;
+ if (context == null) {
+ synchronized ( this.boundAdapterFactories ) {
+ if (context == null) {
+ boundAdapterFactories.add(reference);
+ create = false;
+ }
+ }
+ }
+ if ( create ) {
+ registerAdapterFactory(context, reference);
+ }
+ }
+
+ /**
+ * Unbind a adapter factory.
+ */
+ protected void unbindAdapterFactory(final ServiceReference reference) {
+ unregisterAdapterFactory(reference);
+ }
+
+ // ---------- unit testing stuff only --------------------------------------
+
+ /**
+ * Returns the active adapter factories of this manager.
+ * <p>
+ * <strong><em>THIS METHOD IS FOR UNIT TESTING ONLY. IT MAY BE REMOVED OR
+ * MODIFIED WITHOUT NOTICE.</em></strong>
+ */
+ Map<String, AdapterFactoryDescriptorMap> getFactories() {
+ return descriptors;
+ }
+
+ /**
+ * Returns the current adapter factory cache.
+ * <p>
+ * <strong><em>THIS METHOD IS FOR UNIT TESTING ONLY. IT MAY BE REMOVED OR
+ * MODIFIED WITHOUT NOTICE.</em></strong>
+ */
+ Map<String, Map<String, List<AdapterFactoryDescriptor>>> getFactoryCache() {
+ return factoryCache;
+ }
+
+ /**
+ * Unregisters the {@link AdapterFactory} referred to by the service
+ * <code>reference</code> from the registry.
+ */
+ private void registerAdapterFactory(final ComponentContext context,
+ final ServiceReference reference) {
+ final String[] adaptables = PropertiesUtil.toStringArray(reference.getProperty(ADAPTABLE_CLASSES));
+ final String[] adapters = PropertiesUtil.toStringArray(reference.getProperty(ADAPTER_CLASSES));
+
+ if (adaptables == null || adaptables.length == 0 || adapters == null
+ || adapters.length == 0) {
+ return;
+ }
+
+ final AdapterFactoryDescriptor factoryDesc = new AdapterFactoryDescriptor(context,
+ reference, adapters);
+
+ for (final String adaptable : adaptables) {
+ AdapterFactoryDescriptorMap adfMap = null;
+ synchronized ( this.descriptors ) {
+ adfMap = descriptors.get(adaptable);
+ if (adfMap == null) {
+ adfMap = new AdapterFactoryDescriptorMap();
+ descriptors.put(adaptable, adfMap);
+ }
+ }
+ synchronized ( adfMap ) {
+ adfMap.put(reference, factoryDesc);
+ }
+ }
+
+ // clear the factory cache to force rebuild on next access
+ this.factoryCache.clear();
+
+ // send event
+ final EventAdmin localEA = this.eventAdmin;
+ if ( localEA != null ) {
+ final Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(SlingConstants.PROPERTY_ADAPTABLE_CLASSES, adaptables);
+ props.put(SlingConstants.PROPERTY_ADAPTER_CLASSES, adapters);
+ localEA.postEvent(new Event(SlingConstants.TOPIC_ADAPTER_FACTORY_ADDED,
+ props));
+ }
+ }
+
+ /**
+ * Unregisters the {@link AdapterFactory} referred to by the service
+ * <code>reference</code> from the registry.
+ */
+ private void unregisterAdapterFactory(final ServiceReference reference) {
+ synchronized ( this.boundAdapterFactories ) {
+ boundAdapterFactories.remove(reference);
+ }
+ final String[] adaptables = PropertiesUtil.toStringArray(reference.getProperty(ADAPTABLE_CLASSES));
+ final String[] adapters = PropertiesUtil.toStringArray(reference.getProperty(ADAPTER_CLASSES));
+
+ if (adaptables == null || adaptables.length == 0 || adapters == null
+ || adapters.length == 0) {
+ return;
+ }
+
+ boolean factoriesModified = false;
+ AdapterFactoryDescriptorMap adfMap = null;
+ for (final String adaptable : adaptables) {
+ synchronized ( this.descriptors ) {
+ adfMap = this.descriptors.get(adaptable);
+ }
+ if (adfMap != null) {
+ synchronized ( adfMap ) {
+ factoriesModified |= (adfMap.remove(reference) != null);
+ }
+ }
+ }
+
+ // only remove cache if some adapter factories have actually been
+ // removed
+ if (factoriesModified) {
+ this.factoryCache.clear();
+ }
+
+ // send event
+ final EventAdmin localEA = this.eventAdmin;
+ if ( localEA != null ) {
+ final Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(SlingConstants.PROPERTY_ADAPTABLE_CLASSES, adaptables);
+ props.put(SlingConstants.PROPERTY_ADAPTER_CLASSES, adapters);
+ localEA.postEvent(new Event(SlingConstants.TOPIC_ADAPTER_FACTORY_REMOVED,
+ props));
+ }
+ }
+
+ /**
+ * Returns the map of adapter factories index by adapter (target) class name
+ * for the given adaptable <code>clazz</code>. If no adapter exists for
+ * the <code>clazz</code> and empty map is returned.
+ *
+ * @param clazz The adaptable <code>Class</code> for which to return the
+ * adapter factory map by target class name.
+ * @return The map of adapter factories by target class name. The map may be
+ * empty if there is no adapter factory for the adaptable
+ * <code>clazz</code>.
+ */
+ private Map<String, List<AdapterFactoryDescriptor>> getAdapterFactories(final Class<?> clazz) {
+ final String className = clazz.getName();
+ Map<String, List<AdapterFactoryDescriptor>> entry = this.factoryCache.get(className);
+ if (entry == null) {
+ // create entry
+ entry = createAdapterFactoryMap(clazz);
+ this.factoryCache.put(className, entry);
+ }
+
+ return entry;
+ }
+
+ /**
+ * Creates a new target adapter factory map for the given <code>clazz</code>.
+ * First all factories defined to support the adaptable class by
+ * registration are taken. Next all factories for the implemented interfaces
+ * and finally all base class factories are copied.
+ *
+ * @param clazz The adaptable <code>Class</code> for which to build the
+ * adapter factory map by target class name.
+ * @return The map of adapter factories by target class name. The map may be
+ * empty if there is no adapter factory for the adaptable
+ * <code>clazz</code>.
+ */
+ private Map<String, List<AdapterFactoryDescriptor>> createAdapterFactoryMap(final Class<?> clazz) {
+ final Map<String, List<AdapterFactoryDescriptor>> afm = new HashMap<String, List<AdapterFactoryDescriptor>>();
+
+ // AdapterFactories for this class
+ AdapterFactoryDescriptorMap afdMap = null;
+ synchronized ( this.descriptors ) {
+ afdMap = this.descriptors.get(clazz.getName());
+ }
+ if (afdMap != null) {
+ final List<AdapterFactoryDescriptor> afdSet;
+ synchronized ( afdMap ) {
+ afdSet = new ArrayList<AdapterFactoryDescriptor>(afdMap.values());
+ }
+ for (final AdapterFactoryDescriptor afd : afdSet) {
+ final String[] adapters = afd.getAdapters();
+ for (final String adapter : adapters) {
+ // to handle service ranking, we add to the end of the list or create a new list
+ List<AdapterFactoryDescriptor> factoryDescriptors = afm.get(adapter);
+ if (factoryDescriptors == null) {
+ factoryDescriptors = new ArrayList<AdapterFactoryDescriptor>();
+ afm.put(adapter, factoryDescriptors);
+ }
+ factoryDescriptors.add(afd);
+ }
+ }
+ }
+
+ // AdapterFactories for the interfaces
+ final Class<?>[] interfaces = clazz.getInterfaces();
+ for (final Class<?> iFace : interfaces) {
+ copyAdapterFactories(afm, iFace);
+ }
+
+ // AdapterFactories for the super class
+ final Class<?> superClazz = clazz.getSuperclass();
+ if (superClazz != null) {
+ copyAdapterFactories(afm, superClazz);
+ }
+
+ return afm;
+ }
+
+ /**
+ * Copies all adapter factories for the given <code>clazz</code> from the
+ * <code>cache</code> to the <code>dest</code> map except for those
+ * factories whose target class already exists in the <code>dest</code>
+ * map.
+ *
+ * @param dest The map of target class name to adapter factory into which
+ * additional factories are copied. Existing factories are not
+ * replaced.
+ * @param clazz The adaptable class whose adapter factories are considered
+ * for adding into <code>dest</code>.
+ */
+ private void copyAdapterFactories(final Map<String, List<AdapterFactoryDescriptor>> dest,
+ final Class<?> clazz) {
+
+ // get the adapter factories for the adaptable clazz
+ final Map<String, List<AdapterFactoryDescriptor>> scMap = getAdapterFactories(clazz);
+
+ // for each target class copy the entry to dest and put it in the list or create the list
+ for (Map.Entry<String, List<AdapterFactoryDescriptor>> entry : scMap.entrySet()) {
+
+ List<AdapterFactoryDescriptor> factoryDescriptors = dest.get(entry.getKey());
+
+ if (factoryDescriptors == null) {
+ factoryDescriptors = new ArrayList<AdapterFactoryDescriptor>();
+ dest.put(entry.getKey(), factoryDescriptors);
+ }
+ for (AdapterFactoryDescriptor descriptor : entry.getValue()) {
+ factoryDescriptors.add(descriptor);
+ }
+ }
+ }
+}
Propchange: sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Feb 20 00:21:18 2015
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author
Propchange: sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java?rev=1661040&r1=1661039&r2=1661040&view=diff
==============================================================================
--- sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java (original)
+++ sling/trunk/testing/mocks/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java Fri Feb 20 00:21:18 2015
@@ -18,8 +18,13 @@
*/
package org.apache.sling.testing.mock.sling;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
import org.apache.sling.api.adapter.AdapterManager;
+import org.apache.sling.testing.mock.osgi.MockOsgi;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
/**
* Wrapper for {@link MockAdapterManager} which makes sure multiple unit tests
@@ -28,16 +33,16 @@ import org.osgi.framework.BundleContext;
*/
class ThreadsafeMockAdapterManagerWrapper implements AdapterManager {
- private static final ThreadLocal<MockAdapterManager> THREAD_LOCAL = new ThreadLocal<MockAdapterManager>() {
+ private static final ThreadLocal<AdapterManagerBundleContextFactory> THREAD_LOCAL = new ThreadLocal<AdapterManagerBundleContextFactory>() {
@Override
- protected MockAdapterManager initialValue() {
- return new MockAdapterManager();
+ protected AdapterManagerBundleContextFactory initialValue() {
+ return new AdapterManagerBundleContextFactory();
}
};
@Override
public <AdapterType> AdapterType getAdapter(final Object adaptable, final Class<AdapterType> type) {
- MockAdapterManager adapterManager = THREAD_LOCAL.get();
+ AdapterManager adapterManager = THREAD_LOCAL.get().getAdapterManager();
return adapterManager.getAdapter(adaptable, type);
}
@@ -46,7 +51,7 @@ class ThreadsafeMockAdapterManagerWrappe
* @param bundleContext Bundle context
*/
public void setBundleContext(final BundleContext bundleContext) {
- MockAdapterManager adapterManager = THREAD_LOCAL.get();
+ AdapterManagerBundleContextFactory adapterManager = THREAD_LOCAL.get();
adapterManager.setBundleContext(bundleContext);
}
@@ -54,8 +59,43 @@ class ThreadsafeMockAdapterManagerWrappe
* Removes bundle context reference.
*/
public void clearBundleContext() {
- MockAdapterManager adapterManager = THREAD_LOCAL.get();
+ AdapterManagerBundleContextFactory adapterManager = THREAD_LOCAL.get();
adapterManager.clearBundleContext();
}
+
+
+ private static class AdapterManagerBundleContextFactory {
+
+ private BundleContext bundleContext;
+
+ public void setBundleContext(final BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+
+ // register adapter manager
+ MockAdapterManagerImpl adapterManagerImpl = new MockAdapterManagerImpl();
+ Dictionary<String,Object> properties = new Hashtable<String, Object>();
+ MockOsgi.injectServices(adapterManagerImpl, bundleContext);
+ MockOsgi.activate(adapterManagerImpl, bundleContext, properties);
+ bundleContext.registerService(AdapterManager.class.getName(), adapterManagerImpl, properties);
+ }
+
+ public void clearBundleContext() {
+ this.bundleContext = null;
+ }
+
+ public synchronized AdapterManager getAdapterManager() {
+ if (bundleContext == null) {
+ setBundleContext(MockOsgi.newBundleContext());
+ }
+ ServiceReference serviceReference = bundleContext.getServiceReference(AdapterManager.class.getName());
+ if (serviceReference != null) {
+ return (AdapterManager)bundleContext.getService(serviceReference);
+ }
+ else {
+ throw new RuntimeException("AdapterManager not registered in bundle context.");
+ }
+ }
+
+ }
}