All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.weld.config.WeldConfiguration Maven / Gradle / Ivy

There is a newer version: 3.0.0.Alpha1
Show newest version
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014, Red Hat, Inc., and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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.
 */
package org.jboss.weld.config;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.security.AccessController;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;

import org.jboss.weld.bootstrap.api.Service;
import org.jboss.weld.bootstrap.api.ServiceRegistry;
import org.jboss.weld.bootstrap.spi.BeanDeploymentArchive;
import org.jboss.weld.bootstrap.spi.BootstrapConfiguration;
import org.jboss.weld.bootstrap.spi.Deployment;
import org.jboss.weld.configuration.spi.ExternalConfiguration;
import org.jboss.weld.exceptions.IllegalStateException;
import org.jboss.weld.logging.BeanLogger;
import org.jboss.weld.logging.ConfigurationLogger;
import org.jboss.weld.resources.WeldClassLoaderResourceLoader;
import org.jboss.weld.resources.spi.ResourceLoader;
import org.jboss.weld.resources.spi.ResourceLoadingException;
import org.jboss.weld.security.GetSystemPropertyAction;
import org.jboss.weld.util.Preconditions;
import org.jboss.weld.util.collections.ImmutableMap;
import org.jboss.weld.util.reflection.Reflections;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

/**
 * Represents an immutable per-deployment Weld configuration.
 *
 * 

* Each property may be set in three different sources (by priority in descending order): *

*
    *
  1. In a properties file named `weld.properties`
  2. *
  3. As a system property
  4. *
  5. By a bootstrap configuration provided by an integrator
  6. *
* *

* For backwards compatibility there are some obsolete sources: *

*
    *
  • properties files org.jboss.weld.executor.properties and org.jboss.weld.bootstrap.properties are also loaded for some * configuration keys,
  • *
  • some system properties with obsolete keys are considered
  • *
* *

* If a configuration key is set in multiple sources (e.g. as a system property and in a weld.properties file), the value from the source with * higher priority is taken, other values are ignored. *

* *

* If a configuration key is set multiple times in the same source (e.g. different weld.properties files) and the values are different, the * container automatically detects the problem and treats it as a deployment problem. *

* *

* Unsupported configuration keys are ignored. If an invalid value is set, the container automatically detects the problem and treats it as a deployment * problem. *

* * @author Martin Kouba * @see BootstrapConfiguration * @see ConfigurationKey */ @SuppressWarnings("deprecation") public class WeldConfiguration implements Service { public static final String CONFIGURATION_FILE = "weld.properties"; private static final String EXECUTOR_CONFIGURATION_FILE = "org.jboss.weld.executor.properties"; private static final String BOOTSTRAP_CONFIGURATION_FILE = "org.jboss.weld.bootstrap.properties"; private static final String SYSTEM_PROPETIES = "system properties"; private static final String OBSOLETE_SYSTEM_PROPETIES = "obsolete system properties"; private static final String EXTERNAL_CONFIGURATION_CLASS_NAME = "org.jboss.weld.configuration.spi.ExternalConfiguration"; private static final String UNSAFE_PROXIES_MARKER = "META-INF/org.jboss.weld.enableUnsafeProxies"; private final Map properties; private final File proxyDumpFilePath; private final Pattern proxyIgnoreFinalMethodsPattern; /** * * @param services * @param deployment */ public WeldConfiguration(ServiceRegistry services, Deployment deployment) { Preconditions.checkArgumentNotNull(deployment, "deployment"); this.properties = init(services, deployment); this.proxyDumpFilePath = initProxyDumpFilePath(); this.proxyIgnoreFinalMethodsPattern = initProxyIgnoreFinalMethodsPattern(); StringBuilder logOuputBuilder = new StringBuilder("{"); String prefix = ""; for (ConfigurationKey key : properties.keySet()) { logOuputBuilder.append(prefix); prefix = ", "; logOuputBuilder.append(key.get() + "=" + properties.get(key)); } logOuputBuilder.append("}"); ConfigurationLogger.LOG.configurationInitialized(logOuputBuilder.toString()); } /** * * @param key * @return the property for the given key * @throws IllegalStateException If the property type does not match the required type */ public String getStringProperty(ConfigurationKey key) { return getProperty(key, String.class); } /** * * @param key * @return the property for the given key * @throws IllegalStateException If the property type does not match the required type */ public Boolean getBooleanProperty(ConfigurationKey key) { return getProperty(key, Boolean.class); } /** * * @param key * @return the property for the given key * @throws IllegalStateException If the property type does not match the required type */ public Long getLongProperty(ConfigurationKey key) { return getProperty(key, Long.class); } /** * * @param key * @return the property for the given key * @throws IllegalStateException If the property type does not match the required type */ public Integer getIntegerProperty(ConfigurationKey key) { return getProperty(key, Integer.class); } /** * * @return the path or null if the generated bytecode should not be dumped * @see ConfigurationKey#PROXY_DUMP */ public File getProxyDumpFilePath() { return proxyDumpFilePath; } /** * * @param className * @return true if the final methods declared on the given type should be ignored, false otherwise * @see ConfigurationKey#PROXY_IGNORE_FINAL_METHODS */ public boolean isFinalMethodIgnored(String className) { return proxyIgnoreFinalMethodsPattern != null ? proxyIgnoreFinalMethodsPattern.matcher(className).matches() : false; } @Override public void cleanup() { if (properties != null) { properties.clear(); } } /** * Merge two maps of configuration properties. If the original contains a mapping for the same key, the new mapping is ignored. * * @param original * @param toMerge */ static void merge(Map original, Map toMerge, String mergedSourceDescription) { for (Entry entry : toMerge.entrySet()) { Object existing = original.get(entry.getKey()); if (existing != null) { ConfigurationLogger.LOG.configurationKeyAlreadySet(entry.getKey().get(), existing, entry.getValue(), mergedSourceDescription); } else { original.put(entry.getKey(), entry.getValue()); } } } /** * * @param key * @param requiredType * @throws IllegalStateException If the configuration property type does not match the required type */ static void checkRequiredType(ConfigurationKey key, Class requiredType) { if (!key.isValidValueType(requiredType)) { throw ConfigurationLogger.LOG.configurationPropertyTypeMismatch(key.getDefaultValue().getClass(), requiredType, key.get()); } } /** * * @param key * @return the string value of the system property or null */ static String getSystemProperty(String key) { try { return AccessController.doPrivileged(new GetSystemPropertyAction(key)); } catch (Throwable ignore) { return null; } } private Map init(ServiceRegistry services, Deployment deployment) { // 1. Properties files // weld.properties Map properties = readFileProperties(findPropertiesFiles(deployment, CONFIGURATION_FILE)); // org.jboss.weld.bootstrap.properties merge(properties, readObsoleteFileProperties( findPropertiesFiles(deployment, BOOTSTRAP_CONFIGURATION_FILE), ImmutableMap. builder().put("concurrentDeployment", ConfigurationKey.CONCURRENT_DEPLOYMENT) .put("preloaderThreadPoolSize", ConfigurationKey.PRELOADER_THREAD_POOL_SIZE).build()), BOOTSTRAP_CONFIGURATION_FILE); // org.jboss.weld.executor.properties merge(properties, readObsoleteFileProperties( findPropertiesFiles(deployment, EXECUTOR_CONFIGURATION_FILE), ImmutableMap. builder().put("threadPoolSize", ConfigurationKey.EXECUTOR_THREAD_POOL_SIZE) .put("threadPoolDebug", ConfigurationKey.EXECUTOR_THREAD_POOL_DEBUG) .put("threadPoolType", ConfigurationKey.EXECUTOR_THREAD_POOL_TYPE) .put("threadPoolKeepAliveTime", ConfigurationKey.EXECUTOR_THREAD_POOL_KEEP_ALIVE_TIME).build()), EXECUTOR_CONFIGURATION_FILE); // META-INF/org.jboss.weld.enableUnsafeProxies if (!findPropertiesFiles(deployment, UNSAFE_PROXIES_MARKER).isEmpty()) { merge(properties, ImmutableMap.of(ConfigurationKey.RELAXED_CONSTRUCTION, true), UNSAFE_PROXIES_MARKER); } // 2. System properties merge(properties, getSystemProperties(), SYSTEM_PROPETIES); merge(properties, getObsoleteSystemProperties(), OBSOLETE_SYSTEM_PROPETIES); // 3. Integrator SPI // ExternalConfiguration.getConfigurationProperties() map has precedence merge(properties, processExternalConfiguration(getExternalConfigurationOptions(services)), "ExternalConfiguration"); merge(properties, processBootstrapConfiguration(services.get(BootstrapConfiguration.class)), BootstrapConfiguration.class.getSimpleName()); return properties; } private File initProxyDumpFilePath() { String dumpPath = getStringProperty(ConfigurationKey.PROXY_DUMP); if (!dumpPath.isEmpty()) { File tmp = new File(dumpPath); if (!tmp.isDirectory() && !tmp.mkdirs()) { BeanLogger.LOG.directoryCannotBeCreated(tmp.toString()); return null; } else { return tmp; } } return null; } private Pattern initProxyIgnoreFinalMethodsPattern() { String ignore = getStringProperty(ConfigurationKey.PROXY_IGNORE_FINAL_METHODS); if (!ignore.isEmpty()) { return Pattern.compile(ignore); } return null; } @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS", justification = "Only local URLs involved") private Set findPropertiesFiles(Deployment deployment, String fileName) { Set resourceLoaders = new HashSet(); Set files = new HashSet(); ResourceLoader deploymentResourceLoader = deployment.getServices().get(ResourceLoader.class); if (deploymentResourceLoader != null) { resourceLoaders.add(deploymentResourceLoader); } for (BeanDeploymentArchive archive : deployment.getBeanDeploymentArchives()) { ResourceLoader resourceLoader = archive.getServices().get(ResourceLoader.class); if (resourceLoader == null) { ConfigurationLogger.LOG.resourceLoaderNotSpecifiedForArchive(archive); continue; } resourceLoaders.add(resourceLoader); } for (ResourceLoader resourceLoader : resourceLoaders) { URL file = resourceLoader.getResource(fileName); if (file != null) { files.add(file); } } return files; } /** * Iterate through the {@link ConfigurationKey#values()} and try to get a system property for every key. The value is automatically converted - a runtime * exception may be thrown during conversion. * * @return all the properties set as system properties */ private Map getSystemProperties() { Map found = new EnumMap(ConfigurationKey.class); for (ConfigurationKey key : ConfigurationKey.values()) { String property = getSystemProperty(key.get()); if (property != null) { processKeyValue(found, key, property); } } return found; } /** * Try to get a system property for obsolete keys. The value is automatically converted - a runtime exception may be thrown during conversion. * * @return all the properties whose system property keys were different in previous versions */ private Map getObsoleteSystemProperties() { Map found = new EnumMap(ConfigurationKey.class); String concurrentDeployment = getSystemProperty("org.jboss.weld.bootstrap.properties.concurrentDeployment"); if (concurrentDeployment != null) { processKeyValue(found, ConfigurationKey.CONCURRENT_DEPLOYMENT, concurrentDeployment); found.put(ConfigurationKey.CONCURRENT_DEPLOYMENT, ConfigurationKey.CONCURRENT_DEPLOYMENT.convertValue(concurrentDeployment)); } String preloaderThreadPoolSize = getSystemProperty("org.jboss.weld.bootstrap.properties.preloaderThreadPoolSize"); if (preloaderThreadPoolSize != null) { found.put(ConfigurationKey.PRELOADER_THREAD_POOL_SIZE, ConfigurationKey.PRELOADER_THREAD_POOL_SIZE.convertValue(preloaderThreadPoolSize)); } return found; } /** * Read the set of property files. Keys and Values are automatically validated and converted. * * @param resourceLoader * @return all the properties from the weld.properties file */ @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS", justification = "Only local URLs involved") private Map readFileProperties(Set files) { Map found = new EnumMap(ConfigurationKey.class); for (URL file : files) { ConfigurationLogger.LOG.readingPropertiesFile(file); Properties fileProperties = loadProperties(file); for (String name : fileProperties.stringPropertyNames()) { processKeyValue(found, name, fileProperties.getProperty(name)); } } return found; } @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS", justification = "Only local URLs involved") private Map readObsoleteFileProperties(Set files, Map nameToKeyMap) { if (files.isEmpty()) { return Collections.emptyMap(); } Map found = new EnumMap(ConfigurationKey.class); for (URL file : files) { ConfigurationLogger.LOG.readingPropertiesFile(file); Properties fileProperties = loadProperties(file); for (String name : fileProperties.stringPropertyNames()) { ConfigurationKey key = nameToKeyMap.get(name); if (key != null) { processKeyValue(found, key, fileProperties.getProperty(name)); } else { ConfigurationLogger.LOG.unsupportedConfigurationKeyFound(name + " in " + fileProperties); } } } return found; } private Map processBootstrapConfiguration(BootstrapConfiguration bootstrapConfiguration) { if (bootstrapConfiguration != null) { Map found = new EnumMap(ConfigurationKey.class); processKeyValue(found, ConfigurationKey.CONCURRENT_DEPLOYMENT, bootstrapConfiguration.isConcurrentDeploymentEnabled()); processKeyValue(found, ConfigurationKey.PRELOADER_THREAD_POOL_SIZE, bootstrapConfiguration.getPreloaderThreadPoolSize()); processKeyValue(found, ConfigurationKey.NON_PORTABLE_MODE, bootstrapConfiguration.isNonPortableModeEnabled()); return found; } return Collections.emptyMap(); } private Map processExternalConfiguration(Map externalConfiguration) { Map found = new EnumMap(ConfigurationKey.class); for (Entry entry : externalConfiguration.entrySet()) { processKeyValue(found, entry.getKey(), entry.getValue()); } return found; } private Map getExternalConfigurationOptions(ServiceRegistry services) { // to stay compatible with older SPI versions we first check if ExternalConfiguration is available before using the class if (Reflections.isClassLoadable(EXTERNAL_CONFIGURATION_CLASS_NAME, WeldClassLoaderResourceLoader.INSTANCE)) { final ExternalConfiguration externalConfiguration = services.get(ExternalConfiguration.class); if (externalConfiguration != null) { return externalConfiguration.getConfigurationProperties(); } } return Collections.emptyMap(); } /** * Process the given key and value. First validate the value and check if there's no different value for the same key in the same source - invalid and * different values are treated as a deployment problem. * * @param properties * @param key * @param value */ private void processKeyValue(Map properties, ConfigurationKey key, Object value) { if (value instanceof String) { value = key.convertValue((String) value); } if (key.isValidValue(value)) { Object previous = properties.put(key, value); if (previous != null && !previous.equals(value)) { throw ConfigurationLogger.LOG.configurationKeyHasDifferentValues(key.get(), previous, value); } } else { throw ConfigurationLogger.LOG.invalidConfigurationPropertyValue(value, key.get()); } } /** * Process the given string key and value. First try to convert the stringKey - unsupported keys are ignored. Then delegate to * {@link #processKeyValue(Map, ConfigurationKey, Object)}. * * @param properties * @param stringKey * @param value */ private void processKeyValue(Map properties, String stringKey, Object value) { ConfigurationKey key = ConfigurationKey.fromString(stringKey); if (key != null) { processKeyValue(properties, key, value); } else { ConfigurationLogger.LOG.unsupportedConfigurationKeyFound(stringKey); } } @SuppressWarnings("unchecked") private T getProperty(ConfigurationKey key, Class requiredType) { checkRequiredType(key, requiredType); Object property = properties.get(key); return (T) (property != null ? property : key.getDefaultValue()); } private Properties loadProperties(URL url) { Properties properties = new Properties(); try { properties.load(url.openStream()); } catch (IOException e) { throw new ResourceLoadingException(e); } return properties; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy