import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IProduct;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.ini4j.Ini;
import org.ini4j.InvalidFileFormatException;
+import org.simantics.SimanticsPlatform.OntologyRecoveryPolicy;
+import org.simantics.SimanticsPlatform.RecoveryPolicy;
import org.simantics.databoard.Bindings;
import org.simantics.databoard.Databoard;
import org.simantics.datatypes.literal.Font;
resetDatabase(monitor);
}
+ public boolean handleBaselineDatabase() throws PlatformException {
+ Path workspaceLocation = Platform.getLocation().toFile().toPath();
+ Path baselineIndicatorFile = workspaceLocation.resolve(".baselined");
+ if (Files.isRegularFile(baselineIndicatorFile)) {
+ // This means that the workspace has already been initialized from
+ // a database baseline and further initialization is not necessary.
+ return true;
+ }
+
+ String dbBaselineArchive = System.getProperty("org.simantics.db.baseline", null);
+ if (dbBaselineArchive == null)
+ return false;
+
+ Path baseline = Paths.get(dbBaselineArchive);
+ if (!Files.isRegularFile(baseline))
+ throw new PlatformException("Specified database baseline archive " + baseline + " does not exist. Cannot initialize workspace database.");
+
+ validateBaselineFile(baseline);
+ validateWorkspaceForBaselineInitialization(workspaceLocation);
+
+ try {
+ Files.createDirectories(workspaceLocation);
+ FileUtils.extractZip(baseline.toFile(), workspaceLocation.toFile());
+ Files.write(baselineIndicatorFile, baselineIndicatorContents(baselineIndicatorFile));
+ return true;
+ } catch (IOException e) {
+ throw new PlatformException(e);
+ }
+ }
+
+ private static final DateTimeFormatter TIMESTAMP_FORMAT = DateTimeFormatter.ofPattern("d. MMM yyyy HH:mm:ss");
+
+ private static byte[] baselineIndicatorContents(Path path) throws IOException {
+ return String.format("%s%n%s%n",
+ path.toString(),
+ Instant.now().atZone(ZoneId.systemDefault()).format(TIMESTAMP_FORMAT))
+ .getBytes("UTF-8");
+ }
+
+ private void validateWorkspaceForBaselineInitialization(Path workspaceLocation) throws PlatformException {
+ try {
+ Path db = workspaceLocation.resolve("db");
+ if (Files.exists(db))
+ throw new PlatformException("Database location " + db + " already exists. Cannot re-initialize workspace from baseline.");
+ Path index = workspaceLocation.resolve(".metadata/.plugins/org.simantics.db.indexing");
+ if (!Files.exists(index) || !isEmptyDirectory(index))
+ throw new PlatformException("Index location " + index + " already exists. Cannot re-initialize workspace from baseline.");
+ } catch (IOException e) {
+ throw new PlatformException("Failed to validate workspace for baseline initialization", e);
+ }
+ }
+
+ private static boolean isEmptyDirectory(Path dir) throws IOException {
+ return Files.walk(dir).count() == 1;
+ }
+
+ private void validateBaselineFile(Path baseline) throws PlatformException {
+ try (ZipFile zip = new ZipFile(baseline.toFile())) {
+ ZipEntry db = zip.getEntry("db");
+ if (db == null)
+ throw new PlatformException("Baseline archive does not contain database directory 'db'");
+ ZipEntry index = zip.getEntry(".metadata/.plugins/org.simantics.db.indexing");
+ if (index == null)
+ throw new PlatformException("Baseline archive does not contain database index directory '.metadata/.plugins/org.simantics.db.indexing'");
+ } catch (IOException e) {
+ throw new PlatformException("Failed to validate baseline archive " + baseline, e);
+ }
+ }
+
/**
* Start-up the platform. The procedure consists of 8 steps. Once everything
* is up and running, all fields are set property.
// 0.2 Clear VariableRepository.repository static map which holds references to SessionImplDb
VariableRepository.clear();
+ // 0.3 Handle baseline database before opening db
+ boolean usingBaseline = handleBaselineDatabase();
+
// 1. Assert there is a database at <workspace>/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");
+ if(!usingBaseline) {
+ synchronizeOntologies(progressMonitor, ontologyPolicy, requireSynchronize);
+ TimeLogger.log("Synchronized ontologies");
+ }
// 4. Assert simantics.cfg exists
boolean installProject = assertConfiguration(progressMonitor,workspacePolicy);
try {
// Construct and initialize SessionContext from Session.
SessionContext sessionContext = SessionContext.create(session, init);
- if (init)
+ TimeLogger.log("Session context created");
+ if (init) {
sessionContext.registerServices();
+ TimeLogger.log("Session services registered");
+ }
return sessionContext;
} catch (DatabaseException e) {
throw new PlatformException(e);