- added combo controller to combo field in DerivateSearchView
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / store / CdmStoreConnector.java
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.database.DatabaseTypeEnum;
25 import eu.etaxonomy.cdm.database.DbSchemaValidation;
26 import eu.etaxonomy.cdm.database.ICdmDataSource;
27 import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
28 import eu.etaxonomy.cdm.model.metadata.CdmMetaData.MetaDataPropertyName;
29 import eu.etaxonomy.taxeditor.model.CdmProgressMonitorAdapter;
30 import eu.etaxonomy.taxeditor.ui.dialog.LoginDialog;
31 import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
32
33 /**
34 * @author n.hoffmann
35 * @created Dec 8, 2010
36 * @version 1.0
37 */
38 class CdmStoreConnector extends Job {
39 private final Display display;
40 private final ICdmDataSource dataSource;
41 private DbSchemaValidation dbSchemaValidation;
42 private final Resource applicationContextBean;
43
44 /**
45 * @param datasource
46 * @param dbSchemaValidation
47 * @param applicationContextBean
48 */
49 public CdmStoreConnector(Display display, ICdmDataSource datasource,
50 DbSchemaValidation dbSchemaValidation,
51 Resource applicationContextBean) {
52 super("Connecting to datasource: " + datasource);
53 this.display = display;
54 this.dataSource = datasource;
55 this.dbSchemaValidation = dbSchemaValidation;
56 this.applicationContextBean = applicationContextBean;
57 }
58
59 @Override
60 public IStatus run(final IProgressMonitor monitor) {
61
62 monitor.beginTask(getConnectionMessage(), 10);
63
64 // check if database is up and running
65 checkDatabaseReachable(monitor);
66
67 if (!monitor.isCanceled()) {
68 // check if the datasource actually holds data
69 checkIsNonEmptyCdmDatabase(monitor);
70 }
71
72 if (dbSchemaValidation != DbSchemaValidation.CREATE
73 && !monitor.isCanceled()) {
74 // if we do not create the datasource, we want to check if the
75 // datasource is compatible with this editor
76 checkDbSchemaVersionCompatibility(monitor);
77 }
78
79 // we are done with our low level checking and will free resources now
80 dataSource.closeOpenConnections();
81
82 if (!monitor.isCanceled()) {
83 CdmStore.close(monitor);
84 }
85
86 CdmApplicationController applicationController = null;
87
88 if (!monitor.isCanceled()) {
89 CdmProgressMonitorAdapter subprogressMonitor = CdmProgressMonitorAdapter
90 .CreateSubMonitor(monitor, 7);
91 // This is where we instantiate the application controller
92 try {
93 applicationController = CdmApplicationController.NewInstance(
94 applicationContextBean, dataSource, dbSchemaValidation,
95 false, subprogressMonitor);
96 } catch (Exception e) {
97 if(! causeIsCancelationExceptionRecursive(e)){
98 return new Status(IStatus.ERROR, "Could not connect to CDM Store", "An error occurred while trying to connect to datasource: " + dataSource.getName(), e);
99 }
100 } finally {
101 monitor.done();
102 }
103 }
104
105
106
107 if (!monitor.isCanceled()) {
108 CdmStore.setInstance(applicationController, dataSource);
109
110 display.asyncExec(new Runnable() {
111 /*
112 * (non-Javadoc)
113 *
114 * @see java.lang.Runnable#run()
115 */
116 @Override
117 public void run() {
118 authenticate();
119
120 startContext();
121 }
122 });
123
124 StoreUtil.info("Application context initialized.");
125 return Status.OK_STATUS;
126 } else {
127 // Show datasource view if not shown yet
128 display.asyncExec(new Runnable() {
129 /*
130 * (non-Javadoc)
131 *
132 * @see java.lang.Runnable#run()
133 */
134 @Override
135 public void run() {
136 StoreUtil.showView(CdmDataSourceViewPart.ID);
137 }
138 });
139 return Status.CANCEL_STATUS;
140 }
141
142 }
143
144 private void authenticate() {
145 LoginDialog loginDialog = new LoginDialog(StoreUtil.getShell());
146 loginDialog.open();
147 }
148
149 private void startContext() {
150 CdmStore.getContextManager().notifyContextStart();
151 }
152
153 /**
154 * @return
155 */
156 private String getConnectionMessage() {
157 String message = "";
158 if (dataSource.getDatabaseType().equals(DatabaseTypeEnum.H2)) {
159 message = " local CDM Store ";
160 } else {
161 message = " CDM Community Store ";
162 }
163 message += "'" + dataSource.getName() + "'";
164
165 message = "Connecting to" + message + ".";
166
167 return message;
168 }
169
170 /**
171 * @return
172 * @throws SQLException
173 */
174 private void checkDbSchemaVersionCompatibility(IProgressMonitor monitor) {
175 monitor.subTask("Checking if datasource is compatible with this editor.");
176 String dbSchemaVersion;
177 boolean result = false;
178 try {
179 dbSchemaVersion = (String) dataSource
180 .getSingleValue(MetaDataPropertyName.DB_SCHEMA_VERSION
181 .getSqlQuery());
182 // we assume that empty dbSchemaVersion means an empty database and
183 // skip version checking
184 result = dbSchemaVersion == null ? true : CdmMetaData
185 .isDbSchemaVersionCompatible(dbSchemaVersion);
186 monitor.worked(1);
187 } catch (SQLException e) {
188 //
189 }
190
191 if (!result) {
192 // Show an error message
193 StoreUtil
194 .errorDialog(
195 "DatabaseCompatibilityCheck failed",
196 this,
197 "The database schema for the chosen "
198 + "datasource '"
199 + dataSource
200 + "' \n is not valid for this version of the taxonomic editor. \n"
201 + "Please update the chosen datasource or choose a new data source to connect to in the Datasource View.",
202 null);
203
204 monitor.setCanceled(true);
205 }
206
207 }
208
209 private void checkIsNonEmptyCdmDatabase(IProgressMonitor monitor) {
210 monitor.subTask("Checking if datasource is a non empty CDM database.");
211
212 try {
213 dataSource.getSingleValue(MetaDataPropertyName.DB_SCHEMA_VERSION
214 .getSqlQuery());
215 } catch (SQLException e1) {
216 dbSchemaValidation = DbSchemaValidation.CREATE;
217 }
218 }
219
220 private boolean causeIsCancelationExceptionRecursive(Throwable throwable){
221 if(throwable == null){
222 return false;
223 }else if(throwable instanceof CancellationException){
224 return true;
225 }else{
226 return causeIsCancelationExceptionRecursive(throwable.getCause());
227 }
228 }
229
230 private void checkDatabaseReachable(IProgressMonitor monitor) {
231 try {
232 monitor.subTask("Checking if datasource is reachable.");
233 dataSource.testConnection();
234 monitor.worked(1);
235 } catch (ClassNotFoundException e) {
236 StoreUtil.errorDialog("Could not connect to chosen datasource",
237 this, "Reason: " + e.getMessage(), e);
238 monitor.setCanceled(true);
239 } catch (SQLException e) {
240 StoreUtil.errorDialog("Could not connect to chosen datasource",
241 this, "Reason: " + e.getMessage(), e);
242 monitor.setCanceled(true);
243 }
244
245 }
246 }