Thanks to everyone for replies,

For the benefit of others stuck in this hole, using info in http://njbartlett.name/2010/08/30/osgi-readiness-loading-classes.html and clues provided by Timothy and others, I have been able to get  a working solution. As suggested by Neil in his blog, it is as simple as picking any class in a bundle, in this case the com.vaadin.shared bundle and getting the class loader as shown below.
This then covers all components in that bundle.

Amazing how simple things are when you know how :-P.

Paul

public class QNEComponentFactory implements ComponentFactory {

    private ClassLoader vaadinClassLoader;

    public QNEComponentFactory() {
        vaadinClassLoader = Label.class.getClassLoader(); <<<<<<<<<<<<<<<<could be any component in the bundle<<<<
    }

    @Override
    public Component createComponent(String fullyQualifiedClassName, 
DesignContext context) {

        Class<? extends Component> componentClass;
        try {
            componentClass = resolveComponentClass(fullyQualifiedClassName, 
context);
        } catch (DesignException e) {
            // Try with an inner class.
            int lastDot = fullyQualifiedClassName.lastIndexOf('.');
            if (lastDot != -1) {
                String qualifiedInnerClassName = fullyQualifiedClassName.substring(0, 
lastDot) + "$"
                        + fullyQualifiedClassName.substring(lastDot + 1);
                return createComponent(qualifiedInnerClassName, context);
            } else {
                throw e;
            }

        }

        assert Component.class.isAssignableFrom(componentClass) : "resolveComponentClass returned " + componentClass
                + " which is not a Vaadin Component class";

        try {
            return ReflectTools.createInstance(componentClass);
        } catch (Exception e) {
            throw new DesignException("Could not create component " + 
fullyQualifiedClassName, e);
        }
    }

    /**
     * Resolves a component class based on the fully qualified name of the 
class.
     *
     * @param qualifiedClassName
     *            the fully qualified name of the resolved class
     * @param context
     *            the design context for which the class is resolved
     * @return a component class object representing the provided class name
     */
    protected Class<? extends Component> resolveComponentClass(String qualifiedClassName, DesignContext context) {
        try {
//            Class<?> componentClass = Class.forName(qualifiedClassName, true,VaadinServiceClassLoaderUtil.findDefaultClassLoader());

            Class<?> componentClass = Class.forName(qualifiedClassName, true, vaadinClassLoader); <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

            return componentClass.asSubclass(Component.class);
        } catch (ClassNotFoundException e) {
            throw new DesignException("Unable to load component for design", e);
        }
    }

}


On 19/09/2017 1:16 AM, Timothy Ward wrote:
I would not recommend any solution which involves the use of DynamicImport-Package: *. This is roughly equivalent to saying “I give up and want to switch off OSGi”. You lose any ability to validate a that a set of bundles is complete, and you have no guarantee that things will work at runtime. You also introduce ordering issues into

As BJ says the correct thing to do is to pass sufficient context for the runtime to actually use the plugin. This means that you could:

  * Provide your own ComponentFactory which returns a fully configured instance 
- this is possible
    with the existing API
  * Pass a Class object rather than a String. This would need a minor change to 
the existing user
    interface
  * Have OSGi clients obtain an OSGi service from the Vaadin runtime. This 
service can be
    specialised to each client bundle, at which point the service has 
sufficient context to load
    the plugin class from a String class name.


There are probably other ways to skin this particular cat, but resorting to TCCL and/or DynamicImport-Package: * should be a very long way down the list.

Regards,

Tim Ward




_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to