package org.gcube.portlet.user.userstatisticsportlet.server; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathFactory; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.portal.PortalContext; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.storagehub.client.dsl.StorageHubClient; import org.gcube.portal.custom.communitymanager.SiteManagerUtil; import org.gcube.social_networking.social_networking_client_library.LibClient; import org.gcube.social_networking.socialnetworking.model.shared.Post; import org.gcube.portlet.user.userstatisticsportlet.client.UserStatisticsService; import org.gcube.portlet.user.userstatisticsportlet.server.cache.UserInfrastructureQuotaStorageCache; import org.gcube.portlet.user.userstatisticsportlet.server.cache.UserInfrastructureSpaceCache; import org.gcube.portlet.user.userstatisticsportlet.server.utils.DiscoverQuotaServiceEndPoint; import org.gcube.portlet.user.userstatisticsportlet.shared.PostsStatsBean; import org.gcube.portlet.user.userstatisticsportlet.shared.QuotaInfo; import org.gcube.portlet.user.userstatisticsportlet.shared.UserInformation; import org.gcube.vomanagement.usermanagement.GroupManager; import org.gcube.vomanagement.usermanagement.UserManager; import org.gcube.vomanagement.usermanagement.impl.LiferayGroupManager; import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager; import org.gcube.vomanagement.usermanagement.model.GCubeGroup; import org.gcube.vomanagement.usermanagement.util.ManagementUtils; import org.w3c.dom.Document; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.liferay.portal.kernel.cache.CacheRegistryUtil; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.model.User; import com.liferay.portal.service.UserLocalServiceUtil; /** * The server side implementation of the RPC service. */ @SuppressWarnings("serial") public class UserStatisticsServiceImpl extends RemoteServiceServlet implements UserStatisticsService { // private static final org.slf4j.Logger logger = LoggerFactory.getLogger(UserStatisticsServiceImpl.class); private static final Log logger = LogFactoryUtil.getLog(UserStatisticsServiceImpl.class); private LibClient libClient; private String quotaServiceBaseUrl; private static final String CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY = "show_user_statistics_other_people"; private UserManager userManager = new LiferayUserManager(); private GroupManager groupManager = new LiferayGroupManager(); @Override public void init() { logger.info("Getting connection to Cassandra.."); try { libClient = new LibClient(); } catch (Exception e) { throw new RuntimeException(e); } ServerUtils.createUserCustomField(CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY, true); logger.info("Retrieving quota service endpoint"); quotaServiceBaseUrl = DiscoverQuotaServiceEndPoint.discover(); } /*@Override public void destroy(){ logger.info("Closing connection to Cassandra"); store.closeConnection(); }*/ @Override public QuotaInfo getQuotaStorage(String userid) { QuotaInfo toReturn = null; String userName = null; String quotaOfUser = null; if(quotaServiceBaseUrl != null){ userName = ServerUtils.getCurrentUser(this.getThreadLocalRequest()).getUsername(); quotaOfUser = userName; // check the user's quota to be shown if(userid != null && !userid.equals(userName)) quotaOfUser = userid; logger.debug("Fetching info for quota of user " + quotaOfUser); try{ UserInfrastructureQuotaStorageCache cache = UserInfrastructureQuotaStorageCache.getCacheInstance(); if(cache.get(quotaOfUser) != null) toReturn = cache.get(quotaOfUser); else{ PortalContext pContext = PortalContext.getConfiguration(); String rootContextToken = pContext.getCurrentUserToken("/" + pContext.getInfrastructureName(), quotaOfUser); URL request = new URL(quotaServiceBaseUrl + "?timeinterval=FOREVER&gcube-token=" + rootContextToken); InputStream result = request.openStream(); DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document document = dBuilder.parse(result); document.getDocumentElement().normalize(); logger.debug("Result is " + document); XPathFactory xpf = XPathFactory.newInstance(); XPath xpath = xpf.newXPath(); Float maxQuota = ServerUtils.queryQuotaService(document, xpath, "/quotaStatus/quotaValue/text()"); Float usageQuota = ServerUtils.queryQuotaService(document, xpath, "/quotaStatus/quotaUsage/text()"); logger.debug("Information retrieved are: maxQuota=" + maxQuota + " and usageQuota=" + usageQuota); if(usageQuota != null && maxQuota != null && maxQuota > 0){ toReturn = new QuotaInfo(maxQuota, usageQuota); cache.insert(quotaOfUser, toReturn); } } }catch(Exception e){ logger.error("Failed to retrieve quota information for user", e); } } logger.debug("Quota for user " + quotaOfUser + " is " + toReturn); return toReturn; } @Override public String getTotalSpaceInUse(String userid) { String storageInUse = null; String userName = ServerUtils.getCurrentUser(this.getThreadLocalRequest()).getUsername(); String statisticsOfUsername = userName; if(userid != null && !userid.equals(userName)) statisticsOfUsername = userid; logger.debug("Getting " + statisticsOfUsername + " amount of workspace in use."); try{ UserInfrastructureSpaceCache cacheWorkspace = UserInfrastructureSpaceCache.getCacheInstance(); Long storageInUseLong = (Long) cacheWorkspace.get(statisticsOfUsername); if(storageInUseLong == null){ String userToken = PortalContext.getConfiguration().getCurrentUserToken(ScopeProvider.instance.get(), statisticsOfUsername); SecurityTokenProvider.instance.set(userToken); StorageHubClient shClient = new StorageHubClient(); storageInUseLong = shClient.getTotalVolume(); cacheWorkspace.insert(statisticsOfUsername, storageInUseLong); } storageInUse = ServerUtils.formatFileSize(storageInUseLong); }catch(Exception e){ logger.error("Unable to retrieve workspace information!", e); } return storageInUse; } @Override public int getProfileStrength(String userid) { int profileStrenght = -1; String userName = ServerUtils.getCurrentUser(this.getThreadLocalRequest()).getUsername(); if(userName == null){ logger.warn("Unable to determine the current user, returing null"); } String statisticsOfUsername = userName; if(userid != null && !userid.equals(userName)) statisticsOfUsername = userid; if(ServerUtils.isWithinPortal()){ try{ boolean avatarPresent = (userManager.getUserAvatarBytes(statisticsOfUsername) != null); User user = UserLocalServiceUtil.getUserByScreenName(SiteManagerUtil.getCompany().getCompanyId(), statisticsOfUsername); profileStrenght = ServerUtils.evaluateProfileStrenght(user, avatarPresent); }catch(Exception e){ logger.error("Profile strenght evaluation failed!!" + e.toString(), e); } } return profileStrenght; } @Override public UserInformation getUserSettings(String userid) { String userName = ServerUtils.getCurrentUser(this.getThreadLocalRequest()).getUsername(); if(userName == null){ logger.warn("Unable to determine the current user, returing null"); return null; } String statisticsOfUsername = userName; boolean isOwner = false; boolean isProfileShowable = true; if(userid == null || (userid !=null && userid.equals(userName))){ isOwner = true; isProfileShowable = checkUserPrivacyOption(userName); } if(userid != null && !userid.equals(userName)){ statisticsOfUsername = userid; isProfileShowable = checkUserPrivacyOption(statisticsOfUsername); logger.info("Is profile showable for user " + userid + " " + isProfileShowable); } if(ServerUtils.isWithinPortal()){ boolean isInfrastructure = ServerUtils.isInfrastructureScope(userid, this.getThreadLocalRequest()); logger.debug("User scope is " + (isInfrastructure ? " the whole infrastucture " : " a VRE")); String thumbnailURL = null; try { thumbnailURL = userManager.getUserByUsername(statisticsOfUsername).getUserAvatarURL(); } catch (Exception e) { logger.error("Unable to retrieve avatar url for user " + statisticsOfUsername +". Likely he/she doesn't have an avatar"); } String actualVre = null; if(!isInfrastructure){ String[] temp = ServerUtils.getCurrentContext(this.getThreadLocalRequest(), true).split("/"); actualVre = temp[temp.length - 1]; } String pageLanding = PortalContext.getConfiguration().getSiteLandingPagePath(getThreadLocalRequest()); UserInformation bean = new UserInformation(isInfrastructure, thumbnailURL, userName, actualVre, isOwner, isProfileShowable); bean.setCurrentPageLanding(pageLanding); return bean; } else return new UserInformation(true, null, userName, ServerUtils.getCurrentContext(this.getThreadLocalRequest(), false), true, true); } /** * Check privacy option for user's own statistics * @param username * @return */ private boolean checkUserPrivacyOption(String username) { if(ServerUtils.isWithinPortal()){ try{ ServerUtils.setPermissionChecker(); CacheRegistryUtil.clear(); User user = UserLocalServiceUtil.getUserByScreenName(ManagementUtils.getCompany().getCompanyId(), username); if(!user.getExpandoBridge().hasAttribute(CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY)) return true; return (boolean)user.getExpandoBridge().getAttribute(CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY); }catch(Exception e){ logger.error("Unable to retrieve user's privacy option for his statistics"); return true; } } return false; } @Override public PostsStatsBean getPostsStats(String userid){ String userName = ServerUtils.getCurrentUser(this.getThreadLocalRequest()).getUsername(); if(userName == null){ logger.warn("Unable to determine the current user, returing null"); } String scope = ServerUtils.getCurrentContext(this.getThreadLocalRequest(), true); PostsStatsBean toReturn = null; String statisticsOfUsername = userName; if(userid != null && !userid.equals(userName)) statisticsOfUsername = userid; boolean isInfrastructure = ServerUtils.isInfrastructureScope(userid, this.getThreadLocalRequest()); Calendar oneYearAgo = Calendar.getInstance(); oneYearAgo.set(Calendar.YEAR, oneYearAgo.get(Calendar.YEAR) - 1); logger.debug("Reference time is " + oneYearAgo.getTime()); try { long userId = userManager.getUserId(statisticsOfUsername); List userPosts = libClient.getRecentPostsByUserAndDateLib(statisticsOfUsername, oneYearAgo.getTimeInMillis()); logger.debug("store.getRecentFeedsByUserAndDate"); List recentLikedFeeds = libClient.getRecentLikedPostsByUserAndDateLib(statisticsOfUsername, oneYearAgo.getTimeInMillis()); logger.debug("store.getRecentLikedFeedsByUserAndDate"); // Evaluate the contexts to use List contexts = new ArrayList(); if(isInfrastructure){ Set vresInPortal = groupManager.listGroupsByUserAndSite(userId, getThreadLocalRequest().getServerName()); for (GCubeGroup gCubeGroup : vresInPortal) { contexts.add(groupManager.getInfrastructureScope(gCubeGroup.getGroupId())); } }else{ contexts.add(scope); } logger.info("Context(s) that are going to be used " + contexts); long postCreated = 0, likesGot = 0, commentsGot = 0, commentsMade = 0, likesMade = 0; for (Post post : userPosts) { if(contexts.contains(post.getVreid())){ postCreated ++; commentsGot += Integer.parseInt(post.getCommentsNo()); likesGot += Integer.parseInt(post.getLikesNo()); } } for (Post post : recentLikedFeeds) { if(contexts.contains(post.getVreid())) likesMade ++; } toReturn = new PostsStatsBean(postCreated, likesGot, commentsGot, commentsMade, likesMade); }catch(Exception e){ logger.error("Error while retrieving user's statistics", e); } return toReturn; } @Override public void setShowMyOwnStatisticsToOtherPeople(boolean show) { if(ServerUtils.isWithinPortal()){ String username = ServerUtils.getCurrentUser(this.getThreadLocalRequest()).getUsername(); if(username == null){ logger.warn("Unable to determine the current user, returing null"); } try{ ServerUtils.setPermissionChecker(); CacheRegistryUtil.clear(); User user = UserLocalServiceUtil.getUserByScreenName(ManagementUtils.getCompany().getCompanyId(), username); boolean hasAttribute = user.getExpandoBridge().hasAttribute(CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY); if(hasAttribute){ logger.debug("Setting custom field value to " + show + " for user " + username); user.getExpandoBridge().setAttribute(CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY, show); } }catch(Exception e){ logger.error("Unable to check user's privacy for his statistics", e); } } } }