Project

General

Profile

Download (14.4 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2007 EDIT
3
 * European Distributed Institute of Taxonomy
4
 * http://www.e-taxonomy.eu
5
 *
6
 * The contents of this file are subject to the Mozilla Public License Version 1.1
7
 * See LICENSE.TXT at the top of this package for the full license terms.
8
 */
9

    
10
package eu.etaxonomy.taxeditor.store;
11

    
12
import java.lang.reflect.Constructor;
13
import java.lang.reflect.InvocationTargetException;
14
import java.sql.SQLException;
15
import java.util.concurrent.CancellationException;
16

    
17
import org.eclipse.core.runtime.IProgressMonitor;
18
import org.eclipse.core.runtime.IStatus;
19
import org.eclipse.core.runtime.Status;
20
import org.eclipse.core.runtime.jobs.Job;
21
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
22
import org.eclipse.jface.operation.IRunnableWithProgress;
23
import org.eclipse.swt.widgets.Display;
24
import org.springframework.core.io.Resource;
25

    
26
import eu.etaxonomy.cdm.api.application.CdmApplicationController;
27
import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteController;
28
import eu.etaxonomy.cdm.api.application.ICdmRepository;
29
import eu.etaxonomy.cdm.config.CdmSourceException;
30
import eu.etaxonomy.cdm.config.ICdmSource;
31
import eu.etaxonomy.cdm.database.DbSchemaValidation;
32
import eu.etaxonomy.cdm.database.ICdmDataSource;
33
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
34
import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
35
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
36
import eu.etaxonomy.cdm.model.name.Rank;
37
import eu.etaxonomy.taxeditor.l10n.Messages;
38
import eu.etaxonomy.taxeditor.model.AbstractUtility;
39
import eu.etaxonomy.taxeditor.model.CdmProgressMonitorAdapter;
40
import eu.etaxonomy.taxeditor.model.MessagingUtils;
41
import eu.etaxonomy.taxeditor.remoting.source.ICdmRemoteSource;
42
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
43
import eu.etaxonomy.taxeditor.ui.dialog.LoginDialog;
44
import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
45
import eu.etaxonomy.taxeditor.view.datasource.e4.CdmDataSourceViewPartE4;
46
import eu.etaxonomy.taxeditor.workbench.WorkbenchUtility;
47

    
48

    
49
/**
50
 * @author n.hoffmann
51
 * @created Dec 8, 2010
52
 * @version 1.0
53
 */
54
class CdmStoreConnector extends Job {
55
    private final Display display;
56
    private final ICdmSource cdmSource;
57
    private DbSchemaValidation dbSchemaValidation;
58
    private final Resource applicationContextBean;
59

    
60

    
61
    /**
62
     * @param datasource
63
     * @param dbSchemaValidation
64
     * @param applicationContextBean
65
     */
66
    public CdmStoreConnector(Display display,
67
            ICdmSource cdmSource,
68
            DbSchemaValidation dbSchemaValidation,
69
            Resource applicationContextBean) {
70
        super(String.format(Messages.CdmStoreConnector_CREATING_DATAMODEL, cdmSource));
71
        this.display = display;
72
        this.cdmSource = cdmSource;
73
        this.dbSchemaValidation = dbSchemaValidation;
74
        this.applicationContextBean = applicationContextBean;
75
    }
76

    
77

    
78

    
79
    @Override
80
    public IStatus run(final IProgressMonitor monitor) {
81

    
82
        monitor.beginTask(getConnectionMessage(), 10);
83

    
84
        // check if database is up and running
85
        checkDatabaseReachable(monitor);
86

    
87
        if (!monitor.isCanceled()) {
88
            // check if the datasource actually holds data
89
            checkIsNonEmptyCdmDatabase(monitor);
90
        }
91

    
92
        if (dbSchemaValidation != DbSchemaValidation.CREATE
93
                && !monitor.isCanceled()) {
94
            // if we do not create the datasource, we want to check if the
95
            // datasource is compatible with this editor
96
            checkDbSchemaVersionCompatibility(monitor);
97
        }
98

    
99
        // we are done with our low level checking and will free resources now
100
        cdmSource.closeOpenConnections();
101

    
102
        if (!monitor.isCanceled()) {
103
            CdmStore.close(monitor);
104
        }
105

    
106
        ICdmRepository applicationController = null;
107

    
108
        if (!monitor.isCanceled()) {
109
            CdmProgressMonitorAdapter subprogressMonitor = CdmProgressMonitorAdapter
110
                    .CreateSubMonitor(monitor, 7);
111
            // This is where we instantiate the application controller
112
            int oldPriority = Thread.currentThread().getPriority();
113
            try {
114
                Thread.currentThread().setPriority(10);
115
                applicationController = getApplicationController(cdmSource,subprogressMonitor);
116
                MessagingUtils.informationDialog(Messages.CdmStoreConnector_SUCCESS, Messages.CdmStoreConnector_DATA_MODEL_CREATION_SUCCESSFUL);
117
                CdmDataSourceViewPartE4 dataSourceView = (CdmDataSourceViewPartE4) WorkbenchUtility.getE4WrappedPart(AbstractUtility.getView("eu.etaxonomy.taxeditor.view.datasource", false));
118
                if(dataSourceView!=null){
119
                    dataSourceView.refresh();
120
                }
121
                return Status.OK_STATUS;
122
            } catch (Exception e) {
123
                if(! causeIsCancelationExceptionRecursive(e)){
124
                    MessagingUtils.errorDialog(Messages.CdmStoreConnector_COULD_NOT_CREATE_DATAMODEL, CdmStoreConnector.class,
125
                    		String.format(Messages.CdmStoreConnector_ERROR_DURING_DATAMODEL_CREATION, cdmSource.getName()), TaxeditorStorePlugin.PLUGIN_ID, e, true);
126
                    return Status.CANCEL_STATUS;
127
                }
128
            } finally {
129
                monitor.done();
130
                Thread.currentThread().setPriority(oldPriority);
131
            }
132
        }
133
        return Status.CANCEL_STATUS;
134

    
135
    }
136

    
137
    public void start(final RemotingLoginDialog loginDialog) {
138
        // hide login dialog and start connection dialog
139
        loginDialog.setMessage(null);
140
        loginDialog.hide(true);
141

    
142

    
143
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(StoreUtil.getShell());
144

    
145
        try {
146
            dialog.run(true, true, new IRunnableWithProgress() {
147
                @Override
148
                public void run(final IProgressMonitor monitor) {
149
                    try {
150
                        monitor.beginTask(getConnectionMessage(), 7);
151

    
152
                        // check if database is up and running
153
                        checkDatabaseReachable(monitor);
154

    
155
                        // check if the datasource actually holds data
156
                        checkIsNonEmptyCdmDatabase(monitor);
157

    
158
                        if (dbSchemaValidation != DbSchemaValidation.CREATE) {
159
                            // if we do not create the datasource, we want to check if the
160
                            // datasource is compatible with this editor
161
                            checkDbSchemaVersionCompatibility(monitor);
162
                        }
163

    
164
                        // we are done with our low level checking and will free resources now
165
                        cdmSource.closeOpenConnections();
166

    
167
                        display.syncExec(new Runnable() {
168
                            /*
169
                             * (non-Javadoc)
170
                             *
171
                             * @see java.lang.Runnable#run()
172
                             */
173
                            @Override
174
                            public void run() {
175
                                // close the current context
176
                                CdmStore.close(monitor, false);
177
                            }
178
                        });
179

    
180
                        ICdmRepository applicationController = null;
181

    
182
                        if (!monitor.isCanceled()) {
183
                            CdmProgressMonitorAdapter subprogressMonitor = CdmProgressMonitorAdapter
184
                                    .CreateSubMonitor(monitor, 3);
185
                            // genrerate new application controller
186
                            applicationController = getApplicationController(cdmSource,subprogressMonitor);
187
                        }
188

    
189

    
190
                        if (!monitor.isCanceled()) {
191
                            CdmStore.setInstance(applicationController, cdmSource);
192
                            monitor.subTask(Messages.CdmStoreConnector_AUTHENTICATING_USER);
193
                            display.syncExec(new Runnable() {
194
                                /*
195
                                 * (non-Javadoc)
196
                                 *
197
                                 * @see java.lang.Runnable#run()
198
                                 */
199
                                @Override
200
                                public void run() {
201

    
202
                                    try {
203
                                        // create new security context
204
                                        CdmStore.getLoginManager().doAuthenticate(loginDialog.getUsername(), loginDialog.getPassword());
205
                                        loginDialog.onComplete();
206
                                        CdmStore.getContextManager().notifyContextStart();
207
                                        getInstance(Rank.class).resetTerms();
208
                                        getInstance(NomenclaturalStatusType.class).resetTerms();
209
                                        Rank.initDefaultTerms();
210
                                        NomenclaturalStatusType.initDefaultTerms();
211
                                    } catch(CdmAuthenticationException cae) {
212
                                        loginDialog.hide(false);
213
                                        loginDialog.setMessage(cae.getMessage());
214
                                    }
215

    
216
                                }
217
                            });
218
                        } else {
219
                            throw new RuntimeException("Login cancelled");
220
                        }
221
                    } finally {
222
                        monitor.done();
223
                    }
224
                }
225
            });
226
        } catch (InvocationTargetException e) {
227
            loginDialog.hide(false);
228
            loginDialog.setMessage(e.getMessage());
229
        } catch (InterruptedException e) {
230
            loginDialog.hide(false);
231
            loginDialog.setMessage(e.getMessage());
232
        }
233
    }
234

    
235
    /**
236
     * Returns a new instance for the given class by using the default constructor.
237
     * The constructor must be declared but can be unaccessible (e.g. private)
238
     * @param termClass
239
     * @return
240
     */
241
    private  <T extends DefinedTermBase> T getInstance(Class<? extends DefinedTermBase> termClass) {
242
        try {
243
            Constructor<T> c = ((Class<T>)termClass).getDeclaredConstructor();
244
            c.setAccessible(true);
245
            T termInstance = c.newInstance();
246
            return termInstance;
247
        } catch (Exception e) {
248
            throw new RuntimeException(e);
249
        }
250
    }
251

    
252

    
253
    private ICdmRepository getApplicationController(ICdmSource cdmSource, CdmProgressMonitorAdapter subprogressMonitor) {
254
        if(cdmSource instanceof ICdmDataSource) {
255
            return  CdmApplicationController.NewInstance(applicationContextBean,
256
                    (ICdmDataSource)cdmSource,
257
                    dbSchemaValidation,
258
                    false,
259
                    subprogressMonitor);
260
        } else if(cdmSource instanceof ICdmRemoteSource) {
261
            return CdmApplicationRemoteController.NewInstance((ICdmRemoteSource)cdmSource,
262
                    subprogressMonitor,
263
                    null);
264
        } else {
265
            throw new UnsupportedOperationException("Cannot create application controller for " + cdmSource.getName());
266
        }
267
    }
268

    
269
    private void authenticate() {
270
        LoginDialog saloginDialog = new LoginDialog(StoreUtil.getShell());
271
        saloginDialog.open();
272
    }
273

    
274
    private void startContext() {
275
        CdmStore.getContextManager().notifyContextStart();
276
    }
277

    
278
    /**
279
     * @return
280
     */
281
    private String getConnectionMessage() {
282
        return cdmSource.getConnectionMessage();
283
    }
284

    
285
    /**
286
     * @return
287
     * @throws SQLException
288
     */
289
    private void checkDbSchemaVersionCompatibility(IProgressMonitor monitor) {
290
        monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_EDITOR_IS_COMPATIBLE);
291
        String dbSchemaVersion;
292

    
293
        String message = null;
294
        try {
295
            dbSchemaVersion = cdmSource.getDbSchemaVersion();
296
            // we assume that empty dbSchemaVersion means an empty database and
297
            // skip version checking
298

    
299
            if(dbSchemaVersion != null) {
300
                int compareVersion = CdmMetaData.compareVersion(dbSchemaVersion, CdmMetaData.getDbSchemaVersion(), 3, null);
301
                // if the datasource version is greater than the taxeditor compatible version then the taxeditor needs to
302
                // be updated else the datasource needs to be updated
303
                if(compareVersion > 0) {
304
                    message = Messages.CdmStoreConnector_UPDATE_EDITOR_OR_CHOOSE_COMPATIBLE_DATASOURCE;
305
                } else if (compareVersion < 0) {
306
                    message = Messages.CdmStoreConnector_UPDATE_DATASOUREC_OR_CHOOSE_NEW_DATASOURCE;
307
                }
308
            }
309
            monitor.worked(1);
310
        } catch (CdmSourceException e) {
311
            //
312
        }
313

    
314
        if (message != null) {
315
            // Show an error message
316
            MessagingUtils
317
            .messageDialog(
318
                    Messages.CdmStoreConnector_COMPATIBILITY_CHECK_FAILED,
319
                    this,
320
                    String.format(Messages.CdmStoreConnector_SCHEME_NOT_COMPATIBLE, cdmSource, message),
321
                            null);
322

    
323
            monitor.setCanceled(true);
324
        }
325

    
326
    }
327

    
328
    private void checkIsNonEmptyCdmDatabase(IProgressMonitor monitor) {
329
        monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_NON_EMPTY);
330
        boolean isDbEmpty = false;
331
        try {
332
            isDbEmpty = cdmSource.isDbEmpty();
333
        } catch (CdmSourceException e) {
334
            isDbEmpty = true;
335
        }
336
        if(isDbEmpty) {
337
            dbSchemaValidation = DbSchemaValidation.CREATE;
338
        }
339
    }
340

    
341
    private boolean causeIsCancelationExceptionRecursive(Throwable throwable){
342
        if(throwable == null){
343
            return false;
344
        }else if(throwable instanceof CancellationException){
345
            return true;
346
        }else{
347
            return causeIsCancelationExceptionRecursive(throwable.getCause());
348
        }
349
    }
350

    
351
    private void checkDatabaseReachable(IProgressMonitor monitor) {
352
        try {
353
            monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_REACHABLE);
354
            cdmSource.checkConnection();
355
            monitor.worked(1);
356
        } catch (CdmSourceException e) {
357
            MessagingUtils.messageDialog(Messages.CdmStoreConnector_COULD_NOT_CONNECT_TO_CHOSEN_DATASOURCE,
358
                    this, Messages.CdmStoreConnector_REASON + e.getMessage(), e);
359
            monitor.setCanceled(true);
360
        }
361
    }
362

    
363

    
364
}
(3-3/13)