Project

General

Profile

Download (7.33 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.ui.dialog.LoginDialog;
38
import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
39

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

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

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

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

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

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

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

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

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

    
93
		ICdmApplicationConfiguration applicationController = null;
94

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

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

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

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

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

    
149
	}
150

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

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

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

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

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

    
215
			monitor.setCanceled(true);
216
		}
217

    
218
	}
219

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

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