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.Maps;
28  import fr.ifremer.quadrige3.core.dao.technical.Assert;
29  import fr.ifremer.quadrige3.core.security.AuthenticationInfo;
30  import fr.ifremer.quadrige3.ui.swing.ApplicationUIContext;
31  import fr.ifremer.quadrige3.ui.swing.action.AbstractMainUIAction;
32  import fr.ifremer.quadrige3.ui.swing.content.AbstractMainUIHandler;
33  import fr.ifremer.quadrige3.ui.swing.model.ProgressionUIModel;
34  import org.apache.commons.io.FileUtils;
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  import org.nuiton.jaxx.application.ApplicationTechnicalException;
38  import org.nuiton.jaxx.application.swing.action.ApplicationActionException;
39  import org.nuiton.updater.ApplicationInfo;
40  import org.nuiton.updater.ApplicationUpdaterCallback;
41  
42  import java.io.File;
43  import java.io.IOException;
44  import java.util.Map;
45  
46  import static org.nuiton.i18n.I18n.n;
47  import static org.nuiton.i18n.I18n.t;
48  
49  /**
50   * CallBack to update db.
51   *
52   * @since 2.6
53   */
54  public class DatabaseUpdaterCallBack implements ApplicationUpdaterCallback {
55  
56      /** Logger. */
57      private static final Log LOG =
58              LogFactory.getLog(DatabaseUpdaterCallBack.class);
59  
60      /** Constant <code>DB_UPDATE_NAME="db"</code> */
61      public static final String DB_UPDATE_NAME = "db";
62  
63      static {
64          n("quadrige3.update.db");
65      }
66  
67      protected final ApplicationUIContext context;
68  
69      protected final AbstractMainUIHandler handler;
70  
71      protected final ProgressionUIModel progressionModel;
72  
73      protected boolean dbInstalled;
74  
75      protected boolean dbUpdated;
76  
77      protected final AbstractMainUIAction action;
78  
79      /**
80       * <p>Constructor for DatabaseUpdaterCallBack.</p>
81       *
82       * @param action a {@link AbstractMainUIAction} object.
83       * @param progressionModel a {@link ProgressionUIModel} object.
84       */
85      public DatabaseUpdaterCallBack(AbstractMainUIAction action, ProgressionUIModel progressionModel) {
86          this.action = action;
87          this.handler = action.getHandler();
88          this.context = action.getContext();
89          this.progressionModel = progressionModel;
90      }
91  
92      /**
93       * <p>isDbUpdated.</p>
94       *
95       * @return a boolean.
96       */
97      public boolean isDbUpdated() {
98          return dbUpdated;
99      }
100 
101     /**
102      * <p>isDbInstalled.</p>
103      *
104      * @return a boolean.
105      */
106     public boolean isDbInstalled() {
107         return dbInstalled;
108     }
109 
110     /** {@inheritDoc} */
111     @Override
112     public Map<String, ApplicationInfo> updateToDo(Map<String, ApplicationInfo> appToUpdate) {
113         Map<String, ApplicationInfo> result = Maps.newHashMap();
114 
115         ApplicationInfo info = appToUpdate.get(DB_UPDATE_NAME);
116         if (info == null) {
117             dbInstalled = false;
118             dbUpdated = false;
119         } else {
120             result.put(info.name, info);
121 
122             if (info.needAuthentication) {
123 
124                 // ask auth
125                 AuthenticationInfo authenticationInfo = handler.askAuthenticationInfo(info.url);
126                 if (authenticationInfo != null) {
127                     info.setAuthentication(authenticationInfo.getLogin(), authenticationInfo.getPassword().toCharArray());
128                 }
129             }
130 
131             if (context.isDbExist()) {
132 
133                 // when db exists always an update
134                 dbUpdated = true;
135             } else {
136 
137                 // when no db, then always install
138                 dbInstalled = true;
139             }
140         }
141 
142         return result;
143     }
144 
145     /** {@inheritDoc} */
146     @Override
147     public void startUpdate(ApplicationInfo info) {
148 
149         if (dbInstalled) {
150             progressionModel.setMessage(t("quadrige3.applicationUpdater.startUpdate.db.installation", info.newVersion));
151         } else if (dbUpdated) {
152             progressionModel.setMessage(t("quadrige3.applicationUpdater.startUpdate.db.update", info.newVersion));
153         }
154     }
155 
156     /** {@inheritDoc} */
157     @Override
158     public void updateDone(Map<String, ApplicationInfo> appToUpdate,
159                            Map<String, Exception> appUpdateError) {
160 
161         ApplicationInfo info = appToUpdate.get(DB_UPDATE_NAME);
162         Exception error = appUpdateError.get(DB_UPDATE_NAME);
163         if (error != null) {
164 
165             // something bad while updating db
166             if (LOG.isErrorEnabled()) {
167                 LOG.error("Could not update db", error);
168             }
169             String errorMessage;
170             if (info != null && info.needAuthentication) {
171                 errorMessage = t("quadrige3.updateDb.error.with.auth");
172             } else {
173                 errorMessage = t("quadrige3.updateDb.error.with.noauth");
174             }
175             throw ApplicationActionException.propagateError(
176                     action, new ApplicationTechnicalException(errorMessage, error));
177         } else if (info != null) {
178 
179             if (LOG.isInfoEnabled()) {
180                 LOG.info(String.format(
181                         "A db update was downloaded (oldVersion: %s, newVersion: %s), will process it.",
182                         info.oldVersion, info.newVersion));
183             }
184 
185             if (dbInstalled) {
186 
187                 // first database, just copy it to correct directory
188                 prepareFirstDatabase(info);
189             }
190         }
191     }
192 
193     /** {@inheritDoc} */
194     @Override
195     public void aborted(String propertiesURL, Exception eee) {
196         if (LOG.isErrorEnabled()) {
197             LOG.error("Could not update from " + propertiesURL, eee);
198         }
199         throw ApplicationActionException.propagateError(action, eee);
200     }
201 
202     /**
203      * <p>getDbDirectory.</p>
204      *
205      * @param info a {@link ApplicationInfo} object.
206      * @return a {@link File} object.
207      */
208     protected File getDbDirectory(ApplicationInfo info) {
209         File[] sources = info.destDir.listFiles();
210         Assert.state(
211                 sources != null && sources.length == 1,
212                 "Downloaded db should contains one directory at " + info.destDir);
213         return sources[0];
214     }
215 
216     /**
217      * <p>prepareFirstDatabase.</p>
218      *
219      * @param info a {@link ApplicationInfo} object.
220      */
221     protected void prepareFirstDatabase(ApplicationInfo info) {
222         if (LOG.isInfoEnabled()) {
223             LOG.info("First time database was downloaded at version: " + info.newVersion);
224         }
225         File source = getDbDirectory(info);
226         File target = context.getConfiguration().getDbDirectory();
227         if (LOG.isInfoEnabled()) {
228             LOG.info(String.format("Copy from [%s] to [%s]", source , target));
229         }
230         try {
231             FileUtils.copyDirectory(source, target);
232         } catch (IOException e) {
233             throw new ApplicationTechnicalException(t("quadrige3.applicationUpdater.prepareFirstDB.copyDirectory.error", source, target), e);
234         }
235         try {
236             FileUtils.deleteDirectory(source.getParentFile());
237         } catch (IOException e) {
238             throw new ApplicationTechnicalException(t("quadrige3.applicationUpdater.prepareFirstDB.deleteDirectory.error", target), e);
239         }
240     }
241 }