8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The contents of this file are subject to the terms
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * of the Common Development and Distribution License
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * (the License). You may not use this file except in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * compliance with the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You can obtain a copy of the License at
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * permission and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Header Notice in each file and include the License file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If applicable, add the following below the CDDL Header,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * with the fields enclosed by brackets [] replaced by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * your own identifying information:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts * Portions Copyrighted 2010-2016 ForgeRock AS.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Maddenimport static org.forgerock.openam.utils.CollectionUtils.asSet;
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Maddenimport com.sun.identity.common.configuration.ConfigurationListener;
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Maddenimport com.sun.identity.common.configuration.ConfigurationObserver;
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Maddenimport com.sun.identity.common.configuration.ServerConfiguration;
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Maddenimport com.sun.identity.security.AdminTokenAction;
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Maddenimport java.util.concurrent.atomic.AtomicReference;
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpottsimport org.forgerock.guava.common.base.Predicate;
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Maddenimport org.forgerock.guava.common.collect.ImmutableMap;
69920e8c9c3fc2f914a89ad905988dbbe0a2c13cNeil Maddenimport org.forgerock.openam.cts.api.CoreTokenConstants;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This class provides functionality that allows single-point-of-access to all
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * related system properties.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The system properties can be set in couple of ways: programmatically by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * calling the <code>initializeProperties</code> method, or can be statically
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * loaded at startup from a file named:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>AMConfig.[class,properties]</code>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Setting the properties through the API takes precedence and will replace the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * properties loaded via file. For statically loading the properties via a file,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * this class tries to first find a class, <code>AMConfig.class</code>, and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * then a file, <code>AMConfig.properties</code> in the CLASSPATH accessible
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * to this code. The <code>AMConfig.class</code> takes precedence over the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * flat file <code>AMConfig.properties</code>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If multiple servers are running, each may have their own configuration file.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The naming convention for such scenarios is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>AMConfig-<serverName></code>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @supported.all.api
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Runtime flag to be set, in order to override the path of the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * configuration file.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String CONFIG_PATH = "com.iplanet.services.configpath";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Default name of the configuration file.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String CONFIG_FILE_NAME = "serverconfig.xml";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * New configuration file extension
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String PROPERTIES = "properties";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String NEWCONFDIR = "NEW_CONF_DIR";
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private static final String SERVER_NAME_PROPERTY = "server.name";
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private static final String CONFIG_NAME_PROPERTY = "amconfig";
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private static final String AMCONFIG_FILE_NAME = "AMConfig";
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden /** Regular expression pattern for a sequence of 1 or more white space characters. */
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private static final String WHITESPACE = "\\s+";
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private static final Map<String, AttributeStruct> ATTRIBUTE_MAP = initAttributeMapping();
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden * Maps from tags to the system properties that they should be replaced with. System property values containing
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden * these tags will be replaced with the actual values of these properties by {@link #get(String)}.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private static final Map<String, String> TAG_SWAP_PROPERTIES = ImmutableMap.<String, String>builder()
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden .put("%SERVER_URI%", Constants.AM_SERVICES_DEPLOYMENT_DESCRIPTOR)
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden .put("%SERVER_PROTO%", Constants.AM_SERVER_PROTOCOL)
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden .put("%SESSION_ROOT_SUFFIX%", CoreTokenConstants.SYS_PROPERTY_SESSION_HA_REPOSITORY_ROOT_SUFFIX)
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden .put("%SESSION_STORE_TYPE%", CoreTokenConstants.SYS_PROPERTY_SESSION_HA_REPOSITORY_TYPE)
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private static final boolean SITEMONITOR_DISABLED;
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden * Reference to the current properties map and tagswap values.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private static final AtomicReference<PropertiesHolder> propertiesHolderRef =
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private static String initSecondaryError = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Initialization to load the properties file for config information before
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * anything else starts.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Load properties from file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String serverName = System.getProperty(SERVER_NAME_PROPERTY);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden String configName = System.getProperty(CONFIG_NAME_PROPERTY, AMCONFIG_FILE_NAME);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden PropertiesHolder props = propertiesHolderRef.get();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Get the location of the new configuration file in case
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // of single war deployment
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden String newConfigFileLoc = props.getProperty(Constants.AM_NEW_CONFIGFILE_PATH);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden if (!StringUtils.isEmpty(newConfigFileLoc) && !NEWCONFDIR.equals(newConfigFileLoc)) {
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden String hostName = InetAddress.getLocalHost().getHostName().toLowerCase();
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden String serverURI = props.getProperty(Constants.AM_SERVICES_DEPLOYMENT_DESCRIPTOR).replace('/', '_')
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden String fileName = newConfigFileLoc + "/" + AMCONFIG_FILE_NAME + serverURI + hostName +
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden props.getProperty(Constants.AM_SERVER_PORT) + "." + PROPERTIES;
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden props = loadProperties(props, newConfigFileLoc + "/" + AMCONFIG_FILE_NAME + "." +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Can't print the message to debug due to dependency
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Save it as a String and provide when requested.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden SITEMONITOR_DISABLED = Boolean.parseBoolean(getProp(Constants.SITEMONITOR_DISABLED, "false"));
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private static PropertiesHolder loadProperties(PropertiesHolder props, String file) throws IOException {
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden try (FileInputStream fis = new FileInputStream(file)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Helper function to handle associated exceptions during initialization of
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * properties using external properties file in a single war deployment.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Save it as a String and provide when requested.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This method lets you query for a system property whose value is same as
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>String</code> key. The method first tries to read the property
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * from java.lang.System followed by a lookup in the config file.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param key
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * type <code>String</code>, the key whose value one is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * looking for.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return the value if the key exists; otherwise returns <code>null</code>
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden // look up values in SMS services only if in server mode.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden answer = PropertiesFinder.getProperty(key, ast);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden final Map<String, String> tagswapValues = propertiesHolderRef.get().tagSwapValues;
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden if (answer != null && tagswapValues != null && answer.indexOf(TAG_START) != -1) {
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden for (Map.Entry<String, String> tagSwapEntry : tagswapValues.entrySet()) {
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden answer = answer.replaceAll("/%SERVER_URI%", val);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden answer = answer.replaceAll("%SERVER_URI%", lessSlash);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden answer = answer.replaceAll("%ROOT_SUFFIX%", SMSEntry.getAMSdkBaseDN());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static String getProp(String key, String def) {
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden answer = propertiesHolderRef.get().getProperty(key);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This method lets you query for a system property whose value is same as
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>String</code> key.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param key the key whose value one is looking for.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param def the default value if the key does not exist.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return the value if the key exists; otherwise returns default value.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static String get(String key, String def) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns the property value as a boolean
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param key the key whose value one is looking for.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return the boolean value if the key exists; otherwise returns false
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static boolean getAsBoolean(String key) {
751ffbacd21180fbc0849885f30c91425fcee44ajeff.schenk * Returns the property value as a boolean
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden * @param key the property name.
751ffbacd21180fbc0849885f30c91425fcee44ajeff.schenk * @param defaultValue value if key is not found.
ca66273b61a8889f097081b01b6ff9a5f5801064Peter Major * @return the boolean value if the key exists; otherwise the default value
751ffbacd21180fbc0849885f30c91425fcee44ajeff.schenk public static boolean getAsBoolean(String key, boolean defaultValue) {
537857b204a4425e0ea257b0413a02c5c7c5e266Robert Wapshott * @param key The System Property key to lookup.
537857b204a4425e0ea257b0413a02c5c7c5e266Robert Wapshott * @param defaultValue If the property was not set, or could not be parsed to an int.
537857b204a4425e0ea257b0413a02c5c7c5e266Robert Wapshott * @return Either the defaultValue, or the numeric value assigned to the System Property.
537857b204a4425e0ea257b0413a02c5c7c5e266Robert Wapshott public static int getAsInt(String key, int defaultValue) {
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell * @param key The System Property key to lookup.
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell * @param defaultValue If the property was not set, or could not be parsed to a long.
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell * @return Either the defaultValue, or the numeric value assigned to the System Property.
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell public static long getAsLong(String key, long defaultValue) {
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * Parses a system property as a set of strings by splitting the value on the given delimiter expression.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * @param key The System Property key to lookup.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * @param delimiterRegex The regular expression to use to split the value into elements in the set.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * @param defaultValue The default set to return if the property does not exist.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * @return the value of the property parsed as a set of strings.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden public static Set<String> getAsSet(String key, String delimiterRegex, Set<String> defaultValue) {
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * Parses a system property as a set of strings by splitting the value on the given delimiter expression.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * @param key The System Property key to lookup.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * @param delimiterRegex The regular expression to use to split the value into elements in the set.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * @return the value of the property parsed as a set of strings or an empty set if no match is found.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden public static Set<String> getAsSet(String key, String delimiterRegex) {
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden return getAsSet(key, delimiterRegex, Collections.<String>emptySet());
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * Parses a system property as a set of strings by splitting the value on white space characters.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * @param key The System Property key to lookup.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden * @return the value of the property parsed as a set of strings or an empty set if no match is found.
2cdbc4fc62ed8b9c2c8ef660adc4fe0188b65407Neil Madden public static Set<String> getAsSet(String key) {
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden * Returns all the properties defined and their values. This is a defensive copy of the properties and so updates
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden * to the returned object will not be reflected in the actual properties used by OpenAM.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden * @return Properties object with a copy of all the key value pairs.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden properties.putAll(propertiesHolderRef.get().properties);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This method lets you get all the properties defined and their values. The
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * method first tries to load the properties from java.lang.System followed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * by a lookup in the config file.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return Properties object with all the key value pairs.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden properties.putAll(propertiesHolderRef.get().properties);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden // Iterate over the System Properties & add them in result obj
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This method lets you query for all the platform properties defined and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * their values. Returns a Properties object with all the key value pairs.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @deprecated use <code>getAll()</code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return the platform properties
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Initializes properties bundle from the <code>file<code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param file type <code>String</code>, file name for the resource bundle
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception MissingResourceException
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden public static void initializeProperties(String file) throws MissingResourceException {
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden ResourceBundle bundle = ResourceBundle.getBundle(file);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden // Copy the properties to props
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden public static void initializeProperties(Properties properties) {
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * Initializes the properties to be used by OpenAM. Ideally this
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * must be called first before any other method is called within OpenAM.
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * This method provides a programmatic way to set the properties, and will
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * override similar properties if loaded for a properties file.
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * @param properties properties for OpenAM
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param reset <code>true</code> to reset existing properties.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden public static void initializeProperties(Properties properties, boolean reset) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster initializeProperties(properties, reset, false);
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * Initializes the properties to be used by OpenAM. Ideally this
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * must be called first before any other method is called within OpenAM.
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * This method provides a programmatic way to set the properties, and will
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * override similar properties if loaded for a properties file.
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * @param properties properties for OpenAM.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param reset <code>true</code> to reset existing properties.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param withDefaults <code>true</code> to include default properties.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden public static void initializeProperties(Properties properties, boolean reset, boolean withDefaults) {
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden SSOToken appToken = AccessController.doPrivileged(AdminTokenAction.getInstance());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster defaultProp = ServerConfiguration.getDefaults(appToken);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden newProps = new PropertiesHolder(Maps.fromProperties(combined));
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden } while (!propertiesHolderRef.compareAndSet(oldProps, newProps));
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * Initializes a property to be used by OpenAM. Ideally this
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * must be called first before any other method is called within OpenAM.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This method provides a programmatic way to set a specific property, and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * will override similar property if loaded for a properties file.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param propertyName property name.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param propertyValue property value.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden public static void initializeProperties(String propertyName, String propertyValue) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns a counter for last modification. The counter is incremented if
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the properties are changed by calling the following method
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * <code>initializeProperties</code>. This is a convenience method for
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * applications to track changes to OpenAM properties.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return counter of the last modification
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns error messages during initialization, else <code>null</code>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return error messages during initialization
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static String getInitializationError() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns error messages during initialization using the single war
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * deployment, else <code>null</code>.
8d3140b524c0e28c0a49dc7c7d481123ef3cfe11Chris Lee * @return error messages during initialization of OpenAM as single war
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static String getSecondaryInitializationError() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Sets the server instance name of which properties are retrieved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * to initialized this object.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param name Server instance name.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static void setServerInstanceName(String name) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns the server instance name of which properties are retrieved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * to initialized this object.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return Server instance name.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns <code>true</code> if instance is running in server mode.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return <code>true</code> if instance is running in server mode.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns the property name to service attribute schema name mapping.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return Property name to service attribute schema name mapping.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private static Map<String, AttributeStruct> initAttributeMapping() {
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden final Map<String, AttributeStruct> attributeMapping = new HashMap<>();
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden ResourceBundle rb = ResourceBundle.getBundle("serverAttributeMap");
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden attributeMapping.put(propertyName, new AttributeStruct(rb.getString(propertyName)));
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden // No Resource Bundle Found, Continue.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden // Could be in Test Mode.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden return Collections.unmodifiableMap(attributeMapping);
69920e8c9c3fc2f914a89ad905988dbbe0a2c13cNeil Madden * Lazy initialisation holder idiom for server mode flag as this is read frequently but never changes.
69920e8c9c3fc2f914a89ad905988dbbe0a2c13cNeil Madden // use getProp and not get method to avoid infinite loop
69920e8c9c3fc2f914a89ad905988dbbe0a2c13cNeil Madden private static final boolean isServerMode = Boolean.parseBoolean(getProp(Constants.SERVER_MODE, "false"));
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts * A singleton enum for the configuration listeners, which will be lazily initialized on first use. The code
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts * here cannot be added to the {@code SystemProperties} class initialization as it would create a cyclic
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts * dependency on the static initialization of {@code ConfigurationObserver}.
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts private final Map<String, ServicePropertiesConfigurationListener> servicePropertiesListeners;
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts private final ServicePropertiesConfigurationListener platformServicePropertiesListener;
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts servicePropertiesListeners = new HashMap<>();
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts platformServicePropertiesListener = new ServicePropertiesConfigurationListener();
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts Map<String, Set<String>> services = new HashMap<>();
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden for (Map.Entry<String, AttributeStruct> property : ATTRIBUTE_MAP.entrySet()) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts String serviceName = property.getValue().getServiceName();
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts services.put(serviceName, new HashSet<String>());
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts services.get(serviceName).add(property.getKey());
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts ConfigurationObserver configurationObserver = ConfigurationObserver.getInstance();
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts for (final Map.Entry<String, Set<String>> service : services.entrySet()) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts if (!Constants.SVC_NAME_PLATFORM.equals(service.getKey())) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts Set<String> properties = service.getValue();
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts ServicePropertiesConfigurationListener listener =
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts new ServicePropertiesConfigurationListener(properties);
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts servicePropertiesListeners.put(property, listener);
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts configurationObserver.addServiceListener(listener, new Predicate<String>() {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts return s != null && s.equals(service.getKey());
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts configurationObserver.addServiceListener(platformServicePropertiesListener, new Predicate<String>() {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts return Constants.SVC_NAME_PLATFORM.equals(s);
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts * A listener for the properties that are provided by a single service. Property values are cached so that
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts * property listeners are only notified when the property(-ies) they are observing have changed.
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts private static final class ServicePropertiesConfigurationListener implements ConfigurationListener {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts private final Map<String, Set<ConfigurationListener>> propertyListeners = new HashMap<>();
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts private final Map<String, String> propertyValues = new HashMap<>();
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts private ServicePropertiesConfigurationListener(Set<String> propertyNames) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts for (String propertyName : propertyNames) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts private void registerPropertyName(String propertyName) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts propertyListeners.put(propertyName, Collections.synchronizedSet(new HashSet<ConfigurationListener>()));
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts private ServicePropertiesConfigurationListener() {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts // nothing to see here
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts Set<ConfigurationListener> affectedListeners = new HashSet<>();
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts for (Map.Entry<String, Set<ConfigurationListener>> propertyListeners : this.propertyListeners.entrySet()) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts String propertyName = propertyListeners.getKey();
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts String oldValue = propertyValues.get(propertyName);
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts if (value != null && !value.equals(oldValue) || value == null && oldValue != null) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts Set<ConfigurationListener> listeners = propertyListeners.getValue();
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts for (ConfigurationListener listener : listeners) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts for (ConfigurationListener listener : affectedListeners) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts * Listen for runtime changes to a system property value. Only values that are stored in the SMS will
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts * be changed at runtime. See {@code serverdefaults.properties}, {@code amPlatform.xml} and
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts * @param listener The listener to call when one of the provided properties has changed.
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts * @param properties The list of properties that should be observed. A change in any one of these properties
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts * will cause the listener to be notified.
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts public static void observe(ConfigurationListener listener, String... properties) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts ServicePropertiesConfigurationListener serviceListener =
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts Listeners.INSTANCE.servicePropertiesListeners.get(property);
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts serviceListener = Listeners.INSTANCE.platformServicePropertiesListener;
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts synchronized (serviceListener) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts if (!serviceListener.propertyListeners.containsKey(property)) {
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts serviceListener.registerPropertyName(property);
98ea99a9d0a5253440a949279650e7d229051ee7James Phillpotts serviceListener.propertyListeners.get(property).add(listener);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden * Holds the current properties map together with the tagswap values and last updated timestamp to allow atomic
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden * updates of all three as one unit without locking. This is an immutable structure that is intended to be used
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden * with an AtomicReference.
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden private final Map<String, String> tagSwapValues;
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden PropertiesHolder(final Map<String, String> properties) {
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden Map<String, String> tagSwapMap = new HashMap<>();
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden for (Map.Entry<String, String> tagSwapEntry : TAG_SWAP_PROPERTIES.entrySet()) {
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden this.properties = Collections.unmodifiableMap(properties);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden this.tagSwapValues = Collections.unmodifiableMap(tagSwapMap);
6f4585ccfd5c6dac45cc93a0110ea8ad255315ffNeil Madden PropertiesHolder putAll(Properties newProperties) {