/** * * Copyright 2010 Jive Software. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jivesoftware.smack; import java.io.IOException; import java.util.Date; import java.util.Random; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.PlainStreamElement; import org.jivesoftware.smack.packet.TopLevelStreamElement; import org.jxmpp.jid.FullJid; import org.jxmpp.jid.JidTestUtil; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.stringprep.XmppStringprepException; /** * A dummy implementation of {@link XMPPConnection}, intended to be used during * unit tests. * * Instances store any packets that are delivered to be send using the * {@link #sendPacket(Stanza)} method in a blocking queue. The content of this queue * can be inspected using {@link #getSentPacket()}. Typically these queues are * used to retrieve a message that was generated by the client. * * Packets that should be processed by the client to simulate a received stanza * can be delivered using the {@linkplain #processPacket(Stanza)} method. * It invokes the registered packet interceptors and listeners. * * @see XMPPConnection * @author Guenther Niess */ public class DummyConnection extends AbstractXMPPConnection { private boolean reconnect = false; private final BlockingQueue queue = new LinkedBlockingQueue(); public static ConnectionConfiguration.Builder getDummyConfigurationBuilder() { return DummyConnectionConfiguration.builder().setServiceName(JidTestUtil.EXAMPLE_ORG).setUsernameAndPassword("dummy", "dummypass"); } public DummyConnection() { this(getDummyConfigurationBuilder().build()); } private FullJid getUserJid() { try { return JidCreate.fullFrom(config.getUsername() + "@" + config.getServiceName() + "/" + (config.getResource() != null ? config.getResource() : "Test")); } catch (XmppStringprepException e) { throw new IllegalStateException(e); } } public DummyConnection(ConnectionConfiguration configuration) { super(configuration); for (ConnectionCreationListener listener : XMPPConnectionRegistry.getConnectionCreationListeners()) { listener.connectionCreated(this); } user = getUserJid(); } @Override protected void connectInternal() { connected = true; streamId = "dummy-" + new Random(new Date().getTime()).nextInt(); if (reconnect) { notifyReconnection(); } } @Override protected void shutdown() { user = null; authenticated = false; callConnectionClosedListener(); reconnect = true; } @Override public boolean isSecureConnection() { return false; } @Override public boolean isUsingCompression() { return false; } @Override protected void loginNonAnonymously(String username, String password, String resource) throws XMPPException { user = getUserJid(); authenticated = true; } @Override public void loginAnonymously() throws XMPPException { if (!isConnected()) { throw new IllegalStateException("Not connected to server."); } if (isAuthenticated()) { throw new IllegalStateException("Already logged in to server."); } authenticated = true; } @Override public void send(PlainStreamElement element) { if (SmackConfiguration.DEBUG) { System.out.println("[SEND]: " + element.toXML()); } queue.add(element); } @Override protected void sendPacketInternal(Stanza packet) { if (SmackConfiguration.DEBUG) { System.out.println("[SEND]: " + packet.toXML()); } queue.add(packet); } /** * Returns the number of packets that's sent through {@link #sendPacket(Stanza)} and * that has not been returned by {@link #getSentPacket()}. * * @return the number of packets which are in the queue. */ public int getNumberOfSentPackets() { return queue.size(); } /** * Returns the first packet that's sent through {@link #sendPacket(Stanza)} * and that has not been returned by earlier calls to this method. * * @return a sent packet. */ public

P getSentPacket() { return getSentPacket(5 * 60); } /** * Returns the first packet that's sent through {@link #sendPacket(Stanza)} * and that has not been returned by earlier calls to this method. This * method will block for up to the specified number of seconds if no packets * have been sent yet. * * @return a sent packet. */ @SuppressWarnings("unchecked") public

P getSentPacket(int wait) { try { return (P) queue.poll(wait, TimeUnit.SECONDS); } catch (InterruptedException e) { throw new IllegalStateException(e); } } /** * Processes a packet through the installed packet collectors and listeners * and letting them examine the packet to see if they are a match with the * filter. * * @param packet the packet to process. */ public void processPacket(Stanza packet) { if (SmackConfiguration.DEBUG) { System.out.println("[RECV]: " + packet.toXML()); } invokePacketCollectorsAndNotifyRecvListeners(packet); } public static DummyConnection newConnectedDummyConnection() { DummyConnection dummyConnection = new DummyConnection(); try { dummyConnection.connect(); dummyConnection.login(); } catch (InterruptedException | SmackException | IOException | XMPPException e) { throw new IllegalStateException(e); } return dummyConnection; } public static class DummyConnectionConfiguration extends ConnectionConfiguration { protected DummyConnectionConfiguration(Builder builder) { super(builder); } public static Builder builder() { return new Builder(); } public static class Builder extends ConnectionConfiguration.Builder { private Builder() { } @Override public DummyConnectionConfiguration build() { return new DummyConnectionConfiguration(this); } @Override protected Builder getThis() { return this; } } } }