]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics/src/org/simantics/DatabaseBaselines.java
More sequence terminal relations
[simantics/platform.git] / bundles / org.simantics / src / org / simantics / DatabaseBaselines.java
1 package org.simantics;
2
3 import java.io.IOException;
4 import java.nio.file.Files;
5 import java.nio.file.Path;
6 import java.nio.file.Paths;
7 import java.time.Instant;
8 import java.time.ZoneId;
9 import java.time.format.DateTimeFormatter;
10 import java.util.List;
11 import java.util.stream.Collectors;
12 import java.util.zip.ZipEntry;
13 import java.util.zip.ZipFile;
14 import java.util.zip.ZipOutputStream;
15
16 import org.simantics.utils.FileUtils;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 /**
21  * @author Tuukka Lehtonen
22  * @since 1.34.0
23  */
24 public class DatabaseBaselines {
25
26         private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseBaselines.class);
27
28         private static final boolean REQUIRE_INDEX_IN_BASELINE = false;
29         
30         private static final String DB_DIRECTORY = "db"; //$NON-NLS-1$
31         private static final String INDEX_DIRECTORY = ".metadata/.plugins/org.simantics.db.indexing"; //$NON-NLS-1$
32
33         private static final DateTimeFormatter TIMESTAMP_FORMAT = DateTimeFormatter.ofPattern("d. MMM yyyy HH:mm:ss");
34
35         public static Path packageBaseline(Path fromWorkspace, Path packageFile) throws IOException {
36                 return compressZip(fromWorkspace, collectBaselinePaths(fromWorkspace), packageFile);
37         }
38
39         private static List<Path> collectBaselinePaths(Path workspace) throws IOException {
40                 Path dbPath = workspace.resolve(DB_DIRECTORY);
41                 Path indexPath = workspace.resolve(INDEX_DIRECTORY);
42
43                 if (!Files.isDirectory(dbPath))
44                         throw new IllegalArgumentException("workspace database directory " + dbPath + " does not exist");
45
46                 List<Path> paths = Files.walk(dbPath).collect(Collectors.toList());
47                 if (Files.isDirectory(indexPath)) {
48                         List<Path> indexPaths = Files.walk(indexPath).collect(Collectors.toList());
49                         paths.addAll(indexPaths);
50                 } else {
51                         if (REQUIRE_INDEX_IN_BASELINE)
52                                 throw new IllegalArgumentException("workspace database index directory " + indexPath + " does not exist");
53                 }
54                 return paths;
55         }
56
57         private static Path compressZip(Path relativeRoot, List<Path> paths, Path zipFile) throws IOException {
58                 if (LOGGER.isDebugEnabled())
59                         LOGGER.debug("Compressing " + paths.size() + " path entries into ZIP file " + zipFile);
60                 try (ZipOutputStream zout = new ZipOutputStream(Files.newOutputStream(zipFile))) {
61                         compressZip(relativeRoot, zout, paths);
62                         return zipFile;
63                 } finally {
64                         if (LOGGER.isDebugEnabled())
65                                 LOGGER.debug("Compressed " + paths.size() + " entries into " + zipFile);
66                 }
67         }
68
69         private static void compressZip(Path relativeRoot, ZipOutputStream zout, List<Path> paths) throws IOException {
70                 for (Path p : paths) {
71                         Path rp = relativeRoot.relativize(p);
72                         String name = rp.toString();
73                         if (Files.isDirectory(p)) {
74                                 name = name.endsWith("/") ? name : name + "/";
75                                 zout.putNextEntry(new ZipEntry(name));
76                         } else {
77                                 zout.putNextEntry(new ZipEntry(name));
78                                 FileUtils.copy(p.toFile(), zout);
79                                 zout.closeEntry();
80                         }
81                 }
82         }
83
84         public static byte[] baselineIndicatorContents(Path path) throws IOException {
85                 return String.format("%s%n%s%n",
86                                 path.toString(),
87                                 Instant.now().atZone(ZoneId.systemDefault()).format(TIMESTAMP_FORMAT))
88                                 .getBytes("UTF-8");
89         }
90
91         public static void validateWorkspaceForBaselineInitialization(Path workspaceLocation) throws PlatformException {
92                 try {
93                         Path db = workspaceLocation.resolve(DB_DIRECTORY);
94                         if (Files.exists(db))
95                                 throw new PlatformException("Database location " + db + " already exists. Cannot re-initialize workspace from baseline.");
96                         if (REQUIRE_INDEX_IN_BASELINE) {
97                                 Path index = workspaceLocation.resolve(INDEX_DIRECTORY);
98                                 if (Files.exists(index) || !isEmptyDirectory(index))
99                                         throw new PlatformException("Index location " + index + " already exists. Cannot re-initialize workspace from baseline.");
100                         }
101                 } catch (IOException e) {
102                         throw new PlatformException("Failed to validate workspace for baseline initialization", e);
103                 }
104         }
105
106         private static boolean isEmptyDirectory(Path dir) throws IOException {
107                 return Files.walk(dir).count() == 1;
108         }
109
110         public static void validateBaselineFile(Path baseline) throws PlatformException {
111                 try (ZipFile zip = new ZipFile(baseline.toFile())) {
112                         ZipEntry db = zip.getEntry(DB_DIRECTORY);
113                         if (db == null)
114                                 throw new PlatformException("Baseline archive does not contain database directory '" + DB_DIRECTORY + "'");
115
116                         if (REQUIRE_INDEX_IN_BASELINE) {
117                                 ZipEntry index = zip.getEntry(INDEX_DIRECTORY);
118                                 if (index == null)
119                                         throw new PlatformException("Baseline archive does not contain database index directory '" + INDEX_DIRECTORY + "'");
120                         }
121                 } catch (IOException e) {
122                         throw new PlatformException("Failed to validate baseline archive " + baseline, e);
123                 }
124         }
125
126         public static void initializeWorkspaceWithBaseline(Path baseline, Path workspaceLocation, Path indicatorPath) throws PlatformException {
127                 try {
128                         Files.createDirectories(workspaceLocation);
129                         FileUtils.extractZip(baseline.toFile(), workspaceLocation.toFile());
130                         if (indicatorPath != null)
131                                 Files.write(indicatorPath, DatabaseBaselines.baselineIndicatorContents(indicatorPath));
132                 } catch (IOException e) {
133                         throw new PlatformException(e);
134                 }
135         }
136
137         public static void main(String[] args) throws IOException {
138                 packageBaseline(Paths.get("D:/temp/desktop/workspace"), Paths.get("d:/temp/desktop/workspace/baseline.zip"));
139         }
140
141 }