com.paremus.dosgi.net.impl.RemoteServiceAdminFactoryImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.paremus.dosgi.net Show documentation
Show all versions of com.paremus.dosgi.net Show documentation
An implementation of OSGi Remote Service Admin, enhanced to
provide support for OSGi Promises and streaming using OSGi
PushStreams.
The newest version!
/*-
* #%L
* com.paremus.dosgi.net
* %%
* Copyright (C) 2016 - 2019 Paremus Ltd
* %%
* Licensed under the Fair Source License, Version 0.9 (the "License");
*
* See the NOTICE.txt file distributed with this work for additional
* information regarding copyright ownership. You may not use this file
* except in compliance with the License. For usage restrictions see the
* LICENSE.txt file distributed with this work
* #L%
*/
package com.paremus.dosgi.net.impl;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.launch.Framework;
import com.paremus.dosgi.net.client.ClientConnectionManager;
import com.paremus.dosgi.net.config.TransportConfig;
import com.paremus.dosgi.net.server.RemotingProvider;
import com.paremus.dosgi.net.server.ServerConnectionManager;
import com.paremus.netty.tls.ParemusNettyTLS;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.EventLoopGroup;
import io.netty.util.Timer;
import io.netty.util.concurrent.EventExecutorGroup;
public class RemoteServiceAdminFactoryImpl implements ServiceFactory {
private static class Tuple {
final RemoteServiceAdminEventPublisher rp;
final int usageCount;
public Tuple(RemoteServiceAdminEventPublisher rp, int usageCount) {
this.rp = rp;
this.usageCount = usageCount;
}
}
private final ServerConnectionManager serverConnectionManager;
private final ClientConnectionManager clientConnectionManager;
private final ConcurrentMap bundleFrameworks
= new ConcurrentHashMap<>();
private final ConcurrentMap publisherReferenceCounts
= new ConcurrentHashMap<>();
private final List impls = new CopyOnWriteArrayList<>();
private final EventExecutorGroup serverWorkers;
private final EventExecutorGroup clientWorkers;
private final Timer timer;
private final TransportConfig config;
public RemoteServiceAdminFactoryImpl(TransportConfig config, ParemusNettyTLS tls,
ByteBufAllocator allocator, EventLoopGroup serverIo, EventLoopGroup clientIo,
EventExecutorGroup serverWorkers, EventExecutorGroup clientWorkers, Timer timer) {
this.config = config;
this.timer = timer;
this.serverWorkers = serverWorkers;
this.clientWorkers = clientWorkers;
clientConnectionManager = new ClientConnectionManager(config, tls, allocator, clientIo, clientWorkers, timer);
serverConnectionManager = new ServerConnectionManager(config, tls, allocator, serverIo, timer);
}
@Override
public RemoteServiceAdminImpl getService(Bundle bundle, ServiceRegistration registration) {
Framework framework = bundle.getBundleContext().getBundle(0).adapt(Framework.class);
bundleFrameworks.put(bundle, framework);
RemoteServiceAdminEventPublisher rsaep = publisherReferenceCounts
.compute(framework, (k,v) -> {
Tuple toReturn = v == null ? new Tuple(
new RemoteServiceAdminEventPublisher(framework.getBundleContext()), 1) :
new Tuple(v.rp, v.usageCount + 1);
return toReturn;
}).rp;
rsaep.start();
RemoteServiceAdminImpl impl = new RemoteServiceAdminImpl(this, framework, rsaep, serverConnectionManager.getConfiguredProviders(),
clientConnectionManager, getSupportedIntents(), new ProxyHostBundleFactory(), serverWorkers,
clientWorkers, timer, config);
impls.add(impl);
return impl;
}
@Override
public void ungetService(Bundle bundle, ServiceRegistration registration,
RemoteServiceAdminImpl service) {
impls.remove(service);
service.close();
Framework framework = bundleFrameworks.remove(bundle);
AtomicReference toClose = new AtomicReference();
publisherReferenceCounts
.computeIfPresent(framework, (k,v) -> {
toClose.set(null);
if(v.usageCount == 1) {
toClose.set(v.rp);
return null;
} else {
return new Tuple(v.rp, v.usageCount - 1);
}
});
ofNullable(toClose.get())
.ifPresent(RemoteServiceAdminEventPublisher::destroy);
}
public void close() {
serverConnectionManager.close();
clientConnectionManager.close();
}
public List getSupportedIntents() {
List intents = new ArrayList<>();
intents.add("asyncInvocation");
intents.add("osgi.basic");
intents.add("osgi.async");
intents.addAll(Arrays.asList(config.additional_intents()));
if(serverConnectionManager.getConfiguredProviders().stream()
.anyMatch(RemotingProvider::isSecure)) {
intents.add("confidentiality.message");
intents.add("osgi.confidential");
}
return intents;
}
Collection getRemoteServiceAdmins() {
return impls.stream().collect(toList());
}
}