Author: mnuttall
Date: Tue Aug 13 10:47:59 2013
New Revision: 1513431
URL: http://svn.apache.org/r1513431
Log:
Aries-1095: deal with rare CNFE when service-providing bundle cannot load one
or more of the service's interfaces
Modified:
aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/services/ServiceHelper.java
Modified:
aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/services/ServiceHelper.java
URL:
http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/services/ServiceHelper.java?rev=1513431&r1=1513430&r2=1513431&view=diff
==============================================================================
---
aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/services/ServiceHelper.java
(original)
+++
aries/trunk/jndi/jndi-url/src/main/java/org/apache/aries/jndi/services/ServiceHelper.java
Tue Aug 13 10:47:59 2013
@@ -23,6 +23,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
@@ -285,7 +286,7 @@ public final class ServiceHelper
result = AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run()
{
- return proxyPriviledged(interface1, filter, rebind, ctx, pair,
timeout);
+ return proxyPrivileged(interface1, filter, rebind, ctx, pair,
timeout);
}
});
@@ -299,7 +300,7 @@ public final class ServiceHelper
return result;
}
- private static Object proxyPriviledged(String interface1, String filter,
boolean dynamicRebind, BundleContext ctx, ServicePair pair, int timeout)
+ private static Object proxyPrivileged(String interface1, String filter,
boolean dynamicRebind, BundleContext ctx, ServicePair pair, int timeout)
{
String[] interfaces = null;
if (interface1 != null) {
@@ -310,33 +311,29 @@ public final class ServiceHelper
List<Class<?>> clazz = new ArrayList<Class<?>>(interfaces.length);
- // We load the interface classes the service is registered under using
- // the defining
- // bundle. This is ok because the service must be able to see the
- // classes to be
- // registered using them. We then check to see if isAssignableTo on the
- // reference
- // works for the owning bundle and the interface name and only use the
- // interface if
- // true is returned there.
-
- // This might seem odd, but equinox and felix return true for
- // isAssignableTo if the
- // Bundle provided does not import the package. This is under the
- // assumption the
- // caller will then use reflection. The upshot of doing it this way is
- // that a utility
- // bundle can be created which centralizes JNDI lookups, but the service
- // will be used
- // by another bundle. It is true that class space consistency is less
- // safe, but we
+ // We load the interface classes the service is registered under using the
defining bundle.
+ // This is ok because the service must be able to see the classes to be
registered using them.
+ // We then check to see if isAssignableTo on the reference works for the
owning bundle and
+ // the interface name and only use the interface if true is returned there.
+
+ // This might seem odd, but equinox and felix return true for
isAssignableTo if the
+ // Bundle provided does not import the package. This is under the
assumption the
+ // caller will then use reflection. The upshot of doing it this way is
that a utility
+ // bundle can be created which centralizes JNDI lookups, but the service
will be used
+ // by another bundle. It is true that class space consistency is less
safe, but we
// are enabling a slightly odd use case anyway.
+
+ // August 13th 2013: We've found valid use cases in which a Bundle is
exporting
+ // services that the Bundle itself cannot load. We deal with this rare
case by
+ // noting the classes that we failed to load. If as a result we have no
classes
+ // to proxy, we try those classes again but instead pull the Class objects
off
+ // the service rather than from the bundle exporting that service.
Bundle serviceProviderBundle = pair.ref.getBundle();
Bundle owningBundle = ctx.getBundle();
-
ProxyManager proxyManager = Activator.getProxyManager();
+ Collection<String> classesNotFound = new ArrayList<String>();
for (String interfaceName : interfaces) {
try {
Class<?> potentialClass =
serviceProviderBundle.loadClass(interfaceName);
@@ -344,9 +341,28 @@ public final class ServiceHelper
clazz.add(potentialClass);
}
} catch (ClassNotFoundException e) {
+ classesNotFound.add(interfaceName);
}
}
-
+
+ if (clazz.isEmpty() && !classesNotFound.isEmpty()) {
+ Class<?> ifacesOnService[] =
ctx.getService(pair.ref).getClass().getInterfaces();
+ for (String interfaceName : classesNotFound) {
+ Class<?> thisClass = null;
+ for (Class<?> c : ifacesOnService) {
+ inner: if (c.getName().equals(interfaceName)) {
+ thisClass = c;
+ break inner;
+ }
+ }
+ if (thisClass != null) {
+ if (pair.ref.isAssignableTo(owningBundle,
interfaceName)) {
+ clazz.add(thisClass);
+ }
+ }
+ }
+ }
+
if (clazz.isEmpty()) {
throw new IllegalArgumentException(Arrays.asList(interfaces).toString());
}