Merge remote-tracking branch 'server/bug3785' into bug3785

This commit is contained in:
Axel Uhl committed 2016-07-20 01:54:27 +02:00
commit 1fa86545a8
8 files changed
+198 -53

No files matched your search

@@ -9,6 +9,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.sap.sailing.server.gateway.deserialization,
javax.mail;version="1.4.0",
javax.mail.internet;version="1.4.0",
javax.mail.util;version="1.4.0",
org.json.simple,
org.json.simple.parser,
org.osgi.framework;version="1.3.0",
@@ -1,33 +1,92 @@
<!doctype html>
<html>
<head>
<title>${title}</title>
<style type="text/css">
.textContainer {
margin: 10px;
}
.buttonContainer {
display: inline-block;
}
.linkButton, .linkButton:active, .linkButton:visited {
padding: 15px;
margin: 10px;
width: 200px;
display: inline-block;
background-color: #337ab7;
border-radius: 4px;
color: #ffffff;
border: 1px solid #2e6da4;
text-decoration: none;
}
.linkButton:hover {
background-color: #2b618e;
border: 1px solid #204d74;
}
</style>
</head>
<body>
${body}
</body>
<head>
<title>${title}</title>
<style type="text/css">
.content {
margin: 10px;
}
.buttonContainer {
display: inline-block;
}
.linkButton, .linkButton:active, .linkButton:visited {
padding: 15px;
margin: 10px 10px 0px 0px;
display: inline-block;
background-color: #337ab7;
border-radius: 4px;
color: #ffffff;
border: 1px solid #2e6da4;
text-decoration: none;
}
.linkButton:hover {
background-color: #2b618e;
border: 1px solid #204d74;
}
.body {
background-color: #e3e3e3;
color: black;
padding: 40px;
max-width: 800px;
margin: 0 auto;
margin-bottom: 100px;
font-family: 'Open Sans', sans-serif;
}
.main {
border: 1px solid black;
background-color: white;
}
.header {
background-color: black;
padding: 10px;
font-size: 16px;
border-bottom: .2em solid #efaa00;
color: white;
}
.content {
padding: 20px 30px;
min-height: 200px;
}
.footer {
margin: 30px 10% 200px 10%;
text-align: center;
font-size: 13px;
}
.sapLogo {
height: 30px;
width: auto;
}
.sailingAnalytics {
display: inline-block;
line-height: 30px;
}
</style>
</head>
<body style="margin: 0px;padding: 0px;">
<div class="body">
<div class="main">
<div class="header">
<img src="cid:saplogo" class="sapLogo"/><span class="sailingAnalytics">Sailing Analytics</span>
</div>
<div class="content">
${content}
</div>
</div>
<div class="footer">
<p>${subscription_information}</p>
<p>${site}</p>
<p>${footer_links}</p>
</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

