001/* 002 * Copyright 2002-2015 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.servlet.config; 018 019import java.util.Arrays; 020import java.util.LinkedHashMap; 021import java.util.List; 022import java.util.Map; 023 024import org.w3c.dom.Element; 025 026import org.springframework.beans.factory.config.BeanDefinition; 027import org.springframework.beans.factory.xml.BeanDefinitionParser; 028import org.springframework.beans.factory.xml.ParserContext; 029import org.springframework.util.StringUtils; 030import org.springframework.util.xml.DomUtils; 031import org.springframework.web.cors.CorsConfiguration; 032 033/** 034 * {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses a 035 * {@code cors} element in order to set the CORS configuration in the various 036 * {AbstractHandlerMapping} beans created by {@link AnnotationDrivenBeanDefinitionParser}, 037 * {@link ResourcesBeanDefinitionParser} and {@link ViewControllerBeanDefinitionParser}. 038 * 039 * @author Sebastien Deleuze 040 * @since 4.2 041 */ 042public class CorsBeanDefinitionParser implements BeanDefinitionParser { 043 044 @Override 045 public BeanDefinition parse(Element element, ParserContext parserContext) { 046 047 Map<String, CorsConfiguration> corsConfigurations = new LinkedHashMap<String, CorsConfiguration>(); 048 List<Element> mappings = DomUtils.getChildElementsByTagName(element, "mapping"); 049 050 if (mappings.isEmpty()) { 051 CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues(); 052 corsConfigurations.put("/**", config); 053 } 054 else { 055 for (Element mapping : mappings) { 056 CorsConfiguration config = new CorsConfiguration(); 057 if (mapping.hasAttribute("allowed-origins")) { 058 String[] allowedOrigins = StringUtils.tokenizeToStringArray(mapping.getAttribute("allowed-origins"), ","); 059 config.setAllowedOrigins(Arrays.asList(allowedOrigins)); 060 } 061 if (mapping.hasAttribute("allowed-methods")) { 062 String[] allowedMethods = StringUtils.tokenizeToStringArray(mapping.getAttribute("allowed-methods"), ","); 063 config.setAllowedMethods(Arrays.asList(allowedMethods)); 064 } 065 if (mapping.hasAttribute("allowed-headers")) { 066 String[] allowedHeaders = StringUtils.tokenizeToStringArray(mapping.getAttribute("allowed-headers"), ","); 067 config.setAllowedHeaders(Arrays.asList(allowedHeaders)); 068 } 069 if (mapping.hasAttribute("exposed-headers")) { 070 String[] exposedHeaders = StringUtils.tokenizeToStringArray(mapping.getAttribute("exposed-headers"), ","); 071 config.setExposedHeaders(Arrays.asList(exposedHeaders)); 072 } 073 if (mapping.hasAttribute("allow-credentials")) { 074 config.setAllowCredentials(Boolean.parseBoolean(mapping.getAttribute("allow-credentials"))); 075 } 076 if (mapping.hasAttribute("max-age")) { 077 config.setMaxAge(Long.parseLong(mapping.getAttribute("max-age"))); 078 } 079 corsConfigurations.put(mapping.getAttribute("path"), config.applyPermitDefaultValues()); 080 } 081 } 082 083 MvcNamespaceUtils.registerCorsConfigurations(corsConfigurations, parserContext, parserContext.extractSource(element)); 084 return null; 085 } 086 087}