aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--juick-core/src/main/java/com/juick/util/DateFormatter.java38
-rw-r--r--juick-core/src/main/java/com/juick/util/DateFormattersHolder.java43
-rw-r--r--juick-core/src/main/java/com/juick/util/MessageUtils.java2
-rw-r--r--juick-core/src/main/java/com/juick/xml/adapters/SimpleDateAdapter.java23
-rw-r--r--juick-core/src/test/java/com/juick/FormatterTest.java45
-rw-r--r--juick-rss/src/main/java/com/juick/rss/Main.java16
-rw-r--r--juick-www/src/main/java/com/juick/www/RSS.java6
-rw-r--r--juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickMessage.java132
-rw-r--r--src/test/java/com/juick/json/MessageSerializer.java19
-rw-r--r--src/test/java/com/juick/tests/MessageTests.java5
10 files changed, 210 insertions, 119 deletions
diff --git a/juick-core/src/main/java/com/juick/util/DateFormatter.java b/juick-core/src/main/java/com/juick/util/DateFormatter.java
new file mode 100644
index 00000000..34585c63
--- /dev/null
+++ b/juick-core/src/main/java/com/juick/util/DateFormatter.java
@@ -0,0 +1,38 @@
+package com.juick.util;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
+
+/**
+ * Created by aalexeev on 12/7/16.
+ */
+public class DateFormatter {
+ private final DateTimeFormatter formatter;
+
+ DateFormatter(String pattern) {
+ formatter = DateTimeFormatter.ofPattern(pattern);
+ }
+
+ public String format(final Date date) {
+ if (date == null)
+ return null;
+
+ LocalDateTime ldt = LocalDateTime.ofInstant(date.toInstant(), ZoneOffset.UTC);
+
+ return ldt.format(formatter);
+ }
+
+
+ public Date parse(final String v) {
+ if (StringUtils.isBlank(v))
+ return null;
+
+ LocalDateTime ldt = LocalDateTime.parse(v, formatter);
+
+ return Date.from(ldt.toInstant(ZoneOffset.UTC));
+ }
+}
diff --git a/juick-core/src/main/java/com/juick/util/DateFormattersHolder.java b/juick-core/src/main/java/com/juick/util/DateFormattersHolder.java
new file mode 100644
index 00000000..79414808
--- /dev/null
+++ b/juick-core/src/main/java/com/juick/util/DateFormattersHolder.java
@@ -0,0 +1,43 @@
+package com.juick.util;
+
+/**
+ * Created by aalexeev on 12/7/16.
+ */
+public class DateFormattersHolder {
+
+ private DateFormattersHolder() {
+ throw new IllegalStateException();
+ }
+
+ private static volatile DateFormatter messageFormatter;
+
+ public static DateFormatter getMessageFormatterInstance() {
+ DateFormatter localInstance = messageFormatter;
+
+ if (localInstance == null) {
+ synchronized (DateFormatter.class) {
+ localInstance = messageFormatter;
+
+ if (localInstance == null)
+ messageFormatter = localInstance = new DateFormatter("yyyy-MM-dd HH:mm:ss");
+ }
+ }
+ return localInstance;
+ }
+
+ private static volatile DateFormatter rssFormatter;
+
+ public static DateFormatter getRssFormatterInstance() {
+ DateFormatter localInstance = rssFormatter;
+
+ if (localInstance == null) {
+ synchronized (DateFormatter.class) {
+ localInstance = rssFormatter;
+
+ if (localInstance == null)
+ rssFormatter = localInstance = new DateFormatter("EEE, d MMM yyyy HH:mm:ss");
+ }
+ }
+ return localInstance;
+ }
+}
diff --git a/juick-core/src/main/java/com/juick/util/MessageUtils.java b/juick-core/src/main/java/com/juick/util/MessageUtils.java
index 12ae71c1..96d650a8 100644
--- a/juick-core/src/main/java/com/juick/util/MessageUtils.java
+++ b/juick-core/src/main/java/com/juick/util/MessageUtils.java
@@ -24,6 +24,7 @@ public class MessageUtils {
return result;
}
+
private static Pattern regexLinks2 = Pattern.compile("((?<=\\s)|(?<=\\A))([\\[\\{]|&lt;)((?:ht|f)tps?://(?:www\\.)?([^\\/\\s\\\"\\)\\!]+)/?(?:[^\\]\\}](?<!&gt;))*)([\\]\\}]|&gt;)");
public static String formatMessageCode(String msg) {
@@ -48,6 +49,7 @@ public class MessageUtils {
return "<pre>" + msg + "</pre>";
}
+
public static String formatMessage(String msg) {
msg = msg.replaceAll("&", "&amp;");
msg = msg.replaceAll("<", "&lt;");
diff --git a/juick-core/src/main/java/com/juick/xml/adapters/SimpleDateAdapter.java b/juick-core/src/main/java/com/juick/xml/adapters/SimpleDateAdapter.java
index 1093e47a..382db45a 100644
--- a/juick-core/src/main/java/com/juick/xml/adapters/SimpleDateAdapter.java
+++ b/juick-core/src/main/java/com/juick/xml/adapters/SimpleDateAdapter.java
@@ -1,10 +1,9 @@
package com.juick.xml.adapters;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.TimeZone;
+import com.juick.util.DateFormattersHolder;
import javax.xml.bind.annotation.adapters.XmlAdapter;
+import java.util.Date;
/**
* Created by vitalyster on 15.11.2016.
@@ -12,27 +11,13 @@ import javax.xml.bind.annotation.adapters.XmlAdapter;
public class SimpleDateAdapter extends XmlAdapter<String, Date> {
- private final SimpleDateFormat dateFormat;
- public SimpleDateAdapter() {
- dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- }
-
@Override
public String marshal(Date v) throws Exception {
- if (v == null) {
- return null;
- }
- synchronized (dateFormat) {
- return dateFormat.format(v);
- }
+ return DateFormattersHolder.getMessageFormatterInstance().format(v);
}
@Override
public Date unmarshal(String v) throws Exception {
- synchronized (dateFormat) {
- return dateFormat.parse(v);
- }
+ return DateFormattersHolder.getMessageFormatterInstance().parse(v);
}
-
}
diff --git a/juick-core/src/test/java/com/juick/FormatterTest.java b/juick-core/src/test/java/com/juick/FormatterTest.java
new file mode 100644
index 00000000..d246c369
--- /dev/null
+++ b/juick-core/src/test/java/com/juick/FormatterTest.java
@@ -0,0 +1,45 @@
+package com.juick;
+
+import com.juick.util.DateFormattersHolder;
+import org.apache.commons.lang3.RandomUtils;
+import org.junit.Test;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+
+/**
+ * Created by aalexeev on 12/7/16.
+ */
+public class FormatterTest {
+
+ @Test
+ public void forAnyDateFormatterShouldReturnNotEmptyString() throws Exception {
+ Date date = new Date();
+
+ assertThat(DateFormattersHolder.getMessageFormatterInstance().format(date), not(isEmptyOrNullString()));
+ assertThat(DateFormattersHolder.getRssFormatterInstance().format(date), not(isEmptyOrNullString()));
+
+ date = new Date(RandomUtils.nextLong(1, Long.MAX_VALUE / 10000));
+
+ assertThat(DateFormattersHolder.getMessageFormatterInstance().format(date), not(isEmptyOrNullString()));
+ assertThat(DateFormattersHolder.getRssFormatterInstance().format(date), not(isEmptyOrNullString()));
+ }
+
+ @Test
+ public void forConcreteDateShouldReturnCorrectString() throws Exception {
+ Calendar calendar = GregorianCalendar.getInstance();
+
+ calendar.set(2012, 0, 1, 0, 0, 0);
+ calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+ Date date = calendar.getTime();
+
+ assertThat(DateFormattersHolder.getMessageFormatterInstance().format(date), equalTo("2012-01-01 00:00:00"));
+ assertThat(DateFormattersHolder.getRssFormatterInstance().format(date), equalTo("Sun, 1 Jan 2012 00:00:00"));
+ }
+}
diff --git a/juick-rss/src/main/java/com/juick/rss/Main.java b/juick-rss/src/main/java/com/juick/rss/Main.java
index adb20a0d..8d247465 100644
--- a/juick-rss/src/main/java/com/juick/rss/Main.java
+++ b/juick-rss/src/main/java/com/juick/rss/Main.java
@@ -18,8 +18,10 @@
package com.juick.rss;
import com.juick.Message;
+import com.juick.Tag;
import com.juick.server.MessagesQueries;
import com.juick.server.UserQueries;
+import com.juick.util.DateFormattersHolder;
import com.juick.util.MessageUtils;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang3.StringEscapeUtils;
@@ -33,7 +35,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Properties;
@@ -44,7 +45,6 @@ import java.util.Properties;
@WebServlet(name = "Main", urlPatterns = {"/"})
public class Main extends HttpServlet {
- private static final SimpleDateFormat sdfRSS = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
JdbcTemplate sql;
@Override
@@ -131,19 +131,19 @@ public class Main extends HttpServlet {
out.print("<title><![CDATA[@" + msg.getUser().getName() + ":");
if (!msg.getTags().isEmpty()) {
- for (int n = 0; n < msg.getTags().size(); n++) {
- out.print(" *" + msg.getTags().get(n));
+ for (Tag tag : msg.getTags()) {
+ out.print(" *" + tag);
}
}
out.println("]]></title>");
out.println("<description><![CDATA[" + MessageUtils.formatMessage(msg.getText()) + "]]></description>");
- out.println("<pubDate>" + sdfRSS.format(msg.getDate()) + "</pubDate>");
+ out.println("<pubDate>" + DateFormattersHolder.getRssFormatterInstance().format(msg.getDate()) + "</pubDate>");
out.println("<comments>http://juick.com/" + msg.getUser().getName() + "/" + msg.getMid() + "</comments>");
if (!msg.getTags().isEmpty()) {
- for (int n = 0; n < msg.getTags().size(); n++) {
- out.println("<category>" + StringEscapeUtils.escapeHtml4(msg.getTags().get(n).getName()) + "</category>");
+ for (Tag tag : msg.getTags()) {
+ out.println("<category>" + StringEscapeUtils.escapeHtml4(tag.getName()) + "</category>");
}
}
if (msg.getAttachmentType() != null) {
@@ -209,7 +209,7 @@ public class Main extends HttpServlet {
out.println("<author>http://juick.com/" + r.uname + "/</author>");
out.println("<title>@" + r.uname + ":</title>");
out.println("<description><![CDATA[" + MessageUtils.formatMessage(r.description) + "]]></description>");
- out.println("<pubDate>" + sdfRSS.format(r.pubDate) + "</pubDate>");
+ out.println("<pubDate>" + DateFormattersHolder.getRssFormatterInstance().format(r.pubDate) + "</pubDate>");
String attachment = r.attachmentType;
if (attachment != null && !attachment.isEmpty()) {
if (attachment.equals("jpg")) {
diff --git a/juick-www/src/main/java/com/juick/www/RSS.java b/juick-www/src/main/java/com/juick/www/RSS.java
index a343d13b..91ba9380 100644
--- a/juick-www/src/main/java/com/juick/www/RSS.java
+++ b/juick-www/src/main/java/com/juick/www/RSS.java
@@ -19,6 +19,7 @@ package com.juick.www;
import com.juick.Message;
import com.juick.server.MessagesQueries;
+import com.juick.util.DateFormattersHolder;
import com.juick.util.MessageUtils;
import com.mitchellbosecke.pebble.error.PebbleException;
import com.mitchellbosecke.pebble.template.PebbleTemplate;
@@ -28,7 +29,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -39,8 +39,6 @@ import java.util.Map;
*/
public class RSS {
- private static final SimpleDateFormat sdfRSS = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
-
protected void doGet(JdbcTemplate sql, HttpServletResponse response, int uid) throws ServletException, IOException, PebbleException {
List<Integer> mids = MessagesQueries.getUserBlog(sql, uid, 0, 0);
if (mids.isEmpty()) {
@@ -58,7 +56,7 @@ public class RSS {
Map<String, Object> context = new HashMap<>();
context.put("user", msgs.stream().findFirst().get().getUser());
context.put("msgs", msgs);
- context.put("sdfRSS", sdfRSS);
+ context.put("sdfRSS", DateFormattersHolder.getRssFormatterInstance());
template.evaluate(out, context);
}
}
diff --git a/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickMessage.java b/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickMessage.java
index 18477b2a..b8a329db 100644
--- a/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickMessage.java
+++ b/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickMessage.java
@@ -18,35 +18,27 @@
package com.juick.xmpp.extensions;
import com.juick.Tag;
+import com.juick.util.DateFormattersHolder;
+import com.juick.xmpp.StanzaChild;
import com.juick.xmpp.utils.XmlUtils;
-import com.juick.xmpp.*;
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.TimeZone;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.IOException;
+import java.text.ParseException;
+
/**
- *
* @author Ugnich Anton
*/
public class JuickMessage extends com.juick.Message implements StanzaChild {
-
public final static String XMLNS = "http://juick.com/message";
public final static String TagName = "juick";
- private SimpleDateFormat df;
public JuickMessage() {
- df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- df.setTimeZone(TimeZone.getTimeZone("UTC"));
}
public JuickMessage(com.juick.Message msg) {
super(msg);
- df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- df.setTimeZone(TimeZone.getTimeZone("UTC"));
}
@Override
@@ -84,7 +76,7 @@ public class JuickMessage extends com.juick.Message implements StanzaChild {
}
String ts = parser.getAttributeValue(null, "ts");
if (ts != null) {
- jmsg.setDate(df.parse(ts));
+ jmsg.setDate(DateFormattersHolder.getMessageFormatterInstance().parse(ts));
}
jmsg.setAttachmentType(parser.getAttributeValue(null, "attach"));
@@ -106,78 +98,76 @@ public class JuickMessage extends com.juick.Message implements StanzaChild {
@Override
public String toString() {
- String ret = "";
+ StringBuilder builder = new StringBuilder();
- ret = "<" + TagName + " xmlns=\"" + XMLNS + "\"";
- if (getMid() > 0) {
- ret += " mid=\"" + getMid() + "\"";
- }
- if (getRid() > 0) {
- ret += " rid=\"" + getRid() + "\"";
- }
- if (getReplyto() > 0) {
- ret += " replyto=\"" + getReplyto() + "\"";
- }
- ret += " privacy=\"" + getPrivacy() + "\"";
- if (FriendsOnly) {
- ret += " friendsonly=\"1\"";
- }
- if (ReadOnly) {
- ret += " readonly=\"1\"";
- }
- if (getDate() != null) {
- ret += " ts=\"" + df.format(getDate()) + "\"";
- }
- if (getAttachmentType() != null) {
- ret += " attach=\"" + getAttachmentType() + "\"";
- }
- ret += ">";
- if (getUser() != null) {
- ret += JuickUser.toString(getUser());
- }
- if (getText() != null) {
- ret += "<body>" + XmlUtils.escape(getText()) + "</body>";
- }
- for (com.juick.Tag Tag : getTags()) {
- ret += "<tag>" + XmlUtils.escape(Tag.getName()) + "</tag>";
- }
- ret += "</" + TagName + ">";
+ builder.append("<").append(TagName).append(" xmlns=\"").append(XMLNS).append("\"");
+
+ if (getMid() > 0)
+ builder.append(" mid=\"").append(getMid()).append("\"");
+
+ if (getRid() > 0)
+ builder.append(" rid=\"").append(getRid()).append("\"");
+
+ if (getReplyto() > 0)
+ builder.append(" replyto=\"").append(getReplyto()).append("\"");
+
+ builder.append(" privacy=\"").append(getPrivacy()).append("\"");
+
+ if (FriendsOnly)
+ builder.append(" friendsonly=\"1\"");
- return ret;
+ if (ReadOnly)
+ builder.append(" readonly=\"1\"");
+
+ if (getDate() != null)
+ builder.append(" ts=\"")
+ .append(DateFormattersHolder.getMessageFormatterInstance().format(getDate()))
+ .append("\"");
+
+ if (getAttachmentType() != null)
+ builder.append(" attach=\"").append(getAttachmentType()).append("\"");
+
+ builder.append(">");
+
+ if (getUser() != null)
+ builder.append(JuickUser.toString(getUser()));
+
+ if (getText() != null)
+ builder.append("<body>").append(XmlUtils.escape(getText())).append("</body>");
+
+ for (com.juick.Tag Tag : getTags())
+ builder.append("<tag>").append(XmlUtils.escape(Tag.getName())).append("</tag>");
+
+ builder.append("</").append(TagName).append(">");
+
+ return builder.toString();
}
@Override
public boolean equals(Object obj) {
- if (!(obj instanceof JuickMessage)) {
+ if (obj == this)
+ return true;
+
+ if (!(obj instanceof JuickMessage))
return false;
- }
+
JuickMessage jmsg = (JuickMessage) obj;
return (this.getMid() == jmsg.getMid() && this.getRid() == jmsg.getRid());
}
@Override
public int compareTo(Object obj) throws ClassCastException {
- if (!(obj instanceof JuickMessage)) {
- throw new ClassCastException();
- }
- JuickMessage jmsg = (JuickMessage) obj;
+ if (obj == this)
+ return 0;
- if (this.getMid() != jmsg.getMid()) {
- if (this.getMid() > jmsg.getMid()) {
- return -1;
- } else {
- return 1;
- }
- }
+ if (!(obj instanceof JuickMessage))
+ throw new ClassCastException();
- if (this.getRid() != jmsg.getRid()) {
- if (this.getRid() < jmsg.getRid()) {
- return -1;
- } else {
- return 1;
- }
- }
+ JuickMessage jmsg = (JuickMessage) obj;
+ int cmp = Integer.compare(jmsg.getMid(), getMid());
+ if (cmp == 0)
+ cmp = Integer.compare(getRid(), jmsg.getRid());
- return 0;
+ return cmp;
}
}
diff --git a/src/test/java/com/juick/json/MessageSerializer.java b/src/test/java/com/juick/json/MessageSerializer.java
index b49c991a..7ed060dd 100644
--- a/src/test/java/com/juick/json/MessageSerializer.java
+++ b/src/test/java/com/juick/json/MessageSerializer.java
@@ -20,6 +20,7 @@ package com.juick.json;
import com.juick.Message;
import com.juick.Photo;
import com.juick.Tag;
+import com.juick.util.DateFormattersHolder;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -27,26 +28,18 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.TimeZone;
import java.util.stream.Collectors;
/**
- *
* @author Ugnich Anton
*/
public class MessageSerializer extends JSONSerializer<Message> {
-
private final static Logger LOGGER = LoggerFactory.getLogger(MessageSerializer.class);
-
+
UserSerializer userSerializer = new UserSerializer();
PlaceSerializer placeSerializer = new PlaceSerializer();
- private final SimpleDateFormat df;
-
public MessageSerializer() {
- df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- df.setTimeZone(TimeZone.getTimeZone("UTC"));
}
@Override
@@ -66,7 +59,7 @@ public class MessageSerializer extends JSONSerializer<Message> {
jmsg.setText(json.getString("body").replace("&quot;", "\""));
jmsg.setUser(userSerializer.deserialize(json.getJSONObject("user")));
- jmsg.setDate(df.parse(json.getString("timestamp")));
+ jmsg.setDate(DateFormattersHolder.getMessageFormatterInstance().parse(json.getString("timestamp")));
if (json.has("tags")) {
JSONArray tags = json.getJSONArray("tags");
@@ -115,7 +108,7 @@ public class MessageSerializer extends JSONSerializer<Message> {
json.put("body", msg.getText());
}
if (msg.getDate() != null) {
- json.put("timestamp", df.format(msg.getDate()));
+ json.put("timestamp", DateFormattersHolder.getMessageFormatterInstance().format(msg.getDate()));
}
if (msg.getUser() != null) {
json.put("user", userSerializer.serialize(msg.getUser()));
@@ -145,8 +138,4 @@ public class MessageSerializer extends JSONSerializer<Message> {
return json;
}
-
- public SimpleDateFormat getDf() {
- return df;
- }
}
diff --git a/src/test/java/com/juick/tests/MessageTests.java b/src/test/java/com/juick/tests/MessageTests.java
index 45575ded..a0cfd444 100644
--- a/src/test/java/com/juick/tests/MessageTests.java
+++ b/src/test/java/com/juick/tests/MessageTests.java
@@ -3,6 +3,7 @@ package com.juick.tests;
import static org.junit.Assert.assertEquals;
import com.juick.json.MessageSerializer;
+import com.juick.util.DateFormattersHolder;
import com.juick.xmpp.extensions.JuickMessage;
import org.json.JSONObject;
import org.junit.Test;
@@ -33,7 +34,7 @@ public class MessageTests {
msg.setDate(currentDate);
MessageSerializer serializer = new MessageSerializer();
JSONObject jsonMessage = serializer.serialize(msg);
- assertEquals("date should be in timestamp field", serializer.getDf().format(currentDate),
+ assertEquals("date should be in timestamp field", DateFormattersHolder.getMessageFormatterInstance().format(currentDate),
jsonMessage.getString("timestamp"));
JuickMessage xmppMessage = new JuickMessage(msg);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
@@ -42,7 +43,7 @@ public class MessageTests {
Document doc = db.parse(new ByteArrayInputStream(xmppMessage.toString().getBytes("UTF-8")));
Node juickNode = doc.getElementsByTagName("juick").item(0);
NamedNodeMap attrs = juickNode.getAttributes();
- assertEquals("date should be in ts field", serializer.getDf().format(currentDate),
+ assertEquals("date should be in ts field", DateFormattersHolder.getMessageFormatterInstance().format(currentDate),
attrs.getNamedItem("ts").getNodeValue());
}
} \ No newline at end of file