Project

General

Profile

Download (21.3 KB) Statistics
| Branch: | Tag: | Revision:
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.IReferenceService;
37
import eu.etaxonomy.cdm.api.service.IService;
38
import eu.etaxonomy.cdm.api.service.IUserService;
39
import eu.etaxonomy.cdm.api.service.molecular.IAmplificationService;
40
import eu.etaxonomy.cdm.api.service.molecular.IPrimerService;
41
import eu.etaxonomy.cdm.config.ICdmSource;
42
import eu.etaxonomy.cdm.database.DbSchemaValidation;
43
import eu.etaxonomy.cdm.model.agent.AgentBase;
44
import eu.etaxonomy.cdm.model.common.CdmBase;
45
import eu.etaxonomy.cdm.model.common.Language;
46
import eu.etaxonomy.cdm.model.common.User;
47
import eu.etaxonomy.cdm.model.molecular.Amplification;
48
import eu.etaxonomy.cdm.model.molecular.Primer;
49
import eu.etaxonomy.cdm.model.name.NonViralName;
50
import eu.etaxonomy.cdm.model.occurrence.Collection;
51
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
52
import eu.etaxonomy.cdm.model.reference.Reference;
53
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
54
import eu.etaxonomy.cdm.persistence.hibernate.permission.ICdmPermissionEvaluator;
55
import eu.etaxonomy.cdm.persistence.hibernate.permission.Role;
56
import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
57
import eu.etaxonomy.taxeditor.io.ExportManager;
58
import eu.etaxonomy.taxeditor.io.ImportManager;
59
import eu.etaxonomy.taxeditor.model.AbstractUtility;
60
import eu.etaxonomy.taxeditor.model.MessagingUtils;
61
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
62
import eu.etaxonomy.taxeditor.remoting.cache.CdmRemoteCacheManager;
63
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
64
import eu.etaxonomy.taxeditor.session.mock.MockCdmEntitySessionManager;
65
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
66
import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
67
import eu.etaxonomy.taxeditor.util.ProgressMonitorClientManager;
68
import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
69
import eu.etaxonomy.taxeditor.webapp.CDMServer;
70

    
71
/**
72
 * This implementation of ICdmDataRepository depends on hibernate sessions to
73
 * store the data correctly for the current session. No state is held in this
74
 * class.
75
 *
76
 * Only methods that either get or manipulate data are exposed here. So this
77
 * class acts as a facade for the methods in cdmlib-service.
78
 *
79
 * @author n.hoffmann
80
 * @created 17.03.2009
81
 * @version 1.0
82
 */
