com.pi4j.runtime.impl.DefaultRuntimeProperties Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pi4j-core Show documentation
Show all versions of pi4j-core Show documentation
Pi4J Java API & Runtime Library
The newest version!
package com.pi4j.runtime.impl;
/*-
* #%L
* **********************************************************************
* ORGANIZATION : Pi4J
* PROJECT : Pi4J :: LIBRARY :: Java Library (CORE)
* FILENAME : DefaultRuntimeProperties.java
*
* This file is part of the Pi4J project. More information about
* this project can be found here: https://pi4j.com/
* **********************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import com.pi4j.context.Context;
import com.pi4j.runtime.RuntimeProperties;
import com.pi4j.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
/**
* DefaultRuntimeProperties class.
*
* @author Robert Savage (http://www.savagehomeautomation.com)
* @version $Id: $Id
*/
public class DefaultRuntimeProperties implements RuntimeProperties {
/** Constant PI4J_PROPERTIES_FILE_NAME="pi4j.properties"
*/
public static String PI4J_PROPERTIES_FILE_NAME = "pi4j.properties";
protected Map properties = Collections.synchronizedMap(new HashMap<>());
private Logger logger = LoggerFactory.getLogger(this.getClass());
// static singleton instance
/**
* newInstance.
*
* @param context a {@link com.pi4j.context.Context} object.
* @return a {@link com.pi4j.runtime.RuntimeProperties} object.
*/
public static RuntimeProperties newInstance(Context context){
return new DefaultRuntimeProperties(context);
}
private DefaultRuntimeProperties(Context context){
// now lets load optional Pi4J.properties files from the file system
// first; load any default Pi4J properties defined in the Environment Variables
try{
// iterate the environment variables looking for prefixes matching "PI4J_"
var envars = System.getenv();
envars.keySet().stream().filter(key -> key.toUpperCase().startsWith("PI4J_")).forEach((key)->{
// sanitize keys by making them all lower case and replacing underscores with "." periods.
String k = key.substring(5).replace('_', '.').toLowerCase();
String v = envars.get(key);
put(k, v);
});
// use "pi4j." prefix filter to limit the environment variables that we care about
put(System.getenv(), "pi4j.");
}
catch (Exception e){
logger.error(e.getMessage(), e);
}
// second; load system-scoped Pi4J properties file
// /etc/pi4j/pi4j.properties
try {
Path appFile = Paths.get("/etc/pi4j", PI4J_PROPERTIES_FILE_NAME);
if (Files.exists(appFile)) {
Properties p = new Properties();
p.load(new FileInputStream(appFile.toFile()));
put(p);
}
}
catch (Exception e){
logger.error(e.getMessage(), e);
}
// third; load user-scoped Pi4J properties file
// ~/.pi4j.properties
try {
Path appFile = Paths.get(System.getProperty("user.home"), "." + PI4J_PROPERTIES_FILE_NAME);
if (Files.exists(appFile)) {
Properties p = new Properties();
p.load(new FileInputStream(appFile.toFile()));
put(p);
}
}
catch (Exception e){
logger.error(e.getMessage(), e);
}
// fourth; load an application-scoped Pi4J properties file
// {pwd}/pi4j.properties
try {
Path appFile = Paths.get(System.getProperty("user.dir"), PI4J_PROPERTIES_FILE_NAME);
if (Files.exists(appFile)) {
Properties p = new Properties();
p.load(new FileInputStream(appFile.toFile()));
put(p);
}
}
catch (Exception e){
logger.error(e.getMessage(), e);
}
// fifth; load any application-embedded resource Pi4J properties file
// {app}/{resources}/pi4j.properties
try {
URL resource = getClass().getClassLoader().getResource(PI4J_PROPERTIES_FILE_NAME);
if(resource != null) {
File resourceFile = new File(resource.getFile());
if (resourceFile != null && resourceFile.exists()) {
Properties p = new Properties();
p.load(new FileInputStream(resourceFile));
put(p);
}
}
}
catch (Exception e){
logger.error(e.getMessage(), e);
}
// finally; load any default properties defined in the System.properties
try{
// use "pi4j." prefix filter to limit the system properties that we care about
put(System.getProperties(), "pi4j.");
}
catch (Exception e){
logger.error(e.getMessage(), e);
}
// add all context pre-configured properties to the runtime properties cache
this.put(context.config().properties());
}
/**
* sanitizeKey.
*
* @param key a {@link java.lang.String} object.
* @return a {@link java.lang.String} object.
*/
protected String sanitizeKey(String key){
return key.trim().toLowerCase();
}
/** {@inheritDoc} */
@Override
public boolean has(String key) {
return properties.containsKey(sanitizeKey(key));
}
/** {@inheritDoc} */
@Override
public String get(String key) {
String k = sanitizeKey(key);
// first, attempt to get property for internal cache
if(properties.containsKey(k)){
return properties.get(k);
}
return null;
}
/** {@inheritDoc} */
@Override
public void put(String key, String value) {
properties.put(sanitizeKey(key), value);
}
/** {@inheritDoc} */
@Override
public void put(Properties properties) {
properties.forEach((key,value)->{
this.properties.put(sanitizeKey(key.toString()), value.toString());
});
}
/** {@inheritDoc} */
@Override
public void put(Map values) {
values.forEach((key,value)->{
this.properties.put(sanitizeKey(key), value);
});
}
/** {@inheritDoc} */
@Override
public void put(Map.Entry... value) {
for(Map.Entry e : value){
this.properties.put(sanitizeKey(e.getKey().toString()), e.getValue().toString());
}
}
/** {@inheritDoc} */
@Override
public Map all() {
return Collections.unmodifiableMap(this.properties);
}
/** {@inheritDoc} */
@Override
public int count() {
return this.properties.size();
}
/** {@inheritDoc} */
protected void put(Properties properties, String prefixFilter){
// convert java.util.Properties to a Map object
Map entries = properties.keySet().stream()
.collect(Collectors.toMap(k->k.toString(), key->properties.get(key).toString()));
put(entries, prefixFilter);
}
/** {@inheritDoc} */
protected void put(Map properties, String prefixFilter){
// if a filter was not provided, then load properties without a filter
if(StringUtil.isNullOrEmpty(prefixFilter)) {
put(properties);
return;
}
// sanitize the prefix filter and make sure it includes a "." character at the end
var prefix = (prefixFilter.endsWith(".")) ? prefixFilter : prefixFilter+".";
// iterate the properties object and assign any key with the prefix filter to this config
properties.keySet().stream().filter(key -> key.startsWith(prefix)).forEach((key)->{
put(key.substring(prefix.length()), properties.get(key));
});
}
}