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.info;
018
019import java.time.Instant;
020import java.util.Iterator;
021import java.util.Map;
022import java.util.Properties;
023
024import org.springframework.core.env.PropertiesPropertySource;
025import org.springframework.core.env.PropertySource;
026import org.springframework.util.Assert;
027
028/**
029 * Base class for components exposing unstructured data with dedicated methods for well
030 * known keys.
031 *
032 * @author Stephane Nicoll
033 * @since 1.4.0
034 */
035public class InfoProperties implements Iterable<InfoProperties.Entry> {
036
037        private final Properties entries;
038
039        /**
040         * Create an instance with the specified entries.
041         * @param entries the information to expose
042         */
043        public InfoProperties(Properties entries) {
044                Assert.notNull(entries, "Entries must not be null");
045                this.entries = copy(entries);
046        }
047
048        /**
049         * Return the value of the specified property or {@code null}.
050         * @param key the key of the property
051         * @return the property value
052         */
053        public String get(String key) {
054                return this.entries.getProperty(key);
055        }
056
057        /**
058         * Return the value of the specified property as an {@link Instant} or {@code null} if
059         * the value is not a valid {@link Long} representation of an epoch time.
060         * @param key the key of the property
061         * @return the property value
062         */
063        public Instant getInstant(String key) {
064                String s = get(key);
065                if (s != null) {
066                        try {
067                                return Instant.ofEpochMilli(Long.parseLong(s));
068                        }
069                        catch (NumberFormatException ex) {
070                                // Not valid epoch time
071                        }
072                }
073                return null;
074        }
075
076        @Override
077        public Iterator<Entry> iterator() {
078                return new PropertiesIterator(this.entries);
079        }
080
081        /**
082         * Return a {@link PropertySource} of this instance.
083         * @return a {@link PropertySource}
084         */
085        public PropertySource<?> toPropertySource() {
086                return new PropertiesPropertySource(getClass().getSimpleName(),
087                                copy(this.entries));
088        }
089
090        private Properties copy(Properties properties) {
091                Properties copy = new Properties();
092                copy.putAll(properties);
093                return copy;
094        }
095
096        private final class PropertiesIterator implements Iterator<Entry> {
097
098                private final Iterator<Map.Entry<Object, Object>> iterator;
099
100                private PropertiesIterator(Properties properties) {
101                        this.iterator = properties.entrySet().iterator();
102                }
103
104                @Override
105                public boolean hasNext() {
106                        return this.iterator.hasNext();
107                }
108
109                @Override
110                public Entry next() {
111                        Map.Entry<Object, Object> entry = this.iterator.next();
112                        return new Entry((String) entry.getKey(), (String) entry.getValue());
113                }
114
115                @Override
116                public void remove() {
117                        throw new UnsupportedOperationException("InfoProperties are immutable.");
118                }
119
120        }
121
122        /**
123         * Property entry.
124         */
125        public final class Entry {
126
127                private final String key;
128
129                private final String value;
130
131                private Entry(String key, String value) {
132                        this.key = key;
133                        this.value = value;
134                }
135
136                public String getKey() {
137                        return this.key;
138                }
139
140                public String getValue() {
141                        return this.value;
142                }
143
144        }
145
146}