social-networking-library-ws/src/main/java/org/gcube/portal/social/networking/caches/SocialNetworkingSiteFinder....

249 lines
8.5 KiB
Java

package org.gcube.portal.social.networking.caches;
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite;
import org.gcube.common.portal.GCubePortalConstants;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import org.gcube.smartgears.ContextProvider;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.model.GCubeGroup;
import org.gcube.vomanagement.usermanagement.model.VirtualGroup;
import org.slf4j.LoggerFactory;
/**
* When a notification needs to be sent, this class offers utility to discover (starting from the scope)
* the site information needed to build up the SocialNetworkingSite object (which, for instance, contains the
* portal email).
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class SocialNetworkingSiteFinder {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SocialNetworkingSiteFinder.class);
private static final String EMAIL_SENDER_SITE_CUSTOM_FIELD = "Emailsender";
private static final String CATEGORY = "Portal";
// these properties could be overwritten by the ones read from config.properties
private static String PROD_FALLBACK_GATEWAY = "D4Science.org Gateway";
private static String DEV_FALLBACK_GATEWAY = "gCube Dev4 Snapshot Gateway";
private static String PREPROD_FALLBACK_GATEWAY = "gCube Preprod (dev) Gateway";
/**
* Singleton object
*/
private static SocialNetworkingSiteFinder singleton = new SocialNetworkingSiteFinder();
/**
* Build the singleton instance
*/
private SocialNetworkingSiteFinder(){
// read fallback properties
try{
logger.info("Trying to read config.properties");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("config.properties");
Properties properties = new Properties();
properties.load(input);
PROD_FALLBACK_GATEWAY = properties.getProperty("PROD_FALLBACK_GATEWAY");
DEV_FALLBACK_GATEWAY = properties.getProperty("DEV_FALLBACK_GATEWAY");
PREPROD_FALLBACK_GATEWAY = properties.getProperty("PREPROD_FALLBACK_GATEWAY");
}catch(Exception e){
logger.warn("Failed to read config.properties...", e);
}
}
/**
* Retrieve the singleton instance
*/
public static SocialNetworkingSiteFinder getInstance(){
return singleton;
}
/**
* Retrieve the SocialNetworkingSite given the scope
* @param scope
* @return
*/
public static SocialNetworkingSite getSocialNetworkingSiteFromScope(String scope){
Ehcache socialSitesCache = CachesManager.getCache(CachesManager.SOCIAL_NETWORKING_SITES_CACHE);
if(scope == null || scope.isEmpty())
throw new IllegalArgumentException("Scope cannot be null/empty");
if(socialSitesCache.get(scope) != null)
return (SocialNetworkingSite) socialSitesCache.get(scope).getObjectValue();
else{
SocialNetworkingSite site = discoverSite(scope);
if(site != null)
socialSitesCache.put(new Element(scope, site));
return site;
}
}
/**
* Discover the site for this scope
* @param scope
* @return
*/
private static SocialNetworkingSite discoverSite(String scope) {
try{
logger.info("Requested site for scope " + scope);
GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager();
long groupId = groupManager.getGroupIdFromInfrastructureScope(scope);
GCubeGroup matchingGateway = null;
if(groupManager.isVRE(groupId)){
// get the Virtual groups for the groupid related to the scope
List<VirtualGroup> virtualGroupsOfGroup = groupManager.getVirtualGroups(groupId);
if(virtualGroupsOfGroup == null || virtualGroupsOfGroup.isEmpty())
throw new Exception("It seems that the VRE is not linked to any VirtualGroups");
// get the gateways
List<GCubeGroup> gateways = groupManager.getGateways();
if(gateways == null || gateways.isEmpty())
throw new Exception("It seems there is no gateway here!");
logger.info("Retrieved Gateways are " + gateways);
// now, retrieve the virtual groups for each gateway and stop when a VG matches with one of the group
// then, it is the gateway of interest
ext_loop: for (GCubeGroup gateway : gateways) {
List<VirtualGroup> gatewayVirtualGroups = groupManager.getVirtualGroups(gateway.getGroupId());
if(gatewayVirtualGroups != null && !gatewayVirtualGroups.isEmpty()){
for (VirtualGroup gatewayVirtualGroup : gatewayVirtualGroups) {
if(virtualGroupsOfGroup.contains(gatewayVirtualGroup)){
logger.info("Matching gateway for scope " + scope + " is " + gateway);
matchingGateway = gateway;
break ext_loop;
}
}
}
}
}else{
List<GCubeGroup> gateways = groupManager.getGateways();
// vo and root vo cases are treated separately: in production environment services.d4science.org is used, instead
// in dev next.d4science.org is used TODO better way...
ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears
String rootContext = "/"+ctx.container().configuration().infrastructure();
String matchingGatewayName = null;
if(isDevOrPreprod(rootContext)){
matchingGatewayName = DEV_FALLBACK_GATEWAY;
}else{
matchingGatewayName = PROD_FALLBACK_GATEWAY;
}
// find the matching one among the gateways
for (GCubeGroup gateway : gateways) {
if(gateway.getGroupName().equals(matchingGatewayName)){
matchingGateway = gateway;
break;
}
}
if(matchingGateway == null && isDevOrPreprod(rootContext)){
logger.warn("Checking if it is the preprod environment");
matchingGatewayName = PREPROD_FALLBACK_GATEWAY;
// find the matching one among the gateways
for (GCubeGroup gateway : gateways) {
if(gateway.getGroupName().equals(matchingGatewayName)){
matchingGateway = gateway;
break;
}
}
}
}
if(matchingGateway == null){
logger.warn("There is no gateway for such scope. Returning null");
return null;
}else{
String siteName = matchingGateway.getGroupName();
String emailSender = (String)groupManager.readCustomAttr(matchingGateway.getGroupId(), EMAIL_SENDER_SITE_CUSTOM_FIELD);
String siteLandingPagePath = GCubePortalConstants.PREFIX_GROUP_URL + matchingGateway.getFriendlyURL();
String siteUrl = discoverHostOfServiceEndpoint(siteName);
SocialNetworkingSite site = new SocialNetworkingSite(siteName, emailSender, siteUrl, siteLandingPagePath);
logger.info("Site is " + site);
return site;
}
}catch(Exception e){
logger.error("Failed to determine the SocialNetworkingSite for scope " + scope, e);
}
return null;
}
private static boolean isDevOrPreprod(String rootContext) {
return rootContext.equals("/gcube");
}
/**
* Retrieve endpoint host from IS for this gateway
* @return the host for the gateway
* @throws Exception
*/
private static String discoverHostOfServiceEndpoint(String gatewayName){
String currentScope = ScopeProvider.instance.get();
ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears
ScopeProvider.instance.set("/"+ctx.container().configuration().infrastructure());
String host = null;
try{
SimpleQuery query = queryFor(ServiceEndpoint.class);
query.addCondition("$resource/Profile/Name/text() eq '"+ gatewayName +"'");
query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY +"'");
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
List<ServiceEndpoint> toReturn = client.submit(query);
for (ServiceEndpoint serviceEndpoint : toReturn) {
host = "https://" + serviceEndpoint.profile().runtime().hostedOn();
logger.info("Gateway host is " + host);
break;
}
}catch(Exception e){
logger.error("Error while retrieving host for the gateway " + gatewayName);
}finally{
ScopeProvider.instance.set(currentScope);
}
return host;
}
}