83
public class CdmStore {
84

    
85
    private static final Resource DEFAULT_APPLICATION_CONTEXT = new ClassPathResource(
86
            "/eu/etaxonomy/cdm/editorApplicationContext.xml",
87
            TaxeditorStorePlugin.class);
88
    private static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION = DbSchemaValidation.VALIDATE;
89

    
90
    private static CdmStore instance;
91

    
92
    //private final ICdmApplicationConfiguration applicationConfiguration;
93

    
94
    private static ContextManager contextManager = new ContextManager();
95

    
96
    private static LoginManager loginManager = new LoginManager();
97

    
98
    private static TermManager termManager = new TermManager();
99

    
100
    private static SearchManager searchManager = new SearchManager();
101

    
102
    private static EditorManager editorManager = new EditorManager();
103

    
104
    private static UseObjectStore useObjectInitializer = new UseObjectStore();
105

    
106
    private static ProgressMonitorClientManager progressMonitorClientManager = new ProgressMonitorClientManager();
107

    
108
    private static CdmStoreConnector job;
109

    
110
    private static CDMServer managedServer;
111

    
112
    private Language language;
113

    
114
    private ICdmSource cdmSource;
115

    
116
    private boolean isConnected;
117

    
118

    
119

    
120
    /**
121
     * <p>
122
     * getDefault
123
     * </p>
124
     *
125
     * @return a {@link eu.etaxonomy.taxeditor.store.CdmStore} object.
126
     */
127
    protected static CdmStore getDefault() {
128
        if (instance != null && instance.isConnected) {
129
            return instance;
130
        } else{// if (instance == null || !instance.isConnected) {
131

    
132
            MessagingUtils.noDataSourceWarningDialog(instance);
133

    
134
            AbstractUtility.showView(CdmDataSourceViewPart.ID);
135
            return null;
136
        }
137
    }
138

    
139
    /**
140
     * Initialize the with the last edited datasource
141
     */
142
    public static void connect() {
143

    
144
        ICdmSource cdmSource;
145
        try {
146

    
147
            cdmSource = CdmDataSourceRepository.getCurrentCdmSource();
148
            connect(cdmSource);
149
        } catch (Exception e) {
150
            MessagingUtils.messageDialog("Connection to CDM Source Failed", CdmStore.class, "Could not connect to target CDM Source", e);
151
        }
152

    
153

    
154
    }
155

    
156
    /**
157
     * Initialize with a specific datasource
158
     *
159
     * @param datasource
160
     *            a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
161
     */
162
    public static void connect(ICdmSource cdmSource) {
163
        connect(cdmSource, DEFAULT_DB_SCHEMA_VALIDATION,
164
                DEFAULT_APPLICATION_CONTEXT);
165
    }
166

    
167
    public static void connect(ICdmSource cdmSource, RemotingLoginDialog loginDialog) {
168
        connect(cdmSource,
169
                DEFAULT_DB_SCHEMA_VALIDATION,
170
                DEFAULT_APPLICATION_CONTEXT,
171
                loginDialog);
172
    }
173

    
174
    /**
175
     * Initialize and provide
176
     *
177
     * @param datasource
178
     * @param dbSchemaValidation
179
     * @param applicationContextBean
180
     */
181
    private static void connect(final ICdmSource cdmSource,
182
            final DbSchemaValidation dbSchemaValidation,
183
            final Resource applicationContextBean) {
184

    
185
        MessagingUtils.info("Connecting to datasource: " + cdmSource);
186

    
187
        job = new CdmStoreConnector(Display.getDefault(), cdmSource,
188
                dbSchemaValidation, applicationContextBean);
189
        job.setUser(true);
190
        job.setPriority(Job.BUILD);
191
        job.schedule();
192

    
193
    }
194

    
195
    private static void connect(final ICdmSource cdmSource,
196
            final DbSchemaValidation dbSchemaValidation,
197
            final Resource applicationContextBean,
198
            RemotingLoginDialog remotingLoginDialog) {
199
        RemotingLoginDialog loginDialog = remotingLoginDialog;
200
        if(isActive()) {
201
            // before we connect we clear the entity caches and the sessions
202
            CdmRemoteCacheManager.removeEntityCaches();
203
            if(getCurrentSessionManager() != null) {
204
                getCurrentSessionManager().disposeAll();
205
            }
206
        }
207
        MessagingUtils.info("Connecting to datasource: " + cdmSource);
208

    
209
        job = new CdmStoreConnector(Display.getDefault(),
210
                cdmSource,
211
                dbSchemaValidation,
212
                applicationContextBean);
213
        job.start(loginDialog);
214

    
215
    }
216

    
217
    public static boolean isConnecting() {
218
        return job != null && job.getState() == Job.RUNNING;
219
    }
220

    
221
    /**
222
     * Closes the current application context
223
     *
224
     * @param monitor
225
     *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
226
     */
227
    public static void close(final IProgressMonitor monitor) {
228
        Display.getDefault().asyncExec(new Runnable() {
229
            /*
230
             * (non-Javadoc)
231
             *
232
             * @see java.lang.Runnable#run()
233
             */
234
            @Override
235
            public void run() {
236
                getContextManager().notifyContextAboutToStop(monitor);
237
                if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
238
                    getContextManager().notifyContextStop(monitor);
239
                    instance.close();
240
                }
241
            }
242
        });
243
    }
244

    
245
    public static void close(IProgressMonitor monitor, boolean async) {
246
        if(async) {
247
            close(monitor);
248
        } else {
249
            getContextManager().notifyContextAboutToStop(monitor);
250
            if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
251
                getContextManager().notifyContextStop(monitor);
252
                instance.close();
253
            }
254
        }
255

    
256
    }