@@ -26,3 +26,8 @@ competitorScoreCorrectionBody=New results for competitor {0} in {1} are availabl
boatClassUpcomingRaceSubject=A race for boat class {0} will start soon
# 0: boatClassName, 1: raceDescription, 2: time
boatClassUpcomingRaceBody=For boat class {0} {1} will start approximately at {2}.
subscriptionInformation=You are receiving notifications from SAP Sailing Analytics. To turn off notifications, please visit your profile at the link below.
userProfile=User Profile
imprint=Imprint
privacy=Privacy
@@ -3,26 +3,31 @@ raceInFleetInRegattaOfEvent=Wettfahrt {0} ({3}) der Regatta "{1}" bei Veranstalt
leaderboardOfEvent=Rangliste "{0}" bei Veranstaltung "{1}"
leaderboardShowResultsLinkTitle=Ergebnisse anzeigen
racesOverviewLinkTitle=Wettfahrtübersicht anzeigen
racesOverviewLinkTitle=Wettfahrt&uuml;bersicht anzeigen
raceboardShowRaceLinkTitle=Wettfahrt anzeigen
raceboardRaceAnalysisLinkTitle=Wettfahrtanalyse anzeigen
boatClassRaceFinishedSubject=Wettfahrt für Bootsklasse {0} beendet - Neue Ergebnisse verfügbar
boatClassRaceFinishedSubject=Wettfahrt f&uuml;r Bootsklasse {0} beendet - Neue Ergebnisse verf&uuml;gbar
# 0: boatClassName, 1: raceDescription
boatClassRaceFinishedBody=Neue Ergebnisse für Bootsklasse {0} in {1} sind verfügbar.
boatClassRaceFinishedBody=Neue Ergebnisse f&uuml;r Bootsklasse {0} in {1} sind verf&uuml;gbar.
boatClassScoreCorrectionSubject=Neue Ergebnisse für Bootsklasse {0} verfügbar
boatClassScoreCorrectionSubject=Neue Ergebnisse f&uuml;r Bootsklasse {0} verf&uuml;gbar
# 0: boatClassName, 1: leaderboardDescription
boatClassScoreCorrectionBody=Neue Ergebnisse für Bootsklasse {0} in {1} sind verfügbar.
boatClassScoreCorrectionBody=Neue Ergebnisse f&uuml;r Bootsklasse {0} in {1} sind verf&uuml;gbar.
competitorPassesFinishSubject=Teilnehmer {0} hat eine Wettfahrt beendet
# 0: competitorName, 1: raceDescription
competitorPassesFinishBody=Teilnehmer {0} hat bei {1} die Ziellinie überquert.
competitorPassesFinishBody=Teilnehmer {0} hat bei {1} die Ziellinie &uuml;berquert.
competitorScoreCorrectionSubject=Neue Ergebnisse für Teilnehmer {0}
competitorScoreCorrectionSubject=Neue Ergebnisse f&uuml;r Teilnehmer {0}
# 0: competitorName, 1: leaderboardDescription
competitorScoreCorrectionBody=Für Teilnehmer {0} in {1} sind neue Ergebnisse verfügbar.
competitorScoreCorrectionBody=F&uuml;r Teilnehmer {0} in {1} sind neue Ergebnisse verf&uuml;gbar.
boatClassUpcomingRaceSubject=Wettfahrt in Bootsklasse {0} startet bald
# 0: boatClassName, 1: raceDescription, 2: time
boatClassUpcomingRaceBody=In Bootsklasse {0} startet {1} um etwa {2}.
subscriptionInformation=Bei dieser Mail handelt es sich um eine automatisierte Benachrichtigung aus der SAP Sailing Analytics. Die Benachrichtigungen k&ouml;nnen im Benutzerprofil (s.u.) abgeschaltet werden.
userProfile=Benutzerprofil
imprint=Impressum
privacy=Datenschutzerkl&auml;rung
@@ -1,5 +1,6 @@
package com.sap.sailing.server.notification.impl;
import java.net.URL;
import java.util.Arrays;
import com.sap.sse.common.Util.Pair;
@@ -9,21 +10,29 @@ public class NotificationMailTemplate {
private final String subject;
private final String title;
private final String text;
private final String serverBaseUrl;
private final Iterable<Pair<String, String>> labelsAndLinkUrls;
@SafeVarargs
public NotificationMailTemplate(String subject, String text, Pair<String, String>... labelsAndLinkUrls) {
this(subject, null, text, labelsAndLinkUrls);
public NotificationMailTemplate(String subject, String text, URL serverBaseUrl,
Pair<String, String>... labelsAndLinkUrls) {
this(subject, null, text, serverBaseUrl, labelsAndLinkUrls);
}
@SafeVarargs
public NotificationMailTemplate(String subject, String title, String text, Pair<String, String>... labelsAndLinkUrls) {
public NotificationMailTemplate(String subject, String title, String text, URL serverBaseUrl,
Pair<String, String>... labelsAndLinkUrls) {
this.subject = subject;
this.title = title;
this.text = text;
this.serverBaseUrl = serverBaseUrl.toString();
this.labelsAndLinkUrls = Arrays.asList(labelsAndLinkUrls);
}
public String getServerBaseUrl() {
return serverBaseUrl;
}
public String getSubject() {
return subject;
}
@@ -1,19 +1,25 @@
package com.sap.sailing.server.notification.impl;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.BodyPart;
import javax.mail.Multipart;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.i18n.impl.ResourceBundleStringMessagesImpl;
import com.sap.sse.mail.MailService;
import com.sap.sse.mail.queue.MailNotification;
import com.sap.sse.security.PreferenceObjectBasedNotificationSet;
@@ -22,7 +28,10 @@ public abstract class NotificationSetNotification<T> implements MailNotification
private static final Logger logger = Logger.getLogger(NotificationSetNotification.class.getName());
private static final String TEMPLATE_FILE = "notification-mail-template.html";
private static final String LOGO_FILE = "sap_logo_header.png";
private static final String TEMPLATE = loadTemplateFile();
private static final byte[] LOGO_BYTES = loadLogoFile();
private static String loadTemplateFile() {
StringBuilder content = new StringBuilder();
@@ -38,13 +47,31 @@ public abstract class NotificationSetNotification<T> implements MailNotification
return content.toString();
}
private static byte[] loadLogoFile() {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream in = NotificationSetNotification.class.getResourceAsStream(LOGO_FILE)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) >= 0) {
baos.write(buffer, 0, bytesRead);
}
return baos.toByteArray();
} catch (IOException exc) {
logger.log(Level.SEVERE, "Error while loading notification mail template!", exc);
return null;
}
}
private final T objectToNotifyAbout;
private final PreferenceObjectBasedNotificationSet<?, T> associatedNotificationSet;
private static final ResourceBundleStringMessagesImpl messages = new ResourceBundleStringMessagesImpl(
SailingNotificationServiceImpl.STRING_MESSAGES_BASE_NAME,
NotificationSetNotification.class.getClassLoader());
public NotificationSetNotification(T objectToNotifyAbout, PreferenceObjectBasedNotificationSet<?, T> associatedNotificationSet) {
this.objectToNotifyAbout = objectToNotifyAbout;
this.associatedNotificationSet = associatedNotificationSet;
}
@Override
@@ -55,10 +82,19 @@ public abstract class NotificationSetNotification<T> implements MailNotification
Locale locale = user.getLocaleOrDefault();
Multipart multipart = new MimeMultipart();
BodyPart bodyPart = new MimeBodyPart();
BodyPart messageImagePart = new MimeBodyPart();
try {
// TODO: add cid:saplogo
NotificationMailTemplate mailTemplate = getMailTemplate(objectToNotifyAbout, locale);
bodyPart.setContent(getMailContent(mailTemplate), "text/html");
bodyPart.setContent(getMailContent(mailTemplate, locale), "text/html");
multipart.addBodyPart(bodyPart);
DataSource imageDs = new ByteArrayDataSource(LOGO_BYTES, "image/png");
messageImagePart.setDataHandler(new DataHandler(imageDs));
messageImagePart.setHeader("Content-ID", "saplogo");
messageImagePart.setHeader("Content-Disposition", "inline;filename=\"saplogo.png\"");
multipart.addBodyPart(messageImagePart);
mailService.sendMail(user.getEmail(), mailTemplate.getSubject(), multipart);
} catch (Exception e) {
logger.log(Level.SEVERE,
@@ -67,17 +103,39 @@ public abstract class NotificationSetNotification<T> implements MailNotification
});
}
private String getMailContent(NotificationMailTemplate notificationMailTemplate) {
private String getMailContent(NotificationMailTemplate notificationMailTemplate, Locale locale) {
StringBuilder bodyContent = new StringBuilder();
if (notificationMailTemplate.getTitle() != null) {
bodyContent.append("<h1>").append(notificationMailTemplate.getTitle()).append("</h1>");
}
bodyContent.append("<p class=\"textContainer\">").append(notificationMailTemplate.getText()).append("</p>");
bodyContent.append("<p>").append(notificationMailTemplate.getText()).append("</p>");
for (Pair<String, String> link : notificationMailTemplate.getLabelsAndLinkUrls()) {
bodyContent.append("<div class=\"buttonContainer\">").append("<a class=\"linkButton\" href=\"");
bodyContent.append(link.getB()).append("\">").append(link.getA()).append("</a>").append("</div>");
}
return TEMPLATE.replace("${title}", notificationMailTemplate.getSubject()).replace("${body}", bodyContent.toString());
String siteLink = "<a href=\"" + notificationMailTemplate.getServerBaseUrl() + "/gwt/Home.html\">"
+ notificationMailTemplate.getServerBaseUrl() + "</a>";
StringBuilder footerLinks = new StringBuilder();
footerLinks //
.append("<a href=\"") //
.append(notificationMailTemplate.getServerBaseUrl())
.append("/gwt/Home.html#/user/profile/:\">").append(messages.get(locale, "userProfile")).append("</a>")
.append(" | ");
footerLinks.append("<a href=\"http://go.sap.com/about/legal/impressum.html\">")
.append(messages.get(locale, "imprint")).append("</a>")
.append(" | ");
footerLinks.append("<a href=\"http://go.sap.com/about/legal/privacy.html\">")
.append(messages.get(locale, "privacy"))
.append("</a>");
String subscriptionInformation = messages.get(locale, "subscriptionInformation");
return TEMPLATE //
.replace("${title}", notificationMailTemplate.getSubject())
.replace("${content}", bodyContent.toString())
.replace("${subscription_information}", subscriptionInformation)
.replace("${site}", siteLink) //
.replace("${footer_links}", footerLinks.toString())
;
}
protected abstract NotificationMailTemplate getMailTemplate(T objectToNotifyAbout, Locale locale);
@@ -37,7 +37,7 @@ import com.sap.sse.mail.queue.MailQueue;
import com.sap.sse.security.UserStore;
public class SailingNotificationServiceImpl implements SailingNotificationService {
private static final String STRING_MESSAGES_BASE_NAME = "stringmessages/StringMessages";
public static final String STRING_MESSAGES_BASE_NAME = "stringmessages/StringMessages";
private static final Logger logger = Logger.getLogger(SailingNotificationServiceImpl.class.getName());
@@ -239,7 +239,9 @@ public class SailingNotificationServiceImpl implements SailingNotificationServic
String raceDescription = calculateRaceDescription(locale, event, leaderboard, raceColumn, fleet);
return new NotificationMailTemplate(
messages.get(locale, "boatClassRaceFinishedSubject", boatClass.getDisplayName()),
messages.get(locale, "boatClassRaceFinishedBody", boatClass.getDisplayName(), raceDescription),
messages.get(locale, "boatClassRaceFinishedBody", boatClass.getDisplayName(),
raceDescription),
getBaseURL(event),
createRaceBoardShowRaceLink(trackedRace, leaderboard, event, leaderboardGroup, locale),
createRaceBoardRaceAnalysisLink(trackedRace, leaderboard, event, leaderboardGroup, locale));
}
@@ -258,7 +260,9 @@ public class SailingNotificationServiceImpl implements SailingNotificationServic
String leaderboardDescription = calculateLeaderboardDescription(locale, event, leaderboard);
return new NotificationMailTemplate(
messages.get(locale, "boatClassScoreCorrectionSubject", boatClass.getDisplayName()),
messages.get(locale, "boatClassScoreCorrectionBody", boatClass.getDisplayName(), leaderboardDescription),
messages.get(locale, "boatClassScoreCorrectionBody", boatClass.getDisplayName(),
leaderboardDescription),
getBaseURL(event),
createHomeLeaderboardLink(leaderboard, event, locale));
}
});
@@ -278,7 +282,8 @@ public class SailingNotificationServiceImpl implements SailingNotificationServic
return new NotificationMailTemplate(
messages.get(locale, "boatClassUpcomingRaceSubject", boatClass.getDisplayName()),
messages.get(locale, "boatClassUpcomingRaceBody", boatClass.getDisplayName(),
raceDescription, time),
raceDescription, time),
getBaseURL(event),
createHomeRacesListLink(leaderboard, event, locale));
}
});
@@ -295,8 +300,9 @@ public class SailingNotificationServiceImpl implements SailingNotificationServic
protected NotificationMailTemplate getMailTemplate(Competitor objectToNotifyAbout, Locale locale) {
String raceDescription = calculateRaceDescription(locale, event, leaderboard, raceColumn, fleet);
return new NotificationMailTemplate(
messages.get(locale, "competitorPassesFinishSubject", competitor.getName()),
messages.get(locale, "competitorPassesFinishBody", competitor.getName(), raceDescription),
messages.get(locale, "competitorPassesFinishSubject", competitor.getName()),
messages.get(locale, "competitorPassesFinishBody", competitor.getName(), raceDescription),
getBaseURL(event),
createRaceBoardShowRaceLink(trackedRace, leaderboard, event, leaderboardGroup, locale),
createRaceBoardRaceAnalysisLink(trackedRace, leaderboard, event, leaderboardGroup, locale));
}
@@ -313,8 +319,10 @@ public class SailingNotificationServiceImpl implements SailingNotificationServic
protected NotificationMailTemplate getMailTemplate(Competitor objectToNotifyAbout, Locale locale) {
String leaderboardDescription = calculateLeaderboardDescription(locale, event, leaderboard);
return new NotificationMailTemplate(
messages.get(locale, "competitorScoreCorrectionSubject", competitor.getName()),
messages.get(locale, "competitorScoreCorrectionBody", competitor.getName(), leaderboardDescription),
messages.get(locale, "competitorScoreCorrectionSubject", competitor.getName()),
messages.get(locale, "competitorScoreCorrectionBody", competitor.getName(),
leaderboardDescription),
getBaseURL(event),
createHomeLeaderboardLink(leaderboard, event, locale));
}
});