package org.springframework.cloud.heroku;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.springframework.cloud.AbstractCloudConnector;
import org.springframework.cloud.CloudException;
import org.springframework.cloud.FallbackServiceInfoCreator;
import org.springframework.cloud.ServiceInfoCreator;
import org.springframework.cloud.app.ApplicationInstanceInfo;
import org.springframework.cloud.service.BaseServiceInfo;
import org.springframework.cloud.service.FallbackBaseServiceInfoCreator;
import org.springframework.cloud.service.ServiceInfo;
import org.springframework.cloud.service.UriBasedServiceData;
import org.springframework.cloud.util.EnvironmentAccessor;
/**
* Implementation of CloudConnector for Heroku
*
* Currently support Postgres (default provided), Mysql (Cleardb), MongoDb (MongoLab, MongoHQ, MongoSoup),
* Redis (RedisToGo, RedisCloud, OpenRedis, RedisGreen), and AMQP (CloudAmqp).
*
* @author Ramnivas Laddad
*/
public class HerokuConnector extends AbstractCloudConnector<UriBasedServiceData> {
private EnvironmentAccessor environment = new EnvironmentAccessor();
private ApplicationInstanceInfoCreator applicationInstanceInfoCreator
= new ApplicationInstanceInfoCreator(environment);
private List<String> serviceEnvPrefixes;
@SuppressWarnings({"unchecked", "rawtypes"})
public HerokuConnector() {
super((Class) HerokuServiceInfoCreator.class);
}
@Override
public boolean isInMatchingCloud() {
return environment.getEnvValue("DYNO") != null;
}
@Override
public ApplicationInstanceInfo getApplicationInstanceInfo() {
try {
return applicationInstanceInfoCreator.createApplicationInstanceInfo();
} catch (Exception e) {
throw new CloudException(e);
}
}
/* package for testing purpose */
void setCloudEnvironment(EnvironmentAccessor environment) {
this.environment = environment;
this.applicationInstanceInfoCreator = new ApplicationInstanceInfoCreator(environment);
}
@Override
protected void registerServiceInfoCreator(ServiceInfoCreator<? extends ServiceInfo, UriBasedServiceData> serviceInfoCreator) {
super.registerServiceInfoCreator(serviceInfoCreator);
HerokuServiceInfoCreator<?> herokuServiceInfoCreator = (HerokuServiceInfoCreator<?>) serviceInfoCreator;
String[] envPrefixes = herokuServiceInfoCreator.getEnvPrefixes();
// need to do this since this method gets called during construction and we cannot initialize serviceEnvPrefixes before this
if (serviceEnvPrefixes == null) {
serviceEnvPrefixes = new ArrayList<String>();
}
serviceEnvPrefixes.addAll(Arrays.asList(envPrefixes));
}
/**
* Return object representation of the bound services
* <p>
* Returns map whose key is the env key and value is the associated url
* </p>
*
* @return information about services bound to the app
*/
protected List<UriBasedServiceData> getServicesData() {
List<UriBasedServiceData> serviceData = new ArrayList<UriBasedServiceData>();
Map<String, String> env = environment.getEnv();
for (Map.Entry<String, String> envEntry : env.entrySet()) {
for (String envPrefix : serviceEnvPrefixes) {
if (envEntry.getKey().startsWith(envPrefix)) {
serviceData.add(new UriBasedServiceData(envEntry.getKey(), envEntry.getValue()));
}
}
}
return serviceData;
}
@Override
protected FallbackServiceInfoCreator<BaseServiceInfo, UriBasedServiceData> getFallbackServiceInfoCreator() {
return new FallbackBaseServiceInfoCreator();
}
}