257
    private void close() {
258
        isConnected = false;
259
        cdmSource = null;
260
        CdmApplicationState.dispose();
261
    }
262

    
263
    static void setInstance(ICdmApplicationConfiguration applicationController,
264
            ICdmSource cdmSource) {
265
        instance = new CdmStore(applicationController, cdmSource);
266
        if(getCurrentSessionManager().isRemoting()) {
267
            CdmApplicationState.setCdmServiceCacher(new CdmServiceCacher());
268
        }
269
    }
270

    
271
    private CdmStore(ICdmApplicationConfiguration applicationController,
272
            ICdmSource cdmSource) {
273
        CdmApplicationState.setCurrentAppConfig(applicationController);
274
        CdmApplicationState.setCurrentDataChangeService(new CdmUIDataChangeService());
275
        this.cdmSource = cdmSource;
276
        isConnected = true;
277
    }
278

    
279
    /**
280
     * All calls to the datastore require
281
     *
282
     * @return
283
     */
284
    private ICdmApplicationConfiguration getApplicationConfiguration() {
285
        try {
286
            return CdmApplicationState.getCurrentAppConfig();
287
        } catch (Exception e) {
288
            MessagingUtils.error(CdmStore.class, e);
289
        }
290
        return null;
291
    }
292

    
293
    /**
294
     * <p>
295
     * getCurrentApplicationController
296
     * </p>
297
     *
298
     * @return a
299
     *         {@link eu.etaxonomy.cdm.remote.api.application.CdmApplicationController}
300
     *         object.
301
     */
302
    public static ICdmApplicationConfiguration getCurrentApplicationConfiguration() {
303
        if (getDefault() != null) {
304
            return getDefault().getApplicationConfiguration();
305
        }
306
        return null;
307
    }
308

    
309
    /*
310
     * CONVERSATIONS
311
     */
312

    
313
    /**
314
     * Creates a new conversation, binds resources to the conversation and start
315
     * a transaction for this conversation.
316
     *
317
     * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
318
     *         object.
319
     */
320
    public static ConversationHolder createConversation() {
321
        ConversationHolder conversation = getCurrentApplicationConfiguration()
322
                .NewConversation();
323
        try {
324
            conversation.startTransaction();
325
        }catch(Exception e){
326
            MessagingUtils.messageDialog("No database connection", CdmStore.class, "No database connection available", e);
327
        }
328
        return conversation;
329
    }
330

    
331
    //FIXME:Remoting should be removed after moving completely to remoting
332
    private MockCdmEntitySessionManager mockCdmEntitySessionManager;
333

    
334
    private ICdmEntitySessionManager getSessionManager() {
335
        //FIXME:Remoting we should only have CdmApplicationRemoteConfiguration after move to remoting
336
        //               bad hack which should be finally removed
337
        if(getCurrentApplicationConfiguration() instanceof CdmApplicationRemoteController) {
338
            return ((CdmApplicationRemoteController)getCurrentApplicationConfiguration()).getCdmEntitySessionManager();
339
        } else {
340
            if(mockCdmEntitySessionManager == null) {
341
                mockCdmEntitySessionManager = new MockCdmEntitySessionManager();
342
            }
343
            return mockCdmEntitySessionManager;
344
        }
345
    }
346

    
347
    public static  ICdmEntitySessionManager getCurrentSessionManager() {
348
        if (getDefault() != null) {
349
            return getDefault().getSessionManager();
350
        }
351
        return null;
352

    
353
    }
354

    
355
    /**
356
     * Generic method that will scan the getters of {@link ICdmApplicationConfiguration} for the given service
357
     * interface. If a matching getter is found the according service implementation is returned by
358
     * invoking the getter otherwise the method returns <code>null</code>.
359
     *
360
     * @param <T>
361
     * @param serviceClass
362
     * @return the configured implementation of <code>serviceClass</code> or <code>null</code>
363
     */
364
    public static <T extends IService> T getService(Class<T> serviceClass) {
365
        T service = null;
366
        try {
367
            service = CdmApplicationState.getService(serviceClass);
368
        } catch (CdmApplicationException cae) {
369
            MessagingUtils.error(CdmStore.class, cae);
370
        }
371

    
372
        return service;
373
    }
