Author: cziegeler
Date: Thu Jul 2 09:16:56 2009
New Revision: 790513
URL: http://svn.apache.org/viewvc?rev=790513&view=rev
Log:
SLING-1031 : Send events when a new adapter factory is added or an old one is
removed.
Modified:
sling/trunk/bundles/api/src/main/java/org/apache/sling/api/SlingConstants.java
sling/trunk/bundles/api/src/main/java/org/apache/sling/api/adapter/AdapterFactory.java
sling/trunk/bundles/extensions/adapter/pom.xml
sling/trunk/bundles/extensions/adapter/src/main/java/org/apache/sling/adapter/internal/AdapterManagerImpl.java
sling/trunk/bundles/extensions/adapter/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java
Modified:
sling/trunk/bundles/api/src/main/java/org/apache/sling/api/SlingConstants.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/SlingConstants.java?rev=790513&r1=790512&r2=790513&view=diff
==============================================================================
---
sling/trunk/bundles/api/src/main/java/org/apache/sling/api/SlingConstants.java
(original)
+++
sling/trunk/bundles/api/src/main/java/org/apache/sling/api/SlingConstants.java
Thu Jul 2 09:16:56 2009
@@ -206,4 +206,36 @@
* @since 2.0.6
*/
public static final String PROPERTY_RESOURCE_SUPER_TYPE =
"resourceSuperType";
+
+ /**
+ * The topic for the OSGi event which is sent when an adapter factory has
been added.
+ * The event contains at least the {...@link #PROPERTY_ADAPTABLE_CLASSES},
+ * and {...@link #PROPERTY_ADAPTER_CLASSES} poperties.
+ * @since 2.0.6
+ */
+ public static final String TOPIC_ADAPTER_FACTORY_ADDED =
"org/apache/sling/api/adapter/AdapterFactory/ADDED";
+
+ /**
+ * The topic for the OSGi event which is sent when an adapter factory has
been removed.
+ * The event contains at least the {...@link #PROPERTY_ADAPTABLE_CLASSES},
+ * and {...@link #PROPERTY_ADAPTER_CLASSES} poperties.
+ * @since 2.0.6
+ */
+ public static final String TOPIC_ADAPTER_FACTORY_REMOVED =
"org/apache/sling/api/adapter/AdapterFactory/REMOVED";
+
+ /**
+ * The event property listing the fully qualified names of
+ * classes which can be adapted by this adapter factory (value is
+ * "adaptables"). The type of the value is a string array.
+ * @since 2.0.6
+ */
+ public static final String PROPERTY_ADAPTABLE_CLASSES = "adaptables";
+
+ /**
+ * The event property listing the fully qualified names of
+ * classes to which this factory can adapt adaptables (value is
"adapters").
+ * The type of the value is a string array.
+ * @since 2.0.6
+ */
+ public static final String PROPERTY_ADAPTER_CLASSES = "adapters";
}
Modified:
sling/trunk/bundles/api/src/main/java/org/apache/sling/api/adapter/AdapterFactory.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/adapter/AdapterFactory.java?rev=790513&r1=790512&r2=790513&view=diff
==============================================================================
---
sling/trunk/bundles/api/src/main/java/org/apache/sling/api/adapter/AdapterFactory.java
(original)
+++
sling/trunk/bundles/api/src/main/java/org/apache/sling/api/adapter/AdapterFactory.java
Thu Jul 2 09:16:56 2009
@@ -34,7 +34,7 @@
* interface as services (value is
* "org.apache.sling.osgi.commons.AdapterFactory").
*/
- static final String SERVICE_NAME = AdapterFactory.class.getName();
+ String SERVICE_NAME = AdapterFactory.class.getName();
/**
* The service registration property listing the fully qualified names of
@@ -43,13 +43,13 @@
* {...@link #getAdapter(Object, Class)} method must be an instance of any
of
* these classes for this factory to be able to adapt the object.
*/
- static final String ADAPTABLE_CLASSES = "adaptables";
+ String ADAPTABLE_CLASSES = "adaptables";
/**
* The service registration property listing the fully qualified names of
* classes to which this factory can adapt adaptables (value is
"adapters").
*/
- static final String ADAPTER_CLASSES = "adapters";
+ String ADAPTER_CLASSES = "adapters";
/**
* Adapt the given object to the adaptable type. The adaptable object is
@@ -67,7 +67,7 @@
* the <code>Adaptable</code> interface, though most of the time this
method
* is called by means of calling the {...@link Adaptable#adaptTo(Class)}
* method.
- *
+ *
* @param <AdapterType> The generic type of the adapter (target) type.
* @param adaptable The object to adapt to the adapter type.
* @param type The type to which the object is to be adapted.
Modified: sling/trunk/bundles/extensions/adapter/pom.xml
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/adapter/pom.xml?rev=790513&r1=790512&r2=790513&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/adapter/pom.xml (original)
+++ sling/trunk/bundles/extensions/adapter/pom.xml Thu Jul 2 09:16:56 2009
@@ -84,7 +84,7 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.api</artifactId>
- <version>2.0.2-incubator</version>
+ <version>2.0.5-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
Modified:
sling/trunk/bundles/extensions/adapter/src/main/java/org/apache/sling/adapter/internal/AdapterManagerImpl.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/adapter/src/main/java/org/apache/sling/adapter/internal/AdapterManagerImpl.java?rev=790513&r1=790512&r2=790513&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/adapter/src/main/java/org/apache/sling/adapter/internal/AdapterManagerImpl.java
(original)
+++
sling/trunk/bundles/extensions/adapter/src/main/java/org/apache/sling/adapter/internal/AdapterManagerImpl.java
Thu Jul 2 09:16:56 2009
@@ -21,17 +21,23 @@
import static org.apache.sling.api.adapter.AdapterFactory.ADAPTABLE_CLASSES;
import static org.apache.sling.api.adapter.AdapterFactory.ADAPTER_CLASSES;
+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 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.OsgiUtil;
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.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
/**
* The <code>AdapterManagerImpl</code> class implements the
@@ -103,6 +109,10 @@
*/
private Map<String, Map<String, AdapterFactory>> factoryCache;
+ /** The service tracker for the event admin
+ */
+ private ServiceTracker eventAdminTracker;
+
// ---------- AdapterManager interface
-------------------------------------
/**
@@ -140,6 +150,10 @@
// ----------- SCR integration
---------------------------------------------
protected synchronized void activate(ComponentContext context) {
+ // setup tracker first as this is used in the bind/unbind methods
+ this.eventAdminTracker = new ServiceTracker(context.getBundleContext(),
+ EventAdmin.class.getName(), null);
+ this.eventAdminTracker.open();
this.context = context;
// register all adapter factories bound before activation
@@ -173,7 +187,10 @@
"Not clearing instance field: Set to another manager "
+ AdapterManagerImpl.INSTANCE, null);
}
-
+ if ( this.eventAdminTracker != null ) {
+ this.eventAdminTracker.close();
+ this.eventAdminTracker = null;
+ }
this.context = null;
}
@@ -226,13 +243,21 @@
}
/**
+ * Get the event admin.
+ * @return The event admin or <code>null</code>
+ */
+ private EventAdmin getEventAdmin() {
+ return (EventAdmin) (this.eventAdminTracker != null ?
this.eventAdminTracker.getService() : null);
+ }
+
+ /**
* Unregisters the {...@link AdapterFactory} referred to by the service
* <code>reference</code> from the registry.
*/
private void registerAdapterFactory(ComponentContext context,
ServiceReference reference) {
- String[] adaptables =
OsgiUtil.toStringArray(reference.getProperty(ADAPTABLE_CLASSES));
- String[] adapters =
OsgiUtil.toStringArray(reference.getProperty(ADAPTER_CLASSES));
+ final String[] adaptables =
OsgiUtil.toStringArray(reference.getProperty(ADAPTABLE_CLASSES));
+ final String[] adapters =
OsgiUtil.toStringArray(reference.getProperty(ADAPTER_CLASSES));
if (adaptables == null || adaptables.length == 0 || adapters == null
|| adapters.length == 0) {
@@ -260,6 +285,16 @@
// clear the factory cache to force rebuild on next access
factoryCache = null;
+
+ // send event
+ final EventAdmin localEA = this.getEventAdmin();
+ 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));
+ }
}
/**
@@ -269,9 +304,11 @@
private void unregisterAdapterFactory(ServiceReference reference) {
boundAdapterFactories.remove(reference);
- String[] adaptables =
OsgiUtil.toStringArray(reference.getProperty(ADAPTABLE_CLASSES));
+ final String[] adaptables =
OsgiUtil.toStringArray(reference.getProperty(ADAPTABLE_CLASSES));
+ final String[] adapters =
OsgiUtil.toStringArray(reference.getProperty(ADAPTER_CLASSES));
- if (adaptables == null || adaptables.length == 0) {
+ if (adaptables == null || adaptables.length == 0 || adapters == null
+ || adapters.length == 0) {
return;
}
@@ -296,6 +333,16 @@
if (factoriesModified) {
factoryCache = null;
}
+
+ // send event
+ final EventAdmin localEA = this.getEventAdmin();
+ 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));
+ }
}
/**
Modified:
sling/trunk/bundles/extensions/adapter/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/adapter/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java?rev=790513&r1=790512&r2=790513&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/adapter/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java
(original)
+++
sling/trunk/bundles/extensions/adapter/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java
Thu Jul 2 09:16:56 2009
@@ -34,7 +34,10 @@
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.runner.RunWith;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
@@ -70,11 +73,21 @@
/**
* Helper method to create a mock component context
*/
- protected ComponentContext createComponentContext() {
+ protected ComponentContext createComponentContext() throws Exception {
+ final BundleContext bundleCtx = this.context.mock(BundleContext.class);
+ final Filter filter = this.context.mock(Filter.class);
final ComponentContext ctx = this.context.mock(ComponentContext.class);
this.context.checking(new Expectations() {{
allowing(ctx).locateService(with(any(String.class)),
with(any(ServiceReference.class)));
will(returnValue(new MockAdapterFactory()));
+ allowing(ctx).getBundleContext();
+ will(returnValue(bundleCtx));
+ allowing(bundleCtx).createFilter(with(any(String.class)));
+ will(returnValue(filter));
+
allowing(bundleCtx).addServiceListener(with(any(ServiceListener.class)),
with(any(String.class)));
+ allowing(bundleCtx).getServiceReferences(with(any(String.class)),
with(any(String.class)));
+ will(returnValue(null));
+
allowing(bundleCtx).removeServiceListener(with(any(ServiceListener.class)));
}});
return ctx;
}
@@ -123,7 +136,7 @@
assertNull("AdapterFactory cache must be null", am.getFactoryCache());
}
- @org.junit.Test public void testInitialized() {
+ @org.junit.Test public void testInitialized() throws Exception {
am.activate(this.createComponentContext());
assertNotNull("AdapterFactoryDescriptors must not be null",
am.getFactories());
@@ -131,7 +144,7 @@
assertNull("AdapterFactory cache must be null", am.getFactoryCache());
}
- @org.junit.Test public void testBindBeforeActivate() {
+ @org.junit.Test public void testBindBeforeActivate() throws Exception {
final ServiceReference ref = createServiceReference();
am.bindAdapterFactory(ref);
@@ -148,7 +161,7 @@
assertNull("AdapterFactory cache must be null", am.getFactoryCache());
}
- @org.junit.Test public void testBindAfterActivate() {
+ @org.junit.Test public void testBindAfterActivate() throws Exception {
am.activate(this.createComponentContext());
// no cache and no factories yet
@@ -178,7 +191,7 @@
assertNull(f.get(TestSlingAdaptable2.class.getName()));
}
- @org.junit.Test public void testAdaptBase() {
+ @org.junit.Test public void testAdaptBase() throws Exception {
am.activate(this.createComponentContext());
TestSlingAdaptable data = new TestSlingAdaptable();
@@ -192,7 +205,7 @@
assertTrue(adapter instanceof ITestAdapter);
}
- @org.junit.Test public void testAdaptExtended() {
+ @org.junit.Test public void testAdaptExtended() throws Exception {
am.activate(this.createComponentContext());
TestSlingAdaptable2 data = new TestSlingAdaptable2();
@@ -206,7 +219,7 @@
assertTrue(adapter instanceof ITestAdapter);
}
- @org.junit.Test public void testAdaptBase2() {
+ @org.junit.Test public void testAdaptBase2() throws Exception {
am.activate(this.createComponentContext());
TestSlingAdaptable data = new TestSlingAdaptable();
@@ -223,7 +236,7 @@
assertTrue(adapter instanceof ITestAdapter);
}
- @org.junit.Test public void testAdaptExtended2() {
+ @org.junit.Test public void testAdaptExtended2() throws Exception {
am.activate(this.createComponentContext());
final ServiceReference ref = createServiceReference();