2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
.store
;
12 import java
.util
.EnumSet
;
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
.slf4j
.Marker
;
18 import org
.springframework
.core
.io
.ClassPathResource
;
19 import org
.springframework
.core
.io
.Resource
;
20 import org
.springframework
.security
.authentication
.AuthenticationManager
;
21 import org
.springframework
.security
.core
.Authentication
;
22 import org
.springframework
.security
.core
.GrantedAuthority
;
23 import org
.springframework
.security
.core
.context
.SecurityContext
;
24 import org
.springframework
.security
.core
.context
.SecurityContextHolder
;
26 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationException
;
27 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationRemoteController
;
28 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationState
;
29 import eu
.etaxonomy
.cdm
.api
.application
.ICdmRepository
;
30 import eu
.etaxonomy
.cdm
.api
.cache
.CdmServiceCacher
;
31 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
32 import eu
.etaxonomy
.cdm
.api
.service
.IAgentService
;
33 import eu
.etaxonomy
.cdm
.api
.service
.IAnnotationService
;
34 import eu
.etaxonomy
.cdm
.api
.service
.IClassificationService
;
35 import eu
.etaxonomy
.cdm
.api
.service
.ICollectionService
;
36 import eu
.etaxonomy
.cdm
.api
.service
.ICommonService
;
37 import eu
.etaxonomy
.cdm
.api
.service
.IDescriptionService
;
38 import eu
.etaxonomy
.cdm
.api
.service
.IDescriptiveDataSetService
;
39 import eu
.etaxonomy
.cdm
.api
.service
.IEntityConstraintViolationService
;
40 import eu
.etaxonomy
.cdm
.api
.service
.IEntityValidationService
;
41 import eu
.etaxonomy
.cdm
.api
.service
.IGrantedAuthorityService
;
42 import eu
.etaxonomy
.cdm
.api
.service
.IGroupService
;
43 import eu
.etaxonomy
.cdm
.api
.service
.IMarkerService
;
44 import eu
.etaxonomy
.cdm
.api
.service
.IMediaService
;
45 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
46 import eu
.etaxonomy
.cdm
.api
.service
.IOccurrenceService
;
47 import eu
.etaxonomy
.cdm
.api
.service
.IPolytomousKeyNodeService
;
48 import eu
.etaxonomy
.cdm
.api
.service
.IPolytomousKeyService
;
49 import eu
.etaxonomy
.cdm
.api
.service
.IReferenceService
;
50 import eu
.etaxonomy
.cdm
.api
.service
.IRegistrationService
;
51 import eu
.etaxonomy
.cdm
.api
.service
.IRightsService
;
52 import eu
.etaxonomy
.cdm
.api
.service
.IService
;
53 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonService
;
54 import eu
.etaxonomy
.cdm
.api
.service
.ITermNodeService
;
55 import eu
.etaxonomy
.cdm
.api
.service
.ITermService
;
56 import eu
.etaxonomy
.cdm
.api
.service
.ITermTreeService
;
57 import eu
.etaxonomy
.cdm
.api
.service
.IUserService
;
58 import eu
.etaxonomy
.cdm
.api
.service
.IVocabularyService
;
59 import eu
.etaxonomy
.cdm
.api
.service
.molecular
.IAmplificationService
;
60 import eu
.etaxonomy
.cdm
.api
.service
.molecular
.IPrimerService
;
61 import eu
.etaxonomy
.cdm
.cache
.CdmRemoteCacheManager
;
62 import eu
.etaxonomy
.cdm
.config
.ICdmSource
;
63 import eu
.etaxonomy
.cdm
.database
.DbSchemaValidation
;
64 import eu
.etaxonomy
.cdm
.model
.agent
.AgentBase
;
65 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
66 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
67 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
68 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
69 import eu
.etaxonomy
.cdm
.model
.description
.DescriptiveDataSet
;
70 import eu
.etaxonomy
.cdm
.model
.description
.PolytomousKey
;
71 import eu
.etaxonomy
.cdm
.model
.description
.PolytomousKeyNode
;
72 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
73 import eu
.etaxonomy
.cdm
.model
.media
.Rights
;
74 import eu
.etaxonomy
.cdm
.model
.molecular
.Amplification
;
75 import eu
.etaxonomy
.cdm
.model
.molecular
.Primer
;
76 import eu
.etaxonomy
.cdm
.model
.name
.Registration
;
77 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
78 import eu
.etaxonomy
.cdm
.model
.occurrence
.Collection
;
79 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
80 import eu
.etaxonomy
.cdm
.model
.permission
.CRUD
;
81 import eu
.etaxonomy
.cdm
.model
.permission
.Group
;
82 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
83 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
84 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
85 import eu
.etaxonomy
.cdm
.model
.term
.DefinedTermBase
;
86 import eu
.etaxonomy
.cdm
.model
.term
.TermNode
;
87 import eu
.etaxonomy
.cdm
.model
.term
.TermTree
;
88 import eu
.etaxonomy
.cdm
.model
.term
.TermVocabulary
;
89 import eu
.etaxonomy
.cdm
.model
.validation
.EntityConstraintViolation
;
90 import eu
.etaxonomy
.cdm
.model
.validation
.EntityValidation
;
91 import eu
.etaxonomy
.cdm
.persistence
.permission
.ICdmPermissionEvaluator
;
92 import eu
.etaxonomy
.cdm
.persistence
.permission
.Role
;
93 import eu
.etaxonomy
.taxeditor
.io
.ExportManager
;
94 import eu
.etaxonomy
.taxeditor
.io
.ImportManager
;
95 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
96 import eu
.etaxonomy
.taxeditor
.preference
.PreferencesUtil
;
97 import eu
.etaxonomy
.taxeditor
.session
.ICdmEntitySessionManager
;
98 import eu
.etaxonomy
.taxeditor
.session
.mock
.MockCdmEntitySessionManager
;
99 import eu
.etaxonomy
.taxeditor
.store
.internal
.TaxeditorStorePlugin
;
100 import eu
.etaxonomy
.taxeditor
.ui
.dialog
.RemotingLoginDialog
;
101 import eu
.etaxonomy
.taxeditor
.util
.ProgressMonitorClientManager
;
104 * This implementation of ICdmDataRepository depends on hibernate sessions to
105 * store the data correctly for the current session. No state is held in this
108 * Only methods that either get or manipulate data are exposed here. So this
109 * class acts as a facade for the methods in cdmlib-service.
112 * @created 17.03.2009
114 public class CdmStore
{
116 public static final Resource DEFAULT_APPLICATION_CONTEXT
= new ClassPathResource(
117 "/eu/etaxonomy/cdm/editorApplicationContext.xml",
118 TaxeditorStorePlugin
.class);
120 public static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION
= DbSchemaValidation
.VALIDATE
;
122 protected static CdmStore instance
;
124 private static ContextManager contextManager
= new ContextManager();
126 private static LoginManager loginManager
= new LoginManager();
128 private static TermManager termManager
= new TermManager();
130 private static SearchManager searchManager
= new SearchManager();
132 private static UseObjectStore useObjectInitializer
= new UseObjectStore();
134 private static ProgressMonitorClientManager progressMonitorClientManager
= new ProgressMonitorClientManager();
136 private static CdmStoreConnector job
;
138 // private static CdmServer managedServer;
140 private Language language
;
142 private ICdmSource cdmSource
;
144 private boolean isConnected
;
146 protected static CdmStore
getDefault(boolean connecting
){
147 if (instance
!= null && instance
.isConnected()) {
149 } else{// if (instance == null || !instance.isConnected) {
151 MessagingUtils
.dataSourceNotAvailableWarningDialog(instance
);
153 MessagingUtils
.noDataSourceWarningDialog(instance
);
159 protected static CdmStore
getDefault(){
160 return getDefault(false);
164 * Initialize the with the last edited datasource
165 * @deprecated this method is not needed anymore after fully changing to remoting.
166 * Therefore it will be removed
169 // public static void connect() {
171 // ICdmSource cdmSource = CdmDataSourceRepository.getCurrentCdmSource();
172 // connect(cdmSource);
173 // } catch (Exception e) {
174 // MessagingUtils.messageDialog("Connection to CDM Source Failed", CdmStore.class, "Could not connect to target CDM Source", e);
179 * Initialize with a specific datasource
182 * a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
184 public static void connect(ICdmSource cdmSource
) {
185 connect(cdmSource
, DEFAULT_DB_SCHEMA_VALIDATION
,
186 DEFAULT_APPLICATION_CONTEXT
);
189 public static void connect(ICdmSource cdmSource
, RemotingLoginDialog loginDialog
) {
191 DEFAULT_DB_SCHEMA_VALIDATION
,
192 DEFAULT_APPLICATION_CONTEXT
,
197 * Initialize and provide
200 * @param dbSchemaValidation
201 * @param applicationContextBean
203 private static void connect(final ICdmSource cdmSource
,
204 final DbSchemaValidation dbSchemaValidation
,
205 final Resource applicationContextBean
) {
207 MessagingUtils
.info("Connecting to datasource: " + cdmSource
);
209 job
= new CdmStoreConnector(Display
.getDefault(), cdmSource
,
210 dbSchemaValidation
, applicationContextBean
);
212 job
.setPriority(Job
.BUILD
);
216 private static void connect(final ICdmSource cdmSource
,
217 final DbSchemaValidation dbSchemaValidation
,
218 final Resource applicationContextBean
,
219 RemotingLoginDialog remotingLoginDialog
) {
220 RemotingLoginDialog loginDialog
= remotingLoginDialog
;
222 // before we connect we clear the entity caches and the sessions
223 CdmRemoteCacheManager
.removeEntityCaches();
224 if(getCurrentSessionManager(true) != null) {
225 getCurrentSessionManager(true).disposeAll();
228 MessagingUtils
.info("Connecting to datasource: " + cdmSource
);
230 job
= new CdmStoreConnector(Display
.getDefault(),
233 applicationContextBean
);
234 job
.start(loginDialog
);
238 public static boolean isConnecting() {
239 return job
!= null && job
.getState() == Job
.RUNNING
;
243 * Closes the current application context
246 * a {@link org.eclipse.core.runtime.IProgressMonitor} object.
248 public static void close(final IProgressMonitor monitor
) {
249 Display
.getDefault().asyncExec(new Runnable() {
253 getContextManager().notifyContextAboutToStop(monitor
);
254 if ((monitor
== null || (!monitor
.isCanceled()) && isActive())) {
255 getContextManager().notifyContextStop(monitor
);
262 public static void close(IProgressMonitor monitor
, boolean async
) {
266 getContextManager().notifyContextAboutToStop(monitor
);
267 if ((monitor
== null || (!monitor
.isCanceled()) && isActive())) {
268 getContextManager().notifyContextStop(monitor
);
274 private void close() {
275 this.setConnected(false);
276 this.cdmSource
= null;
277 CdmApplicationState
.dispose();
280 public static void setInstance(ICdmRepository applicationController
,
281 ICdmSource cdmSource
) {
282 instance
= new CdmStore(applicationController
, cdmSource
);
283 CdmApplicationState
.setCdmServiceCacher(new CdmServiceCacher());
286 protected CdmStore(ICdmRepository repository
,
287 ICdmSource cdmSource
) {
288 CdmApplicationState
.setCurrentAppConfig(repository
);
289 CdmApplicationState
.setCurrentDataChangeService(new CdmUIDataChangeService());
290 this.cdmSource
= cdmSource
;
295 * All calls to the datastore require
299 private ICdmRepository
getApplicationConfiguration() {
301 return CdmApplicationState
.getCurrentAppConfig();
302 } catch (Exception e
) {
303 MessagingUtils
.error(CdmStore
.class, e
);
308 public static ICdmRepository
getCurrentApplicationConfiguration() {
309 if (getDefault() != null) {
310 return getDefault().getApplicationConfiguration();
320 * Creates a new conversation, binds resources to the conversation and start
321 * a transaction for this conversation.
323 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
326 public static ConversationHolder
createConversation() {
327 ConversationHolder conversation
= getCurrentApplicationConfiguration()
330 conversation
.startTransaction();
332 MessagingUtils
.messageDialog("No database connection", CdmStore
.class, "No database connection available", e
);
337 //FIXME:Remoting should be removed after moving completely to remoting
338 private MockCdmEntitySessionManager mockCdmEntitySessionManager
;
340 private ICdmEntitySessionManager
getSessionManager() {
341 //FIXME:Remoting we should only have CdmApplicationRemoteConfiguration after move to remoting
342 // bad hack which should be finally removed
343 if(getCurrentApplicationConfiguration() instanceof CdmApplicationRemoteController
) {
344 return ((CdmApplicationRemoteController
)getCurrentApplicationConfiguration()).getCdmEntitySessionManager();
346 if(mockCdmEntitySessionManager
== null) {
347 mockCdmEntitySessionManager
= new MockCdmEntitySessionManager();
349 return mockCdmEntitySessionManager
;
352 public static ICdmEntitySessionManager
getCurrentSessionManager() {
353 return getCurrentSessionManager(false);
356 public static ICdmEntitySessionManager
getCurrentSessionManager(boolean connecting
) {
357 if (getDefault(connecting
) != null) {
358 return getDefault(connecting
).getSessionManager();
364 * Generic method that will scan the getters of {@link ICdmRepository} for the given service
365 * interface. If a matching getter is found the according service implementation is returned by
366 * invoking the getter otherwise the method returns <code>null</code>.
369 * @param serviceClass
370 * @return the configured implementation of <code>serviceClass</code> or <code>null</code>
372 public static <T
extends IService
> T
getService(Class
<T
> serviceClass
) {
375 service
= CdmApplicationState
.getService(serviceClass
);
376 } catch (CdmApplicationException cae
) {
377 MessagingUtils
.error(CdmStore
.class, cae
);
384 * @see #getService(Class)
385 * As ICommonService is not extending IService we need a specific request here
387 public static ICommonService
getCommonService() {
388 return CdmApplicationState
.getCommonService();
391 public static AuthenticationManager
getAuthenticationManager() {
392 return getCurrentApplicationConfiguration().getAuthenticationManager();
395 public static ICdmPermissionEvaluator
getPermissionEvaluator() {
396 return getCurrentApplicationConfiguration().getPermissionEvaluator();
400 * SECURITY RELATED CONVENIENCE METHODS
404 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
406 * @param targetDomainObject
410 public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject
, EnumSet
<CRUD
> permission
){
411 //TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
412 SecurityContext context
= SecurityContextHolder
.getContext();
413 boolean hasPermission
= false;
415 hasPermission
= getPermissionEvaluator().hasPermission(context
.getAuthentication(), targetDomainObject
,
417 } catch (org
.springframework
.security
.access
.AccessDeniedException e
) {
420 return hasPermission
;
424 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
426 * @param targetDomainObject
430 public static boolean currentAuthentiationHasPermission(Class
<?
extends CdmBase
> targetType
, EnumSet
<CRUD
> permission
){
431 boolean hasPermission
= false;
433 hasPermission
= getPermissionEvaluator().hasPermission(getCurrentAuthentiation(), null, targetType
.getName(), permission
);
434 } catch (org
.springframework
.security
.access
.AccessDeniedException e
) {
437 return hasPermission
;
440 public static boolean currentAuthentiationHasOneOfRoles(Role
... roles
){
441 boolean hasPermission
= false;
443 hasPermission
= getPermissionEvaluator().hasOneOfRoles(getCurrentAuthentiation(), roles
);
444 } catch (org
.springframework
.security
.access
.AccessDeniedException e
) {
447 return hasPermission
;
450 public static Authentication
getCurrentAuthentiation() {
451 SecurityContext context
= SecurityContextHolder
.getContext();
452 return context
.getAuthentication();
460 * Provides access to the global default language set in the application preferences.
462 * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
464 public static Language
getDefaultLanguage() {
465 if (getDefault().getLanguage() == null) {
466 getDefault().setLanguage(PreferencesUtil
.getGlobalLanguage());
468 return getDefault().getLanguage();
471 public static void setDefaultLanguage(Language language
) {
472 getDefault().setLanguage(language
);
475 private Language
getLanguage() {
479 private void setLanguage(Language language
) {
480 this.language
= language
;
487 public static LoginManager
getLoginManager() {
491 public static ContextManager
getContextManager() {
492 return contextManager
;
495 public static TermManager
getTermManager() {
499 public static SearchManager
getSearchManager() {
500 return searchManager
;
504 public static ProgressMonitorClientManager
getProgressMonitorClientManager() {
505 return progressMonitorClientManager
;
509 * IMPORT/EXPORT FACTORIES
512 public static ImportManager
getImportManager() {
513 return ImportManager
.NewInstance(getCurrentApplicationConfiguration());
516 public static ExportManager
getExportManager() {
517 return ExportManager
.NewInstance(getCurrentApplicationConfiguration());
521 * Whether this CdmStore is currently connected to a datasource
525 public static boolean isActive() {
526 return instance
!= null && instance
.isConnected();
529 public static ICdmSource
getActiveCdmSource() {
531 return instance
.getCdmSource();
536 private ICdmSource
getCdmSource() {
540 @SuppressWarnings("unchecked")
541 public static <T
extends CdmBase
> IService
<T
> getService(T cdmBase
){
542 IService
<T
> service
= null;
544 //get corresponding service
545 if(cdmBase
.isInstanceOf(Reference
.class)){
546 service
= (IService
<T
>) getService(IReferenceService
.class);
548 else if (cdmBase
.isInstanceOf(AgentBase
.class)){
549 service
= (IService
<T
>) getService(IAgentService
.class);
551 else if (cdmBase
instanceof TaxonName
) {
552 service
= (IService
<T
>) getService(INameService
.class);
554 else if (cdmBase
instanceof TaxonBase
) {
555 service
= (IService
<T
>) getService(ITaxonService
.class);
557 else if (cdmBase
instanceof SpecimenOrObservationBase
) {
558 service
= (IService
<T
>) getService(IOccurrenceService
.class);
560 else if (cdmBase
instanceof Media
) {
561 service
= (IService
<T
>) getService(IMediaService
.class);
563 else if (cdmBase
instanceof Collection
) {
564 service
= (IService
<T
>) getService(ICollectionService
.class);
566 else if (cdmBase
instanceof eu
.etaxonomy
.cdm
.model
.permission
.User
) {
567 service
= (IService
<T
>) getService(IUserService
.class);
569 else if (cdmBase
instanceof Group
) {
570 service
= (IService
<T
>) getService(IGroupService
.class);
572 else if (cdmBase
instanceof DescriptiveDataSet
) {
573 service
= (IService
<T
>) getService(IDescriptiveDataSetService
.class);
575 else if (cdmBase
instanceof TermVocabulary
<?
>) {
576 service
= (IService
<T
>) getService(IVocabularyService
.class);
578 else if (cdmBase
instanceof DefinedTermBase
<?
>) {
579 service
= (IService
<T
>) getService(ITermService
.class);
581 else if (cdmBase
instanceof Primer
) {
582 service
= (IService
<T
>) getService(IPrimerService
.class);
584 else if (cdmBase
instanceof Amplification
) {
585 service
= (IService
<T
>) getService(IAmplificationService
.class);
587 else if (cdmBase
instanceof PolytomousKey
) {
588 service
= (IService
<T
>) getService(IPolytomousKeyService
.class);
590 else if (cdmBase
instanceof PolytomousKeyNode
) {
591 service
= (IService
<T
>) getService(IPolytomousKeyNodeService
.class);
593 else if (cdmBase
instanceof Annotation
) {
594 service
= (IService
<T
>) getService(IAnnotationService
.class);
596 else if (cdmBase
instanceof Classification
) {
597 service
= (IService
<T
>) getService(IClassificationService
.class);
599 else if (cdmBase
instanceof DescriptionBase
<?
>) {
600 service
= (IService
<T
>) getService(IDescriptionService
.class);
602 else if (cdmBase
instanceof EntityConstraintViolation
) {
603 service
= (IService
<T
>) getService(IEntityConstraintViolationService
.class);
605 else if (cdmBase
instanceof EntityValidation
) {
606 service
= (IService
<T
>) getService(IEntityValidationService
.class);
608 else if (cdmBase
instanceof TermNode
) {
609 service
= (IService
<T
>) getService(ITermNodeService
.class);
611 else if (cdmBase
instanceof TermTree
) {
612 service
= (IService
<T
>) getService(ITermTreeService
.class);
614 else if (cdmBase
instanceof GrantedAuthority
) {
615 service
= (IService
<T
>) getService(IGrantedAuthorityService
.class);
617 else if (cdmBase
instanceof Marker
) {
618 service
= (IService
<T
>) getService(IMarkerService
.class);
620 else if (cdmBase
instanceof Registration
) {
621 service
= (IService
<T
>) getService(IRegistrationService
.class);
623 else if (cdmBase
instanceof Rights
) {
624 service
= (IService
<T
>) getService(IRightsService
.class);
627 String message
= "Service for entity of class %s not yet implemented in TaxEditor";
628 message
= String
.format(message
, cdmBase
.getClass().getSimpleName());
629 throw new RuntimeException(message
);
636 // public static void setManagedServer(ICdmServer server) {
637 // managedServer = server;
640 // public static ICdmServer getManagedServer() {
641 // return managedServer;
643 public boolean isConnected() {
647 public void setConnected(boolean isConnected
) {
648 this.isConnected
= isConnected
;