Revert "ref #6118 catching exception during checkConnection"
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / store / CdmStore.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.util.EnumSet;
13
14 import org.eclipse.core.runtime.IProgressMonitor;
15 import org.eclipse.core.runtime.jobs.Job;
16 import org.eclipse.swt.widgets.Display;
17 import org.springframework.core.io.ClassPathResource;
18 import org.springframework.core.io.Resource;
19 import org.springframework.security.access.PermissionEvaluator;
20 import org.springframework.security.authentication.AuthenticationManager;
21 import org.springframework.security.core.Authentication;
22 import org.springframework.security.core.context.SecurityContext;
23 import org.springframework.security.core.context.SecurityContextHolder;
24
25 import eu.etaxonomy.cdm.api.application.CdmApplicationException;
26 import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteController;
27 import eu.etaxonomy.cdm.api.application.CdmApplicationState;
28 import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
29 import eu.etaxonomy.cdm.api.cache.CdmServiceCacher;
30 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
31 import eu.etaxonomy.cdm.api.service.IAgentService;
32 import eu.etaxonomy.cdm.api.service.ICollectionService;
33 import eu.etaxonomy.cdm.api.service.ICommonService;
34 import eu.etaxonomy.cdm.api.service.INameService;
35 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
36 import eu.etaxonomy.cdm.api.service.IPolytomousKeyService;
37 import eu.etaxonomy.cdm.api.service.IReferenceService;
38 import eu.etaxonomy.cdm.api.service.IService;
39 import eu.etaxonomy.cdm.api.service.IUserService;
40 import eu.etaxonomy.cdm.api.service.molecular.IAmplificationService;
41 import eu.etaxonomy.cdm.api.service.molecular.IPrimerService;
42 import eu.etaxonomy.cdm.config.ICdmSource;
43 import eu.etaxonomy.cdm.database.DbSchemaValidation;
44 import eu.etaxonomy.cdm.model.agent.AgentBase;
45 import eu.etaxonomy.cdm.model.common.CdmBase;
46 import eu.etaxonomy.cdm.model.common.Language;
47 import eu.etaxonomy.cdm.model.common.User;
48 import eu.etaxonomy.cdm.model.description.PolytomousKey;
49 import eu.etaxonomy.cdm.model.molecular.Amplification;
50 import eu.etaxonomy.cdm.model.molecular.Primer;
51 import eu.etaxonomy.cdm.model.name.NonViralName;
52 import eu.etaxonomy.cdm.model.occurrence.Collection;
53 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
54 import eu.etaxonomy.cdm.model.reference.Reference;
55 import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
56 import eu.etaxonomy.cdm.persistence.hibernate.permission.ICdmPermissionEvaluator;
57 import eu.etaxonomy.cdm.persistence.hibernate.permission.Role;
58 import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
59 import eu.etaxonomy.taxeditor.io.ExportManager;
60 import eu.etaxonomy.taxeditor.io.ImportManager;
61 import eu.etaxonomy.taxeditor.model.AbstractUtility;
62 import eu.etaxonomy.taxeditor.model.MessagingUtils;
63 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
64 import eu.etaxonomy.taxeditor.remoting.cache.CdmRemoteCacheManager;
65 import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
66 import eu.etaxonomy.taxeditor.session.mock.MockCdmEntitySessionManager;
67 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
68 import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
69 import eu.etaxonomy.taxeditor.util.ProgressMonitorClientManager;
70 import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
71 import eu.etaxonomy.taxeditor.webapp.CDMServer;
72
73 /**
74 * This implementation of ICdmDataRepository depends on hibernate sessions to
75 * store the data correctly for the current session. No state is held in this
76 * class.
77 *
78 * Only methods that either get or manipulate data are exposed here. So this
79 * class acts as a facade for the methods in cdmlib-service.
80 *
81 * @author n.hoffmann
82 * @created 17.03.2009
83 * @version 1.0
84 */
85 public class CdmStore {
86
87 private static final Resource DEFAULT_APPLICATION_CONTEXT = new ClassPathResource(
88 "/eu/etaxonomy/cdm/editorApplicationContext.xml",
89 TaxeditorStorePlugin.class);
90 private static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION = DbSchemaValidation.VALIDATE;
91
92 private static CdmStore instance;
93
94 //private final ICdmApplicationConfiguration applicationConfiguration;
95
96 private static ContextManager contextManager = new ContextManager();
97
98 private static LoginManager loginManager = new LoginManager();
99
100 private static TermManager termManager = new TermManager();
101
102 private static SearchManager searchManager = new SearchManager();
103
104 private static EditorManager editorManager = new EditorManager();
105
106 private static UseObjectStore useObjectInitializer = new UseObjectStore();
107
108 private static ProgressMonitorClientManager progressMonitorClientManager = new ProgressMonitorClientManager();
109
110 private static CdmStoreConnector job;
111
112 private static CDMServer managedServer;
113
114 private Language language;
115
116 private ICdmSource cdmSource;
117
118 private boolean isConnected;
119
120
121
122 /**
123 * <p>
124 * getDefault
125 * </p>
126 *
127 * @return a {@link eu.etaxonomy.taxeditor.store.CdmStore} object.
128 */
129 protected static CdmStore getDefault() {
130 if (instance != null && instance.isConnected) {
131 return instance;
132 } else{// if (instance == null || !instance.isConnected) {
133
134 MessagingUtils.noDataSourceWarningDialog(instance);
135
136 AbstractUtility.showView(CdmDataSourceViewPart.ID);
137 return null;
138 }
139 }
140
141 /**
142 * Initialize the with the last edited datasource
143 */
144 public static void connect() {
145
146 ICdmSource cdmSource;
147 try {
148
149 cdmSource = CdmDataSourceRepository.getCurrentCdmSource();
150 connect(cdmSource);
151 } catch (Exception e) {
152 MessagingUtils.messageDialog("Connection to CDM Source Failed", CdmStore.class, "Could not connect to target CDM Source", e);
153 }
154
155
156 }
157
158 /**
159 * Initialize with a specific datasource
160 *
161 * @param datasource
162 * a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
163 */
164 public static void connect(ICdmSource cdmSource) {
165 connect(cdmSource, DEFAULT_DB_SCHEMA_VALIDATION,
166 DEFAULT_APPLICATION_CONTEXT);
167 }
168
169 public static void connect(ICdmSource cdmSource, RemotingLoginDialog loginDialog) {
170 connect(cdmSource,
171 DEFAULT_DB_SCHEMA_VALIDATION,
172 DEFAULT_APPLICATION_CONTEXT,
173 loginDialog);
174 }
175
176 /**
177 * Initialize and provide
178 *
179 * @param datasource
180 * @param dbSchemaValidation
181 * @param applicationContextBean
182 */
183 private static void connect(final ICdmSource cdmSource,
184 final DbSchemaValidation dbSchemaValidation,
185 final Resource applicationContextBean) {
186
187 MessagingUtils.info("Connecting to datasource: " + cdmSource);
188
189 job = new CdmStoreConnector(Display.getDefault(), cdmSource,
190 dbSchemaValidation, applicationContextBean);
191 job.setUser(true);
192 job.setPriority(Job.BUILD);
193 job.schedule();
194
195 }
196
197 private static void connect(final ICdmSource cdmSource,
198 final DbSchemaValidation dbSchemaValidation,
199 final Resource applicationContextBean,
200 RemotingLoginDialog remotingLoginDialog) {
201 RemotingLoginDialog loginDialog = remotingLoginDialog;
202 if(isActive()) {
203 // before we connect we clear the entity caches and the sessions
204 CdmRemoteCacheManager.removeEntityCaches();
205 if(getCurrentSessionManager() != null) {
206 getCurrentSessionManager().disposeAll();
207 }
208 }
209 MessagingUtils.info("Connecting to datasource: " + cdmSource);
210
211 job = new CdmStoreConnector(Display.getDefault(),
212 cdmSource,
213 dbSchemaValidation,
214 applicationContextBean);
215 job.start(loginDialog);
216
217 }
218
219 public static boolean isConnecting() {
220 return job != null && job.getState() == Job.RUNNING;
221 }
222
223 /**
224 * Closes the current application context
225 *
226 * @param monitor
227 * a {@link org.eclipse.core.runtime.IProgressMonitor} object.
228 */
229 public static void close(final IProgressMonitor monitor) {
230 Display.getDefault().asyncExec(new Runnable() {
231 /*
232 * (non-Javadoc)
233 *
234 * @see java.lang.Runnable#run()
235 */
236 @Override
237 public void run() {
238 getContextManager().notifyContextAboutToStop(monitor);
239 if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
240 getContextManager().notifyContextStop(monitor);
241 instance.close();
242 }
243 }
244 });
245 }
246
247 public static void close(IProgressMonitor monitor, boolean async) {
248 if(async) {
249 close(monitor);
250 } else {
251 getContextManager().notifyContextAboutToStop(monitor);
252 if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
253 getContextManager().notifyContextStop(monitor);
254 instance.close();
255 }
256 }
257
258 }
259 private void close() {
260 isConnected = false;
261 cdmSource = null;
262 CdmApplicationState.dispose();
263 }
264
265 static void setInstance(ICdmApplicationConfiguration applicationController,
266 ICdmSource cdmSource) {
267 instance = new CdmStore(applicationController, cdmSource);
268 CdmApplicationState.setCdmServiceCacher(new CdmServiceCacher());
269
270 }
271
272 private CdmStore(ICdmApplicationConfiguration applicationController,
273 ICdmSource cdmSource) {
274 CdmApplicationState.setCurrentAppConfig(applicationController);
275 CdmApplicationState.setCurrentDataChangeService(new CdmUIDataChangeService());
276 this.cdmSource = cdmSource;
277 isConnected = true;
278 }
279
280 /**
281 * All calls to the datastore require
282 *
283 * @return
284 */
285 private ICdmApplicationConfiguration getApplicationConfiguration() {
286 try {
287 return CdmApplicationState.getCurrentAppConfig();
288 } catch (Exception e) {
289 MessagingUtils.error(CdmStore.class, e);
290 }
291 return null;
292 }
293
294 /**
295 * <p>
296 * getCurrentApplicationController
297 * </p>
298 *
299 * @return a
300 * {@link eu.etaxonomy.cdm.remote.api.application.CdmApplicationController}
301 * object.
302 */
303 public static ICdmApplicationConfiguration getCurrentApplicationConfiguration() {
304 if (getDefault() != null) {
305 return getDefault().getApplicationConfiguration();
306 }
307 return null;
308 }
309
310 /*
311 * CONVERSATIONS
312 */
313
314 /**
315 * Creates a new conversation, binds resources to the conversation and start
316 * a transaction for this conversation.
317 *
318 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
319 * object.
320 */
321 public static ConversationHolder createConversation() {
322 ConversationHolder conversation = getCurrentApplicationConfiguration()
323 .NewConversation();
324 try {
325 conversation.startTransaction();
326 }catch(Exception e){
327 MessagingUtils.messageDialog("No database connection", CdmStore.class, "No database connection available", e);
328 }
329 return conversation;
330 }
331
332 //FIXME:Remoting should be removed after moving completely to remoting
333 private MockCdmEntitySessionManager mockCdmEntitySessionManager;
334
335 private ICdmEntitySessionManager getSessionManager() {
336 //FIXME:Remoting we should only have CdmApplicationRemoteConfiguration after move to remoting
337 // bad hack which should be finally removed
338 if(getCurrentApplicationConfiguration() instanceof CdmApplicationRemoteController) {
339 return ((CdmApplicationRemoteController)getCurrentApplicationConfiguration()).getCdmEntitySessionManager();
340 } else {
341 if(mockCdmEntitySessionManager == null) {
342 mockCdmEntitySessionManager = new MockCdmEntitySessionManager();
343 }
344 return mockCdmEntitySessionManager;
345 }
346 }
347
348 public static ICdmEntitySessionManager getCurrentSessionManager() {
349 if (getDefault() != null) {
350 return getDefault().getSessionManager();
351 }
352 return null;
353
354 }
355
356 /**
357 * Generic method that will scan the getters of {@link ICdmApplicationConfiguration} for the given service
358 * interface. If a matching getter is found the according service implementation is returned by
359 * invoking the getter otherwise the method returns <code>null</code>.
360 *
361 * @param <T>
362 * @param serviceClass
363 * @return the configured implementation of <code>serviceClass</code> or <code>null</code>
364 */
365 public static <T extends IService> T getService(Class<T> serviceClass) {
366 T service = null;
367 try {
368 service = CdmApplicationState.getService(serviceClass);
369 } catch (CdmApplicationException cae) {
370 MessagingUtils.error(CdmStore.class, cae);
371 }
372
373 return service;
374 }
375
376 /**
377 * @see #getService(Class)
378 * As ICommonService is not extending IService we need a specific request here
379 */
380 public static ICommonService getCommonService() {
381 return CdmApplicationState.getCommonService();
382
383 }
384
385 /**
386 * <p>
387 * getAuthenticationManager
388 * </p>
389 *
390 * @return a
391 * {@link org.springframework.security.authentication.ProviderManager}
392 * object.
393 */
394 public static AuthenticationManager getAuthenticationManager() {
395 return getCurrentApplicationConfiguration().getAuthenticationManager();
396 }
397
398 /**
399 * <p>
400 * getAuthenticationManager
401 * </p>
402 *
403 * @return a
404 * {@link ICdmPermissionEvaluator} object.
405 */
406 public static ICdmPermissionEvaluator getPermissionEvaluator() {
407 return getCurrentApplicationConfiguration().getPermissionEvaluator();
408 }
409
410
411 /*
412 * SECURITY RELATED CONVENIENCE METHODS
413 */
414
415 /**
416 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
417 *
418 * @param targetDomainObject
419 * @param permission
420 * @return
421 */
422 public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject, EnumSet<CRUD> permission){
423 //TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
424 SecurityContext context = SecurityContextHolder.getContext();
425 PermissionEvaluator pe = getPermissionEvaluator();
426 boolean hasPermission = false;
427 try {
428 hasPermission = getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject,
429 permission);
430 } catch (org.springframework.security.access.AccessDeniedException e) {
431 /* IGNORE */
432 }
433 return hasPermission;
434 }
435
436 /**
437 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
438 *
439 * @param targetDomainObject
440 * @param permission
441 * @return
442 */
443 public static boolean currentAuthentiationHasPermission(Class<? extends CdmBase> targetType, EnumSet<CRUD> permission){
444 boolean hasPermission = false;
445 try {
446 hasPermission = getPermissionEvaluator().hasPermission(getCurrentAuthentiation(), null, targetType.getName(), permission);
447 } catch (org.springframework.security.access.AccessDeniedException e) {
448 /* IGNORE */
449 }
450 return hasPermission;
451 }
452
453 public static boolean currentAuthentiationHasOneOfRoles(Role ... roles){
454 boolean hasPermission = false;
455 try {
456 hasPermission = getPermissionEvaluator().hasOneOfRoles(getCurrentAuthentiation(), roles);
457 } catch (org.springframework.security.access.AccessDeniedException e) {
458 /* IGNORE */
459 }
460 return hasPermission;
461 }
462
463 public static Authentication getCurrentAuthentiation() {
464 SecurityContext context = SecurityContextHolder.getContext();
465 return context.getAuthentication();
466 }
467
468 /*
469 * LANGUAGE
470 */
471
472 /**
473 * Provides access to the global default language set in the application preferences.
474 *
475 * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
476 */
477 public static Language getDefaultLanguage() {
478 if (getDefault().getLanguage() == null) {
479 getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
480 }
481 return getDefault().getLanguage();
482 }
483
484 /**
485 * <p>
486 * setDefaultLanguage
487 * </p>
488 *
489 * @param language
490 * a {@link eu.etaxonomy.cdm.model.common.Language} object.
491 */
492 public static void setDefaultLanguage(Language language) {
493 getDefault().setLanguage(language);
494 }
495
496 /**
497 * @return the language
498 */
499 private Language getLanguage() {
500 return language;
501 }
502
503 /**
504 * @param language
505 * the language to set
506 */
507 private void setLanguage(Language language) {
508 this.language = language;
509 }
510
511 /*
512 * LOGIN
513 */
514
515 /**
516 * <p>
517 * Getter for the field <code>loginManager</code>.
518 * </p>
519 *
520 * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
521 */
522 public static LoginManager getLoginManager() {
523 return loginManager;
524 }
525
526 /**
527 * <p>
528 * Getter for the field <code>contextManager</code>.
529 * </p>
530 *
531 * @return a {@link eu.etaxonomy.taxeditor.store.ContextManager} object.
532 */
533 public static ContextManager getContextManager() {
534 return contextManager;
535 }
536
537 public static TermManager getTermManager() {
538 return termManager;
539 }
540
541 public static SearchManager getSearchManager() {
542 return searchManager;
543 }
544
545 public static EditorManager getEditorManager() {
546 return editorManager;
547 }
548
549 public static ProgressMonitorClientManager getProgressMonitorClientManager() {
550 return progressMonitorClientManager;
551 }
552
553 /*
554 * IMPORT/EXPORT FACTORIES
555 */
556
557 /**
558 * <p>
559 * Getter for the field <code>importHandler</code>.
560 * </p>
561 *
562 * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
563 */
564 public static ImportManager getImportManager() {
565 return ImportManager.NewInstance(getCurrentApplicationConfiguration());
566 }
567
568 /**
569 * <p>
570 * Getter for the field <code>exportHandler</code>.
571 * </p>
572 *
573 * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
574 */
575 public static ExportManager getExportManager() {
576 return ExportManager.NewInstance(getCurrentApplicationConfiguration());
577 }
578
579 /**
580 * Whether this CdmStore is currently connected to a datasource
581 *
582 * @return a boolean.
583 */
584 public static boolean isActive() {
585 return instance != null && instance.isConnected;
586 }
587
588 public static ICdmSource getActiveCdmSource() {
589 if (isActive()) {
590 return instance.getCdmSource();
591 }
592 return null;
593 }
594
595 /**
596 * <p>
597 * getDataSource
598 * </p>
599 *
600 * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
601 * @deprecated currently retained for backward compatibility - use {@link getActiveCdmSource()} instead
602 */
603 // public static ICdmDataSource getDataSource() {
604 // if (isActive()) {
605 // return (ICdmDataSource)instance.getCdmSource();
606 // }
607 // return null;
608 // }
609
610 /**
611 * @return
612 */
613 private ICdmSource getCdmSource() {
614 return cdmSource;
615 }
616
617
618 public static <T extends CdmBase> IService<T> getService(T cdmBase){
619 IService<T> service = null;
620 if(cdmBase!=null){
621 //get corresponding service
622 if(cdmBase.isInstanceOf(Reference.class)){
623 service = (IService<T>) getService(IReferenceService.class);
624 }
625 else if (cdmBase.isInstanceOf(AgentBase.class)){
626 service = (IService<T>) getService(IAgentService.class);
627 }
628 else if (cdmBase instanceof NonViralName) {
629 service = (IService<T>) getService(INameService.class);
630 }
631 else if (cdmBase instanceof SpecimenOrObservationBase) {
632 service = (IService<T>) getService(IOccurrenceService.class);
633 }
634 else if (cdmBase instanceof Collection) {
635 service = (IService<T>) getService(ICollectionService.class);
636 }
637 else if (cdmBase instanceof User) {
638 service = (IService<T>) getService(IUserService.class);
639 }
640 else if (cdmBase instanceof Primer) {
641 service = (IService<T>) getService(IPrimerService.class);
642 }
643 else if (cdmBase instanceof Amplification) {
644 service = (IService<T>) getService(IAmplificationService.class);
645 } else if (cdmBase instanceof PolytomousKey) {
646 service = (IService<T>) getService(IPolytomousKeyService.class);
647 }
648 }
649 return service;
650 }
651
652 public static void setManagedServer(CDMServer server) {
653 managedServer = server;
654 }
655
656 public static CDMServer getManagedServer() {
657 return managedServer;
658 }
659
660 }