Project

General

Profile

Download (15.7 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.lang.reflect.InvocationTargetException;
13
import java.lang.reflect.Method;
14
import java.lang.reflect.Type;
15
import java.util.EnumSet;
16

    
17
import org.eclipse.core.runtime.IProgressMonitor;
18
import org.eclipse.core.runtime.jobs.Job;
19
import org.eclipse.swt.widgets.Display;
20
import org.springframework.core.io.ClassPathResource;
21
import org.springframework.core.io.Resource;
22
import org.springframework.security.access.PermissionEvaluator;
23
import org.springframework.security.authentication.ProviderManager;
24
import org.springframework.security.core.Authentication;
25
import org.springframework.security.core.context.SecurityContext;
26
import org.springframework.security.core.context.SecurityContextHolder;
27

    
28

    
29
import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteConfiguration;
30
import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteController;
31
import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
32
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
33
import eu.etaxonomy.cdm.api.service.IService;
34
import eu.etaxonomy.cdm.config.ICdmSource;
35
import eu.etaxonomy.cdm.database.DbSchemaValidation;
36
import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
37
import eu.etaxonomy.cdm.model.common.CdmBase;
38
import eu.etaxonomy.cdm.model.common.Language;
39
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
40
import eu.etaxonomy.cdm.persistence.hibernate.permission.ICdmPermissionEvaluator;
41
import eu.etaxonomy.cdm.persistence.hibernate.permission.Role;
42
import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
43
import eu.etaxonomy.taxeditor.io.ExportManager;
44
import eu.etaxonomy.taxeditor.io.ImportManager;
45
import eu.etaxonomy.taxeditor.model.AbstractUtility;
46
import eu.etaxonomy.taxeditor.model.MessagingUtils;
47
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
48

    
49
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
50
import eu.etaxonomy.taxeditor.session.mock.MockCdmEntitySessionManager;
51
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
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 CdmStoreConnector job;
88

    
89
	private Language language;
90

    
91
	private ICdmSource cdmSource;
92

    
93
	private boolean isConnected;
94
	
95

    
96

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

    
109
			MessagingUtils
110
					.warningDialog(
111
							"Application is not connected to a datastore",
112
							instance,
113
							"The requested operation is only available when "
114
							+ "connected to a datasource. You may choose a datasource to connect to or create a new one in the datasource view.");
115

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

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

    
126
		ICdmSource cdmSource;
127
		try {
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
	/**
149
	 * Initialize and provide
150
	 *
151
	 * @param datasource
152
	 * @param dbSchemaValidation
153
	 * @param applicationContextBean
154
	 */
155
	private static void connect(final ICdmSource cdmSource,
156
			final DbSchemaValidation dbSchemaValidation,
157
			final Resource applicationContextBean) {
158
		MessagingUtils.info("Connecting to datasource: " + cdmSource);
159

    
160
		job = new CdmStoreConnector(Display.getDefault(), cdmSource,
161
				dbSchemaValidation, applicationContextBean);
162
		job.setUser(true);
163
		job.setPriority(Job.BUILD);
164
		job.schedule();
165

    
166
	}
167

    
168
	public static boolean isConnecting() {
169
		return job != null && job.getState() == Job.RUNNING;
170
	}
171

    
172
	/**
173
	 * Closes the current application context
174
	 *
175
	 * @param monitor
176
	 *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
177
	 */
178
	public static void close(final IProgressMonitor monitor) {
179
		Display.getDefault().asyncExec(new Runnable() {
180
			/*
181
			 * (non-Javadoc)
182
			 *
183
			 * @see java.lang.Runnable#run()
184
			 */
185
			@Override
186
			public void run() {
187
				getContextManager().notifyContextAboutToStop(monitor);
188
				if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
189
					getContextManager().notifyContextStop(monitor);
190
					instance.close();
191
				}
192
			}
193
		});
194
	}
195

    
196
	private void close() {
197
		isConnected = false;
198
		cdmSource = null;
199
	}
200

    
201
	static void setInstance(ICdmApplicationConfiguration applicationController,
202
			ICdmSource cdmSource) {
203
		instance = new CdmStore(applicationController, cdmSource);
204
	}
205

    
206
	private CdmStore(ICdmApplicationConfiguration applicationController,
207
			ICdmSource cdmSource) {
208
		this.applicationConfiguration = applicationController;
209
		this.cdmSource = cdmSource;
210
		isConnected = true;
211
	}
212

    
213
	/**
214
	 * All calls to the datastore require
215
	 *
216
	 * @return
217
	 */
218
	private ICdmApplicationConfiguration getApplicationConfiguration() {
219
		try {
220
			return applicationConfiguration;
221
		} catch (Exception e) {
222
			MessagingUtils.error(CdmStore.class, e);
223
		}
224
		return null;
225
	}
226

    
227
	/**
228
	 * <p>
229
	 * getCurrentApplicationController
230
	 * </p>
231
	 *
232
	 * @return a
233
	 *         {@link eu.etaxonomy.cdm.remote.api.application.CdmApplicationController}
234
	 *         object.
235
	 */
236
	public static ICdmApplicationConfiguration getCurrentApplicationConfiguration() {
237
		if (getDefault() != null) {
238
			return getDefault().getApplicationConfiguration();
239
		}
240
		return null;
241
	}
242

    
243
	/*
244
	 * CONVERSATIONS
245
	 */
246

    
247
	/**
248
	 * Creates a new conversation, binds resources to the conversation and start
249
	 * a transaction for this conversation.
250
	 *
251
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
252
	 *         object.
253
	 */
254
	public static ConversationHolder createConversation() {
255
		ConversationHolder conversation = getCurrentApplicationConfiguration()
256
				.NewConversation();
257
		try {
258
			conversation.startTransaction();
259
		}catch(Exception e){
260
			MessagingUtils.messageDialog("No database connection", CdmStore.class, "No database connection available", e);
261
		}
262
		return conversation;
263
	}
264
	
265
	//FIXME:Remoting should be removed after moving completely to remoting
266
	private MockCdmEntitySessionManager mockCdmEntitySessionManager;
267
	
268
	private ICdmEntitySessionManager getSessionManager() {
269
		//FIXME:Remoting we should only have CdmApplicationRemoteConfiguration after move to remoting
270
		//               bad hack which should be finally removed
271
		if(getCurrentApplicationConfiguration() instanceof CdmApplicationRemoteController) {
272
			return ((CdmApplicationRemoteController)getCurrentApplicationConfiguration()).getCdmEntitySessionManager();
273
		} else {
274
			if(mockCdmEntitySessionManager == null) {
275
				mockCdmEntitySessionManager = new MockCdmEntitySessionManager();
276
			}
277
			return mockCdmEntitySessionManager;  			
278
		}
279
	}
280
	
281
	public static  ICdmEntitySessionManager getCurrentSessionManager() {
282
		if (getDefault() != null) {
283
			return getDefault().getSessionManager();
284
		}
285
		return null;
286

    
287
	}
288

    
289
	/**
290
	 * Generic method that will scan the getters of {@link ICdmApplicationConfiguration} for the given service
291
	 * interface. If a matching getter is found the according service implementation is returned by
292
	 * invoking the getter otherwise the method returns <code>null</code>.
293
	 *
294
	 * @param <T>
295
	 * @param serviceClass
296
	 * @return the configured implementation of <code>serviceClass</code> or <code>null</code>
297
	 */
298
	public static <T extends IService> T getService(Class<T> serviceClass) {
299
		ICdmApplicationConfiguration configuration = getCurrentApplicationConfiguration();
300

    
301
		Method[] methods = ICdmApplicationConfiguration.class.getDeclaredMethods();
302

    
303
		T service = null;
304

    
305
		for (Method method : methods) {
306
			Type type = method.getGenericReturnType();
307

    
308
			if (type.equals(serviceClass)) {
309
				try {
310
					service = (T) method.invoke(configuration, null);
311
					break;
312
				} catch (IllegalArgumentException e) {
313
					MessagingUtils.error(CdmStore.class, e);
314
				} catch (IllegalAccessException e) {
315
					MessagingUtils.error(CdmStore.class, e);
316
				} catch (InvocationTargetException e) {
317
					MessagingUtils.error(CdmStore.class, e);
318
				}
319
			}
320
		}
321

    
322
		return service;
323
	}
324

    
325
	/**
326
	 * <p>
327
	 * getAuthenticationManager
328
	 * </p>
329
	 *
330
	 * @return a
331
	 *         {@link org.springframework.security.authentication.ProviderManager}
332
	 *         object.
333
	 */
334
	public static ProviderManager getAuthenticationManager() {
335
		return getCurrentApplicationConfiguration().getAuthenticationManager();
336
	}
337

    
338
	/**
339
	 * <p>
340
	 * getAuthenticationManager
341
	 * </p>
342
	 *
343
	 * @return a
344
	 *         {@link ICdmPermissionEvaluator} object.
345
	 */
346
	public static ICdmPermissionEvaluator getPermissionEvaluator() {
347
		return getCurrentApplicationConfiguration().getPermissionEvaluator();
348
	}
349

    
350
	/**
351
	 * <p>
352
	 * getGeoService
353
	 * </p>
354
	 *
355
	 * @return a {@link eu.etaxonomy.cdm.ext.geo.IEditGeoService} object.
356
	 */
357
	public static IEditGeoService getGeoService() {
358
		return (IEditGeoService) getCurrentApplicationConfiguration().getBean(
359
				"editGeoService");
360
	}
361

    
362
	/*
363
	 * SECURITY RELATED CONVENIENCE METHODS
364
	 */
365

    
366
	/**
367
	 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
368
     *
369
	 * @param targetDomainObject
370
	 * @param permission
371
	 * @return
372
	 */
373
	public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject, EnumSet<CRUD> permission){
374
		//TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
375
		SecurityContext context = SecurityContextHolder.getContext();
376
		PermissionEvaluator pe = getPermissionEvaluator();
377
		boolean hasPermission = false;
378
		try {
379
            hasPermission = getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject,
380
                    permission);
381
        } catch (org.springframework.security.access.AccessDeniedException e) {
382
            /* IGNORE */
383
        }
