Project

General

Profile

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

    
11
package eu.etaxonomy.taxeditor.store;
12

    
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.ICdmApplicationConfiguration;
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.metadata.CdmMetaData;
34
import eu.etaxonomy.cdm.model.name.Rank;
35
import eu.etaxonomy.taxeditor.model.CdmProgressMonitorAdapter;
36
import eu.etaxonomy.taxeditor.model.MessagingUtils;
37
import eu.etaxonomy.taxeditor.remoting.source.ICdmRemoteSource;
38
import eu.etaxonomy.taxeditor.ui.dialog.LoginDialog;
39
import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
40
import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
41

    
42

    
43
/**
44
 * @author n.hoffmann
45
 * @created Dec 8, 2010
46
 * @version 1.0
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

    
55
    /**
56
     * @param datasource
57
     * @param dbSchemaValidation
58
     * @param applicationContextBean
59
     */
60
    public CdmStoreConnector(Display display,
61
            ICdmSource cdmSource,
62
            DbSchemaValidation dbSchemaValidation,
63
            Resource applicationContextBean) {
64
        super("Connecting to datasource: " + cdmSource);
65
        this.display = display;
66
        this.cdmSource = cdmSource;
67
        this.dbSchemaValidation = dbSchemaValidation;
68
        this.applicationContextBean = applicationContextBean;
69
    }
70

    
71

    
72

    
73
    @Override
74
    public IStatus run(final IProgressMonitor monitor) {
75

    
76
        monitor.beginTask(getConnectionMessage(), 10);
77

    
78
        // check if database is up and running
79
        checkDatabaseReachable(monitor);
80

    
81
        if (!monitor.isCanceled()) {
82
            // check if the datasource actually holds data
83
            checkIsNonEmptyCdmDatabase(monitor);
84
        }
85

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

    
93
        // we are done with our low level checking and will free resources now
94
        cdmSource.closeOpenConnections();
95

    
96
        if (!monitor.isCanceled()) {
97
            CdmStore.close(monitor);
98
        }
99

    
100
        ICdmApplicationConfiguration applicationController = null;
101

    
102
        if (!monitor.isCanceled()) {
103
            CdmProgressMonitorAdapter subprogressMonitor = CdmProgressMonitorAdapter
104
                    .CreateSubMonitor(monitor, 7);
105
            // This is where we instantiate the application controller
106
            int oldPriority = Thread.currentThread().getPriority();
107
            try {
108
                Thread.currentThread().setPriority(10);
109
                applicationController = getApplicationController(cdmSource,subprogressMonitor);
110
            } catch (Exception e) {
111
                if(! causeIsCancelationExceptionRecursive(e)){
112
                    return new Status(IStatus.ERROR, "Could not connect to CDM Store", "An error occurred while trying to connect to datasource: " + cdmSource.getName(), e);
113
                }
114
            } finally {
115
                monitor.done();
116
                Thread.currentThread().setPriority(oldPriority);
117
            }
118
        }
119

    
120

    
121

    
122
        if (!monitor.isCanceled()) {
123
            CdmStore.setInstance(applicationController, cdmSource);
124

    
125
            display.asyncExec(new Runnable() {
126
                /*
127
                 * (non-Javadoc)
128
                 *
129
                 * @see java.lang.Runnable#run()
130
                 */
131
                @Override
132
                public void run() {
133
                    authenticate();
134

    
135
                    startContext();
136
                }
137
            });
138

    
139
            MessagingUtils.info("Application context initialized.");
140
            return Status.OK_STATUS;
141
        } else {
142
            // Show datasource view if not shown yet
143
            display.asyncExec(new Runnable() {
144
                /*
145
                 * (non-Javadoc)
146
                 *
147
                 * @see java.lang.Runnable#run()
148
                 */
149
                @Override
150
                public void run() {
151
                    StoreUtil.showView(CdmDataSourceViewPart.ID);
152
                }
153
            });
154
            return Status.CANCEL_STATUS;
155
        }
156

    
157
    }
