/******************************************************************************* * 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 static org.simantics.db.common.utils.Transaction.commit; import static org.simantics.db.common.utils.Transaction.endTransaction; import static org.simantics.db.common.utils.Transaction.readGraph; import static org.simantics.db.common.utils.Transaction.startTransaction; import static org.simantics.db.common.utils.Transaction.writeGraph; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import java.util.TreeMap; import java.util.UUID; import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IProduct; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.osgi.service.resolver.BundleDescription; import org.simantics.databoard.Bindings; import org.simantics.databoard.Databoard; import org.simantics.datatypes.literal.Font; import org.simantics.datatypes.literal.RGB; import org.simantics.db.Driver; import org.simantics.db.Driver.Management; import org.simantics.db.Manager; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.SessionModel; import org.simantics.db.UndoContext; import org.simantics.db.VirtualGraph; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.ObjectsWithType; import org.simantics.db.common.request.Queries; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.request.WriteResultRequest; import org.simantics.db.common.utils.Transaction; import org.simantics.db.exception.ClusterSetExistException; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.ResourceNotFoundException; import org.simantics.db.indexing.DatabaseIndexing; import org.simantics.db.layer0.genericrelation.DependenciesRelation; import org.simantics.db.layer0.util.SimanticsClipboardImpl; import org.simantics.db.layer0.util.SimanticsKeys; import org.simantics.db.layer0.util.TGTransferableGraphSource; import org.simantics.db.layer0.variable.VariableRepository; import org.simantics.db.management.SessionContext; import org.simantics.db.request.Read; import org.simantics.db.service.LifecycleSupport.LifecycleListener; import org.simantics.db.service.LifecycleSupport.LifecycleState; import org.simantics.db.service.QueryControl; import org.simantics.db.service.UndoRedoSupport; import org.simantics.db.service.VirtualGraphSupport; import org.simantics.db.service.XSupport; import org.simantics.graph.db.GraphDependencyAnalyzer; import org.simantics.graph.db.GraphDependencyAnalyzer.IU; import org.simantics.graph.db.GraphDependencyAnalyzer.IdentityNode; import org.simantics.graph.db.IImportAdvisor; import org.simantics.graph.db.TransferableGraphs; import org.simantics.graph.diff.Diff; import org.simantics.graph.diff.TransferableGraphDelta1; import org.simantics.internal.Activator; import org.simantics.internal.startup.StartupExtensions; import org.simantics.layer0.Layer0; import org.simantics.operation.Layer0X; import org.simantics.project.IProject; import org.simantics.project.ProjectFeatures; import org.simantics.project.ProjectKeys; import org.simantics.project.Projects; import org.simantics.project.exception.ProjectException; import org.simantics.project.features.registry.GroupReference; import org.simantics.project.management.DatabaseManagement; import org.simantics.project.management.GraphBundle; import org.simantics.project.management.GraphBundleEx; import org.simantics.project.management.GraphBundleRef; import org.simantics.project.management.PlatformUtil; import org.simantics.project.management.ServerManager; import org.simantics.project.management.ServerManagerFactory; import org.simantics.project.management.WorkspaceUtil; import org.simantics.utils.FileUtils; import org.simantics.utils.datastructures.Pair; import org.simantics.utils.logging.TimeLogger; /** * SimanticsPlatform performs procedures required in order to get simantics * workbench into operational state. This consists of the following steps: * * * @author Toni Kalajainen */ public class SimanticsPlatform implements LifecycleListener { /** * The policy is relevant when developing Simantics from Eclipse IDE. * It is applied when the ontology in the database of a workspace doesn't match * a newer ontology in the Eclipse workspace. */ public static enum OntologyRecoveryPolicy { ThrowError, Merge, ReinstallDatabase } /** * This policy dictates how the Simantics platform startup should react if * the started workspace is not set up properly. The alternatives are to * just throw an error and fail or to attempt all possible measures to fix * the encountered problems. */ public static enum RecoveryPolicy { ThrowError, FixError } /** Singleton instance, started in SimanticsWorkbenchAdvisor */ public static final SimanticsPlatform INSTANCE = new SimanticsPlatform(); /** Set to true when the Simantics Platform is in good-and-go condition */ public boolean running; /** Database Session */ public Session session; private Management databasebManagement; /** Database session context */ public SessionContext sessionContext; /** Project identifier in Database */ public String projectURI; /** Project name */ public String projectName; /** Project resource */ public Resource projectResource; /** Session specific bindings */ public SimanticsBindings simanticsBindings; public SimanticsBindings simanticsBindings2; public Thread mainThread; /** * The {@link IProject} activated by * {@link #startUp(IProgressMonitor, RecoveryPolicy, OntologyRecoveryPolicy, ServerAddress, PlatformUserAgent)} */ private IProject project; protected ILog log; /** * Create a new simantics plaform manager in uninitialized state and * with default policies.

*/ public SimanticsPlatform() { log = Platform.getLog(Activator.getBundleContext().getBundle()); mainThread = Thread.currentThread(); } public String getApplicationClientId() { IProduct product = Platform.getProduct(); if(product == null) return "noProduct";//UUID.randomUUID().toString(); String application = product.getApplication(); return application != null ? application : UUID.randomUUID().toString(); } private Session setupDatabase(String databaseDriverId, IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy, PlatformUserAgent userAgent) throws PlatformException { if (progressMonitor == null) progressMonitor = new NullProgressMonitor(); File dbLocation = Platform.getLocation().append("db").toFile(); ServerManager serverManager; try { serverManager = ServerManagerFactory.create(databaseDriverId, dbLocation.getAbsolutePath()); } catch (DatabaseException | IOException e) { throw new PlatformException("Failed to initialize Server Manager", e); } progressMonitor.beginTask("Setting up Simantics Database", 100); progressMonitor.setTaskName("Asserting Database is installed."); String msg = "Failed to initialize Simantics database."; try { // Create database log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Creating database at " + dbLocation)); progressMonitor.setTaskName("Creating database at " + dbLocation); databasebManagement = serverManager.getManagement(dbLocation); databasebManagement.create(); // Create layer0. return serverManager.createDatabase(dbLocation); } catch (DatabaseException e) { throw new PlatformException(msg, e); } catch (Throwable e) { throw new PlatformException(msg, e); } finally { progressMonitor.worked(20); } } public void synchronizeOntologies(IProgressMonitor progressMonitor, OntologyRecoveryPolicy ontologyPolicy, boolean requireSynchronize) throws PlatformException { if (progressMonitor == null) progressMonitor = new NullProgressMonitor(); final DatabaseManagement mgmt = new DatabaseManagement(); PlatformUtil.compileAllDynamicOntologies(); progressMonitor.setTaskName("Asserting all ontologies are installed"); final Map platformTGs = new HashMap(); try { // Get a list of bundles installed into the database progressMonitor.subTask("find installed bundles from database"); Map installedTGs = new HashMap(); for (GraphBundle b : session.syncRequest( mgmt.GraphBundleQuery )) { installedTGs.put(GraphBundleRef.of(b), GraphBundleEx.extend(b)); } if(!requireSynchronize && installedTGs.size() > 1 && !Platform.inDevelopmentMode()) return; // if(installedTGs.size() > 1) return; // Get a list of all bundles in the platform (Bundle Context) List tgs = new ArrayList(); progressMonitor.subTask("load all transferable graphs from platform"); PlatformUtil.getAllGraphs(tgs); progressMonitor.subTask("extend bundles to compile versions"); for (GraphBundle b : tgs) { GraphBundleEx gbe = GraphBundleEx.extend(b); gbe.build(); platformTGs.put(GraphBundleRef.of(b), gbe); } // Compile a list of TGs that need to be installed or reinstalled in the database progressMonitor.subTask("check bundle reinstallation demand"); List installTGs = new ArrayList(); // Create list of TGs to update, Map reinstallTGs = new TreeMap(); for (Entry e : platformTGs.entrySet()) { GraphBundleRef key = e.getKey(); GraphBundleEx platformBundle = e.getValue(); GraphBundleEx existingBundle = installedTGs.get(key); // System.out.println("GraphBundleRef key=" + key.toString()); if (existingBundle == null) { // Bundle did not exist in the database, put it into list of bundles to install installTGs.add(platformBundle); } else { // Bundle exists in the database boolean platformBundleIsNewer = existingBundle.getVersion().compareTo(platformBundle.getVersion())<0; if (!platformBundleIsNewer) continue; // Check hash of transferable graph to know whether to update or not. if (platformBundle.getHashcode() == existingBundle.getHashcode()) continue; System.out.println("Ontology hashcodes do not match: platform bundle=" + platformBundle.getVersionedId() + ", hash=" + platformBundle.getHashcode() + "; existing bundle=" + existingBundle.getVersionedId() + ", hash=" + existingBundle.getHashcode()); reinstallTGs.put(platformBundle, existingBundle); } } // INSTALL // Database is missing graphs if (!installTGs.isEmpty() || !reinstallTGs.isEmpty()) { session.getService(XSupport.class).setServiceMode(true, true); // Throw error if (ontologyPolicy == OntologyRecoveryPolicy.ThrowError) { StringBuilder sb = new StringBuilder("The following graphs are not installed in the database: "); if (!installTGs.isEmpty()) { int i = 0; for (GraphBundleEx e : installTGs) { if (i>0) sb.append(", "); i++; sb.append(e.toString()); } sb.append(" is missing from the database.\n"); } if (!reinstallTGs.isEmpty()) { int i = 0; for (Entry e : reinstallTGs.entrySet()) { if (i>0) sb.append(", "); i++; sb.append(e.getKey().toString()); } sb.append(" Database/Platform Bundle version mismatch.\n"); } sb.append("Hint: Use -fixErrors to install the graphs."); throw new PlatformException(sb.toString()); } // Reinstall database if (ontologyPolicy == OntologyRecoveryPolicy.ReinstallDatabase) { log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Reinstalling the database.")); // TODO Install DB // Stop Session // Kill Process // Delete Database // Create Database // Start Database // Open Session // Install TGs throw new PlatformException("Reinstalling Database, NOT IMPLEMENTED"); } if (ontologyPolicy == OntologyRecoveryPolicy.Merge) { progressMonitor.subTask("Merging ontology changes"); // Sort missing TGs into install order GraphDependencyAnalyzer analyzer = new GraphDependencyAnalyzer(); for(GraphBundle tg : installTGs) analyzer.addGraph(tg, tg.getGraph()); for(GraphBundle tg : reinstallTGs.keySet()) analyzer.addGraph(tg, tg.getGraph()); if(!analyzer.analyzeDependency()) { Collection> problems = analyzer.getConflicts(); StringBuilder sb = new StringBuilder(); for (Pair problem : problems) { sb.append("Conflict with "+problem.first+" and "+problem.second+".\n"); } throw new PlatformException(sb.toString()); } else if(!session.syncRequest( analyzer.queryExternalDependenciesSatisfied )) { Collection unsatisfiedDependencies = analyzer.getUnsatisfiedDependencies(); StringBuilder sb = new StringBuilder(); for (IdentityNode dep: unsatisfiedDependencies) { sb.append("Unsatisfied Dependency "+dep+". Required by\n"); for(IU iu : GraphDependencyAnalyzer.toCollection(dep.getRequires())) { sb.append(" " + ((GraphBundle)iu.getId()).getId() + "\n"); } } throw new PlatformException(sb.toString()); } List sortedBundles = analyzer.getSortedGraphs(); if(!sortedBundles.isEmpty()) { session.syncRequest(new WriteRequest() { @Override public void perform(WriteGraph graph) throws DatabaseException { try { graph.newClusterSet(graph.getRootLibrary()); } catch (ClusterSetExistException e) { // Cluster set exist already, no problem. } graph.setClusterSet4NewResource(graph.getRootLibrary()); graph.flushCluster(); } }); boolean mergedOntologies = false; // Install TGs for(final GraphBundle tg : sortedBundles) { final IImportAdvisor advisor = new OntologyImportAdvisor(tg, mgmt); final GraphBundle oldTG = reinstallTGs.get(tg); if (oldTG==null) { boolean createImmutable = tg.getImmutable(); session.getService(XSupport.class).setServiceMode(true, createImmutable); // Install TG log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Installing "+tg.toString()+" - "+tg.getName())); TransferableGraphs.importGraph1(session, new TGTransferableGraphSource(tg.getGraph()), advisor, null); } else { // Merge TG startTransaction(session, false); TransferableGraphDelta1 delta = new Diff(oldTG.getGraph(), tg.getGraph()).diff(); final long[] oldResources = oldTG.getResourceArray(); boolean changes = TransferableGraphs.hasChanges(readGraph(), oldResources, delta); endTransaction(); if (!changes) { log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Nothing to merge for "+tg.toString())); continue; } log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Merging new version of "+tg.toString())); startTransaction(session, true); //delta.print(); try { long[] resourceArray = TransferableGraphs.applyDelta(writeGraph(), oldResources, delta); tg.setResourceArray(resourceArray); mgmt.setGraphBundleEntry(tg); commit(); mergedOntologies = true; } catch (Throwable t) { throw new PlatformException(t); } finally { endTransaction(); } } } session.syncRequest(new WriteRequest() { @Override public void perform(WriteGraph graph) throws DatabaseException { graph.setClusterSet4NewResource(graph.getRootLibrary()); graph.flushCluster(); } }); if (mergedOntologies) DatabaseIndexing.deleteAllIndexes(); } TimeLogger.log("Ontologies synchronized."); } session.getService(XSupport.class).setServiceMode(false, false); } progressMonitor.worked(20); } catch (IOException e) { throw new PlatformException(e); } catch (DatabaseException e) { throw new PlatformException(e); } } public boolean assertConfiguration(IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy) throws PlatformException { if (progressMonitor == null) progressMonitor = new NullProgressMonitor(); File workspaceLocation = Platform.getLocation().toFile(); boolean installProject = false; progressMonitor.setTaskName("Asserting simantics.cfg is installed"); try { File propertyFile = new File(workspaceLocation, "simantics.cfg"); Properties properties; try { properties = WorkspaceUtil.readProperties(propertyFile); } catch (IOException e) { if (workspacePolicy == RecoveryPolicy.ThrowError) throw new PlatformException("Could not load "+propertyFile); // Create a project and write Property file properties = new Properties(); properties.setProperty("project_uri", "http://Projects/Development%20Project"); properties.setProperty("project_name", "Development Project"); WorkspaceUtil.writeProperties(propertyFile, properties); installProject |= true; } projectURI = properties.getProperty("project_uri"); projectName = properties.getProperty("project_name"); progressMonitor.worked(10); } catch (IOException e) { throw new PlatformException(e); } return installProject; } public boolean assertProject(IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy, boolean installProject) throws PlatformException { if (progressMonitor == null) progressMonitor = new NullProgressMonitor(); final DatabaseManagement mgmt = new DatabaseManagement(); progressMonitor.setTaskName("Asserting project resource exists in the database"); try { projectResource = session.syncRequest( Queries.resource( projectURI ) ); } catch (ResourceNotFoundException nfe) { // Project was not found if (workspacePolicy == RecoveryPolicy.ThrowError) throw new PlatformException("Project Resource "+projectURI+" is not found in the database."); // Create empty project with no features try { Transaction.startTransaction(session, true); try { // The project needs to be created mutable. session.getService(XSupport.class).setServiceMode(true, false); ArrayList empty = new ArrayList(); projectResource = mgmt.createProject(projectName, empty); installProject |= true; session.getService(XSupport.class).setServiceMode(false, false); Transaction.commit(); } finally { Transaction.endTransaction(); } //session.getService( LifecycleSupport.class ).save(); } catch (DatabaseException e) { throw new PlatformException("Failed to create "+projectURI, e); } } catch (DatabaseException e) { throw new PlatformException("Failed to create "+projectURI, e); } progressMonitor.worked(10); return installProject; } public void updateInstalledGroups(IProgressMonitor progressMonitor, boolean installProject) throws PlatformException { if (installProject) { // Attach all feature groups available in platform to created project progressMonitor.setTaskName("Install all features"); Set publishedFeatureGroups = ProjectFeatures.getInstallGroupsOfPublishedFeatures(); Collection groupsWithoutVersion = GroupReference.stripVersions(publishedFeatureGroups); // final List Platform_Features = new ArrayList(); // // // Convert graph instances // Collection platformGraphs = new ArrayList(); // for (GraphBundleEx e : platformTGs.values()) platformGraphs.add( e.getGraph() ); // IGraph graph = Graphs.createGraph(platformGraphs); // // Res PublishedProjectFeatures = UriUtils.uriToPath( ProjectResource.URIs.PublishedProjectFeatures ); // Path HasFeature = UriUtils.uriToPath( ProjectResource.URIs.HasFeature ); // for(Res feature : graph.getObjects(PublishedProjectFeatures, HasFeature)) { // System.out.println("Installing Project Feature: "+feature.toString()); // Platform_Features.add( feature.toString() ); // } try { Transaction.startTransaction(session, true); try { // for (String feature : Platform_Features) { // try { // getResource(feature); // } catch(ResourceNotFoundException e) { // System.out.println(feature+" not found"); // } // mgmt.installFeature(projectResource, feature); // } Projects.setProjectInstalledGroups(writeGraph(), projectResource, groupsWithoutVersion); Transaction.commit(); } finally { Transaction.endTransaction(); } //session.getService( LifecycleSupport.class ).save(); } catch(DatabaseException ae) { throw new PlatformException("Failed to install features", ae); } progressMonitor.worked(10); } } public void assertSessionModel(IProgressMonitor progressMonitor) throws PlatformException { Properties properties = session.getService(Properties.class); final String clientId = properties.getProperty("clientId"); try { // Currently this needs to be done before data becomes available VirtualGraphSupport support = session.getService(VirtualGraphSupport.class); VirtualGraph activations = support.getWorkspacePersistent("activations"); Resource sessionModel = session.syncRequest(new Read() { @Override public Resource perform(ReadGraph graph) throws DatabaseException { Layer0X L0X = Layer0X.getInstance(graph); for(Resource sessionModel : graph.syncRequest(new ObjectsWithType(graph.getRootLibrary(), L0X.HasSession, L0X.Session))) { String id = graph.getPossibleRelatedValue(sessionModel, L0X.Session_HasClientId); if(id != null && id.equals(clientId)) return sessionModel; } return null; } }); if(sessionModel == null) { sessionModel = session.syncRequest(new WriteResultRequest(activations) { @Override public Resource perform(WriteGraph graph) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); Layer0X L0X = Layer0X.getInstance(graph); Resource session = graph.newResource(); graph.claim(session, L0.InstanceOf, null, L0X.Session); graph.claim(session, L0X.Session_HasUser, null, graph.getResource("http://Users/AdminUser")); graph.addLiteral(session, L0X.Session_HasClientId, L0X.Session_HasClientId_Inverse, clientId, Bindings.STRING); graph.claim(graph.getRootLibrary(), L0X.HasSession, session); return session; } }); } session.registerService(SessionModel.class, new PlatformSessionModel(sessionModel)); } catch (DatabaseException e) { throw new PlatformException(e); } } static class PlatformSessionModel implements SessionModel { private final Resource sessionModel; public PlatformSessionModel(Resource model) { this.sessionModel = model; } @Override public Resource getResource() { return sessionModel; } } public void resetDatabase(IProgressMonitor monitor) throws PlatformException { File dbLocation = Platform.getLocation().append("db").toFile(); if(!dbLocation.exists()) return; try { // Load driver Driver driver = Manager.getDriver("procore"); Management management = driver.getManagement(dbLocation.getAbsolutePath(), null); management.delete(); } catch (DatabaseException e) { throw new PlatformException("Failed to remove database at " + dbLocation.getAbsolutePath(), e); } // We have created extra files to database folder which have to be deleted also. // This is an awful idea! Do not create extra files to database folder! Throwable t = null; for (int i=0; i<10; ++i) { try { FileUtils.deleteAll(dbLocation); t = null; break; } catch (IOException e) { // Assuming this has been thrown because delete file/folder failed. t = e; } try { Thread.sleep(200); } catch (InterruptedException e) { // Ignoring interrupted exception. } } if (null != t) throw new PlatformException("Failed to remove database folder at " + dbLocation.getAbsolutePath(), t); } public void resetWorkspace(IProgressMonitor monitor, ArrayList fileFilter) throws PlatformException, IllegalStateException, IOException { File file = Platform.getLocation().toFile(); if (null != fileFilter) FileUtils.deleteAllWithFilter(file , fileFilter); resetDatabase(monitor); } /** * Start-up the platform. The procedure consists of 8 steps. Once everything * is up and running, all fields are set property. *

* * If workspacePolicy is FixErrors, there is an attempt to fix unexpected * errors. It includes installing database files, installing ontologies, and * installing project features. *

* * In SWB this is handled in SimanticsWorkbenchAdvisor#openWindows(). *

* * If remote server is given, simantics plaform takes connection there * instead of local server at "db/". * * @param workspacePolicy action to take on workspace/database related * errors * @param ontologyPolicy action to take on ontology mismatch * @param progressMonitor optional progress monitor * @param userAgent interface for resorting to user feedback during platform * startup or null to resort to default measures * @throws PlatformException */ public SessionContext startUp(String databaseDriverId, IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy, OntologyRecoveryPolicy ontologyPolicy, boolean requireSynchronize, PlatformUserAgent userAgent) throws PlatformException { assert(!running); TimeLogger.log("Beginning of SimanticsPlatform.startUp"); if (progressMonitor == null) progressMonitor = new NullProgressMonitor(); // For debugging on what kind of platform automatic tests are running in // case there are problems. if ("true".equals(System.getProperty("org.simantics.dumpBundleState"))) dumpPlatformBundleState(); // 0. Consult all startup extensions before doing anything with the workspace. StartupExtensions.consultStartupExtensions(); TimeLogger.log("Consulted platform pre-startup extensions"); // 0.1. Clear all temporary files Simantics.clearTemporaryDirectory(); TimeLogger.log("Cleared temporary directory"); // 0.2 Clear VariableRepository.repository static map which holds references to SessionImplDb VariableRepository.clear(); // 1. Assert there is a database at /db session = setupDatabase(databaseDriverId, progressMonitor, workspacePolicy, userAgent); TimeLogger.log("Database setup complete"); // 2. Assert all graphs, and correct versions, are installed to the database synchronizeOntologies(progressMonitor, ontologyPolicy, requireSynchronize); TimeLogger.log("Synchronized ontologies"); // 4. Assert simantics.cfg exists boolean installProject = assertConfiguration(progressMonitor,workspacePolicy); // 5. Assert Project Resource is installed in the database installProject = assertProject(progressMonitor, workspacePolicy, installProject); // 6. Install all features into project, if in debug mode updateInstalledGroups(progressMonitor, installProject); TimeLogger.log("Installed all features into project"); // 7. Assert L0.Session in database for this session assertSessionModel(progressMonitor); session.getService(XSupport.class).setServiceMode(false, false); try { session.sync(new WriteRequest() { @Override public void perform(WriteGraph graph) throws DatabaseException { QueryControl qc = graph.getService(QueryControl.class); qc.flush(graph); } }); TimeLogger.log("Flushed queries"); } catch (DatabaseException e) { Logger.defaultLogError(e); } boolean loadProject = true; try { sessionContext = SimanticsPlatform.INSTANCE.createSessionContext(true); // This must be before setSessionContext since some listeners might query this sessionContext.setHint(SimanticsKeys.KEY_PROJECT, SimanticsPlatform.INSTANCE.projectResource); Simantics.setSessionContext(sessionContext); // 1. Put ResourceBinding that throws an exception to General Bindings simanticsBindings = new SimanticsBindings( null ); Bindings.classBindingFactory.addFactory( simanticsBindings ); // 2. Create session-specific second Binding context (Databoard) and // put that to Session as a service Session session = sessionContext.getSession(); Databoard sessionDataboard = new Databoard(); session.registerService(Databoard.class, sessionDataboard); simanticsBindings2 = new SimanticsBindings( session ); sessionDataboard.classBindingFactory.addFactory( simanticsBindings2 ); // Register datatype bindings Bindings.defaultBindingFactory.getRepository().put(RGB.Integer.BINDING.type(), RGB.Integer.BINDING); Bindings.defaultBindingFactory.getRepository().put(Font.BINDING.type(), Font.BINDING); if(loadProject) { TimeLogger.log("Load projects"); project = Projects.loadProject(sessionContext.getSession(), SimanticsPlatform.INSTANCE.projectResource); sessionContext.setHint(ProjectKeys.KEY_PROJECT, project); TimeLogger.log("Loading projects complete"); project.activate(); TimeLogger.log("Project activated"); } } catch (DatabaseException e) { Logger.defaultLogError(e); throw new PlatformException(e); } catch (ProjectException e) { boolean hasStackTrace = e.getStackTrace().length > 0; if (!hasStackTrace) throw new PlatformException(e.getMessage(), hasStackTrace); throw new PlatformException(e, hasStackTrace); } running = true; return sessionContext; } public SessionContext createSessionContext(boolean init) throws PlatformException { try { // Construct and initialize SessionContext from Session. SessionContext sessionContext = SessionContext.create(session, init); if (init) sessionContext.registerServices(); return sessionContext; } catch (DatabaseException e) { throw new PlatformException(e); } } // private static File getIgnorePrerequisitesFile(URL workspaceUrl) { // if (workspaceUrl == null) // return null; // return new File(workspaceUrl.getPath(), ".ignorePrerequisites"); // } // // private void ensurePrerequisites(IProgressMonitor progressMonitor, PlatformUserAgent userAgent) throws PlatformException { // Location loc = Platform.getInstanceLocation(); // File ignorePrerequisites = getIgnorePrerequisitesFile(loc.getURL()); // if (loc.isSet() && ignorePrerequisites != null) { // if (ignorePrerequisites.exists() || ignorePrerequisites.isFile()) // return; // } // // try { // ServerEnvironment.ensureServerDependenciesMet(); // } catch (ExecutionEnvironmentException e) { // // Not installed properly, ask user whether to try installation. // try { // StringBuilder msg = new StringBuilder(); // msg.append("Your system seems to be missing the following prerequisites for running this application:\n\n"); // for (Product product : e.requiredProducts) // msg.append("\t" + product.getDescription() + "\n"); // msg.append("\nYou can either install the missing components now or ignore and attempt to start the application without them. Ignore Always will ignore this question for this workspace."); // msg.append("\n\nSelecting Cancel will close the application."); // // int selection = 0; // if (userAgent != null) { // selection = userAgent.showPrompt("Missing Prerequisites", msg.toString(), new String[] { // "Install Pre-requisites", // "Ignore Now", // "Ignore Always", // "Cancel" // }, selection); // } // boolean tryInstall = false; // switch (selection) { // case 0: // tryInstall = true; // break; // case 2: // ignorePrerequisites.createNewFile(); // case 1: // break; // case 3: // case -1: // throw new CancelStartupException(); // } // // if (tryInstall) { // // Try to install it and check for success afterwards. // ServerEnvironment.tryInstallDependencies(progressMonitor); // ServerEnvironment.ensureServerDependenciesMet(); // } // } catch (InstallException ie) { // throw new PlatformException(ie); // } catch (ExecutionEnvironmentException eee) { // throw new PlatformException(eee); // } catch (IOException ie) { // throw new PlatformException(ie); // } // } // } /** * Shutdown Simantics Platform. * * In SWB this is handled in SimanticsWorkbenchAdvisor#disconnectFromWorkspace. * * @param progressMonitor optional progress monitor * @throws PlatformException */ public void shutdown(IProgressMonitor progressMonitor) throws PlatformException { SubMonitor progress = SubMonitor.convert(progressMonitor, 100); PlatformException platformException = null; try { progress.subTask("Close Project"); if (project != null) { project.safeDispose(); } progress.worked(10); running = false; progress.subTask("Close Database Session"); Databoard databoard = null; if (sessionContext != null) { Session s = sessionContext.peekSession(); if (s != null) { databoard = s.peekService(Databoard.class); progress.subTask("Flushing Index Caches"); try { Simantics.flushIndexCaches(progress.newChild(20), s); } catch (Throwable t) { Logger.defaultLogError(t); } } progress.subTask("Close Database Session"); sessionContext.safeDispose(); sessionContext = null; Simantics.setSessionContext(null); } if (simanticsBindings != null) { Bindings.classBindingFactory.removeFactory( simanticsBindings ); simanticsBindings = null; } if (databoard != null) { if (simanticsBindings2 != null) { databoard.classBindingFactory.removeFactory( simanticsBindings2 ); simanticsBindings2 = null; } databoard.clear(); } // Make sure Simantics clipboard doesn't store unwanted session data references. Simantics.setClipboard(new SimanticsClipboardImpl()); progress.worked(30); session = null; projectResource = null; DependenciesRelation.assertFinishedTracking(); } catch (Exception e) { platformException = new PlatformException("Failed to shutdown Simantics Platform", e); } progress.worked(10); progress.subTask("Shutting down database"); try { if (null != databasebManagement) databasebManagement.shutdown(); } catch (Throwable t) { Logger.defaultLogError(t); } progress.worked(10); progress.subTask("Clearing Workspace Temporary Directory"); try { Simantics.clearTemporaryDirectory(); } catch (Throwable t) { Logger.defaultLogError(t); } progress.worked(10); if (null != platformException) throw platformException; } // TODO: consider removing this in the future ?? @Override public void stateChanged(LifecycleState newState) { if(newState == LifecycleState.CLOSED) { if(running) { if(Platform.isRunning()) { mainThread.interrupt(); } } } } /** * @return true if discard was successful, false * if there was no session, {@link UndoRedoSupport} or * {@link UndoContext} to discard through */ public boolean discardSessionUndoHistory() { Session s = session; if (s != null) { UndoRedoSupport urs = s.peekService(UndoRedoSupport.class); if (urs != null) { UndoContext uc = urs.getUndoContext(s); if (uc != null) { uc.clear(); return true; } } } return false; } public void reconnect(String databaseDriverId) throws Exception { // Starts database server. SimanticsPlatform.INSTANCE.startUp(databaseDriverId, null, RecoveryPolicy.ThrowError, OntologyRecoveryPolicy.ThrowError, true, null); } private void dumpPlatformBundleState() { BundleDescription[] bs = Platform.getPlatformAdmin().getState().getBundles(); System.out.println("Total bundles: " + bs.length); for (BundleDescription b : bs) { System.out.format("%-80s @ %s\n", b.toString(), b.getLocation()); } } }