import java.util.TreeSet;
import org.argeo.api.cms.CmsLog;
+import org.argeo.cms.jshell.CmsExecutionControl;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
-import jdk.jshell.execution.DirectExecutionControl;
import jdk.jshell.spi.ExecutionControl;
import jdk.jshell.spi.ExecutionControlProvider;
import jdk.jshell.spi.ExecutionEnv;
@Override
public ExecutionControl generate(ExecutionEnv env, Map<String, String> parameters) throws Throwable {
- // TODO find a better way to get a default bundle context
- // NOTE: the related default bundle has to be started
-
-// String symbolicName = parameters.get(BUNDLE_PARAMETER);
-// Bundle fromBundle = getBundleFromSn(symbolicName);
-
Long bundleId = Long.parseLong(parameters.get(BUNDLE_PARAMETER));
Bundle fromBundle = getBundleFromId(bundleId);
BundleWiring fromBundleWiring = fromBundle.adapt(BundleWiring.class);
ClassLoader fromBundleClassLoader = fromBundleWiring.getClassLoader();
- // use the bundle classloade as context classloader
- Thread.currentThread().setContextClassLoader(fromBundleClassLoader);
-
- ExecutionControl executionControl = new DirectExecutionControl(
- new WrappingLoaderDelegate(fromBundleClassLoader));
- log.debug("JShell from " + fromBundle.getSymbolicName() + "_" + fromBundle.getVersion() + " ["
+ ExecutionControl executionControl = new CmsExecutionControl(env,
+ new WrappingLoaderDelegate(env, fromBundleClassLoader));
+ log.trace(() -> "JShell from " + fromBundle.getSymbolicName() + "_" + fromBundle.getVersion() + " ["
+ fromBundle.getBundleId() + "]");
return executionControl;
}
public static Path getBundleStartupScript(Long bundleId) {
BundleContext bc = FrameworkUtil.getBundle(OsgiExecutionControlProvider.class).getBundleContext();
Bundle fromBundle = bc.getBundle(bundleId);
+
+ int bundleState = fromBundle.getState();
+ if (Bundle.INSTALLED == bundleState)
+ throw new IllegalStateException("Bundle " + fromBundle.getSymbolicName() + " is not resolved");
+ if (Bundle.RESOLVED == bundleState) {
+ try {
+ fromBundle.start();
+ } catch (BundleException e) {
+ throw new IllegalStateException("Cannot start bundle " + fromBundle.getSymbolicName(), e);
+ }
+ while (Bundle.ACTIVE != fromBundle.getState())
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // we assume the session has been closed
+ throw new RuntimeException("Bundle " + fromBundle.getSymbolicName() + " is not active", e);
+ }
+ }
+
Path bundleStartupScript = fromBundle.getDataFile("BUNDLE.jsh").toPath();
BundleWiring fromBundleWiring = fromBundle.adapt(BundleWiring.class);
packagesToImport.add(pkg.getName());
}
- List<BundleWire> bundleWires = fromBundleWiring.getRequiredWires(BundleRevision.PACKAGE_NAMESPACE);
- for (BundleWire bw : bundleWires) {
+// List<BundleWire> exportedWires = fromBundleWiring.getProvidedWires(BundleRevision.PACKAGE_NAMESPACE);
+// for (BundleWire bw : exportedWires) {
+// packagesToImport.add(bw.getCapability().getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE).toString());
+// }
+
+ List<BundleWire> importedWires = fromBundleWiring.getRequiredWires(BundleRevision.PACKAGE_NAMESPACE);
+ for (BundleWire bw : importedWires) {
packagesToImport.add(bw.getCapability().getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE).toString());
}
for (String p : packagesToImport) {
writer.write("import " + p + ".*;\n");
}
+
+ String std = """
+ /open DEFAULT
+ import jdk.jshell.spi.ExecutionEnv;
+ import java.util.function.*;
+
+ /** Redirected standard IO. */
+ public class Std {
+ final static InputStream in = new Supplier<InputStream>() {
+
+ @Override
+ public InputStream get() {
+ return ((ExecutionEnv) getClass().getClassLoader()).userIn();
+ }
+
+ }.get();
+ final static PrintStream out = new Supplier<PrintStream>() {
+
+ @Override
+ public PrintStream get() {
+ return ((ExecutionEnv) getClass().getClassLoader()).userOut();
+ }
+
+ }.get();
+ final static PrintStream err = new Supplier<PrintStream>() {
+
+ @Override
+ public PrintStream get() {
+ return ((ExecutionEnv) getClass().getClassLoader()).userErr();
+ }
+
+ }.get();
+
+ }
+ """;
+ writer.write(std);
} catch (IOException e) {
throw new RuntimeException("Cannot writer bundle startup script to " + bundleStartupScript, e);
}
}
public static String getBundleClasspath(Long bundleId) throws IOException {
- String framework = System.getProperty("osgi.framework");
- Path frameworkLocation = Paths.get(URI.create(framework)).toAbsolutePath();
BundleContext bc = FrameworkUtil.getBundle(OsgiExecutionControlProvider.class).getBundleContext();
+ String framework = bc.getProperty("osgi.framework");
+ Path frameworkLocation = Paths.get(URI.create(framework)).toAbsolutePath();
Bundle fromBundle = bc.getBundle(bundleId);
BundleWiring fromBundleWiring = fromBundle.adapt(BundleWiring.class);
continue bundles;
}
Path p = bundleToPath(frameworkLocation, b);
- classpath.add(p.toString());
+ if (p != null)
+ classpath.add(p.toString());
}
return classpath.toString();
static Path bundleToPath(Path frameworkLocation, Bundle bundle) throws IOException {
String location = bundle.getLocation();
- if (location.startsWith("initial@reference:file:")) {
+ if (location.startsWith("initial@reference:file:")) {// Eclipse IDE environment
location = location.substring("initial@reference:file:".length());
- Path p = frameworkLocation.getParent().resolve(location).toRealPath();
- // TODO load dev.properties from OSGi configuration directory
- if (Files.isDirectory(p))
- p = p.resolve("bin");
- return p;
+ Path p = frameworkLocation.getParent().resolve(location).toAbsolutePath();
+ if (Files.exists(p)) {
+ p = p.toRealPath();
+ // TODO load dev.properties from OSGi configuration directory
+ if (Files.isDirectory(p))
+ p = p.resolve("bin");
+ return p;
+ } else {
+ log.warn("Ignore bundle " + p + " as it does not exist");
+ return null;
+ }
+ } else if (location.startsWith("reference:file:")) {// a2+reference
+ location = location.substring("reference:".length());
+ Path p = Paths.get(URI.create(location));
+ if (Files.exists(p)) {
+ return p;
+ } else {
+ log.warn("Ignore bundle " + p + " as it does not exist");
+ return null;
+ }
}
Path p = Paths.get(location);
return p;