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