From 2cfabeab2e64a1b8b6db32a0135a2fce06bc87ab Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Tue, 15 Nov 2016 15:56:06 +0300 Subject: all components using babbler now, only juick-xmpp uses ugnich xmpp --- .gitmodules | 3 - build.gradle | 1 + deps/com.juick.xmpp | 1 - juick-api/build.gradle | 4 +- juick-api/src/main/java/com/juick/api/Main.java | 131 +++++----- .../src/main/java/com/juick/api/Messages.java | 26 +- juick-api/src/main/java/com/juick/api/PM.java | 33 ++- juick-core/build.gradle | 3 - .../com/juick/xmpp/extensions/JuickMessage.java | 183 -------------- .../java/com/juick/xmpp/extensions/JuickUser.java | 75 ------ juick-crosspost/build.gradle | 3 + .../main/java/com/juick/components/Crosspost.java | 88 +++---- .../configuration/CrosspostAppConfiguration.java | 10 +- juick-notifications/build.gradle | 3 + .../java/com/juick/components/Notifications.java | 269 +++++++++------------ .../NotificationsAppConfiguration.java | 9 +- juick-ws/build.gradle | 4 +- .../src/main/java/com/juick/ws/XMPPConnection.java | 89 +++---- juick-xmpp/build.gradle | 2 + .../com/juick/xmpp/extensions/JuickMessage.java | 183 ++++++++++++++ .../java/com/juick/xmpp/extensions/JuickUser.java | 75 ++++++ server-core/build.gradle | 2 - .../com/juick/server/protocol/JuickProtocol.java | 3 +- settings.gradle | 2 +- 24 files changed, 550 insertions(+), 652 deletions(-) delete mode 160000 deps/com.juick.xmpp delete mode 100644 juick-core/src/main/java/com/juick/xmpp/extensions/JuickMessage.java delete mode 100644 juick-core/src/main/java/com/juick/xmpp/extensions/JuickUser.java create mode 100644 juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickMessage.java create mode 100644 juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickUser.java diff --git a/.gitmodules b/.gitmodules index 4c3e6649..9fbba638 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "deps/com.juick.xmpp"] - path = deps/com.juick.xmpp - url = https://github.com/juick/com.juick.xmpp.git [submodule "juick-www/src/main/resources/help"] path = juick-www/src/main/resources/help url = https://github.com/juick/help.git diff --git a/build.gradle b/build.gradle index bcdadd1c..8c4787aa 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,7 @@ repositories { dependencies { testCompile project(':juick-core') testCompile project(':juick-www') + testCompile project(':juick-xmpp') testCompile 'com.fasterxml.jackson.core:jackson-core:2.8.1' testCompile 'com.fasterxml.jackson.core:jackson-databind:2.8.1' testCompile 'org.springframework:spring-jdbc:4.3.4.RELEASE' diff --git a/deps/com.juick.xmpp b/deps/com.juick.xmpp deleted file mode 160000 index dbf603cf..00000000 --- a/deps/com.juick.xmpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dbf603cfff3a8fe26d711381e59e4ec6f1c66031 diff --git a/juick-api/build.gradle b/juick-api/build.gradle index 7e257ac3..da1a4638 100644 --- a/juick-api/build.gradle +++ b/juick-api/build.gradle @@ -15,11 +15,13 @@ apply plugin: 'com.github.tkruse.groovysh' repositories { mavenCentral() + maven { url "https://jitpack.io" } } dependencies { compile project(':server-core') - compile project(':deps:com.juick.xmpp') + compile 'org.bitbucket.sco0ter.babbler:xmpp-core-client:279e488e51' + compile 'org.bitbucket.sco0ter.babbler:xmpp-extensions-client:279e488e51' providedCompile 'javax.servlet:javax.servlet-api:3.1.0' compile 'com.github.pengrad:java-telegram-bot-api:2.1.4' compile 'org.msbotframework4j:msbotframework4j-builder:0.1.4' diff --git a/juick-api/src/main/java/com/juick/api/Main.java b/juick-api/src/main/java/com/juick/api/Main.java index c102bf18..2ca126d0 100644 --- a/juick-api/src/main/java/com/juick/api/Main.java +++ b/juick-api/src/main/java/com/juick/api/Main.java @@ -23,17 +23,19 @@ import com.juick.server.MessagesQueries; import com.juick.server.SubscriptionsQueries; import com.juick.server.TagQueries; import com.juick.server.UserQueries; -import com.juick.xmpp.JID; -import com.juick.xmpp.Message; -import com.juick.xmpp.Stream; -import com.juick.xmpp.StreamComponent; -import com.juick.xmpp.extensions.JuickMessage; -import com.juick.xmpp.extensions.Nickname; -import com.juick.xmpp.extensions.XOOB; import net.coobird.thumbnailator.Thumbnails; import org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.lang3.math.NumberUtils; import org.springframework.jdbc.core.JdbcTemplate; +import rocks.xmpp.addr.Jid; +import rocks.xmpp.core.XmppException; +import rocks.xmpp.core.session.Extension; +import rocks.xmpp.core.session.XmppSession; +import rocks.xmpp.core.session.XmppSessionConfiguration; +import rocks.xmpp.core.stanza.model.Message; +import rocks.xmpp.extensions.component.accept.ExternalComponent; +import rocks.xmpp.extensions.nick.model.Nickname; +import rocks.xmpp.extensions.oob.model.x.OobX; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; @@ -44,7 +46,8 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; -import java.net.Socket; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -52,19 +55,16 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Properties; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - /** * * @author Ugnich Anton */ @WebServlet(name = "Main", urlPatterns = {"/"}) @MultipartConfig -public class Main extends HttpServlet implements Stream.StreamListener { +public class Main extends HttpServlet { JdbcTemplate jdbc; - Stream xmpp; + ExternalComponent xmpp; Messages messages; Users users; PM pm; @@ -104,27 +104,15 @@ public class Main extends HttpServlet implements Stream.StreamListener { } public void setupXmppComponent(final String host, final int port, final String jid, final String password) { - ExecutorService executorService = Executors.newSingleThreadExecutor(); - executorService.submit(() -> { - try { - Socket socket = new Socket(host, port); - xmpp = new StreamComponent(new JID(jid), socket.getInputStream(), socket.getOutputStream(), password); - xmpp.addListener(Main.this); - xmpp.startParsing(); - } catch (IOException e) { - log("XMPP exception", e); - } - }); - } - - @Override - public void onStreamFail(Exception e) { - log("XMPP failed", e); - } - - @Override - public void onStreamReady() { - log("XMPP STREAM READY"); + XmppSessionConfiguration configuration = XmppSessionConfiguration.builder() + .extensions(Extension.of(com.juick.Message.class)) + .build(); + xmpp = ExternalComponent.create(jid, password, configuration, host, port); + try { + xmpp.connect(); + } catch (XmppException e) { + log("xmpp extension", e); + } } /** @@ -246,7 +234,7 @@ public class Main extends HttpServlet implements Stream.StreamListener { } } - public void doPostMessage(JdbcTemplate sql, HttpServletRequest request, HttpServletResponse response, Stream xmpp, int vuid) + public void doPostMessage(JdbcTemplate sql, HttpServletRequest request, HttpServletResponse response, XmppSession xmpp, int vuid) throws ServletException, IOException { String body = request.getParameter("body"); if (body == null || body.length() < 1 || body.length() > 4096) { @@ -298,18 +286,15 @@ public class Main extends HttpServlet implements Stream.StreamListener { String attachmentType = attachmentFName != null ? attachmentFName.substring(attachmentFName.length() - 3) : null; int mid = MessagesQueries.createMessage(sql, vuid, body, attachmentType, tags); SubscriptionsQueries.subscribeMessage(sql, mid, vuid); - JuickMessage jmsg = new JuickMessage(MessagesQueries.getMessage(sql, mid)); + com.juick.Message jmsg = MessagesQueries.getMessage(sql, mid); if (xmpp != null) { Message xmsg = new Message(); - xmsg.from = new JID("juick", "juick.com", null); - xmsg.type = Message.Type.chat; - xmsg.thread = "juick-" + mid; + xmsg.setFrom(Jid.of("juick@juick.com")); + xmsg.setType(Message.Type.CHAT); + xmsg.setThread("juick-" + mid); - xmsg.addChild(jmsg); - - Nickname nick = new Nickname(); - nick.Nickname = "@" + jmsg.getUser().getName(); - xmsg.addChild(nick); + xmsg.addExtension(jmsg); + xmsg.addExtension(new Nickname("@" + jmsg.getUser().getName())); if (attachmentFName != null) { String fname = mid + "." + attachmentType; @@ -325,34 +310,35 @@ public class Main extends HttpServlet implements Stream.StreamListener { .toFile(Paths.get(imgDir, "ps", fname).toFile()); body = attachmentURL + "\n" + body; - XOOB xoob = new XOOB(); - xoob.URL = attachmentURL; - xmsg.addChild(xoob); + try { + OobX xoob = new OobX(new URI(attachmentURL)); + xmsg.addExtension(xoob); + } catch (URISyntaxException e) { + log("invalid uri: " + attachmentURL, e); + } } String tagsStr2 = ""; for (String tag : tagsArr) { tagsStr2 += " *" + tag; } - xmsg.body = "@" + jmsg.getUser().getName() + ":" + tagsStr2 + "\n" + body + "\n\n#" + mid + " http://juick.com/" + mid; + xmsg.setBody("@" + jmsg.getUser().getName() + ":" + tagsStr2 + "\n" + body + "\n\n#" + mid + " http://juick.com/" + mid); - xmsg.to = new JID("juick", "s2s.juick.com", null); + xmsg.setTo(Jid.of("juick@s2s.juick.com")); xmpp.send(xmsg); - xmsg.to.Host = "ws.juick.com"; + xmsg.setTo(Jid.of("juick@ws.juick.com")); xmpp.send(xmsg); - xmsg.to.Host = "push.juick.com"; + xmsg.setTo(Jid.of("juick@push.juick.com")); xmpp.send(xmsg); - xmsg.to.Host = "crosspost.juick.com"; - xmsg.to.Username = "twitter"; + xmsg.setTo(Jid.of("twitter@crosspost.juick.com")); xmpp.send(xmsg); - xmsg.to.Username = "fb"; + xmsg.setTo(Jid.of("fb@crosspost.juick.com")); xmpp.send(xmsg); - xmsg.to.Host = "nologin.ru"; - xmsg.to.Username = "jubo"; + xmsg.setTo(Jid.of("jubo@nologin.ru")); xmpp.send(xmsg); } else { log("XMPP unavailable"); @@ -361,7 +347,7 @@ public class Main extends HttpServlet implements Stream.StreamListener { Main.replyJSON(request, response, serializer.serialize(jmsg).toString()); } - public void doPostComment(JdbcTemplate sql, HttpServletRequest request, HttpServletResponse response, Stream xmpp, int vuid) + public void doPostComment(JdbcTemplate sql, HttpServletRequest request, HttpServletResponse response, XmppSession xmpp, int vuid) throws ServletException, IOException { int mid = NumberUtils.toInt(request.getParameter("mid"), 0); if (mid == 0) { @@ -421,23 +407,21 @@ public class Main extends HttpServlet implements Stream.StreamListener { int ridnew = MessagesQueries.createReply(sql, mid, rid, vuid, body, attachmentType); SubscriptionsQueries.subscribeMessage(sql, mid, vuid); - JuickMessage jmsg = new JuickMessage(MessagesQueries.getReply(sql, mid, ridnew)); + com.juick.Message jmsg = MessagesQueries.getReply(sql, mid, ridnew); if (xmpp != null) { Message xmsg = new Message(); - xmsg.from = new JID("juick", "juick.com", null); - xmsg.type = Message.Type.chat; - xmsg.thread = "juick-" + mid; - xmsg.addChild(jmsg); + xmsg.setFrom(Jid.of("juick@juick.com")); + xmsg.setType(Message.Type.CHAT); + xmsg.setThread("juick-" + mid); + xmsg.addExtension(jmsg); String quote = reply != null ? reply.getText() : msg.getText(); if (quote.length() >= 50) { quote = quote.substring(0, 47) + "..."; } - Nickname nick = new Nickname(); - nick.Nickname = "@" + jmsg.getUser().getName(); - xmsg.addChild(nick); + xmsg.addExtension(new Nickname("@" + jmsg.getUser().getName())); if (attachmentFName != null) { String fname = mid + "-" + ridnew + "." + attachmentType; @@ -453,20 +437,23 @@ public class Main extends HttpServlet implements Stream.StreamListener { .toFile(Paths.get(imgDir, "ps", fname).toFile()); body = attachmentURL + "\n" + body; - XOOB xoob = new XOOB(); - xoob.URL = attachmentURL; - xmsg.addChild(xoob); + try { + xmsg.addExtension(new OobX(new URI(attachmentURL))); + } catch (URISyntaxException e) { + log("invalid uri: " + attachmentURL, e); + } } - xmsg.body = "Reply by @" + jmsg.getUser().getName() + ":\n>" + quote + "\n" + body + "\n\n#" + mid + "/" + ridnew + " http://juick.com/" + mid + "#" + ridnew; + xmsg.setBody("Reply by @" + jmsg.getUser().getName() + ":\n>" + quote + "\n" + body + "\n\n#" + + mid + "/" + ridnew + " http://juick.com/" + mid + "#" + ridnew); - xmsg.to = new JID("juick", "s2s.juick.com", null); + xmsg.setTo(Jid.of("juick@s2s.juick.com")); xmpp.send(xmsg); - xmsg.to.Host = "ws.juick.com"; + xmsg.setTo(Jid.of("juick@ws.juick.com")); xmpp.send(xmsg); - xmsg.to.Host = "push.juick.com"; + xmsg.setTo(Jid.of("juick@push.juick.com")); xmpp.send(xmsg); } else { log("XMPP unavailable"); diff --git a/juick-api/src/main/java/com/juick/api/Messages.java b/juick-api/src/main/java/com/juick/api/Messages.java index de845d45..93abb06b 100644 --- a/juick-api/src/main/java/com/juick/api/Messages.java +++ b/juick-api/src/main/java/com/juick/api/Messages.java @@ -7,15 +7,14 @@ import com.juick.json.MessageSerializer; import com.juick.server.MessagesQueries; import com.juick.server.TagQueries; import com.juick.server.UserQueries; -import com.juick.xmpp.JID; -import com.juick.xmpp.Message; -import com.juick.xmpp.Stream; -import com.juick.xmpp.extensions.JuickMessage; import org.apache.commons.lang3.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.util.StringUtils; +import rocks.xmpp.addr.Jid; +import rocks.xmpp.core.session.XmppSession; +import rocks.xmpp.core.stanza.model.Message; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -140,7 +139,7 @@ public class Messages { } public void doSetPrivacy(HttpServletRequest request, - HttpServletResponse response, Stream xmpp, int vuid) + HttpServletResponse response, XmppSession xmpp, int vuid) throws ServletException, IOException { int mid = NumberUtils.toInt(request.getParameter("mid"), 0); com.juick.User user = MessagesQueries.getMessageAuthor(sql, mid); @@ -152,7 +151,7 @@ public class Messages { } public void doSetPopular(HttpServletRequest request, - HttpServletResponse response, Stream xmpp) + HttpServletResponse response, XmppSession xmpp) throws ServletException, IOException { int mid = NumberUtils.toInt(request.getParameter("mid"), 0); int popular = NumberUtils.toInt(request.getParameter("popular"), 0); @@ -165,17 +164,16 @@ public class Messages { com.juick.Message m = MessagesQueries.getMessage(sql, mid); if (m != null) { Message msg = new Message(); - msg.from = new JID("juick", "juick.com", null); - msg.to = new JID(null, "crosspost.juick.com", null); - JuickMessage jmsg = new JuickMessage(m); - jmsg.setUser(UserQueries.getUserByUID(sql, 11574).get()); - msg.childs.add(jmsg); + msg.setFrom(Jid.of("juick@juick.com")); + msg.setTo(Jid.of("crosspost.juick.com")); + m.setUser(UserQueries.getUserByUID(sql, 11574).get()); + msg.addExtension(m); - msg.to.Username = "twitter"; + msg.setTo(Jid.of("twitter@crosspost.juick.com")); xmpp.send(msg); - msg.to.Username = "fb"; + msg.setTo(Jid.of("fb@crosspost.juick.com")); xmpp.send(msg); - msg.to.Username = "vk"; + msg.setTo(Jid.of("vk@crosspost.juick.com")); xmpp.send(msg); } else { throw new Exception("Message not found"); diff --git a/juick-api/src/main/java/com/juick/api/PM.java b/juick-api/src/main/java/com/juick/api/PM.java index d8f17366..86d9c534 100644 --- a/juick-api/src/main/java/com/juick/api/PM.java +++ b/juick-api/src/main/java/com/juick/api/PM.java @@ -4,11 +4,10 @@ import com.juick.json.MessageSerializer; import com.juick.server.PMQueries; import com.juick.server.UserQueries; import com.juick.util.UserUtils; -import com.juick.xmpp.JID; -import com.juick.xmpp.Message; -import com.juick.xmpp.Stream; -import com.juick.xmpp.extensions.JuickMessage; import org.springframework.jdbc.core.JdbcTemplate; +import rocks.xmpp.addr.Jid; +import rocks.xmpp.core.session.XmppSession; +import rocks.xmpp.core.stanza.model.Message; import java.io.IOException; import java.util.List; @@ -53,8 +52,8 @@ public class PM { } } - public void doPostPM(HttpServletRequest request, - HttpServletResponse response, Stream xmpp, int vuid) + public void doPostPM(HttpServletRequest request, + HttpServletResponse response, XmppSession xmpp, int vuid) throws ServletException, IOException { String uname = request.getParameter("uname"); int uid = 0; @@ -75,15 +74,15 @@ public class PM { if (PMQueries.createPM(sql, vuid, uid, body)) { Message msg = new Message(); - msg.from = new JID("juick", "juick.com", null); - msg.to = new JID(Integer.toString(uid), "push.juick.com", null); - JuickMessage jmsg = new JuickMessage(); + msg.setFrom(Jid.of("juick@juick.com")); + msg.setTo(Jid.of(String.format("%d@push.juick.com", uid))); + com.juick.Message jmsg = new com.juick.Message(); jmsg.setUser(UserQueries.getUserByUID(sql, vuid).get()); jmsg.setText(body); - msg.childs.add(jmsg); + msg.addExtension(jmsg); xmpp.send(msg); - msg.to.Host = "ws.juick.com"; + msg.setTo(Jid.of(String.format("%d@ws.juick.com", uid))); xmpp.send(msg); Main.replyJSON(request, response, messageSerializer.serialize(jmsg).toString()); @@ -91,14 +90,14 @@ public class PM { List jids = UserQueries.getJIDsbyUID(sql, uid); for (String jid: jids) { Message mm = new Message(); - mm.to = new JID(jid); - mm.type = Message.Type.chat; + mm.setTo(Jid.of(jid)); + mm.setType(Message.Type.CHAT); if (PMQueries.havePMinRoster(sql, vuid, jid)) { - mm.from = new JID(jmsg.getUser().getName(), "juick.com", "Juick"); - mm.body = body; + mm.setFrom(Jid.of(jmsg.getUser().getName(), "juick.com", "Juick")); + mm.setBody(body); } else { - mm.from = new JID("juick", "juick.com", "Juick"); - mm.body = "Private message from @" + jmsg.getUser().getName() + ":\n" + body; + mm.setFrom(Jid.of("juick", "juick.com", "Juick")); + mm.setBody("Private message from @" + jmsg.getUser().getName() + ":\n" + body); } xmpp.send(mm); } diff --git a/juick-core/build.gradle b/juick-core/build.gradle index 6bdd326c..1f3ce9cd 100644 --- a/juick-core/build.gradle +++ b/juick-core/build.gradle @@ -9,10 +9,7 @@ def slf4jVersion = '1.7.21' def jacksonVersion = '2.8.4' dependencies { - compile project(':deps:com.juick.xmpp') - compile "com.fasterxml.jackson.core:jackson-annotations:${jacksonVersion}" - compile "org.slf4j:slf4j-api:${slf4jVersion}" compile 'org.apache.httpcomponents:httpclient:4.5.2' compile 'org.apache.commons:commons-lang3:3.5' diff --git a/juick-core/src/main/java/com/juick/xmpp/extensions/JuickMessage.java b/juick-core/src/main/java/com/juick/xmpp/extensions/JuickMessage.java deleted file mode 100644 index 2c3875c5..00000000 --- a/juick-core/src/main/java/com/juick/xmpp/extensions/JuickMessage.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Juick - * Copyright (C) 2008-2011, Ugnich Anton - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.juick.xmpp.extensions; - -import com.juick.Tag; -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; - -/** - * - * @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 - public String getXMLNS() { - return XMLNS; - } - - @Override - public JuickMessage parse(XmlPullParser parser) throws XmlPullParserException, IOException, ParseException { - JuickMessage jmsg = new JuickMessage(); - - final String sMID = parser.getAttributeValue(null, "mid"); - if (sMID != null) { - jmsg.setMid(Integer.parseInt(sMID)); - } - final String sRID = parser.getAttributeValue(null, "rid"); - if (sRID != null) { - jmsg.setRid(Integer.parseInt(sRID)); - } - final String sReplyTo = parser.getAttributeValue(null, "replyto"); - if (sReplyTo != null) { - jmsg.setReplyto(Integer.parseInt(sReplyTo)); - } - final String sPrivacy = parser.getAttributeValue(null, "privacy"); - if (sPrivacy != null) { - jmsg.setPrivacy(Integer.parseInt(sPrivacy)); - } - final String sFriendsOnly = parser.getAttributeValue(null, "friendsonly"); - if (sFriendsOnly != null) { - jmsg.FriendsOnly = true; - } - final String sReadOnly = parser.getAttributeValue(null, "readonly"); - if (sReadOnly != null) { - jmsg.ReadOnly = true; - } - String ts = parser.getAttributeValue(null, "ts"); - if (ts != null) { - jmsg.setDate(df.parse(ts)); - } - jmsg.AttachmentType = parser.getAttributeValue(null, "attach"); - - while (parser.next() == XmlPullParser.START_TAG) { - final String tag = parser.getName(); - final String xmlns = parser.getNamespace(); - if (tag.equals("body")) { - jmsg.setText(XmlUtils.getTagText(parser)); - } else if (tag.equals(JuickUser.TagName) && xmlns != null && xmlns.equals(JuickUser.XMLNS)) { - jmsg.setUser(new JuickUser().parse(parser)); - } else if (tag.equals("tag")) { - jmsg.getTags().add(new Tag(XmlUtils.getTagText(parser))); - } else { - XmlUtils.skip(parser); - } - } - return jmsg; - } - - @Override - public String toString() { - String ret = ""; - - 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 (AttachmentType != null) { - ret += " attach=\"" + AttachmentType + "\""; - } - ret += ">"; - if (getUser() != null) { - ret += JuickUser.toString(getUser()); - } - if (getText() != null) { - ret += "" + XmlUtils.escape(getText()) + ""; - } - for (com.juick.Tag Tag : getTags()) { - ret += "" + XmlUtils.escape(Tag.getName()) + ""; - } - ret += ""; - - return ret; - } - - @Override - public boolean equals(Object obj) { - 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 (this.getMid() != jmsg.getMid()) { - if (this.getMid() > jmsg.getMid()) { - return -1; - } else { - return 1; - } - } - - if (this.getRid() != jmsg.getRid()) { - if (this.getRid() < jmsg.getRid()) { - return -1; - } else { - return 1; - } - } - - return 0; - } -} diff --git a/juick-core/src/main/java/com/juick/xmpp/extensions/JuickUser.java b/juick-core/src/main/java/com/juick/xmpp/extensions/JuickUser.java deleted file mode 100644 index 7473134c..00000000 --- a/juick-core/src/main/java/com/juick/xmpp/extensions/JuickUser.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Juick - * Copyright (C) 2008-2011, Ugnich Anton - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.juick.xmpp.extensions; - -import com.juick.xmpp.utils.XmlUtils; -import com.juick.xmpp.*; -import java.io.IOException; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -/** - * - * @author Ugnich Anton - */ -public class JuickUser extends com.juick.User implements StanzaChild { - - public final static String XMLNS = "http://juick.com/user"; - public final static String TagName = "user"; - - public JuickUser() { - } - - public JuickUser(com.juick.User user) { - super(user); - } - - @Override - public String getXMLNS() { - return XMLNS; - } - - @Override - public JuickUser parse(final XmlPullParser parser) throws XmlPullParserException, IOException { - JuickUser juser = new JuickUser(); - String strUID = parser.getAttributeValue(null, "uid"); - if (strUID != null) { - juser.setUid(Integer.parseInt(strUID)); - } - juser.setName(parser.getAttributeValue(null, "uname")); - XmlUtils.skip(parser); - return juser; - } - - public static String toString(com.juick.User user) { - String str = "<" + TagName + " xmlns='" + XMLNS + "'"; - if (user.getUid() > 0) { - str += " uid='" + user.getUid() + "'"; - } - if (user.getName() != null && user.getName().length() > 0) { - str += " uname='" + XmlUtils.escape(user.getName()) + "'"; - } - str += "/>"; - return str; - } - - @Override - public String toString() { - return toString(this); - } -} diff --git a/juick-crosspost/build.gradle b/juick-crosspost/build.gradle index 49fa86f9..6f28bc1f 100644 --- a/juick-crosspost/build.gradle +++ b/juick-crosspost/build.gradle @@ -5,12 +5,15 @@ apply plugin: 'com.github.ben-manes.versions' repositories { mavenCentral() + maven { url "https://jitpack.io" } } def springFrameworkVersion = '4.3.4.RELEASE' dependencies { compile project(':server-core') + compile 'org.bitbucket.sco0ter.babbler:xmpp-core-client:279e488e51' + compile 'org.bitbucket.sco0ter.babbler:xmpp-extensions-client:279e488e51' compile "org.springframework:spring-webmvc:${springFrameworkVersion}" compile 'com.mitchellbosecke:pebble-spring4:2.2.3' providedRuntime 'mysql:mysql-connector-java:5.1.40' diff --git a/juick-crosspost/src/main/java/com/juick/components/Crosspost.java b/juick-crosspost/src/main/java/com/juick/components/Crosspost.java index 8ccca67c..f14749eb 100644 --- a/juick-crosspost/src/main/java/com/juick/components/Crosspost.java +++ b/juick-crosspost/src/main/java/com/juick/components/Crosspost.java @@ -18,37 +18,34 @@ package com.juick.components; import com.juick.service.CrosspostService; -import com.juick.util.ThreadHelper; -import com.juick.xmpp.JID; -import com.juick.xmpp.Message; -import com.juick.xmpp.Stream; -import com.juick.xmpp.StreamComponent; -import com.juick.xmpp.extensions.JuickMessage; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.env.Environment; import org.springframework.util.Assert; +import rocks.xmpp.core.XmppException; +import rocks.xmpp.core.session.Extension; +import rocks.xmpp.core.session.XmppSession; +import rocks.xmpp.core.session.XmppSessionConfiguration; +import rocks.xmpp.core.stanza.model.Message; +import rocks.xmpp.extensions.component.accept.ExternalComponent; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.HttpsURLConnection; import java.io.*; -import java.net.Socket; import java.net.URL; import java.net.URLEncoder; import java.security.Key; import java.util.UUID; -import java.util.concurrent.ExecutorService; /** * @author Ugnich Anton */ -public class Crosspost implements InitializingBean, DisposableBean, Stream.StreamListener, Message.MessageListener { +public class Crosspost implements InitializingBean { final static String TWITTERURL = "https://api.twitter.com/1.1/statuses/update.json"; final static String FBURL = "https://graph.facebook.com/me/feed"; final static String VKURL = "https://api.vk.com/method/wall.post"; @@ -56,8 +53,7 @@ public class Crosspost implements InitializingBean, DisposableBean, Stream.Strea private static Logger logger = LoggerFactory.getLogger(Crosspost.class); private final CrosspostService crosspostService; - private final ExecutorService service; - private Stream xmpp; + private XmppSession xmpp; private final String twitter_consumer_key; private final String twitter_consumer_secret; @@ -65,12 +61,10 @@ public class Crosspost implements InitializingBean, DisposableBean, Stream.Strea private final String password; private final int port; - public Crosspost(final Environment env, final ExecutorService service, final CrosspostService crosspostService) { + public Crosspost(final Environment env, final CrosspostService crosspostService) { Assert.notNull(env); - Assert.notNull(service); Assert.notNull(crosspostService); - this.service = service; this.crosspostService = crosspostService; twitter_consumer_key = env.getProperty("twitter_consumer_key", ""); @@ -91,50 +85,28 @@ public class Crosspost implements InitializingBean, DisposableBean, Stream.Strea } @Override - public void afterPropertiesSet() throws Exception { - try { - Socket socket = new Socket("localhost", port); - xmpp = new StreamComponent(new JID(crosspostJid), socket.getInputStream(), socket.getOutputStream(), password); - xmpp.addChildParser(new JuickMessage()); - xmpp.addListener((Stream.StreamListener) this); - xmpp.addListener((Message.MessageListener) this); - - service.submit(() -> xmpp.startParsing()); - - logger.info("Crosspost initialized"); - } catch (Exception e) { - logger.error("Crosspost initialization exception", e); - } - } - - @Override - public void destroy() throws Exception { - ThreadHelper.shutdownAndAwaitTermination(service); - - logger.info("Crosspost destroyed"); - } - - @Override - public void onStreamReady() { - logger.info("XMPP STREAM READY"); - } - - @Override - public void onStreamFail(Exception e) { - logger.error("XMPP STREAM FAIL", e); - } - - @Override - public void onMessage(final com.juick.xmpp.Message msg) { - JuickMessage jmsg = (JuickMessage) msg.getChild(JuickMessage.XMLNS); - if (msg.to != null && msg.to.Username != null && jmsg != null && jmsg.getRid() == 0) { - if (msg.to.Username.equals("twitter")) { - twitterPost(jmsg); - } else if (msg.to.Username.equals("fb")) { - facebookPost(jmsg); - } else if (msg.to.Username.equals("vk")) { - vkontaktePost(jmsg); + public void afterPropertiesSet() { + XmppSessionConfiguration configuration = XmppSessionConfiguration.builder() + .extensions(Extension.of(com.juick.Message.class)) + .build(); + xmpp = ExternalComponent.create(crosspostJid, password, configuration, "localhost", port); + xmpp.addInboundMessageListener(e -> { + Message msg = e.getMessage(); + com.juick.Message jmsg = msg.getExtension(com.juick.Message.class); + if (msg.getTo() != null && msg.getTo().getLocal() != null && jmsg != null && jmsg.getRid() == 0) { + if (msg.getTo().getLocal().equals("twitter")) { + twitterPost(jmsg); + } else if (msg.getTo().getLocal().equals("fb")) { + facebookPost(jmsg); + } else if (msg.getTo().getLocal().equals("vk")) { + vkontaktePost(jmsg); + } } + }); + try { + xmpp.connect(); + } catch (XmppException e) { + logger.warn("xmpp exception", e); } } diff --git a/juick-crosspost/src/main/java/com/juick/components/configuration/CrosspostAppConfiguration.java b/juick-crosspost/src/main/java/com/juick/components/configuration/CrosspostAppConfiguration.java index 603130b3..91a886b3 100644 --- a/juick-crosspost/src/main/java/com/juick/components/configuration/CrosspostAppConfiguration.java +++ b/juick-crosspost/src/main/java/com/juick/components/configuration/CrosspostAppConfiguration.java @@ -8,11 +8,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; -import org.springframework.jdbc.core.JdbcTemplate; import javax.inject.Inject; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; /** * Created by aalexeev on 11/12/16. @@ -28,11 +25,6 @@ public class CrosspostAppConfiguration { @Bean public Crosspost crosspost() { - return new Crosspost(env, service(), crosspostService); - } - - @Bean - public ExecutorService service() { - return Executors.newCachedThreadPool(); + return new Crosspost(env, crosspostService); } } diff --git a/juick-notifications/build.gradle b/juick-notifications/build.gradle index a55da11a..c8350adb 100644 --- a/juick-notifications/build.gradle +++ b/juick-notifications/build.gradle @@ -5,12 +5,15 @@ apply plugin: 'com.github.ben-manes.versions' repositories { mavenCentral() + maven { url "https://jitpack.io" } } def springFrameworkVersion = '4.3.4.RELEASE' dependencies { compile project(':server-core') + compile 'org.bitbucket.sco0ter.babbler:xmpp-core-client:279e488e51' + compile 'org.bitbucket.sco0ter.babbler:xmpp-extensions-client:279e488e51' compile 'com.ganyo:gcm-server:1.1.0' compile 'com.notnoop.apns:apns:1.0.0.Beta6' compile "org.springframework:spring-webmvc:${springFrameworkVersion}" diff --git a/juick-notifications/src/main/java/com/juick/components/Notifications.java b/juick-notifications/src/main/java/com/juick/components/Notifications.java index d37f7a25..e449abef 100644 --- a/juick-notifications/src/main/java/com/juick/components/Notifications.java +++ b/juick-notifications/src/main/java/com/juick/components/Notifications.java @@ -18,16 +18,12 @@ package com.juick.components; import com.google.android.gcm.server.*; +import com.google.android.gcm.server.Message; import com.juick.json.MessageSerializer; import com.juick.util.ThreadHelper; -import com.juick.xmpp.JID; -import com.juick.xmpp.Message.MessageListener; -import com.juick.xmpp.Stream; -import com.juick.xmpp.StreamComponent; -import com.juick.xmpp.extensions.JuickMessage; -import com.juick.xmpp.utils.XmlUtils; import com.notnoop.apns.APNS; import com.notnoop.apns.ApnsService; +import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.math.NumberUtils; import org.apache.http.Consts; import org.apache.http.Header; @@ -50,24 +46,24 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.env.Environment; import org.springframework.http.HttpMethod; import org.springframework.web.client.RestTemplate; +import rocks.xmpp.core.XmppException; +import rocks.xmpp.core.session.Extension; +import rocks.xmpp.core.session.XmppSessionConfiguration; +import rocks.xmpp.extensions.component.accept.ExternalComponent; import java.io.IOException; -import java.net.Socket; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.concurrent.ExecutorService; /** * @author Ugnich Anton */ -public class Notifications implements InitializingBean, DisposableBean, Stream.StreamListener, MessageListener { +public class Notifications implements InitializingBean { private static Logger logger = LoggerFactory.getLogger(Notifications.class); private final RestTemplate rest; - private final ExecutorService service; - private Socket socket; - private Stream xmpp; + private ExternalComponent xmpp; private final Sender GCMSender; private final String wns_application_sip; @@ -78,8 +74,7 @@ public class Notifications implements InitializingBean, DisposableBean, Stream.S private final String xmppPushPassword; - public Notifications(final Environment env, final ExecutorService service, final RestTemplate rest) { - this.service = service; + public Notifications(final Environment env, final RestTemplate rest) { this.rest = rest; wns_application_sip = env.getProperty("wns_application_sip", ""); @@ -92,150 +87,128 @@ public class Notifications implements InitializingBean, DisposableBean, Stream.S } @Override - public void afterPropertiesSet() throws Exception { - try { - socket = new Socket(xmppHost, xmppPort); - xmpp = new StreamComponent(new JID("", pushJid, ""), socket.getInputStream(), socket.getOutputStream(), xmppPushPassword); - xmpp.addChildParser(new JuickMessage()); - xmpp.addListener((Stream.StreamListener) this); - xmpp.addListener((MessageListener) this); - - service.submit(() -> xmpp.startParsing()); - - logger.info("Notifications initialized"); - } catch (Exception e) { - logger.error("Notifications initialization error", e); - } - } - - @Override - public void destroy() { - ThreadHelper.shutdownAndAwaitTermination(service); - - logger.info("component destroyed"); - } - - @Override - public void onStreamReady() { - logger.info("XMPP STREAM READY"); - } - - @Override - public void onStreamFail(final Exception e) { - logger.error("XMPP STREAM FAIL", e); - } - - @Override - public void onMessage(final com.juick.xmpp.Message msg) { - JuickMessage jmsg = (JuickMessage) msg.getChild(JuickMessage.XMLNS); - boolean isPM = jmsg.getMid() == 0; - boolean isReply = jmsg.getRid() > 0; - int pmTo = 0; + public void afterPropertiesSet() { + XmppSessionConfiguration configuration = XmppSessionConfiguration.builder() + .extensions(Extension.of(com.juick.Message.class)) + .build(); + xmpp = ExternalComponent.create(pushJid, xmppPushPassword, configuration, xmppHost, xmppPort); + xmpp.addInboundMessageListener(e -> { + rocks.xmpp.core.stanza.model.Message msg = e.getMessage(); + com.juick.Message jmsg = msg.getExtension(com.juick.Message.class); + boolean isPM = jmsg.getMid() == 0; + boolean isReply = jmsg.getRid() > 0; + int pmTo = 0; - /*** ANDROID ***/ - final List regids = new ArrayList<>(); - if (isPM) { - regids.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=gcm&uid=%s", - jmsg.getUser().getUid()), - HttpMethod.GET, null, new ParameterizedTypeReference>() { - }).getBody()); - } else { - regids.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=gcm&uid=%s&mid=%s", - jmsg.getUser().getUid(), jmsg.getMid()), - HttpMethod.GET, null, new ParameterizedTypeReference>() { - }).getBody()); - } + /*** ANDROID ***/ + final List regids = new ArrayList<>(); + if (isPM) { + regids.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=gcm&uid=%s", + jmsg.getUser().getUid()), + HttpMethod.GET, null, new ParameterizedTypeReference>() { + }).getBody()); + } else { + regids.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=gcm&uid=%s&mid=%s", + jmsg.getUser().getUid(), jmsg.getMid()), + HttpMethod.GET, null, new ParameterizedTypeReference>() { + }).getBody()); + } - if (!regids.isEmpty()) { - MessageSerializer messageSerializer = new MessageSerializer(); - String json = messageSerializer.serialize(jmsg).toString(); - logger.info(json); - Message message = new Message.Builder().addData("message", json).build(); - try { - MulticastResult result = GCMSender.send(message, regids, 3); - List results = result.getResults(); - for (int i = 0; i < results.size(); i++) { - logger.info("RES " + i + ": " + results.get(i).toString()); + if (!regids.isEmpty()) { + MessageSerializer messageSerializer = new MessageSerializer(); + String json = messageSerializer.serialize(jmsg).toString(); + logger.info(json); + Message message = new Message.Builder().addData("message", json).build(); + try { + MulticastResult result = GCMSender.send(message, regids, 3); + List results = result.getResults(); + for (int i = 0; i < results.size(); i++) { + logger.info("RES " + i + ": " + results.get(i).toString()); + } + } catch (IOException ex) { + logger.error(ex.getMessage(), ex); + } catch (IllegalArgumentException err) { + logger.warn("Android: Invalid API Key"); } - } catch (IOException e) { - logger.error(e.getMessage(), e); - } catch (IllegalArgumentException err) { - logger.warn("Android: Invalid API Key"); + } else { + logger.info("GMS: no recipients"); } - } else { - logger.info("GMS: no recipients"); - } - /*** WinPhone ***/ - final List urls = new ArrayList<>(); - if (isPM) { - urls.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=mpns&uid=%s", - jmsg.getUser().getUid()), - HttpMethod.GET, null, new ParameterizedTypeReference>() { - }).getBody()); - } else { - urls.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=mpns&uid=%s&mid=%s", - jmsg.getUser().getUid(), jmsg.getMid()), - HttpMethod.GET, null, new ParameterizedTypeReference>() { - }).getBody()); - } + /*** WinPhone ***/ + final List urls = new ArrayList<>(); + if (isPM) { + urls.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=mpns&uid=%s", + jmsg.getUser().getUid()), + HttpMethod.GET, null, new ParameterizedTypeReference>() { + }).getBody()); + } else { + urls.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=mpns&uid=%s&mid=%s", + jmsg.getUser().getUid(), jmsg.getMid()), + HttpMethod.GET, null, new ParameterizedTypeReference>() { + }).getBody()); + } - if (urls.isEmpty()) { - logger.info("WNS: no recipients"); - } else { - try { - String wnsToken = getWnsAccessToken(); - String text1 = "@" + jmsg.getUser().getName(); - if (!jmsg.getTags().isEmpty()) { - text1 += ":" + XmlUtils.escape(jmsg.getTagsString()); - } - String text2 = XmlUtils.escape(jmsg.getText()); - String xml = "" - + "" - + "" - + "" - + "" - + "" + text1 + "" - + "" + text2 + "" - + "" - + "" - + "" - + "" - + "" - + ""; - logger.trace(xml); - for (String url : urls) { - logger.info("WNS: " + url); - sendWNS(wnsToken, url, xml); + if (urls.isEmpty()) { + logger.info("WNS: no recipients"); + } else { + try { + String wnsToken = getWnsAccessToken(); + String text1 = "@" + jmsg.getUser().getName(); + if (!jmsg.getTags().isEmpty()) { + text1 += ":" + StringEscapeUtils.escapeXml11(jmsg.getTagsString()); + } + String text2 = StringEscapeUtils.escapeXml11(jmsg.getText()); + String xml = "" + + "" + + "" + + "" + + "" + + "" + text1 + "" + + "" + text2 + "" + + "" + + "" + + "" + + "" + + "" + + ""; + logger.trace(xml); + for (String url : urls) { + logger.info("WNS: " + url); + sendWNS(wnsToken, url, xml); + } + } catch (IOException | IllegalStateException ex) { + logger.error("WNS: ", ex); } - } catch (IOException | IllegalStateException e) { - logger.error("WNS: ", e); } - } - /*** iOS ***/ - final List tokens = new ArrayList<>(); - if (isPM) { - tokens.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=apns&uid=%s", - jmsg.getUser().getUid()), - HttpMethod.GET, null, new ParameterizedTypeReference>() { - }).getBody()); - } else { - tokens.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=apns&uid=%s&mid=%s", - jmsg.getUser().getUid(), jmsg.getMid()), - HttpMethod.GET, null, new ParameterizedTypeReference>() { - }).getBody()); - } - if (!tokens.isEmpty()) { - ApnsService service = APNS.newService().withCert("/etc/juick/ios.p12", "juick") - .withSandboxDestination().build(); - for (String token : tokens) { - String payload = APNS.newPayload().alertTitle("@" + jmsg.getUser().getName()).alertBody(jmsg.getText()).build(); - logger.info("APNS: " + token); - service.push(token, payload); + /*** iOS ***/ + final List tokens = new ArrayList<>(); + if (isPM) { + tokens.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=apns&uid=%s", + jmsg.getUser().getUid()), + HttpMethod.GET, null, new ParameterizedTypeReference>() { + }).getBody()); + } else { + tokens.addAll(rest.exchange(String.format("http://api.juick.com/notifications?type=apns&uid=%s&mid=%s", + jmsg.getUser().getUid(), jmsg.getMid()), + HttpMethod.GET, null, new ParameterizedTypeReference>() { + }).getBody()); } - } else { - logger.info("APNS: no recipients"); + if (!tokens.isEmpty()) { + ApnsService service = APNS.newService().withCert("/etc/juick/ios.p12", "juick") + .withSandboxDestination().build(); + for (String token : tokens) { + String payload = APNS.newPayload().alertTitle("@" + jmsg.getUser().getName()).alertBody(jmsg.getText()).build(); + logger.info("APNS: " + token); + service.push(token, payload); + } + } else { + logger.info("APNS: no recipients"); + } + }); + try { + xmpp.connect(); + } catch (XmppException e) { + logger.warn("xmpp extension", e); } } diff --git a/juick-notifications/src/main/java/com/juick/components/configuration/NotificationsAppConfiguration.java b/juick-notifications/src/main/java/com/juick/components/configuration/NotificationsAppConfiguration.java index 1974830a..c17587ac 100644 --- a/juick-notifications/src/main/java/com/juick/components/configuration/NotificationsAppConfiguration.java +++ b/juick-notifications/src/main/java/com/juick/components/configuration/NotificationsAppConfiguration.java @@ -10,8 +10,6 @@ import org.springframework.core.env.Environment; import org.springframework.web.client.RestTemplate; import javax.inject.Inject; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; /** * Created by aalexeev on 11/12/16. @@ -30,11 +28,6 @@ public class NotificationsAppConfiguration { @Bean public Notifications push() { - return new Notifications(env, service(), rest()); - } - - @Bean - public ExecutorService service() { - return Executors.newCachedThreadPool(); + return new Notifications(env, rest()); } } diff --git a/juick-ws/build.gradle b/juick-ws/build.gradle index 80afdcd7..4148b741 100644 --- a/juick-ws/build.gradle +++ b/juick-ws/build.gradle @@ -13,13 +13,15 @@ apply plugin: 'com.github.ben-manes.versions' repositories { mavenCentral() + maven { url "https://jitpack.io" } } def springFrameworkVersion = '4.3.4.RELEASE' dependencies { compile project(':server-core') - compile project(':deps:com.juick.xmpp') + compile 'org.bitbucket.sco0ter.babbler:xmpp-core-client:279e488e51' + compile 'org.bitbucket.sco0ter.babbler:xmpp-extensions-client:279e488e51' compile "org.springframework:spring-webmvc:${springFrameworkVersion}" compile "org.springframework:spring-websocket:${springFrameworkVersion}" compile 'com.mitchellbosecke:pebble-spring4:2.2.3' diff --git a/juick-ws/src/main/java/com/juick/ws/XMPPConnection.java b/juick-ws/src/main/java/com/juick/ws/XMPPConnection.java index 7a6feee1..1b6eb3dc 100644 --- a/juick-ws/src/main/java/com/juick/ws/XMPPConnection.java +++ b/juick-ws/src/main/java/com/juick/ws/XMPPConnection.java @@ -5,11 +5,6 @@ import com.juick.json.MessageSerializer; import com.juick.server.MessagesQueries; import com.juick.server.SubscriptionsQueries; import com.juick.util.ThreadHelper; -import com.juick.xmpp.JID; -import com.juick.xmpp.Message; -import com.juick.xmpp.Stream; -import com.juick.xmpp.StreamComponent; -import com.juick.xmpp.extensions.JuickMessage; import org.apache.commons.lang3.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,9 +14,14 @@ import org.springframework.core.env.Environment; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.util.Assert; import org.springframework.web.socket.TextMessage; +import rocks.xmpp.core.XmppException; +import rocks.xmpp.core.session.Extension; +import rocks.xmpp.core.session.XmppSession; +import rocks.xmpp.core.session.XmppSessionConfiguration; +import rocks.xmpp.core.stanza.model.Message; +import rocks.xmpp.extensions.component.accept.ExternalComponent; import java.io.IOException; -import java.net.Socket; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.stream.Collectors; @@ -29,7 +29,7 @@ import java.util.stream.Collectors; /** * @author ugnich */ -public class XMPPConnection implements InitializingBean, DisposableBean, Stream.StreamListener, Message.MessageListener { +public class XMPPConnection implements InitializingBean, DisposableBean { private static final Logger logger = LoggerFactory.getLogger(XMPPConnection.class); private final JdbcTemplate jdbc; @@ -40,7 +40,7 @@ public class XMPPConnection implements InitializingBean, DisposableBean, Stream. private final int xmppPort; private final String wsJid; - private Stream xmpp; + private XmppSession xmpp; public XMPPConnection( @@ -62,19 +62,34 @@ public class XMPPConnection implements InitializingBean, DisposableBean, Stream. } @Override - public void afterPropertiesSet() throws Exception { + public void afterPropertiesSet() { + XmppSessionConfiguration configuration = XmppSessionConfiguration.builder() + .extensions(Extension.of(com.juick.Message.class)) + .build(); + xmpp = ExternalComponent.create(wsJid, xmppPassword, configuration, "localhost", xmppPort); + xmpp.addInboundMessageListener(e -> { + Message msg = e.getMessage(); + com.juick.Message jmsg = msg.getExtension(com.juick.Message.class); + if (jmsg != null) { + logger.info("got msg: " + ms.serialize(jmsg).toString()); + if (jmsg.getMid() == 0) { + int uid_to = NumberUtils.toInt(msg.getTo().getLocal(), 0); + if (uid_to > 0) { + onJuickPM(uid_to, jmsg); + } + } else if (jmsg.getRid() == 0) { + onJuickMessagePost(jmsg); + } else { + // to get quote + com.juick.Message reply = MessagesQueries.getReply(jdbc, jmsg.getMid(), jmsg.getRid()); + onJuickMessageReply(reply); + } + } + }); try { - Socket socket = new Socket("localhost", xmppPort); - xmpp = new StreamComponent(new JID(wsJid), socket.getInputStream(), socket.getOutputStream(), xmppPassword); - xmpp.addChildParser(new JuickMessage()); - xmpp.addListener((Stream.StreamListener) this); - xmpp.addListener((Message.MessageListener) this); - - service.submit(() -> xmpp.startParsing()); - - logger.info("XMPPConnection initialized"); - } catch (IOException e) { - logger.error("XMPPConnection initialization error", e); + xmpp.connect(); + } catch (XmppException e) { + logger.warn("xmpp extension", e); } } @@ -85,40 +100,6 @@ public class XMPPConnection implements InitializingBean, DisposableBean, Stream. logger.info("XMPPConnection destroyed"); } - @Override - public void onStreamReady() { - logger.info("XMPP stream ready"); - } - - @Override - public void onStreamFail(final Exception ex) { - logger.error("XMPP stream failed", ex); - } - - @Override - public void onMessage(final com.juick.xmpp.Message msg) { - JuickMessage jmsg = (JuickMessage) msg.getChild(JuickMessage.XMLNS); - if (jmsg != null) { - logger.info("got jmsg: " + ms.serialize(jmsg).toString()); - if (jmsg.getMid() == 0) { - int uid_to = 0; - try { - uid_to = Integer.parseInt(msg.to.Username); - } catch (Exception e) { - } - if (uid_to > 0) { - onJuickPM(uid_to, jmsg); - } - } else if (jmsg.getRid() == 0) { - onJuickMessagePost(jmsg); - } else { - // to get quote - com.juick.Message reply = MessagesQueries.getReply(jdbc, jmsg.getMid(), jmsg.getRid()); - onJuickMessageReply(reply); - } - } - } - MessageSerializer messageSerializer = new MessageSerializer(); private void onJuickPM(final int uid_to, final com.juick.Message jmsg) { diff --git a/juick-xmpp/build.gradle b/juick-xmpp/build.gradle index b05762c4..892e23cb 100644 --- a/juick-xmpp/build.gradle +++ b/juick-xmpp/build.gradle @@ -5,6 +5,7 @@ apply plugin: 'com.github.ben-manes.versions' repositories { mavenCentral() + maven { url "https://jitpack.io" } } def springFrameworkVersion = '4.3.4.RELEASE' @@ -13,6 +14,7 @@ def slf4jVersion = '1.7.21' dependencies { compile project(':server-core') + compile 'com.github.juick:com.juick.xmpp:dbf603cfff' compile "org.slf4j:slf4j-api:${slf4jVersion}" compile "org.springframework:spring-webmvc:${springFrameworkVersion}" compile "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}" 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 new file mode 100644 index 00000000..2c3875c5 --- /dev/null +++ b/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickMessage.java @@ -0,0 +1,183 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.juick.xmpp.extensions; + +import com.juick.Tag; +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; + +/** + * + * @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 + public String getXMLNS() { + return XMLNS; + } + + @Override + public JuickMessage parse(XmlPullParser parser) throws XmlPullParserException, IOException, ParseException { + JuickMessage jmsg = new JuickMessage(); + + final String sMID = parser.getAttributeValue(null, "mid"); + if (sMID != null) { + jmsg.setMid(Integer.parseInt(sMID)); + } + final String sRID = parser.getAttributeValue(null, "rid"); + if (sRID != null) { + jmsg.setRid(Integer.parseInt(sRID)); + } + final String sReplyTo = parser.getAttributeValue(null, "replyto"); + if (sReplyTo != null) { + jmsg.setReplyto(Integer.parseInt(sReplyTo)); + } + final String sPrivacy = parser.getAttributeValue(null, "privacy"); + if (sPrivacy != null) { + jmsg.setPrivacy(Integer.parseInt(sPrivacy)); + } + final String sFriendsOnly = parser.getAttributeValue(null, "friendsonly"); + if (sFriendsOnly != null) { + jmsg.FriendsOnly = true; + } + final String sReadOnly = parser.getAttributeValue(null, "readonly"); + if (sReadOnly != null) { + jmsg.ReadOnly = true; + } + String ts = parser.getAttributeValue(null, "ts"); + if (ts != null) { + jmsg.setDate(df.parse(ts)); + } + jmsg.AttachmentType = parser.getAttributeValue(null, "attach"); + + while (parser.next() == XmlPullParser.START_TAG) { + final String tag = parser.getName(); + final String xmlns = parser.getNamespace(); + if (tag.equals("body")) { + jmsg.setText(XmlUtils.getTagText(parser)); + } else if (tag.equals(JuickUser.TagName) && xmlns != null && xmlns.equals(JuickUser.XMLNS)) { + jmsg.setUser(new JuickUser().parse(parser)); + } else if (tag.equals("tag")) { + jmsg.getTags().add(new Tag(XmlUtils.getTagText(parser))); + } else { + XmlUtils.skip(parser); + } + } + return jmsg; + } + + @Override + public String toString() { + String ret = ""; + + 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 (AttachmentType != null) { + ret += " attach=\"" + AttachmentType + "\""; + } + ret += ">"; + if (getUser() != null) { + ret += JuickUser.toString(getUser()); + } + if (getText() != null) { + ret += "" + XmlUtils.escape(getText()) + ""; + } + for (com.juick.Tag Tag : getTags()) { + ret += "" + XmlUtils.escape(Tag.getName()) + ""; + } + ret += ""; + + return ret; + } + + @Override + public boolean equals(Object obj) { + 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 (this.getMid() != jmsg.getMid()) { + if (this.getMid() > jmsg.getMid()) { + return -1; + } else { + return 1; + } + } + + if (this.getRid() != jmsg.getRid()) { + if (this.getRid() < jmsg.getRid()) { + return -1; + } else { + return 1; + } + } + + return 0; + } +} diff --git a/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickUser.java b/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickUser.java new file mode 100644 index 00000000..7473134c --- /dev/null +++ b/juick-xmpp/src/main/java/com/juick/xmpp/extensions/JuickUser.java @@ -0,0 +1,75 @@ +/* + * Juick + * Copyright (C) 2008-2011, Ugnich Anton + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.juick.xmpp.extensions; + +import com.juick.xmpp.utils.XmlUtils; +import com.juick.xmpp.*; +import java.io.IOException; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +/** + * + * @author Ugnich Anton + */ +public class JuickUser extends com.juick.User implements StanzaChild { + + public final static String XMLNS = "http://juick.com/user"; + public final static String TagName = "user"; + + public JuickUser() { + } + + public JuickUser(com.juick.User user) { + super(user); + } + + @Override + public String getXMLNS() { + return XMLNS; + } + + @Override + public JuickUser parse(final XmlPullParser parser) throws XmlPullParserException, IOException { + JuickUser juser = new JuickUser(); + String strUID = parser.getAttributeValue(null, "uid"); + if (strUID != null) { + juser.setUid(Integer.parseInt(strUID)); + } + juser.setName(parser.getAttributeValue(null, "uname")); + XmlUtils.skip(parser); + return juser; + } + + public static String toString(com.juick.User user) { + String str = "<" + TagName + " xmlns='" + XMLNS + "'"; + if (user.getUid() > 0) { + str += " uid='" + user.getUid() + "'"; + } + if (user.getName() != null && user.getName().length() > 0) { + str += " uname='" + XmlUtils.escape(user.getName()) + "'"; + } + str += "/>"; + return str; + } + + @Override + public String toString() { + return toString(this); + } +} diff --git a/server-core/build.gradle b/server-core/build.gradle index f082e2c8..705b7675 100644 --- a/server-core/build.gradle +++ b/server-core/build.gradle @@ -14,8 +14,6 @@ def springFrameworkVersion = '4.3.4.RELEASE' dependencies { compile project(':juick-core') - compile project(':deps:com.juick.xmpp') - compile "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}" compile "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}" compile "com.fasterxml.jackson.core:jackson-annotations:${jacksonVersion}" diff --git a/server-core/src/main/java/com/juick/server/protocol/JuickProtocol.java b/server-core/src/main/java/com/juick/server/protocol/JuickProtocol.java index f1e98eb9..6fa3790e 100644 --- a/server-core/src/main/java/com/juick/server/protocol/JuickProtocol.java +++ b/server-core/src/main/java/com/juick/server/protocol/JuickProtocol.java @@ -8,7 +8,6 @@ import com.juick.json.MessageSerializer; import com.juick.server.*; import com.juick.server.protocol.annotation.UserCommand; import com.juick.util.TagUtils; -import com.juick.xmpp.extensions.JuickMessage; import org.springframework.jdbc.core.JdbcTemplate; import java.lang.reflect.InvocationTargetException; @@ -305,7 +304,7 @@ public class JuickProtocol { if (ret == 200) { - JuickMessage jmsg = new JuickMessage(); + Message jmsg = new Message(); jmsg.setUser(user_from); jmsg.setText(body); // TODO: add PM payload diff --git a/settings.gradle b/settings.gradle index f1b637e5..2b1e5051 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':deps:com.juick.xmpp', ':juick-core', 'server-core', ':juick-api', ':juick-www', ':juick-rss', ':juick-ws', ':juick-demo', ':juick-notifications', ':juick-crosspost', ':juick-xmpp', ':juick-xmpp-ft', ':juick-xmpp-bot' +include ':juick-core', 'server-core', ':juick-api', ':juick-www', ':juick-rss', ':juick-ws', ':juick-demo', ':juick-notifications', ':juick-crosspost', ':juick-xmpp', ':juick-xmpp-ft', ':juick-xmpp-bot' -- cgit v1.2.3