1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics;
14 import static org.simantics.db.common.utils.Transaction.commit;
15 import static org.simantics.db.common.utils.Transaction.endTransaction;
16 import static org.simantics.db.common.utils.Transaction.readGraph;
17 import static org.simantics.db.common.utils.Transaction.startTransaction;
18 import static org.simantics.db.common.utils.Transaction.writeGraph;
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.List;
27 import java.util.Map.Entry;
28 import java.util.Properties;
30 import java.util.TreeMap;
31 import java.util.UUID;
33 import org.eclipse.core.runtime.ILog;
34 import org.eclipse.core.runtime.IProduct;
35 import org.eclipse.core.runtime.IProgressMonitor;
36 import org.eclipse.core.runtime.IStatus;
37 import org.eclipse.core.runtime.NullProgressMonitor;
38 import org.eclipse.core.runtime.Platform;
39 import org.eclipse.core.runtime.Status;
40 import org.eclipse.core.runtime.SubMonitor;
41 import org.eclipse.osgi.service.resolver.BundleDescription;
42 import org.simantics.databoard.Bindings;
43 import org.simantics.databoard.Databoard;
44 import org.simantics.datatypes.literal.Font;
45 import org.simantics.datatypes.literal.RGB;
46 import org.simantics.db.Driver;
47 import org.simantics.db.Driver.Management;
48 import org.simantics.db.Manager;
49 import org.simantics.db.ReadGraph;
50 import org.simantics.db.Resource;
51 import org.simantics.db.Session;
52 import org.simantics.db.SessionModel;
53 import org.simantics.db.UndoContext;
54 import org.simantics.db.VirtualGraph;
55 import org.simantics.db.WriteGraph;
56 import org.simantics.db.common.request.ObjectsWithType;
57 import org.simantics.db.common.request.Queries;
58 import org.simantics.db.common.request.WriteRequest;
59 import org.simantics.db.common.request.WriteResultRequest;
60 import org.simantics.db.common.utils.Transaction;
61 import org.simantics.db.exception.ClusterSetExistException;
62 import org.simantics.db.exception.DatabaseException;
63 import org.simantics.db.exception.ResourceNotFoundException;
64 import org.simantics.db.indexing.DatabaseIndexing;
65 import org.simantics.db.layer0.genericrelation.DependenciesRelation;
66 import org.simantics.db.layer0.util.SimanticsClipboardImpl;
67 import org.simantics.db.layer0.util.SimanticsKeys;
68 import org.simantics.db.layer0.util.TGTransferableGraphSource;
69 import org.simantics.db.layer0.variable.VariableRepository;
70 import org.simantics.db.management.SessionContext;
71 import org.simantics.db.request.Read;
72 import org.simantics.db.service.LifecycleSupport.LifecycleListener;
73 import org.simantics.db.service.LifecycleSupport.LifecycleState;
74 import org.simantics.db.service.QueryControl;
75 import org.simantics.db.service.UndoRedoSupport;
76 import org.simantics.db.service.VirtualGraphSupport;
77 import org.simantics.db.service.XSupport;
78 import org.simantics.graph.db.GraphDependencyAnalyzer;
79 import org.simantics.graph.db.GraphDependencyAnalyzer.IU;
80 import org.simantics.graph.db.GraphDependencyAnalyzer.IdentityNode;
81 import org.simantics.graph.db.IImportAdvisor;
82 import org.simantics.graph.db.TransferableGraphs;
83 import org.simantics.graph.diff.Diff;
84 import org.simantics.graph.diff.TransferableGraphDelta1;
85 import org.simantics.internal.Activator;
86 import org.simantics.internal.startup.StartupExtensions;
87 import org.simantics.layer0.Layer0;
88 import org.simantics.operation.Layer0X;
89 import org.simantics.project.IProject;
90 import org.simantics.project.ProjectFeatures;
91 import org.simantics.project.ProjectKeys;
92 import org.simantics.project.Projects;
93 import org.simantics.project.exception.ProjectException;
94 import org.simantics.project.features.registry.GroupReference;
95 import org.simantics.project.management.DatabaseManagement;
96 import org.simantics.project.management.GraphBundle;
97 import org.simantics.project.management.GraphBundleEx;
98 import org.simantics.project.management.GraphBundleRef;
99 import org.simantics.project.management.PlatformUtil;
100 import org.simantics.project.management.ServerManager;
101 import org.simantics.project.management.ServerManagerFactory;
102 import org.simantics.project.management.WorkspaceUtil;
103 import org.simantics.utils.FileUtils;
104 import org.simantics.utils.datastructures.Pair;
105 import org.simantics.utils.logging.TimeLogger;
106 import org.slf4j.Logger;
107 import org.slf4j.LoggerFactory;
110 * SimanticsPlatform performs procedures required in order to get simantics
111 * workbench into operational state. This consists of the following steps:
113 * <li> Asserting there is Database
115 * <li> Starting Database process
117 * <li> Opening a session to Database process
119 * <li> Asserting required ontologies or other transferable graphs are installed in the database
121 * <li> Asserting required project is installed in the database
123 * <li> Asserting Simantics Features are installed in the database
125 * <li> Asserting Simantics Features are installed to the project
127 * <li> Shutdown: Save Session, Close session, Kill Database process
131 * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
133 public class SimanticsPlatform implements LifecycleListener {
135 private static final Logger LOGGER = LoggerFactory.getLogger(SimanticsPlatform.class);
138 * The policy is relevant when developing Simantics from Eclipse IDE.
139 * It is applied when the ontology in the database of a workspace doesn't match
140 * a newer ontology in the Eclipse workspace.
142 public static enum OntologyRecoveryPolicy { ThrowError, Merge, ReinstallDatabase }
145 * This policy dictates how the Simantics platform startup should react if
146 * the started workspace is not set up properly. The alternatives are to
147 * just throw an error and fail or to attempt all possible measures to fix
148 * the encountered problems.
150 public static enum RecoveryPolicy { ThrowError, FixError }
152 /** Singleton instance, started in SimanticsWorkbenchAdvisor */
153 public static final SimanticsPlatform INSTANCE = new SimanticsPlatform();
155 /** Set to true when the Simantics Platform is in good-and-go condition */
156 public boolean running;
158 /** Database Session */
159 public Session session;
160 private Management databasebManagement;
162 /** Database session context */
163 public SessionContext sessionContext;
165 /** Project identifier in Database */
166 public String projectURI;
169 public String projectName;
171 /** Project resource */
172 public Resource projectResource;
174 /** Session specific bindings */
175 public SimanticsBindings simanticsBindings;
176 public SimanticsBindings simanticsBindings2;
178 public Thread mainThread;
181 * The {@link IProject} activated by
182 * {@link #startUp(IProgressMonitor, RecoveryPolicy, OntologyRecoveryPolicy, ServerAddress, PlatformUserAgent)}
184 private IProject project;
189 * Create a new simantics plaform manager in uninitialized state and
190 * with default policies. <p>
192 public SimanticsPlatform() {
193 log = Platform.getLog(Activator.getBundleContext().getBundle());
194 mainThread = Thread.currentThread();
197 public String getApplicationClientId() {
198 IProduct product = Platform.getProduct();
199 if(product == null) return "noProduct";//UUID.randomUUID().toString();
200 String application = product.getApplication();
201 return application != null ? application : UUID.randomUUID().toString();
204 private Session setupDatabase(String databaseDriverId, IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy, PlatformUserAgent userAgent) throws PlatformException {
205 if (progressMonitor == null)
206 progressMonitor = new NullProgressMonitor();
207 File dbLocation = Platform.getLocation().append("db").toFile();
208 ServerManager serverManager;
210 serverManager = ServerManagerFactory.create(databaseDriverId, dbLocation.getAbsolutePath());
211 } catch (DatabaseException | IOException e) {
212 throw new PlatformException("Failed to initialize Server Manager", e);
214 progressMonitor.beginTask("Setting up Simantics Database", 100);
215 progressMonitor.setTaskName("Asserting Database is installed.");
216 String msg = "Failed to initialize Simantics database.";
219 log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Creating database at " + dbLocation));
220 progressMonitor.setTaskName("Creating database at " + dbLocation);
221 databasebManagement = serverManager.getManagement(dbLocation);
222 databasebManagement.create();
224 return serverManager.createDatabase(dbLocation);
225 } catch (DatabaseException e) {
226 throw new PlatformException(msg, e);
227 } catch (Throwable e) {
228 throw new PlatformException(msg, e);
230 progressMonitor.worked(20);
234 public void synchronizeOntologies(IProgressMonitor progressMonitor, OntologyRecoveryPolicy ontologyPolicy, boolean requireSynchronize) throws PlatformException {
236 if (progressMonitor == null) progressMonitor = new NullProgressMonitor();
238 final DatabaseManagement mgmt = new DatabaseManagement();
240 PlatformUtil.compileAllDynamicOntologies();
242 progressMonitor.setTaskName("Asserting all ontologies are installed");
243 final Map<GraphBundleRef, GraphBundleEx> platformTGs = new HashMap<GraphBundleRef, GraphBundleEx>();
246 // Get a list of bundles installed into the database
247 progressMonitor.subTask("find installed bundles from database");
248 Map<GraphBundleRef, GraphBundleEx> installedTGs = new HashMap<GraphBundleRef, GraphBundleEx>();
249 for (GraphBundle b : session.syncRequest( mgmt.GraphBundleQuery )) {
250 installedTGs.put(GraphBundleRef.of(b), GraphBundleEx.extend(b));
253 if(!requireSynchronize && installedTGs.size() > 1 && !Platform.inDevelopmentMode()) return;
254 // if(installedTGs.size() > 1) return;
256 // Get a list of all bundles in the platform (Bundle Context)
257 List<GraphBundle> tgs = new ArrayList<GraphBundle>();
258 progressMonitor.subTask("load all transferable graphs from platform");
259 PlatformUtil.getAllGraphs(tgs);
260 progressMonitor.subTask("extend bundles to compile versions");
261 for (GraphBundle b : tgs) {
262 GraphBundleEx gbe = GraphBundleEx.extend(b);
264 platformTGs.put(GraphBundleRef.of(b), gbe);
267 // Compile a list of TGs that need to be installed or reinstalled in the database
268 progressMonitor.subTask("check bundle reinstallation demand");
269 List<GraphBundleEx> installTGs = new ArrayList<GraphBundleEx>();
270 // Create list of TGs to update, <newTg, oldTg>
271 Map<GraphBundleEx,GraphBundleEx> reinstallTGs = new TreeMap<GraphBundleEx,GraphBundleEx>();
272 for (Entry<GraphBundleRef, GraphBundleEx> e : platformTGs.entrySet()) {
273 GraphBundleRef key = e.getKey();
274 GraphBundleEx platformBundle = e.getValue();
275 GraphBundleEx existingBundle = installedTGs.get(key);
277 // System.out.println("GraphBundleRef key=" + key.toString());
279 if (existingBundle == null) {
280 // Bundle did not exist in the database, put it into list of bundles to install
281 installTGs.add(platformBundle);
284 // Bundle exists in the database
285 boolean platformBundleIsNewer = existingBundle.getVersion().compareTo(platformBundle.getVersion())<0;
286 if (!platformBundleIsNewer)
288 // Check hash of transferable graph to know whether to update or not.
289 if (platformBundle.getHashcode() == existingBundle.getHashcode())
291 //System.out.println("Ontology hashcodes do not match: platform bundle="
292 // + platformBundle.getVersionedId() + ", hash=" + platformBundle.getHashcode()
293 // + "; existing bundle=" + existingBundle.getVersionedId() + ", hash=" + existingBundle.getHashcode());
294 reinstallTGs.put(platformBundle, existingBundle);
298 // Database is missing graphs
299 if (!installTGs.isEmpty() || !reinstallTGs.isEmpty()) {
300 session.getService(XSupport.class).setServiceMode(true, true);
303 if (ontologyPolicy == OntologyRecoveryPolicy.ThrowError) {
304 StringBuilder sb = new StringBuilder("The following graphs are not installed in the database: ");
305 if (!installTGs.isEmpty()) {
307 for (GraphBundleEx e : installTGs) {
308 if (i>0) sb.append(", ");
310 sb.append(e.toString());
312 sb.append(" is missing from the database.\n");
314 if (!reinstallTGs.isEmpty()) {
316 for (Entry<GraphBundleEx, GraphBundleEx> e : reinstallTGs.entrySet()) {
317 if (i>0) sb.append(", ");
319 sb.append(e.getKey().toString());
321 sb.append(" Database/Platform Bundle version mismatch.\n");
323 sb.append("Hint: Use -fixErrors to install the graphs.");
324 throw new PlatformException(sb.toString());
326 // Reinstall database
327 if (ontologyPolicy == OntologyRecoveryPolicy.ReinstallDatabase) {
328 log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Reinstalling the database."));
337 throw new PlatformException("Reinstalling Database, NOT IMPLEMENTED");
340 if (ontologyPolicy == OntologyRecoveryPolicy.Merge) {
341 progressMonitor.subTask("Merging ontology changes");
342 // Sort missing TGs into install order
343 GraphDependencyAnalyzer<GraphBundle> analyzer = new GraphDependencyAnalyzer<GraphBundle>();
344 for(GraphBundle tg : installTGs) analyzer.addGraph(tg, tg.getGraph());
345 for(GraphBundle tg : reinstallTGs.keySet()) analyzer.addGraph(tg, tg.getGraph());
346 if(!analyzer.analyzeDependency()) {
347 Collection<Pair<GraphBundle, GraphBundle>> problems = analyzer.getConflicts();
348 StringBuilder sb = new StringBuilder();
349 for (Pair<GraphBundle, GraphBundle> problem : problems) {
350 sb.append("Conflict with "+problem.first+" and "+problem.second+".\n");
352 throw new PlatformException(sb.toString());
354 else if(!session.syncRequest( analyzer.queryExternalDependenciesSatisfied )) {
355 Collection<IdentityNode> unsatisfiedDependencies = analyzer.getUnsatisfiedDependencies();
356 StringBuilder sb = new StringBuilder();
357 for (IdentityNode dep: unsatisfiedDependencies) {
358 sb.append("Unsatisfied Dependency "+dep+". Required by\n");
359 for(IU iu : GraphDependencyAnalyzer.toCollection(dep.getRequires())) {
360 sb.append(" " + ((GraphBundle)iu.getId()).getId() + "\n");
363 throw new PlatformException(sb.toString());
366 List<GraphBundle> sortedBundles = analyzer.getSortedGraphs();
367 if(!sortedBundles.isEmpty()) {
369 session.syncRequest(new WriteRequest() {
371 public void perform(WriteGraph graph) throws DatabaseException {
373 graph.newClusterSet(graph.getRootLibrary());
374 } catch (ClusterSetExistException e) {
375 // Cluster set exist already, no problem.
377 graph.setClusterSet4NewResource(graph.getRootLibrary());
378 graph.flushCluster();
382 boolean mergedOntologies = false;
385 for(final GraphBundle tg : sortedBundles) {
387 final IImportAdvisor advisor = new OntologyImportAdvisor(tg, mgmt);
388 final GraphBundle oldTG = reinstallTGs.get(tg);
392 boolean createImmutable = tg.getImmutable();
393 session.getService(XSupport.class).setServiceMode(true, createImmutable);
396 log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Installing "+tg.toString()+" - "+tg.getName()));
397 TransferableGraphs.importGraph1(session, new TGTransferableGraphSource(tg.getGraph()), advisor, null);
400 startTransaction(session, false);
401 TransferableGraphDelta1 delta = new Diff(oldTG.getGraph(), tg.getGraph()).diff();
402 final long[] oldResources = oldTG.getResourceArray();
403 boolean changes = TransferableGraphs.hasChanges(readGraph(), oldResources, delta);
406 //log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Nothing to merge for "+tg.toString()));
410 log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Merging new version of "+tg.toString()));
412 startTransaction(session, true);
418 long[] resourceArray = TransferableGraphs.applyDelta(writeGraph(), oldResources, delta);
419 tg.setResourceArray(resourceArray);
420 mgmt.setGraphBundleEntry(tg);
422 mergedOntologies = true;
423 } catch (Throwable t) {
424 throw new PlatformException(t);
431 session.syncRequest(new WriteRequest() {
433 public void perform(WriteGraph graph) throws DatabaseException {
434 graph.setClusterSet4NewResource(graph.getRootLibrary());
435 graph.flushCluster();
439 if (mergedOntologies)
440 DatabaseIndexing.deleteAllIndexes();
443 TimeLogger.log("Ontologies synchronized.");
446 session.getService(XSupport.class).setServiceMode(false, false);
448 progressMonitor.worked(20);
449 } catch (IOException e) {
450 throw new PlatformException(e);
451 } catch (DatabaseException e) {
452 throw new PlatformException(e);
457 public boolean assertConfiguration(IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy) throws PlatformException {
459 if (progressMonitor == null) progressMonitor = new NullProgressMonitor();
461 File workspaceLocation = Platform.getLocation().toFile();
463 boolean installProject = false;
464 progressMonitor.setTaskName("Asserting simantics.cfg is installed");
466 File propertyFile = new File(workspaceLocation, "simantics.cfg");
467 Properties properties;
469 properties = WorkspaceUtil.readProperties(propertyFile);
470 } catch (IOException e) {
471 if (workspacePolicy == RecoveryPolicy.ThrowError) throw new PlatformException("Could not load "+propertyFile);
473 // Create a project and write Property file
474 properties = new Properties();
475 properties.setProperty("project_uri", "http://Projects/Development%20Project");
476 properties.setProperty("project_name", "Development Project");
477 WorkspaceUtil.writeProperties(propertyFile, properties);
478 installProject |= true;
480 projectURI = properties.getProperty("project_uri");
481 projectName = properties.getProperty("project_name");
482 progressMonitor.worked(10);
483 } catch (IOException e) {
484 throw new PlatformException(e);
487 return installProject;
491 public boolean assertProject(IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy, boolean installProject) throws PlatformException {
493 if (progressMonitor == null) progressMonitor = new NullProgressMonitor();
495 final DatabaseManagement mgmt = new DatabaseManagement();
497 progressMonitor.setTaskName("Asserting project resource exists in the database");
499 projectResource = session.syncRequest( Queries.resource( projectURI ) );
500 } catch (ResourceNotFoundException nfe) {
501 // Project was not found
502 if (workspacePolicy == RecoveryPolicy.ThrowError)
503 throw new PlatformException("Project Resource "+projectURI+" is not found in the database.");
504 // Create empty project with no features
506 Transaction.startTransaction(session, true);
508 // The project needs to be created mutable.
509 session.getService(XSupport.class).setServiceMode(true, false);
511 ArrayList<String> empty = new ArrayList<String>();
512 projectResource = mgmt.createProject(projectName, empty);
513 installProject |= true;
515 session.getService(XSupport.class).setServiceMode(false, false);
516 Transaction.commit();
518 Transaction.endTransaction();
520 //session.getService( LifecycleSupport.class ).save();
521 } catch (DatabaseException e) {
522 throw new PlatformException("Failed to create "+projectURI, e);
524 } catch (DatabaseException e) {
525 throw new PlatformException("Failed to create "+projectURI, e);
527 progressMonitor.worked(10);
529 return installProject;
533 public void updateInstalledGroups(IProgressMonitor progressMonitor, boolean installProject) throws PlatformException {
537 // Attach all feature groups available in platform to created project
538 progressMonitor.setTaskName("Install all features");
539 Set<GroupReference> publishedFeatureGroups = ProjectFeatures.getInstallGroupsOfPublishedFeatures();
540 Collection<GroupReference> groupsWithoutVersion = GroupReference.stripVersions(publishedFeatureGroups);
542 // final List<String> Platform_Features = new ArrayList<String>();
544 // // Convert graph instances
545 // Collection<TransferableGraph1> platformGraphs = new ArrayList<TransferableGraph1>();
546 // for (GraphBundleEx e : platformTGs.values()) platformGraphs.add( e.getGraph() );
547 // IGraph graph = Graphs.createGraph(platformGraphs);
549 // Res PublishedProjectFeatures = UriUtils.uriToPath( ProjectResource.URIs.PublishedProjectFeatures );
550 // Path HasFeature = UriUtils.uriToPath( ProjectResource.URIs.HasFeature );
551 // for(Res feature : graph.getObjects(PublishedProjectFeatures, HasFeature)) {
552 // System.out.println("Installing Project Feature: "+feature.toString());
553 // Platform_Features.add( feature.toString() );
557 Transaction.startTransaction(session, true);
559 // for (String feature : Platform_Features) {
561 // getResource(feature);
562 // } catch(ResourceNotFoundException e) {
563 // System.out.println(feature+" not found");
565 // mgmt.installFeature(projectResource, feature);
567 Projects.setProjectInstalledGroups(writeGraph(), projectResource, groupsWithoutVersion);
568 Transaction.commit();
570 Transaction.endTransaction();
572 //session.getService( LifecycleSupport.class ).save();
573 } catch(DatabaseException ae) {
574 throw new PlatformException("Failed to install features", ae);
576 progressMonitor.worked(10);
581 public void assertSessionModel(IProgressMonitor progressMonitor) throws PlatformException {
583 Properties properties = session.getService(Properties.class);
584 final String clientId = properties.getProperty("clientId");
588 // Currently this needs to be done before data becomes available
589 VirtualGraphSupport support = session.getService(VirtualGraphSupport.class);
590 VirtualGraph activations = support.getWorkspacePersistent("activations");
592 Resource sessionModel = session.syncRequest(new Read<Resource>() {
595 public Resource perform(ReadGraph graph) throws DatabaseException {
597 Layer0X L0X = Layer0X.getInstance(graph);
598 for(Resource sessionModel : graph.syncRequest(new ObjectsWithType(graph.getRootLibrary(), L0X.HasSession, L0X.Session))) {
599 String id = graph.getPossibleRelatedValue(sessionModel, L0X.Session_HasClientId);
600 if(id != null && id.equals(clientId)) return sessionModel;
608 if(sessionModel == null) {
610 sessionModel = session.syncRequest(new WriteResultRequest<Resource>(activations) {
613 public Resource perform(WriteGraph graph) throws DatabaseException {
614 Layer0 L0 = Layer0.getInstance(graph);
615 Layer0X L0X = Layer0X.getInstance(graph);
616 Resource session = graph.newResource();
617 graph.claim(session, L0.InstanceOf, null, L0X.Session);
618 graph.claim(session, L0X.Session_HasUser, null, graph.getResource("http://Users/AdminUser"));
619 graph.addLiteral(session, L0X.Session_HasClientId, L0X.Session_HasClientId_Inverse, clientId, Bindings.STRING);
620 graph.claim(graph.getRootLibrary(), L0X.HasSession, session);
627 session.registerService(SessionModel.class, new PlatformSessionModel(sessionModel));
628 } catch (DatabaseException e) {
629 throw new PlatformException(e);
634 static class PlatformSessionModel implements SessionModel {
635 private final Resource sessionModel;
637 public PlatformSessionModel(Resource model) {
638 this.sessionModel = model;
642 public Resource getResource() {
647 public void resetDatabase(IProgressMonitor monitor) throws PlatformException {
648 File dbLocation = Platform.getLocation().append("db").toFile();
649 if(!dbLocation.exists()) return;
651 Driver driver = Manager.getDriver("procore");
652 Management management = driver.getManagement(dbLocation.getAbsolutePath(), null);
654 } catch (DatabaseException e) {
655 throw new PlatformException("Failed to remove database at " + dbLocation.getAbsolutePath(), e);
657 // We have created extra files to database folder which have to be deleted also.
658 // This is an awful idea! Do not create extra files to database folder!
660 for (int i=0; i<10; ++i) {
662 FileUtils.deleteAll(dbLocation);
665 } catch (IOException e) {
666 // Assuming this has been thrown because delete file/folder failed.
671 } catch (InterruptedException e) {
672 // Ignoring interrupted exception.
676 throw new PlatformException("Failed to remove database folder at " + dbLocation.getAbsolutePath(), t);
678 public void resetWorkspace(IProgressMonitor monitor, ArrayList<String> fileFilter) throws PlatformException, IllegalStateException, IOException {
679 File file = Platform.getLocation().toFile();
680 if (null != fileFilter)
681 FileUtils.deleteAllWithFilter(file , fileFilter);
682 resetDatabase(monitor);
686 * Start-up the platform. The procedure consists of 8 steps. Once everything
687 * is up and running, all fields are set property.
690 * If workspacePolicy is FixErrors, there is an attempt to fix unexpected
691 * errors. It includes installing database files, installing ontologies, and
692 * installing project features.
695 * In SWB this is handled in SimanticsWorkbenchAdvisor#openWindows().
698 * If remote server is given, simantics plaform takes connection there
699 * instead of local server at "db/".
701 * @param workspacePolicy action to take on workspace/database related
703 * @param ontologyPolicy action to take on ontology mismatch
704 * @param progressMonitor optional progress monitor
705 * @param userAgent interface for resorting to user feedback during platform
706 * startup or <code>null</code> to resort to default measures
707 * @throws PlatformException
709 public SessionContext startUp(String databaseDriverId, IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy,
710 OntologyRecoveryPolicy ontologyPolicy, boolean requireSynchronize, PlatformUserAgent userAgent)
711 throws PlatformException
715 TimeLogger.log("Beginning of SimanticsPlatform.startUp");
717 LOGGER.info("Beginning of SimanticsPlatform.startUp");
719 if (progressMonitor == null) progressMonitor = new NullProgressMonitor();
721 // For debugging on what kind of platform automatic tests are running in
722 // case there are problems.
723 if ("true".equals(System.getProperty("org.simantics.dumpBundleState")))
724 dumpPlatformBundleState();
726 // 0. Consult all startup extensions before doing anything with the workspace.
727 StartupExtensions.consultStartupExtensions();
728 TimeLogger.log("Consulted platform pre-startup extensions");
730 // 0.1. Clear all temporary files
731 Simantics.clearTemporaryDirectory();
732 TimeLogger.log("Cleared temporary directory");
734 // 0.2 Clear VariableRepository.repository static map which holds references to SessionImplDb
735 VariableRepository.clear();
737 // 1. Assert there is a database at <workspace>/db
738 session = setupDatabase(databaseDriverId, progressMonitor, workspacePolicy, userAgent);
739 TimeLogger.log("Database setup complete");
741 // 2. Assert all graphs, and correct versions, are installed to the database
742 synchronizeOntologies(progressMonitor, ontologyPolicy, requireSynchronize);
743 TimeLogger.log("Synchronized ontologies");
745 // 4. Assert simantics.cfg exists
746 boolean installProject = assertConfiguration(progressMonitor,workspacePolicy);
748 // 5. Assert Project Resource is installed in the database
749 installProject = assertProject(progressMonitor, workspacePolicy, installProject);
751 // 6. Install all features into project, if in debug mode
752 updateInstalledGroups(progressMonitor, installProject);
753 TimeLogger.log("Installed all features into project");
755 // 7. Assert L0.Session in database for this session
756 assertSessionModel(progressMonitor);
758 session.getService(XSupport.class).setServiceMode(false, false);
761 session.sync(new WriteRequest() {
764 public void perform(WriteGraph graph) throws DatabaseException {
765 QueryControl qc = graph.getService(QueryControl.class);
770 TimeLogger.log("Flushed queries");
771 } catch (DatabaseException e) {
772 LOGGER.error("Flushing queries failed.", e);
774 boolean loadProject = true;
777 sessionContext = SimanticsPlatform.INSTANCE.createSessionContext(true);
778 // This must be before setSessionContext since some listeners might query this
779 sessionContext.setHint(SimanticsKeys.KEY_PROJECT, SimanticsPlatform.INSTANCE.projectResource);
781 Simantics.setSessionContext(sessionContext);
783 // 1. Put ResourceBinding that throws an exception to General Bindings
784 simanticsBindings = new SimanticsBindings( null );
785 Bindings.classBindingFactory.addFactory( simanticsBindings );
788 // 2. Create session-specific second Binding context (Databoard) and
789 // put that to Session as a service
790 Session session = sessionContext.getSession();
791 Databoard sessionDataboard = new Databoard();
792 session.registerService(Databoard.class, sessionDataboard);
793 simanticsBindings2 = new SimanticsBindings( session );
794 sessionDataboard.classBindingFactory.addFactory( simanticsBindings2 );
796 // Register datatype bindings
797 Bindings.defaultBindingFactory.getRepository().put(RGB.Integer.BINDING.type(), RGB.Integer.BINDING);
798 Bindings.defaultBindingFactory.getRepository().put(Font.BINDING.type(), Font.BINDING);
802 TimeLogger.log("Load projects");
803 project = Projects.loadProject(sessionContext.getSession(), SimanticsPlatform.INSTANCE.projectResource);
805 sessionContext.setHint(ProjectKeys.KEY_PROJECT, project);
806 TimeLogger.log("Loading projects complete");
809 TimeLogger.log("Project activated");
812 } catch (DatabaseException e) {
813 LOGGER.error("Platform startup failed.", e);
814 throw new PlatformException(e);
815 } catch (ProjectException e) {
816 boolean hasStackTrace = e.getStackTrace().length > 0;
818 throw new PlatformException(e.getMessage(), hasStackTrace);
819 throw new PlatformException(e, hasStackTrace);
824 return sessionContext;
828 public SessionContext createSessionContext(boolean init) throws PlatformException {
830 // Construct and initialize SessionContext from Session.
831 SessionContext sessionContext = SessionContext.create(session, init);
833 sessionContext.registerServices();
834 return sessionContext;
835 } catch (DatabaseException e) {
836 throw new PlatformException(e);
840 // private static File getIgnorePrerequisitesFile(URL workspaceUrl) {
841 // if (workspaceUrl == null)
843 // return new File(workspaceUrl.getPath(), ".ignorePrerequisites");
846 // private void ensurePrerequisites(IProgressMonitor progressMonitor, PlatformUserAgent userAgent) throws PlatformException {
847 // Location loc = Platform.getInstanceLocation();
848 // File ignorePrerequisites = getIgnorePrerequisitesFile(loc.getURL());
849 // if (loc.isSet() && ignorePrerequisites != null) {
850 // if (ignorePrerequisites.exists() || ignorePrerequisites.isFile())
855 // ServerEnvironment.ensureServerDependenciesMet();
856 // } catch (ExecutionEnvironmentException e) {
857 // // Not installed properly, ask user whether to try installation.
859 // StringBuilder msg = new StringBuilder();
860 // msg.append("Your system seems to be missing the following prerequisites for running this application:\n\n");
861 // for (Product product : e.requiredProducts)
862 // msg.append("\t" + product.getDescription() + "\n");
863 // 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.");
864 // msg.append("\n\nSelecting Cancel will close the application.");
866 // int selection = 0;
867 // if (userAgent != null) {
868 // selection = userAgent.showPrompt("Missing Prerequisites", msg.toString(), new String[] {
869 // "Install Pre-requisites",
875 // boolean tryInstall = false;
876 // switch (selection) {
878 // tryInstall = true;
881 // ignorePrerequisites.createNewFile();
886 // throw new CancelStartupException();
890 // // Try to install it and check for success afterwards.
891 // ServerEnvironment.tryInstallDependencies(progressMonitor);
892 // ServerEnvironment.ensureServerDependenciesMet();
894 // } catch (InstallException ie) {
895 // throw new PlatformException(ie);
896 // } catch (ExecutionEnvironmentException eee) {
897 // throw new PlatformException(eee);
898 // } catch (IOException ie) {
899 // throw new PlatformException(ie);
905 * Shutdown Simantics Platform.
907 * In SWB this is handled in SimanticsWorkbenchAdvisor#disconnectFromWorkspace.
909 * @param progressMonitor optional progress monitor
910 * @throws PlatformException
912 public void shutdown(IProgressMonitor progressMonitor) throws PlatformException
914 SubMonitor progress = SubMonitor.convert(progressMonitor, 100);
915 PlatformException platformException = null;
917 progress.subTask("Close Project");
918 if (project != null) {
919 project.safeDispose();
924 progress.subTask("Close Database Session");
925 Databoard databoard = null;
926 if (sessionContext != null) {
927 Session s = sessionContext.peekSession();
929 databoard = s.peekService(Databoard.class);
931 progress.subTask("Flushing Index Caches");
933 Simantics.flushIndexCaches(progress.newChild(20), s);
934 } catch (Throwable t) {
935 LOGGER.error("Failed to flush index caches.", t);
939 progress.subTask("Close Database Session");
940 sessionContext.safeDispose();
941 sessionContext = null;
942 Simantics.setSessionContext(null);
944 if (simanticsBindings != null) {
945 Bindings.classBindingFactory.removeFactory( simanticsBindings );
946 simanticsBindings = null;
948 if (databoard != null) {
949 if (simanticsBindings2 != null) {
950 databoard.classBindingFactory.removeFactory( simanticsBindings2 );
951 simanticsBindings2 = null;
956 // Make sure Simantics clipboard doesn't store unwanted session data references.
957 Simantics.setClipboard(new SimanticsClipboardImpl());
962 projectResource = null;
964 DependenciesRelation.assertFinishedTracking();
966 } catch (Exception e) {
967 platformException = new PlatformException("Failed to shutdown Simantics Platform", e);
971 progress.subTask("Shutting down database");
973 if (null != databasebManagement)
974 databasebManagement.shutdown();
975 } catch (Throwable t) {
976 LOGGER.error("Database shutdown failed.", t);
980 progress.subTask("Clearing Workspace Temporary Directory");
982 Simantics.clearTemporaryDirectory();
983 } catch (Throwable t) {
984 LOGGER.error("Failed to clear the temporary directory.", t);
987 if (null != platformException)
988 throw platformException;
991 // TODO: consider removing this in the future ??
993 public void stateChanged(LifecycleState newState) {
994 if(newState == LifecycleState.CLOSED) {
996 if(Platform.isRunning()) {
997 mainThread.interrupt();
1004 * @return <code>true</code> if discard was successful, <code>false</code>
1005 * if there was no session, {@link UndoRedoSupport} or
1006 * {@link UndoContext} to discard through
1008 public boolean discardSessionUndoHistory() {
1009 Session s = session;
1011 UndoRedoSupport urs = s.peekService(UndoRedoSupport.class);
1013 UndoContext uc = urs.getUndoContext(s);
1023 public void reconnect(String databaseDriverId) throws Exception {
1024 // Starts database server.
1025 SimanticsPlatform.INSTANCE.startUp(databaseDriverId, null, RecoveryPolicy.ThrowError, OntologyRecoveryPolicy.ThrowError, true, null);
1028 private void dumpPlatformBundleState() {
1029 BundleDescription[] bs = Platform.getPlatformAdmin().getState().getBundles();
1030 System.out.println("Total bundles: " + bs.length);
1031 for (BundleDescription b : bs) {
1032 System.out.format("%-80s @ %s\n", b.toString(), b.getLocation());