/* * Copyright 2009-2015 the original author or authors. * * 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; import java.io.Serializable; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jdal.annotation.SerializableProxy; import org.jdal.vaadin.annotation.UiMapping; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import com.vaadin.server.VaadinRequest; import com.vaadin.ui.UI; /** * {@link UiRequestMapping} implementation that look for {@link UI UIs} by bean name. * Parse {@link UiMapping} annotations in spring context UI types and match urls using * an {@link AntPathMatcher}. * * @author Jose Luis Martin * @since 2.1 */ @SerializableProxy public class UrlBeanNameUiMapping implements UiRequestMapping, Serializable { private static final Log log = LogFactory.getLog(UrlBeanNameUiMapping.class); /** translate paths to bean names */ private Map<String, String> urlMap = new ConcurrentHashMap<String, String>();; /** Used to match url paths */ private transient PathMatcher pathMatcher = new AntPathMatcher(); @Override public UI getUi(VaadinRequest request) { ApplicationContext ctx = VaadinUtils.getApplicationContext(); String beanName = getBeanNameFromRequest(request); if (beanName != null && ctx.containsBean(beanName)) return VaadinUtils.getApplicationContext().getBean(beanName, UI.class); return null; } /** * Try to match a ant url pattern in url mapping and return the UI bean name * @param request vaadin request * @return the bean name for request, null if none. */ protected String getBeanNameFromRequest(VaadinRequest request) { String beanName = null; String pathInfo = request.getPathInfo(); if (this.pathMatcher == null) this.pathMatcher = new AntPathMatcher(); for (String pattern : this.urlMap.keySet()) { if (log.isDebugEnabled()) log.debug("Matching pattern [" + pattern + "] over path info [" + pathInfo + "]"); if (this.pathMatcher.match(pattern, request.getPathInfo())) { beanName = this.urlMap.get(pattern); if (log.isDebugEnabled()) log.debug("Matching success. Using bean name [" + beanName + "]"); break; } } if (beanName == null) beanName = request.getPathInfo(); return beanName; } /** * Init th url map parsing {@link UiMapping} annotations * @param ctx ApplicationContext */ @Autowired public void init(ApplicationContext ctx) { Map<String, Object> uis = ctx.getBeansWithAnnotation(UiMapping.class); for (String name : uis.keySet()) { Object ui = uis.get(name); if (ui instanceof UI) { UiMapping ann = AnnotationUtils.findAnnotation(ui.getClass(), UiMapping.class); if (ann != null) { if (log.isDebugEnabled()) log.debug("Mapping UI [" + ui.getClass().getName() + "] to request path [" + ann.value() + "]"); this.urlMap.put(ann.value(), name); } } } } /** * Lookup UI class from application context. * @param request request */ @Override @SuppressWarnings("unchecked") public Class<?extends UI> getUiClass(VaadinRequest request) { ApplicationContext ctx = VaadinUtils.getApplicationContext(); String beanName = getBeanNameFromRequest(request); if (beanName != null && ctx.containsBean(beanName)) return (Class<? extends UI>) ctx.getType(beanName); return null; } }