Project

General

Profile

Download (14.6 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.term.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.event.EventUtility;
38
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
39
import eu.etaxonomy.taxeditor.l10n.Messages;
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.internal.TaxeditorStorePlugin;
44
import eu.etaxonomy.taxeditor.ui.dialog.LoginDialog;
45
import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
46

    
47

    
48
/**
49
 * @author n.hoffmann
50
 * @created Dec 8, 2010
51
 * @version 1.0
52
 */
53
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

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

    
76

    
77

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

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

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

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

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

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

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

    
105
        ICdmRepository applicationController = null;
106

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

    
136
    }
137

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

    
143

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

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

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

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

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

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

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

    
181
                        ICdmRepository applicationController = null;
182

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

    
190

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

    
203
                                    try {
204
                                        // create new security context
205
                                        CdmStore.getLoginManager().doAuthenticate(loginDialog.getUsername(), loginDialog.getPassword());
206
                                        //loginDialog.onComplete();
207
                                        CdmStore.getContextManager().notifyContextStart();
208
                                        loginDialog.onComplete();
209
                                        getInstance(Rank.class).resetTerms();
210
                                        getInstance(NomenclaturalStatusType.class).resetTerms();
211
                                        Rank.initDefaultTerms();
212
                                        NomenclaturalStatusType.initDefaultTerms();
213
                                    } catch(CdmAuthenticationException cae) {
214
                                        loginDialog.hide(false);
215
                                        loginDialog.setMessage("Your credentials are valid \nbut you are not permitted to use \nthe TaxEditor with the selected data source");
216

    
217
                                    }
218

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

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

    
255

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

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

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

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

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

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

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

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

    
326
            monitor.setCanceled(true);
327
        }
328

    
329
    }
330

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

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

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

    
366

    
367
}
(4-4/14)