Project

General

Profile

Download (11.8 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

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

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

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

    
82

    
83
    public static final String CDM_DATA_SOURCE_ID = DataSourceConfigurer.CDM_DATA_SOURCE_ID;
84

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

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

    
92
    @Autowired
93
    Environment env;
94

    
95
    @Autowired
96
    private SessionFactory sessionFactory;
97

    
98
    @Autowired
99
    private void  setTermCacher(CdmCacher termCacher){
100
        CdmTransientEntityCacher.setDefaultCacher(termCacher);
101
    }
102

    
103
    private boolean registrationUiHibernateEventListenersDone = false;
104

    
105
    /*
106
     * NOTE: It is necessary to map the URLs starting with /VAADIN/* since none of the
107
     * @WebServlets is mapped to the root path. It is sufficient to configure one of the
108
     * servlets with this path see BookOfVaadin 5.9.5. Servlet Mapping with URL Patterns
109
     */
110
    @WebServlet(value = {"/app/*", "/VAADIN/*"}, asyncSupported = true)
111
    public static class Servlet extends SpringVaadinServlet {
112

    
113
        private static final long serialVersionUID = -2615042297393028775L;
114

    
115

    
116
        /**
117
         *
118
        @SuppressWarnings("serial")
119
        @Override
120
        protected void servletInitialized() throws ServletException {
121
            getService().addSessionInitListener(new SessionInitListener() {
122

    
123
                @Override
124
                public void sessionInit(SessionInitEvent sessionInitEvent) throws ServiceException {
125
                    VaadinSession session = sessionInitEvent.getSession();
126
                    session.setErrorHandler(new DefaultErrorHandler(){
127

    
128
                        @Override
129
                        public void error(ErrorEvent errorEvent) {
130
                            // ...
131
                        }
132

    
133
                    });
134
                    ).getServiceRegistry().getService
135

    
136
                }});
137

    
138
        }
139
         */
140

    
141
    }
142

    
143
    public CdmVaadinConfiguration() {
144
        logger.debug("CdmVaadinConfiguration enabled");
145
    }
146

    
147
    @Bean
148
    @UIScope
149
    public ConceptRelationshipUI conceptRelationshipUI() {
150
        if(isUIEnabled(ConceptRelationshipUI.class)){
151
            return new ConceptRelationshipUI();
152
        }
153
        return null;
154
    }
155

    
156
    @Bean
157
    @UIScope
158
    public RegistrationUI registrationUI() {
159
        if(isUIEnabled(RegistrationUI.class)){
160
            registerRegistrationUiHibernateEventListeners();
161

    
162
            return new RegistrationUI();
163
        }
164
        return null;
165
    }
166

    
167
    /**
168
     * this is only a quick implementation for testing,
169
     * TODO see also the NOTE on CdmListenerIntegrator class declaration for a prospective better solution
170
     */
171
    protected void registerRegistrationUiHibernateEventListeners() {
172
        if(!registrationUiHibernateEventListenersDone){
173
            EventListenerRegistry listenerRegistry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(
174
                    EventListenerRegistry.class);
175
            GrantedAuthorityRevokingRegistrationUpdateLister listener = new GrantedAuthorityRevokingRegistrationUpdateLister();
176
            listenerRegistry.appendListeners(EventType.POST_UPDATE, listener);
177
            registrationUiHibernateEventListenersDone = true;
178
        }
179
    }
180

    
181
    @Bean
182
    public AbstractDataInserter registrationRequiredDataInserter() throws BeansException{
183
        if(isUIEnabled(RegistrationUI.class)){
184
            RegistrationRequiredDataInserter inserter = new RegistrationRequiredDataInserter();
185

    
186
            inserter.setRunAsAuthenticationProvider((AuthenticationProvider) applicationContext.getBean("runAsAuthenticationProvider"));
187
            inserter.setCdmRepository((CdmRepository) applicationContext.getBean("cdmRepository"));
188
            return inserter;
189
        } else {
190
            // the return type implements ApplicationListener and thus must not be null,
191
            // therefore we return a empty dummy implementation.
192
            return new DummyDataInserter();
193
        }
194
    }
195

    
196
    @Bean
197
    public RegistrationIdentifierMinter registrationIdentifierMinter() throws IOException {
198
        RegistrationIdentifierMinter minter = new RegistrationIdentifierMinter();
199
        ensureVaadinAppPropertiesLoaded();
200
        minter.setMinLocalId(appProps.getProperty(CDM_SERVICE_MINTER_REGSTRATION_MINID));
201
        minter.setMaxLocalId(appProps.getProperty(CDM_SERVICE_MINTER_REGSTRATION_MAXID));
202
        minter.setIdentifierFormatString(appProps.getProperty(CDM_SERVICE_MINTER_REGSTRATION_IDFORMAT));
203
        return minter;
204
    }
205

    
206
    @Bean
207
    @UIScope
208
    public DistributionStatusUI distributionStatusUI() {
209
        if(isUIEnabled(DistributionStatusUI.class)){
210
            return new DistributionStatusUI();
211
        }
212
        return null;
213
    }
214

    
215
    @Bean
216
    @UIScope
217
    public StatusEditorUI statusEditorUI() {
218
        if(isUIEnabled(StatusEditorUI.class)){
219
            return new StatusEditorUI();
220
        }
221
        return null;
222
    }
223

    
224

    
225

    
226

    
227
    static final String PROPERTIES_FILE_NAME = "vaadin-apps";
228

    
229
    private Properties appProps = null;
230

    
231
    private ApplicationContext applicationContext;
232

    
233
    private List<String> activeUIpaths;
234

    
235
    //@formatter:off
236
    private static final String APP_FILE_CONTENT=
237
            "########################################################\n"+
238
            "#                                                       \n"+
239
            "# Vaadin application specific configurations            \n"+
240
            "#                                                       \n"+
241
            "########################################################\n"+
242
            "                                                        \n"+
243
            "# Enablement of vaadin uis.                             \n"+
244
            "#                                                       \n"+
245
            "# Multiple uis can be defined as comma separated list.  \n"+
246
            "# Whitespace before and after the comma will be ignored.\n"+
247
            "# Valid values are the path properties of the @SpringUI \n"+
248
            "# annotation which is used for UI classes.              \n"+
249
            "cdm-vaadin.ui.activated=concept,distribution,editstatus \n";
250
    //@formatter:on
251

    
252
    /**
253
     * Checks if the ui class supplied is activated by listing it in the properties by its {@link SpringUI#path()} value.
254
     *
255
     * TODO see https://dev.e-taxonomy.eu/redmine/issues/7139 (consider using spring profiles to enable vaadin UI contexts)
256
     *
257
     * @param type
258
     * @return
259
     */
260
    private boolean isUIEnabled(Class<? extends UI>uiClass) {
261

    
262
        String path = uiClass.getAnnotation(SpringUI.class).path().trim();
263

    
264
        if(activeUIpaths == null){
265
            try {
266

    
267
                String activatedVaadinUIs = env.getProperty(CDM_VAADIN_UI_ACTIVATED);
268
                if(activatedVaadinUIs == null){
269
                    // not in environment? Read it from the config file!
270
                    ensureVaadinAppPropertiesLoaded();
271
                    if(appProps.get(CDM_VAADIN_UI_ACTIVATED) != null){
272
                        activatedVaadinUIs = appProps.get(CDM_VAADIN_UI_ACTIVATED).toString();
273
                    }
274
                }
275

    
276
                if(activatedVaadinUIs != null) {
277
                    String[] uiPaths = activatedVaadinUIs.split("\\s*,\\s*");
278
                    this.activeUIpaths = Arrays.asList(uiPaths);
279
                }
280
            } catch (IOException e) {
281
                logger.error("Error reading the vaadin ui properties file. File corrupted?. Stopping instance ...");
282
                throw new RuntimeException(e);
283
            }
284
        }
285
        if(activeUIpaths.stream().anyMatch(p -> p.trim().equals(path))){
286
            return true;
287
        }
288
        return false;
289

    
290
    }
291

    
292
    /**
293
     * @param currentDataSourceId
294
     * @throws IOException
295
     */
296
    protected void ensureVaadinAppPropertiesLoaded() throws IOException {
297

    
298
        String currentDataSourceId = env.getProperty(CDM_DATA_SOURCE_ID);
299
        if(appProps == null){
300
            appProps = new ConfigFileUtil()
301
                    .setDefaultContent(APP_FILE_CONTENT)
302
                    .getProperties(currentDataSourceId, PROPERTIES_FILE_NAME);
303
        }
304
    }
305

    
306
    /**
307
     * {@inheritDoc}
308
     */
309
    @Override
310
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
311
        this.applicationContext = applicationContext;
312
    }
313

    
314

    
315
}
(1-1/2)