374

    
375
    /**
376
     * @see #getService(Class)
377
     * As ICommonService is not extending IService we need a specific request here
378
     */
379
    public static ICommonService getCommonService() {
380
        return CdmApplicationState.getCommonService();
381

    
382
    }
383

    
384
    /**
385
     * <p>
386
     * getAuthenticationManager
387
     * </p>
388
     *
389
     * @return a
390
     *         {@link org.springframework.security.authentication.ProviderManager}
391
     *         object.
392
     */
393
    public static AuthenticationManager getAuthenticationManager() {
394
        return getCurrentApplicationConfiguration().getAuthenticationManager();
395
    }
396

    
397
    /**
398
     * <p>
399
     * getAuthenticationManager
400
     * </p>
401
     *
402
     * @return a
403
     *         {@link ICdmPermissionEvaluator} object.
404
     */
405
    public static ICdmPermissionEvaluator getPermissionEvaluator() {
406
        return getCurrentApplicationConfiguration().getPermissionEvaluator();
407
    }
408

    
409

    
410
    /*
411
     * SECURITY RELATED CONVENIENCE METHODS
412
     */
413

    
414
    /**
415
     * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
416
     *
417
     * @param targetDomainObject
418
     * @param permission
419
     * @return
420
     */
421
    public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject, EnumSet<CRUD> permission){
422
        //TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
423
        SecurityContext context = SecurityContextHolder.getContext();
424
        PermissionEvaluator pe = getPermissionEvaluator();
425
        boolean hasPermission = false;
426
        try {
427
            hasPermission = getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject,
428
                    permission);
429
        } catch (org.springframework.security.access.AccessDeniedException e) {
430
            /* IGNORE */
431
        }
432
        return hasPermission;
433
    }
434

    
435
    /**
436
     * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
437
     *
438
     * @param targetDomainObject
439
     * @param permission
440
     * @return
441
     */
442
    public static boolean currentAuthentiationHasPermission(Class<? extends CdmBase> targetType, EnumSet<CRUD> permission){
443
        boolean hasPermission = false;
444
        try {
445
            hasPermission = getPermissionEvaluator().hasPermission(getCurrentAuthentiation(), null, targetType.getName(), permission);
446
        } catch (org.springframework.security.access.AccessDeniedException e) {
447
            /* IGNORE */
448
        }
449
        return hasPermission;
450
    }
451

    
452
    public static boolean currentAuthentiationHasOneOfRoles(Role ... roles){
453
        boolean hasPermission = false;
454
        try {
455
            hasPermission =  getPermissionEvaluator().hasOneOfRoles(getCurrentAuthentiation(), roles);
456
        } catch (org.springframework.security.access.AccessDeniedException e) {
457
            /* IGNORE */
458
        }
459
        return hasPermission;
460
    }
461

    
462
    public static Authentication getCurrentAuthentiation() {
463
        SecurityContext context = SecurityContextHolder.getContext();
464
        return context.getAuthentication();
465
    }
466

    
467
    /*
468
     * LANGUAGE
469
     */
470

    
471
    /**
472
     * Provides access to the global default language set in the application preferences.
473
     *
474
     * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
475
     */
476
    public static Language getDefaultLanguage() {
477
        if (getDefault().getLanguage() == null) {
478
            getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
479
        }
480
        return getDefault().getLanguage();
481
    }
482

    
483
    /**
484
     * <p>
485
     * setDefaultLanguage
486
     * </p>
487
     *
488
     * @param language
489
     *            a {@link eu.etaxonomy.cdm.model.common.Language} object.
490
     */
491
    public static void setDefaultLanguage(Language language) {
492
        getDefault().setLanguage(language);
493
    }
494

    
495
    /**
496
     * @return the language
497
     */
498
    private Language getLanguage() {
499
        return language;
500
    }
501

    
502
    /**
503
     * @param language
504
     *            the language to set
505
     */
506
    private void setLanguage(Language language) {
507
        this.language = language;
508
    }
509

    
510
    /*
511
     * LOGIN
512
     */
513

    
514
    /**
515
     * <p>
516
     * Getter for the field <code>loginManager</code>.
517
     * </p>
518
     *
519
     * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
520
     */
