add loading of default language to CdmStoreConnector
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / store / CdmStoreConnector.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.taxeditor.store;
11
12 import java.lang.reflect.InvocationTargetException;
13 import java.util.concurrent.CancellationException;
14
15 import org.eclipse.core.runtime.IProgressMonitor;
16 import org.eclipse.core.runtime.IStatus;
17 import org.eclipse.core.runtime.Status;
18 import org.eclipse.core.runtime.jobs.Job;
19 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
20 import org.eclipse.jface.operation.IRunnableWithProgress;
21 import org.eclipse.swt.widgets.Display;
22 import org.springframework.core.io.Resource;
23
24 import eu.etaxonomy.cdm.api.application.CdmApplicationController;
25 import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteController;
26 import eu.etaxonomy.cdm.api.application.ICdmRepository;
27 import eu.etaxonomy.cdm.config.CdmSourceException;
28 import eu.etaxonomy.cdm.config.ICdmSource;
29 import eu.etaxonomy.cdm.database.DbSchemaValidation;
30 import eu.etaxonomy.cdm.database.ICdmDataSource;
31 import eu.etaxonomy.cdm.model.common.Language;
32 import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
33 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
34 import eu.etaxonomy.cdm.model.name.Rank;
35 import eu.etaxonomy.cdm.model.term.init.TermLoader;
36 import eu.etaxonomy.taxeditor.event.EventUtility;
37 import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
38 import eu.etaxonomy.taxeditor.l10n.Messages;
39 import eu.etaxonomy.taxeditor.model.AbstractUtility;
40 import eu.etaxonomy.taxeditor.model.CdmProgressMonitorAdapter;
41 import eu.etaxonomy.taxeditor.model.MessagingUtils;
42 import eu.etaxonomy.taxeditor.remoting.source.ICdmRemoteSource;
43 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
44 import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
45
46 /**
47 * @author n.hoffmann
48 * @created Dec 8, 2010
49 */
50 class CdmStoreConnector extends Job {
51 private final Display display;
52 private final ICdmSource cdmSource;
53 private DbSchemaValidation dbSchemaValidation;
54 private final Resource applicationContextBean;
55
56 public CdmStoreConnector(Display display,
57 ICdmSource cdmSource,
58 DbSchemaValidation dbSchemaValidation,
59 Resource applicationContextBean) {
60 super(String.format(Messages.CdmStoreConnector_CREATING_DATAMODEL, 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 ICdmRepository 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 int oldPriority = Thread.currentThread().getPriority();
101 try {
102 Thread.currentThread().setPriority(10);
103 applicationController = getApplicationController(cdmSource,subprogressMonitor);
104 MessagingUtils.informationDialog(Messages.CdmStoreConnector_SUCCESS, Messages.CdmStoreConnector_DATA_MODEL_CREATION_SUCCESSFUL);
105 //FIXME E4 migrate or delete because data source view is not used anymore
106 // CdmDataSourceViewPartE4 dataSourceView = (CdmDataSourceViewPartE4) WorkbenchUtility.getE4WrappedPart(AbstractUtility.getView("eu.etaxonomy.taxeditor.view.datasource", false));
107 // if(dataSourceView!=null){
108 // dataSourceView.refresh();
109 // }
110 EventUtility.postEvent(WorkbenchEventConstants.REFRESH_DATASOURCE, true);
111 return Status.OK_STATUS;
112 } catch (Exception e) {
113 if(! causeIsCancelationExceptionRecursive(e)){
114 MessagingUtils.errorDialog(Messages.CdmStoreConnector_COULD_NOT_CREATE_DATAMODEL, CdmStoreConnector.class,
115 String.format(Messages.CdmStoreConnector_ERROR_DURING_DATAMODEL_CREATION, cdmSource.getName()), TaxeditorStorePlugin.PLUGIN_ID, e, true);
116 return Status.CANCEL_STATUS;
117 }
118 } finally {
119 monitor.done();
120 Thread.currentThread().setPriority(oldPriority);
121 }
122 }
123 return Status.CANCEL_STATUS;
124 }
125
126 public void start(final RemotingLoginDialog loginDialog) {
127 // hide login dialog and start connection dialog
128 loginDialog.setMessage(null);
129 loginDialog.hide(true);
130
131 ProgressMonitorDialog dialog = new ProgressMonitorDialog(AbstractUtility.getShell());
132
133 try {
134 dialog.run(true, true, new IRunnableWithProgress() {
135 @Override
136 public void run(final IProgressMonitor monitor) {
137 try {
138 monitor.beginTask(getConnectionMessage(), 7);
139
140 // check if database is up and running
141 checkDatabaseReachable(monitor);
142
143 // check if the datasource actually holds data
144 checkIsNonEmptyCdmDatabase(monitor);
145
146 if (dbSchemaValidation != DbSchemaValidation.CREATE) {
147 // if we do not create the datasource, we want to check if the
148 // datasource is compatible with this editor
149 checkDbSchemaVersionCompatibility(monitor);
150 }
151
152 // we are done with our low level checking and will free resources now
153 cdmSource.closeOpenConnections();
154
155 display.syncExec(new Runnable() {
156 @Override
157 public void run() {
158 // close the current context
159 CdmStore.close(monitor, false);
160 }
161 });
162
163 ICdmRepository applicationController = null;
164
165 if (!monitor.isCanceled()) {
166 CdmProgressMonitorAdapter subprogressMonitor = CdmProgressMonitorAdapter
167 .CreateSubMonitor(monitor, 3);
168 // genrerate new application controller
169 applicationController = getApplicationController(cdmSource,subprogressMonitor);
170 }
171
172 if (!monitor.isCanceled()) {
173 CdmStore.setInstance(applicationController, cdmSource);
174 monitor.subTask(Messages.CdmStoreConnector_AUTHENTICATING_USER);
175 display.syncExec(()-> {
176 try {
177 // create new security context
178 CdmStore.getLoginManager().doAuthenticate(loginDialog.getUsername(), loginDialog.getPassword());
179 //loginDialog.onComplete();
180 CdmStore.getContextManager().notifyContextStart();
181 loginDialog.onComplete();
182 new TermLoader().unloadAllTerms();
183 Rank.initDefaultTerms();
184 NomenclaturalStatusType.initDefaultTerms();
185 Language.getDefaultLanguage();
186 } catch(CdmAuthenticationException cae) {
187 loginDialog.hide(false);
188 loginDialog.setMessage(LoginManager.INCORRECT_CREDENTIALS_MESSAGE);
189 }
190 });
191 } else {
192 throw new RuntimeException("Login cancelled");
193 }
194 } finally {
195 monitor.done();
196 }
197 }
198 });
199 } catch (InvocationTargetException e) {
200 loginDialog.hide(false);
201 loginDialog.setMessage(e.getMessage());
202 } catch (InterruptedException e) {
203 loginDialog.hide(false);
204 loginDialog.setMessage(e.getMessage());
205 }
206 }
207
208 private ICdmRepository getApplicationController(ICdmSource cdmSource, CdmProgressMonitorAdapter subprogressMonitor) {
209 if(cdmSource instanceof ICdmDataSource) {
210 return CdmApplicationController.NewInstance(applicationContextBean,
211 (ICdmDataSource)cdmSource,
212 dbSchemaValidation,
213 false,
214 subprogressMonitor);
215 } else if(cdmSource instanceof ICdmRemoteSource) {
216 return CdmApplicationRemoteController.NewInstance((ICdmRemoteSource)cdmSource,
217 subprogressMonitor,
218 null);
219 } else {
220 throw new UnsupportedOperationException("Cannot create application controller for " + cdmSource.getName());
221 }
222 }
223
224 private String getConnectionMessage() {
225 return cdmSource.getConnectionMessage();
226 }
227
228 private void checkDbSchemaVersionCompatibility(IProgressMonitor monitor) {
229 monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_EDITOR_IS_COMPATIBLE);
230 String dbSchemaVersion;
231
232 String message = null;
233 try {
234 dbSchemaVersion = cdmSource.getDbSchemaVersion();
235 // we assume that empty dbSchemaVersion means an empty database and
236 // skip version checking
237
238 if(dbSchemaVersion != null) {
239 int compareVersion = CdmMetaData.compareVersion(dbSchemaVersion, CdmMetaData.getDbSchemaVersion(), 3, null);
240 // if the datasource version is greater than the taxeditor compatible version then the taxeditor needs to
241 // be updated else the datasource needs to be updated
242 if(compareVersion > 0) {
243 message = Messages.CdmStoreConnector_UPDATE_EDITOR_OR_CHOOSE_COMPATIBLE_DATASOURCE;
244 } else if (compareVersion < 0) {
245 message = Messages.CdmStoreConnector_UPDATE_DATASOUREC_OR_CHOOSE_NEW_DATASOURCE;
246 }
247 }
248 monitor.worked(1);
249 } catch (CdmSourceException e) {
250 //
251 }
252
253 if (message != null) {
254 // Show an error message
255 MessagingUtils
256 .messageDialog(
257 Messages.CdmStoreConnector_COMPATIBILITY_CHECK_FAILED,
258 this,
259 String.format(Messages.CdmStoreConnector_SCHEME_NOT_COMPATIBLE, cdmSource, message),
260 null);
261
262 monitor.setCanceled(true);
263 }
264 }
265
266 private void checkIsNonEmptyCdmDatabase(IProgressMonitor monitor) {
267 monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_NON_EMPTY);
268 boolean isDbEmpty = false;
269 try {
270 isDbEmpty = cdmSource.isDbEmpty();
271 } catch (CdmSourceException e) {
272 isDbEmpty = true;
273 }
274 if(isDbEmpty) {
275 dbSchemaValidation = DbSchemaValidation.CREATE;
276 }
277 }
278
279 private boolean causeIsCancelationExceptionRecursive(Throwable throwable){
280 if(throwable == null){
281 return false;
282 }else if(throwable instanceof CancellationException){
283 return true;
284 }else{
285 return causeIsCancelationExceptionRecursive(throwable.getCause());
286 }
287 }
288
289 private void checkDatabaseReachable(IProgressMonitor monitor) {
290 try {
291 monitor.subTask(Messages.CdmStoreConnector_CHECK_IF_REACHABLE);
292 cdmSource.checkConnection();
293 monitor.worked(1);
294 } catch (CdmSourceException e) {
295 MessagingUtils.messageDialog(Messages.CdmStoreConnector_COULD_NOT_CONNECT_TO_CHOSEN_DATASOURCE,
296 this, Messages.CdmStoreConnector_REASON + e.getMessage(), e);
297 monitor.setCanceled(true);
298 }
299 }
300 }