Project

General

Profile

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

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

    
28
import eu.etaxonomy.cdm.api.application.CdmApplicationController;
29
import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
30
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
31
import eu.etaxonomy.cdm.api.service.IService;
32
import eu.etaxonomy.cdm.database.DbSchemaValidation;
33
import eu.etaxonomy.cdm.database.ICdmDataSource;
34
import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
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.Operation;
39
import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
40
import eu.etaxonomy.taxeditor.io.ExportManager;
41
import eu.etaxonomy.taxeditor.io.ImportManager;
42
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
43
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
44
import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
45

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

    
60
	private static final Resource DEFAULT_APPLICATION_CONTEXT = new ClassPathResource(
61
			"/eu/etaxonomy/cdm/editorApplicationContext.xml",
62
			TaxeditorStorePlugin.class);
63
	private static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION = DbSchemaValidation.VALIDATE;
64

    
65
	private static CdmStore instance;
66

    
67
	private final ICdmApplicationConfiguration applicationConfiguration;
68

    
69
	private static ContextManager contextManager = new ContextManager();
70

    
71
	private static LoginManager loginManager = new LoginManager();
72

    
73
	private static TermManager termManager = new TermManager();
74

    
75
	private static SearchManager searchManager = new SearchManager();
76

    
77
	private static EditorManager editorManager = new EditorManager();
78

    
79
	private static CdmStoreConnector job;
80

    
81
	private Language language;
82

    
83
	private ICdmDataSource cdmDatasource;
84

    
85
	private boolean isConnected;
86

    
87
	/**
88
	 * <p>
89
	 * getDefault
90
	 * </p>
91
	 * 
92
	 * @return a {@link eu.etaxonomy.taxeditor.store.CdmStore} object.
93
	 */
94
	protected static CdmStore getDefault() {
95
		if (instance != null && instance.isConnected) {
96
			return instance;
97
		} else if (instance == null || !instance.isConnected) {
98

    
99
			StoreUtil
100
					.warningDialog(
101
							"Application is not connected to a datastore",
102
							instance,
103
							"The requested operation is only available when "
104
									+ "connected to a datasource. You may choose a datasource to connect to or create a new one in the datasource view.");
105

    
106
			StoreUtil.showView(CdmDataSourceViewPart.ID);
107

    
108
		}
109

    
110
		throw new RuntimeException();
111
	}
112

    
113
	/**
114
	 * Initialize the with the last edited datasource
115
	 */
116
	public static void connect() {
117

    
118
		ICdmDataSource datasource = CdmDataSourceRepository
119
				.getCurrentDataSource();
120

    
121
		connect(datasource);
122
	}
123

    
124
	/**
125
	 * Initialize with a specific datasource
126
	 * 
127
	 * @param datasource
128
	 *            a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
129
	 */
130
	public static void connect(ICdmDataSource datasource) {
131
		connect(datasource, DEFAULT_DB_SCHEMA_VALIDATION,
132
				DEFAULT_APPLICATION_CONTEXT);
133
	}
134

    
135
	/**
136
	 * Initialize and provide
137
	 * 
138
	 * @param datasource
139
	 * @param dbSchemaValidation
140
	 * @param applicationContextBean
141
	 */
142
	private static void connect(final ICdmDataSource datasource,
143
			final DbSchemaValidation dbSchemaValidation,
144
			final Resource applicationContextBean) {
145
		StoreUtil.info("Connecting to datasource: " + datasource);
146

    
147
		job = new CdmStoreConnector(Display.getDefault(), datasource,
148
				dbSchemaValidation, applicationContextBean);
149
		job.setUser(true);
150
		job.setPriority(Job.BUILD);
151
		job.schedule();
152

    
153
	}
154

    
155
	public static boolean isConnecting() {
156
		return job != null && job.getState() == Job.RUNNING;
157
	}
158

    
159
	/**
160
	 * Closes the current application context
161
	 * 
162
	 * @param monitor
163
	 *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
164
	 */
165
	public static void close(final IProgressMonitor monitor) {
166
		Display.getDefault().asyncExec(new Runnable() {
167
			/*
168
			 * (non-Javadoc)
169
			 * 
170
			 * @see java.lang.Runnable#run()
171
			 */
172
			@Override
173
			public void run() {
174
				getContextManager().notifyContextAboutToStop(monitor);
175
				if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
176
					getContextManager().notifyContextStop(monitor);
177
					instance.close();
178
				}
179
			}
180
		});
181
	}
