Project

General

Profile

Download (18.9 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.ICommonService;
32
import eu.etaxonomy.cdm.api.service.IService;
33
import eu.etaxonomy.cdm.config.ICdmSource;
34
import eu.etaxonomy.cdm.database.DbSchemaValidation;
35
import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
36
import eu.etaxonomy.cdm.model.common.CdmBase;
37
import eu.etaxonomy.cdm.model.common.Language;
38
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
39
import eu.etaxonomy.cdm.persistence.hibernate.permission.ICdmPermissionEvaluator;
40
import eu.etaxonomy.cdm.persistence.hibernate.permission.Role;
41
import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
42
import eu.etaxonomy.taxeditor.io.ExportManager;
43
import eu.etaxonomy.taxeditor.io.ImportManager;
44
import eu.etaxonomy.taxeditor.model.AbstractUtility;
45
import eu.etaxonomy.taxeditor.model.MessagingUtils;
46
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
47
import eu.etaxonomy.taxeditor.remoting.cache.CdmRemoteCacheManager;
48
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
49
import eu.etaxonomy.taxeditor.session.mock.MockCdmEntitySessionManager;
50
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
51
import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
52
import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
53

    
54
/**
55
 * This implementation of ICdmDataRepository depends on hibernate sessions to
56
 * store the data correctly for the current session. No state is held in this
57
 * class.
58
 *
59
 * Only methods that either get or manipulate data are exposed here. So this
60
 * class acts as a facade for the methods in cdmlib-service.
61
 *
62
 * @author n.hoffmann
63
 * @created 17.03.2009
64
 * @version 1.0
65
 */
66
public class CdmStore {
67

    
68
    private static final Resource DEFAULT_APPLICATION_CONTEXT = new ClassPathResource(
69
            "/eu/etaxonomy/cdm/editorApplicationContext.xml",
70
            TaxeditorStorePlugin.class);
71
    private static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION = DbSchemaValidation.VALIDATE;
72

    
73
    private static CdmStore instance;
74

    
75
    //private final ICdmApplicationConfiguration applicationConfiguration;
76

    
77
    private static ContextManager contextManager = new ContextManager();
78

    
79
    private static LoginManager loginManager = new LoginManager();
80

    
81
    private static TermManager termManager = new TermManager();
82

    
83
    private static SearchManager searchManager = new SearchManager();
84

    
85
    private static EditorManager editorManager = new EditorManager();
86

    
87
    private static UseObjectStore useObjectInitializer = new UseObjectStore();
88

    
89
    private static CdmStoreConnector job;
90

    
91
    private Language language;
92

    
93
    private ICdmSource cdmSource;
94

    
95
    private boolean isConnected;
96

    
97

    
98

    
99
    /**
100
     * <p>
101
     * getDefault
102
     * </p>
103
     *
104
     * @return a {@link eu.etaxonomy.taxeditor.store.CdmStore} object.
105
     */
106
    protected static CdmStore getDefault() {
107
        if (instance != null && instance.isConnected) {
108
            return instance;
109
        } else{// if (instance == null || !instance.isConnected) {
110

    
111
            MessagingUtils.noDataSourceWarningDialog(instance);
112

    
113
            AbstractUtility.showView(CdmDataSourceViewPart.ID);
114
            return null;
115
        }
116
    }
117

    
118
    /**
119
     * Initialize the with the last edited datasource
120
     */
121
    public static void connect() {
122

    
123
        ICdmSource cdmSource;
124
        try {
125

    
126
            cdmSource = CdmDataSourceRepository.getCurrentCdmSource();
127
            connect(cdmSource);
128
        } catch (Exception e) {
129
            MessagingUtils.messageDialog("Connection to CDM Source Failed", CdmStore.class, "Could not connect to target CDM Source", e);
130
        }
131

    
132

    
133
    }
134

    
135
    /**
136
     * Initialize with a specific datasource
137
     *
138
     * @param datasource
139
     *            a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
140
     */
141
    public static void connect(ICdmSource cdmSource) {
142
        connect(cdmSource, DEFAULT_DB_SCHEMA_VALIDATION,
143
                DEFAULT_APPLICATION_CONTEXT);
144
    }
145

    
146
    public static void connect(ICdmSource cdmSource, RemotingLoginDialog loginDialog) {
147
        connect(cdmSource,
148
                DEFAULT_DB_SCHEMA_VALIDATION,
149
                DEFAULT_APPLICATION_CONTEXT,
150
                loginDialog);
151
    }
152

    
153
    /**
154
     * Initialize and provide
155
     *
156
     * @param datasource
157
     * @param dbSchemaValidation
158
     * @param applicationContextBean
159
     */
160
    private static void connect(final ICdmSource cdmSource,
161
            final DbSchemaValidation dbSchemaValidation,
162
            final Resource applicationContextBean) {
163

    
164
        MessagingUtils.info("Connecting to datasource: " + cdmSource);
165

    
166
        job = new CdmStoreConnector(Display.getDefault(), cdmSource,
167
                dbSchemaValidation, applicationContextBean);
168
        job.setUser(true);
169
        job.setPriority(Job.BUILD);
170
        job.schedule();
171

    
172
    }
173

    
174
    private static void connect(final ICdmSource cdmSource,
175
            final DbSchemaValidation dbSchemaValidation,
176
            final Resource applicationContextBean,
177
            RemotingLoginDialog remotingLoginDialog) {
178
        RemotingLoginDialog loginDialog = remotingLoginDialog;
179
        if(isActive()) {
180
            // before we connect we clear the entity caches and the sessions
181
            CdmRemoteCacheManager.removeEntityCaches();
182
            if(getCurrentSessionManager() != null) {
183
                getCurrentSessionManager().disposeAll();
184
            }
185
        }
186
        MessagingUtils.info("Connecting to datasource: " + cdmSource);
187

    
188
        job = new CdmStoreConnector(Display.getDefault(),
189
                cdmSource,
190
                dbSchemaValidation,
191
                applicationContextBean);
192
        job.start(loginDialog);
193

    
194
    }
195

    
196
    public static boolean isConnecting() {
197
        return job != null && job.getState() == Job.RUNNING;
198
    }
199

    
200
    /**
201
     * Closes the current application context
202
     *
203
     * @param monitor
204
     *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
205
     */
206
    public static void close(final IProgressMonitor monitor) {
207
        Display.getDefault().asyncExec(new Runnable() {
208
            /*
209
             * (non-Javadoc)
210
             *
211
             * @see java.lang.Runnable#run()
212
             */
213
            @Override
214
            public void run() {
215
                getContextManager().notifyContextAboutToStop(monitor);
216
                if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
217
                    getContextManager().notifyContextStop(monitor);
218
                    instance.close();
219
                }
220
            }
221
        });
222
    }
223

    
224
    public static void close(IProgressMonitor monitor, boolean async) {
225
        if(async) {
226
            close(monitor);
227
        } else {
228
            getContextManager().notifyContextAboutToStop(monitor);
229
            if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
230
                getContextManager().notifyContextStop(monitor);
231
                instance.close();
232
            }
233
        }
234

    
235
    }
236
    private void close() {
237
        isConnected = false;
238
        cdmSource = null;
239
        CdmApplicationState.dispose();
240
    }
241

    
242
    static void setInstance(ICdmApplicationConfiguration applicationController,
243
            ICdmSource cdmSource) {
244
        instance = new CdmStore(applicationController, cdmSource);
245
        if(getCurrentSessionManager().isRemoting()) {
246
            CdmApplicationState.setCdmServiceCacher(new CdmServiceCacher());
247
        }
248
    }
249

    
250
    private CdmStore(ICdmApplicationConfiguration applicationController,
251
            ICdmSource cdmSource) {
252
        CdmApplicationState.setCurrentAppConfig(applicationController);
253
        CdmApplicationState.setCurrentDataChangeService(new CdmUIDataChangeService());
254
        this.cdmSource = cdmSource;
255
        isConnected = true;
256
    }
257

    
258
    /**
259
     * All calls to the datastore require
260
     *
261
     * @return
262
     */
263
    private ICdmApplicationConfiguration getApplicationConfiguration() {
264
        try {
265
            return CdmApplicationState.getCurrentAppConfig();
266
        } catch (Exception e) {
267
            MessagingUtils.error(CdmStore.class, e);
268
        }
269
        return null;
270
    }
271

    
272
    /**
273
     * <p>
274
     * getCurrentApplicationController
275
     * </p>
276
     *
277
     * @return a
278
     *         {@link eu.etaxonomy.cdm.remote.api.application.CdmApplicationController}
279
     *         object.
280
     */
281
    public static ICdmApplicationConfiguration getCurrentApplicationConfiguration() {
282
        if (getDefault() != null) {
283
            return getDefault().getApplicationConfiguration();
284
        }
285
        return null;
286
    }
287

    
288
    /*
289
     * CONVERSATIONS
290
     */