158

    
159
    public void start(final RemotingLoginDialog loginDialog) {
160
        // hide login dialog and start connection dialog
161
        loginDialog.setMessage(null);
162
        loginDialog.hide(true);
163

    
164

    
165
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(StoreUtil.getShell());
166

    
167
        try {
168
            dialog.run(true, true, new IRunnableWithProgress() {
169
                @Override
170
                public void run(final IProgressMonitor monitor) {
171
                    try {
172
                        monitor.beginTask(getConnectionMessage(), 7);
173

    
174
                        // check if database is up and running
175
                        checkDatabaseReachable(monitor);
176

    
177
                        // check if the datasource actually holds data
178
                        checkIsNonEmptyCdmDatabase(monitor);
179

    
180
                        if (dbSchemaValidation != DbSchemaValidation.CREATE) {
181
                            // if we do not create the datasource, we want to check if the
182
                            // datasource is compatible with this editor
183
                            checkDbSchemaVersionCompatibility(monitor);
184
                        }
185

    
186
                        // we are done with our low level checking and will free resources now
187
                        cdmSource.closeOpenConnections();
188

    
189
                        display.syncExec(new Runnable() {
190
                            /*
191
                             * (non-Javadoc)
192
                             *
193
                             * @see java.lang.Runnable#run()
194
                             */
195
                            @Override
196
                            public void run() {
197
                                // close the current context
198
                                CdmStore.close(monitor, false);
199
                            }
200
                        });
201

    
202
                        ICdmApplicationConfiguration applicationController = null;
203

    
204
                        if (!monitor.isCanceled()) {
205
                            CdmProgressMonitorAdapter subprogressMonitor = CdmProgressMonitorAdapter
206
                                    .CreateSubMonitor(monitor, 3);
207
                            // genrerate new application controller
208
                            applicationController = getApplicationController(cdmSource,subprogressMonitor);
209
                        }
210

    
211

    
212
                        if (!monitor.isCanceled()) {
213
                            CdmStore.setInstance(applicationController, cdmSource);
214
                            monitor.subTask("Authenticating user");
215
                            display.syncExec(new Runnable() {
216
                                /*
217
                                 * (non-Javadoc)
218
                                 *
219
                                 * @see java.lang.Runnable#run()
220
                                 */
221
                                @Override
222
                                public void run() {
223

    
224
                                    try {
225
                                        // create new security context
226
                                        CdmStore.getLoginManager().doAuthenticate(loginDialog.getUsername(), loginDialog.getPassword());
227
                                        loginDialog.onComplete();
228
                                        CdmStore.getContextManager().notifyContextStart();
229
                                        Rank.initDefaultTerms();
230
                                    } catch(CdmAuthenticationException cae) {
231
                                        loginDialog.hide(false);
232
                                        loginDialog.setMessage(cae.getMessage());
233
                                    }
234

    
235
                                }
236
                            });
237
                        } else {
238
                            throw new RuntimeException("Login cancelled");
239
                        }
240
                    } finally {
241
                        monitor.done();
242
                    }
243
                }
244
            });
245
        } catch (InvocationTargetException e) {
246
            loginDialog.hide(false);
247
            loginDialog.setMessage(e.getMessage());
248
        } catch (InterruptedException e) {
249
            loginDialog.hide(false);
250
            loginDialog.setMessage(e.getMessage());
251
        }
252
    }
253

    
254

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

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

    
276
    private void startContext() {
277
        CdmStore.getContextManager().notifyContextStart();
278
    }
279

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

    
287
    /**
288
     * @return
289
     * @throws SQLException
290
     */
291
    private void checkDbSchemaVersionCompatibility(IProgressMonitor monitor) {
292
        monitor.subTask("Checking if datasource is compatible with this editor.");
293
        String dbSchemaVersion;
294

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

    
301
            if(dbSchemaVersion != null) {
302
                int compareVersion = CdmMetaData.compareVersion(dbSchemaVersion, CdmMetaData.getDbSchemaVersion(), 3, null);
303
                // if the datasource version is greater than the taxeditor compatible version then the taxeditor needs to
304
                // be updated else the datasource needs to be updated
305
                if(compareVersion > 0) {
306
                    message = "Please update the Taxonomic Editor (Help->Check for Updates) or choose a compatible datasource";
307
                } else if (compareVersion < 0) {
308
                    message = "Please update the chosen datasource or choose a new data source to connect to in the Datasource View.";
309
                }
310
            }
311
            monitor.worked(1);
312
        } catch (CdmSourceException e) {
313
            //
314
        }
315

    
316
        if (message != null) {
317
            // Show an error message
318
            MessagingUtils
319
            .messageDialog(
320
                    "Datasource Compatibility Check failed",
321
                    this,
322
                    "The database schema for the chosen "
323
                            + "datasource '"
324
                            + cdmSource
325
                            + "' \n is not compatible for this version of the taxonomic editor. \n\n"
326
                            + message,
327
                            null);
328

    
329
            monitor.setCanceled(true);
330
        }
331

    
332
    }
333

    
334
    private void checkIsNonEmptyCdmDatabase(IProgressMonitor monitor) {
335
        monitor.subTask("Checking if datasource is a non empty CDM database.");
336
        boolean isDbEmpty = false;
337
        try {
338
            isDbEmpty = cdmSource.isDbEmpty();
339
        } catch (CdmSourceException e) {
340
            isDbEmpty = true;
341
        }
342
        if(isDbEmpty) {
343
            dbSchemaValidation = DbSchemaValidation.CREATE;
344
        }
345
    }
346

    
347
    private boolean causeIsCancelationExceptionRecursive(Throwable throwable){
348
        if(throwable == null){
349
            return false;
350
        }else if(throwable instanceof CancellationException){
351
            return true;
352
        }else{
353
            return causeIsCancelationExceptionRecursive(throwable.getCause());
354
        }
355
    }
356

    
357
    private void checkDatabaseReachable(IProgressMonitor monitor) {
358
        try {
359
            monitor.subTask("Checking if datasource is reachable.");
360
            cdmSource.checkConnection();
361
            monitor.worked(1);
362
        } catch (CdmSourceException e) {
363
            MessagingUtils.messageDialog("Could not connect to chosen datasource",
364
                    this, "Reason: " + e.getMessage(), e);
365
            monitor.setCanceled(true);
366
        }
367
    }
368

    
369

    
370
}
(3-3/13)