182

    
183
	private void close() {
184
		isConnected = false;
185
		cdmDatasource = null;
186
	}
187

    
188
	static void setInstance(CdmApplicationController applicationController,
189
			ICdmDataSource dataSource) {
190
		instance = new CdmStore(applicationController, dataSource);
191
	}
192

    
193
	private CdmStore(CdmApplicationController applicationController,
194
			ICdmDataSource dataSource) {
195
		this.applicationConfiguration = applicationController;
196
		this.cdmDatasource = dataSource;
197
		isConnected = true;
198
	}
199

    
200
	/**
201
	 * All calls to the datastore require
202
	 * 
203
	 * @return
204
	 */
205
	private ICdmApplicationConfiguration getApplicationConfiguration() {
206
		try {
207
			return applicationConfiguration;
208
		} catch (Exception e) {
209
			StoreUtil.error(CdmStore.class, e);
210
		}
211
		return null;
212
	}
213

    
214
	/**
215
	 * <p>
216
	 * getCurrentApplicationController
217
	 * </p>
218
	 * 
219
	 * @return a
220
	 *         {@link eu.etaxonomy.cdm.api.application.CdmApplicationController}
221
	 *         object.
222
	 */
223
	public static ICdmApplicationConfiguration getCurrentApplicationConfiguration() {
224
		if (getDefault() != null) {
225
			return getDefault().getApplicationConfiguration();
226
		}
227
		return null;
228
	}
229

    
230
	/*
231
	 * CONVERSATIONS
232
	 */
233

    
234
	/**
235
	 * Creates a new conversation, binds resources to the conversation and start
236
	 * a transaction for this conversation.
237
	 * 
238
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
239
	 *         object.
240
	 */
241
	public static ConversationHolder createConversation() {
242
		ConversationHolder conversation = getCurrentApplicationConfiguration()
243
				.NewConversation();
244
		try{
245
			conversation.startTransaction();
246
		}catch(Exception e){
247
			StoreUtil.errorDialog("No database connection", CdmStore.class, "No database connection available", e);
248
		}
249
		return conversation;
250
	}
251

    
252
	/**
253
	 * Generic method that will scan the getters of {@link ICdmApplicationConfiguration} for the given service
254
	 * interface. If a matching getter is found the according service implementation is returned by 
255
	 * invoking the getter otherwise the method returns <code>null</code>. 
256
	 * 
257
	 * @param <T>
258
	 * @param serviceClass
259
	 * @return the configured implementation of <code>serviceClass</code> or <code>null</code>
260
	 */
261
	public static <T extends IService> T getService(Class<T> serviceClass) {
262
		ICdmApplicationConfiguration configuration = getCurrentApplicationConfiguration();
263

    
264
		Method[] methods = ICdmApplicationConfiguration.class.getDeclaredMethods();
265

    
266
		T service = null;
267

    
268
		for (Method method : methods) {
269
			Type type = method.getGenericReturnType();
270

    
271
			if (type.equals(serviceClass)) {
272
				try {
273
					service = (T) method.invoke(configuration, null);
274
					break;
275
				} catch (IllegalArgumentException e) {
276
					StoreUtil.error(CdmStore.class, e);
277
				} catch (IllegalAccessException e) {
278
					StoreUtil.error(CdmStore.class, e);
279
				} catch (InvocationTargetException e) {
280
					StoreUtil.error(CdmStore.class, e);
281
				}
282
			}
283
		}
284

    
285
		return service;
286
	}
287

    
288
	/**
289
	 * <p>
290
	 * getAuthenticationManager
291
	 * </p>
292
	 * 
293
	 * @return a
294
	 *         {@link org.springframework.security.authentication.ProviderManager}
295
	 *         object.
296
	 */
297
	public static ProviderManager getAuthenticationManager() {
298
		return getCurrentApplicationConfiguration().getAuthenticationManager();
299
	}
300
	
301
	/**
302
	 * <p>
303
	 * getAuthenticationManager
304
	 * </p>
305
	 * 
306
	 * @return a
307
	 *         {@link PermissionEvaluator} object.
308
	 */
309
	public static PermissionEvaluator getPermissionEvaluator() {
310
		return getCurrentApplicationConfiguration().getPermissionEvaluator();
311
	}
312

    
313
	/**
314
	 * <p>
315
	 * getGeoService
316
	 * </p>
317
	 * 
318
	 * @return a {@link eu.etaxonomy.cdm.ext.geo.IEditGeoService} object.
319
	 */
320
	public static IEditGeoService getGeoService() {
321
		return (IEditGeoService) getCurrentApplicationConfiguration().getBean(
322
				"editGeoService");
323
	}