291

    
292
    /**
293
     * Creates a new conversation, binds resources to the conversation and start
294
     * a transaction for this conversation.
295
     *
296
     * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
297
     *         object.
298
     */
299
    public static ConversationHolder createConversation() {
300
        ConversationHolder conversation = getCurrentApplicationConfiguration()
301
                .NewConversation();
302
        try {
303
            conversation.startTransaction();
304
        }catch(Exception e){
305
            MessagingUtils.messageDialog("No database connection", CdmStore.class, "No database connection available", e);
306
        }
307
        return conversation;
308
    }
309

    
310
    //FIXME:Remoting should be removed after moving completely to remoting
311
    private MockCdmEntitySessionManager mockCdmEntitySessionManager;
312

    
313
    private ICdmEntitySessionManager getSessionManager() {
314
        //FIXME:Remoting we should only have CdmApplicationRemoteConfiguration after move to remoting
315
        //               bad hack which should be finally removed
316
        if(getCurrentApplicationConfiguration() instanceof CdmApplicationRemoteController) {
317
            return ((CdmApplicationRemoteController)getCurrentApplicationConfiguration()).getCdmEntitySessionManager();
318
        } else {
319
            if(mockCdmEntitySessionManager == null) {
320
                mockCdmEntitySessionManager = new MockCdmEntitySessionManager();
321
            }
322
            return mockCdmEntitySessionManager;
323
        }
324
    }
325

    
326
    public static  ICdmEntitySessionManager getCurrentSessionManager() {
327
        if (getDefault() != null) {
328
            return getDefault().getSessionManager();
329
        }
330
        return null;
331

    
332
    }
333

    
334
    /**
335
     * Generic method that will scan the getters of {@link ICdmApplicationConfiguration} for the given service
336
     * interface. If a matching getter is found the according service implementation is returned by
337
     * invoking the getter otherwise the method returns <code>null</code>.
338
     *
339
     * @param <T>
340
     * @param serviceClass
341
     * @return the configured implementation of <code>serviceClass</code> or <code>null</code>
342
     */
343
    public static <T extends IService> T getService(Class<T> serviceClass) {
344
        T service = null;
345
        try {
346
            service = CdmApplicationState.getService(serviceClass);
347
        } catch (CdmApplicationException cae) {
348
            MessagingUtils.error(CdmStore.class, cae);
349
        }
350

    
351
        return service;
352
    }
353

    
354
    /**
355
     * @see #getService(Class)
356
     * As ICommonService is not extending IService we need a specific request here
357
     */
358
    public static ICommonService getCommonService() {
359
        return CdmApplicationState.getCommonService();
360

    
361
    }
362

    
363
    /**
364
     * <p>
365
     * getAuthenticationManager
366
     * </p>
367
     *
368
     * @return a
369
     *         {@link org.springframework.security.authentication.ProviderManager}
370
     *         object.
371
     */
372
    public static AuthenticationManager getAuthenticationManager() {
373
        return getCurrentApplicationConfiguration().getAuthenticationManager();
374
    }
375

    
376
    /**
377
     * <p>
378
     * getAuthenticationManager
379
     * </p>
380
     *
381
     * @return a
382
     *         {@link ICdmPermissionEvaluator} object.
383
     */
384
    public static ICdmPermissionEvaluator getPermissionEvaluator() {
385
        return getCurrentApplicationConfiguration().getPermissionEvaluator();
386
    }
387

    
388
    /**
389
     * <p>
390
     * getGeoService
391
     * </p>
392
     *
393
     * @return a {@link eu.etaxonomy.cdm.ext.geo.IEditGeoService} object.
394
     */
395
    public static IEditGeoService getGeoService() {
396
        return (IEditGeoService) getCurrentApplicationConfiguration().getBean(
397
                "editGeoService");
398
    }
399

    
400
    /*
401
     * SECURITY RELATED CONVENIENCE METHODS
402
     */
403

    
404
    /**
405
     * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
406
     *
407
     * @param targetDomainObject
408
     * @param permission
409
     * @return
410
     */
411
    public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject, EnumSet<CRUD> permission){
412
        //TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
413
        SecurityContext context = SecurityContextHolder.getContext();
414
        PermissionEvaluator pe = getPermissionEvaluator();
415
        boolean hasPermission = false;
416
        try {
417
            hasPermission = getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject,
418
                    permission);
419
        } catch (org.springframework.security.access.AccessDeniedException e) {
420
            /* IGNORE */
421
        }
422
        return hasPermission;
423
    }
