Project

General

Profile

Download (13.2 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.remote.store;
11

    
12
import java.lang.reflect.InvocationTargetException;
13
import java.util.concurrent.CancellationException;
14

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

    
24
import eu.etaxonomy.cdm.api.application.CdmApplicationController;
25
import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteController;
26
import eu.etaxonomy.cdm.api.application.ICdmRepository;
27
import eu.etaxonomy.cdm.config.CdmSourceException;
28
import eu.etaxonomy.cdm.config.ICdmSource;
29
import eu.etaxonomy.cdm.database.DbSchemaValidation;
30
import eu.etaxonomy.cdm.database.ICdmDataSource;
31
import eu.etaxonomy.cdm.model.common.Language;
32
import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
33
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
34
import eu.etaxonomy.cdm.model.name.Rank;
35
import eu.etaxonomy.cdm.model.term.init.TermLoader;
36
import eu.etaxonomy.taxeditor.event.EventUtility;
37
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
38
import eu.etaxonomy.taxeditor.l10n.Messages;
39
import eu.etaxonomy.taxeditor.model.AbstractUtility;
40
import eu.etaxonomy.taxeditor.model.CdmProgressMonitorAdapter;
41
import eu.etaxonomy.taxeditor.model.MessagingUtils;
42
import eu.etaxonomy.taxeditor.remoting.source.ICdmRemoteSource;
43
import eu.etaxonomy.taxeditor.store.CdmAuthenticationException;
44
import eu.etaxonomy.taxeditor.store.CdmStore;
45
import eu.etaxonomy.taxeditor.store.LoginManager;
46
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
47
import eu.etaxonomy.taxeditor.workbench.datasource.IRemotingLoginDialog;
48

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

    
59
    public CdmStoreConnector(Display display,
60
            ICdmSource cdmSource,
61
            DbSchemaValidation dbSchemaValidation,
62
            Resource applicationContextBean) {
63
        super(String.format(Messages.CdmStoreConnector_CREATING_DATAMODEL, cdmSource));
64
        this.display = display;
65
        this.cdmSource = cdmSource;
66
        this.dbSchemaValidation = dbSchemaValidation;
67
        this.applicationContextBean = applicationContextBean;
68
    }
69

    
70
    @Override
71
    public IStatus run(final IProgressMonitor monitor) {
72

    
73
        monitor.beginTask(getConnectionMessage(), 10);
74

    
75
        // check if database is up and running
76
        checkDatabaseReachable(monitor);
77

    
78
        if (!monitor.isCanceled()) {
79
            // check if the datasource actually holds data
80
            checkIsNonEmptyCdmDatabase(monitor);
81
        }
82

    
83
        if (dbSchemaValidation != DbSchemaValidation.CREATE
84
                && !monitor.isCanceled()) {
85
            // if we do not create the datasource, we want to check if the
86
            // datasource is compatible with this editor
87
            checkDbSchemaVersionCompatibility(monitor);
88
        }
89

    
90
        // we are done with our low level checking and will free resources now
91
        cdmSource.closeOpenConnections();
92

    
93
        if (!monitor.isCanceled()) {
94
            CdmStore.close(monitor);
95
        }
96

    
97
        ICdmRepository applicationController = null;
98

    
99
        if (!monitor.isCanceled()) {
100
            CdmProgressMonitorAdapter subprogressMonitor = CdmProgressMonitorAdapter
101
                    .CreateSubMonitor(monitor, 7);
102
            // This is where we instantiate the application controller
103
            int oldPriority = Thread.currentThread().getPriority();
104
            try {
105
                Thread.currentThread().setPriority(10);
106
                applicationController = getApplicationController(cdmSource,subprogressMonitor);
107
                MessagingUtils.informationDialog(Messages.CdmStoreConnector_SUCCESS, Messages.CdmStoreConnector_DATA_MODEL_CREATION_SUCCESSFUL);
108
                //FIXME E4 migrate or delete because data source view is not used anymore
109
//                CdmDataSourceViewPartE4 dataSourceView = (CdmDataSourceViewPartE4) WorkbenchUtility.getE4WrappedPart(AbstractUtility.getView("eu.etaxonomy.taxeditor.view.datasource", false));
110
//                if(dataSourceView!=null){
111
//                    dataSourceView.refresh();
112
//                }
113
                EventUtility.postEvent(WorkbenchEventConstants.REFRESH_DATASOURCE, true);
114
                return Status.OK_STATUS;
115
            } catch (Exception e) {
116
                if(! causeIsCancelationExceptionRecursive(e)){
117
                    MessagingUtils.errorDialog(Messages.CdmStoreConnector_COULD_NOT_CREATE_DATAMODEL, CdmStoreConnector.class,
118
                    		String.format(Messages.CdmStoreConnector_ERROR_DURING_DATAMODEL_CREATION, cdmSource.getName()), TaxeditorStorePlugin.PLUGIN_ID, e, true);
119
                    return Status.CANCEL_STATUS;
120
                }
121
            } finally {
122
                monitor.done();
123
                Thread.currentThread().setPriority(oldPriority);
124
            }
125
        }
126
        return Status.CANCEL_STATUS;
127
    }
128

    
129
    public void start(final IRemotingLoginDialog loginDialog) {
130
        // hide login dialog and start connection dialog
131
        loginDialog.setMessage(null);
132
        loginDialog.hide(true);
133

    
134
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(AbstractUtility.getShell());
135

    
136
        try {
137
            dialog.run(true, true, new IRunnableWithProgress() {
138
                @Override
139
                public void run(final IProgressMonitor monitor) {
140
                    try {
141
                        monitor.beginTask(getConnectionMessage(), 7);
142

    
143
                        // check if database is up and running
144
                        checkDatabaseReachable(monitor);
145

    
146
                        // check if the datasource actually holds data
147
                        checkIsNonEmptyCdmDatabase(monitor);
148

    
149
                        if (dbSchemaValidation != DbSchemaValidation.CREATE) {
150
                            // if we do not create the datasource, we want to check if the
151
                            // datasource is compatible with this editor
152
                            checkDbSchemaVersionCompatibility(monitor);
153
                        }
154

    
155
                        // we are done with our low level checking and will free resources now
156
                        cdmSource.closeOpenConnections();
157

    
158
                        display.syncExec(new Runnable() {
159
                            @Override
160
                            public void run() {
161
                                // close the current context
162
                                CdmStore.close(monitor, false);
163
                            }
164
                        });
165

    
166
                        ICdmRepository applicationController = null;
167

    
168
                        if (!monitor.isCanceled()) {
169
                            CdmProgressMonitorAdapter subprogressMonitor = CdmProgressMonitorAdapter
170
                                    .CreateSubMonitor(monitor, 3);
171
                            // genrerate new application controller
172
                            applicationController = getApplicationController(cdmSource,subprogressMonitor);
173
                        }
174

    
175
                        if (!monitor.isCanceled()) {
176
                            CdmStoreRemote.setInstance(applicationController, cdmSource);
177
                            CdmStoreRemote.getTermManager().reset();
178
                            monitor.subTask(Messages.CdmStoreConnector_AUTHENTICATING_USER);
179
                            display.syncExec(()-> {
180
                                try {
181
                                    // create new security context
182
                                    CdmStore.getLoginManager().doAuthenticate(loginDialog.getUsername(), loginDialog.getPassword());
183
                                    //loginDialog.onComplete();
184
                                    CdmStore.getContextManager().notifyContextStart();
185
                                    loginDialog.onComplete();
186
                                    //TODO AM: is this necessary to be done on display thread?
187
                                    new TermLoader().unloadAllTerms();
188
                                    Rank.initDefaultTerms();
189
                                    NomenclaturalStatusType.initDefaultTerms();
190
                                    Language.getDefaultLanguage();
191
                                } catch(CdmAuthenticationException cae) {
192
                                    loginDialog.hide(false);
193
                                    loginDialog.setMessage(LoginManager.INCORRECT_CREDENTIALS_MESSAGE);
194
                                }
195
                            });
196
                        } else {
197
                            throw new RuntimeException("Login cancelled");
198
                        }
199
                    } finally {
200
                        monitor.done();
201
                    }
202
                }
203
            });
204
        } catch (InvocationTargetException e) {
205
            loginDialog.hide(false);
206
            loginDialog.setMessage(e.getMessage());
207
        } catch (InterruptedException e) {
208
            loginDialog.hide(false);
209
            loginDialog.setMessage(e.getMessage());
210
        }
211
    }
212

    
213
    private ICdmRepository getApplicationController(ICdmSource cdmSource, CdmProgressMonitorAdapter subprogressMonitor) {
214
        if(cdmSource instanceof ICdmDataSource) {
215
            return  CdmApplicationController.NewInstance(applicationContextBean,
216
                    (ICdmDataSource)cdmSource,
217
                    dbSchemaValidation,
218
                    false,
219
                    subprogressMonitor);
220
        } else if(cdmSource instanceof ICdmRemoteSource) {
221
            return CdmApplicationRemoteController.NewInstance((ICdmRemoteSource)cdmSource,
222
                    subprogressMonitor,
223
                    null);
224
        } else {
225
            throw new UnsupportedOperationException("Cannot create application controller for " + cdmSource.getName());
226
        }
227
    }
228

    
229
    private String getConnectionMessage() {
230
        return cdmSource.getConnectionMessage();
231
    }
232

    
233
    private void checkDbSchemaVersionCompatibility(IProgressMonitor monitor) {
234
        monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_EDITOR_IS_COMPATIBLE);
235
        String dbSchemaVersion;
236

    
237
        String message = null;
238
        try {
239
            dbSchemaVersion = cdmSource.getDbSchemaVersion();
240
            // we assume that empty dbSchemaVersion means an empty database and
241
            // skip version checking
242

    
243
            if(dbSchemaVersion != null) {
244
                int compareVersion = CdmMetaData.compareVersion(dbSchemaVersion, CdmMetaData.getDbSchemaVersion(), 3, null);
245
                // if the datasource version is greater than the taxeditor compatible version then the taxeditor needs to
246
                // be updated else the datasource needs to be updated
247
                if(compareVersion > 0) {
248
                    message = Messages.CdmStoreConnector_UPDATE_EDITOR_OR_CHOOSE_COMPATIBLE_DATASOURCE;
249
                } else if (compareVersion < 0) {
250
                    message = Messages.CdmStoreConnector_UPDATE_DATASOUREC_OR_CHOOSE_NEW_DATASOURCE;
251
                }
252
            }
253
            monitor.worked(1);
254
        } catch (CdmSourceException e) {
255
            //
256
        }
257

    
258
        if (message != null) {
259
            // Show an error message
260
            MessagingUtils
261
            .messageDialog(
262
                    Messages.CdmStoreConnector_COMPATIBILITY_CHECK_FAILED,
263
                    this,
264
                    String.format(Messages.CdmStoreConnector_SCHEME_NOT_COMPATIBLE, cdmSource, message),
265
                            null);
266

    
267
            monitor.setCanceled(true);
268
        }
269
    }
