Use tabs for indentation consistently.

This commit is contained in:
Scott Frederick
2015-05-27 09:50:09 -05:00
parent 2b0bdf5768
commit 3592f34bf3
32 changed files with 684 additions and 718 deletions

View File

@@ -40,349 +40,337 @@ import org.springframework.cloud.service.ServiceInfo.ServiceProperty;
*
*/
public class Cloud {
private CloudConnector cloudConnector;
private ServiceConnectorCreatorRegistry serviceConnectorCreatorRegistry = new ServiceConnectorCreatorRegistry();
private CloudConnector cloudConnector;
private ServiceConnectorCreatorRegistry serviceConnectorCreatorRegistry = new ServiceConnectorCreatorRegistry();
/**
* Package-access constructor.
*
* @param cloudConnector
* the underlying connector
* @param serviceConnectorCreators
* service connector creators
*/
Cloud(CloudConnector cloudConnector, List<ServiceConnectorCreator<?, ? extends ServiceInfo>> serviceConnectorCreators) {
this.cloudConnector = cloudConnector;
/**
* Package-access constructor.
*
* @param cloudConnector the underlying connector
* @param serviceConnectorCreators service connector creators
*/
Cloud(CloudConnector cloudConnector, List<ServiceConnectorCreator<?, ? extends ServiceInfo>> serviceConnectorCreators) {
this.cloudConnector = cloudConnector;
for (ServiceConnectorCreator<?, ? extends ServiceInfo> serviceCreator : serviceConnectorCreators) {
registerServiceConnectorCreator(serviceCreator);
}
}
for (ServiceConnectorCreator<?, ? extends ServiceInfo> serviceCreator : serviceConnectorCreators) {
registerServiceConnectorCreator(serviceCreator);
}
}
/**
* @see CloudConnector#getApplicationInstanceInfo()
*
* @return information about the application instance
*/
public ApplicationInstanceInfo getApplicationInstanceInfo() {
return cloudConnector.getApplicationInstanceInfo();
}
/**
* @see CloudConnector#getApplicationInstanceInfo()
*
* @return information about the application instance
*/
public ApplicationInstanceInfo getApplicationInstanceInfo() {
return cloudConnector.getApplicationInstanceInfo();
}
/**
* Get {@link ServiceInfo} for the given service id
*
* @param serviceId
* service id
* @return info for the serviceId
*/
public ServiceInfo getServiceInfo(String serviceId) {
for (ServiceInfo serviceInfo : getServiceInfos()) {
if (serviceInfo.getId().equals(serviceId)) {
return serviceInfo;
}
}
throw new CloudException("No service with id " + serviceId + " found");
}
/**
* Get {@link ServiceInfo} for the given service id
*
* @param serviceId service id
* @return info for the serviceId
*/
public ServiceInfo getServiceInfo(String serviceId) {
for (ServiceInfo serviceInfo : getServiceInfos()) {
if (serviceInfo.getId().equals(serviceId)) {
return serviceInfo;
}
}
throw new CloudException("No service with id " + serviceId + " found");
}
/**
* @see CloudConnector#getServiceInfos()
* @return information about all services bound to the application
*/
public List<ServiceInfo> getServiceInfos() {
return flatten(cloudConnector.getServiceInfos());
}
/**
* @see CloudConnector#getServiceInfos()
* @return information about all services bound to the application
*/
public List<ServiceInfo> getServiceInfos() {
return flatten(cloudConnector.getServiceInfos());
}
/**
* Get {@link ServiceInfo}s for the bound services that could be mapped to the given service connector type.
*
* <p>
* For example, if the connector type is {@link DataSource}, then the method will return all {@link ServiceInfo} objects
* matching bound relational database services.
* <p>
*
* @param <T>
* The class of the connector to find services for.
* @param serviceConnectorType
* service connector type.
* Passing null returns all {@link ServiceInfo}s (matching that of {@link Cloud#getServiceInfos()}
* @return information about services bound to the application that could be transformed into the given connector type
*/
public <T> List<ServiceInfo> getServiceInfos(Class<T> serviceConnectorType) {
List<ServiceInfo> allServiceInfos = getServiceInfos();
List<ServiceInfo> matchingServiceInfos = new ArrayList<ServiceInfo>();
/**
* Get {@link ServiceInfo}s for the bound services that could be mapped to the given service connector type.
*
* <p>
* For example, if the connector type is {@link DataSource}, then the method will return all {@link ServiceInfo} objects
* matching bound relational database services.
* <p>
*
* @param <T> The class of the connector to find services for.
* @param serviceConnectorType service connector type.
* Passing null returns all {@link ServiceInfo}s (matching that of {@link Cloud#getServiceInfos()}
* @return information about services bound to the application that could be transformed into the given connector type
*/
public <T> List<ServiceInfo> getServiceInfos(Class<T> serviceConnectorType) {
List<ServiceInfo> allServiceInfos = getServiceInfos();
List<ServiceInfo> matchingServiceInfos = new ArrayList<ServiceInfo>();
for (ServiceInfo serviceInfo : allServiceInfos) {
if (serviceConnectorCreatorRegistry.canCreate(serviceConnectorType, serviceInfo)) {
matchingServiceInfos.add(serviceInfo);
}
}
for (ServiceInfo serviceInfo : allServiceInfos) {
if (serviceConnectorCreatorRegistry.canCreate(serviceConnectorType, serviceInfo)) {
matchingServiceInfos.add(serviceInfo);
}
}
return matchingServiceInfos;
}
return matchingServiceInfos;
}
/**
* Get a service connector for the given service id, the connector type, configured with the given config
*
*
* @param <SC>
* The class of the service connector to return.
* @param serviceId
* the service id
* @param serviceConnectorType
* The expected class of service connector such as, DataSource.class.
* @param serviceConnectorConfig
* service connector configuration (such as pooling parameters).
* @return a service connector of the specified type with the given configuration applied
*
*/
public <SC> SC getServiceConnector(String serviceId, Class<SC> serviceConnectorType,
ServiceConnectorConfig serviceConnectorConfig) {
ServiceInfo serviceInfo = getServiceInfo(serviceId);
/**
* Get a service connector for the given service id, the connector type, configured with the given config
*
*
* @param <SC> The class of the service connector to return.
* @param serviceId the service id
* @param serviceConnectorType The expected class of service connector such as, DataSource.class.
* @param serviceConnectorConfig service connector configuration (such as pooling parameters).
* @return a service connector of the specified type with the given configuration applied
*
*/
public <SC> SC getServiceConnector(String serviceId, Class<SC> serviceConnectorType,
ServiceConnectorConfig serviceConnectorConfig) {
ServiceInfo serviceInfo = getServiceInfo(serviceId);
return getServiceConnector(serviceInfo, serviceConnectorType, serviceConnectorConfig);
}
return getServiceConnector(serviceInfo, serviceConnectorType, serviceConnectorConfig);
}
/**
* Get the singleton service connector for the given connector type, configured with the given config
*
* @param <SC>
* The class of the service connector to return.
* @param serviceConnectorType
* The expected class of service connector such as, DataSource.class.
* @param serviceConnectorConfig
* service connector configuration (such as pooling parameters).
* @return the single service connector of the specified type with the given configuration applied
*
*/
public <SC> SC getSingletonServiceConnector(Class<SC> serviceConnectorType, ServiceConnectorConfig serviceConnectorConfig) {
List<ServiceInfo> matchingServiceInfos = getServiceInfos(serviceConnectorType);
/**
* Get the singleton service connector for the given connector type, configured with the given config
*
* @param <SC> The class of the service connector to return.
* @param serviceConnectorType The expected class of service connector such as, DataSource.class.
* @param serviceConnectorConfig service connector configuration (such as pooling parameters).
* @return the single service connector of the specified type with the given configuration applied
*
*/
public <SC> SC getSingletonServiceConnector(Class<SC> serviceConnectorType, ServiceConnectorConfig serviceConnectorConfig) {
List<ServiceInfo> matchingServiceInfos = getServiceInfos(serviceConnectorType);
if (matchingServiceInfos.size() != 1) {
throw new CloudException("No unique service matching " + serviceConnectorType + " found. Expected 1, found "
+ matchingServiceInfos.size());
}
if (matchingServiceInfos.size() != 1) {
throw new CloudException("No unique service matching " + serviceConnectorType + " found. Expected 1, found "
+ matchingServiceInfos.size());
}
ServiceInfo matchingServiceInfo = matchingServiceInfos.get(0);
ServiceInfo matchingServiceInfo = matchingServiceInfos.get(0);
return getServiceConnector(matchingServiceInfo, serviceConnectorType, serviceConnectorConfig);
}
return getServiceConnector(matchingServiceInfo, serviceConnectorType, serviceConnectorConfig);
}
/**
* Register a new service connector creator
*
* @param serviceConnectorCreator the service connector to register
*/
public void registerServiceConnectorCreator(ServiceConnectorCreator<?, ? extends ServiceInfo> serviceConnectorCreator) {
serviceConnectorCreatorRegistry.registerCreator(serviceConnectorCreator);
}
/**
* Register a new service connector creator
*
* @param serviceConnectorCreator the service connector to register
*/
public void registerServiceConnectorCreator(ServiceConnectorCreator<?, ? extends ServiceInfo> serviceConnectorCreator) {
serviceConnectorCreatorRegistry.registerCreator(serviceConnectorCreator);
}
/**
* Get properties for app and services.
*
*
*
* <p>
* Application properties always include <code>cloud.application.app-id</code> and <code>cloud.application.instance-id</code>
* with values bound to application id and instance id. The rest of the properties are cloud-provider specific, but take the
* <code>cloud.application.&lt;property-name&gt;</code> form. <pre>
* cloud.application.app-id = helloworld
* cloud.application.instance-id = instance-0-0fab098f
* cloud.application.&lt;property-name&gt; = &lt;property-value&gt;
* </pre>
*
* <p>
* Service specific properties are exposed for each bound service, with each key starting in <code>cloud.services</code>. Like
* application properties, these too are cloud and service specific. Each key for a specific service starts with
* <code>cloud.services.&lt;service-id&gt;</code> <pre>
* cloud.services.customerDb.type = mysql-5.1
* cloud.services.customerDb.plan = free
* cloud.services.customerDb.connection.hostname = ...
* cloud.services.customerDb.connection.port = ...
* etc...
* </pre>
*
* <p>
* If a there is only a single service of a given type (as defined by the {link ServiceInfo.ServiceLabel}
* annoation's value of the corresponding {@link ServiceInfo} class), that service is aliased
* to the service type. Keys for such properties start in <code>cloud.services.&lt;service-type&gt;</code>.
* For example, if there is only a single MySQL service bound to the application, the service properties
* will also be exposed starting with '<code>cloud.services.mysql</code>' key: <pre>
* cloud.services.mysql.type = mysql-5.1
* cloud.services.mysql.plan = free
* cloud.services.mysql.connection.hostname = ...
* cloud.services.mysql.connection.port = ...
* etc...
* </pre>
*
* @return the properties object
*/
public Properties getCloudProperties() {
Map<String, List<ServiceInfo>> mappedServiceInfos = new HashMap<String, List<ServiceInfo>>();
for (ServiceInfo serviceInfo : getServiceInfos()) {
String key = getServiceLabel(serviceInfo);
List<ServiceInfo> serviceInfosForLabel = mappedServiceInfos.get(key);
if (serviceInfosForLabel == null) {
serviceInfosForLabel = new ArrayList<ServiceInfo>();
mappedServiceInfos.put(key, serviceInfosForLabel);
}
serviceInfosForLabel.add(serviceInfo);
}
/**
* Get properties for app and services.
*
*
*
* <p>
* Application properties always include <code>cloud.application.app-id</code> and <code>cloud.application.instance-id</code>
* with values bound to application id and instance id. The rest of the properties are cloud-provider specific, but take the
* <code>cloud.application.&lt;property-name&gt;</code> form. <pre>
* cloud.application.app-id = helloworld
* cloud.application.instance-id = instance-0-0fab098f
* cloud.application.&lt;property-name&gt; = &lt;property-value&gt;
* </pre>
*
* <p>
* Service specific properties are exposed for each bound service, with each key starting in <code>cloud.services</code>. Like
* application properties, these too are cloud and service specific. Each key for a specific service starts with
* <code>cloud.services.&lt;service-id&gt;</code> <pre>
* cloud.services.customerDb.type = mysql-5.1
* cloud.services.customerDb.plan = free
* cloud.services.customerDb.connection.hostname = ...
* cloud.services.customerDb.connection.port = ...
* etc...
* </pre>
*
* <p>
* If a there is only a single service of a given type (as defined by the {link ServiceInfo.ServiceLabel}
* annoation's value of the corresponding {@link ServiceInfo} class), that service is aliased
* to the service type. Keys for such properties start in <code>cloud.services.&lt;service-type&gt;</code>.
* For example, if there is only a single MySQL service bound to the application, the service properties
* will also be exposed starting with '<code>cloud.services.mysql</code>' key: <pre>
* cloud.services.mysql.type = mysql-5.1
* cloud.services.mysql.plan = free
* cloud.services.mysql.connection.hostname = ...
* cloud.services.mysql.connection.port = ...
* etc...
* </pre>
*
* @return the properties object
*/
public Properties getCloudProperties() {
Map<String, List<ServiceInfo>> mappedServiceInfos = new HashMap<String, List<ServiceInfo>>();
for (ServiceInfo serviceInfo : getServiceInfos()) {
String key = getServiceLabel(serviceInfo);
List<ServiceInfo> serviceInfosForLabel = mappedServiceInfos.get(key);
if (serviceInfosForLabel == null) {
serviceInfosForLabel = new ArrayList<ServiceInfo>();
mappedServiceInfos.put(key, serviceInfosForLabel);
}
serviceInfosForLabel.add(serviceInfo);
}
final String servicePropKeyLead = "cloud.services.";
Properties cloudProperties = new Properties();
for (Entry<String, List<ServiceInfo>> mappedServiceInfo : mappedServiceInfos.entrySet()) {
List<ServiceInfo> serviceInfos = mappedServiceInfo.getValue();
final String servicePropKeyLead = "cloud.services.";
Properties cloudProperties = new Properties();
for (Entry<String, List<ServiceInfo>> mappedServiceInfo : mappedServiceInfos.entrySet()) {
List<ServiceInfo> serviceInfos = mappedServiceInfo.getValue();
for (ServiceInfo serviceInfo : serviceInfos) {
String idBasedKey = servicePropKeyLead + serviceInfo.getId();
cloudProperties.putAll(getServiceProperties(idBasedKey, serviceInfo));
for (ServiceInfo serviceInfo : serviceInfos) {
String idBasedKey = servicePropKeyLead + serviceInfo.getId();
cloudProperties.putAll(getServiceProperties(idBasedKey, serviceInfo));
// If there is only one service for a given label, put props with that label instead of just id
if (serviceInfos.size() == 1) {
String labelBasedKey = servicePropKeyLead + mappedServiceInfo.getKey();
cloudProperties.putAll(getServiceProperties(labelBasedKey, serviceInfo));
}
}
}
// If there is only one service for a given label, put props with that label instead of just id
if (serviceInfos.size() == 1) {
String labelBasedKey = servicePropKeyLead + mappedServiceInfo.getKey();
cloudProperties.putAll(getServiceProperties(labelBasedKey, serviceInfo));
}
}
}
cloudProperties.putAll(getAppProperties());
cloudProperties.putAll(getAppProperties());
return cloudProperties;
}
return cloudProperties;
}
private <SC> SC getServiceConnector(ServiceInfo serviceInfo, Class<SC> serviceConnectorType,
ServiceConnectorConfig serviceConnectorConfig) {
ServiceConnectorCreator<SC, ServiceInfo> serviceConnectorCreator = serviceConnectorCreatorRegistry.getServiceCreator(
serviceConnectorType, serviceInfo);
return serviceConnectorCreator.create(serviceInfo, serviceConnectorConfig);
}
private <SC> SC getServiceConnector(ServiceInfo serviceInfo, Class<SC> serviceConnectorType,
ServiceConnectorConfig serviceConnectorConfig) {
ServiceConnectorCreator<SC, ServiceInfo> serviceConnectorCreator = serviceConnectorCreatorRegistry.getServiceCreator(
serviceConnectorType, serviceInfo);
return serviceConnectorCreator.create(serviceInfo, serviceConnectorConfig);
}
private Properties getAppProperties() {
final String appPropLeadKey = "cloud.application.";
private Properties getAppProperties() {
final String appPropLeadKey = "cloud.application.";
Properties appProperties = new Properties();
appProperties.put(appPropLeadKey + "instance-id", getApplicationInstanceInfo().getInstanceId());
appProperties.put(appPropLeadKey + "app-id", getApplicationInstanceInfo().getAppId());
for (Map.Entry<String, Object> entry : getApplicationInstanceInfo().getProperties().entrySet()) {
if (entry.getValue() != null) {
appProperties.put(appPropLeadKey + entry.getKey(), entry.getValue());
}
}
Properties appProperties = new Properties();
appProperties.put(appPropLeadKey + "instance-id", getApplicationInstanceInfo().getInstanceId());
appProperties.put(appPropLeadKey + "app-id", getApplicationInstanceInfo().getAppId());
for (Map.Entry<String, Object> entry : getApplicationInstanceInfo().getProperties().entrySet()) {
if (entry.getValue() != null) {
appProperties.put(appPropLeadKey + entry.getKey(), entry.getValue());
}
}
return appProperties;
}
return appProperties;
}
private Properties getServiceProperties(String keyLead, ServiceInfo serviceInfo) {
Properties cloudProperties = new Properties();
private Properties getServiceProperties(String keyLead, ServiceInfo serviceInfo) {
Properties cloudProperties = new Properties();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(serviceInfo.getClass());
PropertyDescriptor[] propDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propDescriptor : propDescriptors) {
ServiceProperty propAnnotation = propDescriptor.getReadMethod().getAnnotation(ServiceProperty.class);
String key = keyLead;
try {
BeanInfo beanInfo = Introspector.getBeanInfo(serviceInfo.getClass());
PropertyDescriptor[] propDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propDescriptor : propDescriptors) {
ServiceProperty propAnnotation = propDescriptor.getReadMethod().getAnnotation(ServiceProperty.class);
String key = keyLead;
if (propAnnotation != null) {
if (!propAnnotation.category().isEmpty()) {
key = key + "." + propAnnotation.category();
}
if (!propAnnotation.name().isEmpty()) {
key = key + "." + propAnnotation.name();
} else {
key = key + "." + propDescriptor.getName().toLowerCase();
}
if (propAnnotation != null) {
if (!propAnnotation.category().isEmpty()) {
key = key + "." + propAnnotation.category();
}
if (!propAnnotation.name().isEmpty()) {
key = key + "." + propAnnotation.name();
} else {
key = key + "." + propDescriptor.getName().toLowerCase();
}
Object value = propDescriptor.getReadMethod().invoke(serviceInfo);
Object value = propDescriptor.getReadMethod().invoke(serviceInfo);
if (value != null) {
cloudProperties.put(key, value);
}
}
}
} catch (Exception e) {
throw new CloudException(e);
}
if (value != null) {
cloudProperties.put(key, value);
}
}
}
} catch (Exception e) {
throw new CloudException(e);
}
return cloudProperties;
}
return cloudProperties;
}
private static String getServiceLabel(ServiceInfo serviceInfo) {
Class<? extends ServiceInfo> serviceInfoClass = serviceInfo.getClass();
private static String getServiceLabel(ServiceInfo serviceInfo) {
Class<? extends ServiceInfo> serviceInfoClass = serviceInfo.getClass();
ServiceLabel labelAnnotation = serviceInfoClass.getAnnotation(ServiceInfo.ServiceLabel.class);
ServiceLabel labelAnnotation = serviceInfoClass.getAnnotation(ServiceInfo.ServiceLabel.class);
if (labelAnnotation == null) {
return null;
} else {
return labelAnnotation.value();
}
}
private static List<ServiceInfo> flatten(List<ServiceInfo> serviceInfos) {
List<ServiceInfo> flattened = new ArrayList<ServiceInfo>();
for (ServiceInfo serviceInfo : serviceInfos) {
if (serviceInfo instanceof CompositeServiceInfo) {
// recursively flatten any CompositeServiceInfos
CompositeServiceInfo compositeServiceInfo = (CompositeServiceInfo)serviceInfo;
flattened.addAll(flatten(compositeServiceInfo.getServiceInfos()));
} else {
flattened.add(serviceInfo);
}
}
return flattened;
}
if (labelAnnotation == null) {
return null;
} else {
return labelAnnotation.value();
}
}
private static List<ServiceInfo> flatten(List<ServiceInfo> serviceInfos) {
List<ServiceInfo> flattened = new ArrayList<ServiceInfo>();
for (ServiceInfo serviceInfo : serviceInfos) {
if (serviceInfo instanceof CompositeServiceInfo) {
// recursively flatten any CompositeServiceInfos
CompositeServiceInfo compositeServiceInfo = (CompositeServiceInfo)serviceInfo;
flattened.addAll(flatten(compositeServiceInfo.getServiceInfos()));
} else {
flattened.add(serviceInfo);
}
}
return flattened;
}
}
class ServiceConnectorCreatorRegistry {
private static Logger logger = Logger.getLogger(Cloud.class.getName());
private static Logger logger = Logger.getLogger(Cloud.class.getName());
private List<ServiceConnectorCreator<?, ? extends ServiceInfo>> serviceConnectorCreators = new ArrayList<ServiceConnectorCreator<?, ? extends ServiceInfo>>();
private List<ServiceConnectorCreator<?, ? extends ServiceInfo>> serviceConnectorCreators = new ArrayList<ServiceConnectorCreator<?, ? extends ServiceInfo>>();
public void registerCreator(ServiceConnectorCreator<?, ? extends ServiceInfo> serviceConnectorCreator) {
serviceConnectorCreators.add(serviceConnectorCreator);
}
public void registerCreator(ServiceConnectorCreator<?, ? extends ServiceInfo> serviceConnectorCreator) {
serviceConnectorCreators.add(serviceConnectorCreator);
}
public <SC, SI extends ServiceInfo> ServiceConnectorCreator<SC, SI> getServiceCreator(Class<SC> serviceConnectorType,
SI serviceInfo) {
ServiceConnectorCreator<SC, SI> serviceConnectorCreator = getServiceCreatorOrNull(serviceConnectorType, serviceInfo);
public <SC, SI extends ServiceInfo> ServiceConnectorCreator<SC, SI> getServiceCreator(Class<SC> serviceConnectorType,
SI serviceInfo) {
ServiceConnectorCreator<SC, SI> serviceConnectorCreator = getServiceCreatorOrNull(serviceConnectorType, serviceInfo);
if (serviceConnectorCreator != null) {
return serviceConnectorCreator;
} else {
throw new CloudException("No suitable ServiceConnectorCreator found: "
+ "service id=" + serviceInfo.getId() + ", "
+ "service info type=" + serviceInfo.getClass().getName() + ", "
+ "connector type=" + serviceConnectorType);
}
}
if (serviceConnectorCreator != null) {
return serviceConnectorCreator;
} else {
throw new CloudException("No suitable ServiceConnectorCreator found: "
+ "service id=" + serviceInfo.getId() + ", "
+ "service info type=" + serviceInfo.getClass().getName() + ", "
+ "connector type=" + serviceConnectorType);
}
}
public <SC, SI extends ServiceInfo> boolean canCreate(Class<SC> serviceConnectorType, SI serviceInfo) {
return getServiceCreatorOrNull(serviceConnectorType, serviceInfo) != null;
}
public <SC, SI extends ServiceInfo> boolean canCreate(Class<SC> serviceConnectorType, SI serviceInfo) {
return getServiceCreatorOrNull(serviceConnectorType, serviceInfo) != null;
}
public boolean accept(ServiceConnectorCreator<?, ? extends ServiceInfo> creator, Class<?> serviceConnectorType,
ServiceInfo serviceInfo) {
boolean typeBasedAccept = serviceConnectorType == null ? true : serviceConnectorType.isAssignableFrom(creator
.getServiceConnectorType());
boolean infoBasedAccept = serviceInfo == null ? true : creator.getServiceInfoType()
.isAssignableFrom(serviceInfo.getClass());
public boolean accept(ServiceConnectorCreator<?, ? extends ServiceInfo> creator, Class<?> serviceConnectorType,
ServiceInfo serviceInfo) {
boolean typeBasedAccept = serviceConnectorType == null ||
serviceConnectorType.isAssignableFrom(creator.getServiceConnectorType());
boolean infoBasedAccept = serviceInfo == null ||
creator.getServiceInfoType().isAssignableFrom(serviceInfo.getClass());
return typeBasedAccept && infoBasedAccept;
}
return typeBasedAccept && infoBasedAccept;
}
@SuppressWarnings("unchecked")
private <SC, SI extends ServiceInfo> ServiceConnectorCreator<SC, SI> getServiceCreatorOrNull(Class<SC> serviceConnectorType,
SI serviceInfo) {
for (ServiceConnectorCreator<?, ? extends ServiceInfo> serviceConnectorCreator : serviceConnectorCreators) {
logger.fine("Trying connector creator type " + serviceConnectorCreator);
if (accept(serviceConnectorCreator, serviceConnectorType, serviceInfo)) {
return (ServiceConnectorCreator<SC, SI>) serviceConnectorCreator;
}
}
return null;
}
@SuppressWarnings("unchecked")
private <SC, SI extends ServiceInfo> ServiceConnectorCreator<SC, SI> getServiceCreatorOrNull(Class<SC> serviceConnectorType,
SI serviceInfo) {
for (ServiceConnectorCreator<?, ? extends ServiceInfo> serviceConnectorCreator : serviceConnectorCreators) {
logger.fine("Trying connector creator type " + serviceConnectorCreator);
if (accept(serviceConnectorCreator, serviceConnectorType, serviceInfo)) {
return (ServiceConnectorCreator<SC, SI>) serviceConnectorCreator;
}
}
return null;
}
}

