[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [milo-dev] DelegateRegistry.registerEncoder()/registerDecoder() in static initializer block
|
Hi Kevin,
Thank you for your information. I will cancel my previous mail.
The cause was found. I have tried to run server and client on Apache Felix 4.6.1 (OSGi).
---
com.google.common.reflect.ClassPath$Scanner#getClassPathEntries(ClassLoader classloader)
which is called from DelegateRegistry#loadGeneratedClasses():
---
Above this argument classloader must be a extended class of URLClassLoader.
Under non-OSGi this argument classloader is sun.misc.Launcher$AppClassLoader (extended URLClassLoader).
But under Felix it is org.apache.felix.framework.BundleWiringImpl$BundleClassLoaderJava5 (not extended URLClassLoader).
I was not able to get the extended class of URLClassLoader from Felix.
So client and server got empty ImmutableSet<ClassInfo> by listing classes in enumerated/structured
under Felix. I locally added Activator.java in UaStackCore for the case of osgi only.
I will send this Activator.java to you for your information.
Regards,
--Shigeru
<kevinherron@xxxxxxxxx> wrote, Thu, 18 Aug 2016 06:36:38 -0700
> Hi,
>
> Have you pulled recently? This issue should have been fixed in this PR:
> https://github.com/eclipse/milo/pull/31
>
> The equivalent to what you've done would be to call
> DelegateRegistry.getInstance(), although it shouldn't be necessary any more.
==================================================================================================================
package org.eclipse.milo.opcua.stack.core;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.wiring.BundleWiring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Activator implements BundleActivator {
private static final Logger logger = LoggerFactory.getLogger(Activator.class);
private static BundleContext context;
static BundleContext getContext() {
return context;
}
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
loadClasses("org.eclipse.milo.opcua.stack.core.types.enumerated", Activator.class.getClassLoader(), context.getBundle());
loadClasses("org.eclipse.milo.opcua.stack.core.types.structured", Activator.class.getClassLoader(), context.getBundle());
}
public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null;
}
private void loadClasses(String packageName, ClassLoader classLoader, Bundle bundle) throws ClassNotFoundException {
String resourceName = packageName.replace('.', '/');
URL root = classLoader.getResource(resourceName);
if ("file".equals(root.getProtocol())) {
File[] files = new File(root.getFile()).listFiles(new FileFilter());
if (files != null) {
for (File file : files) {
String name = packageName + "." + file.getName().replaceAll(".class$", "");
Class.forName(name, true, classLoader);
logger.trace("loaded from file - {}", name);
}
}
} else if ("jar".equals(root.getProtocol())) {
try (JarFile jarFile = ((JarURLConnection)root.openConnection()).getJarFile()) {
Iterator<JarEntry> it = Collections.list(jarFile.entries()).stream().iterator();
while (it.hasNext()) {
JarEntry entry = it.next();
String name = entry.getName();
if (!name.startsWith(resourceName) || !name.endsWith(".class")) {
continue;
}
name = name.replace('/', '.').replaceAll(".class$", "");
Class.forName(name, true, classLoader);
logger.trace("loaded from jar - {}", name);
}
} catch (IOException e) {
throw new IllegalStateException(e);
}
} else if ("bundle".equals(root.getProtocol())) {
Collection<String> set = bundle.adapt(BundleWiring.class).listResources(resourceName, "*.class",
BundleWiring.LISTRESOURCES_RECURSE);
for (String name : set) {
name = name.replace('/', '.').replaceAll(".class$", "");
Class.forName(name, true, classLoader);
logger.trace("loaded from bundle - {}", name);
}
}
}
}
class FileFilter implements FilenameFilter {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".class");
}
}