270

    
271
    private void checkIsNonEmptyCdmDatabase(IProgressMonitor monitor) {
272
        monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_NON_EMPTY);
273
        boolean isDbEmpty = false;
274
        try {
275
            isDbEmpty = cdmSource.isDbEmpty();
276
        } catch (CdmSourceException e) {
277
            isDbEmpty = true;
278
        }
279
        if(isDbEmpty) {
280
            dbSchemaValidation = DbSchemaValidation.CREATE;
281
        }
282
    }
283

    
284
    private boolean causeIsCancelationExceptionRecursive(Throwable throwable){
285
        if(throwable == null){
286
            return false;
287
        }else if(throwable instanceof CancellationException){
288
            return true;
289
        }else{
290
            return causeIsCancelationExceptionRecursive(throwable.getCause());
291
        }
292
    }
293

    
294
    private void checkDatabaseReachable(IProgressMonitor monitor) {
295
        try {
296
            monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_REACHABLE);
297
            cdmSource.checkConnection();
298
            monitor.worked(1);
299
        } catch (CdmSourceException e) {
300
            MessagingUtils.messageDialog(Messages.CdmStoreConnector_COULD_NOT_CONNECT_TO_CHOSEN_DATASOURCE,
301
                    this, Messages.CdmStoreConnector_REASON + e.getMessage(), e);
302
            monitor.setCanceled(true);
303
        }
304
    }
305
}
(1-1/2)