384
        return hasPermission;
385
	}
386

    
387
	/**
388
	 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
389
     *
390
	 * @param targetDomainObject
391
	 * @param permission
392
	 * @return
393
	 */
394
	public static boolean currentAuthentiationHasPermission(Class<? extends CdmBase> targetType, EnumSet<CRUD> permission){
395
	    boolean hasPermission = false;
396
        try {
397
            hasPermission = getPermissionEvaluator().hasPermission(getCurrentAuthentiation(), null, targetType.getName(), permission);
398
        } catch (org.springframework.security.access.AccessDeniedException e) {
399
            /* IGNORE */
400
        }
401
        return hasPermission;
402
	}
403

    
404
	public static boolean currentAuthentiationHasOneOfRoles(Role ... roles){
405
	    boolean hasPermission = false;
406
        try {
407
            hasPermission =  getPermissionEvaluator().hasOneOfRoles(getCurrentAuthentiation(), roles);
408
        } catch (org.springframework.security.access.AccessDeniedException e) {
409
            /* IGNORE */
410
        }
411
        return hasPermission;
412
	}
413

    
414
	public static Authentication getCurrentAuthentiation() {
415
		SecurityContext context = SecurityContextHolder.getContext();
416
		return context.getAuthentication();
417
	}
418

    
419
	/*
420
	 * LANGUAGE
421
	 */
