Project

General

Profile

Download (7.3 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.sql.SQLException;
14
import java.util.concurrent.CancellationException;
15

    
16
import org.eclipse.core.runtime.IProgressMonitor;
17
import org.eclipse.core.runtime.IStatus;
18
import org.eclipse.core.runtime.Status;
19
import org.eclipse.core.runtime.jobs.Job;
20
import org.eclipse.swt.widgets.Display;
21
import org.springframework.core.io.Resource;
22

    
23
import eu.etaxonomy.cdm.api.application.CdmApplicationController;
24
import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteController;
25
import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
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.database.ICdmDataSource;
30
import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
31
import eu.etaxonomy.cdm.remote.ICdmRemoteSource;
32
import eu.etaxonomy.taxeditor.model.CdmProgressMonitorAdapter;
33
import eu.etaxonomy.taxeditor.model.MessagingUtils;
34
import eu.etaxonomy.taxeditor.ui.dialog.LoginDialog;
35
import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
36

    
37
/**
38
 * @author n.hoffmann
39
 * @created Dec 8, 2010
40
 * @version 1.0
41
 */
42
class CdmStoreConnector extends Job {
43
	private final Display display;
44
	private final ICdmSource cdmSource;
45
	private DbSchemaValidation dbSchemaValidation;
46
	private final Resource applicationContextBean;
47

    
48
	/**
49
	 * @param datasource
50
	 * @param dbSchemaValidation
51
	 * @param applicationContextBean
52
	 */
53
	public CdmStoreConnector(Display display, ICdmSource cdmSource,
54
			DbSchemaValidation dbSchemaValidation,
55
			Resource applicationContextBean) {
56
		super("Connecting to datasource: " + cdmSource);
57
		this.display = display;
58
		this.cdmSource = cdmSource;
59
		this.dbSchemaValidation = dbSchemaValidation;
60
		this.applicationContextBean = applicationContextBean;
61
	}
62

    
63
	@Override
64
	public IStatus run(final IProgressMonitor monitor) {
65

    
66
		monitor.beginTask(getConnectionMessage(), 10);
67
		
68
		// check if database is up and running
69
		checkDatabaseReachable(monitor);
70

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

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

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

    
86
		if (!monitor.isCanceled()) {
87
			CdmStore.close(monitor);
88
		}
89

    
90
		ICdmApplicationConfiguration applicationController = null;
91

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

    
112
		if (!monitor.isCanceled()) {
113
			CdmStore.setInstance(applicationController, cdmSource);
114

    
115
			display.asyncExec(new Runnable() {
116
				/*
117
				 * (non-Javadoc)
118
				 * 
119
				 * @see java.lang.Runnable#run()
120
				 */
121
				@Override
122
				public void run() {
123
					authenticate();
124

    
125
					startContext();
126
				}
127
			});
128

    
129
			MessagingUtils.info("Application context initialized.");
130
			return Status.OK_STATUS;
131
		} else {
132
			// Show datasource view if not shown yet
133
			display.asyncExec(new Runnable() {
134
				/*
135
				 * (non-Javadoc)
136
				 * 
137
				 * @see java.lang.Runnable#run()
138
				 */
139
				@Override
140
				public void run() {
141
					StoreUtil.showView(CdmDataSourceViewPart.ID);
142
				}
143
			});
144
			return Status.CANCEL_STATUS;
145
		}
146

    
147
	}
148

    
149
	private ICdmApplicationConfiguration getApplicationController(ICdmSource cdmSource, CdmProgressMonitorAdapter subprogressMonitor) {
150
		if(cdmSource instanceof ICdmDataSource) {
151
			return  CdmApplicationController.NewInstance(applicationContextBean, 
152
					(ICdmDataSource)cdmSource, 
153
					dbSchemaValidation,
154
					false, 
155
					subprogressMonitor);
156
		} else if(cdmSource instanceof ICdmRemoteSource) {
157
			return CdmApplicationRemoteController.NewInstance((ICdmRemoteSource)cdmSource, 					
158
							false, 
159
							subprogressMonitor,
160
							null);
161
		} else {
162
			throw new UnsupportedOperationException("Cannot create application controller for " + cdmSource.getName());
163
		}
164
	}
165
	private void authenticate() {
166
		LoginDialog loginDialog = new LoginDialog(StoreUtil.getShell());
167
		loginDialog.open();
168
	}
169

    
170
	private void startContext() {
171
		CdmStore.getContextManager().notifyContextStart();
172
	}
173

    
174
	/**
175
	 * @return
176
	 */
177
	private String getConnectionMessage() {
178
		return cdmSource.getConnectionMessage();
179
	}
180

    
181
	/**
182
	 * @return
183
	 * @throws SQLException
184
	 */
185
	private void checkDbSchemaVersionCompatibility(IProgressMonitor monitor) {
186
		monitor.subTask("Checking if datasource is compatible with this editor.");
187
		String dbSchemaVersion;
188
		boolean result = false;
189
		try {
190
			dbSchemaVersion = cdmSource.getDbSchemaVersion();
191
			// we assume that empty dbSchemaVersion means an empty database and
192
			// skip version checking
193
			result = dbSchemaVersion == null ? true : CdmMetaData
194
					.isDbSchemaVersionCompatible(dbSchemaVersion);
195
			monitor.worked(1);
196
		} catch (CdmSourceException e) {
197
			//
198
		}
199

    
200
		if (!result) {
201
			// Show an error message
202
			MessagingUtils
203
					.messageDialog(
204
							"DatabaseCompatibilityCheck failed",
205
							this,
206
							"The database schema for the chosen "
207
									+ "datasource '"
208
									+ cdmSource
209
									+ "' \n is not valid for this version of the taxonomic editor. \n"
210
									+ "Please update the chosen datasource or choose a new data source to connect to in the Datasource View.",
211
							null);
212

    
213
			monitor.setCanceled(true);
214
		}
215

    
216
	}
217

    
218
	private void checkIsNonEmptyCdmDatabase(IProgressMonitor monitor) {
219
		monitor.subTask("Checking if datasource is a non empty CDM database.");
220
		boolean isDbEmpty = false;
221
		try {
222
			isDbEmpty = cdmSource.isDbEmpty();
223
		} catch (CdmSourceException e) {
224
			isDbEmpty = true;
225
		}
226
		if(isDbEmpty) {
227
			dbSchemaValidation = DbSchemaValidation.CREATE;
228
		}
229
	}
230

    
231
	private boolean causeIsCancelationExceptionRecursive(Throwable throwable){
232
		if(throwable == null){
233
			return false;
234
		}else if(throwable instanceof CancellationException){
235
			return true;
236
		}else{
237
			return causeIsCancelationExceptionRecursive(throwable.getCause());
238
		}
239
	}
240
	
241
	private void checkDatabaseReachable(IProgressMonitor monitor) {
242
		try {
243
			monitor.subTask("Checking if datasource is reachable.");
244
			cdmSource.checkConnection();
245
			monitor.worked(1);
246
		} catch (CdmSourceException e) {
247
			MessagingUtils.messageDialog("Could not connect to chosen datasource",
248
					this, "Reason: " + e.getMessage(), e);
249
			monitor.setCanceled(true);
250
		} 
251
	}
252
}
(2-2/9)