3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
11 package eu
.etaxonomy
.taxeditor
.store
;
13 import java
.lang
.reflect
.InvocationTargetException
;
14 import java
.sql
.SQLException
;
15 import java
.util
.concurrent
.CancellationException
;
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
;
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
.taxeditor
.model
.CdmProgressMonitorAdapter
;
35 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
36 import eu
.etaxonomy
.taxeditor
.remoting
.source
.ICdmRemoteSource
;
37 import eu
.etaxonomy
.taxeditor
.ui
.dialog
.LoginDialog
;
38 import eu
.etaxonomy
.taxeditor
.ui
.dialog
.RemotingLoginDialog
;
39 import eu
.etaxonomy
.taxeditor
.view
.datasource
.CdmDataSourceViewPart
;
44 * @created Dec 8, 2010
47 class CdmStoreConnector
extends Job
{
48 private final Display display
;
49 private final ICdmSource cdmSource
;
50 private DbSchemaValidation dbSchemaValidation
;
51 private final Resource applicationContextBean
;
56 * @param dbSchemaValidation
57 * @param applicationContextBean
59 public CdmStoreConnector(Display display
,
61 DbSchemaValidation dbSchemaValidation
,
62 Resource applicationContextBean
) {
63 super("Connecting to datasource: " + cdmSource
);
64 this.display
= display
;
65 this.cdmSource
= cdmSource
;
66 this.dbSchemaValidation
= dbSchemaValidation
;
67 this.applicationContextBean
= applicationContextBean
;
73 public IStatus
run(final IProgressMonitor monitor
) {
75 monitor
.beginTask(getConnectionMessage(), 10);
77 // check if database is up and running
78 checkDatabaseReachable(monitor
);
80 if (!monitor
.isCanceled()) {
81 // check if the datasource actually holds data
82 checkIsNonEmptyCdmDatabase(monitor
);
85 if (dbSchemaValidation
!= DbSchemaValidation
.CREATE
86 && !monitor
.isCanceled()) {
87 // if we do not create the datasource, we want to check if the
88 // datasource is compatible with this editor
89 checkDbSchemaVersionCompatibility(monitor
);
92 // we are done with our low level checking and will free resources now
93 cdmSource
.closeOpenConnections();
95 if (!monitor
.isCanceled()) {
96 CdmStore
.close(monitor
);
99 ICdmApplicationConfiguration applicationController
= null;
101 if (!monitor
.isCanceled()) {
102 CdmProgressMonitorAdapter subprogressMonitor
= CdmProgressMonitorAdapter
103 .CreateSubMonitor(monitor
, 7);
104 // This is where we instantiate the application controller
105 int oldPriority
= Thread
.currentThread().getPriority();
107 Thread
.currentThread().setPriority(10);
108 applicationController
= getApplicationController(cdmSource
,subprogressMonitor
);
109 } catch (Exception e
) {
110 if(! causeIsCancelationExceptionRecursive(e
)){
111 return new Status(IStatus
.ERROR
, "Could not connect to CDM Store", "An error occurred while trying to connect to datasource: " + cdmSource
.getName(), e
);
115 Thread
.currentThread().setPriority(oldPriority
);
121 if (!monitor
.isCanceled()) {
122 CdmStore
.setInstance(applicationController
, cdmSource
);
124 display
.asyncExec(new Runnable() {
128 * @see java.lang.Runnable#run()
138 MessagingUtils
.info("Application context initialized.");
139 return Status
.OK_STATUS
;
141 // Show datasource view if not shown yet
142 display
.asyncExec(new Runnable() {
146 * @see java.lang.Runnable#run()
150 StoreUtil
.showView(CdmDataSourceViewPart
.ID
);
153 return Status
.CANCEL_STATUS
;
158 public void start(final RemotingLoginDialog loginDialog
) {
159 // hide login dialog and start connection dialog
160 loginDialog
.setMessage(null);
161 loginDialog
.hide(true);
164 ProgressMonitorDialog dialog
= new ProgressMonitorDialog(StoreUtil
.getShell());
167 dialog
.run(true, true, new IRunnableWithProgress() {
169 public void run(final IProgressMonitor monitor
) {
171 monitor
.beginTask(getConnectionMessage(), 7);
173 // check if database is up and running
174 checkDatabaseReachable(monitor
);
176 // check if the datasource actually holds data
177 checkIsNonEmptyCdmDatabase(monitor
);
179 if (dbSchemaValidation
!= DbSchemaValidation
.CREATE
) {
180 // if we do not create the datasource, we want to check if the
181 // datasource is compatible with this editor
182 checkDbSchemaVersionCompatibility(monitor
);
185 // we are done with our low level checking and will free resources now
186 cdmSource
.closeOpenConnections();
188 display
.syncExec(new Runnable() {
192 * @see java.lang.Runnable#run()
196 // close the current context
197 CdmStore
.close(monitor
, false);
201 ICdmApplicationConfiguration applicationController
= null;
203 if (!monitor
.isCanceled()) {
204 CdmProgressMonitorAdapter subprogressMonitor
= CdmProgressMonitorAdapter
205 .CreateSubMonitor(monitor
, 3);
206 // genrerate new application controller
207 applicationController
= getApplicationController(cdmSource
,subprogressMonitor
);
211 if (!monitor
.isCanceled()) {
212 CdmStore
.setInstance(applicationController
, cdmSource
);
213 monitor
.subTask("Authenticating user");
214 display
.syncExec(new Runnable() {
218 * @see java.lang.Runnable#run()
224 // create new security context
225 CdmStore
.getLoginManager().doAuthenticate(loginDialog
.getUsername(), loginDialog
.getPassword());
226 loginDialog
.onComplete();
227 CdmStore
.getContextManager().notifyContextStart();
228 } catch(CdmAuthenticationException cae
) {
229 loginDialog
.hide(false);
230 loginDialog
.setMessage(cae
.getMessage());
236 throw new RuntimeException("Login cancelled");
243 } catch (InvocationTargetException e
) {
244 loginDialog
.hide(false);
245 loginDialog
.setMessage(e
.getMessage());
246 } catch (InterruptedException e
) {
247 loginDialog
.hide(false);
248 loginDialog
.setMessage(e
.getMessage());
253 private ICdmApplicationConfiguration
getApplicationController(ICdmSource cdmSource
, CdmProgressMonitorAdapter subprogressMonitor
) {
254 if(cdmSource
instanceof ICdmDataSource
) {
255 return CdmApplicationController
.NewInstance(applicationContextBean
,
256 (ICdmDataSource
)cdmSource
,
260 } else if(cdmSource
instanceof ICdmRemoteSource
) {
261 return CdmApplicationRemoteController
.NewInstance((ICdmRemoteSource
)cdmSource
,
265 throw new UnsupportedOperationException("Cannot create application controller for " + cdmSource
.getName());
269 private void authenticate() {
270 LoginDialog saloginDialog
= new LoginDialog(StoreUtil
.getShell());
271 saloginDialog
.open();
274 private void startContext() {
275 CdmStore
.getContextManager().notifyContextStart();
281 private String
getConnectionMessage() {
282 return cdmSource
.getConnectionMessage();
287 * @throws SQLException
289 private void checkDbSchemaVersionCompatibility(IProgressMonitor monitor
) {
290 monitor
.subTask("Checking if datasource is compatible with this editor.");
291 String dbSchemaVersion
;
293 String message
= null;
295 dbSchemaVersion
= cdmSource
.getDbSchemaVersion();
296 // we assume that empty dbSchemaVersion means an empty database and
297 // skip version checking
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
= "Please update the Taxonomic Editor (Help->Check for Updates) or choose a compatible datasource";
305 } else if (compareVersion
< 0) {
306 message
= "Please update the chosen datasource or choose a new data source to connect to in the Datasource View.";
310 } catch (CdmSourceException e
) {
314 if (message
!= null) {
315 // Show an error message
318 "Datasource Compatibility Check failed",
320 "The database schema for the chosen "
323 + "' \n is not compatible for this version of the taxonomic editor. \n\n"
327 monitor
.setCanceled(true);
332 private void checkIsNonEmptyCdmDatabase(IProgressMonitor monitor
) {
333 monitor
.subTask("Checking if datasource is a non empty CDM database.");
334 boolean isDbEmpty
= false;
336 isDbEmpty
= cdmSource
.isDbEmpty();
337 } catch (CdmSourceException e
) {
341 dbSchemaValidation
= DbSchemaValidation
.CREATE
;
345 private boolean causeIsCancelationExceptionRecursive(Throwable throwable
){
346 if(throwable
== null){
348 }else if(throwable
instanceof CancellationException
){
351 return causeIsCancelationExceptionRecursive(throwable
.getCause());
355 private void checkDatabaseReachable(IProgressMonitor monitor
) {
357 monitor
.subTask("Checking if datasource is reachable.");
358 cdmSource
.checkConnection();
360 } catch (CdmSourceException e
) {
361 MessagingUtils
.messageDialog("Could not connect to chosen datasource",
362 this, "Reason: " + e
.getMessage(), e
);
363 monitor
.setCanceled(true);