001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2017–2019 microBean. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 014 * implied. See the License for the specific language governing 015 * permissions and limitations under the License. 016 */ 017package org.microbean.configuration.spi; 018 019import java.io.BufferedInputStream; 020import java.io.InputStream; 021import java.io.IOException; 022 023import java.net.URL; 024 025import java.util.Map; 026import java.util.Properties; 027 028import java.util.concurrent.ConcurrentHashMap; 029 030import java.util.function.Function; 031 032import org.microbean.configuration.Configurations; 033 034import org.microbean.configuration.api.ConfigurationException; 035 036import org.microbean.configuration.spi.AbstractResourceLoadingConfiguration.Resource; 037 038import org.microbean.configuration.spi.converter.StringToMapStringStringConverter; 039 040public class PropertiesLoader implements Function<Map<? extends String, ? extends String>, Resource<? extends Properties>> { 041 042 private final ClassLoader resourceLoader; 043 044 protected final String name; 045 046 public PropertiesLoader(final String name) { 047 this(Thread.currentThread().getContextClassLoader(), name); 048 } 049 050 public PropertiesLoader(final ClassLoader resourceLoader, final String name) { 051 super(); 052 this.name = name; 053 this.resourceLoader = resourceLoader; 054 } 055 056 @Override 057 public Resource<? extends Properties> apply(final Map<? extends String, ? extends String> requestedConfigurationCoordinates) { 058 Resource<? extends Properties> returnValue = null; 059 if (this.name != null) { 060 ClassLoader resourceLoader = this.resourceLoader; 061 if (resourceLoader == null) { 062 resourceLoader = Thread.currentThread().getContextClassLoader(); 063 if (resourceLoader == null) { 064 resourceLoader = this.getClass().getClassLoader(); 065 } 066 } 067 assert resourceLoader != null; 068 final URL resource = resourceLoader.getResource(this.computeResourceName(requestedConfigurationCoordinates)); 069 if (resource != null) { 070 Properties properties = null; 071 try (final InputStream inputStream = new BufferedInputStream(resource.openStream())) { 072 if (inputStream != null) { 073 properties = new Properties(); 074 properties.load(inputStream); 075 } 076 } catch (final IOException ioException) { 077 throw new ConfigurationException(ioException.getMessage(), ioException); 078 } 079 returnValue = new Resource<>(properties, new StringToMapStringStringConverter().convert(properties.getProperty(Configurations.CONFIGURATION_COORDINATES))); 080 } 081 } 082 return returnValue; 083 } 084 085 protected String computeResourceName(final Map<? extends String, ? extends String> requestedConfigurationCoordinates) { 086 return this.name; 087 } 088 089}