001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2017-2018 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.Serializable; 020 021import java.util.Collections; 022import java.util.Map; 023import java.util.HashSet; 024import java.util.Properties; 025import java.util.Set; 026 027import org.microbean.configuration.api.ConfigurationValue; 028 029/** 030 * An {@link AbstractConfiguration} that houses {@linkplain 031 * System#getProperties() System properties} and hence, by definition, 032 * minimally {@linkplain ConfigurationValue#specificity() specific} 033 * {@link ConfigurationValue}s representing them. 034 * 035 * @author <a href="https://about.me/lairdnelson" 036 * target="_parent">Laird Nelson</a> 037 */ 038public final class SystemPropertiesConfiguration extends AbstractConfiguration implements Ranked, Serializable { 039 040 041 /* 042 * Static fields. 043 */ 044 045 046 /** 047 * The version of this class for {@linkplain Serializable 048 * serialization} purposes. 049 */ 050 private static final long serialVersionUID = 1L; 051 052 /** 053 * A {@link Set} of {@linkplain System#getProperties() System 054 * properties} that the Java Language Specification guarantees will 055 * exist on all platforms. 056 * 057 * <p>This field is never {@code null}.</p> 058 * 059 * @see System#getProperties() 060 */ 061 private static final Set<String> systemPropertiesGuaranteedToExist = new HashSet<>(29, 1F); 062 063 static { 064 // See https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getProperties-- 065 systemPropertiesGuaranteedToExist.add("java.version"); 066 systemPropertiesGuaranteedToExist.add("java.vendor"); // Java Runtime Environment vendor 067 systemPropertiesGuaranteedToExist.add("java.vendor.url"); // Java vendor URL 068 systemPropertiesGuaranteedToExist.add("java.home"); // Java installation directory 069 systemPropertiesGuaranteedToExist.add("java.vm.specification.version"); // Java Virtual Machine specification version 070 systemPropertiesGuaranteedToExist.add("java.vm.specification.vendor"); // Java Virtual Machine specification vendor 071 systemPropertiesGuaranteedToExist.add("java.vm.specification.name"); // Java Virtual Machine specification name 072 systemPropertiesGuaranteedToExist.add("java.vm.version"); // Java Virtual Machine implementation version 073 systemPropertiesGuaranteedToExist.add("java.vm.vendor"); // Java Virtual Machine implementation vendor 074 systemPropertiesGuaranteedToExist.add("java.vm.name"); // Java Virtual Machine implementation name 075 systemPropertiesGuaranteedToExist.add("java.specification.version"); // Java Runtime Environment specification version 076 systemPropertiesGuaranteedToExist.add("java.specification.vendor"); // Java Runtime Environment specification vendor 077 systemPropertiesGuaranteedToExist.add("java.specification.name"); // Java Runtime Environment specification name 078 systemPropertiesGuaranteedToExist.add("java.class.version"); // Java class format version number 079 systemPropertiesGuaranteedToExist.add("java.class.path"); // Java class path 080 systemPropertiesGuaranteedToExist.add("java.library.path"); // List of paths to search when loading libraries 081 systemPropertiesGuaranteedToExist.add("java.io.tmpdir"); // Default temp file path 082 systemPropertiesGuaranteedToExist.add("java.compiler"); // Name of JIT compiler to use 083 systemPropertiesGuaranteedToExist.add("java.ext.dirs"); // Path of extension directory or directories 084 systemPropertiesGuaranteedToExist.add("os.name"); // Operating system name 085 systemPropertiesGuaranteedToExist.add("os.arch"); // Operating system architecture 086 systemPropertiesGuaranteedToExist.add("os.version"); // Operating system version 087 systemPropertiesGuaranteedToExist.add("file.separator"); // File separator ("/" on UNIX) 088 systemPropertiesGuaranteedToExist.add("path.separator"); // Path separator (":" on UNIX) 089 systemPropertiesGuaranteedToExist.add("line.separator"); // Line separator ("\n" on UNIX) 090 systemPropertiesGuaranteedToExist.add("user.name"); // User's account name 091 systemPropertiesGuaranteedToExist.add("user.home"); // User's home directory 092 systemPropertiesGuaranteedToExist.add("user.dir"); // User's current working directory 093 } 094 095 096 /* 097 * Constructors. 098 */ 099 100 101 /** 102 * Creates a new {@link SystemPropertiesConfiguration}. 103 */ 104 public SystemPropertiesConfiguration() { 105 super(); 106 } 107 108 109 /* 110 * Instance methods. 111 */ 112 113 114 @Override 115 public final int getRank() { 116 return 400; 117 } 118 119 /** 120 * Returns a {@link ConfigurationValue} representing the {@linkplain 121 * System#getProperty(String, String) System property} identified by 122 * the supplied {@code name}, or {@code null}. 123 * 124 * <p>The {@link ConfigurationValue} returned will be marked as 125 * {@linkplain ConfigurationValue#isAuthoritative() authoritative} 126 * if it is one of the {@linkplain System#getProperties() System 127 * properties guaranteed by the Java Language Specification to exist 128 * on every available Java platform}.</p> 129 * 130 * @param coordinates the configuration coordinates in effect for 131 * the current request; may be {@code null} 132 * 133 * @param name the name of the configuration property for which to 134 * return a {@link ConfigurationValue}; may be {@code null} 135 * 136 * @return a {@link ConfigurationValue}, or {@code null} 137 */ 138 @Override 139 public final ConfigurationValue getValue(final Map<String, String> coordinates, final String name) { 140 ConfigurationValue returnValue = null; 141 if (name != null) { 142 final String propertyValue = System.getProperty(name); 143 if (propertyValue != null) { 144 returnValue = new ConfigurationValue(this, null /* deliberately null coordinates */, name, propertyValue, this.isAuthoritative(name)); 145 } 146 } 147 return returnValue; 148 } 149 150 /** 151 * Returns a {@link Set} of the names of all {@link 152 * ConfigurationValue}s that might be returned by this {@link 153 * Configuration}. 154 * 155 * <p>This method never returns {@code null}.</p> 156 * 157 * <p>Overrides of this method must not return {@code null}.</p> 158 * 159 * <p>This implementation returns an immutable representation of the 160 * equivalent of {@link System#getProperties() 161 * System.getProperties().stringPropertyNames()}.</p> 162 * 163 * @return a non-{@code null} {@link Set} of names 164 */ 165 @Override 166 public final Set<String> getNames() { 167 final Properties properties = System.getProperties(); 168 assert properties != null; // by contract 169 assert !properties.isEmpty(); // by contract 170 final Set<String> returnValue = Collections.unmodifiableSet(properties.stringPropertyNames()); 171 return returnValue; 172 } 173 174 /** 175 * Returns {@code true} if the supplied {@code name} is not {@code 176 * null} and is one of the {@linkplain System#getProperties() System 177 * properties guaranteed by the Java Language Specification to exist 178 * on every available Java platform}. 179 * 180 * @param name the name of a {@linkplain System#getProperty(String, 181 * String) System property}; may be {@code null} in which case 182 * {@code false} will be returned 183 * 184 * @return {@code true} if any value that this {@link 185 * SystemPropertiesConfiguration} produces for the supplied {@code 186 * name} is to be regarded as the authoritative value; {@code false} 187 * otherwise 188 */ 189 protected boolean isAuthoritative(final String name) { 190 return name != null && systemPropertiesGuaranteedToExist.contains(name); 191 } 192 193 @Override 194 public final int hashCode() { 195 return System.getProperties().hashCode(); 196 } 197 198 @Override 199 public final boolean equals(final Object other) { 200 return other instanceof SystemPropertiesConfiguration; 201 } 202 203 @Override 204 public String toString() { 205 return System.getProperties().toString(); 206 } 207 208}