/* * Copyright 2009-2014 Jose Luis Martin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jdal.vaadin.ui; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.annotation.PostConstruct; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jdal.annotation.SerializableProxy; import org.jdal.auth.AuthService; import org.jdal.vaadin.annotation.ViewConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.security.access.AccessDeniedException; import org.springframework.util.StringUtils; import com.vaadin.navigator.View; import com.vaadin.navigator.ViewProvider; import com.vaadin.ui.Component; /** * ViewProvider that delegates on a Spring BeanFactory to find Views * * @author Jose Luis Martin * @since 2.0 */ public class SpringViewProvider implements ViewProvider { private static final Log log = LogFactory.getLog(SpringViewProvider.class); @Autowired private ConfigurableListableBeanFactory beanFactory; @SerializableProxy @Autowired(required = false) private AuthService authService; private String defaultView = "mainView"; /** Maps navigator views to view bean names */ private Map<String, String> viewNames = new ConcurrentHashMap<String, String>(); /** Maps view bean names to security access expressions */ private Map<String, String> viewAccess = new ConcurrentHashMap<String, String>(); /** * Parse @VaadinView annotations and craate view mappings. */ @PostConstruct public void init() { String[] beanNames = this.beanFactory.getBeanNamesForAnnotation(ViewConfig.class); for (String name : beanNames) { Class<?> viewClass = this.beanFactory.getType(name); ViewConfig vc = AnnotationUtils.getAnnotation(viewClass, ViewConfig.class); if (!StringUtils.isEmpty(vc.value()) && !this.viewNames.containsKey(vc.value())) { if (log.isDebugEnabled()) log.debug("Mapping navigator view [" + vc.value() + "] to bean name [" + name + "]"); this.viewNames.put(vc.value(), name); if (!StringUtils.isEmpty(vc.access())) this.viewAccess.put(name, vc.access()); } else { if (log.isDebugEnabled()) log.debug("Skipping already registered navigator view ["+ vc.value() + "]"); } } } @Override public String getViewName(String viewAndParameters) { if (this.viewNames.containsKey(viewAndParameters)) return viewNames.get(viewAndParameters); return viewAndParameters; } @SuppressWarnings("rawtypes") @Override public View getView(String viewName) { if (StringUtils.isEmpty(viewName)) viewName = defaultView; Class<?> viewClass = beanFactory.getType(viewName); checkAccess(viewClass, viewName); Object view = beanFactory.getBean(viewName); Component c = null; if (view instanceof org.jdal.vaadin.ui.VaadinView) { c = ((VaadinView) view).getPanel(); } else if (view instanceof Component) { c= (Component) view; } return (View) (c instanceof View ? c : new ComponentViewAdapter(c)); } /** * @param viewName */ private void checkAccess(Class<?> viewClass, String viewName) { if (this.authService == null) return; String access = this.viewAccess.get(viewName); if (access == null) { // lookup annotation and cache result ViewConfig vc = AnnotationUtils.findAnnotation(viewClass, ViewConfig.class); access = vc == null ? "" : vc.access(); this.viewAccess.put(viewName, access); } if (!StringUtils.isEmpty(access) && !this.authService.checkAccess(viewClass, access, null)) throw new AccessDeniedException("Access is Denied"); } /** * @return the beanFactory */ public ConfigurableListableBeanFactory getBeanFactory() { return beanFactory; } /** * @param beanFactory the beanFactory to set */ public void setBeanFactory(ConfigurableListableBeanFactory beanFactory) { this.beanFactory = beanFactory; } public String getDefaultView() { return defaultView; } public void setDefaultView(String defaultView) { this.defaultView = defaultView; } public AuthService getAuthService() { return authService; } public void setAuthManager(AuthService authService) { this.authService = authService; } }