package org.springframework.cloud;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.logging.Logger;
import org.springframework.cloud.service.ServiceInfo;
/**
* Helper abstract class to simplify {@link CloudConnector} implementations.
*
* User the {@link ServiceLoader} approach to looks for file name matching the class passed in constructor
* and registers {@link ServiceInfoCreator} found there.
*
* Implementation of {@link CloudConnector}s that wish to support the recommended service scanning approach
* should extends this approach to gain that functionality automatically.
*
* @author Ramnivas Laddad
*
*/
public abstract class AbstractCloudConnector<SD> implements CloudConnector {
private static Logger logger = Logger.getLogger(AbstractCloudConnector.class.getName());
protected List<ServiceInfoCreator<?,SD>> serviceInfoCreators = new ArrayList<ServiceInfoCreator<?,SD>>();
protected abstract List<SD> getServicesData();
protected abstract FallbackServiceInfoCreator<?,SD> getFallbackServiceInfoCreator();
public AbstractCloudConnector(Class<? extends ServiceInfoCreator<? extends ServiceInfo, ?>> serviceInfoCreatorClass) {
scanServiceInfoCreators(serviceInfoCreatorClass);
}
@Override
public List<ServiceInfo> getServiceInfos() {
List<ServiceInfo> serviceInfos = new ArrayList<ServiceInfo>();
for (SD serviceData : getServicesData()) {
serviceInfos.add(getServiceInfo(serviceData));
}
return serviceInfos;
}
protected void registerServiceInfoCreator(ServiceInfoCreator<? extends ServiceInfo, SD> serviceInfoCreator) {
serviceInfoCreators.add(serviceInfoCreator);
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void scanServiceInfoCreators(Class<? extends ServiceInfoCreator<? extends ServiceInfo,?>> serviceInfoCreatorClass) {
ServiceLoader<? extends ServiceInfoCreator> serviceInfoCreators = ServiceLoader.load(serviceInfoCreatorClass);
for (ServiceInfoCreator<? extends ServiceInfo,SD> serviceInfoCreator : serviceInfoCreators) {
registerServiceInfoCreator(serviceInfoCreator);
}
}
private ServiceInfo getServiceInfo(SD serviceData) {
for (ServiceInfoCreator<? extends ServiceInfo,SD> serviceInfoCreator : serviceInfoCreators) {
if (serviceInfoCreator.accept(serviceData)) {
return serviceInfoCreator.createServiceInfo(serviceData);
}
}
// Fallback with a warning
ServiceInfo fallackServiceInfo = getFallbackServiceInfoCreator().createServiceInfo(serviceData);
logger.warning("No suitable service info creator found for service " + fallackServiceInfo.getId()
+ " Did you forget to add a ServiceInfoCreator?");
return fallackServiceInfo;
}
}