324
	
325
	/*
326
	 * SECURITY RELATED CONVENIENCE METHODS
327
	 */
328
	
329
	/**
330
	 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
331
     *
332
	 * @param targetDomainObject
333
	 * @param permission 
334
	 * @return
335
	 */
336
	public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject, EnumSet<CRUD> permission){
337
		//TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
338
		SecurityContext context = SecurityContextHolder.getContext();
339
		return getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject, permission);
340
	}
341

    
342
	/**
343
	 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
344
     *
345
	 * @param targetDomainObject
346
	 * @param permission 
347
	 * @return
348
	 */
349
	public static boolean currentAuthentiationHasPermission(Class<? extends CdmBase> targetType, EnumSet<CRUD> permission){
350
		SecurityContext context = SecurityContextHolder.getContext();
351
		return getPermissionEvaluator().hasPermission(context.getAuthentication(), null, targetType.getName(), permission);
352
	}
353
	
354
	/*
355
	 * LANGUAGE
356
	 */
357

    
358
	/**
359
	 * <p>
360
	 * getDefaultLanguage
361
	 * </p>
362
	 * 
363
	 * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
364
	 */
365
	public static Language getDefaultLanguage() {
366
		if (getDefault().getLanguage() == null) {
367
			getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
368
		}
369
		return getDefault().getLanguage();
370
	}
371

    
372
	/**
373
	 * <p>
374
	 * setDefaultLanguage
375
	 * </p>
376
	 * 
377
	 * @param language
378
	 *            a {@link eu.etaxonomy.cdm.model.common.Language} object.
379
	 */
380
	public static void setDefaultLanguage(Language language) {
381
		getDefault().setLanguage(language);
382
	}
383

    
384
	/**
385
	 * @return the language
386
	 */
387
	private Language getLanguage() {
388
		return language;
389
	}
390

    
391
	/**
392
	 * @param language
393
	 *            the language to set
394
	 */
395
	private void setLanguage(Language language) {
396
		this.language = language;
397
	}
398

    
399
	/*
400
	 * LOGIN
401
	 */
402

    
403
	/**
404
	 * <p>
405
	 * Getter for the field <code>loginManager</code>.
406
	 * </p>
407
	 * 
408
	 * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
409
	 */
410
	public static LoginManager getLoginManager() {
411
		return loginManager;
412
	}
413

    
414
	/**
415
	 * <p>
416
	 * Getter for the field <code>contextManager</code>.
417
	 * </p>
418
	 * 
419
	 * @return a {@link eu.etaxonomy.taxeditor.store.ContextManager} object.
420
	 */
421
	public static ContextManager getContextManager() {
422
		return contextManager;
423
	}
424

    
425
	public static TermManager getTermManager() {
426
		return termManager;
427
	}
428

    
429
	public static SearchManager getSearchManager() {
430
		return searchManager;
431
	}
432

    
433
	public static EditorManager getEditorManager() {
434
		return editorManager;
435
	}
436

    
437
	/*
438
	 * IMPORT/EXPORT FACTORIES
439
	 */
440

    
441
	/**
442
	 * <p>
443
	 * Getter for the field <code>importHandler</code>.
444
	 * </p>
445
	 * 
446
	 * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
447
	 */
448
	public static ImportManager getImportManager() {
449
		return ImportManager.NewInstance(getCurrentApplicationConfiguration());
450
	}
451

    
452
	/**
453
	 * <p>
454
	 * Getter for the field <code>exportHandler</code>.
455
	 * </p>
456
	 * 
457
	 * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
458
	 */
459
	public static ExportManager getExportManager() {
460
		return ExportManager.NewInstance(getCurrentApplicationConfiguration());
461
	}
462

    
463
	/**
464
	 * Whether this CdmStore is currently connected to a datasource
465
	 * 
466
	 * @return a boolean.
467
	 */
468
	public static boolean isActive() {
469
		return instance != null && instance.isConnected;
470
	}
471

    
472
	/**
473
	 * <p>
474
	 * getDataSource
475
	 * </p>
476
	 * 
477
	 * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
478
	 */
479
	public static ICdmDataSource getDataSource() {
480
		if (isActive()) {
481
			return instance.getDatasource();
482
		}
483
		return null;
484
	}
485

    
486
	/**
487
	 * @return
488
	 */
489
	private ICdmDataSource getDatasource() {
490
		return cdmDatasource;
491
	}
492

    
493
}
(1-1/9)