package org.apereo.cas.support.geo.google; import com.google.maps.GaeRequestHandler; import com.google.maps.GeoApiContext; import com.google.maps.GeocodingApi; import com.google.maps.model.GeocodingResult; import com.google.maps.model.LatLng; import io.userinfo.client.UserInfo; import io.userinfo.client.model.Info; import org.apache.commons.lang3.StringUtils; import org.apereo.cas.authentication.adaptive.geo.GeoLocationResponse; import org.apereo.cas.configuration.model.support.geo.googlemaps.GoogleMapsProperties; import org.apereo.cas.support.geo.AbstractGeoLocationService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.InetAddress; import java.util.Arrays; import java.util.concurrent.TimeUnit; /** * This is {@link GoogleMapsGeoLocationService}. * * @author Misagh Moayyed * @since 5.0.0 */ public class GoogleMapsGeoLocationService extends AbstractGeoLocationService { private static final Logger LOGGER = LoggerFactory.getLogger(GoogleMapsGeoLocationService.class); private final GeoApiContext context; public GoogleMapsGeoLocationService(final GoogleMapsProperties properties) { if (properties.isGoogleAppsEngine()) { context = new GeoApiContext(new GaeRequestHandler()); } else { context = new GeoApiContext(); } if (StringUtils.isNotBlank(properties.getClientId()) && StringUtils.isNotBlank(properties.getClientSecret())) { context.setEnterpriseCredentials(properties.getClientId(), properties.getClientSecret()); } context.setApiKey(properties.getApiKey()); context.setConnectTimeout(properties.getConnectTimeout(), TimeUnit.MILLISECONDS); } @Override public GeoLocationResponse locate(final InetAddress address) { return locate(address.getHostAddress()); } @Override public GeoLocationResponse locate(final String address) { final Info info = UserInfo.getInfo(address); if (info != null && info.getPosition() != null) { return locate(info.getPosition().getLatitude(), info.getPosition().getLongitude()); } return null; } @Override public GeoLocationResponse locate(final Double latitude, final Double longitude) { if (latitude == null || longitude == null) { LOGGER.debug("latitude/longitude must not be null in order for geolocation to proceed"); return null; } final GeoLocationResponse r = new GeoLocationResponse(); r.setLatitude(latitude); r.setLongitude(longitude); final LatLng latlng = new LatLng(latitude, longitude); try { final GeocodingResult[] results = GeocodingApi.reverseGeocode(this.context, latlng).await(); if (results != null && results.length > 0) { Arrays.stream(results) .map(result -> result.formattedAddress) .forEach(r::addAddress); return r; } } catch (final Exception e) { LOGGER.error(e.getMessage(), e); } return r; } }