Project

General

Profile

Download (14.8 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.hibernate.collection.internal.AbstractPersistentCollection;
21
import org.hibernate.proxy.AbstractLazyInitializer;
22
import org.springframework.core.io.ClassPathResource;
23
import org.springframework.core.io.Resource;
24
import org.springframework.security.access.PermissionEvaluator;
25
import org.springframework.security.authentication.ProviderManager;
26
import org.springframework.security.core.Authentication;
27
import org.springframework.security.core.context.SecurityContext;
28
import org.springframework.security.core.context.SecurityContextHolder;
29

    
30
import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
31
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
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.database.ICdmDataSource;
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.cdm.remote.CdmRemoteSourceException;
43
import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
44
import eu.etaxonomy.taxeditor.io.ExportManager;
45
import eu.etaxonomy.taxeditor.io.ImportManager;
46
import eu.etaxonomy.taxeditor.model.AbstractUtility;
47
import eu.etaxonomy.taxeditor.model.MessagingUtils;
48
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
49
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
50
import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
51

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

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

    
71
	private static CdmStore instance;
72

    
73
	private final ICdmApplicationConfiguration applicationConfiguration;
74

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

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

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

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

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

    
85
	private static CdmStoreConnector job;
86

    
87
	private Language language;
88

    
89
	private ICdmSource cdmSource;
90

    
91
	private boolean isConnected;
92

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

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

    
112
			AbstractUtility.showView(CdmDataSourceViewPart.ID);
113

    
114
		}
115

    
116
		throw new RuntimeException();
117
	}
118

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

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

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

    
164
	}
165

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

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

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

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

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

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

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

    
241
	/*
242
	 * CONVERSATIONS
243
	 */
244

    
245
	/**
246
	 * Creates a new conversation, binds resources to the conversation and start
247
	 * a transaction for this conversation.
248
	 *
249
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
250
	 *         object.
251
	 */
252
	public static ConversationHolder createConversation() {
253
		ConversationHolder conversation = getCurrentApplicationConfiguration()
254
				.NewConversation();
255
		try{
256
			conversation.startTransaction();
257
		}catch(Exception e){
258
			MessagingUtils.messageDialog("No database connection", CdmStore.class, "No database connection available", e);
259
		}
260
		return conversation;
261
	}
262

    
263
	/**
264
	 * Generic method that will scan the getters of {@link ICdmApplicationConfiguration} for the given service
265
	 * interface. If a matching getter is found the according service implementation is returned by
266
	 * invoking the getter otherwise the method returns <code>null</code>.
267
	 *
268
	 * @param <T>
269
	 * @param serviceClass
270
	 * @return the configured implementation of <code>serviceClass</code> or <code>null</code>
271
	 */
272
	public static <T extends IService> T getService(Class<T> serviceClass) {
273
		ICdmApplicationConfiguration configuration = getCurrentApplicationConfiguration();
274

    
275
		Method[] methods = ICdmApplicationConfiguration.class.getDeclaredMethods();
276

    
277
		T service = null;
278

    
279
		for (Method method : methods) {
280
			Type type = method.getGenericReturnType();
281

    
282
			if (type.equals(serviceClass)) {
283
				try {
284
					service = (T) method.invoke(configuration, null);
285
					break;
286
				} catch (IllegalArgumentException e) {
287
					MessagingUtils.error(CdmStore.class, e);
288
				} catch (IllegalAccessException e) {
289
					MessagingUtils.error(CdmStore.class, e);
290
				} catch (InvocationTargetException e) {
291
					MessagingUtils.error(CdmStore.class, e);
292
				}
293
			}
294
		}
295

    
296
		return service;
297
	}
298

    
299
	/**
300
	 * <p>
301
	 * getAuthenticationManager
302
	 * </p>
303
	 *
304
	 * @return a
305
	 *         {@link org.springframework.security.authentication.ProviderManager}
306
	 *         object.
307
	 */
308
	public static ProviderManager getAuthenticationManager() {
309
		return getCurrentApplicationConfiguration().getAuthenticationManager();
310
	}
311

    
312
	/**
313
	 * <p>
314
	 * getAuthenticationManager
315
	 * </p>
316
	 *
317
	 * @return a
318
	 *         {@link ICdmPermissionEvaluator} object.
319
	 */
320
	public static ICdmPermissionEvaluator getPermissionEvaluator() {
321
		return getCurrentApplicationConfiguration().getPermissionEvaluator();
322
	}
323

    
324
	/**
325
	 * <p>
326
	 * getGeoService
327
	 * </p>
328
	 *
329
	 * @return a {@link eu.etaxonomy.cdm.ext.geo.IEditGeoService} object.
330
	 */
331
	public static IEditGeoService getGeoService() {
332
		return (IEditGeoService) getCurrentApplicationConfiguration().getBean(
333
				"editGeoService");
334
	}
335

    
336
	/*
337
	 * SECURITY RELATED CONVENIENCE METHODS
338
	 */
339

    
340
	/**
341
	 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
342
     *
343
	 * @param targetDomainObject
344
	 * @param permission
345
	 * @return
346
	 */
