Project

General

Profile

Download (7.4 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.hibernate.collection.internal.AbstractPersistentCollection;
22
import org.hibernate.proxy.AbstractLazyInitializer;
23
import org.springframework.core.io.Resource;
24

    
25
import eu.etaxonomy.cdm.api.application.CdmApplicationController;
26
import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteController;
27
import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
28
import eu.etaxonomy.cdm.config.ICdmSource;
29
import eu.etaxonomy.cdm.remote.ICdmRemoteSource;
30
import eu.etaxonomy.cdm.config.CdmSourceException;
31
import eu.etaxonomy.cdm.database.DatabaseTypeEnum;
32
import eu.etaxonomy.cdm.database.DbSchemaValidation;
33
import eu.etaxonomy.cdm.database.ICdmDataSource;
34
import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
35
import eu.etaxonomy.cdm.model.metadata.CdmMetaData.MetaDataPropertyName;
36
import eu.etaxonomy.taxeditor.model.CdmProgressMonitorAdapter;
37
import eu.etaxonomy.taxeditor.model.MessagingUtils;
38
import eu.etaxonomy.taxeditor.ui.dialog.LoginDialog;
39
import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
40

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

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

    
67
	@Override
68
	public IStatus run(final IProgressMonitor monitor) {
69

    
70
		monitor.beginTask(getConnectionMessage(), 10);
71

    
72
		// check if database is up and running
73
		checkDatabaseReachable(monitor);
74

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

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

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

    
90
		if (!monitor.isCanceled()) {
91
			CdmStore.close(monitor);
92
		}
93

    
94
		ICdmApplicationConfiguration applicationController = null;
95

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

    
115
		if (!monitor.isCanceled()) {
116
			CdmStore.setInstance(applicationController, cdmSource);
117

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

    
128
					startContext();
129
				}
130
			});
131

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

    
150
	}
151

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

    
173
	private void startContext() {
174
		CdmStore.getContextManager().notifyContextStart();
175
	}
176

    
177
	/**
178
	 * @return
179
	 */
180
	private String getConnectionMessage() {
181
		return cdmSource.getConnectionMessage();
182
	}
183

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

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

    
216
			monitor.setCanceled(true);
217
		}
218

    
219
	}
220

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

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