424

    
425
    /**
426
     * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
427
     *
428
     * @param targetDomainObject
429
     * @param permission
430
     * @return
431
     */
432
    public static boolean currentAuthentiationHasPermission(Class<? extends CdmBase> targetType, EnumSet<CRUD> permission){
433
        boolean hasPermission = false;
434
        try {
435
            hasPermission = getPermissionEvaluator().hasPermission(getCurrentAuthentiation(), null, targetType.getName(), permission);
436
        } catch (org.springframework.security.access.AccessDeniedException e) {
437
            /* IGNORE */
438
        }
439
        return hasPermission;
440
    }
441

    
442
    public static boolean currentAuthentiationHasOneOfRoles(Role ... roles){
443
        boolean hasPermission = false;
444
        try {
445
            hasPermission =  getPermissionEvaluator().hasOneOfRoles(getCurrentAuthentiation(), roles);
446
        } catch (org.springframework.security.access.AccessDeniedException e) {
447
            /* IGNORE */
448
        }
449
        return hasPermission;
450
    }
451

    
452
    public static Authentication getCurrentAuthentiation() {
453
        SecurityContext context = SecurityContextHolder.getContext();
454
        return context.getAuthentication();
455
    }
456

    
457
    /*
458
     * LANGUAGE
459
     */
460

    
461
    /**
462
     * Provides access to the global default language set in the application preferences.
463
     *
464
     * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
465
     */
466
    public static Language getDefaultLanguage() {
467
        if (getDefault().getLanguage() == null) {
468
            getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
469
        }
470
        return getDefault().getLanguage();
471
    }
472

    
473
    /**
474
     * <p>
475
     * setDefaultLanguage
476
     * </p>
477
     *
478
     * @param language
479
     *            a {@link eu.etaxonomy.cdm.model.common.Language} object.
480
     */
481
    public static void setDefaultLanguage(Language language) {
482
        getDefault().setLanguage(language);
483
    }
484

    
485
    /**
486
     * @return the language
487
     */
488
    private Language getLanguage() {
489
        return language;
490
    }
491

    
492
    /**
493
     * @param language
494
     *            the language to set
495
     */
496
    private void setLanguage(Language language) {
497
        this.language = language;
498
    }
499

    
500
    /*
501
     * LOGIN
502
     */
503

    
504
    /**
505
     * <p>
506
     * Getter for the field <code>loginManager</code>.
507
     * </p>
508
     *
509
     * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
510
     */
511
    public static LoginManager getLoginManager() {
512
        return loginManager;
513
    }
514

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

    
526
    public static TermManager getTermManager() {
527
        return termManager;
528
    }
529

    
530
    public static SearchManager getSearchManager() {
531
        return searchManager;
532
    }
533

    
534
    public static EditorManager getEditorManager() {
535
        return editorManager;
536
    }
537

    
538
    /*
539
     * IMPORT/EXPORT FACTORIES
540
     */
541

    
542
    /**
543
     * <p>
544
     * Getter for the field <code>importHandler</code>.
545
     * </p>
546
     *
547
     * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
548
     */
549
    public static ImportManager getImportManager() {
550
        return ImportManager.NewInstance(getCurrentApplicationConfiguration());
551
    }
552

    
553
    /**
554
     * <p>
555
     * Getter for the field <code>exportHandler</code>.
556
     * </p>
557
     *
558
     * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
559
     */
560
    public static ExportManager getExportManager() {
561
        return ExportManager.NewInstance(getCurrentApplicationConfiguration());
562
    }
563

    
564
    /**
565
     * Whether this CdmStore is currently connected to a datasource
566
     *
567
     * @return a boolean.
568
     */
569
    public static boolean isActive() {
570
        return instance != null && instance.isConnected;
571
    }
572

    
573
    public static ICdmSource getActiveCdmSource() {
574
        if (isActive()) {
575
            return instance.getCdmSource();
576
        }
577
        return null;
578
    }
579

    
580
    /**
581
     * <p>
582
     * getDataSource
583
     * </p>
584
     *
585
     * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
586
     * @deprecated currently retained for backward compatibility - use {@link getActiveCdmSource()} instead
587
     */
588
    //	public static ICdmDataSource getDataSource() {
589
    //		if (isActive()) {
590
    //			return (ICdmDataSource)instance.getCdmSource();
591
    //		}
592
    //		return null;
593
    //	}
594

    
595
    /**
596
     * @return
597
     */
598
    private ICdmSource getCdmSource() {
599
        return cdmSource;
600
    }
601

    
602
}
(2-2/13)