View File

@@ -28,78 +28,78 @@ import org.springframework.cloud.util.ServiceLoaderWithExceptionControl;
*
*/
public class CloudFactory {
private List<CloudConnector> cloudConnectors = new ArrayList<CloudConnector>();
private List<ServiceConnectorCreator<?, ? extends ServiceInfo>> serviceCreators = new ArrayList<ServiceConnectorCreator<?, ? extends ServiceInfo>>();
private List<CloudConnector> cloudConnectors = new ArrayList<CloudConnector>();
private List<ServiceConnectorCreator<?, ? extends ServiceInfo>> serviceCreators = new ArrayList<ServiceConnectorCreator<?, ? extends ServiceInfo>>();
public CloudFactory() {
scanCloudConnectors();
scanServiceConnectorCreators();
}
public CloudFactory() {
scanCloudConnectors();
scanServiceConnectorCreators();
}
/**
*
* @return a cloud suitable for the current environment
* @throws CloudException
* if no suitable cloud found
*/
public Cloud getCloud() {
CloudConnector suitableCloudConnector = null;
for (CloudConnector cloudConnector : cloudConnectors) {
if (cloudConnector.isInMatchingCloud()) {
suitableCloudConnector = cloudConnector;
break;
}
}
/**
*
* @return a cloud suitable for the current environment
* @throws CloudException
* if no suitable cloud found
*/
public Cloud getCloud() {
CloudConnector suitableCloudConnector = null;
for (CloudConnector cloudConnector : cloudConnectors) {
if (cloudConnector.isInMatchingCloud()) {
suitableCloudConnector = cloudConnector;
break;
}
}
if (suitableCloudConnector == null) {
throw new CloudException("No suitable cloud connector found");
}
if (suitableCloudConnector == null) {
throw new CloudException("No suitable cloud connector found");
}
return new Cloud(suitableCloudConnector, serviceCreators);
}
return new Cloud(suitableCloudConnector, serviceCreators);
}
/**
* Register a cloud connector.
*
* <p>
* CloudConnector developers should prefer the declarative mechanism described in README.MD instead of calling this method.
* </p>
*
* @param cloudConnector
* the cloud connector to register for discovery
*/
public void registerCloudConnector(CloudConnector cloudConnector) {
cloudConnectors.add(cloudConnector);
}
/**
* Register a cloud connector.
*
* <p>
* CloudConnector developers should prefer the declarative mechanism described in README.MD instead of calling this method.
* </p>
*
* @param cloudConnector
* the cloud connector to register for discovery
*/
public void registerCloudConnector(CloudConnector cloudConnector) {
cloudConnectors.add(cloudConnector);
}
/* package access for testing */
List<CloudConnector> getCloudConnectors() {
return cloudConnectors;
}
/* package access for testing */
List<CloudConnector> getCloudConnectors() {
return cloudConnectors;
}
/* package access for testing */
List<ServiceConnectorCreator<?, ? extends ServiceInfo>> getServiceCreators() {
return serviceCreators;
}
/* package access for testing */
List<ServiceConnectorCreator<?, ? extends ServiceInfo>> getServiceCreators() {
return serviceCreators;
}
private void registerServiceCreator(ServiceConnectorCreator<?, ? extends ServiceInfo> serviceConnectorCreator) {
serviceCreators.add(serviceConnectorCreator);
}
private void registerServiceCreator(ServiceConnectorCreator<?, ? extends ServiceInfo> serviceConnectorCreator) {
serviceCreators.add(serviceConnectorCreator);
}
private void scanCloudConnectors() {
Iterable<CloudConnector> loader = ServiceLoader.load(CloudConnector.class);
for (CloudConnector cloudConnector : loader) {
registerCloudConnector(cloudConnector);
}
}
private void scanCloudConnectors() {
Iterable<CloudConnector> loader = ServiceLoader.load(CloudConnector.class);
for (CloudConnector cloudConnector : loader) {
registerCloudConnector(cloudConnector);
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void scanServiceConnectorCreators() {
Iterable<ServiceConnectorCreator> loader = ServiceLoaderWithExceptionControl.load(ServiceConnectorCreator.class);
for (ServiceConnectorCreator serviceConnectorCreator : loader) {
if (serviceConnectorCreator != null) {
registerServiceCreator(serviceConnectorCreator);
}
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void scanServiceConnectorCreators() {
Iterable<ServiceConnectorCreator> loader = ServiceLoaderWithExceptionControl.load(ServiceConnectorCreator.class);
for (ServiceConnectorCreator serviceConnectorCreator : loader) {
if (serviceConnectorCreator != null) {
registerServiceCreator(serviceConnectorCreator);
}
}
}
}

View File

@@ -11,20 +11,17 @@ import org.springframework.cloud.service.ServiceInfo;
* for it isn't placed properly to be picked up by scanning. By having a fallback mechanism, we can
* extract as much info from the service data as possible (minimally, the service id) and issue a warning.
*
* @param <SI> the type of {@link ServiceInfo} that this fallback creator will return
* @param <SD> the type of service definition data that this creator will consume
* @author Ramnivas Laddad
*
* @param <SI>
* the type of {@link ServiceInfo} that this fallback creator will return
* @param <SD>
* the type of service definition data that this creator will consume
*/
public abstract class FallbackServiceInfoCreator<SI extends ServiceInfo, SD> implements ServiceInfoCreator<SI, SD> {
/*
* Override to ensure that it accepts all service data
*/
@Override
public final boolean accept(SD serviceData) {
return true;
}
/*
* Override to ensure that it accepts all service data
*/
@Override
public final boolean accept(SD serviceData) {
return true;
}
}

View File

@@ -10,16 +10,16 @@ import java.util.List;
*
*/
public class BaseCompositeServiceInfo extends BaseServiceInfo implements CompositeServiceInfo {
private List<ServiceInfo> constituents;
public BaseCompositeServiceInfo(String id, ServiceInfo... constituents) {
super(id);
this.constituents = Arrays.asList(constituents);
}
private List<ServiceInfo> constituents;
@Override
public List<ServiceInfo> getServiceInfos() {
return constituents;
}
public BaseCompositeServiceInfo(String id, ServiceInfo... constituents) {
super(id);
this.constituents = Arrays.asList(constituents);
}
@Override
public List<ServiceInfo> getServiceInfos() {
return constituents;
}
}

View File

@@ -19,6 +19,6 @@ import org.springframework.cloud.Cloud;
*/
public interface CompositeServiceInfo extends ServiceInfo {
List<ServiceInfo> getServiceInfos();
List<ServiceInfo> getServiceInfos();
}

View File

@@ -3,8 +3,8 @@ package org.springframework.cloud.service;
import org.springframework.cloud.FallbackServiceInfoCreator;
public class FallbackBaseServiceInfoCreator extends FallbackServiceInfoCreator<BaseServiceInfo, UriBasedServiceData> {
@Override
public BaseServiceInfo createServiceInfo(UriBasedServiceData serviceData) {
return new BaseServiceInfo(serviceData.getKey());
}
@Override
public BaseServiceInfo createServiceInfo(UriBasedServiceData serviceData) {
return new BaseServiceInfo(serviceData.getKey());
}
}

View File

@@ -8,35 +8,31 @@ import org.springframework.cloud.service.common.MysqlServiceInfo;
*
* @author Ramnivas Laddad
*
* @param <SC>
* service connector type
* @param <SI>
* service info type
* @param <SC> service connector type
* @param <SI> service info type
*/
public interface ServiceConnectorCreator<SC, SI extends ServiceInfo> {
/**
* Create service for the given service info and configured with the given
* configuration
*
* @param serviceInfo
* the {@link ServiceInfo} object containing the information necessary to connect to the service
* @param serviceConnectorConfig
* configuration information to be applied to the connection
* @return service connector
*/
SC create(SI serviceInfo, ServiceConnectorConfig serviceConnectorConfig);
/**
* Create service for the given service info and configured with the given
* configuration
*
* @param serviceInfo the {@link ServiceInfo} object containing the information necessary to connect to the service
* @param serviceConnectorConfig configuration information to be applied to the connection
* @return service connector
*/
SC create(SI serviceInfo, ServiceConnectorConfig serviceConnectorConfig);
/**
* Get the type of connector created (such as {@link DataSource})
*
* @return service connector type
*/
Class<SC> getServiceConnectorType();
/**
* Get the type of connector created (such as {@link DataSource})
*
* @return service connector type
*/
Class<SC> getServiceConnectorType();
/**
* Get the service info type this creator can work with (such as {@link MysqlServiceInfo})
*
* @return service info type
*/
Class<?> getServiceInfoType();
/**
* Get the service info type this creator can work with (such as {@link MysqlServiceInfo})
*
* @return service info type
*/
Class<?> getServiceInfoType();
}

View File

@@ -11,7 +11,7 @@ import org.springframework.cloud.service.ServiceInfo.ServiceLabel;
@ServiceLabel("mongo")
public class MongoServiceInfo extends UriBasedServiceInfo {
public static final String MONGODB_SCHEME = "mongodb";
public static final String MONGODB_SCHEME = "mongodb";
public MongoServiceInfo(String id, String host, int port, String username, String password, String db) {
super(id, MONGODB_SCHEME, host, port, username, password, db);

View File

@@ -10,11 +10,11 @@ import org.springframework.cloud.service.ServiceInfo.ServiceLabel;
@ServiceLabel("mysql")
public class MysqlServiceInfo extends RelationalServiceInfo {
private static final String JDBC_URL_TYPE = "mysql";
private static final String JDBC_URL_TYPE = "mysql";
public static final String MYSQL_SCHEME = JDBC_URL_TYPE;
public static final String MYSQL_SCHEME = JDBC_URL_TYPE;
public MysqlServiceInfo(String id, String url) {
super(id, url, MYSQL_SCHEME);
}
public MysqlServiceInfo(String id, String url) {
super(id, url, MYSQL_SCHEME);
}
}

View File

@@ -5,9 +5,9 @@ import org.springframework.cloud.service.ServiceInfo;
@ServiceInfo.ServiceLabel("oracle")
public class OracleServiceInfo extends RelationalServiceInfo {
private static final String JDBC_URL_TYPE = "oracle";
private static final String JDBC_URL_TYPE = "oracle";
public static final String ORACLE_SCHEME = JDBC_URL_TYPE;
public static final String ORACLE_SCHEME = JDBC_URL_TYPE;
public OracleServiceInfo(String id, String url) {
super(id, url, JDBC_URL_TYPE);

View File

@@ -11,9 +11,9 @@ import org.springframework.cloud.service.ServiceInfo.ServiceLabel;
@ServiceLabel("postgresql")
public class PostgresqlServiceInfo extends RelationalServiceInfo {
private static final String JDBC_URL_TYPE = "postgresql";
private static final String JDBC_URL_TYPE = "postgresql";
public static final String POSTGRES_SCHEME = "postgres";
public static final String POSTGRES_SCHEME = "postgres";
public PostgresqlServiceInfo(String id, String url) {
super(id, url, JDBC_URL_TYPE);

View File

@@ -11,13 +11,13 @@ import org.springframework.cloud.service.ServiceInfo.ServiceLabel;
@ServiceLabel("redis")
public class RedisServiceInfo extends UriBasedServiceInfo {
public static final String REDIS_SCHEME = "redis";
public static final String REDIS_SCHEME = "redis";
public RedisServiceInfo(String id, String host, int port, String password) {
super(id, REDIS_SCHEME, host, port, null, password, null);
}
public RedisServiceInfo(String id, String uri) {
super(id, uri);
}
super(id, uri);
}
}

View File

@@ -20,56 +20,55 @@ import org.springframework.cloud.service.ServiceConnectorCreator;
*
* @author Ramnivas Laddad
*
* @param <T>
* the type of the service being loaded
* @param <T> the type of the service being loaded
*/
public class ServiceLoaderWithExceptionControl<T> implements Iterable<T> {
private Iterable<T> underlying;
private Iterable<T> underlying;
private static Logger logger = Logger.getLogger(ServiceLoaderWithExceptionControl.class.getName());
private static Logger logger = Logger.getLogger(ServiceLoaderWithExceptionControl.class.getName());
public static <T> Iterable<T> load(Class<T> serviceType) {
ServiceLoader<T> loader = ServiceLoader.load(serviceType);
return new ServiceLoaderWithExceptionControl<T>(loader);
}
public static <T> Iterable<T> load(Class<T> serviceType) {
ServiceLoader<T> loader = ServiceLoader.load(serviceType);
return new ServiceLoaderWithExceptionControl<T>(loader);
}
private ServiceLoaderWithExceptionControl(Iterable<T> underlying) {
this.underlying = underlying;
}
private ServiceLoaderWithExceptionControl(Iterable<T> underlying) {
this.underlying = underlying;
}
@Override
public Iterator<T> iterator() {
return new ServiceLoaderIterator(underlying.iterator());
}
@Override
public Iterator<T> iterator() {
return new ServiceLoaderIterator(underlying.iterator());
}
private class ServiceLoaderIterator implements Iterator<T> {
private Iterator<T> underlying;
private class ServiceLoaderIterator implements Iterator<T> {
private Iterator<T> underlying;
public ServiceLoaderIterator(Iterator<T> underlying) {
this.underlying = underlying;
}
public ServiceLoaderIterator(Iterator<T> underlying) {
this.underlying = underlying;
}
@Override
public boolean hasNext() {
return underlying.hasNext();
}
@Override
public boolean hasNext() {
return underlying.hasNext();
}
@Override
public T next() {
try {
return underlying.next();
} catch (ServiceConfigurationError e) {
logger.log(Level.CONFIG, "Failed to load " + e);
if (hasNext()) {
return next();
}
}
return null;
}
@Override
public T next() {
try {
return underlying.next();
} catch (ServiceConfigurationError e) {
logger.log(Level.CONFIG, "Failed to load " + e);
if (hasNext()) {
return next();
}
}
return null;
}
@Override
public void remove() {
underlying.remove();
}
}
@Override
public void remove() {
underlying.remove();
}
}
}

View File

@@ -18,8 +18,8 @@ public class AmqpServiceInfoCreator extends HerokuServiceInfoCreator<AmqpService
return new AmqpServiceInfo(HerokuUtil.computeServiceName(id), uri);
}
@Override
public String[] getEnvPrefixes() {
return new String[]{ "CLOUDAMQP_URL" };
}
@Override
public String[] getEnvPrefixes() {
return new String[]{ "CLOUDAMQP_URL" };
}
}

View File

@@ -1,15 +1,15 @@
package org.springframework.cloud.heroku;
public class HerokuUtil {
public static String computeServiceName(String envVar) {
String[] stripSuffices = new String[]{"_URL", "_URI"};
for (String suffix: stripSuffices) {
if (envVar.endsWith(suffix)) {
return envVar.substring(0, envVar.length() - suffix.length());
}
}
return envVar;
}
public static String computeServiceName(String envVar) {
String[] stripSuffices = new String[]{"_URL", "_URI"};
for (String suffix: stripSuffices) {
if (envVar.endsWith(suffix)) {
return envVar.substring(0, envVar.length() - suffix.length());
}
}
return envVar;
}
}

View File

@@ -18,8 +18,8 @@ public class MongoServiceInfoCreator extends HerokuServiceInfoCreator<MongoServi
return new MongoServiceInfo(HerokuUtil.computeServiceName(id), uri);
}
@Override
public String[] getEnvPrefixes() {
return new String[]{ "MONGOLAB_URI", "MONGOHQ_URL", "MONGOSOUP_URL" };
}
@Override
public String[] getEnvPrefixes() {
return new String[]{ "MONGOLAB_URI", "MONGOHQ_URL", "MONGOSOUP_URL" };
}
}

View File

@@ -18,8 +18,8 @@ public class MysqlServiceInfoCreator extends RelationalServiceInfoCreator<MysqlS
return new MysqlServiceInfo(HerokuUtil.computeServiceName(id), uri);
}
@Override
public String[] getEnvPrefixes() {
return new String[]{"CLEARDB_DATABASE_URL"};
}
@Override
public String[] getEnvPrefixes() {
return new String[]{"CLEARDB_DATABASE_URL"};
}
}

View File

@@ -18,8 +18,8 @@ public class PostgresqlServiceInfoCreator extends RelationalServiceInfoCreator<P
return new PostgresqlServiceInfo(HerokuUtil.computeServiceName(id), uri);
}
@Override
public String[] getEnvPrefixes() {
return new String[]{"HEROKU_POSTGRESQL_"};
}
@Override
public String[] getEnvPrefixes() {
return new String[]{"HEROKU_POSTGRESQL_"};
}
}

View File

@@ -18,8 +18,8 @@ public class RedisServiceInfoCreator extends HerokuServiceInfoCreator<RedisServi
return new RedisServiceInfo(HerokuUtil.computeServiceName(id), uri);
}
@Override
public String[] getEnvPrefixes() {
return new String[]{ "REDISTOGO_URL", "REDISCLOUD_URL", "OPENREDIS_URL", "REDISGREEN_URL" };
}
@Override
public String[] getEnvPrefixes() {
return new String[]{ "REDISTOGO_URL", "REDISCLOUD_URL", "OPENREDIS_URL", "REDISGREEN_URL" };
}
}

