View Javadoc
1   package fr.ifremer.tutti.ui.swing.content.db.actions;
2   
3   /*
4    * #%L
5    * Tutti :: UI
6    * %%
7    * Copyright (C) 2012 - 2014 Ifremer
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the 
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public 
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
23   */
24  
25  import fr.ifremer.tutti.TuttiConfiguration;
26  import fr.ifremer.tutti.persistence.ProgressionModel;
27  import fr.ifremer.tutti.persistence.TuttiPersistence;
28  import fr.ifremer.tutti.persistence.service.UpdateSchemaContextSupport;
29  import fr.ifremer.tutti.ui.swing.TuttiScreen;
30  import fr.ifremer.tutti.ui.swing.content.actions.AbstractChangeScreenAction;
31  import fr.ifremer.tutti.ui.swing.content.MainUIHandler;
32  import fr.ifremer.tutti.ui.swing.update.TuttiDbUpdaterCallBack;
33  import fr.ifremer.tutti.ui.swing.update.Updates;
34  import fr.ifremer.tutti.ui.swing.util.AbstractTuttiUIHandler;
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  import org.nuiton.jaxx.application.ApplicationBusinessException;
38  import org.nuiton.jaxx.application.swing.action.ApplicationUIAction;
39  import org.nuiton.updater.ApplicationInfo;
40  import org.nuiton.version.Version;
41  
42  import javax.swing.JOptionPane;
43  import java.io.File;
44  import java.util.Date;
45  
46  import static org.nuiton.i18n.I18n.t;
47  
48  /**
49   * To open existing db.
50   *
51   * @author Tony Chemit - chemit@codelutin.com
52   * @since 1.0
53   */
54  public class OpenDbAction extends AbstractChangeScreenAction {
55  
56      /** Logger. */
57      private static final Log log = LogFactory.getLog(OpenDbAction.class);
58  
59      protected UpdateSchemaContext updateSchemaContext;
60  
61      protected boolean updateReferentiel;
62  
63      protected String jdbcUrl;
64  
65      protected ApplicationInfo updateDbVersion;
66  
67      public OpenDbAction(MainUIHandler handler) {
68          super(handler, true, TuttiScreen.SELECT_CRUISE);
69          setActionDescription(t("tutti.dbManager.action.openDb.tip"));
70      }
71  
72      public void setUpdateReferentiel(boolean updateReferentiel) {
73          this.updateReferentiel = updateReferentiel;
74      }
75  
76      @Override
77      public boolean prepareAction() throws Exception {
78  
79          boolean canContinue = super.prepareAction();
80          if (canContinue) {
81  
82              jdbcUrl = null;
83              updateSchemaContext = null;
84              updateDbVersion = null;
85  
86              updateReferentiel &= getContext().checkUpdateDataReachable(false);
87  
88              if (updateReferentiel) {
89  
90                  // get the next db version
91                  updateDbVersion = Updates.getDatabaseUpdateVersion(getConfig());
92  
93                  if (updateDbVersion != null && updateDbVersion.newVersion != null) {
94  
95                      // ask user if it wants to do the update
96                      String htmlMessage = String.format(
97                              AbstractTuttiUIHandler.CONFIRMATION_FORMAT,
98                              t("tutti.dbManager.updatedb.found", updateDbVersion.newVersion),
99                              t("tutti.common.askBeforeUpdate.help"));
100                     int i = JOptionPane.showConfirmDialog(
101                             getHandler().getTopestUI(),
102                             htmlMessage,
103                             t("tutti.dbManager.title.confirm.updatedb"),
104                             JOptionPane.OK_CANCEL_OPTION,
105                             JOptionPane.QUESTION_MESSAGE);
106 
107                     updateReferentiel = i == JOptionPane.OK_OPTION;
108                 }
109 
110             }
111         }
112         return canContinue;
113     }
114 
115     public class UpdateSchemaContext extends UpdateSchemaContextSupport {
116 
117         private boolean closeDb;
118 
119         private File file;
120 
121         private final File dbBackupDirectory;
122 
123         public UpdateSchemaContext(File dbBackupDirectory) {
124             this.dbBackupDirectory = dbBackupDirectory;
125         }
126 
127         @Override
128         protected boolean askUserToMigrate(Version schemaVersion, Version schemaVersionIfUpdate) {
129 
130             // database schema need to migrate
131             // ask user to migrate or not (if not will close db)
132 
133             // ask user where to backup db
134 
135             String message = t("tutti.dbManager.action.upgradeDb.schema.to.update.message", schemaVersion, schemaVersionIfUpdate);
136 
137             String htmlMessage = String.format(
138                     AbstractTuttiUIHandler.CONFIRMATION_FORMAT,
139                     message,
140                     t("tutti.dbManager.action.upgradeDb.schema.to.update.message.help"));
141 
142             int i = JOptionPane.showConfirmDialog(
143                     getHandler().getTopestUI(),
144                     htmlMessage,
145                     t("tutti.dbManager.title.schema.toupdate"),
146                     JOptionPane.OK_CANCEL_OPTION,
147                     JOptionPane.QUESTION_MESSAGE);
148 
149             boolean continueAction = i == JOptionPane.OK_OPTION;
150 
151             if (continueAction) {
152 
153                 // ask user file where to backup db
154 
155                 file = saveFile(
156                         dbBackupDirectory,
157                         "tutti-db-" + ExportDbAction.df.format(new Date()),
158                         "zip",
159                         t("tutti.dbManager.title.choose.dbBackupFile"),
160                         t("tutti.dbManager.action.chooseDbBackupFile"),
161                         "^.*\\.zip", t("tutti.common.file.zip")
162                 );
163 
164                 if (file == null) {
165 
166                     // won't migrate db
167                     closeDb = true;
168                     continueAction = false;
169 
170                     displayWarningMessage(
171                             t("tutti.dbManager.title.choose.dbBackupFile"),
172                             t("tutti.dbManager.action.upgradeDb.no.backup.db.choosen")
173                     );
174                 } else {
175 
176                     continueAction = true;
177                 }
178             } else {
179 
180                 //close db
181                 closeDb = true;
182             }
183 
184             return continueAction;
185 
186         }
187 
188         @Override
189         public void init(Version schemaVersion, Version schemaVersionIfUpdate) {
190 
191             super.init(schemaVersion, schemaVersionIfUpdate);
192 
193 
194             if (isSchemaVersionTooHigh()) {
195 
196                 // database schema version is higher than application one
197                 displayWarningMessage(
198                         t("tutti.dbManager.title.schema.toupdate"),
199                         t("tutti.dbManager.action.upgradeDb.schema.not.update.message", schemaVersion, schemaVersionIfUpdate)
200                 );
201 
202             }
203 
204         }
205 
206         public boolean isCloseDb() {
207             return closeDb;
208         }
209 
210         public File getFile() {
211             return file;
212         }
213     }
214 
215     @Override
216     public void doAction() throws Exception {
217 
218         if (log.isDebugEnabled()) {
219             log.debug("Will open db...");
220         }
221 
222         jdbcUrl = getConfig().getJdbcUrl();
223 
224         // at the beginning 3 steps (open db + check version + check db context)
225         ProgressionModel progressionModel = new ProgressionModel();
226         setProgressionModel(progressionModel);
227         progressionModel.setTotal(3 + (updateReferentiel ? 1 : 0));
228 
229         // ------------------------------------------------------------------ //
230         // --- open db                                                        //
231         // ------------------------------------------------------------------ //
232 
233         progressionModel.increments(t("tutti.openDb.step.open", jdbcUrl));
234         try {
235             getContext().openPersistenceService();
236         } catch (Exception e) {
237 
238             if (log.isErrorEnabled()) {
239                 log.error("Could not open db", e);
240             }
241             // no more db
242             getContext().closePersistenceService();
243 
244             // could not load db
245             throw new ApplicationBusinessException(t("tutti.dbManager.action.openDb.couldNotOpen"));
246         }
247 
248         // ------------------------------------------------------------------ //
249         // --- check schema version                                           //
250         // ------------------------------------------------------------------ //
251 
252         progressionModel.increments(t("tutti.openDb.step.checkSchemaVersion"));
253 
254         TuttiPersistence persistenceService = getContext().getPersistenceService();
255 
256         TuttiConfiguration config = getConfig();
257 
258         updateSchemaContext = new UpdateSchemaContext(config.getDbBackupDirectory());
259         persistenceService.prepareUpdateSchemaContext(updateSchemaContext);
260 
261         Version schemaVersion = updateSchemaContext.getSchemaVersion();
262 
263         if (log.isInfoEnabled()) {
264             log.info("Detected database version: " + schemaVersion);
265         }
266         Version schemaVersionIfUpdate = updateSchemaContext.getSchemaVersionIfUpdate();
267 
268         if (log.isInfoEnabled()) {
269             log.info("Detected schema application version:" + schemaVersionIfUpdate);
270         }
271 
272         boolean updateSchema = updateSchemaContext.isWillUpdate();
273 
274         if (updateSchemaContext.isCloseDb()) {
275 
276             // ------------------------------------------------------------------ //
277             // --- close current db                                               //
278             // ------------------------------------------------------------------ //
279 
280             progressionModel.increments(t("tutti.importDb.step.closeDb"));
281             getActionEngine().runInternalAction(getHandler(), CloseDbAction.class);
282 
283             setScreen(TuttiScreen.MANAGE_DB);
284             super.doAction();
285             return;
286         }
287 
288         if (updateSchema) {
289 
290             // need to export db + migrate schema)
291             progressionModel.adaptTotal(progressionModel.getTotal() + ExportDbAction.TOTAL_STEP + 1);
292 
293             // ------------------------------------------------------------------ //
294             // --- backup current db                                              //
295             // ------------------------------------------------------------------ //
296 
297             ApplicationUIAction<ExportDbAction> backupAction =
298                     getActionFactory().createUIAction(getHandler(), ExportDbAction.class);
299             backupAction.getLogicAction().setProgressionModel(getProgressionModel());
300             backupAction.getLogicAction().setFile(updateSchemaContext.getFile());
301             backupAction.getLogicAction().setNoUI(true);
302             getActionEngine().runInternalAction(backupAction.getLogicAction());
303 
304             // ------------------------------------------------------------------ //
305             // --- update schema                                                  //
306             // ------------------------------------------------------------------ //
307 
308             String message = t("tutti.openDb.step.will.migrateSchema", schemaVersion, schemaVersionIfUpdate);
309 
310             progressionModel.increments(message);
311             sendMessage(message);
312             getContext().getPersistenceService().updateSchema();
313         }
314 
315         if (updateReferentiel) {
316 
317             // ------------------------------------------------------------------ //
318             // --- update referentiel                                             //
319             // ------------------------------------------------------------------ //
320 
321             progressionModel.increments(t("tutti.openDb.step.updateReferential"));
322 
323             progressionModel.setMessage(t("tutti.dbManager.action.upgradeDb.check"));
324 
325             File current = config.getDataDirectory();
326             String url = config.getUpdateDataUrl();
327             TuttiDbUpdaterCallBack callback = new TuttiDbUpdaterCallBack(url, this, progressionModel);
328 
329             Updates.doUpdate(config, callback, current);
330 
331             if (callback.isDbUpdated()) {
332 
333                 progressionModel.setMessage(t("tutti.dbManager.action.upgradeDb.reloading"));
334 
335             } else {
336                 sendMessage(t("tutti.dbManager.action.upgradeDb.upToDate"));
337             }
338         }
339 
340         // ------------------------------------------------------------------ //
341         // --- check db context                                               //
342         // ------------------------------------------------------------------ //
343 
344         String message = t("tutti.openDb.step.check.dbContext", schemaVersion, schemaVersionIfUpdate);
345 
346         progressionModel.increments(message);
347 
348         if (log.isDebugEnabled()) {
349             log.debug("Check db context");
350         }
351         getContext().checkDbContext();
352 
353         super.doAction();
354     }
355 
356     @Override
357     public void postSuccessAction() {
358 
359         handler.reloadDbManagerText();
360 
361         // make sure title is reloaded
362         handler.changeTitle();
363 
364         if (updateSchemaContext.isCloseDb()) {
365             sendMessage(t("tutti.flash.info.db.not.opened", jdbcUrl));
366         } else {
367             sendMessage(t("tutti.flash.info.db.opened", jdbcUrl));
368         }
369     }
370 
371     @Override
372     public void postFailedAction(Throwable error) {
373 
374         handler.reloadDbManagerText();
375 
376         super.postFailedAction(error);
377     }
378 }