Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust and clean-up/simplify sisu-OSGi-connect #1361

Merged
merged 2 commits into from
Sep 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public class MyPlexusComponent {
For the setup you need to do the following:

1. include any bundle you like to make up your plexus-osgi-connect framework as a dependency of your maven plugin
2. include a file `META-INF/sisu-connect.bundles` that list all your bundles you like to have installed in the format `bsn[,true]`, where `bsn` is the symbolid name and optionally you can control if your bundle has to be started or not
2. include a file `META-INF/sisu/connect.bundles` that list all your bundles you like to have installed in the format `bsn[,true]`, where `bsn` is the symbolid name and optionally you can control if your bundle has to be started or not
3. include the following additional dependency
```
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.logging.Logger;

final class DummyClassRealm extends ClassRealm {

Expand All @@ -30,15 +29,15 @@ final class DummyClassRealm extends ClassRealm {
private ClassLoader classLoader;
private List<URL> urls;

DummyClassRealm(String id, ClassLoader classLoader, Logger log) {
DummyClassRealm(String id, ClassLoader classLoader) {
super(new ClassWorld(), id, classLoader);
this.classLoader = classLoader;
}

@Override
public URL[] getURLs() {
if (urls == null) {
urls = new ArrayList<URL>();
urls = new ArrayList<>();
try {
Enumeration<URL> resources = classLoader.getResources(JarFile.MANIFEST_NAME);
while (resources.hasMoreElements()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@
* created by plexus
*
*/
class PlexusConnectFramework
class PlexusConnectFramework //
implements Logger, EmbeddedEquinox, EquinoxServiceFactory, FrameworkUtilHelper, FrameworkListener, LogListener,
BundleActivator {

private final Framework framework;
private final Logger logger;
private final String uuid = UUID.randomUUID().toString();
private final Map<Class<?>, ServiceTracker<?, ?>> trackerMap = new ConcurrentHashMap<Class<?>, ServiceTracker<?, ?>>();
private final Map<Class<?>, ServiceTracker<?, ?>> trackerMap = new ConcurrentHashMap<>();
private final ClassRealm realm;
final PlexusFrameworkConnectServiceFactory factory;
final boolean foreign;
Expand Down Expand Up @@ -313,29 +313,27 @@ public void logged(LogEntry entry) {
@Override
public void start(BundleContext context) {
context.addFrameworkListener(this);
serviceTracker = new ServiceTracker<LogReaderService, LogReaderService>(
context, LogReaderService.class, new ServiceTrackerCustomizer<LogReaderService, LogReaderService>() {

@Override
public LogReaderService addingService(ServiceReference<LogReaderService> reference) {
LogReaderService service = context.getService(reference);
if (service != null) {
service.addLogListener(PlexusConnectFramework.this);
}
return service;
}

@Override
public void modifiedService(ServiceReference<LogReaderService> reference,
LogReaderService service) {
}

@Override
public void removedService(ServiceReference<LogReaderService> reference, LogReaderService service) {
service.removeLogListener(PlexusConnectFramework.this);
context.ungetService(reference);
}
});
serviceTracker = new ServiceTracker<>(context, LogReaderService.class, new ServiceTrackerCustomizer<>() {

@Override
public LogReaderService addingService(ServiceReference<LogReaderService> reference) {
LogReaderService service = context.getService(reference);
if (service != null) {
service.addLogListener(PlexusConnectFramework.this);
}
return service;
}

@Override
public void modifiedService(ServiceReference<LogReaderService> reference, LogReaderService service) {
}

@Override
public void removedService(ServiceReference<LogReaderService> reference, LogReaderService service) {
service.removeLogListener(PlexusConnectFramework.this);
context.ungetService(reference);
}
});
serviceTracker.open();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,17 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Properties;
import java.util.ServiceLoader;
Expand All @@ -44,6 +41,7 @@
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.util.StringUtils;
import org.eclipse.sisu.equinox.EquinoxServiceFactory;
import org.eclipse.sisu.equinox.embedder.EquinoxLifecycleListener;
import org.osgi.framework.Bundle;
Expand Down Expand Up @@ -73,7 +71,7 @@ public class PlexusFrameworkConnectServiceFactory implements Initializable, Disp
private Logger log;

private static final Map<ClassRealm, PlexusConnectFramework> frameworkMap = new HashMap<>();

private static final Map<ClassLoader, ClassRealm> loaderMap = new HashMap<>();

@Requirement(role = EquinoxLifecycleListener.class)
Expand Down Expand Up @@ -109,15 +107,15 @@ synchronized PlexusConnectFramework getFramework(ClassRealm realm) throws Bundle
}
Framework foreignFramework = getForeignFramework(realm);
if (foreignFramework != null) {
PlexusConnectFramework connectFramework = new PlexusConnectFramework(foreignFramework, log, this, realm,
true);
frameworkMap.put(realm, connectFramework);
return connectFramework;
PlexusConnectFramework connectFwk = new PlexusConnectFramework(foreignFramework, log, this, realm, true);
frameworkMap.put(realm, connectFwk);
return connectFwk;
}
if (log.isDebugEnabled()) {
printRealm(realm, 0, new HashSet<ClassRealm>());
printRealm(realm, 0, new HashSet<>());
}
Collection<ClassRealm> realms = collectRealms(realm, new LinkedHashSet<ClassRealm>());
Collection<ClassRealm> realms = collectRealms(realm, new LinkedHashSet<>());

log.debug("Create framework for " + this + " with realm " + realm);
Logger fwLogger = new PlexusConnectFramework(null, log, this, realm, false);
Map<String, String> p = readProperties(realm, fwLogger);
Expand All @@ -129,23 +127,25 @@ synchronized PlexusConnectFramework getFramework(ClassRealm realm) throws Bundle
p.put(Constants.FRAMEWORK_STORAGE, storagePath + File.separator + "storage");
p.put(Constants.FRAMEWORK_BEGINNING_STARTLEVEL, "6");
p.put("osgi.instance.area", storagePath + File.separator + "instance");
ServiceLoader<ConnectFrameworkFactory> sl = ServiceLoader.load(ConnectFrameworkFactory.class,
getClass().getClassLoader());
ConnectFrameworkFactory factory = sl.iterator().next();

var loader = ServiceLoader.load(ConnectFrameworkFactory.class, getClass().getClassLoader());
ConnectFrameworkFactory factory = loader.findFirst()
.orElseThrow(() -> new NoSuchElementException("No ConnectFrameworkFactory found"));

PlexusModuleConnector connector = new PlexusModuleConnector(factory);
Framework osgiFramework = factory.newFramework(p, connector);
PlexusConnectFramework connectFramework = new PlexusConnectFramework(osgiFramework, log, this, realm, false);
PlexusFrameworkUtilHelper.registerHelper(connectFramework);
osgiFramework.init(connectFramework);
frameworkMap.put(realm, connectFramework);

connectFramework.start(osgiFramework.getBundleContext());
for (ClassRealm r : realms) {
connector.installRealm(r, osgiFramework.getBundleContext(), connectFramework);
}
osgiFramework.start();

Collection<EquinoxLifecycleListener> values = lifecycleListeners.values();
for (EquinoxLifecycleListener listener : values) {
for (EquinoxLifecycleListener listener : lifecycleListeners.values()) {
connectFramework.debug("Calling " + listener + "...");
listener.afterFrameworkStarted(connectFramework);
}
Expand All @@ -163,17 +163,11 @@ private void printRealm(ClassRealm realm, int indent, Set<ClassRealm> printed) {
printRealm(parentRealm, indent, printed);
indent += 2;
}
for (int j = 0; j < indent; j++) {
System.out.print(' ');
}
System.out.println("> " + realm.getId() + " (parent = " + realm.getParentRealm() + ")");
String indentation = StringUtils.repeat(" ", indent);
System.out.println(indentation + "> " + realm.getId() + " (parent = " + realm.getParentRealm() + ")");
Enumeration<URL> resources = realm.loadResourcesFromSelf(PlexusModuleConnector.MAVEN_EXTENSION_DESCRIPTOR);
while (resources != null && resources.hasMoreElements()) {
URL url = resources.nextElement();
for (int j = 0; j < indent; j++) {
System.out.print(' ');
}
System.out.println(" " + url);
if (resources != null) {
resources.asIterator().forEachRemaining(url -> System.out.println(indentation + " " + url));
}
realm.display();
for (ClassRealm imports : realm.getImportRealms()) {
Expand All @@ -195,24 +189,22 @@ private static Collection<ClassRealm> collectRealms(ClassRealm realm, Collection
return realms;
}

protected ClassRealm getRealm(ClassLoader classloader) throws BundleException {
protected ClassRealm getRealm(ClassLoader classloader) {
if (classloader instanceof ClassRealm) {
return (ClassRealm) classloader;
}
return loaderMap.computeIfAbsent(classloader,
cl -> new DummyClassRealm("Not called from a ClassRealm", cl, log));
return loaderMap.computeIfAbsent(classloader, cl -> new DummyClassRealm("Not called from a ClassRealm", cl));
}

private static Map<String, String> readProperties(ClassLoader classloader, Logger logger) {
Map<String, String> frameworkProperties = new HashMap<String, String>();
Map<String, String> frameworkProperties = new HashMap<>();
Enumeration<URL> resources;
try {
resources = classloader.getResources("META-INF/sisu-connect.properties");
resources = classloader.getResources("META-INF/sisu/connect.properties");
} catch (IOException e1) {
return frameworkProperties;
}
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
resources.asIterator().forEachRemaining(url -> {
logger.debug("Reading properties from " + url);
Properties properties = new Properties();
try (InputStream stream = url.openStream()) {
Expand All @@ -221,14 +213,10 @@ private static Map<String, String> readProperties(ClassLoader classloader, Logge
logger.warn("Can't read properties from url " + url);
}
for (String property : properties.stringPropertyNames()) {
String existing = frameworkProperties.get(property);
if (existing == null) {
frameworkProperties.put(property, properties.getProperty(property));
} else {
frameworkProperties.put(property, existing + "," + properties.getProperty(property));
}
String value = properties.getProperty(property);
frameworkProperties.merge(property, value, (v1, v2) -> v1 + "," + v2);
}
}
});
return frameworkProperties;
}

Expand All @@ -239,10 +227,11 @@ private static void printFrameworkState(Framework framework, Logger log) {
String.CASE_INSENSITIVE_ORDER);
Comparator<Bundle> byState = Comparator.comparingInt(Bundle::getState);
Arrays.stream(bundles).sorted(byState.thenComparing(bySymbolicName)).forEachOrdered(bundle -> {
log.info(toBundleState(bundle.getState()) + " | " + bundle.getSymbolicName() + " (" + bundle.getVersion()
+ ")");
String state = toBundleState(bundle.getState());
log.info(state + " | " + bundle.getSymbolicName() + " (" + bundle.getVersion() + ") at "
+ bundle.getLocation());
});
ServiceTracker<ServiceComponentRuntime, ServiceComponentRuntime> st = new ServiceTracker<ServiceComponentRuntime, ServiceComponentRuntime>(
ServiceTracker<ServiceComponentRuntime, ServiceComponentRuntime> st = new ServiceTracker<>(
framework.getBundleContext(), ServiceComponentRuntime.class, null);
st.open();
try {
Expand Down Expand Up @@ -273,8 +262,8 @@ private static void printFrameworkState(Framework framework, Logger log) {
st.close();
}
log.info("============ Registered Services ==================");
Arrays.stream(bundles).map(bundle -> bundle.getRegisteredServices()).filter(Objects::nonNull)
.flatMap(Arrays::stream).forEach(reference -> {
Arrays.stream(bundles).map(Bundle::getRegisteredServices).filter(Objects::nonNull).flatMap(Arrays::stream)
.forEach(reference -> {
Object service = reference.getProperty(Constants.OBJECTCLASS);
if (service instanceof Object[]) {
Object[] objects = (Object[]) service;
Expand Down Expand Up @@ -324,14 +313,11 @@ private static String toBundleState(int state) {

@Override
public void dispose() {
List<Entry<ClassRealm, PlexusConnectFramework>> cleared = new ArrayList<>();
frameworkMap.entrySet().forEach(entry -> {
PlexusConnectFramework connect = entry.getValue();
if (connect.factory == this) {
cleared.add(entry);
if (connect.foreign) {
return;
}
frameworkMap.values().removeIf(connect -> {
if (connect.factory != this) {
return false;
}
if (!connect.foreign) {
Framework fw = connect.getFramework();
connect.stop(fw.getBundleContext());
String storage = fw.getBundleContext().getProperty(Constants.FRAMEWORK_STORAGE);
Expand All @@ -348,15 +334,12 @@ public void dispose() {
FileUtils.deleteQuietly(new File(storage));
}
}
return true;
});
for (Entry<ClassRealm, PlexusConnectFramework> entry : cleared) {
frameworkMap.remove(entry.getKey(), entry.getValue());
}
}

@Override
public void initialize() throws InitializationException {

log.debug("Init instance " + this + " [" + getClass().getClassLoader() + "]");
}

Expand Down Expand Up @@ -399,18 +382,9 @@ public static Framework getForeignFramework(ClassRealm realm) {
try {
Method method = foreignFactoryClass.getMethod("getOsgiFramework", ClassRealm.class);
return (Framework) method.invoke(null, realm);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
} catch (ReflectiveOperationException e) {
}
}
return null;
}

public static Framework getOsgiFramework(ClassRealm realm) {
PlexusConnectFramework cachedFramework = frameworkMap.get(realm);
if (cachedFramework != null) {
return cachedFramework.getFramework();
}
return null;
}
}
Loading