diff --git a/.classpath b/.classpath
index 1151b0d..91f2707 100644
--- a/.classpath
+++ b/.classpath
@@ -25,7 +25,7 @@
-
+
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
index db32697..839d647 100644
--- a/.settings/org.eclipse.core.resources.prefs
+++ b/.settings/org.eclipse.core.resources.prefs
@@ -1,3 +1,5 @@
eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
+encoding//src/test/java=UTF-8
encoding/=UTF-8
diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component
index 7bedda1..bf18a98 100644
--- a/.settings/org.eclipse.wst.common.component
+++ b/.settings/org.eclipse.wst.common.component
@@ -4,7 +4,9 @@
-
+
+ uses
+
diff --git a/pom.xml b/pom.xml
index 756fde0..058631f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,6 +64,11 @@
org.gcube.portal
social-networking-library
provided
+
+
+ org.gcube.portal
+ notifications-common-library
+ [1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT)
com.google
diff --git a/src/main/java/org/gcube/portal/socialmail/MailReader.java b/src/main/java/org/gcube/portal/socialmail/MailReader.java
index 6d27a5f..880ebc8 100644
--- a/src/main/java/org/gcube/portal/socialmail/MailReader.java
+++ b/src/main/java/org/gcube/portal/socialmail/MailReader.java
@@ -90,13 +90,4 @@ public class MailReader extends HttpServlet {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
-
- public static void main(String[] args) {
- new MailReader().init();
- System.out.println("Scheduling periodic task ... ");
- //System.out.println(host + user + password);
- scheduler.scheduleAtFixedRate(new PeriodicTask(store, portalName, host, user, password), 0, MINUTES_DELAY, TimeUnit.MINUTES);
- }
-
-
}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/portal/socialmail/PeriodicTask.java b/src/main/java/org/gcube/portal/socialmail/PeriodicTask.java
index b044a22..1963b83 100644
--- a/src/main/java/org/gcube/portal/socialmail/PeriodicTask.java
+++ b/src/main/java/org/gcube/portal/socialmail/PeriodicTask.java
@@ -1,6 +1,7 @@
package org.gcube.portal.socialmail;
import java.security.GeneralSecurityException;
+import java.util.ArrayList;
import java.util.Date;
import java.util.Properties;
import java.util.UUID;
@@ -21,12 +22,21 @@ import javax.mail.internet.MimeMessage.RecipientType;
import org.gcube.application.framework.core.session.ASLSession;
import org.gcube.application.framework.core.session.SessionManager;
import org.gcube.application.framework.core.util.GenderType;
+import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager;
+import org.gcube.applicationsupportlayer.social.NotificationsManager;
import org.gcube.applicationsupportlayer.social.mailing.EmailPlugin;
import org.gcube.common.portal.PortalContext;
import org.gcube.portal.custom.communitymanager.OrganizationsUtil;
import org.gcube.portal.databook.server.DatabookStore;
import org.gcube.portal.databook.shared.Comment;
+import org.gcube.portal.databook.shared.Feed;
+import org.gcube.portal.databook.shared.Like;
+import org.gcube.portal.databook.shared.ex.ColumnNameNotFoundException;
import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException;
+import org.gcube.portal.databook.shared.ex.FeedTypeNotFoundException;
+import org.gcube.portal.databook.shared.ex.PrivacyLevelTypeNotFoundException;
+import org.gcube.portal.notifications.thread.CommentNotificationsThread;
+import org.gcube.portal.notifications.thread.LikeNotificationsThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,7 +53,7 @@ import com.sun.mail.util.MailSSLSocketFactory;
*/
public class PeriodicTask implements Runnable {
private static final Logger _log = LoggerFactory.getLogger(PeriodicTask.class);
-
+
private DatabookStore socialStore;
private String host;
private String mailserver_username;
@@ -81,7 +91,7 @@ public class PeriodicTask implements Runnable {
User user = UserLocalServiceUtil.getUserByEmailAddress(companyId, emailAddress);
username = user.getScreenName();
SessionManager.getInstance().getASLSession(sessionID, username).setScope(scope);
-
+
//add the social information needed by apps
String fullName = user.getFirstName() + " " + user.getLastName();
String email = user.getEmailAddress();
@@ -92,11 +102,13 @@ public class PeriodicTask implements Runnable {
SessionManager.getInstance().getASLSession(sessionID, username).setUserEmailAddress(email);
SessionManager.getInstance().getASLSession(sessionID, username).setUserAvatarId(thumbnailURL);
SessionManager.getInstance().getASLSession(sessionID, username).setUserGender(isMale? GenderType.MALE : GenderType.FEMALE);
-
+
+ _log.debug("Created fakesession for user " + username + " email="+emailAddress);
+
} catch (PortalException | SystemException e) {
e.printStackTrace();
}
-
+
return SessionManager.getInstance().getASLSession(sessionID, username);
}
@@ -120,7 +132,7 @@ public class PeriodicTask implements Runnable {
Session emailSession = Session.getDefaultInstance(pop3Props);
- //emailSession.setDebug(true);
+ emailSession.setDebug(false);
//create the POP3 socialStore object and connect with the pop server
Store store = emailSession.getStore("pop3s");
@@ -143,19 +155,19 @@ public class PeriodicTask implements Runnable {
String feedId = extractFeedId(message);
String commentText = extractText(portalName, feedId, message);
-
+
String escapedCommentText = Utils.escapeHtmlAndTransformUrl(commentText);
-
+
Address[] froms = message.getFrom();
String emailAddress = froms == null ? null : ((InternetAddress) froms[0]).getAddress();
-
+
ASLSession fakeSession = getFakeASLSession(emailAddress);
-
+
Comment comment = new Comment(UUID.randomUUID().toString(), fakeSession.getUsername(),
new Date(), feedId, escapedCommentText, fakeSession.getUserFullName(), fakeSession.getUserAvatarId());
-
- _log.debug("Parsed and escapedCommentText =>" + escapedCommentText);
+
+ _log.debug("The EscapedCommentText =>" + escapedCommentText);
boolean commentCommitResult = false;
try {
if (socialStore.addComment(comment))
@@ -164,11 +176,11 @@ public class PeriodicTask implements Runnable {
_log.error("Related post not found for this comment " + e.getMessage());
e.printStackTrace();
}
- if (commentCommitResult) { //the notify
- _log.info("Now the NOTIFICATION SHOULD START!!!!!");
+ if (commentCommitResult) { //the notifications should start
+ notifyUsersInvolved(comment, escapedCommentText, feedId, fakeSession);
}
-
+ //delete this message
message.setFlag(Flags.Flag.DELETED, true);
System.out.println("Marked DELETE for message: " + subject);
}
@@ -185,7 +197,53 @@ public class PeriodicTask implements Runnable {
e.printStackTrace();
}
}
+ /**
+ * this method take care of notify all the users that need to be notified when someone comment
+ * @param comment
+ * @param feedId
+ * @param fakeSession
+ * @throws PrivacyLevelTypeNotFoundException
+ * @throws FeedTypeNotFoundException
+ * @throws FeedIDNotFoundException
+ * @throws ColumnNameNotFoundException
+ */
+ private void notifyUsersInvolved(Comment comment, String commentText, String feedId, ASLSession fakeSession) throws PrivacyLevelTypeNotFoundException, FeedTypeNotFoundException, FeedIDNotFoundException, ColumnNameNotFoundException {
+ Feed feed = socialStore.readFeed(feedId);
+ String feedOwnerId = feed.getEntityId();
+ boolean isAppFeed = feed.isApplicationFeed();
+ //if the user who commented this post is not the user who posted it notifies the poster user (Feed owner)
+ NotificationsManager nm = new ApplicationNotificationsManager(fakeSession);
+ if (! fakeSession.getUsername().equals(feedOwnerId) && (!isAppFeed)) {
+ boolean result = nm.notifyOwnCommentReply(feedOwnerId, feedId, commentText);
+ _log.trace("Comment Notification to post owner added? " + result);
+ }
+
+ //if there are users who liked this post they get notified, asynchronously with this thread
+ ArrayList favorites = getAllLikesByFeed(feedId);
+ Thread likesThread = new Thread(new LikeNotificationsThread(commentText, nm, favorites, feedOwnerId));
+ likesThread.start();
+
+ //notify the other users who commented this post (excluding the ones above)
+ Thread commentsNotificationthread = new Thread(new CommentNotificationsThread(socialStore, fakeSession.getUsername(), comment.getFeedid(), commentText, nm, feedOwnerId, favorites));
+ commentsNotificationthread.start();
+ }
+ /**
+ *
+ * @param feedid
+ * @return
+ */
+ public ArrayList getAllLikesByFeed(String feedid) {
+ _log.trace("Asking likes for " + feedid);
+ ArrayList toReturn = (ArrayList) socialStore.getAllLikesByFeed(feedid);
+ return toReturn;
+ }
+ /**
+ *
+ * @param message
+ * @return
+ * @throws MessagingException
+ */
private String extractFeedId(Message message) throws MessagingException {
Address[] emails = message.getRecipients(RecipientType.TO);
String toParse = emails[0].toString();
@@ -195,9 +253,15 @@ public class PeriodicTask implements Runnable {
return null;
return toParse.substring(plus+1, at);
}
-
+ /**
+ *
+ * @param portalName
+ * @param subjectId
+ * @param message
+ * @return
+ * @throws Exception
+ */
private String extractText(String portalName, String subjectId, Message message) throws Exception {
- Address[] emails = message.getRecipients(RecipientType.TO);
Object messageContent = message.getContent();
String toParse = null;
// Check if content is pure text/html or in parts
@@ -212,7 +276,7 @@ public class PeriodicTask implements Runnable {
_log.debug("Found g text/plain Message, getting text");
toParse = messageContent.toString();
}
-
+ //cut the text below the WRITE_ABOVE_TO_REPLY text
String[] lines = toParse.split(System.getProperty("line.separator"));
int until = -1;
for (int i = 0; i < lines.length; i++) {
@@ -221,13 +285,18 @@ public class PeriodicTask implements Runnable {
break;
}
}
- String toReturn = "";
+ StringBuilder sb = new StringBuilder();
+ /*
+ * this is needed to remove the text added by the email client like when you reply, e.g. On wrote ...
+ * it also handles the case where the user writes between that and the WRITE_ABOVE_TO_REPLY text
+ */
for (int i = 0; i < until; i++) {
if (! ( lines[i].contains(portalName) || lines[i].contains(subjectId) || (lines[i].startsWith("> ") && lines[i].trim().length() < 2)) ) {
- toReturn += lines[i];
+ sb.append(lines[i]);
}
+ if (! (i == until -1) )
+ sb.append("\n");
}
- return toReturn;
-
+ return sb.toString().trim();
}
}
diff --git a/src/main/java/org/gcube/portal/socialmail/Utils.java b/src/main/java/org/gcube/portal/socialmail/Utils.java
index 36dee71..35200b6 100644
--- a/src/main/java/org/gcube/portal/socialmail/Utils.java
+++ b/src/main/java/org/gcube/portal/socialmail/Utils.java
@@ -80,4 +80,18 @@ public class Utils {
}
return null;
}
+ /**
+ * 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
+ */
+ protected static String escapeHtml(String html) {
+ if (html == null) {
+ return null;
+ }
+ return html.replaceAll("&", "&").replaceAll("<", "<")
+ .replaceAll(">", ">");
+ }
}