/*
* Copyright 2011-2017 the original author or authors.
*
* 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.cloudfoundry.reconfiguration.play;
import org.springframework.cloud.Cloud;
import org.springframework.cloud.service.ServiceInfo;
import org.springframework.cloud.service.common.MysqlServiceInfo;
import org.springframework.cloud.service.common.PostgresqlServiceInfo;
import org.springframework.cloud.service.common.RelationalServiceInfo;
import javax.sql.DataSource;
import java.net.URI;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
import java.util.logging.Logger;
final class Configurer {
private static final Logger LOGGER = Logger.getLogger(Configurer.class.getName());
private Configurer() {
}
static void configure(ApplicationConfiguration applicationConfiguration,
Cloud cloud, PropertySetter propertySetter) {
propertySetter.setCloudProperties();
Set<String> databaseNames = applicationConfiguration.getDatabaseNames();
propertySetter.setDatabaseProperties(databaseNames);
if (databaseNames.isEmpty()) {
LOGGER.info("No databases found. Skipping auto-reconfiguration.");
} else if (databaseNames.size() > 1) {
LOGGER.warning(String.format("Multiple (%d) databases found. Skipping auto-reconfiguration.",
databaseNames.size()));
} else {
processDatabase(applicationConfiguration, cloud, databaseNames.iterator().next());
}
}
private static void processDatabase(ApplicationConfiguration applicationConfiguration, Cloud cloud, String name) {
List<ServiceInfo> serviceInfos = cloud.getServiceInfos(DataSource.class);
if (serviceInfos.isEmpty()) {
LOGGER.info("No matching service found. Skipping auto-reconfiguration.");
} else if (serviceInfos.size() > 1) {
LOGGER.warning(String.format("More than one (%d) matching services found. Skipping auto-reconfiguration.",
serviceInfos.size()));
} else {
configureDatabase(name, (RelationalServiceInfo) serviceInfos.get(0));
configureJpa(applicationConfiguration);
}
}
private static void configureDatabase(String name, RelationalServiceInfo serviceInfo) {
LOGGER.info(String.format("Auto-reconfiguring %s", name));
System.setProperty(String.format("db.%s.url", name), serviceInfo.getJdbcUrl());
String username = serviceInfo.getUserName();
String password = serviceInfo.getPassword();
if ((username == null || password == null) && serviceInfo instanceof MysqlServiceInfo) {
Map<String, String> queryMap = getQueryParameters(serviceInfo);
if (username == null) {
username = queryMap.get("user");
}
if (password == null) {
password = queryMap.get("password");
}
}
System.setProperty(String.format("db.%s.user", name), username);
if (password != null) {
System.setProperty(String.format("db.%s.password", name), password);
}
if (serviceInfo instanceof MysqlServiceInfo) {
System.setProperty(String.format("db.%s.driver", name), PropertySetter.MYSQL_DRIVER_CLASS);
} else if (serviceInfo instanceof PostgresqlServiceInfo) {
System.setProperty(String.format("db.%s.driver", name), PropertySetter.POSTGRES_DRIVER_CLASS);
}
}
private static Map<String, String> getQueryParameters(RelationalServiceInfo serviceInfo) {
URI uri = URI.create(serviceInfo.getUri());
if (uri.getQuery() != null) {
return processQueryString(uri.getQuery());
}
URI schemeSpecificUri = URI.create(uri.getSchemeSpecificPart());
return processQueryString(schemeSpecificUri.getQuery());
}
private static Map<String, String> processQueryString(String queryString) {
String[] fields = queryString.split("&");
String[] keyValue;
Map<String, String> queryMap = new HashMap<>();
for (String field : fields) {
keyValue = field.split("=");
if (2 == keyValue.length) {
queryMap.put(keyValue[0], keyValue[1]);
}
}
return queryMap;
}
private static void configureJpa(ApplicationConfiguration applicationConfiguration) {
String status = applicationConfiguration.getConfiguration().getProperty("jpaplugin");
if (!"disabled".equals(status)) {
LOGGER.info("Auto-reconfiguring JPA Plugin");
System.setProperty("cfjpaplugin", "enabled");
}
System.setProperty("jpaplugin", "disabled");
}
}