X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics%2Fsrc%2Forg%2Fsimantics%2FSimantics.java;h=35808bd929fa74d63f18f860bdc51680abeababf;hp=daa9e7e10afd49e250767e29822d8f749eb166cd;hb=e460fd6f0af60314e2ca28391ef7ff2043016d97;hpb=0144ba232323a0e4f7ec8fe0681a150faafd7caf diff --git a/bundles/org.simantics/src/org/simantics/Simantics.java b/bundles/org.simantics/src/org/simantics/Simantics.java index daa9e7e10..35808bd92 100644 --- a/bundles/org.simantics/src/org/simantics/Simantics.java +++ b/bundles/org.simantics/src/org/simantics/Simantics.java @@ -1,610 +1,660 @@ -/******************************************************************************* - * 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; -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 = "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.error("Flushing index caches failed.", 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.db.service.XSupport; +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); + } + } + + public static void saveQueries(Session session) { + try { + XSupport xs = session.getService(XSupport.class); + xs.saveQueries(); + } catch (Exception e) { + LOGGER.error("Saving database queries 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; + } + +}