Project

General

Profile

Download (18.5 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.view.datasource.CdmDataSourceViewPart;
52

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

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

    
72
    private static CdmStore instance;
73

    
74
    //private final ICdmApplicationConfiguration applicationConfiguration;
75

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

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

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

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

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

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

    
88
    private static CdmStoreConnector job;
89

    
90
    private Language language;
91

    
92
    private ICdmSource cdmSource;
93

    
94
    private boolean isConnected;
95

    
96

    
97

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

    
110
            MessagingUtils.noDataSourceWarningDialog(instance);
111

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

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

    
122
        ICdmSource cdmSource;
123
        try {
124

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

    
131

    
132
    }
133

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

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

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

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

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

    
171
    }
172

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

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

    
193
    }
194

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

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

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

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

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

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

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

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

    
287
    /*
288
     * CONVERSATIONS
289
     */
290

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

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

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

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

    
331
    }
332

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

    
350
        return service;
351
    }
352

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

    
360
    }
361

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

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

    
387

    
388
    /*
389
     * SECURITY RELATED CONVENIENCE METHODS
390
     */
391

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

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

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

    
440
    public static Authentication getCurrentAuthentiation() {
441
        SecurityContext context = SecurityContextHolder.getContext();
442
        return context.getAuthentication();
443
    }
444

    
445
    /*
446
     * LANGUAGE
447
     */
448

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

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

    
473
    /**
474
     * @return the language
475
     */
476
    private Language getLanguage() {
477
        return language;
478
    }
479

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

    
488
    /*
489
     * LOGIN
490
     */
491

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

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

    
514
    public static TermManager getTermManager() {
515
        return termManager;
516
    }
517

    
518
    public static SearchManager getSearchManager() {
519
        return searchManager;
520
    }
521

    
522
    public static EditorManager getEditorManager() {
523
        return editorManager;
524
    }
525

    
526
    /*
527
     * IMPORT/EXPORT FACTORIES
528
     */
529

    
530
    /**
531
     * <p>
532
     * Getter for the field <code>importHandler</code>.
533
     * </p>
534
     *
535
     * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
536
     */
537
    public static ImportManager getImportManager() {
538
        return ImportManager.NewInstance(getCurrentApplicationConfiguration());
539
    }
540

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

    
552
    /**
553
     * Whether this CdmStore is currently connected to a datasource
554
     *
555
     * @return a boolean.
556
     */
557
    public static boolean isActive() {
558
        return instance != null && instance.isConnected;
559
    }
560

    
561
    public static ICdmSource getActiveCdmSource() {
562
        if (isActive()) {
563
            return instance.getCdmSource();
564
        }
565
        return null;
566
    }
567

    
568
    /**
569
     * <p>
570
     * getDataSource
571
     * </p>
572
     *
573
     * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
574
     * @deprecated currently retained for backward compatibility - use {@link getActiveCdmSource()} instead
575
     */
576
    //	public static ICdmDataSource getDataSource() {
577
    //		if (isActive()) {
578
    //			return (ICdmDataSource)instance.getCdmSource();
579
    //		}
580
    //		return null;
581
    //	}
582

    
583
    /**
584
     * @return
585
     */
586
    private ICdmSource getCdmSource() {
587
        return cdmSource;
588
    }
589

    
590
}
(2-2/13)