1 package fr.ifremer.tutti.ui.swing.updater;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 import java.io.File;
28 import java.io.IOException;
29 import java.nio.charset.StandardCharsets;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.nio.file.StandardCopyOption;
33 import java.nio.file.attribute.PosixFilePermission;
34 import java.text.SimpleDateFormat;
35 import java.util.Date;
36 import java.util.HashSet;
37 import java.util.List;
38 import java.util.Set;
39
40
41
42
43
44
45
46 public class UpdaterFileSystemPathes {
47
48 private static final String BACKUP_DIRECTORY_NAME = "OLD";
49
50 private static final String UPDATE_DIRECTORY_NAME = "NEW";
51
52 private static final String LAUNCHER_DIRECTORY_NAME = "launcher";
53
54 private static final String EMBEDDED_DIRECTORY_NAME = "embedded";
55
56 private static final String UPDATE_RUNTIME_CMD = "update_runtime";
57
58 private static final String BATCH_WINDOWS_EXTENSION = ".bat";
59
60 private static final String EXE_WINDOWS_EXTENSION = ".exe";
61
62 private static final String BATCH_UNIX_EXTENSION = ".sh";
63
64 private static final String VERSION_FILENAME = "version.appup";
65
66 private final Path baseDir;
67
68 private final boolean windowsOS;
69
70 private final String backupDate;
71
72 public UpdaterFileSystemPathes(Path baseDir) {
73 this.baseDir = baseDir;
74 this.windowsOS = System.getProperty("os.name").startsWith("Windows");
75 this.backupDate = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
76 }
77
78 public Path getUpdateDirectory() {
79 return baseDir.resolve(UPDATE_DIRECTORY_NAME);
80 }
81
82 public Path getUpdateModulePath(UpdateModule updateModule) {
83 return getUpdateDirectory().resolve(updateModule.name());
84 }
85
86 public boolean isUpdateModuleExists(UpdateModule updateModule) {
87
88 Path updateModulePath = getUpdateModulePath(updateModule);
89 return Files.isDirectory(updateModulePath);
90
91 }
92
93 public String getUpdateModuleVersion(UpdateModule updateModule) throws IOException {
94
95 Path updateModulePath = getUpdateModulePath(updateModule);
96 return getVersion(updateModulePath);
97
98 }
99
100 public Path getModulePath(UpdateModule updateModule) {
101 return baseDir.resolve(updateModule.name());
102 }
103
104 public boolean isModuleExists(UpdateModule updateModule) {
105
106 Path modulePath = getModulePath(updateModule);
107 return Files.isDirectory(modulePath);
108
109 }
110
111 public String getModuleVersion(UpdateModule updateModule) throws IOException {
112
113 Path modulePath = getModulePath(updateModule);
114 return getVersion(modulePath);
115
116 }
117
118 public Path getUpdaterScriptPath() {
119
120 String scriptFilename = UPDATE_RUNTIME_CMD + (windowsOS ? BATCH_WINDOWS_EXTENSION : BATCH_UNIX_EXTENSION);
121 return baseDir.resolve(scriptFilename);
122
123 }
124
125 public void cleanObsoleteFiles() throws IOException {
126
127 Path applicationDirectoryPath = getModulePath(UpdateModule.tutti);
128
129 if (windowsOS) {
130
131
132 DeleteHelper.deleteFiles(baseDir, "*" + BATCH_UNIX_EXTENSION);
133
134 } else {
135
136
137 DeleteHelper.deleteFiles(baseDir, "*" + BATCH_WINDOWS_EXTENSION);
138 DeleteHelper.deleteFiles(baseDir, "*" + EXE_WINDOWS_EXTENSION);
139
140 }
141
142
143 DeleteHelper.deleteFiles(applicationDirectoryPath, "*" + BATCH_UNIX_EXTENSION);
144 DeleteHelper.deleteFiles(applicationDirectoryPath, "*" + BATCH_WINDOWS_EXTENSION);
145 DeleteHelper.deleteFiles(applicationDirectoryPath, "*" + EXE_WINDOWS_EXTENSION);
146 DeleteHelper.deleteDirectory(applicationDirectoryPath.resolve(LAUNCHER_DIRECTORY_NAME));
147 DeleteHelper.deleteDirectory(applicationDirectoryPath.resolve(EMBEDDED_DIRECTORY_NAME));
148
149 }
150
151 public void makeExecutable(Path path) throws IOException {
152
153 if (!windowsOS) {
154
155 Set<PosixFilePermission> perms = new HashSet<>();
156
157 perms.add(PosixFilePermission.OWNER_READ);
158 perms.add(PosixFilePermission.OWNER_WRITE);
159 perms.add(PosixFilePermission.OWNER_EXECUTE);
160
161 perms.add(PosixFilePermission.GROUP_READ);
162 perms.add(PosixFilePermission.GROUP_WRITE);
163 perms.add(PosixFilePermission.GROUP_EXECUTE);
164
165 perms.add(PosixFilePermission.OTHERS_READ);
166 perms.add(PosixFilePermission.OTHERS_EXECUTE);
167
168 Files.setPosixFilePermissions(path, perms);
169
170 }
171
172 }
173
174 public void removeOlderBackup(UpdateModule updateModule) throws IOException {
175
176 String moduleName = updateModule.name();
177
178 Path backupDirectory = getBackupDirectory();
179
180
181 System.out.println(String.format("%s Clean backup directory %s", updateModule.getModuleLoggerName(), backupDirectory + File.separator + moduleName + "-*"));
182 DeleteHelper.deleteDirectories(backupDirectory, moduleName + "-*");
183
184 }
185
186 public void backupModule(UpdateModule updateModule, String version) throws IOException {
187
188 Path modulePath = getModulePath(updateModule);
189
190 String moduleName = updateModule.name();
191
192 Path backupDirectory = getBackupDirectory();
193
194 Path backupModulePath = backupDirectory.resolve(String.format("%s-%s-%s", moduleName, version, backupDate));
195
196 System.out.println(String.format("%s Backup old version %s from %s to %s", updateModule.getModuleLoggerName(), version, modulePath, backupModulePath));
197 move(modulePath, backupModulePath);
198
199 }
200
201 public void move(Path source, Path target) throws IOException {
202
203 Path absoluteSourcePath = source.toAbsolutePath();
204 Path absoluteTargetPath = target.toAbsolutePath();
205
206 try {
207
208 System.out.println(String.format("Try to move from %s to %s", absoluteSourcePath, absoluteTargetPath));
209 Files.move(absoluteSourcePath, absoluteTargetPath, StandardCopyOption.ATOMIC_MOVE);
210
211 } catch (IOException e) {
212
213
214 System.out.println(String.format("Try fallback install (copy then delete, atomic move is not possible from %s to %s)", source, target));
215
216 MoveHelper.move(absoluteSourcePath, absoluteTargetPath, false);
217
218 }
219
220 }
221
222 private Path getBackupDirectory() throws IOException {
223
224 Path backupDirectory = baseDir.resolve(BACKUP_DIRECTORY_NAME);
225 if (!Files.isDirectory(backupDirectory)) {
226 Files.createDirectory(backupDirectory);
227 }
228
229 return backupDirectory;
230
231 }
232
233 private String getVersion(Path path) throws IOException {
234
235
236 Path versionFile = path.resolve(VERSION_FILENAME);
237 List<String> lines = Files.readAllLines(versionFile, StandardCharsets.UTF_8);
238 if (lines == null || lines.isEmpty()) {
239 throw new IOException(versionFile.toString() + " is empty");
240 }
241 return lines.get(0);
242 }
243
244 }