X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics%2Fsrc%2Forg%2Fsimantics%2FSimantics.java;h=cbe17e940d9436223aa6c2b62127872963a7b769;hb=ffc32a9e2dda6170269dd1149db275f8039981ff;hp=50110cb0375b51232cd78860b6a91ac5e96e0a28;hpb=9b79343ca481f448a4bcdeb3c2b35af91c8dfb62;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics/src/org/simantics/Simantics.java b/bundles/org.simantics/src/org/simantics/Simantics.java
index 50110cb03..cbe17e940 100644
--- a/bundles/org.simantics/src/org/simantics/Simantics.java
+++ b/bundles/org.simantics/src/org/simantics/Simantics.java
@@ -1,607 +1,651 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
- * in Industry THTH ry.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * VTT Technical Research Centre of Finland - initial API and implementation
- *******************************************************************************/
-package org.simantics;
-
-import java.io.File;
-import java.util.UUID;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.Platform;
-import org.simantics.SimanticsPlatform.OntologyRecoveryPolicy;
-import org.simantics.SimanticsPlatform.RecoveryPolicy;
-import org.simantics.application.arguments.IArguments;
-import org.simantics.application.arguments.SimanticsArguments;
-import org.simantics.db.ReadGraph;
-import org.simantics.db.Resource;
-import org.simantics.db.Session;
-import org.simantics.db.WriteGraph;
-import org.simantics.db.common.procedure.adapter.ProcedureAdapter;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.exception.RuntimeDatabaseException;
-import org.simantics.db.indexing.IndexUtils;
-import org.simantics.db.layer0.util.SimanticsClipboard;
-import org.simantics.db.layer0.util.SimanticsKeys;
-import org.simantics.db.layer0.variable.Variable;
-import org.simantics.db.layer0.variable.Variables;
-import org.simantics.db.management.ISessionContext;
-import org.simantics.db.management.ISessionContextProvider;
-import org.simantics.db.management.ISessionContextProviderSource;
-import org.simantics.db.management.SessionContextProvider;
-import org.simantics.db.management.SingleSessionContextProviderSource;
-import org.simantics.db.request.ReadInterface;
-import org.simantics.db.request.WriteInterface;
-import org.simantics.internal.FileServiceImpl;
-import org.simantics.layer0.Layer0;
-import org.simantics.project.IProject;
-import org.simantics.project.ProjectKeys;
-import org.simantics.scl.compiler.top.ValueNotFound;
-import org.simantics.scl.osgi.SCLOsgi;
-import org.simantics.scl.runtime.SCLContext;
-import org.simantics.scl.runtime.function.Function;
-import org.simantics.scl.runtime.function.Function1;
-import org.simantics.scl.runtime.function.Function2;
-import org.simantics.utils.FileService;
-import org.simantics.utils.FileUtils;
-import org.simantics.utils.TempFiles;
-import org.simantics.utils.threads.ThreadUtils;
-
-/**
- * A facade for accessing basic Simantics platform services. Usable without a
- * graphical UI, i.e. in headless contexts.
- *
- * TODO: in time, move headless functionality of SimanticsUI into this class but
- * originals as delegates in SimanticsUI.
- *
- * TODO: duplicate of org.simantics.db.layer0.util.Simantics, do something about this!!
- */
-public class Simantics {
-
- /**
- * Default database driver ID
- */
- private static final String DEFAULT_DATABASE_DRIVER_ID = "procore";
-
- private static String defaultDatabaseDriverId = DEFAULT_DATABASE_DRIVER_ID;
-
- private static ISessionContextProviderSource providerSource = null;
- private static volatile FileServiceImpl fileService = null;
-
- /**
- * Sets the database driver to be used by the platform. To have any effect,
- * this must be set before platform startup.
- *
- * @param id driver id
- */
- public static void setDefaultDatabaseDriver(String id) {
- defaultDatabaseDriverId = id;
- }
-
- /**
- * Returns currently set default database driver id.
- */
- public static String getDefaultDatabaseDriver() {
- return defaultDatabaseDriverId;
- }
-
- /**
- * @param args
- * @param progress
- * @return
- * @throws PlatformException
- */
- public static ISessionContext startUpHeadless(IArguments args, IProgressMonitor progress) throws PlatformException {
- if (SimanticsPlatform.INSTANCE.sessionContext != null) {
- throw new RuntimeDatabaseException("Simantics is already up and running.");
- }
-
- RecoveryPolicy workspacePolicy = Platform.inDevelopmentMode() ? RecoveryPolicy.FixError : RecoveryPolicy.ThrowError;
- OntologyRecoveryPolicy ontologyPolicy = Platform.inDevelopmentMode() ? OntologyRecoveryPolicy.Merge : OntologyRecoveryPolicy.ThrowError;
-
- if (args.contains(SimanticsArguments.RECOVERY_POLICY_FIX_ERRORS)) {
- workspacePolicy = RecoveryPolicy.FixError;
- ontologyPolicy = OntologyRecoveryPolicy.Merge;
- }
-
- if (args.contains(SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL)) {
- ontologyPolicy = OntologyRecoveryPolicy.ReinstallDatabase;
- }
-
- if (args.contains(SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL)) {
- ontologyPolicy = OntologyRecoveryPolicy.ReinstallDatabase;
- }
-
- int localPort = 0;
- if (args.contains(SimanticsArguments.LOCAL_SERVER_PORT)) {
- try {
- localPort = args.get(SimanticsArguments.LOCAL_SERVER_PORT);
- } catch (IllegalArgumentException e) {
- throw new PlatformException("Failed to open database session", e);
- }
- }
-
-// ServerAddress remoteDatabase = null;
-// if (args.contains(SimanticsArguments.SERVER)) {
-// String serverAddress = args.get(SimanticsArguments.SERVER);
-// try {
-// remoteDatabase = new ServerAddress(serverAddress);
-// } catch (IllegalArgumentException e) {
-// throw new PlatformException("Failed to open database session", e);
-// }
-// }
-
- return startUpHeadless(progress, workspacePolicy, ontologyPolicy, localPort /*, remoteDatabase*/);
- }
-
- /**
- * @param progress
- * @param workspacePolicy
- * @param ontologyPolicy
- * @param localPort
- * @param remoteDatabase
- * @return
- * @throws PlatformException
- */
- public static ISessionContext startUpHeadless(IProgressMonitor progress, RecoveryPolicy workspacePolicy, OntologyRecoveryPolicy ontologyPolicy, int localPort) throws PlatformException {
- if (SimanticsPlatform.INSTANCE.sessionContext != null) {
- throw new RuntimeDatabaseException("Simantics is already up and running.");
- }
-
- // Set session context provider.
- final ISessionContextProvider provider = new SessionContextProvider(null);
- ISessionContextProviderSource source = new SingleSessionContextProviderSource(provider);
- setSessionContextProviderSource(source);
- org.simantics.db.layer0.internal.SimanticsInternal.setSessionContextProviderSource(source);
-
- if (progress == null)
- progress = new NullProgressMonitor();
- return SimanticsPlatform.INSTANCE.startUp(defaultDatabaseDriverId, progress, workspacePolicy, ontologyPolicy, true, new ConsoleUserAgent());
- }
-
- /**
- * @param progress
- * @throws PlatformException
- */
- public static void shutdown(IProgressMonitor progress) throws PlatformException {
- SimanticsPlatform.INSTANCE.shutdown(progress);
- }
-
- /**
- * Queue execution of a runnable.
- *
- * @param runnable
- */
- public static void async(Runnable runnable) {
- ThreadUtils.getBlockingWorkExecutor().execute(runnable);
- }
-
- public static void async(Runnable runnable, int delay, TimeUnit unit) {
- ThreadUtils.getTimer().schedule(runnable, delay, unit);
- }
-
- public static ScheduledFuture> scheduleAtFixedRate(Runnable runnable, int initialDelay, int period, TimeUnit unit) {
- return ThreadUtils.getTimer().scheduleAtFixedRate(runnable, initialDelay, period, unit);
- }
-
- /**
- * Queue execution of a non-blocking runnable. Use this method with caution.
- * A non-blocking runnable nevers locks anything, No Locks, No semaphores,
- * No Object.wait(), No synchronized() {} blocks.
- *
- * @param runnable a non-blocking runnable
- */
- public static void asyncNonblocking(Runnable runnable) {
- ThreadUtils.getNonBlockingWorkExecutor().execute(runnable);
- }
-
- /**
- * Schedule execution of a non-blocking runnable. Use this method with caution.
- * A non-blocking runnable never locks anything, No Locks, No semaphores,
- * No Object,wait(), No synchronized() {} blocks.
- *
- * @param runnable a non-blocking runnable
- * @param initialDelay
- * @param period
- */
- public static void asyncNonblocking(Runnable runnable, int initialDelay, int period) {
- ThreadUtils.getNonBlockingWorkExecutor().scheduleAtFixedRate(runnable, initialDelay, period, TimeUnit.MILLISECONDS);
- }
-
- public static synchronized ISessionContext setSessionContext(ISessionContext ctx) {
- return getSessionContextProvider().setSessionContext(ctx);
- }
-
- public static void setSessionContextProviderSource(ISessionContextProviderSource source) {
- if (source == null)
- throw new IllegalArgumentException("null provider source");
- providerSource = source;
- }
-
- public static ISessionContextProviderSource getProviderSource() {
- if (providerSource == null)
- throw new IllegalStateException(
- "providerSource must be initialized by the application before using class Simantics");
- return providerSource;
- }
-
- public static ISessionContextProvider getSessionContextProvider() {
- return getProviderSource().getActive();
- }
-
- /**
- * Returns the database session context associated with the currently active
- * context. This method should be used to retrieve session contexts only
- * when the client is sure that the correct context is active.
- *
- * @return the session context associated with the currently active context
- * or null
if the context has no session context
- */
- public static ISessionContext getSessionContext() {
- ISessionContextProvider provider = getSessionContextProvider();
- return provider != null ? provider.getSessionContext() : null;
- }
-
- /**
- * Returns the database Session bound to the currently active context.
- *
- *
- * The method always returns a non-null Session or produces an
- * IllegalStateException if a Session was not attainable.
- *
- *
- * @return the Session bound to the currently active workbench window
- * @throws IllegalStateException if no Session was available
- */
- public static Session getSession() {
- ISessionContext ctx = getSessionContext();
- if (ctx == null)
- throw new IllegalStateException("Session unavailable, no database session open");
- return ctx.getSession();
- }
-
- /**
- * Returns the database Session bound to the currently active context.
- * Differently from {@link #getSession()}, this method returns
- * null
if there is no current Session available.
- *
- * @see #getSession()
- * @return the Session bound to the currently active context or
- * null
- */
- public static Session peekSession() {
- ISessionContext ctx = getSessionContext();
- return ctx == null ? null : ctx.peekSession();
- }
-
- /**
- * @return the currently open and active project as a Resource
- * @throws IllegalStateException if there is no currently active database
- * session, which also means there is no active project at the
- * moment
- */
- public static Resource getProjectResource() {
- ISessionContext ctx = getSessionContext();
- if (ctx == null)
- throw new IllegalStateException("No current database session");
- Resource project = ctx.getHint(SimanticsKeys.KEY_PROJECT);
- if (project == null)
- throw new IllegalStateException("No current project resource in session context " + ctx);
- return project;
- }
-
- /**
- * @return the currently open and active project as a {@link Resource}
- */
- public static Resource peekProjectResource() {
- ISessionContext ctx = getSessionContext();
- return ctx != null ? ctx.getHint(SimanticsKeys.KEY_PROJECT) : null;
- }
-
- /**
- * @return the currently open and active project as an {@link IProject}
- * @throws IllegalStateException if there is no currently active database
- * session, which also means there is no active project at the
- * moment
- */
- public static IProject getProject() {
- ISessionContext ctx = getSessionContext();
- if (ctx == null)
- throw new IllegalStateException("No current database session");
- IProject project = ctx.getHint(ProjectKeys.KEY_PROJECT);
- if (project == null)
- throw new IllegalStateException("No current project in session context " + ctx);
- return project;
- }
-
- /**
- * @return the currently open and active project as an {@link IProject} or
- * null
if there is no active session or project
- */
- public static IProject peekProject() {
- ISessionContext ctx = getSessionContext();
- return ctx == null ? null : ctx.getHint(ProjectKeys.KEY_PROJECT);
- }
-
- // FIXME: once org.simantics.db.layer0.util.Simantics is gone, re-enable this
-// private static SimanticsClipboard clipboard = SimanticsClipboard.EMPTY;
-
- /**
- * @param content
- */
- public static void setClipboard(SimanticsClipboard content) {
- // FIXME: once org.simantics.db.layer0.util.Simantics is gone, re-enable this
-// if (content == null)
-// throw new NullPointerException("null clipboard content");
-// clipboard = content;
- org.simantics.db.layer0.internal.SimanticsInternal.setClipboard(content);
- }
-
- public static SimanticsClipboard getClipboard() {
- // FIXME: once org.simantics.db.layer0.util.Simantics is gone, re-enable this
- //return clipboard;
- return org.simantics.db.layer0.internal.SimanticsInternal.getClipboard();
- }
-
- public static Layer0 getLayer0() throws DatabaseException {
- return Layer0.getInstance(getSession());
- }
-
- public static T sync(ReadInterface r) throws DatabaseException {
- return getSession().sync(r);
- }
-
- public static T sync(WriteInterface r) throws DatabaseException {
- return getSession().sync(r);
- }
-
- public static void async(ReadInterface r) {
- getSession().async(r, new ProcedureAdapter());
- }
-
- public static void async(WriteInterface r) {
- getSession().async(r);
- }
-
- public static void clearTemporaryDirectory() {
- FileUtils.deleteDir(getTemporaryDirectory());
- }
-
- public static File getTempfile(String directory, String suffix) {
- File dir = getTemporaryDirectory(directory);
- return new File(dir, UUID.randomUUID().toString() + "." + suffix);
- }
-
- public static File getTemporaryDirectory(String directory) {
- File sub = new File(getTemporaryDirectory(), directory);
- sub.mkdirs();
- return sub;
- }
-
- public static File getTemporaryDirectory() {
- File workspace = Platform.getLocation().toFile();
- File temp = new File(workspace, "tempFiles");
- temp.mkdirs();
- return temp;
- }
-
- public static TempFiles getTempFiles() {
- return TEMP_FILES;
- }
-
- private static class TempFilesImpl implements TempFiles {
- private final TempFilesImpl parent;
- private final String prefix;
- private final String fullPrefix;
-
- private TempFilesImpl(TempFilesImpl parent, String directory) {
- this.parent = parent;
- this.prefix = directory;
- this.fullPrefix = getPrefix(new StringBuilder()).toString();
- }
-
- private StringBuilder getPrefix(StringBuilder sb) {
- if (parent != null)
- parent.getPrefix(sb);
- if (prefix != null && !prefix.isEmpty())
- sb.append(prefix).append(File.separatorChar);
- return sb;
- }
-
- @Override
- public File getRoot() {
- return Simantics.getTemporaryDirectory(fullPrefix);
- }
-
- @Override
- public File getTempfile(String directory, String suffix) {
- return Simantics.getTempfile(fullPrefix.isEmpty() ? directory : fullPrefix + directory, suffix);
- }
-
- @Override
- public TempFiles subdirectory(String directory) {
- return new TempFilesImpl(this, directory);
- }
- }
-
- public static TempFiles TEMP_FILES = new TempFilesImpl(null, null);
-
- public static void flushIndexCaches(IProgressMonitor progress, Session session) {
- try {
- IndexUtils.flushIndexCaches(progress, session);
- } catch (Exception e) {
- Logger.defaultLogError(e);
- }
- }
-
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static T applySCL(String module, String function, ReadGraph graph, Object ... args) throws DatabaseException {
- SCLContext sclContext = SCLContext.getCurrent();
- Object oldGraph = sclContext.put("graph", graph);
- try {
- T t = (T)((Function)SCLOsgi.MODULE_REPOSITORY.getValue(module, function)).applyArray(args);
- return t;
- } catch (ValueNotFound e) {
- throw new DatabaseException("SCL Value not found: " + e.name);
- } catch (Throwable t) {
- throw new DatabaseException(t);
- } finally {
- sclContext.put("graph", oldGraph);
- }
-
- }
-
- @SuppressWarnings("unchecked")
- public static T applySCLWrite(WriteGraph graph, @SuppressWarnings("rawtypes") Function f, Object ... args) throws DatabaseException {
- SCLContext sclContext = SCLContext.getCurrent();
- Object oldGraph = sclContext.put("graph", graph);
- try {
- return (T)f.applyArray(args);
- } catch (Throwable t) {
- throw new DatabaseException(t);
- } finally {
- sclContext.put("graph", oldGraph);
- }
- }
-
- @SuppressWarnings("unchecked")
- public static T applySCLRead(ReadGraph graph, @SuppressWarnings("rawtypes") Function f, Object ... args) throws DatabaseException {
- SCLContext sclContext = SCLContext.getCurrent();
- Object oldGraph = sclContext.put("graph", graph);
- try {
- return (T)f.applyArray(args);
- } catch (Throwable t) {
- throw new DatabaseException(t);
- } finally {
- sclContext.put("graph", oldGraph);
- }
- }
-
- public static R applySCLWrite(WriteGraph graph, Function1 function, P0 p0) throws DatabaseException {
- SCLContext sclContext = SCLContext.getCurrent();
- Object oldGraph = sclContext.put("graph", graph);
- try {
- return function.apply(p0);
- } catch (Throwable t) {
- throw new DatabaseException(t);
- } finally {
- sclContext.put("graph", oldGraph);
- }
- }
-
- public static R applySCLRead(ReadGraph graph, Function1 function, P0 p0) throws DatabaseException {
- SCLContext sclContext = SCLContext.getCurrent();
- Object oldGraph = sclContext.put("graph", graph);
- try {
- return function.apply(p0);
- } catch (Throwable t) {
- throw new DatabaseException(t);
- } finally {
- sclContext.put("graph", oldGraph);
- }
- }
-
- public static R applySCLRead(ReadGraph graph, Function2 function, P0 p0, P1 p1) throws DatabaseException {
- SCLContext sclContext = SCLContext.getCurrent();
- Object oldGraph = sclContext.put("graph", graph);
- try {
- return function.apply(p0, p1);
- } catch (Throwable t) {
- throw new DatabaseException(t);
- } finally {
- sclContext.put("graph", oldGraph);
- }
- }
-
- public static R invokeSCLWrite(WriteGraph graph, Variable property, P0 p0) throws DatabaseException {
- Function1 fn = property.getPossibleValue(graph);
- if(fn == null) throw new DatabaseException("No function for " + property.getURI(graph));
- return Simantics.applySCLWrite(graph, fn, p0);
- }
-
- public static R invokeSCL(ReadGraph graph, Variable property, P0 p0) throws DatabaseException {
- Function1 fn = property.getPossibleValue(graph);
- if(fn == null) throw new DatabaseException("No function for " + property.getURI(graph));
- return Simantics.applySCLRead(graph, fn, p0);
- }
-
- public static R invokeSCL(ReadGraph graph, Variable property, P0 p0, P1 p1) throws DatabaseException {
- Function2 fn = property.getPossibleValue(graph);
- if(fn == null) throw new DatabaseException("No function for " + property.getURI(graph));
- return Simantics.applySCLRead(graph, fn, p0, p1);
- }
-
- public static R invokeSCLWrite(WriteGraph graph, Resource entity, Resource property, P0 p0) throws DatabaseException {
- return invokeSCLWrite(graph, getProperty(graph, entity, property), p0);
- }
-
- public static R invokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0) throws DatabaseException {
- return invokeSCL(graph, getProperty(graph, entity, property), p0);
- }
-
- public static R invokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0, P1 p1) throws DatabaseException {
- return invokeSCL(graph, getProperty(graph, entity, property), p0, p1);
- }
-
- public static R tryInvokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0) throws DatabaseException {
- Variable p = Variables.tryGetProperty(graph, entity, property);
- if (p == null)
- return null;
- return invokeSCL(graph, p, p0);
- }
-
- public static R tryInvokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0, P1 p1) throws DatabaseException {
- Variable p = Variables.tryGetProperty(graph, entity, property);
- if (p == null)
- return null;
- return invokeSCL(graph, p, p0, p1);
- }
-
- private static Variable getProperty(ReadGraph graph, Resource entity, Resource property) throws DatabaseException {
- return Variables.getVariable(graph, entity).getProperty(graph, property);
- }
-
- public static boolean ensureMemoryBytes(long bytes) {
-
- Runtime runtime = Runtime.getRuntime();
- long consumedMemory = runtime.totalMemory() - runtime.freeMemory();
- long available = runtime.maxMemory() - consumedMemory;
-
- return available > bytes;
-
- }
-
- public static long getDiskBytes() {
-
- File ws = new File(Platform.getInstanceLocation().getURL().getFile());
- return ws.getUsableSpace();
-
- }
-
- /**
- * @return a service for dealing with recurring file system handling cases
- */
- public static FileService getFileService() {
- FileService fs = fileService;
- if (fs == null) {
- synchronized (Simantics.class) {
- fs = fileService;
- if (fs == null)
- fs = fileService = new FileServiceImpl();
- }
- }
- return fs;
- }
-
-}
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics;
+
+import java.io.File;
+import java.util.UUID;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.simantics.SimanticsPlatform.OntologyRecoveryPolicy;
+import org.simantics.SimanticsPlatform.RecoveryPolicy;
+import org.simantics.application.arguments.IArguments;
+import org.simantics.application.arguments.SimanticsArguments;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.RequestProcessor;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.Indexing;
+import org.simantics.db.common.procedure.adapter.ProcedureAdapter;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.RuntimeDatabaseException;
+import org.simantics.db.indexing.IndexUtils;
+import org.simantics.db.layer0.util.SimanticsClipboard;
+import org.simantics.db.layer0.util.SimanticsKeys;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.layer0.variable.Variables;
+import org.simantics.db.management.ISessionContext;
+import org.simantics.db.management.ISessionContextProvider;
+import org.simantics.db.management.ISessionContextProviderSource;
+import org.simantics.db.management.SessionContextProvider;
+import org.simantics.db.management.SingleSessionContextProviderSource;
+import org.simantics.db.request.ReadInterface;
+import org.simantics.db.request.WriteInterface;
+import org.simantics.internal.FileServiceImpl;
+import org.simantics.layer0.Layer0;
+import org.simantics.project.IProject;
+import org.simantics.project.ProjectKeys;
+import org.simantics.scl.compiler.top.ValueNotFound;
+import org.simantics.scl.osgi.SCLOsgi;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.scl.runtime.function.Function2;
+import org.simantics.utils.FileService;
+import org.simantics.utils.FileUtils;
+import org.simantics.utils.TempFiles;
+import org.simantics.utils.threads.ThreadUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A facade for accessing basic Simantics platform services. Usable without a
+ * graphical UI, i.e. in headless contexts.
+ *
+ * TODO: in time, move headless functionality of SimanticsUI into this class but
+ * originals as delegates in SimanticsUI.
+ *
+ * TODO: duplicate of org.simantics.db.layer0.util.Simantics, do something about this!!
+ */
+public class Simantics {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Simantics.class);
+
+ /**
+ * Default database driver ID
+ */
+ private static final String DEFAULT_DATABASE_DRIVER_ID = "acorn";
+
+ private static String defaultDatabaseDriverId = DEFAULT_DATABASE_DRIVER_ID;
+
+ private static ISessionContextProviderSource providerSource = null;
+ private static volatile FileServiceImpl fileService = null;
+
+ /**
+ * Sets the database driver to be used by the platform. To have any effect,
+ * this must be set before platform startup.
+ *
+ * @param id driver id
+ */
+ public static void setDefaultDatabaseDriver(String id) {
+ defaultDatabaseDriverId = id;
+ }
+
+ /**
+ * Returns currently set default database driver id.
+ */
+ public static String getDefaultDatabaseDriver() {
+ return defaultDatabaseDriverId;
+ }
+
+ /**
+ * @param args
+ * @param progress
+ * @return
+ * @throws PlatformException
+ */
+ public static ISessionContext startUpHeadless(IArguments args, IProgressMonitor progress) throws PlatformException {
+ if (SimanticsPlatform.INSTANCE.sessionContext != null) {
+ throw new RuntimeDatabaseException("Simantics is already up and running.");
+ }
+
+ RecoveryPolicy workspacePolicy = Platform.inDevelopmentMode() ? RecoveryPolicy.FixError : RecoveryPolicy.ThrowError;
+ OntologyRecoveryPolicy ontologyPolicy = Platform.inDevelopmentMode() ? OntologyRecoveryPolicy.Merge : OntologyRecoveryPolicy.ThrowError;
+
+ if (args.contains(SimanticsArguments.RECOVERY_POLICY_FIX_ERRORS)) {
+ workspacePolicy = RecoveryPolicy.FixError;
+ ontologyPolicy = OntologyRecoveryPolicy.Merge;
+ }
+
+ if (args.contains(SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL)) {
+ ontologyPolicy = OntologyRecoveryPolicy.ReinstallDatabase;
+ }
+
+ if (args.contains(SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL)) {
+ ontologyPolicy = OntologyRecoveryPolicy.ReinstallDatabase;
+ }
+
+ if (args.contains(SimanticsArguments.DISABLE_INDEX)) {
+ Indexing.setDefaultDependenciesIndexingEnabled(false);
+ }
+
+ String databaseDriverId = defaultDatabaseDriverId;
+ if (args.contains(SimanticsArguments.DATABASE_ID)) {
+ databaseDriverId = args.get(SimanticsArguments.DATABASE_ID);
+ Simantics.setDefaultDatabaseDriver(databaseDriverId);
+ }
+
+ int localPort = 0;
+ if (args.contains(SimanticsArguments.LOCAL_SERVER_PORT)) {
+ try {
+ localPort = args.get(SimanticsArguments.LOCAL_SERVER_PORT);
+ } catch (IllegalArgumentException e) {
+ throw new PlatformException("Failed to open database session", e);
+ }
+ }
+
+// ServerAddress remoteDatabase = null;
+// if (args.contains(SimanticsArguments.SERVER)) {
+// String serverAddress = args.get(SimanticsArguments.SERVER);
+// try {
+// remoteDatabase = new ServerAddress(serverAddress);
+// } catch (IllegalArgumentException e) {
+// throw new PlatformException("Failed to open database session", e);
+// }
+// }
+
+ return startUpHeadless(progress, workspacePolicy, ontologyPolicy, localPort, databaseDriverId /*, remoteDatabase*/);
+ }
+
+ /**
+ * @param progress
+ * @param workspacePolicy
+ * @param ontologyPolicy
+ * @param localPort
+ * @param remoteDatabase
+ * @return
+ * @throws PlatformException
+ */
+ public static ISessionContext startUpHeadless(IProgressMonitor progress, RecoveryPolicy workspacePolicy, OntologyRecoveryPolicy ontologyPolicy, int localPort, String databaseDriverId) throws PlatformException {
+ if (SimanticsPlatform.INSTANCE.sessionContext != null) {
+ throw new RuntimeDatabaseException("Simantics is already up and running.");
+ }
+
+ // Set session context provider.
+ final ISessionContextProvider provider = new SessionContextProvider(null);
+ ISessionContextProviderSource source = new SingleSessionContextProviderSource(provider);
+ setSessionContextProviderSource(source);
+ org.simantics.db.layer0.internal.SimanticsInternal.setSessionContextProviderSource(source);
+
+ if (progress == null)
+ progress = new NullProgressMonitor();
+ return SimanticsPlatform.INSTANCE.startUp(databaseDriverId, progress, workspacePolicy, ontologyPolicy, true, new ConsoleUserAgent());
+ }
+
+ /**
+ * @param progress
+ * @throws PlatformException
+ */
+ public static void shutdown(IProgressMonitor progress) throws PlatformException {
+ SimanticsPlatform.INSTANCE.shutdown(progress);
+ }
+
+ /**
+ * Queue execution of a runnable.
+ *
+ * @param runnable
+ */
+ public static void async(Runnable runnable) {
+ ThreadUtils.getBlockingWorkExecutor().execute(runnable);
+ }
+
+ public static void async(Runnable runnable, int delay, TimeUnit unit) {
+ ThreadUtils.getTimer().schedule(runnable, delay, unit);
+ }
+
+ public static ScheduledFuture> scheduleAtFixedRate(Runnable runnable, int initialDelay, int period, TimeUnit unit) {
+ return ThreadUtils.getTimer().scheduleAtFixedRate(runnable, initialDelay, period, unit);
+ }
+
+ /**
+ * Queue execution of a non-blocking runnable. Use this method with caution.
+ * A non-blocking runnable nevers locks anything, No Locks, No semaphores,
+ * No Object.wait(), No synchronized() {} blocks.
+ *
+ * @param runnable a non-blocking runnable
+ */
+ public static void asyncNonblocking(Runnable runnable) {
+ ThreadUtils.getNonBlockingWorkExecutor().execute(runnable);
+ }
+
+ /**
+ * Schedule execution of a non-blocking runnable. Use this method with caution.
+ * A non-blocking runnable never locks anything, No Locks, No semaphores,
+ * No Object,wait(), No synchronized() {} blocks.
+ *
+ * @param runnable a non-blocking runnable
+ * @param initialDelay
+ * @param period
+ */
+ public static void asyncNonblocking(Runnable runnable, int initialDelay, int period) {
+ ThreadUtils.getNonBlockingWorkExecutor().scheduleAtFixedRate(runnable, initialDelay, period, TimeUnit.MILLISECONDS);
+ }
+
+ public static synchronized ISessionContext setSessionContext(ISessionContext ctx) {
+ return getSessionContextProvider().setSessionContext(ctx);
+ }
+
+ public static void setSessionContextProviderSource(ISessionContextProviderSource source) {
+ if (source == null)
+ throw new IllegalArgumentException("null provider source");
+ providerSource = source;
+ }
+
+ public static ISessionContextProviderSource getProviderSource() {
+ if (providerSource == null)
+ throw new IllegalStateException(
+ "providerSource must be initialized by the application before using class Simantics");
+ return providerSource;
+ }
+
+ public static ISessionContextProvider getSessionContextProvider() {
+ return getProviderSource().getActive();
+ }
+
+ /**
+ * Returns the database session context associated with the currently active
+ * context. This method should be used to retrieve session contexts only
+ * when the client is sure that the correct context is active.
+ *
+ * @return the session context associated with the currently active context
+ * or null
if the context has no session context
+ */
+ public static ISessionContext getSessionContext() {
+ ISessionContextProvider provider = getSessionContextProvider();
+ return provider != null ? provider.getSessionContext() : null;
+ }
+
+ /**
+ * Returns the database Session bound to the currently active context.
+ *
+ *
+ * The method always returns a non-null Session or produces an
+ * IllegalStateException if a Session was not attainable.
+ *
+ *
+ * @return the Session bound to the currently active workbench window
+ * @throws IllegalStateException if no Session was available
+ */
+ public static Session getSession() {
+ ISessionContext ctx = getSessionContext();
+ if (ctx == null)
+ throw new IllegalStateException("Session unavailable, no database session open");
+ return ctx.getSession();
+ }
+
+ public static RequestProcessor getAvailableRequestProcessor() {
+ Object graph = SCLContext.getCurrent().get("graph");
+ if(graph instanceof ReadGraph)
+ return (RequestProcessor)graph;
+ else
+ return Simantics.getSession();
+ }
+
+ /**
+ * Returns the database Session bound to the currently active context.
+ * Differently from {@link #getSession()}, this method returns
+ * null
if there is no current Session available.
+ *
+ * @see #getSession()
+ * @return the Session bound to the currently active context or
+ * null
+ */
+ public static Session peekSession() {
+ ISessionContext ctx = getSessionContext();
+ return ctx == null ? null : ctx.peekSession();
+ }
+
+ /**
+ * @return the currently open and active project as a Resource
+ * @throws IllegalStateException if there is no currently active database
+ * session, which also means there is no active project at the
+ * moment
+ */
+ public static Resource getProjectResource() {
+ ISessionContext ctx = getSessionContext();
+ if (ctx == null)
+ throw new IllegalStateException("No current database session");
+ Resource project = ctx.getHint(SimanticsKeys.KEY_PROJECT);
+ if (project == null)
+ throw new IllegalStateException("No current project resource in session context " + ctx);
+ return project;
+ }
+
+ /**
+ * @return the currently open and active project as a {@link Resource}
+ */
+ public static Resource peekProjectResource() {
+ ISessionContext ctx = getSessionContext();
+ return ctx != null ? ctx.getHint(SimanticsKeys.KEY_PROJECT) : null;
+ }
+
+ /**
+ * @return the currently open and active project as an {@link IProject}
+ * @throws IllegalStateException if there is no currently active database
+ * session, which also means there is no active project at the
+ * moment
+ */
+ public static IProject getProject() {
+ ISessionContext ctx = getSessionContext();
+ if (ctx == null)
+ throw new IllegalStateException("No current database session");
+ IProject project = ctx.getHint(ProjectKeys.KEY_PROJECT);
+ if (project == null)
+ throw new IllegalStateException("No current project in session context " + ctx);
+ return project;
+ }
+
+ /**
+ * @return the currently open and active project as an {@link IProject} or
+ * null
if there is no active session or project
+ */
+ public static IProject peekProject() {
+ ISessionContext ctx = getSessionContext();
+ return ctx == null ? null : ctx.getHint(ProjectKeys.KEY_PROJECT);
+ }
+
+ // FIXME: once org.simantics.db.layer0.util.Simantics is gone, re-enable this
+// private static SimanticsClipboard clipboard = SimanticsClipboard.EMPTY;
+
+ /**
+ * @param content
+ */
+ public static void setClipboard(SimanticsClipboard content) {
+ // FIXME: once org.simantics.db.layer0.util.Simantics is gone, re-enable this
+// if (content == null)
+// throw new NullPointerException("null clipboard content");
+// clipboard = content;
+ org.simantics.db.layer0.internal.SimanticsInternal.setClipboard(content);
+ }
+
+ public static SimanticsClipboard getClipboard() {
+ // FIXME: once org.simantics.db.layer0.util.Simantics is gone, re-enable this
+ //return clipboard;
+ return org.simantics.db.layer0.internal.SimanticsInternal.getClipboard();
+ }
+
+ public static Layer0 getLayer0() throws DatabaseException {
+ return Layer0.getInstance(getSession());
+ }
+
+ public static T sync(ReadInterface r) throws DatabaseException {
+ return getSession().sync(r);
+ }
+
+ public static T sync(WriteInterface r) throws DatabaseException {
+ return getSession().sync(r);
+ }
+
+ public static void async(ReadInterface r) {
+ getSession().async(r, new ProcedureAdapter());
+ }
+
+ public static void async(WriteInterface r) {
+ getSession().async(r);
+ }
+
+ public static void clearTemporaryDirectory() {
+ FileUtils.deleteDir(getTemporaryDirectory());
+ }
+
+ public static File getTempfile(String directory, String suffix) {
+ File dir = getTemporaryDirectory(directory);
+ return new File(dir, UUID.randomUUID().toString() + "." + suffix);
+ }
+
+ public static File getTemporaryDirectory(String directory) {
+ File sub = new File(getTemporaryDirectory(), directory);
+ sub.mkdirs();
+ return sub;
+ }
+
+ public static File getTemporaryDirectory() {
+ File workspace = Platform.getLocation().toFile();
+ File temp = new File(workspace, "tempFiles");
+ temp.mkdirs();
+ return temp;
+ }
+
+ public static TempFiles getTempFiles() {
+ return TEMP_FILES;
+ }
+
+ private static class TempFilesImpl implements TempFiles {
+ private final TempFilesImpl parent;
+ private final String prefix;
+ private final String fullPrefix;
+
+ private TempFilesImpl(TempFilesImpl parent, String directory) {
+ this.parent = parent;
+ this.prefix = directory;
+ this.fullPrefix = getPrefix(new StringBuilder()).toString();
+ }
+
+ private StringBuilder getPrefix(StringBuilder sb) {
+ if (parent != null)
+ parent.getPrefix(sb);
+ if (prefix != null && !prefix.isEmpty())
+ sb.append(prefix).append(File.separatorChar);
+ return sb;
+ }
+
+ @Override
+ public File getRoot() {
+ return Simantics.getTemporaryDirectory(fullPrefix);
+ }
+
+ @Override
+ public File getTempfile(String directory, String suffix) {
+ return Simantics.getTempfile(fullPrefix.isEmpty() ? directory : fullPrefix + directory, suffix);
+ }
+
+ @Override
+ public TempFiles subdirectory(String directory) {
+ return new TempFilesImpl(this, directory);
+ }
+ }
+
+ public static TempFiles TEMP_FILES = new TempFilesImpl(null, null);
+
+ public static void flushIndexCaches(IProgressMonitor progress, Session session) {
+ try {
+ IndexUtils.flushIndexCaches(progress, session);
+ } catch (Exception e) {
+ LOGGER.error("Flushing index caches failed.", e);
+ }
+ }
+
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static T applySCL(String module, String function, Object ... args) throws DatabaseException {
+ try {
+ T t = (T)((Function)SCLOsgi.MODULE_REPOSITORY.getValue(module, function)).applyArray(args);
+ return t;
+ } catch (ValueNotFound e) {
+ throw new DatabaseException("SCL Value not found: " + e.name);
+ } catch (Throwable t) {
+ if (t instanceof DatabaseException)
+ throw (DatabaseException) t;
+ throw new DatabaseException(t);
+ }
+ }
+
+ public static T applySCL(String module, String function, ReadGraph graph, Object ... args) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ try {
+ return applySCL(module, function, args);
+ } catch (DatabaseException dbe) {
+ throw dbe;
+ } catch (Throwable t) {
+ throw new DatabaseException(t);
+ } finally {
+ sclContext.put("graph", oldGraph);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static T applySCLWrite(WriteGraph graph, @SuppressWarnings("rawtypes") Function f, Object ... args) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ try {
+ return (T)f.applyArray(args);
+ } catch (Throwable t) {
+ if (t instanceof DatabaseException)
+ throw (DatabaseException) t;
+ throw new DatabaseException(t);
+ } finally {
+ sclContext.put("graph", oldGraph);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static T applySCLRead(ReadGraph graph, @SuppressWarnings("rawtypes") Function f, Object ... args) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ try {
+ return (T)f.applyArray(args);
+ } catch (Throwable t) {
+ if (t instanceof DatabaseException)
+ throw (DatabaseException) t;
+ throw new DatabaseException(t);
+ } finally {
+ sclContext.put("graph", oldGraph);
+ }
+ }
+
+ public static R applySCLWrite(WriteGraph graph, Function1 function, P0 p0) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ try {
+ return function.apply(p0);
+ } catch (Throwable t) {
+ if (t instanceof DatabaseException)
+ throw (DatabaseException) t;
+ throw new DatabaseException(t);
+ } finally {
+ sclContext.put("graph", oldGraph);
+ }
+ }
+
+ public static R applySCLRead(ReadGraph graph, Function1 function, P0 p0) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ try {
+ return function.apply(p0);
+ } catch (Throwable t) {
+ if (t instanceof DatabaseException)
+ throw (DatabaseException) t;
+ throw new DatabaseException(t);
+ } finally {
+ sclContext.put("graph", oldGraph);
+ }
+ }
+
+ public static R applySCLRead(ReadGraph graph, Function2 function, P0 p0, P1 p1) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ try {
+ return function.apply(p0, p1);
+ } catch (Throwable t) {
+ if (t instanceof DatabaseException)
+ throw (DatabaseException) t;
+ throw new DatabaseException(t);
+ } finally {
+ sclContext.put("graph", oldGraph);
+ }
+ }
+
+ public static R invokeSCLWrite(WriteGraph graph, Variable property, P0 p0) throws DatabaseException {
+ Function1 fn = property.getPossibleValue(graph);
+ if(fn == null) throw new DatabaseException("No function for " + property.getURI(graph));
+ return Simantics.applySCLWrite(graph, fn, p0);
+ }
+
+ public static R invokeSCL(ReadGraph graph, Variable property, P0 p0) throws DatabaseException {
+ Function1 fn = property.getPossibleValue(graph);
+ if(fn == null) throw new DatabaseException("No function for " + property.getURI(graph));
+ return Simantics.applySCLRead(graph, fn, p0);
+ }
+
+ public static R invokeSCL(ReadGraph graph, Variable property, P0 p0, P1 p1) throws DatabaseException {
+ Function2 fn = property.getPossibleValue(graph);
+ if(fn == null) throw new DatabaseException("No function for " + property.getURI(graph));
+ return Simantics.applySCLRead(graph, fn, p0, p1);
+ }
+
+ public static R invokeSCLWrite(WriteGraph graph, Resource entity, Resource property, P0 p0) throws DatabaseException {
+ return invokeSCLWrite(graph, getProperty(graph, entity, property), p0);
+ }
+
+ public static R invokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0) throws DatabaseException {
+ return invokeSCL(graph, getProperty(graph, entity, property), p0);
+ }
+
+ public static R invokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0, P1 p1) throws DatabaseException {
+ return invokeSCL(graph, getProperty(graph, entity, property), p0, p1);
+ }
+
+ public static R tryInvokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0) throws DatabaseException {
+ Variable p = Variables.tryGetProperty(graph, entity, property);
+ if (p == null)
+ return null;
+ return invokeSCL(graph, p, p0);
+ }
+
+ public static R tryInvokeSCL(ReadGraph graph, Resource entity, Resource property, P0 p0, P1 p1) throws DatabaseException {
+ Variable p = Variables.tryGetProperty(graph, entity, property);
+ if (p == null)
+ return null;
+ return invokeSCL(graph, p, p0, p1);
+ }
+
+ private static Variable getProperty(ReadGraph graph, Resource entity, Resource property) throws DatabaseException {
+ return Variables.getVariable(graph, entity).getProperty(graph, property);
+ }
+
+ public static boolean ensureMemoryBytes(long bytes) {
+
+ Runtime runtime = Runtime.getRuntime();
+ long consumedMemory = runtime.totalMemory() - runtime.freeMemory();
+ long available = runtime.maxMemory() - consumedMemory;
+
+ return available > bytes;
+
+ }
+
+ public static long getDiskBytes() {
+
+ File ws = new File(Platform.getInstanceLocation().getURL().getFile());
+ return ws.getUsableSpace();
+
+ }
+
+ /**
+ * @return a service for dealing with recurring file system handling cases
+ */
+ public static FileService getFileService() {
+ FileService fs = fileService;
+ if (fs == null) {
+ synchronized (Simantics.class) {
+ fs = fileService;
+ if (fs == null)
+ fs = fileService = new FileServiceImpl();
+ }
+ }
+ return fs;
+ }
+
+}