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