001/* 002 * Copyright 2012-2018 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 * http://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.boot.context.properties.source; 018 019import java.util.Collections; 020import java.util.Iterator; 021import java.util.LinkedHashMap; 022import java.util.Map; 023import java.util.stream.Stream; 024 025import org.springframework.core.env.MapPropertySource; 026import org.springframework.util.Assert; 027 028/** 029 * An {@link ConfigurationPropertySource} backed by a {@link Map} and using standard name 030 * mapping rules. 031 * 032 * @author Phillip Webb 033 * @author Madhura Bhave 034 */ 035public class MapConfigurationPropertySource 036 implements IterableConfigurationPropertySource { 037 038 private final Map<String, Object> source; 039 040 private final IterableConfigurationPropertySource delegate; 041 042 /** 043 * Create a new empty {@link MapConfigurationPropertySource} instance. 044 */ 045 public MapConfigurationPropertySource() { 046 this(Collections.emptyMap()); 047 } 048 049 /** 050 * Create a new {@link MapConfigurationPropertySource} instance with entries copies 051 * from the specified map. 052 * @param map the source map 053 */ 054 public MapConfigurationPropertySource(Map<?, ?> map) { 055 this.source = new LinkedHashMap<>(); 056 this.delegate = new SpringIterableConfigurationPropertySource( 057 new MapPropertySource("source", this.source), 058 DefaultPropertyMapper.INSTANCE); 059 putAll(map); 060 } 061 062 /** 063 * Add all entries from the specified map. 064 * @param map the source map 065 */ 066 public void putAll(Map<?, ?> map) { 067 Assert.notNull(map, "Map must not be null"); 068 assertNotReadOnlySystemAttributesMap(map); 069 map.forEach(this::put); 070 } 071 072 /** 073 * Add an individual entry. 074 * @param name the name 075 * @param value the value 076 */ 077 public void put(Object name, Object value) { 078 this.source.put((name != null) ? name.toString() : null, value); 079 } 080 081 @Override 082 public Object getUnderlyingSource() { 083 return this.source; 084 } 085 086 @Override 087 public ConfigurationProperty getConfigurationProperty( 088 ConfigurationPropertyName name) { 089 return this.delegate.getConfigurationProperty(name); 090 } 091 092 @Override 093 public Iterator<ConfigurationPropertyName> iterator() { 094 return this.delegate.iterator(); 095 } 096 097 @Override 098 public Stream<ConfigurationPropertyName> stream() { 099 return this.delegate.stream(); 100 } 101 102 private void assertNotReadOnlySystemAttributesMap(Map<?, ?> map) { 103 try { 104 map.size(); 105 } 106 catch (UnsupportedOperationException ex) { 107 throw new IllegalArgumentException( 108 "Security restricted maps are not supported", ex); 109 } 110 } 111 112}