/***
* Copyright (c) 2009 Caelum - www.caelum.com.br/opensource All rights reserved.
*
* 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 br.com.caelum.vraptor.environment;
import static br.com.caelum.vraptor.environment.EnvironmentType.DEVELOPMENT;
import static br.com.caelum.vraptor.environment.EnvironmentType.PRODUCTION;
import static br.com.caelum.vraptor.environment.EnvironmentType.TEST;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.security.AccessController.doPrivileged;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.PrivilegedAction;
import java.util.NoSuchElementException;
import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A default {@link Environment} implementation which loads the environment file based on {@code VRAPTOR_ENV} system
* property or {@code br.com.caelum.vraptor.environment} property in the context init parameter.
*
* @author Alexandre Atoji
* @author Andrew Kurauchi
* @author Guilherme Silveira
* @author Rodrigo Turini
* @author Otávio Garcia
*/
@ApplicationScoped
@Named("environment")
public class DefaultEnvironment implements Environment {
private static final Logger LOG = LoggerFactory.getLogger(DefaultEnvironment.class);
public static final String ENVIRONMENT_PROPERTY = "br.com.caelum.vraptor.environment";
public static final String BASE_ENVIRONMENT_FILE = "environment";
private final ServletContext context;
private Properties properties;
private EnvironmentType environmentType;
/**
* @deprecated CDI eyes only
*/
protected DefaultEnvironment() {
this((ServletContext) null);
}
@Inject
public DefaultEnvironment(ServletContext context) {
this.context = context;
}
public DefaultEnvironment(EnvironmentType environmentType) {
this((ServletContext) null);
this.environmentType = environmentType;
loadProperties();
}
@PostConstruct
protected void setup() {
loadProperties();
}
private void loadProperties() {
properties = new Properties();
loadAndPut(BASE_ENVIRONMENT_FILE);
loadAndPut(getEnvironmentType().getName());
LOG.debug("Environment is up with properties {}", properties);
}
private EnvironmentType getEnvironmentType() {
if (environmentType == null) {
environmentType = new EnvironmentType(findEnvironmentName(context));
}
return environmentType;
}
private void loadAndPut(String environment) {
try (InputStream resource = getClass().getResourceAsStream("/" + environment + ".properties")) {
properties.load(resource);
LOG.debug("File {}.properties loaded", environment);
} catch (NullPointerException | IOException whenNotFound) {
LOG.warn("Could not find the file " + environment + ".properties to load.", whenNotFound);
}
}
private String findEnvironmentName(final ServletContext context) {
return doPrivileged(new PrivilegedAction<String>() {
@Override
public String run() {
String name = fromSystemEnv();
if (name != null) {
LOG.debug("Environment {} loaded by system env", name);
return name;
}
name = fromSystemProperty();
if (name != null) {
LOG.debug("Environment {} loaded by system property", name);
return name;
}
name = fromApplicationContext();
if (name != null) {
LOG.debug("Environment {} loaded by web.xml", name);
return name;
}
LOG.debug("No enviroment was found, using development as default");
return "development";
}
});
}
/**
* Find environment name using {@code VRAPTOR_ENV} from system environment.
*/
private static String fromSystemEnv() {
return System.getenv("VRAPTOR_ENV");
}
/**
* Find environment name using {@code br.com.caelum.vraptor.environment} from system property. To define this
* you can start the application server using {@code -Dbr.com.caelum.vraptor.environment=DEVELOPMENT}.
*/
private static String fromSystemProperty() {
return System.getProperty(ENVIRONMENT_PROPERTY);
}
/**
* Find environment name using {@code br.com.caelum.vraptor.environment} from application context. You
* can define using web.xml, adding an init parameter {@code br.com.caelum.vraptor.environment=DEVELOPMENT}.
*/
private String fromApplicationContext() {
return context.getInitParameter(ENVIRONMENT_PROPERTY);
}
@Override
public boolean supports(String feature) {
if (has(feature)) {
return Boolean.parseBoolean(get(feature).trim());
}
return false;
}
@Override
public boolean has(String key) {
return properties.containsKey(key);
}
@Override
public String get(String key) {
if (!has(key)) {
throw new NoSuchElementException(String.format("Key %s not found in environment %s", key, getName()));
}
String systemProperty = System.getProperty(key);
if (!isNullOrEmpty(systemProperty)) {
return systemProperty;
} else {
return properties.getProperty(key);
}
}
@Override
public String get(String key, String defaultValue) {
if (has(key)) {
return get(key);
}
return defaultValue;
}
@Override
public void set(String key, String value) {
properties.setProperty(key, value);
}
@Override
public Iterable<String> getKeys() {
return properties.stringPropertyNames();
}
@Override
public boolean isProduction() {
return PRODUCTION.equals(getEnvironmentType());
}
@Override
public boolean isDevelopment() {
return DEVELOPMENT.equals(getEnvironmentType());
}
@Override
public boolean isTest() {
return TEST.equals(getEnvironmentType());
}
@Override
public URL getResource(String name) {
URL resource = getClass().getResource("/" + getEnvironmentType().getName() + name);
if (resource != null) {
LOG.debug("Loading resource {} from environment {}", name, getEnvironmentType().getName());
return resource;
}
return getClass().getResource(name);
}
@Override
public String getName() {
return getEnvironmentType().getName();
}
}