org.osgi.service.http.whiteboard;version=0.0.0,\
org.osgi.framework.namespace;version=0.0.0,\
org.argeo.cms.osgi,\
-javax.servlet.*;version="[3,5)",\
*
+# javax.servlet.*;version="[3,5)",\
+
+
Service-Component:\
OSGI-INF/pkgServletContext.xml,\
OSGI-INF/pkgServlet.xml,\
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).toAbsolutePath();
if (Files.exists(p)) {
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;
//
@Override
public void logged(LogEntry status) {
- CmsLog pluginLog = CmsLog.getLog(status.getBundle().getSymbolicName());
+ String loggerName = status.getBundle().getSymbolicName();
+ if (loggerName == null)
+ loggerName = "org.argeo.ext.osgi";
+ CmsLog pluginLog = CmsLog.getLog(loggerName);
LogLevel severity = status.getLogLevel();
if (severity.equals(LogLevel.ERROR) && pluginLog.isErrorEnabled()) {
// FIXME Fix Argeo TP
if (contextPath == null)
return; // ignore silently
httpHandlers.remove(contextPath);
- if (!httpServer.isDone())
+ if (!httpExpected || !httpServer.isDone())
return;
// TODO use resultNow when switching to Java 21
httpServer.join().removeContext(contextPath);
org.osgi.*;version=0.0.0,\
java.util.logging;resolution:=optional
-Export-Package: org.argeo.api.*
\ No newline at end of file
+Export-Package: \
+org.argeo.api.*,\
+org.argeo.init.osgi,\
\ No newline at end of file
package org.argeo.api.init;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Map;
+import java.util.Properties;
import java.util.function.Consumer;
/** Dynamically manages multiple runtimes within a single JVM. */
public interface RuntimeManager {
+ String JVM_ARGS = "jvm.args";
+ String STATE = "state";
+ String DATA = "data";
+
public void startRuntime(String relPath, Consumer<Map<String, String>> configCallback);
public void closeRuntime(String relPath, boolean async);
+
+ static void loadConfig(Path dir, Map<String, String> config) {
+ try {
+ // System.out.println("Load from " + dir);
+ Path jvmArgsPath = dir.resolve(RuntimeManager.JVM_ARGS);
+ if (!Files.exists(jvmArgsPath)) {
+ // load from parent directory
+ loadConfig(dir.getParent(), config);
+ }
+
+ if (Files.exists(dir))
+ for (Path p : Files.newDirectoryStream(dir, "*.ini")) {
+ Properties props = new Properties();
+ try (InputStream in = Files.newInputStream(p)) {
+ props.load(in);
+ }
+ for (Object key : props.keySet()) {
+ config.put(key.toString(), props.getProperty(key.toString()));
+ }
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException("Cannot load configuration from " + dir, e);
+ }
+ }
}
import static org.argeo.api.init.InitConstants.SYMBOLIC_NAME_INIT;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
-import java.util.Properties;
import java.util.TreeMap;
import java.util.function.Consumer;
private final static long RUNTIME_SHUTDOWN_TIMEOUT = 60 * 1000;
- private final static String JVM_ARGS = "jvm.args";
-
private Path baseConfigArea;
- private Path baseStateArea;
+ private Path baseWritableArea;
private Map<String, String> configuration = new HashMap<>();
private Map<String, OsgiRuntimeContext> runtimeContexts = new TreeMap<>();
RuntimeManagerMain(Path configArea, Path stateArea) {
- loadConfig(configArea, configuration);
- configuration.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, stateArea.toUri().toString());
+ RuntimeManager.loadConfig(configArea, configuration);
+ configuration.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, stateArea.resolve(STATE).toUri().toString());
+ // use config area if instance area is not set
+ if (!configuration.containsKey(InitConstants.PROP_OSGI_INSTANCE_AREA))
+ configuration.put(InitConstants.PROP_OSGI_INSTANCE_AREA, stateArea.resolve(DATA).toUri().toString());
this.baseConfigArea = configArea.getParent();
- this.baseStateArea = stateArea.getParent();
+ this.baseWritableArea = stateArea.getParent();
logger.log(Level.TRACE, () -> "Runtime manager configuration: " + configuration);
}
}
- public static void loadConfig(Path dir, Map<String, String> config) {
- try {
-// System.out.println("Load from " + dir);
- Path jvmArgsPath = dir.resolve(JVM_ARGS);
- if (!Files.exists(jvmArgsPath)) {
- // load from parent directory
- loadConfig(dir.getParent(), config);
- }
-
- if (Files.exists(dir))
- for (Path p : Files.newDirectoryStream(dir, "*.ini")) {
- Properties props = new Properties();
- try (InputStream in = Files.newInputStream(p)) {
- props.load(in);
- }
- for (Object key : props.keySet()) {
- config.put(key.toString(), props.getProperty(key.toString()));
- }
- }
- } catch (IOException e) {
- throw new UncheckedIOException("Cannot load configuration from " + dir, e);
- }
- }
-
OsgiRuntimeContext loadRuntime(String relPath, Consumer<Map<String, String>> configCallback) {
closeRuntime(relPath, false);
- Path stateArea = baseStateArea.resolve(relPath);
+ Path writableArea = baseWritableArea.resolve(relPath);
Path configArea = baseConfigArea.resolve(relPath);
Map<String, String> config = new HashMap<>();
- loadConfig(configArea, config);
- config.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, stateArea.toUri().toString());
+ RuntimeManager.loadConfig(configArea, config);
+ config.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, writableArea.resolve(STATE).toUri().toString());
if (configCallback != null)
configCallback.accept(config);
// use config area if instance area is not set
if (!config.containsKey(InitConstants.PROP_OSGI_INSTANCE_AREA))
- config.put(InitConstants.PROP_OSGI_INSTANCE_AREA, config.get(InitConstants.PROP_OSGI_CONFIGURATION_AREA));
+ config.put(InitConstants.PROP_OSGI_INSTANCE_AREA, writableArea.resolve(DATA).toUri().toString());
OsgiRuntimeContext runtimeContext = new OsgiRuntimeContext(config);
runtimeContexts.put(relPath, runtimeContext);
OsgiRuntimeContext runtimeContext = loadRuntime(relPath, configCallback);
runtimeContext.run();
Framework framework = runtimeContext.getFramework();
+
+// for (Bundle b : framework.getBundleContext().getBundles()) {
+// try {
+//// if (b.getSymbolicName().startsWith("org.eclipse.swt.gtk")) {
+//// b.uninstall();
+//// }
+//// else if (b.getSymbolicName().startsWith("org.eclipse.jface")) {
+//// b.uninstall();
+//// }
+// } catch (Exception e) {
+// // TODO Auto-generated catch block
+// e.printStackTrace();
+// }
+// }
+
if (framework != null) {// in case the framework has closed very quickly after run
framework.getBundleContext().addFrameworkListener((e) -> {
if (e.getType() >= FrameworkEvent.STOPPED) {
// we don't synchronize maps on purpose as it would be
// too expensive during normal operation
// updates to the config may be shortly inconsistent
- private SortedMap<String, ThinLogger> loggers = new TreeMap<>();
+ private SortedMap<String, ThinLogger> loggers = Collections.synchronizedSortedMap(new TreeMap<>());
private NavigableMap<String, Level> levels = new TreeMap<>();
private volatile boolean updatingConfiguration = false;
}
public Logger getLogger(String name, Module module) {
+ Objects.requireNonNull(name, "logger name");
if (!loggers.containsKey(name)) {
ThinLogger logger = new ThinLogger(name, computeApplicableLevel(name));
loggers.put(name, logger);
provisioningManager.registerSource(
A2Source.SCHEME_A2 + "://" + homePath.toString() + "/.local/share/a2" + queryPart);
provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/share/a2" + queryPart);
- provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/lib/a2" + queryPart);
+// provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/lib/a2" + queryPart);
provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/share/a2" + queryPart);
- provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/lib/a2" + queryPart);
+// provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/lib/a2" + queryPart);
} else if (source.trim().equals(A2Source.DEFAULT_A2_REFERENCE_URI)) {
if (Files.exists(homePath))
provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + "://" + homePath.toString()
+ "/.local/share/a2" + queryPart);
provisioningManager
.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/share/a2" + queryPart);
- provisioningManager
- .registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/lib/a2" + queryPart);
+// provisioningManager
+// .registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/lib/a2" + queryPart);
provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/share/a2" + queryPart);
- provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/lib/a2" + queryPart);
+// provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/lib/a2" + queryPart);
} else {
provisioningManager.registerSource(source + queryPart);
}
}
OsgiBoot osgiBoot = new OsgiBoot(bundleContext);
String frameworkUuuid = bundleContext.getProperty(Constants.FRAMEWORK_UUID);
- new Thread("OSGi boot framework " + frameworkUuuid) {
+
+ // separate thread in order to improve logging
+ Thread osgiBootThread = new Thread("OSGi boot framework " + frameworkUuuid) {
@Override
public void run() {
osgiBoot.bootstrap(config);
}
- }.start();
+ };
+ osgiBootThread.start();
+ // TODO return a completable stage so that inits can run in parallel
+// try {
+// osgiBootThread.join(60 * 1000);
+// } catch (InterruptedException e) {
+// // silent
+// }
}
public void update() {
-Subproject commit 6f8e29e850f9fcfa5149e296e650355fab930752
+Subproject commit e021d17c09f8586a68177e9eb40d9caa088c37b1
package org.argeo.eclipse.ui.specific;
-import org.eclipse.jface.viewers.AbstractTableViewer;
-import org.eclipse.jface.viewers.ColumnViewer;
-import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
-import org.eclipse.jface.viewers.Viewer;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.swt.widgets.Widget;
widget.setData("org.eclipse.rap.rwt.markupValidationDisabled", Boolean.TRUE);
}
- /**
- * TootlTip support is supported only for {@link AbstractTableViewer} in RAP
- */
- public static void enableToolTipSupport(Viewer viewer) {
- if (viewer instanceof ColumnViewer)
- ColumnViewerToolTipSupport.enableFor((ColumnViewer) viewer);
- }
-
private EclipseUiSpecificUtils() {
}
}
// Styling
CmsTheme theme = CmsSwtUtils.getCmsTheme(parent);
if (theme != null) {
- cssEngine = new CSSSWTEngineImpl(display);
- for (String path : theme.getSwtCssPaths()) {
- try (InputStream in = theme.loadPath(path)) {
- cssEngine.parseStyleSheet(in);
- } catch (IOException e) {
- throw new IllegalStateException("Cannot load stylesheet " + path, e);
+ try {
+ cssEngine = new CSSSWTEngineImpl(display);
+ for (String path : theme.getSwtCssPaths()) {
+ try (InputStream in = theme.loadPath(path)) {
+ cssEngine.parseStyleSheet(in);
+ } catch (IOException e) {
+ throw new IllegalStateException("Cannot load stylesheet " + path, e);
+ }
}
+ cssEngine.setErrorHandler(new CSSErrorHandler() {
+ public void error(Exception e) {
+ log.error("SWT styling error: ", e);
+ }
+ });
+ applyStyles(shell);
+ } catch (Throwable e) {// could be a class not found error
+ log.error("Cannot initialise RCP theming", e);
}
- cssEngine.setErrorHandler(new CSSErrorHandler() {
- public void error(Exception e) {
- log.error("SWT styling error: ", e);
- }
- });
- applyStyles(shell);
}
shell.layout(true, true);
public void run() {
try {
display = Display.getDefault();
- display.setRuntimeExceptionHandler((e) -> e.printStackTrace());
- display.setErrorHandler((e) -> e.printStackTrace());
-
- while (!shutdown) {
- if (!display.readAndDispatch())
- display.sleep();
+ boolean displayOwner = display.getThread() == this;
+ if (displayOwner) {
+ display.setRuntimeExceptionHandler((e) -> e.printStackTrace());
+ display.setErrorHandler((e) -> e.printStackTrace());
+
+ while (!shutdown) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+ display.dispose();
+ display = null;
}
- display.dispose();
- display = null;
} catch (UnsatisfiedLinkError e) {
logger.log(Level.ERROR,
"Cannot load SWT, either because the SWT DLLs are no in the java.library.path,"
}
}
+ @Deprecated
public Display getDisplay() {
return display;
}
Import-Package: \
-!java.*,\
-org.apache.commons.io,\
-org.eclipse.core.commands,\
+org.eclipse.core.commands;resolution:=optional,\
!org.eclipse.core.runtime,\
!org.eclipse.ui.plugin,\
org.eclipse.swt,\
-javax.servlet.http;version="[3,5)",\
-javax.servlet;version="[3,5)",\
+javax.servlet.http;resolution:=optional,\
+javax.servlet;resolution:=optional,\
*
Export-Package: org.argeo.*,\
org.eclipse.rap.fileupload.*;version="3.10",\
org.eclipse.rap.rwt.*;version="3.10"
-# Was !org.eclipse.core.commands,\ why ?
+# Was !org.eclipse.core.commands, why ?
-#Bundle-Activator: org.argeo.eclipse.ui.ArgeoUiPlugin
+Bundle-Activator: org.argeo.internal.swt.specific.osgi.SwtSpecificRcpActivator
#Bundle-ActivationPolicy: lazy
#Ignore-Package: org.eclipse.core.commands
\ No newline at end of file
package org.argeo.eclipse.ui.rcp.internal.rwt;
import java.io.ByteArrayInputStream;
-import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
-import org.argeo.cms.util.StreamUtils;
import org.eclipse.rap.rwt.service.ResourceManager;
public class RcpResourceManager implements ResourceManager {
@Override
public void register(String name, InputStream in) {
- try {
- register.put(name, StreamUtils.toByteArray(in));
- } catch (IOException e) {
- throw new RuntimeException("Cannot register " + name, e);
- }
+ // FIXME implement it
+ throw new UnsupportedOperationException();
+// try {
+// register.put(name, StreamUtils.toByteArray(in));
+// } catch (IOException e) {
+// throw new RuntimeException("Cannot register " + name, e);
+// }
}
@Override
package org.argeo.eclipse.ui.specific;
-import org.eclipse.jface.viewers.ColumnViewer;
-import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
-import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.widgets.Widget;
/** Static utilities to bridge differences between RCP and RAP */
// does nothing
}
- /**
- * TootlTip support is supported for {@link ColumnViewer} in RCP
- *
- * @see ColumnViewerToolTipSupport#enableFor(Viewer)
- */
- public static void enableToolTipSupport(Viewer viewer) {
- if (viewer instanceof ColumnViewer)
- ColumnViewerToolTipSupport.enableFor((ColumnViewer) viewer);
- }
-
private EclipseUiSpecificUtils() {
}
}
--- /dev/null
+package org.argeo.internal.swt.specific.osgi;
+
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class SwtSpecificRcpActivator implements BundleActivator {
+ private static Display display;
+ private static Shell rootShell;
+ private static UiThread uiThread;
+
+ private static boolean debug = true;
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ if (display != null)
+ throw new IllegalStateException("SWT display already exists");
+ uiThread = new UiThread();
+ uiThread.start();
+ }
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ if (display == null)
+ return; // TODO log issue
+ display.asyncExec(() -> rootShell.dispose());
+ display.wake();
+ uiThread.join(60 * 1000);
+ uiThread = null;
+ display = null;
+ }
+
+ static class UiThread extends Thread {
+
+ @Override
+ public void run() {
+ boolean displayOwner = true;
+ Display d = Display.getDefault();
+ if (d.getThread() != UiThread.this) {
+ displayOwner = false;
+ // throw new IllegalStateException("There was already a default SWT display");
+ }
+
+ d.syncExec(() -> {
+ try {
+ rootShell = new Shell(d);
+ } catch (SWTError e) {
+ e.printStackTrace();
+ display.dispose();
+ return;
+ }
+
+ if (debug) {
+ rootShell.setLayout(new FillLayout());
+ new Label(rootShell, 0).setText("ROOT SHELL");
+ rootShell.pack();
+ rootShell.open();
+ }
+ });
+
+ display = d;
+
+ if (displayOwner) {
+ while (!rootShell.isDisposed())
+ if (!display.readAndDispatch())
+ display.sleep();
+ display.dispose();
+ }
+ }
+ }
+}