521
    public static LoginManager getLoginManager() {
522
        return loginManager;
523
    }
524

    
525
    /**
526
     * <p>
527
     * Getter for the field <code>contextManager</code>.
528
     * </p>
529
     *
530
     * @return a {@link eu.etaxonomy.taxeditor.store.ContextManager} object.
531
     */
532
    public static ContextManager getContextManager() {
533
        return contextManager;
534
    }
535

    
536
    public static TermManager getTermManager() {
537
        return termManager;
538
    }
539

    
540
    public static SearchManager getSearchManager() {
541
        return searchManager;
542
    }
543

    
544
    public static EditorManager getEditorManager() {
545
        return editorManager;
546
    }
547

    
548
    public static ProgressMonitorClientManager getProgressMonitorClientManager() {
549
        return progressMonitorClientManager;
550
    }
551

    
552
    /*
553
     * IMPORT/EXPORT FACTORIES
554
     */
555

    
556
    /**
557
     * <p>
558
     * Getter for the field <code>importHandler</code>.
559
     * </p>
560
     *
561
     * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
562
     */
563
    public static ImportManager getImportManager() {
564
        return ImportManager.NewInstance(getCurrentApplicationConfiguration());
565
    }
566

    
567
    /**
568
     * <p>
569
     * Getter for the field <code>exportHandler</code>.
570
     * </p>
571
     *
572
     * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
573
     */
574
    public static ExportManager getExportManager() {
575
        return ExportManager.NewInstance(getCurrentApplicationConfiguration());
576
    }
577

    
578
    /**
579
     * Whether this CdmStore is currently connected to a datasource
580
     *
581
     * @return a boolean.
582
     */
583
    public static boolean isActive() {
584
        return instance != null && instance.isConnected;
585
    }
586

    
587
    public static ICdmSource getActiveCdmSource() {
588
        if (isActive()) {
589
            return instance.getCdmSource();
590
        }
591
        return null;
592
    }
593

    
594
    /**
595
     * <p>
596
     * getDataSource
597
     * </p>
598
     *
599
     * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
600
     * @deprecated currently retained for backward compatibility - use {@link getActiveCdmSource()} instead
601
     */
602
    //	public static ICdmDataSource getDataSource() {
603
    //		if (isActive()) {
604
    //			return (ICdmDataSource)instance.getCdmSource();
605
    //		}
606
    //		return null;
607
    //	}
608

    
609
    /**
610
     * @return
611
     */
612
    private ICdmSource getCdmSource() {
613
        return cdmSource;
614
    }
615

    
616

    
617
    public static <T extends CdmBase> IService<T> getService(T cdmBase){
618
        IService<T> service = null;
619
        if(cdmBase!=null){
620
            //get corresponding service
621
            if(cdmBase.isInstanceOf(Reference.class)){
622
                service = (IService<T>) getService(IReferenceService.class);
623
            }
624
            else if (cdmBase.isInstanceOf(AgentBase.class)){
625
                service = (IService<T>) getService(IAgentService.class);
626
            }
627
            else if (cdmBase instanceof NonViralName) {
628
                service = (IService<T>) getService(INameService.class);
629
            }
630
            else if (cdmBase instanceof SpecimenOrObservationBase) {
631
                service = (IService<T>) getService(IOccurrenceService.class);
632
            }
633
            else if (cdmBase instanceof Collection) {
634
                service = (IService<T>) getService(ICollectionService.class);
635
            }
636
            else if (cdmBase instanceof User) {
637
                service = (IService<T>) getService(IUserService.class);
638
            }
639
            else if (cdmBase instanceof Primer) {
640
                service = (IService<T>) getService(IPrimerService.class);
641
            }
642
            else if (cdmBase instanceof Amplification) {
643
                service = (IService<T>) getService(IAmplificationService.class);
644
            }
645
        }
646
        return service;
647
    }
648

    
649
    public static void setManagedServer(CDMServer server) {
650
        managedServer = server;
651
    }
652

    
653
    public static CDMServer getManagedServer() {
654
        return managedServer;
655
    }
656

    
657
}
(2-2/13)