From 3dad0c5938fc1d79ce5ed1d9b380fd7cccc75451 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Sun, 12 Oct 2014 16:24:04 +0200 Subject: [PATCH] Update to Smack 4.0.5 Remove Presence Packet listener in XmppConsumer. It never worked, since the processPacket() method does check if the given Packet is instanceof Message, so the filtered Presence Packets never got processed. XMPPError.getCode() is no more. Integer error codes have been deprecated from XMPP for a while. Use getType() instead. Use the connection packet reply timeout, instead of the global one in SmackConfiguration (where the method name was changed to SmackConfiguration.getDefaultPacketReplyTimeout()). Use JivePropertiesManager for Packet properties. Fixes CAMEL-7903 --- components/camel-xmpp/pom.xml | 9 +- .../camel/component/xmpp/XmppBinding.java | 9 +- .../camel/component/xmpp/XmppConsumer.java | 28 ++---- .../camel/component/xmpp/XmppEndpoint.java | 93 +++++++++++++++---- .../component/xmpp/XmppGroupChatProducer.java | 17 ++-- .../xmpp/XmppPrivateChatProducer.java | 15 ++- parent/pom.xml | 4 +- 7 files changed, 117 insertions(+), 58 deletions(-) diff --git a/components/camel-xmpp/pom.xml b/components/camel-xmpp/pom.xml index d848a7f179050..ae782268c8d02 100644 --- a/components/camel-xmpp/pom.xml +++ b/components/camel-xmpp/pom.xml @@ -47,12 +47,17 @@ org.igniterealtime.smack - smack + smack-tcp ${smack-version} org.igniterealtime.smack - smackx + smack-resolver-javax + ${smack-version} + + + org.igniterealtime.smack + smack-extensions ${smack-version} diff --git a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppBinding.java b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppBinding.java index 58debd7997e8d..5d1e1ba02ace3 100644 --- a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppBinding.java +++ b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppBinding.java @@ -25,6 +25,7 @@ import org.apache.camel.spi.HeaderFilterStrategy; import org.apache.camel.util.ObjectHelper; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smackx.jiveproperties.JivePropertiesManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,7 +71,7 @@ public void populateXmppMessage(Message message, Exchange exchange) { message.setLanguage(language); } else { try { - message.setProperty(name, value); + JivePropertiesManager.addProperty(message, name, value); LOG.trace("Added property name: {} value: {}", name, value.toString()); } catch (IllegalArgumentException iae) { if (LOG.isDebugEnabled()) { @@ -83,7 +84,7 @@ public void populateXmppMessage(Message message, Exchange exchange) { String id = exchange.getExchangeId(); if (id != null) { - message.setProperty("exchangeId", id); + JivePropertiesManager.addProperty(message, "exchangeId", id); } } @@ -97,8 +98,8 @@ public Object extractBodyFromXmpp(Exchange exchange, Message message) { public Map extractHeadersFromXmpp(Message xmppMessage, Exchange exchange) { Map answer = new HashMap(); - for (String name : xmppMessage.getPropertyNames()) { - Object value = xmppMessage.getProperty(name); + for (String name : JivePropertiesManager.getPropertiesNames(xmppMessage)) { + Object value = JivePropertiesManager.getProperty(xmppMessage, name); if (!headerFilterStrategy.applyFilterToExternalHeaders(name, value, exchange)) { answer.put(name, value); diff --git a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppConsumer.java b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppConsumer.java index 657c5045e9722..f2e015ef28388 100644 --- a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppConsumer.java +++ b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppConsumer.java @@ -18,6 +18,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; + import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.impl.DefaultConsumer; @@ -27,15 +28,10 @@ import org.jivesoftware.smack.ChatManagerListener; import org.jivesoftware.smack.MessageListener; import org.jivesoftware.smack.PacketListener; -import org.jivesoftware.smack.SmackConfiguration; import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.filter.AndFilter; -import org.jivesoftware.smack.filter.PacketTypeFilter; -import org.jivesoftware.smack.filter.ToContainsFilter; +import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; -import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smackx.muc.DiscussionHistory; import org.jivesoftware.smackx.muc.MultiUserChat; import org.slf4j.Logger; @@ -64,7 +60,7 @@ public XmppConsumer(XmppEndpoint endpoint, Processor processor) { protected void doStart() throws Exception { try { connection = endpoint.createConnection(); - } catch (XMPPException e) { + } catch (XMPPErrorException e) { if (endpoint.isTestConnectionOnStartup()) { throw new RuntimeException("Could not connect to XMPP server.", e); } else { @@ -77,7 +73,7 @@ protected void doStart() throws Exception { } } - chatManager = connection.getChatManager(); + chatManager = ChatManager.getInstanceFor(connection); chatManager.addChatListener(this); if (endpoint.getRoom() == null) { @@ -89,24 +85,18 @@ protected void doStart() throws Exception { } privateChat.addMessageListener(this); } else { - privateChat = connection.getChatManager().createChat(endpoint.getParticipant(), endpoint.getChatId(), this); + privateChat = chatManager.createChat(endpoint.getParticipant(), endpoint.getChatId(), this); if (LOG.isDebugEnabled()) { LOG.debug("Opening private chat to " + privateChat.getParticipant()); } } } else { - // add the presence packet listener to the connection so we only get packets that concerns us - // we must add the listener before creating the muc - final ToContainsFilter toFilter = new ToContainsFilter(endpoint.getParticipant()); - final AndFilter packetFilter = new AndFilter(new PacketTypeFilter(Presence.class), toFilter); - connection.addPacketListener(this, packetFilter); - muc = new MultiUserChat(connection, endpoint.resolveRoom(connection)); muc.addMessageListener(this); DiscussionHistory history = new DiscussionHistory(); history.setMaxChars(0); // we do not want any historical messages - muc.join(endpoint.getNickname(), null, history, SmackConfiguration.getPacketReplyTimeout()); + muc.join(endpoint.getNickname(), null, history, connection.getPacketReplyTimeout()); if (LOG.isInfoEnabled()) { LOG.info("Joined room: {} as: {}", muc.getRoom(), endpoint.getNickname()); } @@ -153,7 +143,7 @@ private void checkConnection() throws Exception { LOG.info("Attempting to reconnect to: {}", XmppEndpoint.getConnectionMessage(connection)); try { connection.connect(); - } catch (XMPPException e) { + } catch (XMPPErrorException e) { LOG.warn(XmppEndpoint.getXmppExceptionLogMessage(e)); } } @@ -198,9 +188,7 @@ public void chatCreated(Chat chat, boolean createdLocally) { } public void processPacket(Packet packet) { - if (packet instanceof Message) { - processMessage(null, (Message)packet); - } + processMessage(null, (Message)packet); } public void processMessage(Chat chat, Message message) { diff --git a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppEndpoint.java b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppEndpoint.java index 8c3f85322f88f..1dc7420d8b242 100644 --- a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppEndpoint.java +++ b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppEndpoint.java @@ -16,7 +16,17 @@ */ package org.apache.camel.component.xmpp; -import java.util.Iterator; +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Collection; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import org.apache.camel.Consumer; import org.apache.camel.Exchange; @@ -31,12 +41,16 @@ import org.apache.camel.util.ObjectHelper; import org.jivesoftware.smack.AccountManager; import org.jivesoftware.smack.ConnectionConfiguration; +import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode; +import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.filter.PacketFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.XMPPError; +import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smackx.muc.MultiUserChat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,6 +78,8 @@ public class XmppEndpoint extends DefaultEndpoint implements HeaderFilterStrateg private XMPPConnection connection; private boolean testConnectionOnStartup = true; private int connectionPollDelay = 10; + private boolean useTls = true; + private boolean acceptAllCertificates = true; // TODO change to false public XmppEndpoint() { } @@ -127,22 +143,61 @@ public boolean isSingleton() { return true; } - public synchronized XMPPConnection createConnection() throws XMPPException { + public synchronized XMPPConnection createConnection() throws XMPPException, SmackException, IOException { if (connection != null && connection.isConnected()) { return connection; } + ConnectionConfiguration connectionConfiguration; if (connection == null) { if (port > 0) { if (getServiceName() == null) { - connection = new XMPPConnection(new ConnectionConfiguration(host, port)); + connectionConfiguration = new ConnectionConfiguration(host, port); } else { - connection = new XMPPConnection(new ConnectionConfiguration(host, port, serviceName)); + connectionConfiguration = new ConnectionConfiguration(host, port, serviceName); } } else { - connection = new XMPPConnection(host); + connectionConfiguration = new ConnectionConfiguration(host); } + + if (useTls) { + connectionConfiguration.setSecurityMode(SecurityMode.required); + } else { + connectionConfiguration.setSecurityMode(SecurityMode.disabled); + } + + if (acceptAllCertificates) { + // TODO Replace with + // org.jivesoftware.smack.util.TLSUtils.acceptAllCertificates(ConnectionConfiguration) + // once camel-xmpp uses Smack 4.1 + SSLContext context; + try { + context = SSLContext.getInstance("TLS"); + X509TrustManager acceptAllTrustManager = new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + // Nothing to do here + } + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + // Nothing to do here + } + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + }; + context.init(null, new TrustManager[] { acceptAllTrustManager }, new SecureRandom()); + connectionConfiguration.setCustomSSLContext(context); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + throw new IOException(e); + } + + } + connection = new XMPPTCPConnection(connectionConfiguration); } connection.connect(); @@ -168,7 +223,7 @@ public boolean accept(Packet packet) { } if (createAccount) { - AccountManager accountManager = new AccountManager(connection); + AccountManager accountManager = AccountManager.getInstance(connection); accountManager.createAccount(user, password); } if (login) { @@ -194,19 +249,19 @@ public boolean accept(Packet packet) { * If there is no "@" symbol in the room, find the chat service JID and * return fully qualified JID for the room as room@conference.server.domain */ - public String resolveRoom(XMPPConnection connection) throws XMPPException { + public String resolveRoom(XMPPConnection connection) throws XMPPException, SmackException { ObjectHelper.notEmpty(room, "room"); if (room.indexOf('@', 0) != -1) { return room; } - Iterator iterator = MultiUserChat.getServiceNames(connection).iterator(); - if (!iterator.hasNext()) { - throw new XMPPException("Cannot find Multi User Chat service on connection: " + getConnectionMessage(connection)); + Collection mucServices = MultiUserChat.getServiceNames(connection); + if (mucServices.isEmpty()) { + throw new SmackException("Cannot find Multi User Chat service on connection: " + getConnectionMessage(connection)); } - String chatServer = iterator.next(); + String chatServer = mucServices.iterator().next(); LOG.debug("Detected chat server: {}", chatServer); return room + "@" + chatServer; @@ -220,18 +275,14 @@ public static String getConnectionMessage(XMPPConnection connection) { return connection.getHost() + ":" + connection.getPort() + "/" + connection.getServiceName(); } - public static String getXmppExceptionLogMessage(XMPPException e) { + public static String getXmppExceptionLogMessage(XMPPErrorException e) { XMPPError xmppError = e.getXMPPError(); - Throwable t = e.getWrappedThrowable(); StringBuilder strBuff = new StringBuilder(); if (xmppError != null) { - strBuff.append("[ ").append(xmppError.getCode()).append(" ] ") + strBuff.append("[ ").append(xmppError.getType()).append(" ] ") .append(xmppError.getCondition()).append(" : ") .append(xmppError.getMessage()); } - if (t != null) { - strBuff.append(" ( ").append(e.getWrappedThrowable().getMessage()).append(" )"); - } return strBuff.toString(); } @@ -341,6 +392,14 @@ public void setServiceName(String serviceName) { this.serviceName = serviceName; } + public void setUseTls(boolean useTls) { + this.useTls = useTls; + } + + public void setAcceptAllCertificates(boolean acceptAllCertificates) { + this.acceptAllCertificates = acceptAllCertificates; + } + public String getServiceName() { return serviceName; } diff --git a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppGroupChatProducer.java b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppGroupChatProducer.java index 67d7227864d14..a597448b1eb77 100644 --- a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppGroupChatProducer.java +++ b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppGroupChatProducer.java @@ -16,12 +16,15 @@ */ package org.apache.camel.component.xmpp; +import java.io.IOException; + import org.apache.camel.Exchange; import org.apache.camel.RuntimeExchangeException; import org.apache.camel.impl.DefaultProducer; -import org.jivesoftware.smack.SmackConfiguration; +import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smackx.muc.DiscussionHistory; import org.jivesoftware.smackx.muc.MultiUserChat; @@ -48,7 +51,7 @@ public void process(Exchange exchange) { if (connection == null) { try { connection = endpoint.createConnection(); - } catch (XMPPException e) { + } catch (XMPPException | SmackException | IOException e) { throw new RuntimeExchangeException("Could not connect to XMPP server.", exchange, e); } } @@ -79,12 +82,12 @@ public void process(Exchange exchange) { // must invoke nextMessage to consume the response from the server // otherwise the client local queue will fill up (CAMEL-1467) chat.pollMessage(); - } catch (XMPPException e) { + } catch (XMPPException | SmackException | IOException e) { throw new RuntimeExchangeException("Could not send XMPP message: " + message, exchange, e); } } - private synchronized void reconnect() throws XMPPException { + private synchronized void reconnect() throws XMPPException, SmackException, IOException { if (!connection.isConnected()) { if (LOG.isDebugEnabled()) { LOG.debug("Reconnecting to: {}", XmppEndpoint.getConnectionMessage(connection)); @@ -98,7 +101,7 @@ protected void doStart() throws Exception { if (connection == null) { try { connection = endpoint.createConnection(); - } catch (XMPPException e) { + } catch (XMPPErrorException e) { if (endpoint.isTestConnectionOnStartup()) { throw new RuntimeException("Could not connect to XMPP server: " + endpoint.getConnectionDescription(), e); } else { @@ -114,13 +117,13 @@ protected void doStart() throws Exception { super.doStart(); } - protected synchronized void initializeChat() throws XMPPException { + protected synchronized void initializeChat() throws XMPPException, SmackException { if (chat == null) { room = endpoint.resolveRoom(connection); chat = new MultiUserChat(connection, room); DiscussionHistory history = new DiscussionHistory(); history.setMaxChars(0); // we do not want any historical messages - chat.join(endpoint.getNickname(), null, history, SmackConfiguration.getPacketReplyTimeout()); + chat.join(endpoint.getNickname(), null, history, connection.getPacketReplyTimeout()); if (LOG.isInfoEnabled()) { LOG.info("Joined room: {} as: {}", room, endpoint.getNickname()); } diff --git a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppPrivateChatProducer.java b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppPrivateChatProducer.java index 33644d0b388cb..1110964b57a4a 100644 --- a/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppPrivateChatProducer.java +++ b/components/camel-xmpp/src/main/java/org/apache/camel/component/xmpp/XmppPrivateChatProducer.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.xmpp; +import java.io.IOException; + import org.apache.camel.Exchange; import org.apache.camel.RuntimeExchangeException; import org.apache.camel.impl.DefaultProducer; @@ -23,8 +25,11 @@ import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.ChatManager; import org.jivesoftware.smack.MessageListener; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.packet.Message; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,7 +63,7 @@ public void process(Exchange exchange) { if (!connection.isConnected()) { this.reconnect(); } - } catch (XMPPException e) { + } catch (XMPPException | SmackException | IOException e) { throw new RuntimeException("Could not connect to XMPP server.", e); } @@ -70,7 +75,7 @@ public void process(Exchange exchange) { thread = "Chat:" + participant + ":" + endpoint.getUser(); } - ChatManager chatManager = connection.getChatManager(); + ChatManager chatManager = ChatManager.getInstanceFor(connection); Chat chat = getOrCreateChat(chatManager, participant, thread); Message message = null; try { @@ -86,7 +91,7 @@ public void process(Exchange exchange) { LOG.debug("Sending XMPP message to {} from {} : {}", new Object[]{participant, endpoint.getUser(), message.getBody()}); } chat.sendMessage(message); - } catch (XMPPException xmppe) { + } catch (NotConnectedException xmppe) { throw new RuntimeExchangeException("Could not send XMPP message: to " + participant + " from " + endpoint.getUser() + " : " + message + " to: " + XmppEndpoint.getConnectionMessage(connection), exchange, xmppe); } catch (Exception e) { @@ -117,7 +122,7 @@ public void processMessage(Chat chat, Message message) { return chat; } - private synchronized void reconnect() throws XMPPException { + private synchronized void reconnect() throws XMPPException, SmackException, IOException { if (!connection.isConnected()) { if (LOG.isDebugEnabled()) { LOG.debug("Reconnecting to: {}", XmppEndpoint.getConnectionMessage(connection)); @@ -131,7 +136,7 @@ protected void doStart() throws Exception { if (connection == null) { try { connection = endpoint.createConnection(); - } catch (XMPPException e) { + } catch (XMPPErrorException e) { if (endpoint.isTestConnectionOnStartup()) { throw new RuntimeException("Could not establish connection to XMPP server: " + endpoint.getConnectionDescription(), e); } else { diff --git a/parent/pom.xml b/parent/pom.xml index 4081f6cb363c1..36d4b881a1d5d 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -391,8 +391,7 @@ 1.6.6 1.7.7 - 3.2.1_1 - 3.2.1 + 4.0.5 1.1.0.1 2.3.0_1 4.8.1_1 @@ -498,7 +497,6 @@ org.eclipse.jetty.*;version="[7.5,10)", com.thoughtworks.xstream.*;version="[1.3,2)", org.antlr.stringtemplate.*;version="[3.0,4)", - org.jivesoftware.smack.*;version="[3.0,4)", org.ccil.cowan.tagsoup.*;version="[1.2,2)", org.mortbay.cometd.*;version="[6.1,7)", org.slf4j.*;version="[1.6,2)",