ref #8842 replacing caching in CdmServiceRequestExecutor by CachingHttpInvokerProxyFa...
[taxeditor.git] / eu.etaxonomy.taxeditor.cdmlib / src / main / java / eu / etaxonomy / cdm / api / application / CdmApplicationRemoteConfiguration.java
1 /**
2 * Copyright (C) 2014 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.cdm.api.application;
11
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17
18 import org.apache.log4j.Logger;
19 import org.springframework.beans.BeansException;
20 import org.springframework.context.ApplicationContext;
21 import org.springframework.context.ApplicationContextAware;
22 import org.springframework.remoting.httpinvoker.CachingHttpInvokerProxyFactoryBean;
23 import org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor;
24 import org.springframework.security.access.AccessDecisionVoter;
25 import org.springframework.security.authentication.AuthenticationProvider;
26 import org.springframework.security.authentication.ProviderManager;
27 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
28 import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
29 import org.springframework.security.authentication.dao.ReflectionSaltSource;
30 import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
31 import org.springframework.security.core.Authentication;
32 import org.springframework.security.core.context.SecurityContext;
33 import org.springframework.security.core.context.SecurityContextHolder;
34 import org.springframework.stereotype.Component;
35 import org.springframework.transaction.PlatformTransactionManager;
36 import org.springframework.transaction.TransactionStatus;
37
38 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
39 import eu.etaxonomy.cdm.api.conversation.ConversationHolderMock;
40 import eu.etaxonomy.cdm.api.service.IAgentService;
41 import eu.etaxonomy.cdm.api.service.IAnnotationService;
42 import eu.etaxonomy.cdm.api.service.IClassificationService;
43 import eu.etaxonomy.cdm.api.service.ICollectionService;
44 import eu.etaxonomy.cdm.api.service.ICommonService;
45 import eu.etaxonomy.cdm.api.service.IDatabaseService;
46 import eu.etaxonomy.cdm.api.service.IDescriptionService;
47 import eu.etaxonomy.cdm.api.service.IDescriptiveDataSetService;
48 import eu.etaxonomy.cdm.api.service.IEntityConstraintViolationService;
49 import eu.etaxonomy.cdm.api.service.IEntityValidationService;
50 import eu.etaxonomy.cdm.api.service.IEventBaseService;
51 import eu.etaxonomy.cdm.api.service.IFeatureNodeService;
52 import eu.etaxonomy.cdm.api.service.IFeatureTreeService;
53 import eu.etaxonomy.cdm.api.service.IGrantedAuthorityService;
54 import eu.etaxonomy.cdm.api.service.IGroupService;
55 import eu.etaxonomy.cdm.api.service.IIdentificationKeyService;
56 import eu.etaxonomy.cdm.api.service.ILocationService;
57 import eu.etaxonomy.cdm.api.service.IMediaService;
58 import eu.etaxonomy.cdm.api.service.IMetadataService;
59 import eu.etaxonomy.cdm.api.service.INameService;
60 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
61 import eu.etaxonomy.cdm.api.service.IPolytomousKeyNodeService;
62 import eu.etaxonomy.cdm.api.service.IPolytomousKeyService;
63 import eu.etaxonomy.cdm.api.service.IPreferenceService;
64 import eu.etaxonomy.cdm.api.service.IProgressMonitorService;
65 import eu.etaxonomy.cdm.api.service.IReferenceService;
66 import eu.etaxonomy.cdm.api.service.IRegistrationService;
67 import eu.etaxonomy.cdm.api.service.IRightsService;
68 import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
69 import eu.etaxonomy.cdm.api.service.ITaxonService;
70 import eu.etaxonomy.cdm.api.service.ITermNodeService;
71 import eu.etaxonomy.cdm.api.service.ITermService;
72 import eu.etaxonomy.cdm.api.service.ITermTreeService;
73 import eu.etaxonomy.cdm.api.service.ITestService;
74 import eu.etaxonomy.cdm.api.service.IUserService;
75 import eu.etaxonomy.cdm.api.service.IVocabularyService;
76 import eu.etaxonomy.cdm.api.service.longrunningService.ILongRunningTasksService;
77 import eu.etaxonomy.cdm.api.service.molecular.IAmplificationService;
78 import eu.etaxonomy.cdm.api.service.molecular.IPrimerService;
79 import eu.etaxonomy.cdm.api.service.molecular.ISequenceService;
80 import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
81 import eu.etaxonomy.cdm.io.service.IIOService;
82 import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermissionEvaluator;
83 import eu.etaxonomy.cdm.persistence.hibernate.permission.ICdmPermissionEvaluator;
84 import eu.etaxonomy.cdm.persistence.hibernate.permission.UnanimousBasedUnrevokable;
85 import eu.etaxonomy.cdm.persistence.hibernate.permission.voter.DescriptionBaseVoter;
86 import eu.etaxonomy.cdm.persistence.hibernate.permission.voter.DescriptionElementVoter;
87 import eu.etaxonomy.cdm.persistence.hibernate.permission.voter.GrantAlwaysVoter;
88 import eu.etaxonomy.cdm.persistence.hibernate.permission.voter.TaxonBaseVoter;
89 import eu.etaxonomy.cdm.persistence.hibernate.permission.voter.TaxonNodeVoter;
90 import eu.etaxonomy.taxeditor.remoting.source.ICdmRemoteSource;
91 import eu.etaxonomy.taxeditor.service.CachedCommonServiceImpl;
92 import eu.etaxonomy.taxeditor.service.CdmAuthenticatedHttpInvokerRequestExecutor;
93 import eu.etaxonomy.taxeditor.service.CdmServiceRequestExecutor;
94 import eu.etaxonomy.taxeditor.service.ICachedCommonService;
95 import eu.etaxonomy.taxeditor.service.RemoteInvocationTermCacher;
96 import eu.etaxonomy.taxeditor.session.CdmEntitySessionManager;
97 import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
98
99
100 /**
101 * CDM Application Configuration class which manages the configuration for remoting
102 * clients
103 *
104 */
105 @Component
106 // TODO split into CdmRepository and proper @Configuration class
107 public class CdmApplicationRemoteConfiguration implements ICdmRepository, ApplicationContextAware {
108
109 private static final int HTTP_READ_TIMEOUT = 0;
110
111 @SuppressWarnings("unused")
112 private static final Logger logger = Logger.getLogger(CdmApplicationRemoteConfiguration.class);
113
114 protected ApplicationContext applicationContext;
115
116 private ICdmRemoteSource remoteSource;
117
118 //TODO should be something like Map<Class<IService>, IService>, but we have no common service base interface yet
119 private Map<Class<?>, Object> serviceMap = new HashMap<>();
120
121 private ICdmEntitySessionManager cdmEntitySessionManager;
122
123 private CdmPermissionEvaluator cdmPermissionEvaluator;
124
125 private ProviderManager authenticationManager;
126
127 private ICachedCommonService cachedCommonService;
128
129 public CdmApplicationRemoteConfiguration() {}
130
131 public CdmApplicationRemoteConfiguration(ICdmRemoteSource remoteSource) {
132 this.remoteSource = remoteSource;
133
134 }
135
136 public void setRemoteSource(ICdmRemoteSource remoteSource) {
137 this.remoteSource = remoteSource;
138 }
139
140 private Object getService(Class<?/* extends IService*/> clazz, String serviceSuffix, HttpComponentsHttpInvokerRequestExecutor executor) {
141 if(serviceMap.containsKey(clazz)) {
142 return serviceMap.get(clazz);
143 }
144 Object service = getService(clazz, serviceSuffix, remoteSource, executor);
145 serviceMap.put(clazz, service);
146 return service;
147 }
148
149 public static Object getService(Class<?> clazz,
150 String serviceSuffix,
151 ICdmRemoteSource remoteSource,
152 HttpComponentsHttpInvokerRequestExecutor executor) {
153
154 String baseUrl;
155 if(remoteSource.getContextPath() == null || remoteSource.getContextPath().equals("")) {
156 baseUrl = "http://" + remoteSource.getServer() + ":" + String.valueOf(remoteSource.getPort());
157 } else {
158 baseUrl = "http://" + remoteSource.getServer() + ":" + String.valueOf(remoteSource.getPort()) + "/" + remoteSource.getContextPath();
159 }
160 CachingHttpInvokerProxyFactoryBean proxyFactory = new CachingHttpInvokerProxyFactoryBean();
161 proxyFactory.setServiceInterface(clazz);
162 proxyFactory.setServiceUrl(baseUrl + serviceSuffix);
163 if(executor != null) {
164 executor.setReadTimeout(HTTP_READ_TIMEOUT);
165 proxyFactory.setHttpInvokerRequestExecutor(executor);
166 }
167 if(ITermService.class.isAssignableFrom(clazz)){
168 proxyFactory.setRemoteInvocationTermCacher(new RemoteInvocationTermCacher());
169 }
170 proxyFactory.afterPropertiesSet();
171 return proxyFactory.getObject();
172 }
173
174 // ****************************** APPLICATION CONTEXT *************************************************/
175
176 @Override
177 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException{
178 this.applicationContext = applicationContext;
179 }
180
181 /* (non-Javadoc)
182 * @see eu.etaxonomy.cdm.api.application.CdmApplicationDefaultConfiguration#getTransactionManager()
183 */
184 @Override
185 public PlatformTransactionManager getTransactionManager() throws UnsupportedOperationException {
186 throw new UnsupportedOperationException("getTransactionManager is not implemented for CdmApplicationRemoteConfiguration");
187 }
188
189
190
191 /**
192 * @return
193 */
194 public IEditGeoService getEditGeoService() {
195 return (IEditGeoService) getService(IEditGeoService.class, "/remoting/editgeo.service", new CdmServiceRequestExecutor());
196 }
197
198 /**
199 * @return
200 */
201 public ICachedCommonService getCachedCommonService(){
202 if(cachedCommonService == null) {
203 cachedCommonService = new CachedCommonServiceImpl();
204 }
205 return cachedCommonService;
206 }
207
208
209 public ICdmEntitySessionManager getCdmEntitySessionManager() {
210 if(cdmEntitySessionManager == null) {
211 cdmEntitySessionManager = new CdmEntitySessionManager();
212 }
213 return cdmEntitySessionManager;
214 }
215
216
217
218
219
220
221 // ****************************** GETTER *************************************************/
222
223 @Override
224 public final Object getBean(String name){
225 throw new UnsupportedOperationException("getBean is not implemented for CdmApplicationRemoteConfiguration");
226 }
227
228 @Override
229 public IAgentService getAgentService(){
230 return (IAgentService) getService(IAgentService.class, "/remoting/agent.service", new CdmServiceRequestExecutor());
231 }
232
233 @Override
234 public IAnnotationService getAnnotationService(){
235 return (IAnnotationService) getService(IAnnotationService.class, "/remoting/annotation.service", new CdmServiceRequestExecutor());
236 }
237
238 @Override
239 public IDatabaseService getDatabaseService(){
240 return (IDatabaseService) getService(IDatabaseService.class, "/remoting/database.service", new CdmServiceRequestExecutor());
241 }
242
243 @Override
244 public INameService getNameService(){
245 return (INameService) getService(INameService.class, "/remoting/name.service", new CdmServiceRequestExecutor());
246 }
247
248 @Override
249 public IReferenceService getReferenceService(){
250 return (IReferenceService) getService(IReferenceService.class, "/remoting/reference.service", new CdmServiceRequestExecutor());
251 }
252
253 @Override
254 public ITaxonService getTaxonService(){
255 return (ITaxonService) getService(ITaxonService.class, "/remoting/taxon.service", new CdmServiceRequestExecutor());
256 }
257
258 @Override
259 public IClassificationService getClassificationService(){
260 return (IClassificationService) getService(IClassificationService.class, "/remoting/classification.service", new CdmServiceRequestExecutor());
261 }
262
263 @Override
264 public ITaxonNodeService getTaxonNodeService(){
265 return (ITaxonNodeService) getService(ITaxonNodeService.class, "/remoting/taxonnode.service", new CdmServiceRequestExecutor());
266 }
267
268 @Override
269 public IDescriptionService getDescriptionService(){
270 return (IDescriptionService) getService(IDescriptionService.class, "/remoting/description.service", new CdmServiceRequestExecutor());
271 }
272
273 @Override
274 public IOccurrenceService getOccurrenceService(){
275 return (IOccurrenceService) getService(IOccurrenceService.class, "/remoting/occurrence.service", new CdmServiceRequestExecutor());
276 }
277
278 @Override
279 public IPrimerService getPrimerService(){
280 return (IPrimerService) getService(IPrimerService.class, "/remoting/primer.service", new CdmServiceRequestExecutor());
281 }
282
283 @Override
284 public IAmplificationService getAmplificationService(){
285 return (IAmplificationService) getService(IAmplificationService.class, "/remoting/amplification.service", new CdmServiceRequestExecutor());
286 }
287
288 @Override
289 public ISequenceService getSequenceService(){
290 return (ISequenceService) getService(ISequenceService.class, "/remoting/sequence.service", new CdmServiceRequestExecutor());
291 }
292
293 @Override
294 public IEventBaseService getEventBaseService() {
295 return (IEventBaseService) getService(IEventBaseService.class, "/remoting/eventbase.service", new CdmServiceRequestExecutor());
296 }
297
298 @Override
299 public IMediaService getMediaService(){
300 return (IMediaService) getService(IMediaService.class, "/remoting/media.service", new CdmServiceRequestExecutor());
301 }
302
303 @Override
304 public ITermService getTermService(){
305 return (ITermService) getService(ITermService.class, "/remoting/term.service", new CdmServiceRequestExecutor());
306 }
307
308 @Override
309 public IRightsService getRightsService(){
310 return (IRightsService) getService(IRightsService.class, "/remoting/rights.service", new CdmServiceRequestExecutor());
311 }
312
313 @Override
314 public ICommonService getCommonService(){
315 return (ICommonService) getService(ICommonService.class, "/remoting/common.service", new CdmServiceRequestExecutor());
316 }
317
318 @Override
319 public ILocationService getLocationService(){
320 return (ILocationService) getService(ILocationService.class, "/remoting/location.service", new CdmServiceRequestExecutor());
321 }
322
323 @Override
324 public IUserService getUserService(){
325 return (IUserService) getService(IUserService.class, "/remoting-public/user.service", new CdmServiceRequestExecutor());
326 }
327
328
329 public static IUserService getUserService(ICdmRemoteSource remoteSource) {
330 return (IUserService) getService(IUserService.class, "/remoting-public/user.service", remoteSource, new HttpComponentsHttpInvokerRequestExecutor());
331 }
332
333 @Override
334 public IMetadataService getMetadataService() {
335 return (IMetadataService) getService(IMetadataService.class, "/remoting-public/metadata.service", new HttpComponentsHttpInvokerRequestExecutor());
336 }
337
338 public static IMetadataService getMetadataService(ICdmRemoteSource remoteSource) {
339 return (IMetadataService) getService(IMetadataService.class, "/remoting-public/metadata.service", remoteSource, new HttpComponentsHttpInvokerRequestExecutor());
340 }
341
342 @Override
343 public IGrantedAuthorityService getGrantedAuthorityService(){
344 return (IGrantedAuthorityService) getService(IGrantedAuthorityService.class, "/remoting/grantedauthority.service", new CdmServiceRequestExecutor());
345 }
346
347
348 @Override
349 public ProviderManager getAuthenticationManager(){
350 if(authenticationManager == null) {
351 authenticationManager = getAuthenticationManager(getUserService());
352 }
353 return authenticationManager;
354 }
355
356 public static ProviderManager getAuthenticationManager(IUserService userService) {
357 Md5PasswordEncoder passwordEncoder = new Md5PasswordEncoder();
358 ReflectionSaltSource saltSource = new ReflectionSaltSource();
359 saltSource.setUserPropertyToUse("getUsername");
360
361 DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
362 daoAuthenticationProvider.setUserDetailsService(userService);
363 daoAuthenticationProvider.setSaltSource(saltSource);
364 daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
365
366 return new ProviderManager(Arrays.asList((AuthenticationProvider)daoAuthenticationProvider));
367 }
368
369
370 @Override
371 public ConversationHolder NewConversation() {
372 return new ConversationHolderMock();
373 }
374
375 @Override
376 public ICollectionService getCollectionService(){
377 return (ICollectionService) getService(ICollectionService.class, "/remoting/collection.service", new CdmServiceRequestExecutor());
378 }
379
380 @Override
381 public IFeatureTreeService getFeatureTreeService(){
382 return (IFeatureTreeService) getService(IFeatureTreeService.class, "/remoting/featuretree.service", new CdmServiceRequestExecutor());
383 }
384 @Override
385 public ITermTreeService getTermTreeService() {
386 return (ITermTreeService) getService(ITermTreeService.class, "/remoting/termtree.service", new CdmServiceRequestExecutor());
387 }
388
389 @Override
390 public IFeatureNodeService getFeatureNodeService(){
391 return (IFeatureNodeService) getService(IFeatureNodeService.class, "/remoting/featurenode.service", new CdmServiceRequestExecutor());
392 }
393
394 @Override
395 public ITermNodeService getTermNodeService() {
396 return (ITermNodeService) getService(ITermNodeService.class, "/remoting/termnode.service", new CdmServiceRequestExecutor());
397 }
398
399 @Override
400 public IVocabularyService getVocabularyService(){
401 return (IVocabularyService) getService(IVocabularyService.class, "/remoting/vocabulary.service", new CdmServiceRequestExecutor());
402 }
403
404 @Override
405 public IIdentificationKeyService getIdentificationKeyService(){
406 return (IIdentificationKeyService) getService(IIdentificationKeyService.class, "/remoting/identificationkey.service", new CdmServiceRequestExecutor());
407 }
408
409 @Override
410 public IPolytomousKeyService getPolytomousKeyService(){
411 return (IPolytomousKeyService) getService(IPolytomousKeyService.class, "/remoting/polytomouskey.service", new CdmServiceRequestExecutor());
412 }
413
414
415 @Override
416 public IPolytomousKeyNodeService getPolytomousKeyNodeService(){
417 return (IPolytomousKeyNodeService) getService(IPolytomousKeyNodeService.class, "/remoting/polytomouskeynode.service", new CdmServiceRequestExecutor());
418 }
419
420 @Override
421 public IProgressMonitorService getProgressMonitorService() {
422 return (IProgressMonitorService) getService(IProgressMonitorService.class, "/remoting/progressmonitor.service", new CdmAuthenticatedHttpInvokerRequestExecutor());
423 }
424
425 @Override
426 public IDescriptiveDataSetService getDescriptiveDataSetService(){
427 return (IDescriptiveDataSetService) getService(IDescriptiveDataSetService.class, "/remoting/descriptivedataset.service", new CdmServiceRequestExecutor());
428 }
429
430 /**
431 * {@inheritDoc}
432 */
433 @Override
434 public IRegistrationService getRegistrationService() {
435 return (IRegistrationService) getService(IRegistrationService.class, "/remoting/registration.service", new CdmServiceRequestExecutor());
436
437 }
438
439 @Override
440 public IGroupService getGroupService(){
441 return (IGroupService) getService(IGroupService.class, "/remoting/group.service", new CdmServiceRequestExecutor());
442 }
443
444 @Override
445 public IPreferenceService getPreferenceService(){
446 return (IPreferenceService) getService(IPreferenceService.class, "/remoting/preference.service", new CdmServiceRequestExecutor());
447 }
448
449
450 @Override
451 public IEntityValidationService getEntityValidationService(){
452 return (IEntityValidationService) getService(IEntityValidationService.class, "/remoting/entityvalidation.service", new CdmServiceRequestExecutor());
453 }
454
455
456 @Override
457 public IEntityConstraintViolationService getEntityConstraintViolationService(){
458 return (IEntityConstraintViolationService) getService(IEntityConstraintViolationService.class, "/remoting/entityconstraintviolation.service", new CdmServiceRequestExecutor());
459 }
460
461 @Override
462 public ICdmPermissionEvaluator getPermissionEvaluator(){
463
464 if(cdmPermissionEvaluator != null) {
465 return cdmPermissionEvaluator;
466 }
467 List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<>();
468 decisionVoters.add(new GrantAlwaysVoter());
469 decisionVoters.add(new TaxonNodeVoter());
470 decisionVoters.add(new TaxonBaseVoter());
471 decisionVoters.add(new DescriptionBaseVoter());
472 decisionVoters.add(new DescriptionElementVoter());
473 UnanimousBasedUnrevokable accessDecisionManager = new UnanimousBasedUnrevokable(decisionVoters);
474
475 cdmPermissionEvaluator = new CdmPermissionEvaluator();
476 cdmPermissionEvaluator.setAccessDecisionManager(accessDecisionManager);
477
478 return cdmPermissionEvaluator;
479 }
480
481
482 @Override
483 public TransactionStatus startTransaction() throws UnsupportedOperationException {
484 throw new UnsupportedOperationException("startTransaction is not implemented for CdmApplicationRemoteConfiguration");
485 }
486
487 @Override
488 public TransactionStatus startTransaction(Boolean readOnly) throws UnsupportedOperationException {
489 throw new UnsupportedOperationException("startTransaction is not implemented for CdmApplicationRemoteConfiguration");
490 }
491
492
493 @Override
494 public void commitTransaction(TransactionStatus txStatus) throws UnsupportedOperationException {
495 throw new UnsupportedOperationException("commitTransaction is not implemented for CdmApplicationRemoteConfiguration");
496 }
497
498 @Override
499 public void rollbackTransaction(TransactionStatus arg0) {
500 throw new UnsupportedOperationException("rollbackTransaction is not implemented for CdmApplicationRemoteConfiguration");
501 }
502
503 @Override
504 public void authenticate(String username, String password){
505 UsernamePasswordAuthenticationToken tokenForUser = new UsernamePasswordAuthenticationToken(username, password);
506 Authentication authentication = this.getAuthenticationManager().authenticate(tokenForUser);
507 SecurityContext context = SecurityContextHolder.getContext();
508 context.setAuthentication(authentication);
509 }
510
511 public IIOService getIOService() {
512 return (IIOService) getService(IIOService.class, "/remoting/io.service", new CdmServiceRequestExecutor());
513 }
514
515 @Override
516 public ILongRunningTasksService getLongRunningTasksService() {
517 return (ILongRunningTasksService) getService(ILongRunningTasksService.class, "/remoting/longrunningtasks.service", new CdmServiceRequestExecutor());
518 }
519
520 public ITestService getTestService() {
521 return (ITestService) getService(ITestService.class, "/remoting/test.service", new CdmServiceRequestExecutor());
522 }
523
524 }