422

    
423
	/**
424
	 * Provides access to the global default language set in the application preferences.
425
	 *
426
	 * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
427
	 */
428
	public static Language getDefaultLanguage() {
429
		if (getDefault().getLanguage() == null) {
430
			getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
431
		}
432
		return getDefault().getLanguage();
433
	}
434

    
435
	/**
436
	 * <p>
437
	 * setDefaultLanguage
438
	 * </p>
439
	 *
440
	 * @param language
441
	 *            a {@link eu.etaxonomy.cdm.model.common.Language} object.
442
	 */
443
	public static void setDefaultLanguage(Language language) {
444
		getDefault().setLanguage(language);
445
	}
446

    
447
	/**
448
	 * @return the language
449
	 */
450
	private Language getLanguage() {
451
		return language;
452
	}
453

    
454
	/**
455
	 * @param language
456
	 *            the language to set
457
	 */
458
	private void setLanguage(Language language) {
459
		this.language = language;
460
	}
461

    
462
	/*
463
	 * LOGIN
464
	 */
465

    
466
	/**
467
	 * <p>
468
	 * Getter for the field <code>loginManager</code>.
469
	 * </p>
470
	 *
471
	 * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
472
	 */
473
	public static LoginManager getLoginManager() {
474
		return loginManager;
475
	}
476

    
477
	/**
478
	 * <p>
479
	 * Getter for the field <code>contextManager</code>.
480
	 * </p>
481
	 *
482
	 * @return a {@link eu.etaxonomy.taxeditor.store.ContextManager} object.
483
	 */
484
	public static ContextManager getContextManager() {
485
		return contextManager;
486
	}
487

    
488
	public static TermManager getTermManager() {
489
		return termManager;
490
	}
491

    
492
	public static SearchManager getSearchManager() {
493
		return searchManager;
494
	}
495

    
496
	public static EditorManager getEditorManager() {
497
		return editorManager;
498
	}
499

    
500
	/*
501
	 * IMPORT/EXPORT FACTORIES
502
	 */
503

    
504
	/**
505
	 * <p>
506
	 * Getter for the field <code>importHandler</code>.
507
	 * </p>
508
	 *
509
	 * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
510
	 */
511
	public static ImportManager getImportManager() {
512
		return ImportManager.NewInstance(getCurrentApplicationConfiguration());
513
	}
514

    
515
	/**
516
	 * <p>
517
	 * Getter for the field <code>exportHandler</code>.
518
	 * </p>
519
	 *
520
	 * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
521
	 */
522
	public static ExportManager getExportManager() {
523
		return ExportManager.NewInstance(getCurrentApplicationConfiguration());
524
	}
525

    
526
	/**
527
	 * Whether this CdmStore is currently connected to a datasource
528
	 *
529
	 * @return a boolean.
530
	 */
531
	public static boolean isActive() {
532
		return instance != null && instance.isConnected;
533
	}
534

    
535
	public static ICdmSource getActiveCdmSource() {
536
		if (isActive()) {
537
			return instance.getCdmSource();
538
		}
539
		return null;
540
	}
541

    
542
	/**
543
	 * <p>
544
	 * getDataSource
545
	 * </p>
546
	 *
547
	 * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
548
	 * @deprecated currently retained for backward compatibility - use {@link getActiveCdmSource()} instead
549
	 */
550
//	public static ICdmDataSource getDataSource() {
551
//		if (isActive()) {
552
//			return (ICdmDataSource)instance.getCdmSource();
553
//		}
554
//		return null;
555
//	}
556

    
557
	/**
558
	 * @return
559
	 */
560
	private ICdmSource getCdmSource() {
561
		return cdmSource;
562
	}
563

    
564
}
(1-1/9)