Project

General

Profile

Download (12 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.application.IRunAs;
46
import eu.etaxonomy.cdm.api.application.RunAsAdmin;
47
import eu.etaxonomy.cdm.api.cache.CdmCacher;
48
import eu.etaxonomy.cdm.api.config.ApplicationConfiguration;
49
import eu.etaxonomy.cdm.api.config.ApplicationConfigurationFile;
50
import eu.etaxonomy.cdm.api.service.idminter.RegistrationIdentifierMinter;
51
import eu.etaxonomy.cdm.api.service.taxonGraph.TaxonGraphBeforeTransactionCompleteProcess;
52
import eu.etaxonomy.cdm.cache.CdmTransientEntityCacher;
53
import eu.etaxonomy.cdm.dataInserter.RegistrationRequiredDataInserter;
54
import eu.etaxonomy.cdm.persistence.hibernate.GrantedAuthorityRevokingRegistrationUpdateLister;
55
import eu.etaxonomy.cdm.persistence.hibernate.ITaxonGraphHibernateListener;
56
import eu.etaxonomy.cdm.vaadin.permission.annotation.EnableAnnotationBasedAccessControl;
57
import eu.etaxonomy.cdm.vaadin.ui.ConceptRelationshipUI;
58
import eu.etaxonomy.cdm.vaadin.ui.DistributionStatusUI;
59
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUI;
60
import eu.etaxonomy.cdm.vaadin.ui.StatusEditorUI;
61
import eu.etaxonomy.vaadin.ui.annotation.EnableVaadinSpringNavigation;
62

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

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

    
94
    public static final Logger logger = Logger.getLogger(CdmVaadinConfiguration.class);
95

    
96
    @Autowired
97
    Environment env;
98

    
99
    @Autowired
100
    private SessionFactory sessionFactory;
101

    
102
    @Autowired
103
    private ApplicationConfiguration appConfig;
104

    
105
    @Autowired
106
    private ITaxonGraphHibernateListener taxonGraphHibernateListener;
107

    
108
    @Autowired
109
    private void  setTermCacher(CdmCacher termCacher){
110
        CdmTransientEntityCacher.setPermanentCacher(termCacher);
111
    }
112

    
113
    private boolean registrationUiHibernateEventListenersDone = false;
114

    
115

    
116
    ApplicationConfigurationFile configFile = new ApplicationConfigurationFile(PROPERTIES_FILE_NAME, APP_FILE_CONTENT);
117

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

    
126
        private static final long serialVersionUID = -2615042297393028775L;
127

    
128

    
129
        /**
130
         *
131
        @SuppressWarnings("serial")
132
        @Override
133
        protected void servletInitialized() throws ServletException {
134
            getService().addSessionInitListener(new SessionInitListener() {
135

    
136
                @Override
137
                public void sessionInit(SessionInitEvent sessionInitEvent) throws ServiceException {
138
                    VaadinSession session = sessionInitEvent.getSession();
139
                    session.setErrorHandler(new DefaultErrorHandler(){
140

    
141
                        @Override
142
                        public void error(ErrorEvent errorEvent) {
143
                            // ...
144
                        }
145

    
146
                    });
147
                    ).getServiceRegistry().getService
148

    
149
                }});
150

    
151
        }
152
         */
153

    
154
    }
155

    
156
    public CdmVaadinConfiguration() {
157
        logger.debug("CdmVaadinConfiguration enabled");
158
    }
159

    
160
    @Bean
161
    @UIScope
162
    public ConceptRelationshipUI conceptRelationshipUI() {
163
        if(isUIEnabled(ConceptRelationshipUI.class)){
164
            return new ConceptRelationshipUI();
165
        }
166
        return null;
167
    }
168

    
169
    @Bean
170
    @UIScope
171
    public RegistrationUI registrationUI() {
172
        if(isUIEnabled(RegistrationUI.class)){
173
            registerRegistrationUiHibernateEventListeners();
174
            return new RegistrationUI();
175
        }
176
        return null;
177
    }
