merge taxeditor validation2 into trunk
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / store / CdmStore.java
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 import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
29 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
30 import eu.etaxonomy.cdm.api.service.ICommonService;
31 import eu.etaxonomy.cdm.api.service.IService;
32 import eu.etaxonomy.cdm.config.ICdmSource;
33 import eu.etaxonomy.cdm.database.DbSchemaValidation;
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.ICdmPermissionEvaluator;
39 import eu.etaxonomy.cdm.persistence.hibernate.permission.Role;
40 import eu.etaxonomy.cdm.remote.CdmRemoteSourceException;
41 import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
42 import eu.etaxonomy.taxeditor.io.ExportManager;
43 import eu.etaxonomy.taxeditor.io.ImportManager;
44 import eu.etaxonomy.taxeditor.model.AbstractUtility;
45 import eu.etaxonomy.taxeditor.model.MessagingUtils;
46 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
47 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
48 import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
49
50 /**
51 * This implementation of ICdmDataRepository depends on hibernate sessions to
52 * store the data correctly for the current session. No state is held in this
53 * class.
54 *
55 * Only methods that either get or manipulate data are exposed here. So this
56 * class acts as a facade for the methods in cdmlib-service.
57 *
58 * @author n.hoffmann
59 * @created 17.03.2009
60 * @version 1.0
61 */
62 public class CdmStore {
63
64 private static final Resource DEFAULT_APPLICATION_CONTEXT = new ClassPathResource(
65 "/eu/etaxonomy/cdm/editorApplicationContext.xml",
66 TaxeditorStorePlugin.class);
67 private static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION = DbSchemaValidation.VALIDATE;
68
69 private static CdmStore instance;
70
71 private final ICdmApplicationConfiguration applicationConfiguration;
72
73 private static ContextManager contextManager = new ContextManager();
74
75 private static LoginManager loginManager = new LoginManager();
76
77 private static TermManager termManager = new TermManager();
78
79 private static SearchManager searchManager = new SearchManager();
80
81 private static EditorManager editorManager = new EditorManager();
82
83 private static CdmStoreConnector job;
84
85 private Language language;
86
87 private ICdmSource cdmSource;
88
89 private boolean isConnected;
90
91 /**
92 * <p>
93 * getDefault
94 * </p>
95 *
96 * @return a {@link eu.etaxonomy.taxeditor.store.CdmStore} object.
97 */
98 protected static CdmStore getDefault() {
99 if (instance != null && instance.isConnected) {
100 return instance;
101 } else{// if (instance == null || !instance.isConnected) {
102
103 MessagingUtils.noDataSourceWarningDialog(instance);
104
105 AbstractUtility.showView(CdmDataSourceViewPart.ID);
106 return null;
107 }
108 }
109
110 /**
111 * Initialize the with the last edited datasource
112 */
113 public static void connect() {
114
115 ICdmSource cdmSource;
116 try {
117 cdmSource = CdmDataSourceRepository.getCurrentCdmSource();
118 connect(cdmSource);
119 } catch (CdmRemoteSourceException e) {
120 MessagingUtils.messageDialog("Connection to CDM Source Failed", CdmStore.class, "Could not connect to target CDM Source", e);
121 }
122
123
124 }
125
126 /**
127 * Initialize with a specific datasource
128 *
129 * @param datasource
130 * a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
131 */
132 public static void connect(ICdmSource cdmSource) {
133 connect(cdmSource, DEFAULT_DB_SCHEMA_VALIDATION,
134 DEFAULT_APPLICATION_CONTEXT);
135 }
136
137 /**
138 * Initialize and provide
139 *
140 * @param datasource
141 * @param dbSchemaValidation
142 * @param applicationContextBean
143 */
144 private static void connect(final ICdmSource cdmSource,
145 final DbSchemaValidation dbSchemaValidation,
146 final Resource applicationContextBean) {
147 MessagingUtils.info("Connecting to datasource: " + cdmSource);
148
149 job = new CdmStoreConnector(Display.getDefault(), cdmSource,
150 dbSchemaValidation, applicationContextBean);
151 job.setUser(true);
152 job.setPriority(Job.BUILD);
153 job.schedule();
154
155 }
156
157 public static boolean isConnecting() {
158 return job != null && job.getState() == Job.RUNNING;
159 }
160
161 /**
162 * Closes the current application context
163 *
164 * @param monitor
165 * a {@link org.eclipse.core.runtime.IProgressMonitor} object.
166 */
167 public static void close(final IProgressMonitor monitor) {
168 Display.getDefault().asyncExec(new Runnable() {
169 /*
170 * (non-Javadoc)
171 *
172 * @see java.lang.Runnable#run()
173 */
174 @Override
175 public void run() {
176 getContextManager().notifyContextAboutToStop(monitor);
177 if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
178 getContextManager().notifyContextStop(monitor);
179 instance.close();
180 }
181 }
182 });
183 }
184
185 private void close() {
186 isConnected = false;
187 cdmSource = null;
188 }
189
190 static void setInstance(ICdmApplicationConfiguration applicationController,
191 ICdmSource cdmSource) {
192 instance = new CdmStore(applicationController, cdmSource);
193 }
194
195 private CdmStore(ICdmApplicationConfiguration applicationController,
196 ICdmSource cdmSource) {
197 this.applicationConfiguration = applicationController;
198 this.cdmSource = cdmSource;
199 isConnected = true;
200 }
201
202 /**
203 * All calls to the datastore require
204 *
205 * @return
206 */
207 private ICdmApplicationConfiguration getApplicationConfiguration() {
208 try {
209 return applicationConfiguration;
210 } catch (Exception e) {
211 MessagingUtils.error(CdmStore.class, e);
212 }
213 return null;
214 }
215
216 /**
217 * <p>
218 * getCurrentApplicationController
219 * </p>
220 *
221 * @return a
222 * {@link eu.etaxonomy.cdm.remote.api.application.CdmApplicationController}
223 * object.
224 */
225 public static ICdmApplicationConfiguration getCurrentApplicationConfiguration() {
226 if (getDefault() != null) {
227 return getDefault().getApplicationConfiguration();
228 }
229 return null;
230 }
231
232 /*
233 * CONVERSATIONS
234 */
235
236 /**
237 * Creates a new conversation, binds resources to the conversation and start
238 * a transaction for this conversation.
239 *
240 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
241 * object.
242 */
243 public static ConversationHolder createConversation() {
244 ConversationHolder conversation = getCurrentApplicationConfiguration()
245 .NewConversation();
246 try{
247 conversation.startTransaction();
248 }catch(Exception e){
249 MessagingUtils.messageDialog("No database connection", CdmStore.class, "No database connection available", e);
250 }
251 return conversation;
252 }
253
254 /**
255 * Generic method that will scan the getters of {@link ICdmApplicationConfiguration} for the given service
256 * interface. If a matching getter is found the according service implementation is returned by
257 * invoking the getter otherwise the method returns <code>null</code>.
258 *
259 * @param <T>
260 * @param serviceClass
261 * @return the configured implementation of <code>serviceClass</code> or <code>null</code>
262 */
263 public static <T extends IService> T getService(Class<T> serviceClass) {
264 ICdmApplicationConfiguration configuration = getCurrentApplicationConfiguration();
265
266 Method[] methods = ICdmApplicationConfiguration.class.getDeclaredMethods();
267
268 T service = null;
269
270 for (Method method : methods) {
271 Type type = method.getGenericReturnType();
272
273 if (type.equals(serviceClass)) {
274 try {
275 service = (T) method.invoke(configuration, null);
276 break;
277 } catch (IllegalArgumentException e) {
278 MessagingUtils.error(CdmStore.class, e);
279 } catch (IllegalAccessException e) {
280 MessagingUtils.error(CdmStore.class, e);
281 } catch (InvocationTargetException e) {
282 MessagingUtils.error(CdmStore.class, e);
283 }
284 }
285 }
286
287 return service;
288 }
289
290 /**
291 * Generic method that will scan the getters of {@link ICdmApplicationConfiguration} for the given service
292 * interface. If a matching getter is found the according service implementation is returned by
293 * invoking the getter otherwise the method returns <code>null</code>.
294 *
295 * @param <T>
296 * @param serviceClass
297 * @return the configured implementation of <code>serviceClass</code> or <code>null</code>
298 */
299 public static ICommonService getCommonService() {
300 ICdmApplicationConfiguration configuration = getCurrentApplicationConfiguration();
301
302 return configuration.getCommonService();
303
304 }
305
306 /**
307 * <p>
308 * getAuthenticationManager
309 * </p>
310 *
311 * @return a
312 * {@link org.springframework.security.authentication.ProviderManager}
313 * object.
314 */
315 public static ProviderManager getAuthenticationManager() {
316 return getCurrentApplicationConfiguration().getAuthenticationManager();
317 }
318
319 /**
320 * <p>
321 * getAuthenticationManager
322 * </p>
323 *
324 * @return a
325 * {@link ICdmPermissionEvaluator} object.
326 */
327 public static ICdmPermissionEvaluator getPermissionEvaluator() {
328 return getCurrentApplicationConfiguration().getPermissionEvaluator();
329 }
330
331 /**
332 * <p>
333 * getGeoService
334 * </p>
335 *
336 * @return a {@link eu.etaxonomy.cdm.ext.geo.IEditGeoService} object.
337 */
338 public static IEditGeoService getGeoService() {
339 return (IEditGeoService) getCurrentApplicationConfiguration().getBean(
340 "editGeoService");
341 }
342
343 /*
344 * SECURITY RELATED CONVENIENCE METHODS
345 */
346
347 /**
348 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
349 *
350 * @param targetDomainObject
351 * @param permission
352 * @return
353 */
354 public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject, EnumSet<CRUD> permission){
355 //TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
356 SecurityContext context = SecurityContextHolder.getContext();
357 PermissionEvaluator pe = getPermissionEvaluator();
358 boolean hasPermission = false;
359 try {
360 hasPermission = getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject,
361 permission);
362 } catch (org.springframework.security.access.AccessDeniedException e) {
363 /* IGNORE */
364 }
365 return hasPermission;
366 }
367
368 /**
369 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
370 *
371 * @param targetDomainObject
372 * @param permission
373 * @return
374 */
375 public static boolean currentAuthentiationHasPermission(Class<? extends CdmBase> targetType, EnumSet<CRUD> permission){
376 boolean hasPermission = false;
377 try {
378 hasPermission = getPermissionEvaluator().hasPermission(getCurrentAuthentiation(), null, targetType.getName(), permission);
379 } catch (org.springframework.security.access.AccessDeniedException e) {
380 /* IGNORE */
381 }
382 return hasPermission;
383 }
384
385 public static boolean currentAuthentiationHasOneOfRoles(Role ... roles){
386 boolean hasPermission = false;
387 try {
388 hasPermission = getPermissionEvaluator().hasOneOfRoles(getCurrentAuthentiation(), roles);
389 } catch (org.springframework.security.access.AccessDeniedException e) {
390 /* IGNORE */
391 }
392 return hasPermission;
393 }
394
395 public static Authentication getCurrentAuthentiation() {
396 SecurityContext context = SecurityContextHolder.getContext();
397 return context.getAuthentication();
398 }
399
400 /*
401 * LANGUAGE
402 */
403
404 /**
405 * Provides access to the global default language set in the application preferences.
406 *
407 * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
408 */
409 public static Language getDefaultLanguage() {
410 if (getDefault().getLanguage() == null) {
411 getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
412 }
413 return getDefault().getLanguage();
414 }
415
416 /**
417 * <p>
418 * setDefaultLanguage
419 * </p>
420 *
421 * @param language
422 * a {@link eu.etaxonomy.cdm.model.common.Language} object.
423 */
424 public static void setDefaultLanguage(Language language) {
425 getDefault().setLanguage(language);
426 }
427
428 /**
429 * @return the language
430 */
431 private Language getLanguage() {
432 return language;
433 }
434
435 /**
436 * @param language
437 * the language to set
438 */
439 private void setLanguage(Language language) {
440 this.language = language;
441 }
442
443 /*
444 * LOGIN
445 */
446
447 /**
448 * <p>
449 * Getter for the field <code>loginManager</code>.
450 * </p>
451 *
452 * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
453 */
454 public static LoginManager getLoginManager() {
455 return loginManager;
456 }
457
458 /**
459 * <p>
460 * Getter for the field <code>contextManager</code>.
461 * </p>
462 *
463 * @return a {@link eu.etaxonomy.taxeditor.store.ContextManager} object.
464 */
465 public static ContextManager getContextManager() {
466 return contextManager;
467 }
468
469 public static TermManager getTermManager() {
470 return termManager;
471 }
472
473 public static SearchManager getSearchManager() {
474 return searchManager;
475 }
476
477 public static EditorManager getEditorManager() {
478 return editorManager;
479 }
480
481 /*
482 * IMPORT/EXPORT FACTORIES
483 */
484
485 /**
486 * <p>
487 * Getter for the field <code>importHandler</code>.
488 * </p>
489 *
490 * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
491 */
492 public static ImportManager getImportManager() {
493 return ImportManager.NewInstance(getCurrentApplicationConfiguration());
494 }
495
496 /**
497 * <p>
498 * Getter for the field <code>exportHandler</code>.
499 * </p>
500 *
501 * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
502 */
503 public static ExportManager getExportManager() {
504 return ExportManager.NewInstance(getCurrentApplicationConfiguration());
505 }
506
507 /**
508 * Whether this CdmStore is currently connected to a datasource
509 *
510 * @return a boolean.
511 */
512 public static boolean isActive() {
513 return instance != null && instance.isConnected;
514 }
515
516 public static ICdmSource getActiveCdmSource() {
517 if (isActive()) {
518 return instance.getCdmSource();
519 }
520 return null;
521 }
522
523 /**
524 * <p>
525 * getDataSource
526 * </p>
527 *
528 * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
529 * @deprecated currently retained for backward compatibility - use {@link getActiveCdmSource()} instead
530 */
531 // public static ICdmDataSource getDataSource() {
532 // if (isActive()) {
533 // return (ICdmDataSource)instance.getCdmSource();
534 // }
535 // return null;
536 // }
537
538 /**
539 * @return
540 */
541 private ICdmSource getCdmSource() {
542 return cdmSource;
543 }
544
545 }