001/*
002 * Copyright 2002-2016 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.core.io.support;
018
019import java.io.IOException;
020import java.io.InputStream;
021import java.io.Reader;
022import java.net.URL;
023import java.net.URLConnection;
024import java.util.Enumeration;
025import java.util.Properties;
026
027import org.springframework.core.io.Resource;
028import org.springframework.util.Assert;
029import org.springframework.util.ClassUtils;
030import org.springframework.util.DefaultPropertiesPersister;
031import org.springframework.util.PropertiesPersister;
032import org.springframework.util.ResourceUtils;
033
034/**
035 * Convenient utility methods for loading of {@code java.util.Properties},
036 * performing standard handling of input streams.
037 *
038 * <p>For more configurable properties loading, including the option of a
039 * customized encoding, consider using the PropertiesLoaderSupport class.
040 *
041 * @author Juergen Hoeller
042 * @author Rob Harrop
043 * @since 2.0
044 * @see PropertiesLoaderSupport
045 */
046public abstract class PropertiesLoaderUtils {
047
048        private static final String XML_FILE_EXTENSION = ".xml";
049
050
051        /**
052         * Load properties from the given EncodedResource,
053         * potentially defining a specific encoding for the properties file.
054         * @see #fillProperties(java.util.Properties, EncodedResource)
055         */
056        public static Properties loadProperties(EncodedResource resource) throws IOException {
057                Properties props = new Properties();
058                fillProperties(props, resource);
059                return props;
060        }
061
062        /**
063         * Fill the given properties from the given EncodedResource,
064         * potentially defining a specific encoding for the properties file.
065         * @param props the Properties instance to load into
066         * @param resource the resource to load from
067         * @throws IOException in case of I/O errors
068         */
069        public static void fillProperties(Properties props, EncodedResource resource)
070                        throws IOException {
071
072                fillProperties(props, resource, new DefaultPropertiesPersister());
073        }
074
075        /**
076         * Actually load properties from the given EncodedResource into the given Properties instance.
077         * @param props the Properties instance to load into
078         * @param resource the resource to load from
079         * @param persister the PropertiesPersister to use
080         * @throws IOException in case of I/O errors
081         */
082        static void fillProperties(Properties props, EncodedResource resource, PropertiesPersister persister)
083                        throws IOException {
084
085                InputStream stream = null;
086                Reader reader = null;
087                try {
088                        String filename = resource.getResource().getFilename();
089                        if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
090                                stream = resource.getInputStream();
091                                persister.loadFromXml(props, stream);
092                        }
093                        else if (resource.requiresReader()) {
094                                reader = resource.getReader();
095                                persister.load(props, reader);
096                        }
097                        else {
098                                stream = resource.getInputStream();
099                                persister.load(props, stream);
100                        }
101                }
102                finally {
103                        if (stream != null) {
104                                stream.close();
105                        }
106                        if (reader != null) {
107                                reader.close();
108                        }
109                }
110        }
111
112        /**
113         * Load properties from the given resource (in ISO-8859-1 encoding).
114         * @param resource the resource to load from
115         * @return the populated Properties instance
116         * @throws IOException if loading failed
117         * @see #fillProperties(java.util.Properties, Resource)
118         */
119        public static Properties loadProperties(Resource resource) throws IOException {
120                Properties props = new Properties();
121                fillProperties(props, resource);
122                return props;
123        }
124
125        /**
126         * Fill the given properties from the given resource (in ISO-8859-1 encoding).
127         * @param props the Properties instance to fill
128         * @param resource the resource to load from
129         * @throws IOException if loading failed
130         */
131        public static void fillProperties(Properties props, Resource resource) throws IOException {
132                InputStream is = resource.getInputStream();
133                try {
134                        String filename = resource.getFilename();
135                        if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
136                                props.loadFromXML(is);
137                        }
138                        else {
139                                props.load(is);
140                        }
141                }
142                finally {
143                        is.close();
144                }
145        }
146
147        /**
148         * Load all properties from the specified class path resource
149         * (in ISO-8859-1 encoding), using the default class loader.
150         * <p>Merges properties if more than one resource of the same name
151         * found in the class path.
152         * @param resourceName the name of the class path resource
153         * @return the populated Properties instance
154         * @throws IOException if loading failed
155         */
156        public static Properties loadAllProperties(String resourceName) throws IOException {
157                return loadAllProperties(resourceName, null);
158        }
159
160        /**
161         * Load all properties from the specified class path resource
162         * (in ISO-8859-1 encoding), using the given class loader.
163         * <p>Merges properties if more than one resource of the same name
164         * found in the class path.
165         * @param resourceName the name of the class path resource
166         * @param classLoader the ClassLoader to use for loading
167         * (or {@code null} to use the default class loader)
168         * @return the populated Properties instance
169         * @throws IOException if loading failed
170         */
171        public static Properties loadAllProperties(String resourceName, ClassLoader classLoader) throws IOException {
172                Assert.notNull(resourceName, "Resource name must not be null");
173                ClassLoader classLoaderToUse = classLoader;
174                if (classLoaderToUse == null) {
175                        classLoaderToUse = ClassUtils.getDefaultClassLoader();
176                }
177                Enumeration<URL> urls = (classLoaderToUse != null ? classLoaderToUse.getResources(resourceName) :
178                                ClassLoader.getSystemResources(resourceName));
179                Properties props = new Properties();
180                while (urls.hasMoreElements()) {
181                        URL url = urls.nextElement();
182                        URLConnection con = url.openConnection();
183                        ResourceUtils.useCachesIfNecessary(con);
184                        InputStream is = con.getInputStream();
185                        try {
186                                if (resourceName.endsWith(XML_FILE_EXTENSION)) {
187                                        props.loadFromXML(is);
188                                }
189                                else {
190                                        props.load(is);
191                                }
192                        }
193                        finally {
194                                is.close();
195                        }
196                }
197                return props;
198        }
199
200}