178

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

    
188
            listenerRegistry.appendListeners(EventType.POST_UPDATE, new GrantedAuthorityRevokingRegistrationUpdateLister());
189
            // TODO also POST_DELETE needed for GrantedAuthorityRevokingRegistrationUpdateLister?
190

    
191
            try {
192
                taxonGraphHibernateListener.registerProcessClass(TaxonGraphBeforeTransactionCompleteProcess.class, new Object[]{new RunAsAdmin()}, new Class[]{IRunAs.class});
193
            } catch (NoSuchMethodException | SecurityException e) {
194
                // re-throw as RuntimeException as the context can not be created correctly
195
                throw new RuntimeException(e);
196
            }
197

    
198
            registrationUiHibernateEventListenersDone = true;
199
        }
200
    }
201

    
202
    @Bean
203
    public AbstractDataInserter registrationRequiredDataInserter() throws BeansException{
204
        if(isUIEnabled(RegistrationUI.class)){
205
            RegistrationRequiredDataInserter inserter = new RegistrationRequiredDataInserter();
206

    
207
            inserter.setRunAsAuthenticationProvider((AuthenticationProvider) applicationContext.getBean("runAsAuthenticationProvider"));
208
            inserter.setCdmRepository((CdmRepository) applicationContext.getBean("cdmRepository"));
209
            return inserter;
210
        } else {
211
            // the return type implements ApplicationListener and thus must not be null,
212
            // therefore we return a empty dummy implementation.
213
            return new DummyDataInserter();
214
        }
215
    }
216

    
217
    @Bean
218
    public RegistrationIdentifierMinter registrationIdentifierMinter() throws IOException {
219
        RegistrationIdentifierMinter minter = new RegistrationIdentifierMinter();
220

    
221
        minter.setMinLocalId(appConfig.getProperty(configFile , CDM_SERVICE_MINTER_REGSTRATION_MINID));
222
        minter.setMaxLocalId(appConfig.getProperty(configFile , CDM_SERVICE_MINTER_REGSTRATION_MAXID));
223
        minter.setIdentifierFormatString(appConfig.getProperty(configFile , CDM_SERVICE_MINTER_REGSTRATION_IDFORMAT));
224
        return minter;
225
    }
226

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

    
236
    @Bean
237
    @UIScope
238
    public StatusEditorUI statusEditorUI() {
239
        if(isUIEnabled(StatusEditorUI.class)){
240
            return new StatusEditorUI();
241
        }
242
        return null;
243
    }
244

    
245
    static final String PROPERTIES_FILE_NAME = "vaadin-apps";
246

    
247
    private Properties appProps = null;
248

    
249
    private ApplicationContext applicationContext;
250

    
251
    private List<String> activeUIpaths;
252

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

    
270
    /**
271
     * Checks if the ui class supplied is activated by listing it in the properties by its {@link SpringUI#path()} value.
272
     *
273
     * TODO see https://dev.e-taxonomy.eu/redmine/issues/7139 (consider using spring profiles to enable vaadin UI contexts)
274
     *
275
     * @param type
276
     * @return
277
     */
278
    private boolean isUIEnabled(Class<? extends UI>uiClass) {
279

    
280
        String path = uiClass.getAnnotation(SpringUI.class).path().trim();
281

    
282
        if(activeUIpaths == null){
283
            String activatedVaadinUIs = env.getProperty(CDM_VAADIN_UI_ACTIVATED);
284
            if(activatedVaadinUIs == null){
285
                // not in environment? Read it from the config file!
286
                activatedVaadinUIs = appConfig.getProperty(configFile , CDM_VAADIN_UI_ACTIVATED);
287
            }
288

    
289
            if(activatedVaadinUIs != null) {
290
                String[] uiPaths = activatedVaadinUIs.split("\\s*,\\s*");
291
                this.activeUIpaths = Arrays.asList(uiPaths);
292
            }
293
        }
294
        if(activeUIpaths.stream().anyMatch(p -> p.trim().equals(path))){
295
            return true;
296
        }
297
        return false;
298

    
299
    }
300

    
301

    
302

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

    
311

    
312
}
(1-1/2)