chemistry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Sascha Homeier (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (CMIS-878) Allow loading classes from other OSGi Bundles in OSGi Client Wrapper
Date Thu, 07 May 2015 13:57:07 GMT

    [ https://issues.apache.org/jira/browse/CMIS-878?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14532664#comment-14532664
] 

Sascha Homeier edited comment on CMIS-878 at 5/7/15 1:56 PM:
-------------------------------------------------------------

Thats a good hint. Unfortenately SessionFactoryImpl is not accessible from another OSGi bundle
because it is not exported.
But it clears the way for a imho nice solution which only needs modification inside OSGi client
Activator and SessionFactoryImpl:

1. In Activator bind the OSGi services of AuthenticationProvider, ObjectFactory, Cache and
TypeDefinitionCache (if any).
{code}
 public void start(BundleContext context) {
        // register the MetaTypeService now, that we are ready
        Dictionary<String, String> props = new Hashtable<String, String>();
        props.put(Constants.SERVICE_DESCRIPTION, "Apache Chemistry OpenCMIS Client Session
Factory");
        props.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");

        // get Chemistry OpenCMIS service references - they may be null
        ObjectFactory objectFactory = getObjectFactory(context);
        AuthenticationProvider authenticationProvider = getAuthenticationProvider(context);
        Cache cache = getCache(context);
        TypeDefinitionCache typeDefCache = getTypeDefinitionCache(context);

        SessionFactoryImpl sessionFactory = SessionFactoryImpl.newInstance(objectFactory,
authenticationProvider,
                cache, typeDefCache);

        context.registerService(SessionFactory.class.getName(), sessionFactory, props);
}

public void stop(BundleContext context) {
        // The SessionFactory service will be unregistered automatically
}

private AuthenticationProvider getAuthenticationProvider(BundleContext context) {

        ServiceReference<?> serviceReference = context
                .getServiceReference(org.apache.chemistry.opencmis.commons.spi.AuthenticationProvider.class.getName());
        if (serviceReference != null) {
            return (AuthenticationProvider) context.getService(serviceReference);
        } else {
            return null;
        }
}

...
{code}

2. In SessionFactoryImpl pass the AuthenticationProvider, ObjectFactory, Cache and TypeDefCache:
{code}
public class SessionFactoryImpl implements SessionFactory, Serializable {

    private static final long serialVersionUID = 1L;

    private ObjectFactory objectFactory;

    private AuthenticationProvider authenticationProvider;

    private Cache cache;

    private TypeDefinitionCache typeDefCache;

    protected SessionFactoryImpl() {
    }

    public static SessionFactoryImpl newInstance() {
        return new SessionFactoryImpl();
    }

    protected SessionFactoryImpl(ObjectFactory objectFactory, AuthenticationProvider authenticationProvider,
            Cache cache, TypeDefinitionCache typeDefCache) {
        this.objectFactory = objectFactory;
        this.authenticationProvider = authenticationProvider;
        this.cache = cache;
        this.typeDefCache = typeDefCache;
    }

    public static SessionFactoryImpl newInstance(ObjectFactory objectFactory,
            AuthenticationProvider authenticationProvider, Cache cache, TypeDefinitionCache
typeDefCache) {
        return new SessionFactoryImpl(objectFactory, authenticationProvider, cache, typeDefCache);
    }

    public Session createSession(Map<String, String> parameters) {
        return createSession(parameters, objectFactory, authenticationProvider, cache, typeDefCache);
    }
...
}
{code}

All AuthProvider, ObjFactory and the two Caches are null if no OSGi service was found (so
old behaviour is not changed).
If one or more services were found they override the SessionParam.

So my main concern was to not change common functionality in non-OSGi environment (obviously
the most often used) and to not change it in OSGi environment (for example when fragments
are used).

Unfortenately the Cache and TypeDefinitionCache are in internal packages.
Any chance to move them to SPI public packages?
If not I can limit the code avove to AuthProvider and ObjectFactory only.

I implemented the feature here in a chemistry fork:
https://github.com/shomeier/chemistry-opencmis

I also tested it in an OSGi environment with a MockAuthenticationProvider OSGi Service and
a MockObjectFactory OSGi service.
(I can push the eclipse project if you are interested)

Please let me know what you think of it.
(Did not yet include JavaDoc etc because I first wanted to get some feedback)


was (Author: shomeier):
Thats a good hint. Unfortenately SessionFactoryImpl is not accessible from another OSGi bundle
because it is not exported.
But it clears the way for a imho nice solution which only needs modification inside OSGi client
Activator and SessionFactoryImpl:

1. In Activator bind the OSGi services of AuthenticationProvider, ObjectFactory, Cache and
TypeDefinitionCache (if any).
{code}
 public void start(BundleContext context) {
        // register the MetaTypeService now, that we are ready
        Dictionary<String, String> props = new Hashtable<String, String>();
        props.put(Constants.SERVICE_DESCRIPTION, "Apache Chemistry OpenCMIS Client Session
Factory");
        props.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");

        // get Chemistry OpenCMIS service references - they may be null
        ObjectFactory objectFactory = getObjectFactory(context);
        AuthenticationProvider authenticationProvider = getAuthenticationProvider(context);
        Cache cache = getCache(context);
        TypeDefinitionCache typeDefCache = getTypeDefinitionCache(context);

        SessionFactoryImpl sessionFactory = SessionFactoryImpl.newInstance(objectFactory,
authenticationProvider,
                cache, typeDefCache);

        context.registerService(SessionFactory.class.getName(), sessionFactory, props);
}

public void stop(BundleContext context) {
        // The SessionFactory service will be unregistered automatically
}

private AuthenticationProvider getAuthenticationProvider(BundleContext context) {

        ServiceReference<?> serviceReference = context
                .getServiceReference(org.apache.chemistry.opencmis.commons.spi.AuthenticationProvider.class.getName());
        if (serviceReference != null) {
            return (AuthenticationProvider) context.getService(serviceReference);
        } else {
            return null;
        }
}

...
{code}

2. In SessionFactoryImpl pass the AuthenticationProvider, ObjectFactory, Cache and TypeDefCache:
{code}
public class SessionFactoryImpl implements SessionFactory, Serializable {

    private static final long serialVersionUID = 1L;

    private ObjectFactory objectFactory;

    private AuthenticationProvider authenticationProvider;

    private Cache cache;

    private TypeDefinitionCache typeDefCache;

    protected SessionFactoryImpl() {
    }

    public static SessionFactoryImpl newInstance() {
        return new SessionFactoryImpl();
    }

    protected SessionFactoryImpl(ObjectFactory objectFactory, AuthenticationProvider authenticationProvider,
            Cache cache, TypeDefinitionCache typeDefCache) {
        this.objectFactory = objectFactory;
        this.authenticationProvider = authenticationProvider;
        this.cache = cache;
        this.typeDefCache = typeDefCache;
    }

    public static SessionFactoryImpl newInstance(ObjectFactory objectFactory,
            AuthenticationProvider authenticationProvider, Cache cache, TypeDefinitionCache
typeDefCache) {
        return new SessionFactoryImpl(objectFactory, authenticationProvider, cache, typeDefCache);
    }

    public Session createSession(Map<String, String> parameters) {
        return createSession(parameters, objectFactory, authenticationProvider, cache, typeDefCache);
    }
...
}
{code}

All AuthProvider, ObjFactory and the two Caches are null if no OSGi service was found (so
old behaviour is not changed).
If one or more services were found they override the SessionParam.

So my main concern was to not change common functionality in non-OSGi environment (obviously
the most often used) and to not change it in OSGi environment (for example when fragments
are used).

Unfortenately the Cache and TypeDefinitionCache are in internal packages.
Any chance to move them to SPI public packages?
If not I can limit the code avove to AuthProvider and ObjectFactory only.

I implemented the feature here in a chemistry fork:
https://github.com/shomeier/chemistry-opencmis

I also tested it in an OSGi environment with a MockAuthenticationProvider OSGi Service and
a MockObjectFactory OSGi service.
(I can push the eclipse project if you are interested)

Please let me know what you think of it.

> Allow loading classes from other OSGi Bundles in OSGi Client Wrapper
> --------------------------------------------------------------------
>
>                 Key: CMIS-878
>                 URL: https://issues.apache.org/jira/browse/CMIS-878
>             Project: Chemistry
>          Issue Type: Improvement
>          Components: opencmis-client
>    Affects Versions: OpenCMIS 0.12.0
>         Environment: OSGi
>            Reporter: Sascha Homeier
>            Priority: Minor
>
> When using the OpenCMIS OSGi Client Wrapper it is hard to load classes from other bundles.
For example if you specify an own Authentication Provider class as Session Parameter then
the Wrapper will not find this class when it is located inside another bundle. Same problem
should occur when defining an own Cache.
> *1)*
> It would be nice if other bundles could register their Classloaders so that ClassLoaderUtil
can use it when trying to load classes.
> *2)*
> Another simpler option would be to simply add "DynamicImport-Package: *" to the Manifest
of the Wrapper. By doing this the Wrapper will find all classes which are exported by other
bundles. Though this approach feels more like a hack since it breaks modularity.
> What do you think about it?
> Cheers
> Sascha



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Mime
View raw message