Project

General

Profile

Download (12.3 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.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.CdmApplicationRemoteController;
25
import eu.etaxonomy.cdm.api.application.ICdmRepository;
26
import eu.etaxonomy.cdm.config.CdmSourceException;
27
import eu.etaxonomy.cdm.config.ICdmSource;
28
import eu.etaxonomy.cdm.database.DbSchemaValidation;
29
import eu.etaxonomy.cdm.model.common.Language;
30
import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
31
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
32
import eu.etaxonomy.cdm.model.name.Rank;
33
import eu.etaxonomy.cdm.model.term.init.TermLoader;
34
import eu.etaxonomy.taxeditor.event.EventUtility;
35
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
36
import eu.etaxonomy.taxeditor.l10n.Messages;
37
import eu.etaxonomy.taxeditor.model.AbstractUtility;
38
import eu.etaxonomy.taxeditor.model.CdmProgressMonitorAdapter;
39
import eu.etaxonomy.taxeditor.model.MessagingUtils;
40
import eu.etaxonomy.taxeditor.remoting.source.ICdmRemoteSource;
41
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
42
import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
43

    
44
/**
45
 * @author n.hoffmann
46
 * @created Dec 8, 2010
47
 */
48
class CdmStoreConnector extends Job {
49
    private final Display display;
50
    private final ICdmSource cdmSource;
51
    private DbSchemaValidation dbSchemaValidation;
52
    private final Resource applicationContextBean;
53

    
54
    public CdmStoreConnector(Display display,
55
            ICdmSource cdmSource,
56
            DbSchemaValidation dbSchemaValidation,
57
            Resource applicationContextBean) {
58
        super(String.format(Messages.CdmStoreConnector_CREATING_DATAMODEL, cdmSource));
59
        this.display = display;
60
        this.cdmSource = cdmSource;
61
        this.dbSchemaValidation = dbSchemaValidation;
62
        this.applicationContextBean = applicationContextBean;
63
    }
64

    
65
    @Override
66
    public IStatus run(final IProgressMonitor monitor) {
67

    
68
        monitor.beginTask(getConnectionMessage(), 10);
69

    
70
        // check if database is up and running
71
        checkDatabaseReachable(monitor);
72

    
73
        if (!monitor.isCanceled()) {
74
            // check if the datasource actually holds data
75
            checkIsNonEmptyCdmDatabase(monitor);
76
        }
77

    
78
        if (dbSchemaValidation != DbSchemaValidation.CREATE
79
                && !monitor.isCanceled()) {
80
            // if we do not create the datasource, we want to check if the
81
            // datasource is compatible with this editor
82
            checkDbSchemaVersionCompatibility(monitor);
83
        }
84

    
85
        // we are done with our low level checking and will free resources now
86
        cdmSource.closeOpenConnections();
87

    
88
        if (!monitor.isCanceled()) {
89
            CdmStore.close(monitor);
90
        }
91

    
92
        ICdmRepository applicationController = null;
93

    
94
        if (!monitor.isCanceled()) {
95
            CdmProgressMonitorAdapter subprogressMonitor = CdmProgressMonitorAdapter
96
                    .CreateSubMonitor(monitor, 7);
97
            // This is where we instantiate the application controller
98
            int oldPriority = Thread.currentThread().getPriority();
99
            try {
100
                Thread.currentThread().setPriority(10);
101
                applicationController = getApplicationController(cdmSource, subprogressMonitor);
102
                MessagingUtils.informationDialog(Messages.CdmStoreConnector_SUCCESS, Messages.CdmStoreConnector_DATA_MODEL_CREATION_SUCCESSFUL);
103
                EventUtility.postEvent(WorkbenchEventConstants.REFRESH_DATASOURCE, true);
104
                return Status.OK_STATUS;
105
            } catch (Exception e) {
106
                if(! causeIsCancelationExceptionRecursive(e)){
107
                    MessagingUtils.errorDialog(Messages.CdmStoreConnector_COULD_NOT_CREATE_DATAMODEL, CdmStoreConnector.class,
108
                    		String.format(Messages.CdmStoreConnector_ERROR_DURING_DATAMODEL_CREATION, cdmSource.getName()), TaxeditorStorePlugin.PLUGIN_ID, e, true);
109
                    return Status.CANCEL_STATUS;
110
                }
111
            } finally {
112
                monitor.done();
113
                Thread.currentThread().setPriority(oldPriority);
114
            }
115
        }
116
        return Status.CANCEL_STATUS;
117
    }
118

    
119
    public void start(final RemotingLoginDialog loginDialog) {
120
        // hide login dialog and start connection dialog
121
        loginDialog.setMessage(null);
122
        loginDialog.hide(true);
123

    
124
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(AbstractUtility.getShell());
125

    
126
        try {
127
            dialog.run(true, true, new IRunnableWithProgress() {
128
                @Override
129
                public void run(final IProgressMonitor monitor) {
130
                    try {
131
                        monitor.beginTask(getConnectionMessage(), 7);
132

    
133
                        // check if database is up and running
134
                        checkDatabaseReachable(monitor);
135

    
136
                        // check if the datasource actually holds data
137
                        checkIsNonEmptyCdmDatabase(monitor);
138

    
139
                        if (dbSchemaValidation != DbSchemaValidation.CREATE) {
140
                            // if we do not create the datasource, we want to check if the
141
                            // datasource is compatible with this editor
142
                            checkDbSchemaVersionCompatibility(monitor);
143
                        }
144

    
145
                        // we are done with our low level checking and will free resources now
146
                        cdmSource.closeOpenConnections();
147

    
148
                        display.syncExec(new Runnable() {
149
                            @Override
150
                            public void run() {
151
                                // close the current context
152
                                CdmStore.close(monitor, false);
153
                            }
154
                        });
155

    
156
                        CdmApplicationRemoteController applicationController = null;
157

    
158
                        if (!monitor.isCanceled()) {
159
                            CdmProgressMonitorAdapter subprogressMonitor = CdmProgressMonitorAdapter
160
                                    .CreateSubMonitor(monitor, 3);
161
                            // genrerate new application controller
162
                            applicationController = getApplicationController(cdmSource, subprogressMonitor);
163
                        }
164

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

    
203
    private CdmApplicationRemoteController getApplicationController(ICdmSource cdmSource, CdmProgressMonitorAdapter subprogressMonitor) {
204
        if(cdmSource instanceof ICdmRemoteSource) {
205
            return CdmApplicationRemoteController.NewInstance((ICdmRemoteSource)cdmSource,
206
                    subprogressMonitor,
207
                    null);
208
        } else {
209
            throw new UnsupportedOperationException("Cannot create application controller for " + cdmSource.getName());
210
        }
211
    }
212

    
213
    private String getConnectionMessage() {
214
        return cdmSource.getConnectionMessage();
215
    }
216

    
217
    private void checkDbSchemaVersionCompatibility(IProgressMonitor monitor) {
218
        monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_EDITOR_IS_COMPATIBLE);
219
        String dbSchemaVersion;
220

    
221
        String message = null;
222
        try {
223
            dbSchemaVersion = cdmSource.getDbSchemaVersion();
224
            // we assume that empty dbSchemaVersion means an empty database and
225
            // skip version checking
226

    
227
            if(dbSchemaVersion != null) {
228
                int compareVersion = CdmMetaData.compareVersion(dbSchemaVersion, CdmMetaData.getDbSchemaVersion(), 3, null);
229
                // if the datasource version is greater than the taxeditor compatible version then the taxeditor needs to
230
                // be updated else the datasource needs to be updated
231
                if(compareVersion > 0) {
232
                    message = Messages.CdmStoreConnector_UPDATE_EDITOR_OR_CHOOSE_COMPATIBLE_DATASOURCE;
233
                } else if (compareVersion < 0) {
234
                    message = Messages.CdmStoreConnector_UPDATE_DATASOUREC_OR_CHOOSE_NEW_DATASOURCE;
235
                }
236
            }
237
            monitor.worked(1);
238
        } catch (CdmSourceException e) {
239
            //
240
        }
241

    
242
        if (message != null) {
243
            // Show an error message
244
            MessagingUtils
245
            .messageDialog(
246
                    Messages.CdmStoreConnector_COMPATIBILITY_CHECK_FAILED,
247
                    this,
248
                    String.format(Messages.CdmStoreConnector_SCHEME_NOT_COMPATIBLE, cdmSource, message),
249
                            null);
250

    
251
            monitor.setCanceled(true);
252
        }
253
    }
254

    
255
    private void checkIsNonEmptyCdmDatabase(IProgressMonitor monitor) {
256
        monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_NON_EMPTY);
257
        boolean isDbEmpty = false;
258
        try {
259
            isDbEmpty = cdmSource.isDbEmpty();
260
        } catch (CdmSourceException e) {
261
            isDbEmpty = true;
262
        }
263
        if(isDbEmpty) {
264
            dbSchemaValidation = DbSchemaValidation.CREATE;
265
        }
266
    }
267

    
268
    private boolean causeIsCancelationExceptionRecursive(Throwable throwable){
269
        if(throwable == null){
270
            return false;
271
        }else if(throwable instanceof CancellationException){
272
            return true;
273
        }else{
274
            return causeIsCancelationExceptionRecursive(throwable.getCause());
275
        }
276
    }
277

    
278
    private void checkDatabaseReachable(IProgressMonitor monitor) {
279
        try {
280
            monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_REACHABLE);
281
            cdmSource.checkConnection();
282
            monitor.worked(1);
283
        } catch (CdmSourceException e) {
284
            MessagingUtils.messageDialog(Messages.CdmStoreConnector_COULD_NOT_CONNECT_TO_CHOSEN_DATASOURCE,
285
                    this, Messages.CdmStoreConnector_REASON + e.getMessage(), e);
286
            monitor.setCanceled(true);
287
        }
288
    }
289
}
(4-4/13)