This is an automated email from the ASF dual-hosted git repository.
sseifert pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-sling-mock.git
The following commit(s) were added to refs/heads/master by this push:
new 42f8e2b SLING-13001 Update MockAdapterManagerImpl to Sling Adapter
2.2.0 (#51)
42f8e2b is described below
commit 42f8e2b8867667daa5a18175d5c9502a3205c6ee
Author: Stefan Seifert <[email protected]>
AuthorDate: Wed Nov 12 17:50:27 2025 +0100
SLING-13001 Update MockAdapterManagerImpl to Sling Adapter 2.2.0 (#51)
---
.../testing/mock/sling/MockAdapterManagerImpl.java | 250 ++++++++-------------
.../sling/testing/mock/sling/package-info.java | 2 +-
2 files changed, 95 insertions(+), 157 deletions(-)
diff --git
a/core/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java
b/core/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java
index 0c0cdfb..ee31dce 100644
---
a/core/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java
+++
b/core/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManagerImpl.java
@@ -23,7 +23,6 @@ import java.util.Arrays;
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.TreeMap;
@@ -35,16 +34,15 @@ import org.apache.sling.adapter.internal.AdaptionImpl;
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.jetbrains.annotations.NotNull;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.util.converter.Converter;
+import org.osgi.util.converter.Converters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,42 +50,23 @@ import static
org.apache.sling.api.adapter.AdapterFactory.ADAPTABLE_CLASSES;
import static org.apache.sling.api.adapter.AdapterFactory.ADAPTER_CLASSES;
/**
- * This is a copy of org.apache.sling.adapter.internal.AdpaterManagerImpl from
Sling Adapter 2.1.6,
- * with all calls to SyntheticResource.setAdapterManager/unsetAdapterManager
disabled, because this would
+ * This is a copy of org.apache.sling.adapter.internal.AdpaterManagerImpl from
Sling Adapter 2.2.0,
+ * with all calls to SlingAdaptable.setAdapterManager/unsetAdapterManager
disabled, because this would
* break the {@link ThreadsafeMockAdapterManagerWrapper} concept.
* Additionally the reference to PackageAdmin is disabled.
*/
@Component(
- immediate = true,
service = AdapterManager.class,
+ immediate = true,
property = {
Constants.SERVICE_DESCRIPTION + "=Sling Adapter Manager",
Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
- },
- reference =
- @Reference(
- name = "AdapterFactory",
- service = AdapterFactory.class,
- cardinality = ReferenceCardinality.MULTIPLE,
- policy = ReferencePolicy.DYNAMIC,
- bind = "bindAdapterFactory",
- unbind = "unbindAdapterFactory"))
+ })
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<AdapterFactory>> boundAdapterFactories
= new LinkedList<>();
+ static final String ALLOWED_IN_PRIVATE =
"adapter.allowed.in.private.package";
/**
* A map of {@link AdapterFactoryDescriptorMap} instances. The map is
@@ -113,7 +92,6 @@ public class MockAdapterManagerImpl implements
AdapterManager {
// DISABLED IN THIS COPY OF CLASS
/*
- @Reference
private PackageAdmin packageAdmin;
*/
@@ -126,9 +104,7 @@ public class MockAdapterManagerImpl implements
AdapterManager {
* @see
org.apache.sling.api.adapter.AdapterManager#getAdapter(java.lang.Object,
java.lang.Class)
*/
@Override
- @SuppressWarnings("null")
- public <AdapterType> AdapterType getAdapter(
- @NotNull final Object adaptable, @NotNull final Class<AdapterType>
type) {
+ 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());
@@ -136,9 +112,9 @@ public class MockAdapterManagerImpl implements
AdapterManager {
// get the factory for the target type
final List<AdapterFactoryDescriptor> descList =
factories.get(type.getName());
- if (descList != null && !descList.isEmpty()) {
+ if (descList != null && descList.size() > 0) {
for (AdapterFactoryDescriptor desc : descList) {
- final AdapterFactory factory = desc == null ? null :
desc.getFactory();
+ final AdapterFactory factory = desc.getFactory();
// have the factory adapt the adaptable if the factory exists
if (factory != null) {
@@ -163,64 +139,55 @@ public class MockAdapterManagerImpl implements
AdapterManager {
/**
* 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<AdapterFactory>> refs;
- synchronized (this.boundAdapterFactories) {
- refs = new ArrayList<>(this.boundAdapterFactories);
- boundAdapterFactories.clear();
- }
- for (final ServiceReference<AdapterFactory> reference : refs) {
- registerAdapterFactory(context, reference);
- }
-
- // final "enable" this manager by setting the instance
- // DISABLED IN THIS COPY OF CLASS
- // SyntheticResource.setAdapterManager(this);
+ // DISABLED IN THIS COPY OF CLASS
+ /*
+ @Activate
+ public AdapterManagerImpl() {
+ // "enable" this manager by setting the instance
+ SlingAdaptable.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;
+ // DISABLED IN THIS COPY OF CLASS
+ /*
+ @Deactivate
+ protected void deactivate() {
+ SlingAdaptable.unsetAdapterManager(this);
}
+ */
/**
* Bind a new adapter factory.
- * @param reference Service reference
*/
- protected void bindAdapterFactory(final ServiceReference<AdapterFactory>
reference) {
- boolean create = true;
- if (context == null) {
- synchronized (this.boundAdapterFactories) {
- if (context == null) {
- boundAdapterFactories.add(reference);
- create = false;
- }
- }
- }
- if (create) {
- registerAdapterFactory(context, reference);
- }
+ @Reference(
+ service = AdapterFactory.class,
+ updated = "updatedAdapterFactory",
+ cardinality = ReferenceCardinality.MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC)
+ protected void bindAdapterFactory(final AdapterFactory factory, final
ServiceReference<AdapterFactory> reference) {
+ registerAdapterFactory(factory, reference);
}
/**
* Unbind a adapter factory.
- * @param reference Service reference
*/
protected void unbindAdapterFactory(final ServiceReference<AdapterFactory>
reference) {
unregisterAdapterFactory(reference);
}
+ /**
+ * Modify a adapter factory.
+ */
+ protected void updatedAdapterFactory(
+ final AdapterFactory factory, final
ServiceReference<AdapterFactory> reference) {
+ unregisterAdapterFactory(reference);
+ registerAdapterFactory(factory, reference);
+ }
+
// ---------- unit testing stuff only
--------------------------------------
/**
@@ -247,11 +214,17 @@ public class MockAdapterManagerImpl implements
AdapterManager {
* Unregisters the {@link AdapterFactory} referred to by the service
* <code>reference</code> from the registry.
*/
- @SuppressWarnings({"null", "deprecation"})
private void registerAdapterFactory(
- final ComponentContext context, final
ServiceReference<AdapterFactory> reference) {
- final String[] adaptables =
PropertiesUtil.toStringArray(reference.getProperty(ADAPTABLE_CLASSES));
- final String[] adapters =
PropertiesUtil.toStringArray(reference.getProperty(ADAPTER_CLASSES));
+ final AdapterFactory factory, final
ServiceReference<AdapterFactory> reference) {
+ final Converter converter = Converters.standardConverter();
+ final String[] adaptables =
+
converter.convert(reference.getProperty(ADAPTABLE_CLASSES)).to(String[].class);
+ final String[] adapters =
+
converter.convert(reference.getProperty(ADAPTER_CLASSES)).to(String[].class);
+ final boolean allowedInPrivatePackage = converter
+ .convert(reference.getProperty(ALLOWED_IN_PRIVATE))
+ .defaultValue(false)
+ .to(Boolean.class);
if (adaptables == null || adaptables.length == 0 || adapters == null
|| adapters.length == 0) {
return;
@@ -260,28 +233,24 @@ public class MockAdapterManagerImpl implements
AdapterManager {
// DISABLED IN THIS COPY OF CLASS
/*
for (String clazz : adaptables) {
- if (!checkPackage(packageAdmin, clazz)) {
+ if (!allowedInPrivatePackage && !checkPackage(packageAdmin,
clazz)) {
log.warn("Adaptable class {} in factory service {} is not in
an exported package.", clazz, reference.getProperty(Constants.SERVICE_ID));
}
}
for (String clazz : adapters) {
- if (!checkPackage(packageAdmin, clazz)) {
+ if (!allowedInPrivatePackage && !checkPackage(packageAdmin,
clazz)) {
log.warn("Adapter class {} in factory service {} is not in an
exported package.", clazz, reference.getProperty(Constants.SERVICE_ID));
}
}
*/
- final AdapterFactoryDescriptor factoryDesc = new
AdapterFactoryDescriptor(context, reference, adapters);
+ final AdapterFactoryDescriptor factoryDesc = new
AdapterFactoryDescriptor(factory, adapters, adaptables);
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);
- }
+ adfMap = descriptors.computeIfAbsent(adaptable, key -> new
AdapterFactoryDescriptorMap());
}
synchronized (adfMap) {
adfMap.put(reference, factoryDesc);
@@ -296,8 +265,8 @@ public class MockAdapterManagerImpl implements
AdapterManager {
props.put(SlingConstants.PROPERTY_ADAPTABLE_CLASSES, adaptables);
props.put(SlingConstants.PROPERTY_ADAPTER_CLASSES, adapters);
- ServiceRegistration<Adaption> adaptionRegistration =
-
this.context.getBundleContext().registerService(Adaption.class,
AdaptionImpl.INSTANCE, props);
+ factoryDesc.setAdaption(
+
reference.getBundle().getBundleContext().registerService(Adaption.class,
AdaptionImpl.INSTANCE, props));
if (log.isDebugEnabled()) {
log.debug("Registered service {} with {} : {} and {} : {}", new
Object[] {
Adaption.class.getName(),
@@ -307,7 +276,6 @@ public class MockAdapterManagerImpl implements
AdapterManager {
Arrays.toString(adapters)
});
}
- factoryDesc.setAdaption(adaptionRegistration);
}
static String getPackageName(String clazz) {
@@ -338,60 +306,45 @@ public class MockAdapterManagerImpl implements
AdapterManager {
* Unregisters the {@link AdapterFactory} referred to by the service
* <code>reference</code> from the registry.
*/
- @SuppressWarnings("deprecation")
private void unregisterAdapterFactory(final
ServiceReference<AdapterFactory> 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;
+ final List<AdapterFactoryDescriptorMap> list = new ArrayList<>();
+ synchronized (this.descriptors) {
+ for (final AdapterFactoryDescriptorMap map :
this.descriptors.values()) {
+ list.add(map);
+ }
}
-
- boolean factoriesModified = false;
- AdapterFactoryDescriptorMap adfMap = null;
-
AdapterFactoryDescriptor removedDescriptor = null;
- for (final String adaptable : adaptables) {
- synchronized (this.descriptors) {
- adfMap = this.descriptors.get(adaptable);
- }
- if (adfMap != null) {
- synchronized (adfMap) {
- AdapterFactoryDescriptor factoryDesc =
adfMap.remove(reference);
- if (factoryDesc != null) {
- factoriesModified = true;
- // A single ServiceReference should correspond to a
single Adaption service being registered
- // Since the code paths above does not fully guarantee
it though, let's keep this check in place
- if (removedDescriptor != null && removedDescriptor !=
factoryDesc) {
- log.error(
- "When unregistering reference {} got
duplicate service descriptors {} and {}. Unregistration of {} services may be
incomplete.",
- new Object[] {reference,
removedDescriptor, factoryDesc, Adaption.class.getName()});
- }
- removedDescriptor = factoryDesc;
- }
+ for (final AdapterFactoryDescriptorMap map : list) {
+ synchronized (map) {
+ final AdapterFactoryDescriptor factoryDesc =
map.remove(reference);
+ if (factoryDesc != null) {
+ removedDescriptor = factoryDesc;
}
}
}
- // only remove cache if some adapter factories have actually been
- // removed
- if (factoriesModified) {
- this.factoryCache.clear();
- }
-
// unregister adaption
if (removedDescriptor != null) {
- removedDescriptor.getAdaption().unregister();
+ // only remove cache if some adapter factories have actually been
+ // removed
+ this.factoryCache.clear();
+
+ final ServiceRegistration<Adaption> reg =
removedDescriptor.getAdaption();
+ if (reg != null) {
+ removedDescriptor.setAdaption(null);
+ try {
+ reg.unregister();
+ } catch (final IllegalStateException ignore) {
+ // ignore IAE on shutdown
+ }
+ }
if (log.isDebugEnabled()) {
log.debug("Unregistered service {} with {} : {} and {} : {}",
new Object[] {
Adaption.class.getName(),
SlingConstants.PROPERTY_ADAPTABLE_CLASSES,
- Arrays.toString(adaptables),
+ Arrays.toString(removedDescriptor.getAdaptables()),
SlingConstants.PROPERTY_ADAPTER_CLASSES,
- Arrays.toString(adapters)
+ Arrays.toString(removedDescriptor.getAdapters())
});
}
}
@@ -494,12 +447,9 @@ public class MockAdapterManagerImpl implements
AdapterManager {
// 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());
+ final List<AdapterFactoryDescriptor> factoryDescriptors =
+ dest.computeIfAbsent(entry.getKey(), id -> new
ArrayList<>());
- if (factoryDescriptors == null) {
- factoryDescriptors = new ArrayList<>();
- dest.put(entry.getKey(), factoryDescriptors);
- }
for (AdapterFactoryDescriptor descriptor : entry.getValue()) {
factoryDescriptors.add(descriptor);
}
@@ -518,13 +468,8 @@ public class MockAdapterManagerImpl implements
AdapterManager {
* tuple. Of course only the first entry (this is the reason for having a
sorted
* map) for such a given tuple is actually being used. If that first
instance is
* removed the eventual second instance may actually be used instead.
- *
- * <p>
- * Copy of import
org.apache.sling.adapter.internal.AdapterFactoryDescriptorMap,
- * signature has changed in adapter impl 2.2.0.
- * </p>
*/
- static class AdapterFactoryDescriptorMap
+ private static class AdapterFactoryDescriptorMap
extends TreeMap<ServiceReference<AdapterFactory>,
AdapterFactoryDescriptor> {
private static final long serialVersionUID = 2L;
@@ -534,36 +479,25 @@ public class MockAdapterManagerImpl implements
AdapterManager {
* The <code>AdapterFactoryDescriptor</code> is an entry in the
* {@link AdapterFactoryDescriptorMap} conveying the list of adapter
(target)
* types and the respective {@link AdapterFactory}.
- * <p>
- * Copy of import
org.apache.sling.adapter.internal.AdapterFactoryDescriptor,
- * signature has changed in adapter impl 2.2.0.
- * </p>
*/
- static class AdapterFactoryDescriptor {
+ private static class AdapterFactoryDescriptor {
- private volatile AdapterFactory factory;
+ private final AdapterFactory factory;
private final String[] adapters;
- private final ServiceReference<AdapterFactory> reference;
-
- private final ComponentContext context;
+ private final String[] adaptables;
private volatile ServiceRegistration<Adaption> adaption;
public AdapterFactoryDescriptor(
- final ComponentContext context,
- final ServiceReference<AdapterFactory> reference,
- final String[] adapters) {
- this.reference = reference;
- this.context = context;
+ final AdapterFactory factory, final String[] adapters, final
String[] adaptables) {
+ this.factory = factory;
this.adapters = adapters;
+ this.adaptables = adaptables;
}
public AdapterFactory getFactory() {
- if (factory == null) {
- factory = context.locateService("AdapterFactory", reference);
- }
return factory;
}
@@ -571,11 +505,15 @@ public class MockAdapterManagerImpl implements
AdapterManager {
return adapters;
}
+ public String[] getAdaptables() {
+ return adaptables;
+ }
+
public ServiceRegistration<Adaption> getAdaption() {
return adaption;
}
- public void setAdaption(ServiceRegistration<Adaption> adaption) {
+ public void setAdaption(final ServiceRegistration<Adaption> adaption) {
this.adaption = adaption;
}
}
diff --git
a/core/src/main/java/org/apache/sling/testing/mock/sling/package-info.java
b/core/src/main/java/org/apache/sling/testing/mock/sling/package-info.java
index fe11125..c3a3dc8 100644
--- a/core/src/main/java/org/apache/sling/testing/mock/sling/package-info.java
+++ b/core/src/main/java/org/apache/sling/testing/mock/sling/package-info.java
@@ -19,5 +19,5 @@
/**
* Mock implementation of selected Sling APIs.
*/
[email protected]("4.1.0")
[email protected]("5.0.0")
package org.apache.sling.testing.mock.sling;