347
	public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject, EnumSet<CRUD> permission){
348
		//TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
349
		SecurityContext context = SecurityContextHolder.getContext();
350
		PermissionEvaluator pe = getPermissionEvaluator();
351
		boolean hasPermission = false;
352
		try {
353
            hasPermission = getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject,
354
                    permission);
355
        } catch (org.springframework.security.access.AccessDeniedException e) {
356
            /* IGNORE */
357
        }
358
        return hasPermission;
359
	}
360

    
361
	/**
362
	 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
363
     *
364
	 * @param targetDomainObject
365
	 * @param permission
366
	 * @return
367
	 */
368
	public static boolean currentAuthentiationHasPermission(Class<? extends CdmBase> targetType, EnumSet<CRUD> permission){
369
	    boolean hasPermission = false;
370
        try {
371
            hasPermission = getPermissionEvaluator().hasPermission(getCurrentAuthentiation(), null, targetType.getName(), permission);
372
        } catch (org.springframework.security.access.AccessDeniedException e) {
373
            /* IGNORE */
374
        }
375
        return hasPermission;
376
	}
377

    
378
	public static boolean currentAuthentiationHasOneOfRoles(Role ... roles){
379
	    boolean hasPermission = false;
380
        try {
381
            hasPermission =  getPermissionEvaluator().hasOneOfRoles(getCurrentAuthentiation(), roles);
382
        } catch (org.springframework.security.access.AccessDeniedException e) {
383
            /* IGNORE */
384
        }
385
        return hasPermission;
386
	}
387

    
388
	public static Authentication getCurrentAuthentiation() {
389
		SecurityContext context = SecurityContextHolder.getContext();
390
		return context.getAuthentication();
391
	}
392

    
393
	/*
394
	 * LANGUAGE
395
	 */
396

    
397
	/**
398
	 * Provides access to the global default language set in the application preferences.
399
	 *
400
	 * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
401
	 */
402
	public static Language getDefaultLanguage() {
403
		if (getDefault().getLanguage() == null) {
404
			getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
405
		}
406
		return getDefault().getLanguage();
407
	}
408

    
409
	/**
410
	 * <p>
411
	 * setDefaultLanguage
412
	 * </p>
413
	 *
414
	 * @param language
415
	 *            a {@link eu.etaxonomy.cdm.model.common.Language} object.
416
	 */
417
	public static void setDefaultLanguage(Language language) {
418
		getDefault().setLanguage(language);
419
	}
420

    
421
	/**
422
	 * @return the language
423
	 */
424
	private Language getLanguage() {
425
		return language;
426
	}
427

    
428
	/**
429
	 * @param language
430
	 *            the language to set
431
	 */
432
	private void setLanguage(Language language) {
433
		this.language = language;
434
	}
435

    
436
	/*
437
	 * LOGIN
438
	 */
439

    
440
	/**
441
	 * <p>
442
	 * Getter for the field <code>loginManager</code>.
443
	 * </p>
444
	 *
445
	 * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
446
	 */
447
	public static LoginManager getLoginManager() {
448
		return loginManager;
449
	}
450

    
451
	/**
452
	 * <p>
453
	 * Getter for the field <code>contextManager</code>.
454
	 * </p>
455
	 *
456
	 * @return a {@link eu.etaxonomy.taxeditor.store.ContextManager} object.
457
	 */
458
	public static ContextManager getContextManager() {
459
		return contextManager;
460
	}
461

    
462
	public static TermManager getTermManager() {
463
		return termManager;
464
	}
465

    
466
	public static SearchManager getSearchManager() {
467
		return searchManager;
468
	}
469

    
470
	public static EditorManager getEditorManager() {
471
		return editorManager;
472
	}
473

    
474
	/*
475
	 * IMPORT/EXPORT FACTORIES
476
	 */
477

    
478
	/**
479
	 * <p>
480
	 * Getter for the field <code>importHandler</code>.
481
	 * </p>
482
	 *
483
	 * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
484
	 */
485
	public static ImportManager getImportManager() {
486
		return ImportManager.NewInstance(getCurrentApplicationConfiguration());
487
	}
488

    
489
	/**
490
	 * <p>
491
	 * Getter for the field <code>exportHandler</code>.
492
	 * </p>
493
	 *
494
	 * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
495
	 */
496
	public static ExportManager getExportManager() {
497
		return ExportManager.NewInstance(getCurrentApplicationConfiguration());
498
	}
499

    
500
	/**
501
	 * Whether this CdmStore is currently connected to a datasource
502
	 *
503
	 * @return a boolean.
504
	 */
505
	public static boolean isActive() {
506
		return instance != null && instance.isConnected;
507
	}
508

    
509
	public static ICdmSource getActiveCdmSource() {
510
		if (isActive()) {
511
			return instance.getCdmSource();
512
		}
513
		return null;
514
	}
515
	
516
	/**
517
	 * <p>
518
	 * getDataSource
519
	 * </p>
520
	 *
521
	 * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
522
	 * @deprecated currently retained for backward compatibility - use {@link getActiveCdmSource()} instead
523
	 */
524
//	public static ICdmDataSource getDataSource() {
525
//		if (isActive()) {
526
//			return (ICdmDataSource)instance.getCdmSource();
527
//		}
528
//		return null;
529
//	}
530

    
531
	/**
532
	 * @return
533
	 */
534
	private ICdmSource getCdmSource() {
535
		return cdmSource;
536
	}
537

    
538
}
(1-1/9)