Project

General

Profile

Download (11.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2017 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
package eu.etaxonomy.cdm.addon.config;
10

    
11
import java.io.IOException;
12
import java.util.Arrays;
13
import java.util.List;
14
import java.util.Properties;
15

    
16
import javax.servlet.annotation.WebServlet;
17

    
18
import org.apache.log4j.Logger;
19
import org.hibernate.SessionFactory;
20
import org.hibernate.event.service.spi.EventListenerRegistry;
21
import org.hibernate.event.spi.EventType;
22
import org.hibernate.internal.SessionFactoryImpl;
23
import org.springframework.beans.BeansException;
24
import org.springframework.beans.factory.annotation.Autowired;
25
import org.springframework.context.ApplicationContext;
26
import org.springframework.context.ApplicationContextAware;
27
import org.springframework.context.annotation.Bean;
28
import org.springframework.context.annotation.ComponentScan;
29
import org.springframework.context.annotation.ComponentScan.Filter;
30
import org.springframework.context.annotation.Configuration;
31
import org.springframework.context.annotation.FilterType;
32
import org.springframework.core.env.Environment;
33
import org.springframework.security.authentication.AuthenticationProvider;
34
import org.vaadin.spring.events.annotation.EnableEventBus;
35

    
36
import com.vaadin.spring.annotation.EnableVaadin;
37
import com.vaadin.spring.annotation.SpringUI;
38
import com.vaadin.spring.annotation.UIScope;
39
import com.vaadin.spring.server.SpringVaadinServlet;
40
import com.vaadin.ui.UI;
41

    
42
import eu.etaxonomy.cdm.api.application.AbstractDataInserter;
43
import eu.etaxonomy.cdm.api.application.CdmRepository;
44
import eu.etaxonomy.cdm.api.application.DummyDataInserter;
45
import eu.etaxonomy.cdm.api.cache.CdmCacher;
46
import eu.etaxonomy.cdm.api.config.ApplicationConfiguration;
47
import eu.etaxonomy.cdm.api.config.ApplicationConfigurationFile;
48
import eu.etaxonomy.cdm.api.service.idminter.RegistrationIdentifierMinter;
49
import eu.etaxonomy.cdm.cache.CdmTransientEntityCacher;
50
import eu.etaxonomy.cdm.dataInserter.RegistrationRequiredDataInserter;
51
import eu.etaxonomy.cdm.persistence.hibernate.GrantedAuthorityRevokingRegistrationUpdateLister;
52
import eu.etaxonomy.cdm.persistence.hibernate.TaxonGraphHibernateListener;
53
import eu.etaxonomy.cdm.vaadin.permission.annotation.EnableAnnotationBasedAccessControl;
54
import eu.etaxonomy.cdm.vaadin.ui.ConceptRelationshipUI;
55
import eu.etaxonomy.cdm.vaadin.ui.DistributionStatusUI;
56
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUI;
57
import eu.etaxonomy.cdm.vaadin.ui.StatusEditorUI;
58
import eu.etaxonomy.vaadin.ui.annotation.EnableVaadinSpringNavigation;
59

    
60
/**
61
 *
62
 * @author a.kohlbecker
63
 * @since Feb 8, 2017
64
 *
65
 */
66
@Configuration
67
@ComponentScan(basePackages={
68
        "eu.etaxonomy.vaadin.ui",
69
        "eu.etaxonomy.cdm.vaadin",
70
        "eu.etaxonomy.cdm.service",
71
        "org.springframework.context.event",
72
        "eu.etaxonomy.cdm.ext.registration.messages.redmine" // FIXME needed???
73
        },
74
        // exclude UI classes, these are provided via the @Bean annotated methods below
75
        excludeFilters={@Filter(
76
                pattern="eu\\.etaxonomy\\.cdm\\.vaadin\\.ui\\..*",
77
                type=FilterType.REGEX
78
                )
79
            })
80
@EnableVaadin   // this imports VaadinConfiguration
81
@EnableVaadinSpringNavigation // activate the NavigationManagerBean
82
@EnableAnnotationBasedAccessControl // enable annotation based per view access control
83
@EnableEventBus // enable the vaadin spring event bus
84
public class CdmVaadinConfiguration implements ApplicationContextAware  {
85

    
86
    public static final String CDM_VAADIN_UI_ACTIVATED = "cdm-vaadin.ui.activated";
87
    public static final String CDM_SERVICE_MINTER_REGSTRATION_MINID = "cdm.service.minter.registration.minLocalId";
88
    public static final String CDM_SERVICE_MINTER_REGSTRATION_MAXID = "cdm.service.minter.registration.maxLocalId";
89
    public static final String CDM_SERVICE_MINTER_REGSTRATION_IDFORMAT = "cdm.service.minter.registration.identifierFormatString";
90

    
91
    public static final Logger logger = Logger.getLogger(CdmVaadinConfiguration.class);
92

    
93
    @Autowired
94
    Environment env;
95

    
96
    @Autowired
97
    private SessionFactory sessionFactory;
98

    
99
    @Autowired
100
    private ApplicationConfiguration appConfig;
101

    
102
    @Autowired
103
    private void  setTermCacher(CdmCacher termCacher){
104
        CdmTransientEntityCacher.setPermanentCacher(termCacher);
105
    }
106

    
107
    private boolean registrationUiHibernateEventListenersDone = false;
108

    
109

    
110
    ApplicationConfigurationFile configFile = new ApplicationConfigurationFile(PROPERTIES_FILE_NAME, APP_FILE_CONTENT);
111

    
112
    /*
113
     * NOTE: It is necessary to map the URLs starting with /VAADIN/* since none of the
114
     * @WebServlets is mapped to the root path. It is sufficient to configure one of the
115
     * servlets with this path see BookOfVaadin 5.9.5. Servlet Mapping with URL Patterns
116
     */
117
    @WebServlet(value = {"/app/*", "/VAADIN/*"}, asyncSupported = true)
118
    public static class Servlet extends SpringVaadinServlet {
119

    
120
        private static final long serialVersionUID = -2615042297393028775L;
121

    
122

    
123
        /**
124
         *
125
        @SuppressWarnings("serial")
126
        @Override
127
        protected void servletInitialized() throws ServletException {
128
            getService().addSessionInitListener(new SessionInitListener() {
129

    
130
                @Override
131
                public void sessionInit(SessionInitEvent sessionInitEvent) throws ServiceException {
132
                    VaadinSession session = sessionInitEvent.getSession();
133
                    session.setErrorHandler(new DefaultErrorHandler(){
134

    
135
                        @Override
136
                        public void error(ErrorEvent errorEvent) {
137
                            // ...
138
                        }
139

    
140
                    });
141
                    ).getServiceRegistry().getService
142

    
143
                }});
144

    
145
        }
146
         */
147

    
148
    }
149

    
150
    public CdmVaadinConfiguration() {
151
        logger.debug("CdmVaadinConfiguration enabled");
152
    }
153

    
154
    @Bean
155
    @UIScope
156
    public ConceptRelationshipUI conceptRelationshipUI() {
157
        if(isUIEnabled(ConceptRelationshipUI.class)){
158
            return new ConceptRelationshipUI();
159
        }
160
        return null;
161
    }
162

    
163
    @Bean
164
    @UIScope
165
    public RegistrationUI registrationUI() {
166
        if(isUIEnabled(RegistrationUI.class)){
167
            registerRegistrationUiHibernateEventListeners();
168
            return new RegistrationUI();
169
        }
170
        return null;
171
    }
172

    
173

    
174

    
175
    /**
176
     * this is only a quick implementation for testing,
177
     * TODO see also the NOTE on CdmListenerIntegrator class declaration for a prospective better solution
178
     */
179
    protected void registerRegistrationUiHibernateEventListeners() {
180
        if(!registrationUiHibernateEventListenersDone){
181
            EventListenerRegistry listenerRegistry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(
182
                    EventListenerRegistry.class);
183

    
184
            listenerRegistry.appendListeners(EventType.POST_UPDATE, new GrantedAuthorityRevokingRegistrationUpdateLister());
185
            // TODO also POST_DELETE needed for GrantedAuthorityRevokingRegistrationUpdateLister?
186

    
187
            listenerRegistry.appendListeners(EventType.POST_UPDATE, new TaxonGraphHibernateListener());
188
            listenerRegistry.appendListeners(EventType.POST_INSERT, new TaxonGraphHibernateListener());
189

    
190
            registrationUiHibernateEventListenersDone = true;
191
        }
192
    }
193

    
194
    @Bean
195
    public AbstractDataInserter registrationRequiredDataInserter() throws BeansException{
196
        if(isUIEnabled(RegistrationUI.class)){
197
            RegistrationRequiredDataInserter inserter = new RegistrationRequiredDataInserter();
198

    
199
            inserter.setRunAsAuthenticationProvider((AuthenticationProvider) applicationContext.getBean("runAsAuthenticationProvider"));
200
            inserter.setCdmRepository((CdmRepository) applicationContext.getBean("cdmRepository"));
201
            return inserter;
202
        } else {
203
            // the return type implements ApplicationListener and thus must not be null,
204
            // therefore we return a empty dummy implementation.
205
            return new DummyDataInserter();
206
        }
207
    }
208

    
209
    @Bean
210
    public RegistrationIdentifierMinter registrationIdentifierMinter() throws IOException {
211
        RegistrationIdentifierMinter minter = new RegistrationIdentifierMinter();
212

    
213
        minter.setMinLocalId(appConfig.getProperty(configFile , CDM_SERVICE_MINTER_REGSTRATION_MINID));
214
        minter.setMaxLocalId(appConfig.getProperty(configFile , CDM_SERVICE_MINTER_REGSTRATION_MAXID));
215
        minter.setIdentifierFormatString(appConfig.getProperty(configFile , CDM_SERVICE_MINTER_REGSTRATION_IDFORMAT));
216
        return minter;
217
    }
218

    
219
    @Bean
220
    @UIScope
221
    public DistributionStatusUI distributionStatusUI() {
222
        if(isUIEnabled(DistributionStatusUI.class)){
223
            return new DistributionStatusUI();
224
        }
225
        return null;
226
    }
227

    
228
    @Bean
229
    @UIScope
230
    public StatusEditorUI statusEditorUI() {
231
        if(isUIEnabled(StatusEditorUI.class)){
232
            return new StatusEditorUI();
233
        }
234
        return null;
235
    }
236

    
237
    static final String PROPERTIES_FILE_NAME = "vaadin-apps";
238

    
239
    private Properties appProps = null;
240

    
241
    private ApplicationContext applicationContext;
242

    
243
    private List<String> activeUIpaths;
244

    
245
    //@formatter:off
246
    private static final String APP_FILE_CONTENT=
247
            "########################################################\n"+
248
            "#                                                       \n"+
249
            "# Vaadin application specific configurations            \n"+
250
            "#                                                       \n"+
251
            "########################################################\n"+
252
            "                                                        \n"+
253
            "# Enablement of vaadin uis.                             \n"+
254
            "#                                                       \n"+
255
            "# Multiple uis can be defined as comma separated list.  \n"+
256
            "# Whitespace before and after the comma will be ignored.\n"+
257
            "# Valid values are the path properties of the @SpringUI \n"+
258
            "# annotation which is used for UI classes.              \n"+
259
            "cdm-vaadin.ui.activated=concept,distribution,editstatus \n";
260
    //@formatter:on
261

    
262
    /**
263
     * Checks if the ui class supplied is activated by listing it in the properties by its {@link SpringUI#path()} value.
264
     *
265
     * TODO see https://dev.e-taxonomy.eu/redmine/issues/7139 (consider using spring profiles to enable vaadin UI contexts)
266
     *
267
     * @param type
268
     * @return
269
     */
270
    private boolean isUIEnabled(Class<? extends UI>uiClass) {
271

    
272
        String path = uiClass.getAnnotation(SpringUI.class).path().trim();
273

    
274
        if(activeUIpaths == null){
275
            String activatedVaadinUIs = env.getProperty(CDM_VAADIN_UI_ACTIVATED);
276
            if(activatedVaadinUIs == null){
277
                // not in environment? Read it from the config file!
278
                activatedVaadinUIs = appConfig.getProperty(configFile , CDM_VAADIN_UI_ACTIVATED);
279
            }
280

    
281
            if(activatedVaadinUIs != null) {
282
                String[] uiPaths = activatedVaadinUIs.split("\\s*,\\s*");
283
                this.activeUIpaths = Arrays.asList(uiPaths);
284
            }
285
        }
286
        if(activeUIpaths.stream().anyMatch(p -> p.trim().equals(path))){
287
            return true;
288
        }
289
        return false;
290

    
291
    }
292

    
293

    
294

    
295
    /**
296
     * {@inheritDoc}
297
     */
298
    @Override
299
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
300
        this.applicationContext = applicationContext;
301
    }
302

    
303

    
304
}
(1-1/2)