package org.gcube.portlet.user.userstatisticsportlet.server; import java.text.DecimalFormat; import java.util.Date; import java.util.List; import org.gcube.application.framework.core.session.ASLSession; import org.gcube.application.framework.core.session.SessionManager; import org.gcube.common.homelibrary.home.HomeLibrary; import org.gcube.common.homelibrary.home.workspace.Workspace; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean.Type; import org.gcube.portal.custom.communitymanager.OrganizationsUtil; import org.gcube.portal.custom.scopemanager.scopehelper.ScopeHelper; import org.gcube.portal.databook.server.DBCassandraAstyanaxImpl; import org.gcube.portal.databook.server.DatabookStore; import org.gcube.portal.databook.shared.Feed; import org.gcube.portlet.user.userstatisticsportlet.client.UserStatisticsService; import org.gcube.portlet.user.userstatisticsportlet.shared.PostsStatsBean; import org.gcube.portlet.user.userstatisticsportlet.shared.UserInformation; import org.slf4j.LoggerFactory; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.liferay.portal.kernel.util.WebKeys; import com.liferay.portal.model.Contact; import com.liferay.portal.model.User; import com.liferay.portal.model.Website; import com.liferay.portal.service.UserLocalServiceUtil; import com.liferay.portal.service.WebsiteLocalServiceUtil; import com.liferay.portal.theme.ThemeDisplay; /** * The server side implementation of the RPC service. */ @SuppressWarnings("serial") public class UserStatisticsServiceImpl extends RemoteServiceServlet implements UserStatisticsService { // Logger private static final org.slf4j.Logger _log = LoggerFactory.getLogger(UserStatisticsServiceImpl.class); //dev user public static final String userid = "test.user"; //dev vre private static final String vreID = "/gcube/devsec/devVRE"; // Cassandra connection private DatabookStore store; @Override public void init() { // get connection to Cassandra _log.info("Getting connection to Cassandra.."); store = new DBCassandraAstyanaxImpl(); } @Override public void destroy(){ // shutting down connection to Cassandra _log.info("Closing connection to Cassandra"); store.closeConnection(); } /** * the current ASLSession * @return the session */ private ASLSession getASLSession() { String sessionID = this.getThreadLocalRequest().getSession().getId(); String user = (String) this.getThreadLocalRequest().getSession().getAttribute(ScopeHelper.USERNAME_ATTRIBUTE); if (user == null) { _log.warn("USER IS NULL setting " + userid + " and Running OUTSIDE PORTAL"); user = getDevelopmentUser(); SessionManager.getInstance().getASLSession(sessionID, user).setScope(vreID); } return SessionManager.getInstance().getASLSession(sessionID, user); } /** * Indicates whether the scope is the whole infrastructure. * @return true if it is, false otherwise. */ private boolean isInfrastructureScope() { boolean toReturn = false; try { ScopeBean scope = new ScopeBean(getASLSession().getScope()); toReturn = scope.is(Type.INFRASTRUCTURE); return toReturn; } catch (NullPointerException e) { _log.error("NullPointerException in isInfrastructureScope returning false"); return false; } } /** * Online or in development mode? * @return true if you're running into the portal, false if in development */ private boolean isWithinPortal() { try { UserLocalServiceUtil.getService(); return true; } catch (com.liferay.portal.kernel.bean.BeanLocatorException ex) { _log.trace("Development Mode ON"); return false; } } /** * when packaging test will fail if the user is not set to test.user * @return . */ public String getDevelopmentUser() { String user = userid; // user = "massimiliano.assante"; return user; } @Override public String getTotalSpaceInUse() { String storageInUse = null; // get the session ASLSession session = getASLSession(); //username String userName = session.getUsername(); //in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info) //this check just return nothing if that happens if (userName.compareTo(userid) == 0) { _log.debug("Found " + userName + " returning nothing"); return null; }else{ _log.info("Getting " + userName + " amount of workspace in use."); try{ long init = System.currentTimeMillis(); Workspace workspace = HomeLibrary.getUserWorkspace(userName); long storage = workspace.getDiskUsage(); storageInUse = formatFileSize(storage); long end = System.currentTimeMillis(); _log.info("[USER-STATISTICS] time taken to retrieve user space is " + (end - init) + "ms"); }catch(Exception e){ _log.error("Unable to retrieve workspace information!"); } } return storageInUse; } @Override public int getProfileStrength() { int profileStrenght = -1; // get the session ASLSession session = getASLSession(); //username String userName = session.getUsername(); //in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info) //this check just return nothing if that happens if (userName.compareTo(userid) == 0) { _log.debug("Found " + userName + " returning nothing"); return profileStrenght; }else{ // valuate profile strength if(isWithinPortal()){ try{ // check if the avatar is present boolean avatarPresent = session.getUserAvatarId() != null; long init = System.currentTimeMillis(); User user = OrganizationsUtil.validateUser(userName); profileStrenght = evaluateProfileStrenght(user, avatarPresent); long end = System.currentTimeMillis(); _log.info("[USER-STATISTICS] time taken to evaluate user profile strenght is " + (end - init) + "ms"); }catch(Exception e){ _log.error("Profile strenght evaluation failed!!"); } } } return profileStrenght; } @Override public UserInformation getUserSettings() { // get the session ASLSession session = getASLSession(); //username String userName = session.getUsername(); //in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info) //this check just return nothing if that happens if (userName.compareTo(userid) == 0) { _log.debug("Found " + userName + " returning nothing"); return null; } if(isWithinPortal()){ // If the user is in the root panel, we have to send him the overall number of posts made, comments/likes(received) and the space in use. // Otherwise we have to filter on the vre. boolean isInfrastructure = isInfrastructureScope(); _log.info("User scope is " + (isInfrastructure ? " the whole infrastucture " : " a VRE")); // get path of the avatar String thumbnailURL = session.getUserAvatarId(); _log.info(userName + " avatar has url " + thumbnailURL); // get the vre (if not in the infrastructure) String actualVre = null; if(!isInfrastructure){ String[] temp = session.getScope().split("/"); actualVre = temp[temp.length - 1]; } // url account to change the avatar String accountURL = null; ThemeDisplay themeDisplay = (ThemeDisplay) this.getThreadLocalRequest().getSession().getAttribute(WebKeys.THEME_DISPLAY); accountURL = themeDisplay.getURLMyAccount().toString(); _log.info("Account url for " + userName + " is " + accountURL); return new UserInformation(isInfrastructure, thumbnailURL, userName, actualVre, accountURL); } else return new UserInformation(true, null, userName, null, null); } @SuppressWarnings("deprecation") @Override public PostsStatsBean getPostsStats(){ // get the session ASLSession session = getASLSession(); //username String userName = session.getUsername(); //in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info) //this check just return nothing if that happens if (userName.compareTo(userid) == 0) { _log.debug("Found " + userName + " returning nothing"); return null; } long totalFeeds = 0, totalLikes = 0, totalComments = 0; // check if the user is or not in a VRE boolean isInfrastructure = isInfrastructureScope(); // date corresponding to one year ago Date oneYearAgo = new Date(); oneYearAgo.setYear(oneYearAgo.getYear() - 1); _log.info("Reference time is " + oneYearAgo.toString()); try { long init = System.currentTimeMillis(); _log.info("Getting " + userName + " feeds in the last year."); List userFeeds = store.getRecentFeedsByUserAndDate(userName, oneYearAgo.getTime()); _log.info("Evaluating number of comments and likes of " + userName + "'s feeds."); for (Feed feed : userFeeds) { try{ // check if the user is in the root, if not check if the VRE of the feed is the current one if(!isInfrastructure && !feed.getVreid().equals(session.getScope())) continue; // increment feeds number totalFeeds ++; //increment number of post replies and likes totalComments += Integer.parseInt(feed.getCommentsNo()); totalLikes += Integer.parseInt(feed.getLikesNo()); }catch(NumberFormatException e){ _log.error(e.toString()); } } long end = System.currentTimeMillis(); _log.info("[USER-STATISTICS] time taken to retrieve and filter user feeds, get likes and replies got is " + (end - init) + "ms"); _log.info("Total number of feeds (after time filtering) of " + userName + " is " + totalFeeds); _log.info("Total number of likes (after time filtering) for " + userName + " is " + totalLikes); _log.info("Total number of comments (after time filtering) for " + userName + " is " + totalComments); }catch(Exception e){ _log.error(e.toString()); return null; } // return the object return new PostsStatsBean(totalFeeds, totalLikes, totalComments); } /** * returns dynamically the formated size. * * @param size the size * @return the string */ private static String formatFileSize(long size) { String formattedSize = null; double b = size; double k = size/1024.0; double m = ((size/1024.0)/1024.0); double g = (((size/1024.0)/1024.0)/1024.0); double t = ((((size/1024.0)/1024.0)/1024.0)/1024.0); DecimalFormat dec = new DecimalFormat("0.00"); if ( t >= 1.0 ) { formattedSize = dec.format(t).concat(" TB"); } else if ( g >= 1.0 ) { formattedSize = dec.format(g).concat(" GB"); } else if ( m >= 1.0 ) { formattedSize = dec.format(m).concat(" MB"); } else if ( k >= 1.0 ) { formattedSize = dec.format(k).concat(" KB"); } else { formattedSize = dec.format(b).concat(" Bytes"); } return formattedSize; } /** * Evaluates the profile strenght of the user * @param user * @return a int in [0, 100] */ private static int evaluateProfileStrenght(User user, boolean imageIsPresent) { int score = evaluateContactScore(user); score += evaluateInformationScore(user, imageIsPresent); return score; } /** * Evaluates a score according to the information of the user such as job, organization, comments * @param user * @return a score in [0, 65] */ private static int evaluateInformationScore(User user, boolean imageIsPresent) { int score = 0; score += user.getJobTitle().compareTo("") != 0 ? 20 : 0; score += user.getOpenId().compareTo("") != 0 ? 20 : 0; String summary = getSummary(user); int lenght = summary.replace(" ", "").length(); float partialScore = ((float)lenght / 10.0f); score += partialScore > 20f ? 20 : (int)partialScore; if(imageIsPresent) score += 5; return score; } /** * get the user's comment * @param user * @return */ private static String getSummary(User user) { String toReturn = escapeHtml(user.getComments()); // replace all the line breaks by
toReturn = toReturn.replaceAll("(\r\n|\n)","
"); // then replace all the double spaces by the html version   toReturn = toReturn.replaceAll("\\s\\s","  "); return toReturn; } /** * Escape an html string. Escaping data received from the client helps to * prevent cross-site script vulnerabilities. * * @param html the html string to escape * @return the escaped string */ private static String escapeHtml(String html) { if (html == null) { return null; } return html.replaceAll("&", "&").replaceAll("<", "<") .replaceAll(">", ">"); } /** * Evaluates user's contact information * @param user * @return a value in [0, 35] */ private static int evaluateContactScore(User user){ int score = 0; try{ Contact contact = user.getContact(); score += contact.getMySpaceSn().compareTo("") != 0 ? 5 : 0; score += contact.getTwitterSn().compareTo("") != 0 ? 5 : 0; score += contact.getFacebookSn().compareTo("") != 0 ? 5 : 0; score += contact.getSkypeSn().compareTo("") != 0 ? 5 : 0; score += contact.getJabberSn().compareTo("") != 0 ? 5 : 0; score += contact.getAimSn().compareTo("") != 0 ? 5 : 0; List websites = WebsiteLocalServiceUtil.getWebsites(user.getCompanyId(), "com.liferay.portal.model.Contact", contact.getContactId()); score += websites.size() > 0 ? 5 : 0; }catch(Exception e ){ _log.error("Contact profile score evaluation failed!!"); score = 0; } return score; } }