d1665cb8e78c7ab60bad5ad033153f43895d95f0
[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.api.application.CdmApplicationRemoteController;
25 import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
26 import eu.etaxonomy.cdm.config.ICdmSource;
27 import eu.etaxonomy.cdm.remote.ICdmRemoteSource;
28 import eu.etaxonomy.cdm.config.CdmSourceException;
29 import eu.etaxonomy.cdm.database.DatabaseTypeEnum;
30 import eu.etaxonomy.cdm.database.DbSchemaValidation;
31 import eu.etaxonomy.cdm.database.ICdmDataSource;
32 import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
33 import eu.etaxonomy.cdm.model.metadata.CdmMetaData.MetaDataPropertyName;
34 import eu.etaxonomy.taxeditor.model.CdmProgressMonitorAdapter;
35 import eu.etaxonomy.taxeditor.ui.dialog.LoginDialog;
36 import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
37
38 /**
39 * @author n.hoffmann
40 * @created Dec 8, 2010
41 * @version 1.0
42 */
43 class CdmStoreConnector extends Job {
44 private final Display display;
45 private final ICdmSource cdmSource;
46 private DbSchemaValidation dbSchemaValidation;
47 private final Resource applicationContextBean;
48
49 /**
50 * @param datasource
51 * @param dbSchemaValidation
52 * @param applicationContextBean
53 */
54 public CdmStoreConnector(Display display, ICdmSource cdmSource,
55 DbSchemaValidation dbSchemaValidation,
56 Resource applicationContextBean) {
57 super("Connecting to datasource: " + cdmSource);
58 this.display = display;
59 this.cdmSource = cdmSource;
60 this.dbSchemaValidation = dbSchemaValidation;
61 this.applicationContextBean = applicationContextBean;
62 }
63
64 @Override
65 public IStatus run(final IProgressMonitor monitor) {
66
67 monitor.beginTask(getConnectionMessage(), 10);
68
69 // check if database is up and running
70 checkDatabaseReachable(monitor);
71
72 if (!monitor.isCanceled()) {
73 // check if the datasource actually holds data
74 checkIsNonEmptyCdmDatabase(monitor);
75 }
76
77 if (dbSchemaValidation != DbSchemaValidation.CREATE
78 && !monitor.isCanceled()) {
79 // if we do not create the datasource, we want to check if the
80 // datasource is compatible with this editor
81 checkDbSchemaVersionCompatibility(monitor);
82 }
83
84 // we are done with our low level checking and will free resources now
85 cdmSource.closeOpenConnections();
86
87 if (!monitor.isCanceled()) {
88 CdmStore.close(monitor);
89 }
90
91 ICdmApplicationConfiguration applicationController = null;
92
93 if (!monitor.isCanceled()) {
94 CdmProgressMonitorAdapter subprogressMonitor = CdmProgressMonitorAdapter
95 .CreateSubMonitor(monitor, 7);
96 // This is where we instantiate the application controller
97 try {
98
99 applicationController = getApplicationController(cdmSource,subprogressMonitor);
100
101 } catch (Exception e) {
102 if(! causeIsCancelationExceptionRecursive(e)){
103 return new Status(IStatus.ERROR, "Could not connect to CDM Store", "An error occurred while trying to connect to datasource: " + cdmSource.getName(), e);
104 }
105 } finally {
106 monitor.done();
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 StoreUtil.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(applicationContextBean,
158 (ICdmRemoteSource)cdmSource,
159 false,
160 subprogressMonitor,
161 null);
162 } else {
163 throw new UnsupportedOperationException("Cannot create application controller for " + cdmSource.getName());
164 }
165 }
166 private void authenticate() {
167 LoginDialog loginDialog = new LoginDialog(StoreUtil.getShell());
168 loginDialog.open();
169 }
170
171 private void startContext() {
172 CdmStore.getContextManager().notifyContextStart();
173 }
174
175 /**
176 * @return
177 */
178 private String getConnectionMessage() {
179 return cdmSource.getConnectionMessage();
180 }
181
182 /**
183 * @return
184 * @throws SQLException
185 */
186 private void checkDbSchemaVersionCompatibility(IProgressMonitor monitor) {
187 monitor.subTask("Checking if datasource is compatible with this editor.");
188 String dbSchemaVersion;
189 boolean result = false;
190 try {
191 dbSchemaVersion = cdmSource.getDbSchemaVersion();
192 // we assume that empty dbSchemaVersion means an empty database and
193 // skip version checking
194 result = dbSchemaVersion == null ? true : CdmMetaData
195 .isDbSchemaVersionCompatible(dbSchemaVersion);
196 monitor.worked(1);
197 } catch (CdmSourceException e) {
198 //
199 }
200
201 if (!result) {
202 // Show an error message
203 StoreUtil
204 .errorDialog(
205 "DatabaseCompatibilityCheck failed",
206 this,
207 "The database schema for the chosen "
208 + "datasource '"
209 + cdmSource
210 + "' \n is not valid for this version of the taxonomic editor. \n"
211 + "Please update the chosen datasource or choose a new data source to connect to in the Datasource View.",
212 null);
213
214 monitor.setCanceled(true);
215 }
216
217 }
218
219 private void checkIsNonEmptyCdmDatabase(IProgressMonitor monitor) {
220 monitor.subTask("Checking if datasource is a non empty CDM database.");
221 boolean isDbEmpty = false;
222 try {
223 isDbEmpty = cdmSource.isDbEmpty();
224 } catch (CdmSourceException e) {
225 isDbEmpty = true;
226 }
227 if(isDbEmpty) {
228 dbSchemaValidation = DbSchemaValidation.CREATE;
229 }
230 }
231
232 private boolean causeIsCancelationExceptionRecursive(Throwable throwable){
233 if(throwable == null){
234 return false;
235 }else if(throwable instanceof CancellationException){
236 return true;
237 }else{
238 return causeIsCancelationExceptionRecursive(throwable.getCause());
239 }
240 }
241
242 private void checkDatabaseReachable(IProgressMonitor monitor) {
243 try {
244 monitor.subTask("Checking if datasource is reachable.");
245 cdmSource.checkConnection();
246 monitor.worked(1);
247 } catch (CdmSourceException e) {
248 StoreUtil.errorDialog("Could not connect to chosen datasource",
249 this, "Reason: " + e.getMessage(), e);
250 monitor.setCanceled(true);
251 }
252 }
253 }