View File

@@ -5,43 +5,41 @@ import static org.junit.Assert.assertEquals;
import org.springframework.cloud.service.common.RelationalServiceInfo;
/**
*
* @author Ramnivas Laddad
*
*/
public abstract class AbstractHerokuConnectorRelationalServiceTest extends AbstractHerokuConnectorTest {
private String databaseType;
private String databaseType;
public AbstractHerokuConnectorRelationalServiceTest(String databaseType) {
this.databaseType = databaseType;
}
public AbstractHerokuConnectorRelationalServiceTest(String databaseType) {
this.databaseType = databaseType;
}
protected String getJdbcUrl(String name) {
String jdbcUrlDatabaseType = databaseType;
if (databaseType.equals("postgres")) {
jdbcUrlDatabaseType = "postgresql";
}
return "jdbc:" + jdbcUrlDatabaseType + "://" + hostname + ":" + port + "/" + name +
"?user=" + username + "&password=" + password;
return "jdbc:" + jdbcUrlDatabaseType + "://" + hostname + ":" + port + "/" + name +
"?user=" + username + "&password=" + password;
}
protected String getRelationalServiceUrl(String name) {
String template = "$databaseType://$username:$password@$host:$port/$database";
protected String getRelationalServiceUrl(String name) {
String template = "$databaseType://$username:$password@$host:$port/$database";
return template.replace("$databaseType", databaseType).
replace("$username", username).
replace("$password", password).
replace("$host", hostname).
replace("$port", Integer.toString(port)).
replace("$database", name);
}
protected void assertReleationServiceInfo(RelationalServiceInfo serviceInfo, String databaseName) {
assertEquals(hostname, serviceInfo.getHost());
assertEquals(port, serviceInfo.getPort());
assertEquals(username, serviceInfo.getUserName());
assertEquals(password, serviceInfo.getPassword());
assertEquals(getJdbcUrl(databaseName), serviceInfo.getJdbcUrl());
}
return template.replace("$databaseType", databaseType).
replace("$username", username).
replace("$password", password).
replace("$host", hostname).
replace("$port", Integer.toString(port)).
replace("$database", name);
}
protected void assertReleationServiceInfo(RelationalServiceInfo serviceInfo, String databaseName) {
assertEquals(hostname, serviceInfo.getHost());
assertEquals(port, serviceInfo.getPort());
assertEquals(username, serviceInfo.getUserName());
assertEquals(password, serviceInfo.getPassword());
assertEquals(getJdbcUrl(databaseName), serviceInfo.getJdbcUrl());
}
}

