View Javadoc
1   package fr.ifremer.quadrige3.ui.swing.callback;
2   
3   /*-
4    * #%L
5    * Quadrige3 Core :: Quadrige3 UI Common
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2017 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (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 Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  
27  import com.google.common.collect.Lists;
28  import com.google.common.collect.Maps;
29  import fr.ifremer.quadrige3.ui.swing.ApplicationUIContext;
30  import fr.ifremer.quadrige3.ui.swing.action.AbstractAction;
31  import fr.ifremer.quadrige3.ui.swing.model.ProgressionUIModel;
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.nuiton.jaxx.application.ApplicationIOUtil;
35  import org.nuiton.jaxx.application.ApplicationTechnicalException;
36  import org.nuiton.jaxx.application.swing.action.ApplicationActionException;
37  import org.nuiton.updater.ApplicationInfo;
38  
39  import java.io.File;
40  import java.util.List;
41  import java.util.Map;
42  
43  import static org.nuiton.i18n.I18n.n;
44  import static org.nuiton.i18n.I18n.t;
45  
46  /**
47   * CallBack to update jre, application, i18n.
48   *
49   * @since 1.0
50   */
51  public class ApplicationUpdaterCallBack implements org.nuiton.updater.ApplicationUpdaterCallback {
52  
53      /** Logger. */
54      private static final Log LOG = LogFactory.getLog(ApplicationUpdaterCallBack.class);
55  
56      public enum UpdateType {
57          LAUNCHER(n("quadrige3.update.launcher")),
58          JRE(n("quadrige3.update.jre")),
59          APPLICATION(n("quadrige3.update.application")),
60          I18N(n("quadrige3.update.i18n")),
61          HELP(n("quadrige3.update.help"));
62  
63          private final String i18nKey;
64  
65          UpdateType(String i18nKey) {
66              this.i18nKey = i18nKey;
67          }
68  
69          public String getLabel() {
70              return t(i18nKey);
71          }
72      }
73  
74      protected final ApplicationUIContext context;
75  
76      protected List<UpdateType> types;
77  
78      protected final ProgressionUIModel progressionModel;
79  
80      protected boolean applicationUpdated;
81  
82      protected final AbstractAction<?, ?, ?> action;
83  
84      /**
85       * <p>Constructor for ApplicationUpdaterCallBack.</p>
86       *
87       * @param action a {@link AbstractAction} object.
88       * @param progressionModel a {@link ProgressionUIModel} object.
89       */
90      public ApplicationUpdaterCallBack(AbstractAction<?, ?, ?> action, ProgressionUIModel progressionModel) {
91          this.action = action;
92          this.context = action.getContext();
93          this.progressionModel = progressionModel;
94      }
95  
96      /**
97       * <p>Setter for the field <code>types</code>.</p>
98       *
99       * @param types a {@link ApplicationUpdaterCallBack.UpdateType} object.
100      */
101     public void setTypes(UpdateType... types) {
102         this.types = Lists.newArrayList(types);
103     }
104 
105     /**
106      * <p>isApplicationUpdated.</p>
107      *
108      * @return a boolean.
109      */
110     public boolean isApplicationUpdated() {
111         return applicationUpdated;
112     }
113 
114     /** {@inheritDoc} */
115     @Override
116     public Map<String, ApplicationInfo> updateToDo(Map<String, ApplicationInfo> appToUpdate) {
117         Map<String, ApplicationInfo> result = Maps.newHashMap();
118 
119         for (UpdateType type : types) {
120             ApplicationInfo info = getInfo(type, appToUpdate);
121             if (info != null) {
122                 result.put(info.name, info);
123             }
124         }
125         return result;
126     }
127 
128     /** {@inheritDoc} */
129     @Override
130     public void startUpdate(ApplicationInfo info) {
131         if (UpdateType.LAUNCHER.name().toLowerCase().equals(info.name)) {
132             progressionModel.setMessage(t("quadrige3.applicationUpdater.startUpdate.launcher", info.newVersion));
133         }
134 
135         if (UpdateType.JRE.name().toLowerCase().equals(info.name)) {
136             progressionModel.setMessage(t("quadrige3.applicationUpdater.startUpdate.jre", info.newVersion));
137         }
138 
139         if (UpdateType.APPLICATION.name().toLowerCase().equals(info.name)) {
140             progressionModel.setMessage(t("quadrige3.applicationUpdater.startUpdate.application", info.newVersion));
141         }
142 
143         if (UpdateType.I18N.name().toLowerCase().equals(info.name)) {
144             progressionModel.setMessage(t("quadrige3.applicationUpdater.startUpdate.i18n", info.newVersion));
145         }
146         if (UpdateType.HELP.name().toLowerCase().equals(info.name)) {
147             progressionModel.setMessage(t("quadrige3.applicationUpdater.startUpdate.help", info.newVersion));
148         }
149     }
150 
151     /** {@inheritDoc} */
152     @Override
153     public void updateDone(Map<String, ApplicationInfo> appToUpdate,
154                            Map<String, Exception> appUpdateError) {
155 
156         boolean updateLauncher = updateDoneLauncher(appToUpdate, appUpdateError);
157         boolean updateJRE = updateDoneJre(appToUpdate, appUpdateError);
158         boolean updateApplication = updateDoneApplication(appToUpdate, appUpdateError);
159         boolean updateI18n = updateDoneI18n(appToUpdate, appUpdateError);
160         boolean updateHelp = updateDoneHelp(appToUpdate, appUpdateError);
161 
162         boolean doRestart = updateLauncher || updateJRE || updateApplication || updateI18n || updateHelp;
163 
164         if (doRestart) {
165             applicationUpdated = true;
166         }
167     }
168 
169     /** {@inheritDoc} */
170     @Override
171     public void aborted(String propertiesURL, Exception eee) {
172         if (LOG.isErrorEnabled()) {
173             LOG.error("Could not update from " + propertiesURL, eee);
174         }
175         throw ApplicationActionException.propagateError(action, eee);
176     }
177 
178     /**
179      * <p>updateDoneLauncher.</p>
180      *
181      * @param appToUpdate a {@link Map} object.
182      * @param appUpdateError a {@link Map} object.
183      * @return a boolean.
184      */
185     protected boolean updateDoneLauncher(Map<String, ApplicationInfo> appToUpdate, Map<String, Exception> appUpdateError) {
186 
187         boolean doRestart = false;
188         Exception error = getError(UpdateType.LAUNCHER, appUpdateError);
189         if (error != null) {
190 
191             // something bad while updating launcher
192             throw ApplicationActionException.propagateError(
193                     action, new ApplicationTechnicalException(t("quadrige3.applicationUpdater.launcher.error"), error));
194         } else {
195             ApplicationInfo info = getInfo(UpdateType.LAUNCHER, appToUpdate);
196             if (info != null) {
197 
198                 if (LOG.isInfoEnabled()) {
199                     LOG.info(String.format(
200                             "A launcher update was downloaded (oldVersion: %s, newVersion: %s), will restart application to use it",
201                             info.oldVersion, info.newVersion));
202                 }
203                 doRestart = true;
204             }
205         }
206         return doRestart;
207 
208     }
209 
210     /**
211      * <p>updateDoneJre.</p>
212      *
213      * @param appToUpdate a {@link Map} object.
214      * @param appUpdateError a {@link Map} object.
215      * @return a boolean.
216      */
217     protected boolean updateDoneJre(Map<String, ApplicationInfo> appToUpdate,
218                                     Map<String, Exception> appUpdateError) {
219         boolean doRestart = false;
220         Exception error = getError(UpdateType.JRE, appUpdateError);
221         if (error != null) {
222 
223             // something bad while updating jre
224             throw ApplicationActionException.propagateError(
225                     action, new ApplicationTechnicalException(t("quadrige3.applicationUpdater.jre.error"), error));
226         }
227         ApplicationInfo info = getInfo(UpdateType.JRE, appToUpdate);
228         if (info != null) {
229             if (LOG.isInfoEnabled()) {
230                 LOG.info(String.format(
231                         "A jre update was downloaded (oldVersion: %s, newVersion: %s), will restart application to use it",
232                         info.oldVersion, info.newVersion));
233             }
234             doRestart = true;
235         }
236         return doRestart;
237     }
238 
239     /**
240      * <p>updateDoneApplication.</p>
241      *
242      * @param appToUpdate a {@link Map} object.
243      * @param appUpdateError a {@link Map} object.
244      * @return a boolean.
245      */
246     protected boolean updateDoneApplication(Map<String, ApplicationInfo> appToUpdate,
247                                             Map<String, Exception> appUpdateError) {
248         boolean doRestart = false;
249         Exception error = getError(UpdateType.APPLICATION, appUpdateError);
250         if (error != null) {
251 
252             // something bad while updating application
253             throw ApplicationActionException.propagateError(
254                     action, new ApplicationTechnicalException(t("quadrige3.applicationUpdater.application.error"), error));
255         }
256         ApplicationInfo info = getInfo(UpdateType.APPLICATION, appToUpdate);
257         if (info != null) {
258 
259             if (LOG.isInfoEnabled()) {
260                 LOG.info(String.format(
261                         "A application update was downloaded (oldVersion: %s, newVersion: %s), will restart application to use it",
262                         info.oldVersion, info.newVersion));
263             }
264             doRestart = true;
265 
266             //FIXME-check this is necessary: i18n is no more generated ?
267             // must also remove i18n directory
268             File i18nDirectory = context.getConfiguration().getI18nDirectory();
269             ApplicationIOUtil.forceDeleteOnExit(
270                     i18nDirectory,
271                     t("quadrige3.applicationUpdater.updateDone.deleteDirectory.i18n.error", i18nDirectory)
272             );
273 
274             // must remove db cache directory
275             File cacheDirectory = context.getConfiguration().getCacheDirectory();
276             ApplicationIOUtil.forceDeleteOnExit(
277                     cacheDirectory,
278                     t("quadrige3.applicationUpdater.updateDone.deleteDirectory.caches.error", cacheDirectory)
279             );
280         }
281         return doRestart;
282     }
283 
284     /**
285      * <p>updateDoneI18n.</p>
286      *
287      * @param appToUpdate a {@link Map} object.
288      * @param appUpdateError a {@link Map} object.
289      * @return a boolean.
290      */
291     protected boolean updateDoneI18n(Map<String, ApplicationInfo> appToUpdate,
292                                      Map<String, Exception> appUpdateError) {
293         boolean doRestart = false;
294         Exception error = getError(UpdateType.I18N, appUpdateError);
295         if (error != null) {
296 
297             // something bad while updating i18n
298             throw ApplicationActionException.propagateError(
299                     action, new ApplicationTechnicalException(t("quadrige3.applicationUpdater.i18n.error"), error));
300         }
301         ApplicationInfo info = getInfo(UpdateType.I18N, appToUpdate);
302         if (info != null) {
303 
304             if (LOG.isInfoEnabled()) {
305                 LOG.info(String.format(
306                         "A i18n update was downloaded (oldVersion: %s, newVersion: %s), will restart application to use it",
307                         info.oldVersion, info.newVersion));
308             }
309             doRestart = true;
310         }
311         return doRestart;
312     }
313 
314     /**
315      * <p>updateDoneHelp.</p>
316      *
317      * @param appToUpdate a {@link Map} object.
318      * @param appUpdateError a {@link Map} object.
319      * @return a boolean.
320      */
321     protected boolean updateDoneHelp(Map<String, ApplicationInfo> appToUpdate,
322                                      Map<String, Exception> appUpdateError) {
323         boolean doRestart = false;
324         Exception error = getError(UpdateType.HELP, appUpdateError);
325         if (error != null) {
326 
327             // something bad while updating help
328             throw ApplicationActionException.propagateError(
329                     action, new ApplicationTechnicalException(t("quadrige3.applicationUpdater.help.error"), error));
330         }
331         ApplicationInfo info = getInfo(UpdateType.HELP, appToUpdate);
332         if (info != null) {
333 
334             if (LOG.isInfoEnabled()) {
335                 LOG.info(String.format(
336                         "A help update was downloaded (oldVersion: %s, newVersion: %s), will restart application to use it",
337                         info.oldVersion, info.newVersion));
338             }
339             doRestart = true;
340         }
341         return doRestart;
342     }
343 
344     /**
345      * <p>getInfo.</p>
346      *
347      * @param type a {@link ApplicationUpdaterCallBack.UpdateType} object.
348      * @param appToUpdate a {@link Map} object.
349      * @return a {@link ApplicationInfo} object.
350      */
351     protected ApplicationInfo getInfo(UpdateType type, Map<String, ApplicationInfo> appToUpdate) {
352         return appToUpdate.get(type.name().toLowerCase());
353     }
354 
355     /**
356      * <p>getError.</p>
357      *
358      * @param type a {@link ApplicationUpdaterCallBack.UpdateType} object.
359      * @param appUpdateError a {@link Map} object.
360      * @return a {@link Exception} object.
361      */
362     protected Exception getError(UpdateType type, Map<String, Exception> appUpdateError) {
363         return appUpdateError.get(type.name().toLowerCase());
364     }
365 }