View Javadoc
1   package fr.ifremer.tutti.ui.swing.updater;
2   
3   /*
4    * #%L
5    * Tutti :: UI Updater
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2012 - 2015 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU General Public License as
13   * published by the Free Software Foundation, either version 3 of the
14   * License, or (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public
22   * License along with this program.  If not, see
23   * <http://www.gnu.org/licenses/gpl-3.0.html>.
24   * #L%
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   * Created on 1/27/15.
42   *
43   * @author Tony Chemit - chemit@codelutin.com
44   * @since 3.13
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             // Delete linux files
132             DeleteHelper.deleteFiles(baseDir, "*" + BATCH_UNIX_EXTENSION);
133 
134         } else {
135 
136             // Delete Windows files
137             DeleteHelper.deleteFiles(baseDir, "*" + BATCH_WINDOWS_EXTENSION);
138             DeleteHelper.deleteFiles(baseDir, "*" + EXE_WINDOWS_EXTENSION);
139 
140         }
141 
142         // Delete embedded files
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             //add owners permission
157             perms.add(PosixFilePermission.OWNER_READ);
158             perms.add(PosixFilePermission.OWNER_WRITE);
159             perms.add(PosixFilePermission.OWNER_EXECUTE);
160             //add group permissions
161             perms.add(PosixFilePermission.GROUP_READ);
162             perms.add(PosixFilePermission.GROUP_WRITE);
163             perms.add(PosixFilePermission.GROUP_EXECUTE);
164             //add others permissions
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         // Remove older backup
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             // copy atomic impossible
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         // Return the version of a module from version.appup file
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 }