View File

@@ -12,11 +12,11 @@ import org.springframework.cloud.util.EnvironmentAccessor;
* Base test class that provides setup and utility methods to generate test payload
*
* @author Ramnivas Laddad
*
*/
public abstract class AbstractHerokuConnectorTest {
protected HerokuConnector testCloudConnector = new HerokuConnector();
@Mock protected EnvironmentAccessor mockEnvironment;
@Mock
protected EnvironmentAccessor mockEnvironment;
protected static final String hostname = "10.20.30.40";
protected static final int port = 1234;

View File

@@ -14,43 +14,41 @@ import org.springframework.cloud.service.ServiceInfo;
import org.springframework.cloud.service.common.AmqpServiceInfo;
/**
*
* @author Ramnivas Laddad
*
*/
public class HerokuConnectorAmqpServiceTest extends AbstractHerokuConnectorTest {
@Test
public void amqpServiceCreation() {
Map<String, String> env = new HashMap<String, String>();
String amqpUrl = getAmqpServiceUrl("db");
env.put("CLOUDAMQP_URL", amqpUrl);
when(mockEnvironment.getEnv()).thenReturn(env);
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
ServiceInfo serviceInfo = getServiceInfo(serviceInfos, "CLOUDAMQP");
assertNotNull(serviceInfo);
assertTrue(serviceInfo instanceof AmqpServiceInfo);
assertAmqpServiceInfo((AmqpServiceInfo)serviceInfo, "db");
}
private String getAmqpServiceUrl(String name) {
String template = "amqp://$username:$password@$hostname:$port/$virtualHost";
@Test
public void amqpServiceCreation() {
Map<String, String> env = new HashMap<String, String>();
String amqpUrl = getAmqpServiceUrl("db");
env.put("CLOUDAMQP_URL", amqpUrl);
when(mockEnvironment.getEnv()).thenReturn(env);
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
ServiceInfo serviceInfo = getServiceInfo(serviceInfos, "CLOUDAMQP");
assertNotNull(serviceInfo);
assertTrue(serviceInfo instanceof AmqpServiceInfo);
assertAmqpServiceInfo((AmqpServiceInfo) serviceInfo, "db");
}
private String getAmqpServiceUrl(String name) {
String template = "amqp://$username:$password@$hostname:$port/$virtualHost";
return template.replace("$username", username).
replace("$password", password).
replace("$hostname", hostname).
replace("$port", Integer.toString(port)).
replace("$virtualHost", name);
}
protected void assertAmqpServiceInfo(AmqpServiceInfo serviceInfo, String virtualHost) {
assertEquals(hostname, serviceInfo.getHost());
assertEquals(port, serviceInfo.getPort());
assertEquals(username, serviceInfo.getUserName());
assertEquals(password, serviceInfo.getPassword());
assertEquals(virtualHost, serviceInfo.getPath());
}
return template.replace("$username", username).
replace("$password", password).
replace("$hostname", hostname).
replace("$port", Integer.toString(port)).
replace("$virtualHost", name);
}
protected void assertAmqpServiceInfo(AmqpServiceInfo serviceInfo, String virtualHost) {
assertEquals(hostname, serviceInfo.getHost());
assertEquals(port, serviceInfo.getPort());
assertEquals(username, serviceInfo.getUserName());
assertEquals(password, serviceInfo.getPassword());
assertEquals(virtualHost, serviceInfo.getPath());
}
}

View File

@@ -10,35 +10,33 @@ import java.util.Map;
import org.junit.Test;
/**
*
* @author Ramnivas Laddad
*
*/
public class HerokuConnectorApplicationTest extends AbstractHerokuConnectorTest {
@Test
@Test
public void isInMatchingEnvironment() {
when(mockEnvironment.getEnvValue("DYNO")).thenReturn("web.1");
assertTrue(testCloudConnector.isInMatchingCloud());
when(mockEnvironment.getEnvValue("DYNO")).thenReturn(null);
assertFalse(testCloudConnector.isInMatchingCloud());
}
@Test
public void applicationInstanceInfo() {
when(mockEnvironment.getEnvValue("SPRING_CLOUD_APP_NAME")).thenReturn("myapp");
when(mockEnvironment.getEnvValue("DYNO")).thenReturn("web.1");
when(mockEnvironment.getEnvValue("PORT")).thenReturn(Integer.toString(port));
when(mockEnvironment.getHost()).thenReturn(hostname);
assertEquals("myapp", testCloudConnector.getApplicationInstanceInfo().getAppId());
assertEquals("web.1", testCloudConnector.getApplicationInstanceInfo().getInstanceId());
Map<String,Object> appProps = testCloudConnector.getApplicationInstanceInfo().getProperties();
Map<String, Object> appProps = testCloudConnector.getApplicationInstanceInfo().getProperties();
assertEquals(hostname, appProps.get("host"));
assertEquals(Integer.toString(port), appProps.get("port"));
}
@Test
public void applicationInstanceInfoNoSpringCloudAppName() {
when(mockEnvironment.getEnvValue("DYNO")).thenReturn("web.1");

View File

@@ -14,45 +14,43 @@ import org.springframework.cloud.service.ServiceInfo;
import org.springframework.cloud.service.common.MongoServiceInfo;
/**
*
* @author Ramnivas Laddad
*
*/
public class HerokuConnectorMongoServiceTest extends AbstractHerokuConnectorTest {
@Test
public void mongoServiceCreation() {
for (String mongoEnv: new String[]{"MONGOLAB_URI", "MONGOHQ_URL", "MONGOSOUP_URL"}) {
Map<String, String> env = new HashMap<String, String>();
String mongoUrl = getMongoServiceUrl("db");
env.put(mongoEnv, mongoUrl);
when(mockEnvironment.getEnv()).thenReturn(env);
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
ServiceInfo serviceInfo = getServiceInfo(serviceInfos, mongoEnv.substring(0, mongoEnv.length()-4));
assertNotNull(serviceInfo);
assertTrue(serviceInfo instanceof MongoServiceInfo);
assertMongoServiceInfo((MongoServiceInfo)serviceInfo, "db");
}
}
private String getMongoServiceUrl(String name) {
String template = "mongodb://$username:$password@$hostname:$port/$db";
return template.replace("$username", username).
replace("$password", password).
replace("$hostname", hostname).
replace("$port", Integer.toString(port)).
replace("$db", name);
}
protected void assertMongoServiceInfo(MongoServiceInfo serviceInfo, String databaseName) {
assertEquals(hostname, serviceInfo.getHost());
assertEquals(port, serviceInfo.getPort());
assertEquals(username, serviceInfo.getUserName());
assertEquals(password, serviceInfo.getPassword());
assertEquals(databaseName, serviceInfo.getPath());
}
@Test
public void mongoServiceCreation() {
for (String mongoEnv : new String[]{"MONGOLAB_URI", "MONGOHQ_URL", "MONGOSOUP_URL"}) {
Map<String, String> env = new HashMap<String, String>();
String mongoUrl = getMongoServiceUrl("db");
env.put(mongoEnv, mongoUrl);
when(mockEnvironment.getEnv()).thenReturn(env);
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
ServiceInfo serviceInfo = getServiceInfo(serviceInfos, mongoEnv.substring(0, mongoEnv.length() - 4));
assertNotNull(serviceInfo);
assertTrue(serviceInfo instanceof MongoServiceInfo);
assertMongoServiceInfo((MongoServiceInfo) serviceInfo, "db");
}
}
private String getMongoServiceUrl(String name) {
String template = "mongodb://$username:$password@$hostname:$port/$db";
return template.replace("$username", username).
replace("$password", password).
replace("$hostname", hostname).
replace("$port", Integer.toString(port)).
replace("$db", name);
}
protected void assertMongoServiceInfo(MongoServiceInfo serviceInfo, String databaseName) {
assertEquals(hostname, serviceInfo.getHost());
assertEquals(port, serviceInfo.getPort());
assertEquals(username, serviceInfo.getUserName());
assertEquals(password, serviceInfo.getPassword());
assertEquals(databaseName, serviceInfo.getPath());
}
}

View File

@@ -13,26 +13,24 @@ import org.springframework.cloud.service.ServiceInfo;
import org.springframework.cloud.service.common.MysqlServiceInfo;
/**
*
* @author Ramnivas Laddad
*
*/
public class HerokuConnectorMysqlServiceTest extends AbstractHerokuConnectorRelationalServiceTest {
public HerokuConnectorMysqlServiceTest() {
super(MysqlServiceInfo.MYSQL_SCHEME);
}
public HerokuConnectorMysqlServiceTest() {
super(MysqlServiceInfo.MYSQL_SCHEME);
}
@Test
public void mysqlServiceCreation() {
Map<String, String> env = new HashMap<String, String>();
String mysqlUrl = getRelationalServiceUrl("db");
env.put("CLEARDB_DATABASE_URL", mysqlUrl);
when(mockEnvironment.getEnv()).thenReturn(env);
@Test
public void mysqlServiceCreation() {
Map<String, String> env = new HashMap<String, String>();
String mysqlUrl = getRelationalServiceUrl("db");
env.put("CLEARDB_DATABASE_URL", mysqlUrl);
when(mockEnvironment.getEnv()).thenReturn(env);
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
ServiceInfo serviceInfo = getServiceInfo(serviceInfos, "CLEARDB_DATABASE");
assertNotNull(serviceInfo);
assertTrue(serviceInfo instanceof MysqlServiceInfo);
assertReleationServiceInfo((MysqlServiceInfo)serviceInfo, "db");
}
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
ServiceInfo serviceInfo = getServiceInfo(serviceInfos, "CLEARDB_DATABASE");
assertNotNull(serviceInfo);
assertTrue(serviceInfo instanceof MysqlServiceInfo);
assertReleationServiceInfo((MysqlServiceInfo) serviceInfo, "db");
}
}

View File

@@ -13,26 +13,24 @@ import org.springframework.cloud.service.ServiceInfo;
import org.springframework.cloud.service.common.PostgresqlServiceInfo;
/**
*
* @author Ramnivas Laddad
*
*/
public class HerokuConnectorPostgresqlServiceTest extends AbstractHerokuConnectorRelationalServiceTest {
public HerokuConnectorPostgresqlServiceTest() {
super(PostgresqlServiceInfo.POSTGRES_SCHEME);
}
public HerokuConnectorPostgresqlServiceTest() {
super(PostgresqlServiceInfo.POSTGRES_SCHEME);
}
@Test
public void postgresqlServiceCreation() {
Map<String, String> env = new HashMap<String, String>();
String postgresUrl = getRelationalServiceUrl("db");
env.put("HEROKU_POSTGRESQL_YELLOW_URL", postgresUrl);
when(mockEnvironment.getEnv()).thenReturn(env);
@Test
public void postgresqlServiceCreation() {
Map<String, String> env = new HashMap<String, String>();
String postgresUrl = getRelationalServiceUrl("db");
env.put("HEROKU_POSTGRESQL_YELLOW_URL", postgresUrl);
when(mockEnvironment.getEnv()).thenReturn(env);
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
ServiceInfo serviceInfo = getServiceInfo(serviceInfos, "HEROKU_POSTGRESQL_YELLOW");
assertNotNull(serviceInfo);
assertTrue(serviceInfo instanceof PostgresqlServiceInfo);
assertReleationServiceInfo((PostgresqlServiceInfo)serviceInfo, "db");
}
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
ServiceInfo serviceInfo = getServiceInfo(serviceInfos, "HEROKU_POSTGRESQL_YELLOW");
assertNotNull(serviceInfo);
assertTrue(serviceInfo instanceof PostgresqlServiceInfo);
assertReleationServiceInfo((PostgresqlServiceInfo) serviceInfo, "db");
}
}

View File

@@ -14,42 +14,40 @@ import org.springframework.cloud.service.ServiceInfo;
import org.springframework.cloud.service.common.RedisServiceInfo;
/**
*
* @author Ramnivas Laddad
*
*/
public class HerokuConnectorRedisServiceTest extends AbstractHerokuConnectorTest {
@Test
public void redisServiceCreation() {
for (String redisEnv: new String[]{"REDISTOGO_URL", "REDISCLOUD_URL", "OPENREDIS_URL", "REDISGREEN_URL"}) {
Map<String, String> env = new HashMap<String, String>();
String redisUrl = getRedisServiceUrl();
env.put(redisEnv, redisUrl);
when(mockEnvironment.getEnv()).thenReturn(env);
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
ServiceInfo serviceInfo = getServiceInfo(serviceInfos, redisEnv.substring(0, redisEnv.length()-4));
assertNotNull(serviceInfo);
assertTrue(serviceInfo instanceof RedisServiceInfo);
assertRedisServiceInfo((RedisServiceInfo)serviceInfo);
}
}
private String getRedisServiceUrl() {
String template = "redis://$username:$password@$hostname:$port";
@Test
public void redisServiceCreation() {
for (String redisEnv : new String[]{"REDISTOGO_URL", "REDISCLOUD_URL", "OPENREDIS_URL", "REDISGREEN_URL"}) {
Map<String, String> env = new HashMap<String, String>();
String redisUrl = getRedisServiceUrl();
env.put(redisEnv, redisUrl);
when(mockEnvironment.getEnv()).thenReturn(env);
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
ServiceInfo serviceInfo = getServiceInfo(serviceInfos, redisEnv.substring(0, redisEnv.length() - 4));
assertNotNull(serviceInfo);
assertTrue(serviceInfo instanceof RedisServiceInfo);
assertRedisServiceInfo((RedisServiceInfo) serviceInfo);
}
}
private String getRedisServiceUrl() {
String template = "redis://$username:$password@$hostname:$port";
return template.replace("$username", username).
replace("$password", password).
replace("$hostname", hostname).
replace("$port", Integer.toString(port));
}
protected void assertRedisServiceInfo(RedisServiceInfo serviceInfo) {
assertEquals(hostname, serviceInfo.getHost());
assertEquals(port, serviceInfo.getPort());
assertEquals(username, serviceInfo.getUserName());
assertEquals(password, serviceInfo.getPassword());
}
return template.replace("$username", username).
replace("$password", password).
replace("$hostname", hostname).
replace("$port", Integer.toString(port));
}
protected void assertRedisServiceInfo(RedisServiceInfo serviceInfo) {
assertEquals(hostname, serviceInfo.getHost());
assertEquals(port, serviceInfo.getPort());
assertEquals(username, serviceInfo.getUserName());
assertEquals(password, serviceInfo.getPassword());
}
}

View File

@@ -15,21 +15,21 @@ import org.springframework.cloud.service.common.RelationalServiceInfo;
*/
public class BasicDbcpPooledDataSourceCreator<SI extends RelationalServiceInfo> extends DbcpLikePooledDataSourceCreator<SI> {
@Override
public DataSource create(RelationalServiceInfo serviceInfo, ServiceConnectorConfig serviceConnectorConfig,
String driverClassName, String validationQuery) {
if (hasClass("org.apache.commons.dbcp2.BasicDataSource")) {
logger.info("Found DBCP2 on the classpath. Using it for DataSource connection pooling.");
org.apache.commons.dbcp2.BasicDataSource ds = new org.apache.commons.dbcp2.BasicDataSource();
setBasicDataSourceProperties(ds, serviceInfo, serviceConnectorConfig, driverClassName, validationQuery);
return ds;
} else if (hasClass("org.apache.commons.dbcp.BasicDataSource")) {
logger.info("Found DBCP on the classpath. Using it for DataSource connection pooling.");
org.apache.commons.dbcp.BasicDataSource ds = new org.apache.commons.dbcp.BasicDataSource();
setBasicDataSourceProperties(ds, serviceInfo, serviceConnectorConfig, driverClassName, validationQuery);
return ds;
} else {
return null;
}
}
@Override
public DataSource create(RelationalServiceInfo serviceInfo, ServiceConnectorConfig serviceConnectorConfig,
String driverClassName, String validationQuery) {
if (hasClass("org.apache.commons.dbcp2.BasicDataSource")) {
logger.info("Found DBCP2 on the classpath. Using it for DataSource connection pooling.");
org.apache.commons.dbcp2.BasicDataSource ds = new org.apache.commons.dbcp2.BasicDataSource();
setBasicDataSourceProperties(ds, serviceInfo, serviceConnectorConfig, driverClassName, validationQuery);
return ds;
} else if (hasClass("org.apache.commons.dbcp.BasicDataSource")) {
logger.info("Found DBCP on the classpath. Using it for DataSource connection pooling.");
org.apache.commons.dbcp.BasicDataSource ds = new org.apache.commons.dbcp.BasicDataSource();
setBasicDataSourceProperties(ds, serviceInfo, serviceConnectorConfig, driverClassName, validationQuery);
return ds;
} else {
return null;
}
}
}

View File

@@ -5,21 +5,21 @@ import static org.junit.Assert.assertEquals;
import org.springframework.test.util.ReflectionTestUtils;
public class CommonPoolCloudConfigTestHelper {
public static void assertCommonsPoolProperties(Object pool, int maxActive, int minIdle, long maxWait) {
assertEquals(maxActive, getValue(pool, "maxActive", "maxTotal"));
assertEquals(minIdle, getValue(pool, "minIdle"));
assertEquals(maxWait, getValue(pool, "maxWait", "maxWaitMillis"));
}
protected static Object getValue(Object object, String... fieldNames) {
for (String fieldName : fieldNames) {
try {
return ReflectionTestUtils.getField(object, fieldName);
} catch (IllegalArgumentException ex) {
}
}
return null;
}
public static void assertCommonsPoolProperties(Object pool, int maxActive, int minIdle, long maxWait) {
assertEquals(maxActive, getValue(pool, "maxActive", "maxTotal"));
assertEquals(minIdle, getValue(pool, "minIdle"));
assertEquals(maxWait, getValue(pool, "maxWait", "maxWaitMillis"));
}
protected static Object getValue(Object object, String... fieldNames) {
for (String fieldName : fieldNames) {
try {
return ReflectionTestUtils.getField(object, fieldName);
} catch (IllegalArgumentException ex) {
}
}
return null;
}
}

View File

@@ -21,11 +21,11 @@ public class CloudScanJavaConfigTest extends AbstractCloudConfigServiceScanTest
}
@Test
public void cloudScanIntroducesApplicationInstanceInfo() {
ApplicationContext testContext = getTestApplicationContext();
assertNotNull(testContext.getBean(ApplicationInstanceInfo.class));
}
public void cloudScanIntroducesApplicationInstanceInfo() {
ApplicationContext testContext = getTestApplicationContext();
assertNotNull(testContext.getBean(ApplicationInstanceInfo.class));
}
}
@Configuration

View File

@@ -7,8 +7,8 @@ package org.springframework.cloud.service.relational;
*
*/
public class MysqlServiceCreatorWithDefaultDriverTest extends MysqlServiceCreatorTest {
private static final String MYSQL_DRIVER_CLASS_NAME = "org.mariadb.jdbc.Driver";
private static final String MYSQL_DRIVER_CLASS_NAME = "org.mariadb.jdbc.Driver";
@Override
public String getDriverName() {
return MYSQL_DRIVER_CLASS_NAME;

View File

@@ -9,17 +9,17 @@ import org.junit.Before;
*
*/
public class MysqlServiceCreatorWithMysqlDriverTest extends MysqlServiceCreatorTest {
private static final String MYSQL_DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
private static final String MYSQL_DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
@Before
public void setup() {
super.setup();
System.setProperty("spring-cloud.mysql.driver", MYSQL_DRIVER_CLASS_NAME);
System.setProperty("spring-cloud.mysql.driver", MYSQL_DRIVER_CLASS_NAME);
}
@After
public void tearDown() {
System.setProperty("spring-cloud.mysql.driver", "");
System.setProperty("spring-cloud.mysql.driver", "");
}
@Override