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.model.common.CdmBase;
36
import eu.etaxonomy.cdm.model.common.Language;
37
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
38
import eu.etaxonomy.cdm.persistence.hibernate.permission.ICdmPermissionEvaluator;
39
import eu.etaxonomy.cdm.persistence.hibernate.permission.Role;
40
import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
41
import eu.etaxonomy.taxeditor.io.ExportManager;
42
import eu.etaxonomy.taxeditor.io.ImportManager;
43
import eu.etaxonomy.taxeditor.model.AbstractUtility;
44
import eu.etaxonomy.taxeditor.model.MessagingUtils;
45
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
46
import eu.etaxonomy.taxeditor.remoting.cache.CdmRemoteCacheManager;
47
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
48
import eu.etaxonomy.taxeditor.session.mock.MockCdmEntitySessionManager;
49
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
50
import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
51
import eu.etaxonomy.taxeditor.util.ProgressMonitorClientManager;
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 ProgressMonitorClientManager progressMonitorClientManager = new ProgressMonitorClientManager();
90

    
91
    private static CdmStoreConnector job;
92

    
93
    private Language language;
94

    
95
    private ICdmSource cdmSource;
96

    
97
    private boolean isConnected;
98

    
99

    
100

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

    
113
            MessagingUtils.noDataSourceWarningDialog(instance);
114

    
115
            AbstractUtility.showView(CdmDataSourceViewPart.ID);
116
            return null;
117
        }
118
    }
119

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

    
125
        ICdmSource cdmSource;
126
        try {
127

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

    
134

    
135
    }
136

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

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

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

    
166
        MessagingUtils.info("Connecting to datasource: " + cdmSource);
167

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

    
174
    }
175

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

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

    
196
    }
197

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

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

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

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

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

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

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

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

    
290
    /*
291
     * CONVERSATIONS
292
     */
293

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

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

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

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

    
334
    }
335

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

    
353
        return service;
354
    }
355

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

    
363
    }
364

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

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

    
390

    
391
    /*
392
     * SECURITY RELATED CONVENIENCE METHODS
393
     */
394

    
395
    /**
396
     * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
397
     *
398
     * @param targetDomainObject
399
     * @param permission
400
     * @return
401
     */
402
    public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject, EnumSet<CRUD> permission){
403
        //TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
404
        SecurityContext context = SecurityContextHolder.getContext();
405
        PermissionEvaluator pe = getPermissionEvaluator();
406
        boolean hasPermission = false;
407
        try {
408
            hasPermission = getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject,
409
                    permission);
410
        } catch (org.springframework.security.access.AccessDeniedException e) {
411
            /* IGNORE */
412
        }
413
        return hasPermission;
414
    }
415

    
416
    /**
417
     * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
418
     *
419
     * @param targetDomainObject
420
     * @param permission
421
     * @return
422
     */
423
    public static boolean currentAuthentiationHasPermission(Class<? extends CdmBase> targetType, EnumSet<CRUD> permission){
424
        boolean hasPermission = false;
425
        try {
426
            hasPermission = getPermissionEvaluator().hasPermission(getCurrentAuthentiation(), null, targetType.getName(), permission);
427
        } catch (org.springframework.security.access.AccessDeniedException e) {
428
            /* IGNORE */
429
        }
430
        return hasPermission;
431
    }
432

    
433
    public static boolean currentAuthentiationHasOneOfRoles(Role ... roles){
434
        boolean hasPermission = false;
435
        try {
436
            hasPermission =  getPermissionEvaluator().hasOneOfRoles(getCurrentAuthentiation(), roles);
437
        } catch (org.springframework.security.access.AccessDeniedException e) {
438
            /* IGNORE */
439
        }
440
        return hasPermission;
441
    }
442

    
443
    public static Authentication getCurrentAuthentiation() {
444
        SecurityContext context = SecurityContextHolder.getContext();
445
        return context.getAuthentication();
446
    }
447

    
448
    /*
449
     * LANGUAGE
450
     */
451

    
452
    /**
453
     * Provides access to the global default language set in the application preferences.
454
     *
455
     * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
456
     */
457
    public static Language getDefaultLanguage() {
458
        if (getDefault().getLanguage() == null) {
459
            getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
460
        }
461
        return getDefault().getLanguage();
462
    }
463

    
464
    /**
465
     * <p>
466
     * setDefaultLanguage
467
     * </p>
468
     *
469
     * @param language
470
     *            a {@link eu.etaxonomy.cdm.model.common.Language} object.
471
     */
472
    public static void setDefaultLanguage(Language language) {
473
        getDefault().setLanguage(language);
474
    }
475

    
476
    /**
477
     * @return the language
478
     */
479
    private Language getLanguage() {
480
        return language;
481
    }
482

    
483
    /**
484
     * @param language
485
     *            the language to set
486
     */
487
    private void setLanguage(Language language) {
488
        this.language = language;
489
    }
490

    
491
    /*
492
     * LOGIN
493
     */
494

    
495
    /**
496
     * <p>
497
     * Getter for the field <code>loginManager</code>.
498
     * </p>
499
     *
500
     * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
501
     */
502
    public static LoginManager getLoginManager() {
503
        return loginManager;
504
    }
505

    
506
    /**
507
     * <p>
508
     * Getter for the field <code>contextManager</code>.
509
     * </p>
510
     *
511
     * @return a {@link eu.etaxonomy.taxeditor.store.ContextManager} object.
512
     */
513
    public static ContextManager getContextManager() {
514
        return contextManager;
515
    }
516

    
517
    public static TermManager getTermManager() {
518
        return termManager;
519
    }
520

    
521
    public static SearchManager getSearchManager() {
522
        return searchManager;
523
    }
524

    
525
    public static EditorManager getEditorManager() {
526
        return editorManager;
527
    }
528

    
529
    public static ProgressMonitorClientManager getProgressMonitorClientManager() {
530
        return progressMonitorClientManager;
531
    }
532

    
533
    /*
534
     * IMPORT/EXPORT FACTORIES
535
     */
536

    
537
    /**
538
     * <p>
539
     * Getter for the field <code>importHandler</code>.
540
     * </p>
541
     *
542
     * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
543
     */
544
    public static ImportManager getImportManager() {
545
        return ImportManager.NewInstance(getCurrentApplicationConfiguration());
546
    }
547

    
548
    /**
549
     * <p>
550
     * Getter for the field <code>exportHandler</code>.
551
     * </p>
552
     *
553
     * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
554
     */
555
    public static ExportManager getExportManager() {
556
        return ExportManager.NewInstance(getCurrentApplicationConfiguration());
557
    }
558

    
559
    /**
560
     * Whether this CdmStore is currently connected to a datasource
561
     *
562
     * @return a boolean.
563
     */
564
    public static boolean isActive() {
565
        return instance != null && instance.isConnected;
566
    }
567

    
568
    public static ICdmSource getActiveCdmSource() {
569
        if (isActive()) {
570
            return instance.getCdmSource();
571
        }
572
        return null;
573
    }
574

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

    
590
    /**
591
     * @return
592
     */
593
    private ICdmSource getCdmSource() {
594
        return cdmSource;
595
    }
596

    
597
}
(2-2/13)