Skip to main content

[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");
	}
}


Back to the top