1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2025-09-11 11:19:41 +02:00

Merge branch '4.2'

This commit is contained in:
Florian Schmaus 2017-02-11 20:55:43 +01:00
commit ca54f65b3e
346 changed files with 7037 additions and 5593 deletions

View file

@ -53,6 +53,7 @@ import org.jxmpp.jid.Jid;
*
* @see <a href="https://xmpp.org/extensions/xep-0296.html">XEP-0296: Best Practices for Resource Locking</a>
*/
@SuppressWarnings("FunctionalInterfaceClash")
public final class ChatManager extends Manager {
private static final Map<XMPPConnection, ChatManager> INSTANCES = new WeakHashMap<>();
@ -69,7 +70,7 @@ public final class ChatManager extends Manager {
// @FORMATTER:OFF
private static final StanzaFilter MESSAGE_FILTER = new AndFilter(
MessageTypeFilter.NORMAL_OR_CHAT,
new OrFilter(MessageWithBodiesFilter.INSTANCE), new StanzaExtensionFilter(XHTMLExtension.ELEMENT, XHTMLExtension.NAMESPACE)
new OrFilter(MessageWithBodiesFilter.INSTANCE, new StanzaExtensionFilter(XHTMLExtension.ELEMENT, XHTMLExtension.NAMESPACE))
);
private static final StanzaFilter OUTGOING_MESSAGE_FILTER = new AndFilter(
@ -188,22 +189,84 @@ public final class ChatManager extends Manager {
return true;
}
public boolean addListener(IncomingChatMessageListener listener) {
/**
* Add a new listener for incoming chat messages.
*
* @param listener the listener to add.
* @return <code>true</code> if the listener was not already added.
*/
public boolean addIncomingListener(IncomingChatMessageListener listener) {
return incomingListeners.add(listener);
}
/**
* Add a new listener for incoming chat messages.
*
* @param listener the listener to add.
* @return <code>true</code> if the listener was not already added.
*/
@Deprecated
@SuppressWarnings("FunctionalInterfaceClash")
public boolean addListener(IncomingChatMessageListener listener) {
return addIncomingListener(listener);
}
/**
* Remove an incoming chat message listener.
*
* @param listener the listener to remove.
* @return <code>true</code> if the listener was active and got removed.
*/
@SuppressWarnings("FunctionalInterfaceClash")
public boolean removeListener(IncomingChatMessageListener listener) {
return incomingListeners.remove(listener);
}
public boolean addListener(OutgoingChatMessageListener listener) {
/**
* Add a new listener for outgoing chat messages.
*
* @param listener the listener to add.
* @return <code>true</code> if the listener was not already added.
*/
public boolean addOutgoingListener(OutgoingChatMessageListener listener) {
return outgoingListeners.add(listener);
}
public boolean removeOutoingLIstener(OutgoingChatMessageListener listener) {
/**
* Add a new listener for incoming chat messages.
*
* @param listener the listener to add.
* @return <code>true</code> if the listener was not already added.
* @deprecated use {@link #addOutgoingListener(OutgoingChatMessageListener)} instead.
*/
@Deprecated
@SuppressWarnings("FunctionalInterfaceClash")
public boolean addListener(OutgoingChatMessageListener listener) {
return addOutgoingListener(listener);
}
/**
* Remove an outgoing chat message listener.
*
* @param listener the listener to remove.
* @return <code>true</code> if the listener was active and got removed.
*/
public boolean removeListener(OutgoingChatMessageListener listener) {
return outgoingListeners.remove(listener);
}
/**
* Remove an outgoing chat message listener.
*
* @param listener the listener to remove.
* @return <code>true</code> if the listener was active and got removed.
* @deprecated use {@link #removeListener(OutgoingChatMessageListener)} instead.
*/
@Deprecated
public boolean removeOutoingLIstener(OutgoingChatMessageListener listener) {
return removeListener(listener);
}
/**
* Start a new or retrieve the existing chat with <code>jid</code>.
*

View file

@ -40,6 +40,7 @@ public class AMPManager {
// The ServiceDiscoveryManager class should have been already initialized
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
AMPManager.setServiceEnabled(connection, true);
}

View file

@ -47,6 +47,7 @@ public class AttentionExtension implements ExtensionElement {
*
* @see org.jivesoftware.smack.packet.PacketExtension#getElementName()
*/
@Override
public String getElementName() {
return ELEMENT_NAME;
}
@ -56,6 +57,7 @@ public class AttentionExtension implements ExtensionElement {
*
* @see org.jivesoftware.smack.packet.PacketExtension#getNamespace()
*/
@Override
public String getNamespace() {
return NAMESPACE;
}
@ -65,6 +67,7 @@ public class AttentionExtension implements ExtensionElement {
*
* @see org.jivesoftware.smack.packet.PacketExtension#toXML()
*/
@Override
public String toXML() {
final StringBuilder sb = new StringBuilder();
sb.append('<').append(getElementName()).append(" xmlns=\"").append(

View file

@ -0,0 +1,23 @@
/**
*
* Copyright 2017 Florian Schmaus
*
* 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.smackx.blocking;
public interface AllJidsUnblockedListener {
void onAllJidsUnblocked();
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2016 Fernando Ramirez, Florian Schmaus
* Copyright 2016-2017 Fernando Ramirez, Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,7 +20,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import org.jivesoftware.smack.AbstractConnectionListener;
import org.jivesoftware.smack.ConnectionCreationListener;
@ -82,6 +84,12 @@ public final class BlockingCommandManager extends Manager {
return blockingCommandManager;
}
private final Set<AllJidsUnblockedListener> allJidsUnblockedListeners = new CopyOnWriteArraySet<>();
private final Set<JidsBlockedListener> jidsBlockedListeners = new CopyOnWriteArraySet<>();
private final Set<JidsUnblockedListener> jidsUnblockedListeners = new CopyOnWriteArraySet<>();
private BlockingCommandManager(XMPPConnection connection) {
super(connection);
@ -99,6 +107,10 @@ public final class BlockingCommandManager extends Manager {
List<Jid> blockedJids = blockContactIQ.getJids();
blockListCached.addAll(blockedJids);
for (JidsBlockedListener listener : jidsBlockedListeners) {
listener.onJidsBlocked(blockedJids);
}
return IQ.createResultIQ(blockContactIQ);
}
});
@ -117,8 +129,14 @@ public final class BlockingCommandManager extends Manager {
List<Jid> unblockedJids = unblockContactIQ.getJids();
if (unblockedJids == null) { // remove all
blockListCached.clear();
for (AllJidsUnblockedListener listener : allJidsUnblockedListeners) {
listener.onAllJidsUnblocked();
}
} else { // remove only some
blockListCached.removeAll(unblockedJids);
for (JidsUnblockedListener listener : jidsUnblockedListeners) {
listener.onJidsUnblocked(unblockedJids);
}
}
return IQ.createResultIQ(unblockContactIQ);
@ -216,4 +234,27 @@ public final class BlockingCommandManager extends Manager {
connection().createStanzaCollectorAndSend(unblockContactIQ).nextResultOrThrow();
}
public void addJidsBlockedListener(JidsBlockedListener jidsBlockedListener) {
jidsBlockedListeners.add(jidsBlockedListener);
}
public void removeJidsBlockedListener(JidsBlockedListener jidsBlockedListener) {
jidsBlockedListeners.remove(jidsBlockedListener);
}
public void addJidsUnblockedListener(JidsUnblockedListener jidsUnblockedListener) {
jidsUnblockedListeners.add(jidsUnblockedListener);
}
public void removeJidsUnblockedListener(JidsUnblockedListener jidsUnblockedListener) {
jidsUnblockedListeners.remove(jidsUnblockedListener);
}
public void addAllJidsUnblockedListener(AllJidsUnblockedListener allJidsUnblockedListener) {
allJidsUnblockedListeners.add(allJidsUnblockedListener);
}
public void removeAllJidsUnblockedListener(AllJidsUnblockedListener allJidsUnblockedListener) {
allJidsUnblockedListeners.remove(allJidsUnblockedListener);
}
}

View file

@ -0,0 +1,27 @@
/**
*
* Copyright 2017 Florian Schmaus
*
* 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.smackx.blocking;
import java.util.List;
import org.jxmpp.jid.Jid;
public interface JidsBlockedListener {
void onJidsBlocked(List<Jid> blockedJids);
}

View file

@ -0,0 +1,27 @@
/**
*
* Copyright 2017 Florian Schmaus
*
* 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.smackx.blocking;
import java.util.List;
import org.jxmpp.jid.Jid;
public interface JidsUnblockedListener {
void onJidsUnblocked(List<Jid> unblockedJids);
}

View file

@ -16,6 +16,7 @@
*/
package org.jivesoftware.smackx.blocking.element;
import java.util.Collections;
import java.util.List;
import org.jivesoftware.smack.packet.IQ;
@ -51,7 +52,7 @@ public class BlockContactsIQ extends IQ {
public BlockContactsIQ(List<Jid> jids) {
super(ELEMENT, NAMESPACE);
this.setType(Type.set);
this.jids = jids;
this.jids = Collections.unmodifiableList(jids);
}
/**

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2016 Fernando Ramirez, Florian Schmaus
* Copyright 2016-2017 Fernando Ramirez, Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@
*/
package org.jivesoftware.smackx.blocking.element;
import java.util.Collections;
import java.util.List;
import org.jivesoftware.smack.packet.IQ;
@ -52,7 +53,11 @@ public class UnblockContactsIQ extends IQ {
public UnblockContactsIQ(List<Jid> jids) {
super(ELEMENT, NAMESPACE);
this.setType(Type.set);
this.jids = jids;
if (jids != null) {
this.jids = Collections.unmodifiableList(jids);
} else {
this.jids = null;
}
}
/**
@ -63,9 +68,9 @@ public class UnblockContactsIQ extends IQ {
}
/**
* Get the JIDs.
* Get the JIDs. This may return null, which means that all JIDs should be or where unblocked.
*
* @return the list of JIDs
* @return the list of JIDs or <code>null</code>.
*/
public List<Jid> getJids() {
return jids;
@ -73,14 +78,16 @@ public class UnblockContactsIQ extends IQ {
@Override
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
xml.rightAngleBracket();
if (jids == null) {
xml.setEmptyElement();
return xml;
}
if (jids != null) {
for (Jid jid : jids) {
xml.halfOpenElement("item");
xml.attribute("jid", jid);
xml.closeEmptyElement();
}
xml.rightAngleBracket();
for (Jid jid : jids) {
xml.halfOpenElement("item");
xml.attribute("jid", jid);
xml.closeEmptyElement();
}
return xml;

View file

@ -20,9 +20,9 @@ import java.util.ArrayList;
import java.util.List;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smackx.blocking.element.BlockContactsIQ;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
import org.xmlpull.v1.XmlPullParser;
/**
@ -36,7 +36,7 @@ public class BlockContactsIQProvider extends IQProvider<BlockContactsIQ> {
@Override
public BlockContactsIQ parse(XmlPullParser parser, int initialDepth) throws Exception {
List<Jid> jids = null;
List<Jid> jids = new ArrayList<>();
outerloop: while (true) {
int eventType = parser.next();
@ -45,10 +45,8 @@ public class BlockContactsIQProvider extends IQProvider<BlockContactsIQ> {
case XmlPullParser.START_TAG:
if (parser.getName().equals("item")) {
if (jids == null) {
jids = new ArrayList<>();
}
jids.add(JidCreate.from(parser.getAttributeValue("", "jid")));
Jid jid = ParserUtils.getJidAttribute(parser);
jids.add(jid);
}
break;

View file

@ -131,6 +131,7 @@ public class BookmarkedConference implements SharedBookmark {
this.isShared = isShared;
}
@Override
public boolean isShared() {
return isShared;
}

View file

@ -102,6 +102,7 @@ public class BookmarkedURL implements SharedBookmark {
this.isShared = shared;
}
@Override
public boolean isShared() {
return isShared;
}

View file

@ -151,6 +151,7 @@ public class Bookmarks implements PrivateData {
*
* @return the element name.
*/
@Override
public String getElementName() {
return ELEMENT;
}
@ -160,6 +161,7 @@ public class Bookmarks implements PrivateData {
*
* @return the namespace.
*/
@Override
public String getNamespace() {
return NAMESPACE;
}
@ -218,6 +220,7 @@ public class Bookmarks implements PrivateData {
super();
}
@Override
public PrivateData parsePrivateData(XmlPullParser parser) throws XmlPullParserException, IOException {
Bookmarks storage = new Bookmarks();

View file

@ -34,6 +34,7 @@ public abstract class InBandBytestreamListener implements BytestreamListener {
@Override
public void incomingBytestreamRequest(BytestreamRequest request) {
incomingBytestreamRequest((InBandBytestreamRequest) request);
}

View file

@ -103,6 +103,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
*/
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(final XMPPConnection connection) {
// create the manager for this connection
InBandBytestreamManager.getByteStreamManager(connection);
@ -236,6 +237,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
*
* @param listener the listener to register
*/
@Override
public void addIncomingBytestreamListener(BytestreamListener listener) {
this.allRequestListeners.add(listener);
}
@ -246,6 +248,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
*
* @param listener the listener to remove
*/
@Override
public void removeIncomingBytestreamListener(BytestreamListener listener) {
this.allRequestListeners.remove(listener);
}
@ -268,6 +271,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
* @param listener the listener to register
* @param initiatorJID the JID of the user that wants to establish an In-Band Bytestream
*/
@Override
public void addIncomingBytestreamListener(BytestreamListener listener, Jid initiatorJID) {
this.userListeners.put(initiatorJID, listener);
}
@ -277,6 +281,9 @@ public final class InBandBytestreamManager implements BytestreamManager {
*
* @param initiatorJID the JID of the user the listener should be removed
*/
@Override
// TODO: Change argument to Jid in Smack 4.3.
@SuppressWarnings("CollectionIncompatibleType")
public void removeIncomingBytestreamListener(String initiatorJID) {
this.userListeners.remove(initiatorJID);
}
@ -402,6 +409,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
* @throws SmackException if there was no response from the server.
* @throws InterruptedException
*/
@Override
public InBandBytestreamSession establishSession(Jid targetJID) throws XMPPException, SmackException, InterruptedException {
String sessionID = getNextSessionID();
return establishSession(targetJID, sessionID);
@ -420,6 +428,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
* @throws NotConnectedException
* @throws InterruptedException
*/
@Override
public InBandBytestreamSession establishSession(Jid targetJID, String sessionID)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
Open byteStreamRequest = new Open(sessionID, this.defaultBlockSize, this.stanza);

View file

@ -50,6 +50,7 @@ public class InBandBytestreamRequest implements BytestreamRequest {
*
* @return the sender of the In-Band Bytestream open request
*/
@Override
public Jid getFrom() {
return this.byteStreamRequest.getFrom();
}
@ -59,6 +60,7 @@ public class InBandBytestreamRequest implements BytestreamRequest {
*
* @return the session ID of the In-Band Bytestream open request
*/
@Override
public String getSessionID() {
return this.byteStreamRequest.getSessionID();
}
@ -71,6 +73,7 @@ public class InBandBytestreamRequest implements BytestreamRequest {
* @throws NotConnectedException
* @throws InterruptedException
*/
@Override
public InBandBytestreamSession accept() throws NotConnectedException, InterruptedException {
XMPPConnection connection = this.manager.getConnection();
@ -92,6 +95,7 @@ public class InBandBytestreamRequest implements BytestreamRequest {
* @throws NotConnectedException
* @throws InterruptedException
*/
@Override
public void reject() throws NotConnectedException, InterruptedException {
this.manager.replyRejectPacket(this.byteStreamRequest);
}

View file

@ -109,18 +109,22 @@ public class InBandBytestreamSession implements BytestreamSession {
}
@Override
public InputStream getInputStream() {
return this.inputStream;
}
@Override
public OutputStream getOutputStream() {
return this.outputStream;
}
@Override
public int getReadTimeout() {
return this.inputStream.readTimeout;
}
@Override
public void setReadTimeout(int timeout) {
if (timeout < 0) {
throw new IllegalArgumentException("Timeout must be >= 0");
@ -151,6 +155,7 @@ public class InBandBytestreamSession implements BytestreamSession {
this.closeBothStreamsEnabled = closeBothStreamsEnabled;
}
@Override
public void close() throws IOException {
closeByLocal(true); // close input stream
closeByLocal(false); // close output stream
@ -224,7 +229,9 @@ public class InBandBytestreamSession implements BytestreamSession {
this.inputStream.cleanup();
// remove session from manager
InBandBytestreamManager.getByteStreamManager(this.connection).getSessions().remove(this);
// Thanks Google Error Prone for finding the bug where remove() was called with 'this' as argument. Changed
// now to remove(byteStreamRequest.getSessionID).
InBandBytestreamManager.getByteStreamManager(this.connection).getSessions().remove(byteStreamRequest.getSessionID());
}
}
@ -283,6 +290,7 @@ public class InBandBytestreamSession implements BytestreamSession {
*/
protected abstract StanzaFilter getDataPacketFilter();
@Override
public synchronized int read() throws IOException {
checkClosed();
@ -298,6 +306,7 @@ public class InBandBytestreamSession implements BytestreamSession {
return buffer[bufferPointer++] & 0xff;
}
@Override
public synchronized int read(byte[] b, int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
@ -331,6 +340,7 @@ public class InBandBytestreamSession implements BytestreamSession {
return len;
}
@Override
public synchronized int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@ -405,10 +415,12 @@ public class InBandBytestreamSession implements BytestreamSession {
}
}
@Override
public boolean markSupported() {
return false;
}
@Override
public void close() throws IOException {
if (closeInvoked) {
return;
@ -444,11 +456,13 @@ public class InBandBytestreamSession implements BytestreamSession {
*/
private class IQIBBInputStream extends IBBInputStream {
@Override
protected StanzaListener getDataPacketListener() {
return new StanzaListener() {
private long lastSequence = -1;
@Override
public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException {
// get data packet extension
DataPacketExtension data = ((Data) packet).getDataPacketExtension();
@ -491,6 +505,7 @@ public class InBandBytestreamSession implements BytestreamSession {
};
}
@Override
protected StanzaFilter getDataPacketFilter() {
/*
* filter all IQ stanzas having type 'SET' (represented by Data class), containing a
@ -507,9 +522,11 @@ public class InBandBytestreamSession implements BytestreamSession {
*/
private class MessageIBBInputStream extends IBBInputStream {
@Override
protected StanzaListener getDataPacketListener() {
return new StanzaListener() {
@Override
public void processStanza(Stanza packet) {
// get data packet extension
DataPacketExtension data = (DataPacketExtension) packet.getExtension(
@ -555,6 +572,7 @@ public class InBandBytestreamSession implements BytestreamSession {
*/
private class IBBDataPacketFilter implements StanzaFilter {
@Override
public boolean accept(Stanza packet) {
// sender equals remote peer
if (!packet.getFrom().equals(remoteJID)) {
@ -619,6 +637,7 @@ public class InBandBytestreamSession implements BytestreamSession {
*/
protected abstract void writeToXML(DataPacketExtension data) throws IOException, NotConnectedException, InterruptedException;
@Override
public synchronized void write(int b) throws IOException {
if (this.isClosed) {
throw new IOException("Stream is closed");
@ -632,6 +651,7 @@ public class InBandBytestreamSession implements BytestreamSession {
buffer[bufferPointer++] = (byte) b;
}
@Override
public synchronized void write(byte[] b, int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
@ -662,6 +682,7 @@ public class InBandBytestreamSession implements BytestreamSession {
}
}
@Override
public synchronized void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
@ -698,6 +719,7 @@ public class InBandBytestreamSession implements BytestreamSession {
bufferPointer += len - available;
}
@Override
public synchronized void flush() throws IOException {
if (this.isClosed) {
throw new IOException("Stream is closed");
@ -735,6 +757,7 @@ public class InBandBytestreamSession implements BytestreamSession {
}
@Override
public void close() throws IOException {
if (isClosed) {
return;

View file

@ -66,6 +66,7 @@ class InitiationListener extends AbstractIqRequestHandler {
public IQ handleIQRequest(final IQ packet) {
initiationListenerExecutor.execute(new Runnable() {
@Override
public void run() {
try {
processRequest(packet);

View file

@ -126,10 +126,12 @@ public class DataPacketExtension implements ExtensionElement {
return this.decodedData;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public String getNamespace() {
return NAMESPACE;
}

View file

@ -62,6 +62,7 @@ final class InitiationListener extends AbstractIqRequestHandler {
public IQ handleIQRequest(final IQ packet) {
initiationListenerExecutor.execute(new Runnable() {
@Override
public void run() {
try {
processRequest(packet);

View file

@ -32,6 +32,7 @@ import org.jivesoftware.smackx.bytestreams.BytestreamRequest;
*/
public abstract class Socks5BytestreamListener implements BytestreamListener {
@Override
public void incomingBytestreamRequest(BytestreamRequest request) {
incomingBytestreamRequest((Socks5BytestreamRequest) request);
}

View file

@ -98,6 +98,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(final XMPPConnection connection) {
// create the manager for this connection
Socks5BytestreamManager.getBytestreamManager(connection);
@ -198,6 +199,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
*
* @param listener the listener to register
*/
@Override
public void addIncomingBytestreamListener(BytestreamListener listener) {
this.allRequestListeners.add(listener);
}
@ -208,6 +210,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
*
* @param listener the listener to remove
*/
@Override
public void removeIncomingBytestreamListener(BytestreamListener listener) {
this.allRequestListeners.remove(listener);
}
@ -230,6 +233,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
* @param listener the listener to register
* @param initiatorJID the JID of the user that wants to establish a SOCKS5 Bytestream
*/
@Override
public void addIncomingBytestreamListener(BytestreamListener listener, Jid initiatorJID) {
this.userListeners.put(initiatorJID, listener);
}
@ -239,6 +243,9 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
*
* @param initiatorJID the JID of the user the listener should be removed
*/
// TODO: Change parameter to Jid in Smack 4.3.
@Override
@SuppressWarnings("CollectionIncompatibleType")
public void removeIncomingBytestreamListener(String initiatorJID) {
this.userListeners.remove(initiatorJID);
}
@ -386,6 +393,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
* @throws InterruptedException if the current thread was interrupted while waiting
* @throws SmackException if there was no response from the server.
*/
@Override
public Socks5BytestreamSession establishSession(Jid targetJID) throws XMPPException,
IOException, InterruptedException, SmackException {
String sessionID = getNextSessionID();
@ -405,6 +413,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
* @throws SmackException if the target does not support SOCKS5.
* @throws XMPPException
*/
@Override
public Socks5BytestreamSession establishSession(Jid targetJID, String sessionID)
throws IOException, InterruptedException, NoResponseException, SmackException, XMPPException{
XMPPConnection connection = connection();

View file

@ -170,6 +170,7 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
*
* @return the sender of the SOCKS5 Bytestream initialization request.
*/
@Override
public Jid getFrom() {
return this.bytestreamRequest.getFrom();
}
@ -179,6 +180,7 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
*
* @return the session ID of the SOCKS5 Bytestream initialization request.
*/
@Override
public String getSessionID() {
return this.bytestreamRequest.getSessionID();
}
@ -195,6 +197,7 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
* @throws XMPPErrorException
* @throws SmackException
*/
@Override
public Socks5BytestreamSession accept() throws InterruptedException, XMPPErrorException, SmackException {
Collection<StreamHost> streamHosts = this.bytestreamRequest.getStreamHosts();
@ -264,6 +267,7 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
* @throws NotConnectedException
* @throws InterruptedException
*/
@Override
public void reject() throws NotConnectedException, InterruptedException {
this.manager.replyRejectPacket(this.bytestreamRequest);
}

View file

@ -64,14 +64,17 @@ public class Socks5BytestreamSession implements BytestreamSession {
return !this.isDirect;
}
@Override
public InputStream getInputStream() throws IOException {
return this.socket.getInputStream();
}
@Override
public OutputStream getOutputStream() throws IOException {
return this.socket.getOutputStream();
}
@Override
public int getReadTimeout() throws IOException {
try {
return this.socket.getSoTimeout();
@ -81,6 +84,7 @@ public class Socks5BytestreamSession implements BytestreamSession {
}
}
@Override
public void setReadTimeout(int timeout) throws IOException {
try {
this.socket.setSoTimeout(timeout);
@ -90,6 +94,7 @@ public class Socks5BytestreamSession implements BytestreamSession {
}
}
@Override
public void close() throws IOException {
this.socket.close();
}

View file

@ -19,6 +19,7 @@ package org.jivesoftware.smackx.bytestreams.socks5;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
@ -34,6 +35,7 @@ import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost;
/**
@ -82,6 +84,7 @@ class Socks5Client {
// wrap connecting in future for timeout
FutureTask<Socket> futureTask = new FutureTask<Socket>(new Callable<Socket>() {
@Override
public Socket call() throws IOException, SmackException {
// initialize socket
@ -199,7 +202,13 @@ class Socks5Client {
* @return SOCKS5 connection request message
*/
private byte[] createSocks5ConnectRequest() {
byte[] addr = this.digest.getBytes();
byte[] addr;
try {
addr = digest.getBytes(StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
byte[] data = new byte[7 + addr.length];
data[0] = (byte) 0x05; // version (SOCKS5)

View file

@ -69,6 +69,7 @@ class Socks5ClientForInitiator extends Socks5Client {
this.target = target;
}
@Override
public Socket getSocket(int timeout) throws IOException, InterruptedException,
TimeoutException, XMPPException, SmackException {
Socket socket = null;

View file

@ -38,6 +38,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.util.StringUtils;
/**
* The Socks5Proxy class represents a local SOCKS5 proxy server. It can be enabled/disabled by
@ -381,6 +382,7 @@ public final class Socks5Proxy {
*/
private class Socks5ServerProcess implements Runnable {
@Override
public void run() {
while (true) {
Socket socket = null;
@ -470,7 +472,7 @@ public final class Socks5Proxy {
byte[] connectionRequest = Socks5Utils.receiveSocks5Message(in);
// extract digest
String responseDigest = new String(connectionRequest, 5, connectionRequest[4]);
String responseDigest = new String(connectionRequest, 5, connectionRequest[4], StringUtils.UTF8);
// return error if digest is not allowed
if (!Socks5Proxy.this.allowedConnections.contains(responseDigest)) {

View file

@ -317,6 +317,7 @@ public class Bytestream extends IQ {
return port;
}
@Override
public String getElementName() {
return ELEMENTNAME;
}
@ -366,6 +367,7 @@ public class Bytestream extends IQ {
return JID;
}
@Override
public String getElementName() {
return ELEMENTNAME;
}
@ -408,6 +410,7 @@ public class Bytestream extends IQ {
return target;
}
@Override
public String getElementName() {
return ELEMENTNAME;
}

View file

@ -65,6 +65,7 @@ import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ -113,6 +114,7 @@ public final class EntityCapsManager extends Manager {
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
getInstanceFor(connection);
}
@ -346,6 +348,7 @@ public final class EntityCapsManager extends Manager {
// XEP-0115 specifies that a client SHOULD include entity capabilities
// with every presence notification it sends.
StanzaListener packetInterceptor = new StanzaListener() {
@Override
public void processStanza(Stanza packet) {
if (!entityCapsEnabled) {
// Be sure to not send stanzas with the caps extension if it's not enabled
@ -403,7 +406,11 @@ public final class EntityCapsManager extends Manager {
* @param user
* the user (Full JID)
*/
// TODO: Change parameter type to Jid in Smack 4.3.
@SuppressWarnings("CollectionIncompatibleType")
public static void removeUserCapsNode(String user) {
// While JID_TO_NODEVER_CHACHE has the generic types <Jid, NodeVerHash>, it is ok to call remove with String
// arguments, since the same Jid and String representations would be equal and have the same hash code.
JID_TO_NODEVER_CACHE.remove(user);
}
@ -658,6 +665,7 @@ public final class EntityCapsManager extends Manager {
// XEP-0128 data forms, sort the forms by the FORM_TYPE (i.e.,
// by the XML character data of the <value/> element).
SortedSet<FormField> fs = new TreeSet<FormField>(new Comparator<FormField>() {
@Override
public int compare(FormField f1, FormField f2) {
return f1.getVariable().compareTo(f2.getVariable());
}
@ -701,9 +709,16 @@ public final class EntityCapsManager extends Manager {
// encoded using Base64 as specified in Section 4 of RFC 4648
// (note: the Base64 output MUST NOT include whitespace and MUST set
// padding bits to zero).
byte[] bytes;
try {
bytes = sb.toString().getBytes(StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
byte[] digest;
synchronized(md) {
digest = md.digest(sb.toString().getBytes());
digest = md.digest(bytes);
}
String version = Base64.encodeToString(digest);
return new CapsVersionAndHash(version, hash);

View file

@ -35,10 +35,12 @@ public class CapsExtension implements ExtensionElement {
this.hash = hash;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public String getNamespace() {
return NAMESPACE;
}

View file

@ -27,6 +27,7 @@ import org.xmlpull.v1.XmlPullParserException;
public class CapsExtensionProvider extends ExtensionElementProvider<CapsExtension> {
@Override
public CapsExtension parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException,
SmackException {
String hash = null;

View file

@ -119,6 +119,7 @@ public final class ChatStateManager extends Manager {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@ -129,6 +130,7 @@ public final class ChatStateManager extends Manager {
}
@Override
public int hashCode() {
return connection().hashCode();
}
@ -164,12 +166,14 @@ public final class ChatStateManager extends Manager {
}
}
private class IncomingMessageInterceptor implements ChatManagerListener, ChatMessageListener {
private static class IncomingMessageInterceptor implements ChatManagerListener, ChatMessageListener {
@Override
public void chatCreated(final org.jivesoftware.smack.chat.Chat chat, boolean createdLocally) {
chat.addMessageListener(this);
}
@Override
public void processMessage(org.jivesoftware.smack.chat.Chat chat, Message message) {
ExtensionElement extension = message.getExtension(NAMESPACE);
if (extension == null) {

View file

@ -19,9 +19,7 @@ package org.jivesoftware.smackx.chatstates.packet;
import org.jivesoftware.smackx.chatstates.ChatState;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.xmlpull.v1.XmlPullParser;
/**
* Represents a chat state which is an extension to message packets which is used to indicate
@ -66,18 +64,4 @@ public class ChatStateExtension implements ExtensionElement {
return xml;
}
public static class Provider extends ExtensionElementProvider<ChatStateExtension> {
@Override
public ChatStateExtension parse(XmlPullParser parser, int initialDepth) {
ChatState state;
try {
state = ChatState.valueOf(parser.getName());
}
catch (Exception ex) {
state = ChatState.active;
}
return new ChatStateExtension(state);
}
}
}

View file

@ -0,0 +1,34 @@
/**
*
* Copyright 2017 Florian Schmaus
*
* 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.smackx.chatstates.provider;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smackx.chatstates.ChatState;
import org.jivesoftware.smackx.chatstates.packet.ChatStateExtension;
import org.xmlpull.v1.XmlPullParser;
public class ChatStateExtensionProvider extends ExtensionElementProvider<ChatStateExtension> {
@Override
public ChatStateExtension parse(XmlPullParser parser, int initialDepth) throws Exception {
String chatStateString = parser.getName();
ChatState state = ChatState.valueOf(chatStateString);
return new ChatStateExtension(state);
}
}

View file

@ -0,0 +1,21 @@
/**
*
* Copyright 2017 Florian Schmaus
*
* 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.
*/
/**
* Provider classes for Chat State Notifications (XEP-0085).
*/
package org.jivesoftware.smackx.chatstates.provider;

View file

@ -457,12 +457,13 @@ public abstract class AdHocCommand {
*/
sessionExpired("session-expired");
private String value;
private final String value;
SpecificErrorCondition(String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}

View file

@ -17,6 +17,7 @@
package org.jivesoftware.smackx.commands;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@ -83,6 +84,7 @@ public final class AdHocCommandManager extends Manager {
*/
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
getAddHocCommandsManager(connection);
}
@ -200,8 +202,16 @@ public final class AdHocCommandManager extends Manager {
*/
public void registerCommand(String node, String name, final Class<? extends LocalCommand> clazz) {
registerCommand(node, name, new LocalCommandFactory() {
@Override
public LocalCommand getInstance() throws InstantiationException, IllegalAccessException {
return clazz.newInstance();
try {
return clazz.getConstructor().newInstance();
}
catch (IllegalArgumentException | InvocationTargetException | NoSuchMethodException
| SecurityException e) {
// TODO: Throw those method in Smack 4.3.
throw new IllegalStateException(e);
}
}
});
}
@ -393,6 +403,7 @@ public final class AdHocCommandManager extends Manager {
// See if the session reaping thread is started. If not, start it.
if (sessionsSweeper == null) {
sessionsSweeper = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
for (String sessionId : executingCommands.keySet()) {

View file

@ -248,9 +248,11 @@ public class AdHocCommandData extends IQ {
this.condition = condition;
}
@Override
public String getElementName() {
return condition.toString();
}
@Override
public String getNamespace() {
return namespace;
}
@ -259,6 +261,7 @@ public class AdHocCommandData extends IQ {
return condition;
}
@Override
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append('<').append(getElementName());

View file

@ -88,10 +88,12 @@ public class DelayInformation implements ExtensionElement {
return reason;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public String getNamespace() {
return NAMESPACE;
}

View file

@ -25,18 +25,22 @@ import java.util.List;
public abstract class AbstractNodeInformationProvider implements NodeInformationProvider {
@Override
public List<DiscoverItems.Item> getNodeItems() {
return null;
}
@Override
public List<String> getNodeFeatures() {
return null;
}
@Override
public List<DiscoverInfo.Identity> getNodeIdentities() {
return null;
}
@Override
public List<ExtensionElement> getNodePacketExtensions() {
return null;
}

View file

@ -91,6 +91,7 @@ public final class ServiceDiscoveryManager extends Manager {
// Create a new ServiceDiscoveryManager on every established connection
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
getInstanceFor(connection);
}

View file

@ -394,6 +394,7 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
* <a href="http://xmpp.org/extensions/xep-0115.html#ver-proc">XEP-0015 5.4 Processing Method (Step 3.3)</a>.
*
*/
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
@ -437,6 +438,7 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
* @return a negative integer, zero, or a positive integer as this object is less than,
* equal to, or greater than the specified object.
*/
@Override
public int compareTo(DiscoverInfo.Identity other) {
String otherLang = other.lang == null ? "" : other.lang;
String thisLang = lang == null ? "" : lang;
@ -512,6 +514,7 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
return xml;
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;

View file

@ -55,11 +55,13 @@ public class FaultTolerantNegotiator extends StreamNegotiator {
secondaryNegotiator.newStreamInitiation(from, streamID);
}
@Override
InputStream negotiateIncomingStream(Stanza streamInitiation) {
throw new UnsupportedOperationException("Negotiation only handled by create incoming " +
"stream method.");
}
@Override
public InputStream createIncomingStream(final StreamInitiation initiation) throws SmackException, XMPPErrorException, InterruptedException {
// This could be either an xep47 ibb 'open' iq or an xep65 streamhost iq
IQ initationSet = initiateIncomingStream(connection, initiation);
@ -79,6 +81,7 @@ public class FaultTolerantNegotiator extends StreamNegotiator {
}
}
@Override
public OutputStream createOutgoingStream(String streamID, Jid initiator, Jid target)
throws SmackException, XMPPException, InterruptedException {
OutputStream stream;
@ -92,6 +95,7 @@ public class FaultTolerantNegotiator extends StreamNegotiator {
return stream;
}
@Override
public String[] getNamespaces() {
String[] primary = primaryNegotiator.getNamespaces();
String[] secondary = secondaryNegotiator.getNamespaces();

View file

@ -31,27 +31,27 @@ import org.jxmpp.jid.Jid;
*/
public abstract class FileTransfer {
private String fileName;
private String fileName;
private String filePath;
private String filePath;
private long fileSize;
private long fileSize;
private Jid peer;
private Jid peer;
private Status status = Status.initial;
private Status status = Status.initial;
private final Object statusMonitor = new Object();
protected FileTransferNegotiator negotiator;
protected FileTransferNegotiator negotiator;
protected String streamID;
protected String streamID;
protected long amountWritten = -1;
protected long amountWritten = -1;
private Error error;
private Error error;
private Exception exception;
private Exception exception;
/**
* Buffer size between input and output
@ -59,137 +59,137 @@ public abstract class FileTransfer {
private static final int BUFFER_SIZE = 8192;
protected FileTransfer(Jid peer, String streamID,
FileTransferNegotiator negotiator) {
this.peer = peer;
this.streamID = streamID;
this.negotiator = negotiator;
}
FileTransferNegotiator negotiator) {
this.peer = peer;
this.streamID = streamID;
this.negotiator = negotiator;
}
protected void setFileInfo(String fileName, long fileSize) {
this.fileName = fileName;
this.fileSize = fileSize;
}
protected void setFileInfo(String fileName, long fileSize) {
this.fileName = fileName;
this.fileSize = fileSize;
}
protected void setFileInfo(String path, String fileName, long fileSize) {
this.filePath = path;
this.fileName = fileName;
this.fileSize = fileSize;
}
protected void setFileInfo(String path, String fileName, long fileSize) {
this.filePath = path;
this.fileName = fileName;
this.fileSize = fileSize;
}
/**
* Returns the size of the file being transfered.
*
* @return Returns the size of the file being transfered.
*/
public long getFileSize() {
return fileSize;
}
/**
* Returns the size of the file being transfered.
*
* @return Returns the size of the file being transfered.
*/
public long getFileSize() {
return fileSize;
}
/**
* Returns the name of the file being transfered.
*
* @return Returns the name of the file being transfered.
*/
public String getFileName() {
return fileName;
}
/**
* Returns the name of the file being transfered.
*
* @return Returns the name of the file being transfered.
*/
public String getFileName() {
return fileName;
}
/**
* Returns the local path of the file.
*
* @return Returns the local path of the file.
*/
public String getFilePath() {
return filePath;
}
/**
* Returns the local path of the file.
*
* @return Returns the local path of the file.
*/
public String getFilePath() {
return filePath;
}
/**
* Returns the JID of the peer for this file transfer.
*
* @return Returns the JID of the peer for this file transfer.
*/
public Jid getPeer() {
return peer;
}
/**
* Returns the JID of the peer for this file transfer.
*
* @return Returns the JID of the peer for this file transfer.
*/
public Jid getPeer() {
return peer;
}
/**
* Returns the progress of the file transfer as a number between 0 and 1.
*
* @return Returns the progress of the file transfer as a number between 0
* and 1.
*/
public double getProgress() {
/**
* Returns the progress of the file transfer as a number between 0 and 1.
*
* @return Returns the progress of the file transfer as a number between 0
* and 1.
*/
public double getProgress() {
if (amountWritten <= 0 || fileSize <= 0) {
return 0;
}
return (double) amountWritten / (double) fileSize;
}
}
/**
* Returns true if the transfer has been cancelled, if it has stopped because
* of a an error, or the transfer completed successfully.
*
* @return Returns true if the transfer has been cancelled, if it has stopped
* because of a an error, or the transfer completed successfully.
*/
public boolean isDone() {
return status == Status.cancelled || status == Status.error
|| status == Status.complete || status == Status.refused;
}
/**
* Returns true if the transfer has been cancelled, if it has stopped because
* of a an error, or the transfer completed successfully.
*
* @return Returns true if the transfer has been cancelled, if it has stopped
* because of a an error, or the transfer completed successfully.
*/
public boolean isDone() {
return status == Status.cancelled || status == Status.error
|| status == Status.complete || status == Status.refused;
}
/**
* Returns the current status of the file transfer.
*
* @return Returns the current status of the file transfer.
*/
public Status getStatus() {
return status;
}
/**
* Returns the current status of the file transfer.
*
* @return Returns the current status of the file transfer.
*/
public Status getStatus() {
return status;
}
protected void setError(Error type) {
this.error = type;
}
protected void setError(Error type) {
this.error = type;
}
/**
* When {@link #getStatus()} returns that there was an {@link Status#error}
* during the transfer, the type of error can be retrieved through this
* method.
*
* @return Returns the type of error that occurred if one has occurred.
*/
public Error getError() {
return error;
}
/**
* When {@link #getStatus()} returns that there was an {@link Status#error}
* during the transfer, the type of error can be retrieved through this
* method.
*
* @return Returns the type of error that occurred if one has occurred.
*/
public Error getError() {
return error;
}
/**
* If an exception occurs asynchronously it will be stored for later
* retrieval. If there is an error there maybe an exception set.
*
* @return The exception that occurred or null if there was no exception.
* @see #getError()
*/
public Exception getException() {
return exception;
}
/**
* If an exception occurs asynchronously it will be stored for later
* retrieval. If there is an error there maybe an exception set.
*
* @return The exception that occurred or null if there was no exception.
* @see #getError()
*/
public Exception getException() {
return exception;
}
public String getStreamID() {
return streamID;
}
/**
* Cancels the file transfer.
*/
public abstract void cancel();
/**
* Cancels the file transfer.
*/
public abstract void cancel();
protected void setException(Exception exception) {
this.exception = exception;
}
protected void setException(Exception exception) {
this.exception = exception;
}
protected void setStatus(Status status) {
protected void setStatus(Status status) {
synchronized (statusMonitor) {
// CHECKSTYLE:OFF
this.status = status;
}
this.status = status;
}
// CHECKSTYLE:ON
}
@ -206,98 +206,99 @@ public abstract class FileTransfer {
protected void writeToStream(final InputStream in, final OutputStream out)
throws IOException
{
final byte[] b = new byte[BUFFER_SIZE];
int count = 0;
amountWritten = 0;
final byte[] b = new byte[BUFFER_SIZE];
int count = 0;
amountWritten = 0;
while ((count = in.read(b)) > 0 && !getStatus().equals(Status.cancelled)) {
out.write(b, 0, count);
amountWritten += count;
}
// the connection was likely terminated abruptly if these are not equal
if (!getStatus().equals(Status.cancelled) && getError() == Error.none
&& amountWritten != fileSize) {
// the connection was likely terminated abruptly if these are not equal
if (!getStatus().equals(Status.cancelled) && getError() == Error.none
&& amountWritten != fileSize) {
setStatus(Status.error);
this.error = Error.connection;
}
}
this.error = Error.connection;
}
}
/**
* A class to represent the current status of the file transfer.
*
* @author Alexander Wenckus
*
*/
public enum Status {
/**
* A class to represent the current status of the file transfer.
*
* @author Alexander Wenckus
*
*/
public enum Status {
/**
* An error occurred during the transfer.
*
* @see FileTransfer#getError()
*/
error("Error"),
/**
* An error occurred during the transfer.
*
* @see FileTransfer#getError()
*/
error("Error"),
/**
/**
* The initial status of the file transfer.
*/
initial("Initial"),
/**
* The file transfer is being negotiated with the peer. The party
* Receiving the file has the option to accept or refuse a file transfer
* request. If they accept, then the process of stream negotiation will
* begin. If they refuse the file will not be transfered.
*
* @see #negotiating_stream
*/
negotiating_transfer("Negotiating Transfer"),
* The file transfer is being negotiated with the peer. The party
* Receiving the file has the option to accept or refuse a file transfer
* request. If they accept, then the process of stream negotiation will
* begin. If they refuse the file will not be transfered.
*
* @see #negotiating_stream
*/
negotiating_transfer("Negotiating Transfer"),
/**
* The peer has refused the file transfer request halting the file
* transfer negotiation process.
*/
refused("Refused"),
/**
* The peer has refused the file transfer request halting the file
* transfer negotiation process.
*/
refused("Refused"),
/**
* The stream to transfer the file is being negotiated over the chosen
* stream type. After the stream negotiating process is complete the
* status becomes negotiated.
*
* @see #negotiated
*/
negotiating_stream("Negotiating Stream"),
/**
* The stream to transfer the file is being negotiated over the chosen
* stream type. After the stream negotiating process is complete the
* status becomes negotiated.
*
* @see #negotiated
*/
negotiating_stream("Negotiating Stream"),
/**
* After the stream negotiation has completed the intermediate state
* between the time when the negotiation is finished and the actual
* transfer begins.
*/
negotiated("Negotiated"),
/**
* After the stream negotiation has completed the intermediate state
* between the time when the negotiation is finished and the actual
* transfer begins.
*/
negotiated("Negotiated"),
/**
* The transfer is in progress.
*
* @see FileTransfer#getProgress()
*/
in_progress("In Progress"),
/**
* The transfer is in progress.
*
* @see FileTransfer#getProgress()
*/
in_progress("In Progress"),
/**
* The transfer has completed successfully.
*/
complete("Complete"),
/**
* The transfer has completed successfully.
*/
complete("Complete"),
/**
* The file transfer was cancelled.
*/
cancelled("Cancelled");
/**
* The file transfer was cancelled.
*/
cancelled("Cancelled");
private String status;
private final String status;
private Status(String status) {
this.status = status;
}
@Override
public String toString() {
return status;
}
@ -312,55 +313,56 @@ public abstract class FileTransfer {
}
public enum Error {
/**
* No error.
*/
none("No error"),
/**
* No error.
*/
none("No error"),
/**
* The peer did not find any of the provided stream mechanisms
* acceptable.
*/
not_acceptable("The peer did not find any of the provided stream mechanisms acceptable."),
/**
* The peer did not find any of the provided stream mechanisms
* acceptable.
*/
not_acceptable("The peer did not find any of the provided stream mechanisms acceptable."),
/**
* The provided file to transfer does not exist or could not be read.
*/
bad_file("The provided file to transfer does not exist or could not be read."),
/**
* The provided file to transfer does not exist or could not be read.
*/
bad_file("The provided file to transfer does not exist or could not be read."),
/**
* The remote user did not respond or the connection timed out.
*/
no_response("The remote user did not respond or the connection timed out."),
/**
* The remote user did not respond or the connection timed out.
*/
no_response("The remote user did not respond or the connection timed out."),
/**
* An error occurred over the socket connected to send the file.
*/
connection("An error occured over the socket connected to send the file."),
/**
* An error occurred over the socket connected to send the file.
*/
connection("An error occured over the socket connected to send the file."),
/**
* An error occurred while sending or receiving the file.
*/
stream("An error occured while sending or recieving the file.");
/**
* An error occurred while sending or receiving the file.
*/
stream("An error occured while sending or recieving the file.");
private final String msg;
private final String msg;
private Error(String msg) {
this.msg = msg;
}
private Error(String msg) {
this.msg = msg;
}
/**
* Returns a String representation of this error.
*
* @return Returns a String representation of this error.
*/
public String getMessage() {
return msg;
}
/**
* Returns a String representation of this error.
*
* @return Returns a String representation of this error.
*/
public String getMessage() {
return msg;
}
public String toString() {
return msg;
}
}
@Override
public String toString() {
return msg;
}
}
}

View file

@ -23,11 +23,11 @@ package org.jivesoftware.smackx.filetransfer;
* @author Alexander Wenckus
*/
public interface FileTransferListener {
/**
* A request to send a file has been recieved from another user.
*
* @param request
* The request from the other user.
*/
public void fileTransferRequest(final FileTransferRequest request);
/**
* A request to send a file has been recieved from another user.
*
* @param request
* The request from the other user.
*/
public void fileTransferRequest(final FileTransferRequest request);
}

View file

@ -56,20 +56,20 @@ public final class FileTransferManager extends Manager {
return fileTransferManager;
}
private final FileTransferNegotiator fileTransferNegotiator;
private final FileTransferNegotiator fileTransferNegotiator;
private final List<FileTransferListener> listeners = new CopyOnWriteArrayList<FileTransferListener>();
private final List<FileTransferListener> listeners = new CopyOnWriteArrayList<FileTransferListener>();
/**
* Creates a file transfer manager to initiate and receive file transfers.
*
* @param connection
* The XMPPConnection that the file transfers will use.
*/
private FileTransferManager(XMPPConnection connection) {
super(connection);
this.fileTransferNegotiator = FileTransferNegotiator
.getInstanceFor(connection);
/**
* Creates a file transfer manager to initiate and receive file transfers.
*
* @param connection
* The XMPPConnection that the file transfers will use.
*/
private FileTransferManager(XMPPConnection connection) {
super(connection);
this.fileTransferNegotiator = FileTransferNegotiator
.getInstanceFor(connection);
connection.registerIQRequestHandler(new AbstractIqRequestHandler(StreamInitiation.ELEMENT,
StreamInitiation.NAMESPACE, IQ.Type.set, Mode.async) {
@Override
@ -82,42 +82,42 @@ public final class FileTransferManager extends Manager {
return null;
}
});
}
}
/**
* Add a file transfer listener to listen to incoming file transfer
* requests.
*
* @param li
* The listener
* @see #removeFileTransferListener(FileTransferListener)
* @see FileTransferListener
*/
public void addFileTransferListener(final FileTransferListener li) {
listeners.add(li);
}
/**
* Add a file transfer listener to listen to incoming file transfer
* requests.
*
* @param li
* The listener
* @see #removeFileTransferListener(FileTransferListener)
* @see FileTransferListener
*/
public void addFileTransferListener(final FileTransferListener li) {
listeners.add(li);
}
/**
* Removes a file transfer listener.
*
* @param li
* The file transfer listener to be removed
* @see FileTransferListener
*/
public void removeFileTransferListener(final FileTransferListener li) {
listeners.remove(li);
}
/**
* Removes a file transfer listener.
*
* @param li
* The file transfer listener to be removed
* @see FileTransferListener
*/
public void removeFileTransferListener(final FileTransferListener li) {
listeners.remove(li);
}
/**
* Creates an OutgoingFileTransfer to send a file to another user.
*
* @param userID
* The fully qualified jabber ID (i.e. full JID) with resource of the user to
* send the file to.
* @return The send file object on which the negotiated transfer can be run.
* @exception IllegalArgumentException if userID is null or not a full JID
*/
public OutgoingFileTransfer createOutgoingFileTransfer(EntityFullJid userID) {
/**
* Creates an OutgoingFileTransfer to send a file to another user.
*
* @param userID
* The fully qualified jabber ID (i.e. full JID) with resource of the user to
* send the file to.
* @return The send file object on which the negotiated transfer can be run.
* @exception IllegalArgumentException if userID is null or not a full JID
*/
public OutgoingFileTransfer createOutgoingFileTransfer(EntityFullJid userID) {
// We need to create outgoing file transfers with a full JID since this method will later
// use XEP-0095 to negotiate the stream. This is done with IQ stanzas that need to be addressed to a full JID
// in order to reach an client entity.
@ -125,45 +125,45 @@ public final class FileTransferManager extends Manager {
throw new IllegalArgumentException("userID was null");
}
return new OutgoingFileTransfer(connection().getUser(), userID,
FileTransferNegotiator.getNextStreamID(),
fileTransferNegotiator);
}
/**
* When the file transfer request is acceptable, this method should be
* invoked. It will create an IncomingFileTransfer which allows the
* transmission of the file to procede.
*
* @param request
* The remote request that is being accepted.
* @return The IncomingFileTransfer which manages the download of the file
* from the transfer initiator.
*/
protected IncomingFileTransfer createIncomingFileTransfer(
FileTransferRequest request) {
if (request == null) {
throw new NullPointerException("RecieveRequest cannot be null");
}
IncomingFileTransfer transfer = new IncomingFileTransfer(request,
return new OutgoingFileTransfer(connection().getUser(), userID,
FileTransferNegotiator.getNextStreamID(),
fileTransferNegotiator);
transfer.setFileInfo(request.getFileName(), request.getFileSize());
}
return transfer;
}
/**
* When the file transfer request is acceptable, this method should be
* invoked. It will create an IncomingFileTransfer which allows the
* transmission of the file to procede.
*
* @param request
* The remote request that is being accepted.
* @return The IncomingFileTransfer which manages the download of the file
* from the transfer initiator.
*/
protected IncomingFileTransfer createIncomingFileTransfer(
FileTransferRequest request) {
if (request == null) {
throw new NullPointerException("RecieveRequest cannot be null");
}
/**
* Reject an incoming file transfer.
* <p>
* Specified in XEP-95 4.2 and 3.2 Example 8
* </p>
* @param request
* @throws NotConnectedException
* @throws InterruptedException
*/
protected void rejectIncomingFileTransfer(FileTransferRequest request) throws NotConnectedException, InterruptedException {
StreamInitiation initiation = request.getStreamInitiation();
IncomingFileTransfer transfer = new IncomingFileTransfer(request,
fileTransferNegotiator);
transfer.setFileInfo(request.getFileName(), request.getFileSize());
return transfer;
}
/**
* Reject an incoming file transfer.
* <p>
* Specified in XEP-95 4.2 and 3.2 Example 8
* </p>
* @param request
* @throws NotConnectedException
* @throws InterruptedException
*/
protected void rejectIncomingFileTransfer(FileTransferRequest request) throws NotConnectedException, InterruptedException {
StreamInitiation initiation = request.getStreamInitiation();
// Reject as specified in XEP-95 4.2. Note that this is not to be confused with the Socks 5
// Bytestream rejection as specified in XEP-65 5.3.1 Example 13, which says that
@ -172,5 +172,5 @@ public final class FileTransferManager extends Manager {
IQ rejection = IQ.createErrorResponse(initiation, XMPPError.getBuilder(
XMPPError.Condition.forbidden));
connection().sendStanza(rejection);
}
}
}

View file

@ -27,113 +27,113 @@ import org.jxmpp.jid.Jid;
*
*/
public class FileTransferRequest {
private final StreamInitiation streamInitiation;
private final StreamInitiation streamInitiation;
private final FileTransferManager manager;
private final FileTransferManager manager;
/**
* A recieve request is constructed from the Stream Initiation request
* received from the initator.
*
* @param manager
* The manager handling this file transfer
*
* @param si
* The Stream initiaton recieved from the initiator.
*/
public FileTransferRequest(FileTransferManager manager, StreamInitiation si) {
this.streamInitiation = si;
this.manager = manager;
}
/**
* A recieve request is constructed from the Stream Initiation request
* received from the initator.
*
* @param manager
* The manager handling this file transfer
*
* @param si
* The Stream initiaton recieved from the initiator.
*/
public FileTransferRequest(FileTransferManager manager, StreamInitiation si) {
this.streamInitiation = si;
this.manager = manager;
}
/**
* Returns the name of the file.
*
* @return Returns the name of the file.
*/
public String getFileName() {
return streamInitiation.getFile().getName();
}
/**
* Returns the name of the file.
*
* @return Returns the name of the file.
*/
public String getFileName() {
return streamInitiation.getFile().getName();
}
/**
* Returns the size in bytes of the file.
*
* @return Returns the size in bytes of the file.
*/
public long getFileSize() {
return streamInitiation.getFile().getSize();
}
/**
* Returns the size in bytes of the file.
*
* @return Returns the size in bytes of the file.
*/
public long getFileSize() {
return streamInitiation.getFile().getSize();
}
/**
* Returns the description of the file provided by the requestor.
*
* @return Returns the description of the file provided by the requestor.
*/
public String getDescription() {
return streamInitiation.getFile().getDesc();
}
/**
* Returns the description of the file provided by the requestor.
*
* @return Returns the description of the file provided by the requestor.
*/
public String getDescription() {
return streamInitiation.getFile().getDesc();
}
/**
* Returns the mime-type of the file.
*
* @return Returns the mime-type of the file.
*/
public String getMimeType() {
return streamInitiation.getMimeType();
}
/**
* Returns the mime-type of the file.
*
* @return Returns the mime-type of the file.
*/
public String getMimeType() {
return streamInitiation.getMimeType();
}
/**
* Returns the fully-qualified jabber ID of the user that requested this
* file transfer.
*
* @return Returns the fully-qualified jabber ID of the user that requested
* this file transfer.
*/
public Jid getRequestor() {
return streamInitiation.getFrom();
}
/**
* Returns the fully-qualified jabber ID of the user that requested this
* file transfer.
*
* @return Returns the fully-qualified jabber ID of the user that requested
* this file transfer.
*/
public Jid getRequestor() {
return streamInitiation.getFrom();
}
/**
* Returns the stream ID that uniquely identifies this file transfer.
*
* @return Returns the stream ID that uniquely identifies this file
* transfer.
*/
public String getStreamID() {
return streamInitiation.getSessionID();
}
/**
* Returns the stream ID that uniquely identifies this file transfer.
*
* @return Returns the stream ID that uniquely identifies this file
* transfer.
*/
public String getStreamID() {
return streamInitiation.getSessionID();
}
/**
* Returns the stream initiation stanza(/packet) that was sent by the requestor which
* contains the parameters of the file transfer being transfer and also the
* methods available to transfer the file.
*
* @return Returns the stream initiation stanza(/packet) that was sent by the
* requestor which contains the parameters of the file transfer
* being transfer and also the methods available to transfer the
* file.
*/
protected StreamInitiation getStreamInitiation() {
return streamInitiation;
}
/**
* Returns the stream initiation stanza(/packet) that was sent by the requestor which
* contains the parameters of the file transfer being transfer and also the
* methods available to transfer the file.
*
* @return Returns the stream initiation stanza(/packet) that was sent by the
* requestor which contains the parameters of the file transfer
* being transfer and also the methods available to transfer the
* file.
*/
protected StreamInitiation getStreamInitiation() {
return streamInitiation;
}
/**
* Accepts this file transfer and creates the incoming file transfer.
*
* @return Returns the <b><i>IncomingFileTransfer</b></i> on which the
* file transfer can be carried out.
*/
public IncomingFileTransfer accept() {
return manager.createIncomingFileTransfer(this);
}
/**
* Accepts this file transfer and creates the incoming file transfer.
*
* @return Returns the <b><i>IncomingFileTransfer</b></i> on which the
* file transfer can be carried out.
*/
public IncomingFileTransfer accept() {
return manager.createIncomingFileTransfer(this);
}
/**
* Rejects the file transfer request.
* @throws NotConnectedException
* @throws InterruptedException
*/
public void reject() throws NotConnectedException, InterruptedException {
manager.rejectIncomingFileTransfer(this);
}
/**
* Rejects the file transfer request.
* @throws NotConnectedException
* @throws InterruptedException
*/
public void reject() throws NotConnectedException, InterruptedException {
manager.rejectIncomingFileTransfer(this);
}
}

View file

@ -58,6 +58,7 @@ public class IBBTransferNegotiator extends StreamNegotiator {
this.manager = InBandBytestreamManager.getByteStreamManager(connection);
}
@Override
public OutputStream createOutgoingStream(String streamID, Jid initiator,
Jid target) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
InBandBytestreamSession session = this.manager.establishSession(target, streamID);
@ -65,6 +66,7 @@ public class IBBTransferNegotiator extends StreamNegotiator {
return session.getOutputStream();
}
@Override
public InputStream createIncomingStream(StreamInitiation initiation)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
/*
@ -87,10 +89,12 @@ public class IBBTransferNegotiator extends StreamNegotiator {
this.manager.ignoreBytestreamRequestOnce(streamID);
}
@Override
public String[] getNamespaces() {
return new String[] { DataPacketExtension.NAMESPACE };
}
@Override
InputStream negotiateIncomingStream(Stanza streamInitiation) throws NotConnectedException, InterruptedException {
// build In-Band Bytestream request
InBandBytestreamRequest request = new ByteStreamRequest(this.manager,

View file

@ -126,6 +126,7 @@ public class IncomingFileTransfer extends FileTransfer {
}
Thread transferThread = new Thread(new Runnable() {
@Override
public void run() {
try {
inputStream = negotiateStream();
@ -184,6 +185,7 @@ public class IncomingFileTransfer extends FileTransfer {
FutureTask<InputStream> streamNegotiatorTask = new FutureTask<InputStream>(
new Callable<InputStream>() {
@Override
public InputStream call() throws Exception {
return streamNegotiator
.createIncomingStream(recieveRequest.getStreamInitiation());
@ -220,6 +222,7 @@ public class IncomingFileTransfer extends FileTransfer {
return inputStream;
}
@Override
public void cancel() {
setStatus(Status.cancelled);
}

View file

@ -43,7 +43,7 @@ import org.jxmpp.jid.Jid;
public class OutgoingFileTransfer extends FileTransfer {
private static final Logger LOGGER = Logger.getLogger(OutgoingFileTransfer.class.getName());
private static int RESPONSE_TIMEOUT = 60 * 1000;
private static int RESPONSE_TIMEOUT = 60 * 1000;
private NegotiationProgress callback;
/**
@ -58,349 +58,353 @@ public class OutgoingFileTransfer extends FileTransfer {
return RESPONSE_TIMEOUT;
}
/**
* Sets the time in milliseconds after which the file transfer negotiation
* process will timeout if the other user has not responded.
*
* @param responseTimeout
* The timeout time in milliseconds.
*/
public static void setResponseTimeout(int responseTimeout) {
RESPONSE_TIMEOUT = responseTimeout;
}
/**
* Sets the time in milliseconds after which the file transfer negotiation
* process will timeout if the other user has not responded.
*
* @param responseTimeout
* The timeout time in milliseconds.
*/
public static void setResponseTimeout(int responseTimeout) {
RESPONSE_TIMEOUT = responseTimeout;
}
private OutputStream outputStream;
private OutputStream outputStream;
private Jid initiator;
private Jid initiator;
private Thread transferThread;
private Thread transferThread;
protected OutgoingFileTransfer(Jid initiator, Jid target,
String streamID, FileTransferNegotiator transferNegotiator) {
super(target, streamID, transferNegotiator);
this.initiator = initiator;
}
protected OutgoingFileTransfer(Jid initiator, Jid target,
String streamID, FileTransferNegotiator transferNegotiator) {
super(target, streamID, transferNegotiator);
this.initiator = initiator;
}
protected void setOutputStream(OutputStream stream) {
if (outputStream == null) {
this.outputStream = stream;
}
}
protected void setOutputStream(OutputStream stream) {
if (outputStream == null) {
this.outputStream = stream;
}
}
/**
* Returns the output stream connected to the peer to transfer the file. It
* is only available after it has been successfully negotiated by the
* {@link StreamNegotiator}.
*
* @return Returns the output stream connected to the peer to transfer the
* file.
*/
protected OutputStream getOutputStream() {
if (getStatus().equals(FileTransfer.Status.negotiated)) {
return outputStream;
} else {
return null;
}
}
/**
* Returns the output stream connected to the peer to transfer the file. It
* is only available after it has been successfully negotiated by the
* {@link StreamNegotiator}.
*
* @return Returns the output stream connected to the peer to transfer the
* file.
*/
protected OutputStream getOutputStream() {
if (getStatus().equals(FileTransfer.Status.negotiated)) {
return outputStream;
} else {
return null;
}
}
/**
* This method handles the negotiation of the file transfer and the stream,
* it only returns the created stream after the negotiation has been completed.
*
* @param fileName
* The name of the file that will be transmitted. It is
* preferable for this name to have an extension as it will be
* used to determine the type of file it is.
* @param fileSize
* The size in bytes of the file that will be transmitted.
* @param description
* A description of the file that will be transmitted.
* @return The OutputStream that is connected to the peer to transmit the
* file.
* @throws XMPPException
* Thrown if an error occurs during the file transfer
* negotiation process.
* @throws SmackException if there was no response from the server.
* @throws InterruptedException
*/
public synchronized OutputStream sendFile(String fileName, long fileSize,
String description) throws XMPPException, SmackException, InterruptedException {
if (isDone() || outputStream != null) {
throw new IllegalStateException(
"The negotation process has already"
+ " been attempted on this file transfer");
}
try {
setFileInfo(fileName, fileSize);
this.outputStream = negotiateStream(fileName, fileSize, description);
} catch (XMPPErrorException e) {
handleXMPPException(e);
throw e;
}
return outputStream;
}
/**
* This method handles the negotiation of the file transfer and the stream,
* it only returns the created stream after the negotiation has been completed.
*
* @param fileName
* The name of the file that will be transmitted. It is
* preferable for this name to have an extension as it will be
* used to determine the type of file it is.
* @param fileSize
* The size in bytes of the file that will be transmitted.
* @param description
* A description of the file that will be transmitted.
* @return The OutputStream that is connected to the peer to transmit the
* file.
* @throws XMPPException
* Thrown if an error occurs during the file transfer
* negotiation process.
* @throws SmackException if there was no response from the server.
* @throws InterruptedException
*/
public synchronized OutputStream sendFile(String fileName, long fileSize,
String description) throws XMPPException, SmackException, InterruptedException {
if (isDone() || outputStream != null) {
throw new IllegalStateException(
"The negotation process has already"
+ " been attempted on this file transfer");
}
try {
setFileInfo(fileName, fileSize);
this.outputStream = negotiateStream(fileName, fileSize, description);
} catch (XMPPErrorException e) {
handleXMPPException(e);
throw e;
}
return outputStream;
}
/**
* This methods handles the transfer and stream negotiation process. It
* returns immediately and its progress will be updated through the
* {@link NegotiationProgress} callback.
*
* @param fileName
* The name of the file that will be transmitted. It is
* preferable for this name to have an extension as it will be
* used to determine the type of file it is.
* @param fileSize
* The size in bytes of the file that will be transmitted.
* @param description
* A description of the file that will be transmitted.
* @param progress
* A callback to monitor the progress of the file transfer
* negotiation process and to retrieve the OutputStream when it
* is complete.
*/
public synchronized void sendFile(final String fileName,
final long fileSize, final String description,
final NegotiationProgress progress)
/**
* This methods handles the transfer and stream negotiation process. It
* returns immediately and its progress will be updated through the
* {@link NegotiationProgress} callback.
*
* @param fileName
* The name of the file that will be transmitted. It is
* preferable for this name to have an extension as it will be
* used to determine the type of file it is.
* @param fileSize
* The size in bytes of the file that will be transmitted.
* @param description
* A description of the file that will be transmitted.
* @param progress
* A callback to monitor the progress of the file transfer
* negotiation process and to retrieve the OutputStream when it
* is complete.
*/
public synchronized void sendFile(final String fileName,
final long fileSize, final String description,
final NegotiationProgress progress)
{
if(progress == null) {
throw new IllegalArgumentException("Callback progress cannot be null.");
}
checkTransferThread();
if (isDone() || outputStream != null) {
throw new IllegalStateException(
"The negotation process has already"
+ " been attempted for this file transfer");
}
if (isDone() || outputStream != null) {
throw new IllegalStateException(
"The negotation process has already"
+ " been attempted for this file transfer");
}
setFileInfo(fileName, fileSize);
this.callback = progress;
transferThread = new Thread(new Runnable() {
public void run() {
try {
OutgoingFileTransfer.this.outputStream = negotiateStream(
fileName, fileSize, description);
@Override
public void run() {
try {
OutgoingFileTransfer.this.outputStream = negotiateStream(
fileName, fileSize, description);
progress.outputStreamEstablished(OutgoingFileTransfer.this.outputStream);
}
catch (XMPPErrorException e) {
handleXMPPException(e);
}
handleXMPPException(e);
}
catch (Exception e) {
setException(e);
}
}
}, "File Transfer Negotiation " + streamID);
transferThread.start();
}
}
}, "File Transfer Negotiation " + streamID);
transferThread.start();
}
private void checkTransferThread() {
if (transferThread != null && transferThread.isAlive() || isDone()) {
throw new IllegalStateException(
"File transfer in progress or has already completed.");
}
}
private void checkTransferThread() {
if ((transferThread != null && transferThread.isAlive()) || isDone()) {
throw new IllegalStateException(
"File transfer in progress or has already completed.");
}
}
/**
* This method handles the stream negotiation process and transmits the file
* to the remote user. It returns immediately and the progress of the file
* transfer can be monitored through several methods:
*
* <UL>
* <LI>{@link FileTransfer#getStatus()}
* <LI>{@link FileTransfer#getProgress()}
* <LI>{@link FileTransfer#isDone()}
* </UL>
*
* This method handles the stream negotiation process and transmits the file
* to the remote user. It returns immediately and the progress of the file
* transfer can be monitored through several methods:
*
* <UL>
* <LI>{@link FileTransfer#getStatus()}
* <LI>{@link FileTransfer#getProgress()}
* <LI>{@link FileTransfer#isDone()}
* </UL>
*
* @param file the file to transfer to the remote entity.
* @param description a description for the file to transfer.
* @throws SmackException
* If there is an error during the negotiation process or the
* sending of the file.
*/
public synchronized void sendFile(final File file, final String description)
throws SmackException {
checkTransferThread();
if (file == null || !file.exists() || !file.canRead()) {
throw new IllegalArgumentException("Could not read file");
} else {
setFileInfo(file.getAbsolutePath(), file.getName(), file.length());
}
* @throws SmackException
* If there is an error during the negotiation process or the
* sending of the file.
*/
public synchronized void sendFile(final File file, final String description)
throws SmackException {
checkTransferThread();
if (file == null || !file.exists() || !file.canRead()) {
throw new IllegalArgumentException("Could not read file");
} else {
setFileInfo(file.getAbsolutePath(), file.getName(), file.length());
}
transferThread = new Thread(new Runnable() {
public void run() {
try {
outputStream = negotiateStream(file.getName(), file
.length(), description);
} catch (XMPPErrorException e) {
handleXMPPException(e);
return;
}
transferThread = new Thread(new Runnable() {
@Override
public void run() {
try {
outputStream = negotiateStream(file.getName(), file
.length(), description);
} catch (XMPPErrorException e) {
handleXMPPException(e);
return;
}
catch (Exception e) {
setException(e);
}
if (outputStream == null) {
return;
}
if (outputStream == null) {
return;
}
if (!updateStatus(Status.negotiated, Status.in_progress)) {
return;
}
return;
}
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
writeToStream(inputStream, outputStream);
} catch (FileNotFoundException e) {
setStatus(FileTransfer.Status.error);
setError(Error.bad_file);
setException(e);
} catch (IOException e) {
setStatus(FileTransfer.Status.error);
setException(e);
} finally {
if (inputStream != null) {
try {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
writeToStream(inputStream, outputStream);
} catch (FileNotFoundException e) {
setStatus(FileTransfer.Status.error);
setError(Error.bad_file);
setException(e);
} catch (IOException e) {
setStatus(FileTransfer.Status.error);
setException(e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Closing input stream", e);
}
}
}
try {
try {
outputStream.close();
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Closing output stream", e);
}
}
}
updateStatus(Status.in_progress, FileTransfer.Status.complete);
}
}
}, "File Transfer " + streamID);
transferThread.start();
}
}, "File Transfer " + streamID);
transferThread.start();
}
/**
* This method handles the stream negotiation process and transmits the file
* to the remote user. It returns immediately and the progress of the file
* transfer can be monitored through several methods:
*
* <UL>
* <LI>{@link FileTransfer#getStatus()}
* <LI>{@link FileTransfer#getProgress()}
* <LI>{@link FileTransfer#isDone()}
* </UL>
*
* This method handles the stream negotiation process and transmits the file
* to the remote user. It returns immediately and the progress of the file
* transfer can be monitored through several methods:
*
* <UL>
* <LI>{@link FileTransfer#getStatus()}
* <LI>{@link FileTransfer#getProgress()}
* <LI>{@link FileTransfer#isDone()}
* </UL>
*
* @param in the stream to transfer to the remote entity.
* @param fileName the name of the file that is transferred
* @param fileSize the size of the file that is transferred
* @param description a description for the file to transfer.
*/
public synchronized void sendStream(final InputStream in, final String fileName, final long fileSize, final String description){
checkTransferThread();
*/
public synchronized void sendStream(final InputStream in, final String fileName, final long fileSize, final String description){
checkTransferThread();
setFileInfo(fileName, fileSize);
transferThread = new Thread(new Runnable() {
public void run() {
setFileInfo(fileName, fileSize);
transferThread = new Thread(new Runnable() {
@Override
public void run() {
//Create packet filter
try {
outputStream = negotiateStream(fileName, fileSize, description);
} catch (XMPPErrorException e) {
handleXMPPException(e);
return;
}
outputStream = negotiateStream(fileName, fileSize, description);
} catch (XMPPErrorException e) {
handleXMPPException(e);
return;
}
catch (Exception e) {
setException(e);
}
if (outputStream == null) {
return;
}
if (outputStream == null) {
return;
}
if (!updateStatus(Status.negotiated, Status.in_progress)) {
return;
}
try {
writeToStream(in, outputStream);
} catch (IOException e) {
setStatus(FileTransfer.Status.error);
setException(e);
} finally {
try {
if (in != null) {
in.close();
}
return;
}
try {
writeToStream(in, outputStream);
} catch (IOException e) {
setStatus(FileTransfer.Status.error);
setException(e);
} finally {
try {
if (in != null) {
in.close();
}
outputStream.flush();
outputStream.close();
} catch (IOException e) {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
/* Do Nothing */
}
}
}
}
updateStatus(Status.in_progress, FileTransfer.Status.complete);
}
}
}, "File Transfer " + streamID);
transferThread.start();
}
}, "File Transfer " + streamID);
transferThread.start();
}
private void handleXMPPException(XMPPErrorException e) {
XMPPError error = e.getXMPPError();
if (error != null) {
switch (error.getCondition()) {
case forbidden:
setStatus(Status.refused);
return;
case bad_request:
setStatus(Status.error);
setError(Error.not_acceptable);
break;
private void handleXMPPException(XMPPErrorException e) {
XMPPError error = e.getXMPPError();
if (error != null) {
switch (error.getCondition()) {
case forbidden:
setStatus(Status.refused);
return;
case bad_request:
setStatus(Status.error);
setError(Error.not_acceptable);
break;
default:
setStatus(FileTransfer.Status.error);
}
}
setException(e);
}
}
/**
* Returns the amount of bytes that have been sent for the file transfer. Or
* -1 if the file transfer has not started.
* <p>
* Note: This method is only useful when the {@link #sendFile(File, String)}
* method is called, as it is the only method that actually transmits the
* file.
*
* @return Returns the amount of bytes that have been sent for the file
* transfer. Or -1 if the file transfer has not started.
*/
public long getBytesSent() {
return amountWritten;
}
/**
* Returns the amount of bytes that have been sent for the file transfer. Or
* -1 if the file transfer has not started.
* <p>
* Note: This method is only useful when the {@link #sendFile(File, String)}
* method is called, as it is the only method that actually transmits the
* file.
*
* @return Returns the amount of bytes that have been sent for the file
* transfer. Or -1 if the file transfer has not started.
*/
public long getBytesSent() {
return amountWritten;
}
private OutputStream negotiateStream(String fileName, long fileSize,
String description) throws SmackException, XMPPException, InterruptedException {
// Negotiate the file transfer profile
private OutputStream negotiateStream(String fileName, long fileSize,
String description) throws SmackException, XMPPException, InterruptedException {
// Negotiate the file transfer profile
if (!updateStatus(Status.initial, Status.negotiating_transfer)) {
throw new IllegalStateChangeException();
}
StreamNegotiator streamNegotiator = negotiator.negotiateOutgoingTransfer(
getPeer(), streamID, fileName, fileSize, description,
RESPONSE_TIMEOUT);
StreamNegotiator streamNegotiator = negotiator.negotiateOutgoingTransfer(
getPeer(), streamID, fileName, fileSize, description,
RESPONSE_TIMEOUT);
// Negotiate the stream
if (!updateStatus(Status.negotiating_transfer, Status.negotiating_stream)) {
throw new IllegalStateChangeException();
}
outputStream = streamNegotiator.createOutgoingStream(streamID,
outputStream = streamNegotiator.createOutgoingStream(streamID,
initiator, getPeer());
if (!updateStatus(Status.negotiating_stream, Status.negotiated)) {
throw new IllegalStateChangeException();
}
return outputStream;
}
}
return outputStream;
}
public void cancel() {
setStatus(Status.cancelled);
}
@Override
public void cancel() {
setStatus(Status.cancelled);
}
@Override
protected boolean updateStatus(Status oldStatus, Status newStatus) {
@ -429,30 +433,30 @@ public class OutgoingFileTransfer extends FileTransfer {
}
/**
* A callback class to retrieve the status of an outgoing transfer
* negotiation process.
*
* @author Alexander Wenckus
*
*/
public interface NegotiationProgress {
* A callback class to retrieve the status of an outgoing transfer
* negotiation process.
*
* @author Alexander Wenckus
*
*/
public interface NegotiationProgress {
/**
* Called when the status changes.
/**
* Called when the status changes.
*
* @param oldStatus the previous status of the file transfer.
* @param newStatus the new status of the file transfer.
*/
void statusUpdated(Status oldStatus, Status newStatus);
void statusUpdated(Status oldStatus, Status newStatus);
/**
* Once the negotiation process is completed the output stream can be
* retrieved.
/**
* Once the negotiation process is completed the output stream can be
* retrieved.
*
* @param stream the established stream which can be used to transfer the file to the remote
* entity
*/
void outputStreamEstablished(OutputStream stream);
*/
void outputStreamEstablished(OutputStream stream);
/**
* Called when an exception occurs during the negotiation progress.

View file

@ -34,6 +34,7 @@ public final class GeoLocationManager extends Manager {
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
getInstanceFor(connection);
}

View file

@ -108,6 +108,7 @@ public final class LastActivityManager extends Manager {
// Enable the LastActivity support on every established connection
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
LastActivityManager.getInstanceFor(connection);
}
@ -135,6 +136,7 @@ public final class LastActivityManager extends Manager {
// Listen to all the sent messages to reset the idle time on each one
connection.addPacketSendingListener(new StanzaListener() {
@Override
public void processStanza(Stanza packet) {
Presence presence = (Presence) packet;
Presence.Mode mode = presence.getMode();

View file

@ -66,6 +66,7 @@ public class DefaultPrivateData implements PrivateData {
*
* @return the XML element name of the stanza(/packet) extension.
*/
@Override
public String getElementName() {
return elementName;
}
@ -75,10 +76,12 @@ public class DefaultPrivateData implements PrivateData {
*
* @return the XML namespace of the stanza(/packet) extension.
*/
@Override
public String getNamespace() {
return namespace;
}
@Override
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append('<').append(elementName).append(" xmlns=\"").append(namespace).append("\">");

View file

@ -71,6 +71,6 @@ public class RegistrationProvider extends IQProvider<Registration> {
Registration registration = new Registration(instruction, fields);
registration.addExtensions(packetExtensions);
return registration;
}
}
}

View file

@ -71,6 +71,7 @@ public final class VersionManager extends Manager {
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
VersionManager.getInstanceFor(connection);
}

View file

@ -32,48 +32,63 @@ import org.jxmpp.jid.parts.Resourcepart;
*/
public class DefaultParticipantStatusListener implements ParticipantStatusListener {
@Override
public void joined(EntityFullJid participant) {
}
@Override
public void left(EntityFullJid participant) {
}
@Override
public void kicked(EntityFullJid participant, Jid actor, String reason) {
}
@Override
public void voiceGranted(EntityFullJid participant) {
}
@Override
public void voiceRevoked(EntityFullJid participant) {
}
@Override
public void banned(EntityFullJid participant, Jid actor, String reason) {
}
@Override
public void membershipGranted(EntityFullJid participant) {
}
@Override
public void membershipRevoked(EntityFullJid participant) {
}
@Override
public void moderatorGranted(EntityFullJid participant) {
}
@Override
public void moderatorRevoked(EntityFullJid participant) {
}
@Override
public void ownershipGranted(EntityFullJid participant) {
}
@Override
public void ownershipRevoked(EntityFullJid participant) {
}
@Override
public void adminGranted(EntityFullJid participant) {
}
@Override
public void adminRevoked(EntityFullJid participant) {
}
@Override
public void nicknameChanged(EntityFullJid participant, Resourcepart newNickname) {
}

View file

@ -30,42 +30,55 @@ import org.jxmpp.jid.Jid;
*/
public class DefaultUserStatusListener implements UserStatusListener {
@Override
public void kicked(Jid actor, String reason) {
}
@Override
public void voiceGranted() {
}
@Override
public void voiceRevoked() {
}
@Override
public void banned(Jid actor, String reason) {
}
@Override
public void membershipGranted() {
}
@Override
public void membershipRevoked() {
}
@Override
public void moderatorGranted() {
}
@Override
public void moderatorRevoked() {
}
@Override
public void ownershipGranted() {
}
@Override
public void ownershipRevoked() {
}
@Override
public void adminGranted() {
}
@Override
public void adminRevoked() {
}
@Override
public void roomDestroyed(MultiUserChat alternateMUC, String reason) {
}

View file

@ -20,7 +20,7 @@ package org.jivesoftware.smackx.muc;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.muc.packet.MUCUser;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.EntityJid;
/**
* A listener that is fired anytime an invitation to join a MUC room is received.
@ -43,7 +43,7 @@ public interface InvitationListener {
* @param message the message used by the inviter to send the invitation.
* @param invitation the raw invitation received with the message.
*/
public abstract void invitationReceived(XMPPConnection conn, MultiUserChat room, EntityFullJid inviter, String reason,
public abstract void invitationReceived(XMPPConnection conn, MultiUserChat room, EntityJid inviter, String reason,
String password, Message message, MUCUser.Invite invitation);
}

View file

@ -95,15 +95,16 @@ public final class MucEnterConfiguration {
/**
* Set the presence used to join the MUC room.
* <p>
* The 'to' value of the given presence will be overridden.
* The 'to' value of the given presence will be overridden and the given presence must be of type
* 'available', otherwise an {@link IllegalArgumentException} will be thrown.
* <p>
*
* @param presence
* @return a reference to this builder.
*/
public Builder withPresence(Presence presence) {
if (presence.getType() == Presence.Type.available) {
throw new IllegalArgumentException();
if (presence.getType() != Presence.Type.available) {
throw new IllegalArgumentException("Presence must be of type 'available'");
}
joinPresence = presence;

View file

@ -46,7 +46,7 @@ import org.jivesoftware.smack.filter.NotFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
import org.jivesoftware.smack.filter.StanzaTypeFilter;
import org.jivesoftware.smack.filter.ToFilter;
import org.jivesoftware.smack.filter.ToMatchesFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
@ -163,6 +163,7 @@ public class MultiUserChat {
// Create a listener for subject updates.
subjectListener = new StanzaListener() {
@Override
public void processStanza(Stanza packet) {
Message msg = (Message) packet;
EntityFullJid from = msg.getFrom().asEntityFullJidIfPossible();
@ -181,6 +182,7 @@ public class MultiUserChat {
// Create a listener for all presence updates.
presenceListener = new StanzaListener() {
@Override
public void processStanza(Stanza packet) {
Presence presence = (Presence) packet;
final EntityFullJid from = presence.getFrom().asEntityFullJidIfPossible();
@ -251,6 +253,7 @@ public class MultiUserChat {
// Listens for all messages that include a MUCUser extension and fire the invitation
// rejection listeners if the message includes an invitation rejection.
declinesListener = new StanzaListener() {
@Override
public void processStanza(Stanza packet) {
Message message = (Message) packet;
// Get the MUC User extension
@ -319,7 +322,7 @@ public class MultiUserChat {
connection.addSyncStanzaListener(subjectListener, new AndFilter(fromRoomFilter,
MessageWithSubjectFilter.INSTANCE, new NotFilter(MessageTypeFilter.ERROR)));
connection.addSyncStanzaListener(declinesListener, DECLINE_FILTER);
connection.addPacketInterceptor(presenceInterceptor, new AndFilter(new ToFilter(room),
connection.addPacketInterceptor(presenceInterceptor, new AndFilter(ToMatchesFilter.create(room),
StanzaTypeFilter.PRESENCE));
messageCollector = connection.createStanzaCollector(fromRoomGroupchatFilter);
@ -331,7 +334,7 @@ public class MultiUserChat {
try {
presence = connection.createStanzaCollectorAndSend(responseFilter, joinPresence).nextResultOrThrow(conf.getTimeout());
}
catch (InterruptedException | NoResponseException | XMPPErrorException e) {
catch (NotConnectedException | InterruptedException | NoResponseException | XMPPErrorException e) {
// Ensure that all callbacks are removed if there is an exception
removeConnectionCallbacks();
throw e;

View file

@ -1,6 +1,6 @@
/**
*
* Copyright © 2014-2016 Florian Schmaus
* Copyright © 2014-2017 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -55,7 +55,6 @@ import org.jivesoftware.smackx.muc.MultiUserChatException.NotAMucServiceExceptio
import org.jivesoftware.smackx.muc.packet.MUCInitialPresence;
import org.jivesoftware.smackx.muc.packet.MUCUser;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.parts.Resourcepart;
@ -83,6 +82,7 @@ public final class MultiUserChatManager extends Manager {
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(final XMPPConnection connection) {
// Set on every established connection that this client supports the Multi-User
// Chat protocol. This information will be used when another client tries to
@ -150,6 +150,7 @@ public final class MultiUserChatManager extends Manager {
// Listens for all messages that include a MUCUser extension and fire the invitation
// listeners if the message includes an invitation.
StanzaListener invitationPacketListener = new StanzaListener() {
@Override
public void processStanza(Stanza packet) {
final Message message = (Message) packet;
// Get the MUCUser extension
@ -165,7 +166,7 @@ public final class MultiUserChatManager extends Manager {
final MultiUserChat muc = getMultiUserChat(mucJid);
final XMPPConnection connection = connection();
final MUCUser.Invite invite = mucUser.getInvite();
final EntityFullJid from = invite.getFrom();
final EntityJid from = invite.getFrom();
final String reason = invite.getReason();
final String password = mucUser.getPassword();
for (final InvitationListener listener : invitationsListeners) {

View file

@ -110,6 +110,7 @@ public class Occupant {
return nick;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Occupant)) {
return false;
@ -118,6 +119,7 @@ public class Occupant {
return jid.equals(occupant.jid);
}
@Override
public int hashCode() {
int result;
result = affiliation.hashCode();

View file

@ -92,10 +92,12 @@ public class GroupChatInvitation implements ExtensionElement {
return roomAddress;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public String getNamespace() {
return NAMESPACE;
}

View file

@ -72,10 +72,12 @@ public class MUCInitialPresence implements ExtensionElement {
}
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public String getNamespace() {
return NAMESPACE;
}
@ -282,6 +284,7 @@ public class MUCInitialPresence implements ExtensionElement {
this.since = since;
}
@Override
public XmlStringBuilder toXML() {
XmlStringBuilder xml = new XmlStringBuilder(this);
xml.optIntAttribute("maxchars", getMaxChars());

View file

@ -158,6 +158,7 @@ public class MUCItem implements NamedElement {
return role;
}
@Override
public XmlStringBuilder toXML() {
XmlStringBuilder xml = new XmlStringBuilder(this);
xml.optAttribute("affiliation", getAffiliation());

View file

@ -29,6 +29,7 @@ import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.EntityJid;
/**
* Represents extended presence information about roles, affiliations, full JIDs,
@ -49,10 +50,12 @@ public class MUCUser implements ExtensionElement {
private String password;
private Destroy destroy;
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public String getNamespace() {
return NAMESPACE;
}
@ -247,7 +250,12 @@ public class MUCUser implements ExtensionElement {
public static final String ELEMENT ="invite";
private final String reason;
private final EntityFullJid from;
/**
* From XEP-0045 § 7.8.2: "… whose value is the bare JID, full JID, or occupant JID of the inviter …"
*/
private final EntityJid from;
private final EntityBareJid to;
public Invite(String reason, EntityFullJid from) {
@ -258,7 +266,7 @@ public class MUCUser implements ExtensionElement {
this(reason, null, to);
}
public Invite(String reason, EntityFullJid from, EntityBareJid to) {
public Invite(String reason, EntityJid from, EntityBareJid to) {
this.reason = reason;
this.from = from;
this.to = to;
@ -270,7 +278,7 @@ public class MUCUser implements ExtensionElement {
*
* @return the room's occupant that sent the invitation.
*/
public EntityFullJid getFrom() {
public EntityJid getFrom() {
return from;
}

View file

@ -24,7 +24,7 @@ import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smackx.muc.packet.MUCUser;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.EntityJid;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@ -86,7 +86,7 @@ public class MUCUserProvider extends ExtensionElementProvider<MUCUser> {
private static MUCUser.Invite parseInvite(XmlPullParser parser) throws XmlPullParserException, IOException {
String reason = null;
EntityBareJid to = ParserUtils.getBareJidAttribute(parser, "to");
EntityFullJid from = ParserUtils.getFullJidAttribute(parser, "from");
EntityJid from = ParserUtils.getEntityJidAttribute(parser, "from");
outerloop: while (true) {
int eventType = parser.next();

View file

@ -31,77 +31,80 @@ import org.xmlpull.v1.XmlPullParserException;
*/
public class Nick implements ExtensionElement {
public static final String NAMESPACE = "http://jabber.org/protocol/nick";
public static final String NAMESPACE = "http://jabber.org/protocol/nick";
public static final String ELEMENT_NAME = "nick";
public static final String ELEMENT_NAME = "nick";
private String name = null;
private String name = null;
public Nick(String name) {
this.name = name;
}
public Nick(String name) {
this.name = name;
}
/**
* The value of this nickname.
*
* @return the nickname
*/
public String getName() {
return name;
}
/**
* The value of this nickname.
*
* @return the nickname
*/
public String getName() {
return name;
}
/**
* Sets the value of this nickname.
*
* @param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* Sets the value of this nickname.
*
* @param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}
/*
* (non-Javadoc)
*
* @see org.jivesoftware.smack.packet.PacketExtension#getElementName()
*/
public String getElementName() {
return ELEMENT_NAME;
}
/*
* (non-Javadoc)
*
* @see org.jivesoftware.smack.packet.PacketExtension#getElementName()
*/
@Override
public String getElementName() {
return ELEMENT_NAME;
}
/*
* (non-Javadoc)
*
* @see org.jivesoftware.smack.packet.PacketExtension#getNamespace()
*/
public String getNamespace() {
return NAMESPACE;
}
/*
* (non-Javadoc)
*
* @see org.jivesoftware.smack.packet.PacketExtension#getNamespace()
*/
@Override
public String getNamespace() {
return NAMESPACE;
}
/*
* (non-Javadoc)
*
* @see org.jivesoftware.smack.packet.PacketExtension#toXML()
*/
public String toXML() {
final StringBuilder buf = new StringBuilder();
/*
* (non-Javadoc)
*
* @see org.jivesoftware.smack.packet.PacketExtension#toXML()
*/
@Override
public String toXML() {
final StringBuilder buf = new StringBuilder();
buf.append('<').append(ELEMENT_NAME).append(" xmlns=\"").append(
NAMESPACE).append("\">");
buf.append(getName());
buf.append("</").append(ELEMENT_NAME).append('>');
buf.append('<').append(ELEMENT_NAME).append(" xmlns=\"").append(
NAMESPACE).append("\">");
buf.append(getName());
buf.append("</").append(ELEMENT_NAME).append('>');
return buf.toString();
}
return buf.toString();
}
public static class Provider extends ExtensionElementProvider<Nick> {
public static class Provider extends ExtensionElementProvider<Nick> {
@Override
public Nick parse(XmlPullParser parser, int initialDepth)
throws XmlPullParserException, IOException {
final String name = parser.nextText();
final String name = parser.nextText();
return new Nick(name);
}
}
return new Nick(name);
}
}
}

View file

@ -152,6 +152,7 @@ public class OfflineMessageManager {
}
// Filter offline messages that were requested by this request
StanzaFilter messageFilter = new AndFilter(PACKET_FILTER, new StanzaFilter() {
@Override
public boolean accept(Stanza packet) {
OfflineMessageInfo info = (OfflineMessageInfo) packet.getExtension("offline",
namespace);

View file

@ -42,6 +42,7 @@ public class OfflineMessageInfo implements ExtensionElement {
*
* @return the XML element name of the stanza(/packet) extension.
*/
@Override
public String getElementName() {
return "offline";
}
@ -52,6 +53,7 @@ public class OfflineMessageInfo implements ExtensionElement {
*
* @return the XML namespace of the stanza(/packet) extension.
*/
@Override
public String getNamespace() {
return "http://jabber.org/protocol/offline";
}
@ -78,6 +80,7 @@ public class OfflineMessageInfo implements ExtensionElement {
this.node = node;
}
@Override
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append('<').append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(

View file

@ -91,6 +91,7 @@ public final class PEPManager extends Manager {
private PEPManager(XMPPConnection connection) {
super(connection);
StanzaListener packetListener = new StanzaListener() {
@Override
public void processStanza(Stanza stanza) {
Message message = (Message) stanza;
EventElement event = EventElement.from(stanza);

View file

@ -67,6 +67,7 @@ public final class PingManager extends Manager {
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
getInstanceFor(connection);
}
@ -402,6 +403,7 @@ public final class PingManager extends Manager {
}
private final Runnable pingServerRunnable = new Runnable() {
@Override
public void run() {
LOGGER.fine("ServerPingTask run()");
pingServerIfNecessary();

View file

@ -78,6 +78,7 @@ public final class PrivacyListManager extends Manager {
static {
// Create a new PrivacyListManager on every established connection.
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
getInstanceFor(connection);
}
@ -95,7 +96,7 @@ public final class PrivacyListManager extends Manager {
*
* @param connection the XMPP connection.
*/
private PrivacyListManager(XMPPConnection connection) {
private PrivacyListManager(XMPPConnection connection) {
super(connection);
connection.registerIQRequestHandler(new AbstractIqRequestHandler(Privacy.ELEMENT, Privacy.NAMESPACE,
@ -215,24 +216,24 @@ public final class PrivacyListManager extends Manager {
return plm;
}
/**
* Send the {@link Privacy} stanza(/packet) to the server in order to know some privacy content and then
* waits for the answer.
*
* @param requestPrivacy is the {@link Privacy} stanza(/packet) configured properly whose XML
/**
* Send the {@link Privacy} stanza(/packet) to the server in order to know some privacy content and then
* waits for the answer.
*
* @param requestPrivacy is the {@link Privacy} stanza(/packet) configured properly whose XML
* will be sent to the server.
* @return a new {@link Privacy} with the data received from the server.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
private Privacy getRequest(Privacy requestPrivacy) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request is a get iq type
requestPrivacy.setType(Privacy.Type.get);
* @return a new {@link Privacy} with the data received from the server.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
private Privacy getRequest(Privacy requestPrivacy) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request is a get iq type
requestPrivacy.setType(Privacy.Type.get);
return connection().createStanzaCollectorAndSend(requestPrivacy).nextResultOrThrow();
}
}
/**
* Send the {@link Privacy} stanza(/packet) to the server in order to modify the server privacy and waits
@ -253,22 +254,22 @@ public final class PrivacyListManager extends Manager {
return connection().createStanzaCollectorAndSend(requestPrivacy).nextResultOrThrow();
}
/**
* Answer a privacy containing the list structure without {@link PrivacyItem}.
*
* @return a Privacy with the list names.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
private Privacy getPrivacyWithListNames() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an empty privacy message
Privacy request = new Privacy();
/**
* Answer a privacy containing the list structure without {@link PrivacyItem}.
*
* @return a Privacy with the list names.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
private Privacy getPrivacyWithListNames() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an empty privacy message
Privacy request = new Privacy();
// Send the package to the server and get the answer
return getRequest(request);
}
// Send the package to the server and get the answer
return getRequest(request);
}
/**
* Answer the active privacy list. Returns <code>null</code> if there is no active list.
@ -386,20 +387,20 @@ public final class PrivacyListManager extends Manager {
return privacyAnswer.getPrivacyList(listName);
}
/**
* Answer the privacy list items under listName with the allowed and blocked permissions.
*
* @param listName the name of the list to get the allowed and blocked permissions.
* @return a privacy list under the list listName.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public PrivacyList getPrivacyList(String listName) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
/**
* Answer the privacy list items under listName with the allowed and blocked permissions.
*
* @param listName the name of the list to get the allowed and blocked permissions.
* @return a privacy list under the list listName.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public PrivacyList getPrivacyList(String listName) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
listName = StringUtils.requireNotNullOrEmpty(listName, "List name must not be null");
return new PrivacyList(false, false, listName, getPrivacyListItems(listName));
}
}
/**
* Answer every privacy list with the allowed and blocked permissions.
@ -423,87 +424,87 @@ public final class PrivacyListManager extends Manager {
return lists;
}
/**
* Set or change the active list to listName.
*
* @param listName the list name to set as the active one.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void setActiveListName(String listName) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an privacy message with an empty list
Privacy request = new Privacy();
request.setActiveName(listName);
/**
* Set or change the active list to listName.
*
* @param listName the list name to set as the active one.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void setActiveListName(String listName) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an privacy message with an empty list
Privacy request = new Privacy();
request.setActiveName(listName);
// Send the package to the server
setRequest(request);
}
// Send the package to the server
setRequest(request);
}
/**
* Client declines the use of active lists.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void declineActiveList() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an privacy message with an empty list
Privacy request = new Privacy();
request.setDeclineActiveList(true);
/**
* Client declines the use of active lists.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void declineActiveList() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an privacy message with an empty list
Privacy request = new Privacy();
request.setDeclineActiveList(true);
// Send the package to the server
setRequest(request);
}
// Send the package to the server
setRequest(request);
}
/**
* Set or change the default list to listName.
*
* @param listName the list name to set as the default one.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void setDefaultListName(String listName) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an privacy message with an empty list
Privacy request = new Privacy();
request.setDefaultName(listName);
/**
* Set or change the default list to listName.
*
* @param listName the list name to set as the default one.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void setDefaultListName(String listName) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an privacy message with an empty list
Privacy request = new Privacy();
request.setDefaultName(listName);
// Send the package to the server
setRequest(request);
}
// Send the package to the server
setRequest(request);
}
/**
* Client declines the use of default lists.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void declineDefaultList() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an privacy message with an empty list
Privacy request = new Privacy();
request.setDeclineDefaultList(true);
/**
* Client declines the use of default lists.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void declineDefaultList() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an privacy message with an empty list
Privacy request = new Privacy();
request.setDeclineDefaultList(true);
// Send the package to the server
setRequest(request);
}
// Send the package to the server
setRequest(request);
}
/**
* The client has created a new list. It send the new one to the server.
*
/**
* The client has created a new list. It send the new one to the server.
*
* @param listName the list that has changed its content.
* @param privacyItems a List with every privacy item in the list.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void createPrivacyList(String listName, List<PrivacyItem> privacyItems) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
updatePrivacyList(listName, privacyItems);
}
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void createPrivacyList(String listName, List<PrivacyItem> privacyItems) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
updatePrivacyList(listName, privacyItems);
}
/**
* The client has edited an existing list. It updates the server content with the resulting
@ -526,23 +527,23 @@ public final class PrivacyListManager extends Manager {
setRequest(request);
}
/**
* Remove a privacy list.
*
/**
* Remove a privacy list.
*
* @param listName the list that has changed its content.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void deletePrivacyList(String listName) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an privacy message with an empty list
Privacy request = new Privacy();
request.setPrivacyList(listName, new ArrayList<PrivacyItem>());
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void deletePrivacyList(String listName) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
// The request of the list is an privacy message with an empty list
Privacy request = new Privacy();
request.setPrivacyList(listName, new ArrayList<PrivacyItem>());
// Send the package to the server
setRequest(request);
}
// Send the package to the server
setRequest(request);
}
/**
* Adds a privacy list listener that will be notified of any new update in the user

View file

@ -45,17 +45,17 @@ public class Privacy extends IQ {
public static final String ELEMENT = QUERY_ELEMENT;
public static final String NAMESPACE = "jabber:iq:privacy";
/** declineActiveList is true when the user declines the use of the active list **/
private boolean declineActiveList=false;
/** activeName is the name associated with the active list set for the session **/
private String activeName;
/** declineDefaultList is true when the user declines the use of the default list **/
private boolean declineDefaultList=false;
/** defaultName is the name of the default list that applies to the user as a whole **/
private String defaultName;
/** itemLists holds the set of privacy items classified in lists. It is a map where the
* key is the name of the list and the value a collection with privacy items. **/
private Map<String, List<PrivacyItem>> itemLists = new HashMap<String, List<PrivacyItem>>();
/** declineActiveList is true when the user declines the use of the active list **/
private boolean declineActiveList=false;
/** activeName is the name associated with the active list set for the session **/
private String activeName;
/** declineDefaultList is true when the user declines the use of the default list **/
private boolean declineDefaultList=false;
/** defaultName is the name of the default list that applies to the user as a whole **/
private String defaultName;
/** itemLists holds the set of privacy items classified in lists. It is a map where the
* key is the name of the list and the value a collection with privacy items. **/
private Map<String, List<PrivacyItem>> itemLists = new HashMap<String, List<PrivacyItem>>();
public Privacy() {
super(ELEMENT, NAMESPACE);
@ -94,13 +94,13 @@ public class Privacy extends IQ {
public void deletePrivacyList(String listName) {
// Remove the list from the cache
// CHECKSTYLE:OFF
this.getItemLists().remove(listName);
this.getItemLists().remove(listName);
// CHECKSTYLE:ON
// Check if deleted list was the default list
if (this.getDefaultName() != null && listName.equals(this.getDefaultName())) {
// CHECKSTYLE:OFF
this.setDefaultName(null);
this.setDefaultName(null);
// CHECKSTYLE:ON
}
}
@ -114,9 +114,9 @@ public class Privacy extends IQ {
// Check if we have the default list
// CHECKSTYLE:OFF
if (this.getActiveName() == null) {
return null;
return null;
} else {
return this.getItemLists().get(this.getActiveName());
return this.getItemLists().get(this.getActiveName());
}
// CHECKSTYLE:ON
}
@ -130,9 +130,9 @@ public class Privacy extends IQ {
// Check if we have the default list
// CHECKSTYLE:OFF
if (this.getDefaultName() == null) {
return null;
return null;
} else {
return this.getItemLists().get(this.getDefaultName());
return this.getItemLists().get(this.getDefaultName());
}
// CHECKSTYLE:ON
}
@ -156,15 +156,15 @@ public class Privacy extends IQ {
*/
public PrivacyItem getItem(String listName, int order) {
// CHECKSTYLE:OFF
Iterator<PrivacyItem> values = getPrivacyList(listName).iterator();
PrivacyItem itemFound = null;
while (itemFound == null && values.hasNext()) {
PrivacyItem element = values.next();
if (element.getOrder() == order) {
itemFound = element;
}
}
return itemFound;
Iterator<PrivacyItem> values = getPrivacyList(listName).iterator();
PrivacyItem itemFound = null;
while (itemFound == null && values.hasNext()) {
PrivacyItem element = values.next();
if (element.getOrder() == order) {
itemFound = element;
}
}
return itemFound;
// CHECKSTYLE:ON
}
@ -180,7 +180,7 @@ public class Privacy extends IQ {
return true;
} else {
// CHECKSTYLE:OFF
return false;
return false;
// CHECKSTYLE:ON
}
}
@ -192,7 +192,7 @@ public class Privacy extends IQ {
*/
public void deleteList(String listName) {
// CHECKSTYLE:OFF
this.getItemLists().remove(listName);
this.getItemLists().remove(listName);
// CHECKSTYLE:ON
}
@ -203,9 +203,9 @@ public class Privacy extends IQ {
* @return the name of the active list.
*/
// CHECKSTYLE:OFF
public String getActiveName() {
return activeName;
}
public String getActiveName() {
return activeName;
}
// CHECKSTYLE:ON
/**
@ -215,9 +215,9 @@ public class Privacy extends IQ {
* @param activeName is the name of the active list.
*/
// CHECKSTYLE:OFF
public void setActiveName(String activeName) {
this.activeName = activeName;
}
public void setActiveName(String activeName) {
this.activeName = activeName;
}
// CHECKSTYLE:ON
/**
@ -228,9 +228,9 @@ public class Privacy extends IQ {
* @return the name of the default list.
*/
// CHECKSTYLE:OFF
public String getDefaultName() {
return defaultName;
}
public String getDefaultName() {
return defaultName;
}
// CHECKSTYLE:ON
/**
@ -243,9 +243,9 @@ public class Privacy extends IQ {
* @param defaultName is the name of the default list.
*/
// CHECKSTYLE:OFF
public void setDefaultName(String defaultName) {
this.defaultName = defaultName;
}
public void setDefaultName(String defaultName) {
this.defaultName = defaultName;
}
// CHECKSTYLE:ON
/**
@ -257,9 +257,9 @@ public class Privacy extends IQ {
* collection of privacy items.
*/
// CHECKSTYLE:OFF
public Map<String, List<PrivacyItem>> getItemLists() {
return itemLists;
}
public Map<String, List<PrivacyItem>> getItemLists() {
return itemLists;
}
// CHECKSTYLE:ON
/**
@ -268,9 +268,9 @@ public class Privacy extends IQ {
* @return the decline status of the list.
*/
// CHECKSTYLE:OFF
public boolean isDeclineActiveList() {
return declineActiveList;
}
public boolean isDeclineActiveList() {
return declineActiveList;
}
// CHECKSYTLE:ON
/**
@ -279,9 +279,9 @@ public class Privacy extends IQ {
* @param declineActiveList indicates if the receiver declines the use of an active list.
*/
// CHECKSTYLE:OFF
public void setDeclineActiveList(boolean declineActiveList) {
this.declineActiveList = declineActiveList;
}
public void setDeclineActiveList(boolean declineActiveList) {
this.declineActiveList = declineActiveList;
}
// CHECKSTYLE:ON
/**
@ -290,9 +290,9 @@ public class Privacy extends IQ {
* @return the decline status of the list.
*/
// CHECKSTYLE:OFF
public boolean isDeclineDefaultList() {
return declineDefaultList;
}
public boolean isDeclineDefaultList() {
return declineDefaultList;
}
// CHECKSTYLE:ON
/**
@ -301,18 +301,18 @@ public class Privacy extends IQ {
* @param declineDefaultList indicates if the receiver declines the use of a default list.
*/
// CHECKSTYLE:OFF
public void setDeclineDefaultList(boolean declineDefaultList) {
this.declineDefaultList = declineDefaultList;
}
public void setDeclineDefaultList(boolean declineDefaultList) {
this.declineDefaultList = declineDefaultList;
}
/**
/**
* Returns all the list names the user has defined to group restrictions.
*
* @return a Set with Strings containing every list names.
*/
public Set<String> getPrivacyListNames() {
return this.itemLists.keySet();
}
public Set<String> getPrivacyListNames() {
return this.itemLists.keySet();
}
// CHECKSTYLE:ON
@Override
@ -322,40 +322,40 @@ public class Privacy extends IQ {
// Add the active tag
if (this.isDeclineActiveList()) {
buf.append("<active/>");
buf.append("<active/>");
} else {
if (this.getActiveName() != null) {
if (this.getActiveName() != null) {
buf.append("<active name=\"").escape(getActiveName()).append("\"/>");
}
}
// Add the default tag
if (this.isDeclineDefaultList()) {
buf.append("<default/>");
buf.append("<default/>");
} else {
if (this.getDefaultName() != null) {
if (this.getDefaultName() != null) {
buf.append("<default name=\"").escape(getDefaultName()).append("\"/>");
}
}
}
// Add the list with their privacy items
for (Map.Entry<String, List<PrivacyItem>> entry : this.getItemLists().entrySet()) {
String listName = entry.getKey();
List<PrivacyItem> items = entry.getValue();
// Begin the list tag
if (items.isEmpty()) {
// Begin the list tag
if (items.isEmpty()) {
buf.append("<list name=\"").escape(listName).append("\"/>");
} else {
} else {
buf.append("<list name=\"").escape(listName).append("\">");
}
for (PrivacyItem item : items) {
// Append the item xml representation
buf.append(item.toXML());
}
// Close the list tag
if (!items.isEmpty()) {
buf.append("</list>");
}
}
}
for (PrivacyItem item : items) {
// Append the item xml representation
buf.append(item.toXML());
}
// Close the list tag
if (!items.isEmpty()) {
buf.append("</list>");
}
}
// CHECKSTYLE:ON
return buf;
}

View file

@ -47,20 +47,20 @@ public class PrivacyProvider extends IQProvider<Privacy> {
if (eventType == XmlPullParser.START_TAG) {
// CHECKSTYLE:OFF
if (parser.getName().equals("active")) {
String activeName = parser.getAttributeValue("", "name");
if (activeName == null) {
privacy.setDeclineActiveList(true);
} else {
privacy.setActiveName(activeName);
}
String activeName = parser.getAttributeValue("", "name");
if (activeName == null) {
privacy.setDeclineActiveList(true);
} else {
privacy.setActiveName(activeName);
}
}
else if (parser.getName().equals("default")) {
String defaultName = parser.getAttributeValue("", "name");
if (defaultName == null) {
privacy.setDeclineDefaultList(true);
} else {
privacy.setDefaultName(defaultName);
}
String defaultName = parser.getAttributeValue("", "name");
if (defaultName == null) {
privacy.setDeclineDefaultList(true);
} else {
privacy.setDefaultName(defaultName);
}
}
// CHECKSTYLE:ON
else if (parser.getName().equals("list")) {
@ -75,10 +75,10 @@ public class PrivacyProvider extends IQProvider<Privacy> {
}
return privacy;
}
}
// Parse the list complex type
private static void parseList(XmlPullParser parser, Privacy privacy) throws XmlPullParserException, IOException, SmackException {
// Parse the list complex type
private static void parseList(XmlPullParser parser, Privacy privacy) throws XmlPullParserException, IOException, SmackException {
boolean done = false;
String listName = parser.getAttributeValue("", "name");
ArrayList<PrivacyItem> items = new ArrayList<PrivacyItem>();
@ -87,7 +87,7 @@ public class PrivacyProvider extends IQProvider<Privacy> {
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("item")) {
// CHECKSTYLE:OFF
items.add(parseItem(parser));
items.add(parseItem(parser));
// CHECKSTYLE:ON
}
}
@ -100,10 +100,10 @@ public class PrivacyProvider extends IQProvider<Privacy> {
privacy.setPrivacyList(listName, items);
// CHECKSTYLE:OFF
}
}
// Parse the list complex type
private static PrivacyItem parseItem(XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
// Parse the list complex type
private static PrivacyItem parseItem(XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
// CHECKSTYLE:ON
// Retrieves the required attributes
String actionValue = parser.getAttributeValue("", "action");
@ -142,7 +142,7 @@ public class PrivacyProvider extends IQProvider<Privacy> {
parseItemChildElements(parser, item);
return item;
// CHECKSTYLE:OFF
}
}
// CHECKSTYLE:ON
private static void parseItemChildElements(XmlPullParser parser, PrivacyItem privacyItem) throws XmlPullParserException, IOException {

View file

@ -24,18 +24,18 @@ package org.jivesoftware.smackx.pubsub;
*/
public enum AccessModel
{
/** Anyone may subscribe and retrieve items. */
open,
/** Anyone may subscribe and retrieve items. */
open,
/** Subscription request must be approved and only subscribers may retrieve items. */
authorize,
/** Subscription request must be approved and only subscribers may retrieve items. */
authorize,
/** Anyone with a presence subscription of both or from may subscribe and retrieve items. */
presence,
/** Anyone with a presence subscription of both or from may subscribe and retrieve items. */
presence,
/** Anyone in the specified roster group(s) may subscribe and retrieve items. */
roster,
/** Anyone in the specified roster group(s) may subscribe and retrieve items. */
roster,
/** Only those on a whitelist may subscribe and retrieve items. */
whitelist;
/** Only those on a whitelist may subscribe and retrieve items. */
whitelist;
}

View file

@ -42,17 +42,17 @@ public class Affiliation implements ExtensionElement
private final Type affiliation;
private final PubSubNamespace namespace;
public enum Type
{
member, none, outcast, owner, publisher
}
public enum Type
{
member, none, outcast, owner, publisher
}
/**
* Constructs an affiliation.
*
* @param node The node the user is affiliated with.
* @param affiliation the optional affiliation.
*/
/**
* Constructs an affiliation.
*
* @param node The node the user is affiliated with.
* @param affiliation the optional affiliation.
*/
public Affiliation(String node, Type affiliation) {
this.node = StringUtils.requireNotNullOrEmpty(node, "node must not be null or empty");
this.affiliation = affiliation;
@ -122,6 +122,7 @@ public class Affiliation implements ExtensionElement
return ELEMENT;
}
@Override
public String getNamespace() {
return namespace.getXmlns();
}

View file

@ -30,8 +30,8 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
*/
public class AffiliationsExtension extends NodeExtension
{
protected List<Affiliation> items = Collections.emptyList();
private final String node;
protected List<Affiliation> items = Collections.emptyList();
private final String node;
public AffiliationsExtension() {
this(null, null);
@ -47,20 +47,20 @@ public class AffiliationsExtension extends NodeExtension
this.node = node;
}
public List<Affiliation> getAffiliations()
{
return items;
}
public List<Affiliation> getAffiliations()
{
return items;
}
@Override
public CharSequence toXML()
{
if ((items == null) || (items.size() == 0))
{
return super.toXML();
}
else
{
@Override
public CharSequence toXML()
{
if ((items == null) || (items.size() == 0))
{
return super.toXML();
}
else
{
// Can't use XmlStringBuilder(this), because we don't want the namespace to be included
XmlStringBuilder xml = new XmlStringBuilder();
xml.openElement(getElementName());
@ -69,6 +69,6 @@ public class AffiliationsExtension extends NodeExtension
xml.append(items);
xml.closeElement(this);
return xml;
}
}
}
}
}

View file

@ -24,12 +24,12 @@ package org.jivesoftware.smackx.pubsub;
*/
public enum ChildrenAssociationPolicy
{
/** Anyone may associate leaf nodes with the collection. */
all,
/** Anyone may associate leaf nodes with the collection. */
all,
/** Only collection node owners may associate leaf nodes with the collection. */
owners,
/** Only collection node owners may associate leaf nodes with the collection. */
owners,
/** Only those on a whitelist may associate leaf nodes with the collection. */
whitelist;
/** Only those on a whitelist may associate leaf nodes with the collection. */
whitelist;
}

View file

@ -18,9 +18,9 @@ package org.jivesoftware.smackx.pubsub;
public class CollectionNode extends Node
{
CollectionNode(PubSubManager pubSubManager, String nodeId)
{
super(pubSubManager, nodeId);
}
CollectionNode(PubSubManager pubSubManager, String nodeId)
{
super(pubSubManager, nodeId);
}
}

View file

@ -31,29 +31,30 @@ import org.jivesoftware.smack.packet.ExtensionElement;
*/
public class ConfigurationEvent extends NodeExtension implements EmbeddedPacketExtension
{
private ConfigureForm form;
private ConfigureForm form;
public ConfigurationEvent(String nodeId)
{
super(PubSubElementType.CONFIGURATION, nodeId);
}
public ConfigurationEvent(String nodeId)
{
super(PubSubElementType.CONFIGURATION, nodeId);
}
public ConfigurationEvent(String nodeId, ConfigureForm configForm)
{
super(PubSubElementType.CONFIGURATION, nodeId);
form = configForm;
}
public ConfigurationEvent(String nodeId, ConfigureForm configForm)
{
super(PubSubElementType.CONFIGURATION, nodeId);
form = configForm;
}
public ConfigureForm getConfiguration()
{
return form;
}
public ConfigureForm getConfiguration()
{
return form;
}
public List<ExtensionElement> getExtensions()
{
if (getConfiguration() == null)
return Collections.emptyList();
else
return Arrays.asList(((ExtensionElement)getConfiguration().getDataFormToSend()));
}
@Override
public List<ExtensionElement> getExtensions()
{
if (getConfiguration() == null)
return Collections.emptyList();
else
return Arrays.asList(((ExtensionElement)getConfiguration().getDataFormToSend()));
}
}

View file

@ -29,193 +29,193 @@ import org.jivesoftware.smackx.xdata.Form;
*/
public enum ConfigureNodeFields
{
/**
* Determines who may subscribe and retrieve items.
*
* <p><b>Value: {@link AccessModel}</b></p>
*/
access_model,
/**
* Determines who may subscribe and retrieve items.
*
* <p><b>Value: {@link AccessModel}</b></p>
*/
access_model,
/**
* The URL of an XSL transformation which can be applied to
* payloads in order to generate an appropriate message
* body element.
*
* <p><b>Value: {@link URL}</b></p>
*/
body_xslt,
/**
* The URL of an XSL transformation which can be applied to
* payloads in order to generate an appropriate message
* body element.
*
* <p><b>Value: {@link URL}</b></p>
*/
body_xslt,
/**
* The collection with which a node is affiliated.
*
* <p><b>Value: String</b></p>
*/
collection,
/**
* The collection with which a node is affiliated.
*
* <p><b>Value: String</b></p>
*/
collection,
/**
* The URL of an XSL transformation which can be applied to
* payload format in order to generate a valid Data Forms result
* that the client could display using a generic Data Forms
* rendering engine body element.
*
* <p><b>Value: {@link URL}</b></p>
*/
dataform_xslt,
/**
* The URL of an XSL transformation which can be applied to
* payload format in order to generate a valid Data Forms result
* that the client could display using a generic Data Forms
* rendering engine body element.
*
* <p><b>Value: {@link URL}</b></p>
*/
dataform_xslt,
/**
* Whether to deliver payloads with event notifications.
*
* <p><b>Value: boolean</b></p>
*/
deliver_payloads,
/**
* Whether to deliver payloads with event notifications.
*
* <p><b>Value: boolean</b></p>
*/
deliver_payloads,
/**
* Whether owners or publisher should receive replies to items.
*
* <p><b>Value: {@link ItemReply}</b></p>
*/
itemreply,
/**
* Whether owners or publisher should receive replies to items.
*
* <p><b>Value: {@link ItemReply}</b></p>
*/
itemreply,
/**
* Who may associate leaf nodes with a collection.
*
* <p><b>Value: {@link ChildrenAssociationPolicy}</b></p>
*/
children_association_policy,
/**
* Who may associate leaf nodes with a collection.
*
* <p><b>Value: {@link ChildrenAssociationPolicy}</b></p>
*/
children_association_policy,
/**
* The list of JIDs that may associate leaf nodes with a
* collection.
*
* <p><b>Value: List of JIDs as Strings</b></p>
*/
children_association_whitelist,
/**
* The list of JIDs that may associate leaf nodes with a
* collection.
*
* <p><b>Value: List of JIDs as Strings</b></p>
*/
children_association_whitelist,
/**
* The child nodes (leaf or collection) associated with a collection.
*
* <p><b>Value: List of Strings</b></p>
*/
children,
/**
* The child nodes (leaf or collection) associated with a collection.
*
* <p><b>Value: List of Strings</b></p>
*/
children,
/**
* The maximum number of child nodes that can be associated with a
* collection.
*
* <p><b>Value: int</b></p>
*/
children_max,
/**
* The maximum number of child nodes that can be associated with a
* collection.
*
* <p><b>Value: int</b></p>
*/
children_max,
/**
* The maximum number of items to persist.
*
* <p><b>Value: int</b></p>
*/
max_items,
/**
* The maximum number of items to persist.
*
* <p><b>Value: int</b></p>
*/
max_items,
/**
* The maximum payload size in bytes.
*
* <p><b>Value: int</b></p>
*/
max_payload_size,
/**
* The maximum payload size in bytes.
*
* <p><b>Value: int</b></p>
*/
max_payload_size,
/**
* Whether the node is a leaf (default) or collection.
*
* <p><b>Value: {@link NodeType}</b></p>
*/
node_type,
/**
* Whether the node is a leaf (default) or collection.
*
* <p><b>Value: {@link NodeType}</b></p>
*/
node_type,
/**
* Whether to notify subscribers when the node configuration changes.
*
* <p><b>Value: boolean</b></p>
*/
notify_config,
/**
* Whether to notify subscribers when the node configuration changes.
*
* <p><b>Value: boolean</b></p>
*/
notify_config,
/**
* Whether to notify subscribers when the node is deleted.
*
* <p><b>Value: boolean</b></p>
*/
notify_delete,
/**
* Whether to notify subscribers when the node is deleted.
*
* <p><b>Value: boolean</b></p>
*/
notify_delete,
/**
* Whether to notify subscribers when items are removed from the node.
*
* <p><b>Value: boolean</b></p>
*/
notify_retract,
/**
* Whether to notify subscribers when items are removed from the node.
*
* <p><b>Value: boolean</b></p>
*/
notify_retract,
/**
* Whether to persist items to storage. This is required to have. multiple
* items in the node.
*
* <p><b>Value: boolean</b></p>
*/
persist_items,
/**
* Whether to persist items to storage. This is required to have. multiple
* items in the node.
*
* <p><b>Value: boolean</b></p>
*/
persist_items,
/**
* Whether to deliver notifications to available users only.
*
* <p><b>Value: boolean</b></p>
*/
presence_based_delivery,
/**
* Whether to deliver notifications to available users only.
*
* <p><b>Value: boolean</b></p>
*/
presence_based_delivery,
/**
* Defines who can publish to the node.
*
* <p><b>Value: {@link PublishModel}</b></p>
*/
publish_model,
/**
* Defines who can publish to the node.
*
* <p><b>Value: {@link PublishModel}</b></p>
*/
publish_model,
/**
* The specific multi-user chat rooms to specify for replyroom.
*
* <p><b>Value: List of JIDs as Strings</b></p>
*/
replyroom,
/**
* The specific multi-user chat rooms to specify for replyroom.
*
* <p><b>Value: List of JIDs as Strings</b></p>
*/
replyroom,
/**
* The specific JID(s) to specify for replyto.
*
* <p><b>Value: List of JIDs as Strings</b></p>
*/
replyto,
/**
* The specific JID(s) to specify for replyto.
*
* <p><b>Value: List of JIDs as Strings</b></p>
*/
replyto,
/**
* The roster group(s) allowed to subscribe and retrieve items.
*
* <p><b>Value: List of strings</b></p>
*/
roster_groups_allowed,
/**
* The roster group(s) allowed to subscribe and retrieve items.
*
* <p><b>Value: List of strings</b></p>
*/
roster_groups_allowed,
/**
* Whether to allow subscriptions.
*
* <p><b>Value: boolean</b></p>
*/
subscribe,
/**
* Whether to allow subscriptions.
*
* <p><b>Value: boolean</b></p>
*/
subscribe,
/**
* A friendly name for the node.
*
* <p><b>Value: String</b></p>
*/
title,
/**
* A friendly name for the node.
*
* <p><b>Value: String</b></p>
*/
title,
/**
* The type of node data, ussually specified by the namespace
* of the payload(if any);MAY be a list-single rather than a
* text single.
*
* <p><b>Value: String</b></p>
*/
type;
/**
* The type of node data, ussually specified by the namespace
* of the payload(if any);MAY be a list-single rather than a
* text single.
*
* <p><b>Value: String</b></p>
*/
type;
public String getFieldName()
{
return "pubsub#" + toString();
}
public String getFieldName()
{
return "pubsub#" + toString();
}
}

View file

@ -39,10 +39,10 @@ import org.jivesoftware.smack.util.PacketParserUtils;
*/
public interface EmbeddedPacketExtension extends ExtensionElement
{
/**
* Get the list of embedded {@link ExtensionElement} objects.
*
* @return List of embedded {@link ExtensionElement}
*/
List<ExtensionElement> getExtensions();
/**
* Get the list of embedded {@link ExtensionElement} objects.
*
* @return List of embedded {@link ExtensionElement}
*/
List<ExtensionElement> getExtensions();
}

View file

@ -44,39 +44,42 @@ public class EventElement implements EmbeddedPacketExtension
*/
public static final String NAMESPACE = PubSubNamespace.EVENT.getXmlns();
private EventElementType type;
private NodeExtension ext;
private EventElementType type;
private NodeExtension ext;
public EventElement(EventElementType eventType, NodeExtension eventExt)
{
type = eventType;
ext = eventExt;
}
public EventElement(EventElementType eventType, NodeExtension eventExt)
{
type = eventType;
ext = eventExt;
}
public EventElementType getEventType()
{
return type;
}
public EventElementType getEventType()
{
return type;
}
public List<ExtensionElement> getExtensions()
{
return Arrays.asList(new ExtensionElement[]{getEvent()});
}
@Override
public List<ExtensionElement> getExtensions()
{
return Arrays.asList(new ExtensionElement[]{getEvent()});
}
public NodeExtension getEvent()
{
return ext;
}
public NodeExtension getEvent()
{
return ext;
}
public String getElementName()
{
return "event";
}
@Override
public String getElementName()
{
return "event";
}
public String getNamespace()
{
return PubSubNamespace.EVENT.getXmlns();
}
@Override
public String getNamespace()
{
return PubSubNamespace.EVENT.getXmlns();
}
@Override
public XmlStringBuilder toXML() {

View file

@ -24,21 +24,21 @@ package org.jivesoftware.smackx.pubsub;
*/
public enum EventElementType
{
/** A node has been associated or dissassociated with a collection node. */
collection,
/** A node has been associated or dissassociated with a collection node. */
collection,
/** A node has had its configuration changed. */
configuration,
/** A node has had its configuration changed. */
configuration,
/** A node has been deleted. */
delete,
/** A node has been deleted. */
delete,
/** Items have been published to a node. */
items,
/** Items have been published to a node. */
items,
/** All items have been purged from a node. */
purge,
/** All items have been purged from a node. */
purge,
/** A node has been subscribed to. */
subscription
/** A node has been subscribed to. */
subscription
}

View file

@ -28,75 +28,75 @@ import org.jivesoftware.smackx.xdata.Form;
*/
public class FormNode extends NodeExtension
{
private Form configForm;
private Form configForm;
/**
* Create a {@link FormNode} which contains the specified form.
*
* @param formType The type of form being sent
* @param submitForm The form
*/
public FormNode(FormNodeType formType, Form submitForm)
{
super(formType.getNodeElement());
/**
* Create a {@link FormNode} which contains the specified form.
*
* @param formType The type of form being sent
* @param submitForm The form
*/
public FormNode(FormNodeType formType, Form submitForm)
{
super(formType.getNodeElement());
if (submitForm == null)
throw new IllegalArgumentException("Submit form cannot be null");
configForm = submitForm;
}
if (submitForm == null)
throw new IllegalArgumentException("Submit form cannot be null");
configForm = submitForm;
}
/**
* Create a {@link FormNode} which contains the specified form, which is
* associated with the specified node.
*
* @param formType The type of form being sent
* @param nodeId The node the form is associated with
* @param submitForm The form
*/
public FormNode(FormNodeType formType, String nodeId, Form submitForm)
{
super(formType.getNodeElement(), nodeId);
/**
* Create a {@link FormNode} which contains the specified form, which is
* associated with the specified node.
*
* @param formType The type of form being sent
* @param nodeId The node the form is associated with
* @param submitForm The form
*/
public FormNode(FormNodeType formType, String nodeId, Form submitForm)
{
super(formType.getNodeElement(), nodeId);
if (submitForm == null)
throw new IllegalArgumentException("Submit form cannot be null");
configForm = submitForm;
}
if (submitForm == null)
throw new IllegalArgumentException("Submit form cannot be null");
configForm = submitForm;
}
/**
* Get the Form that is to be sent, or was retrieved from the server.
*
* @return The form
*/
public Form getForm()
{
return configForm;
}
/**
* Get the Form that is to be sent, or was retrieved from the server.
*
* @return The form
*/
public Form getForm()
{
return configForm;
}
@Override
public CharSequence toXML()
{
if (configForm == null)
{
return super.toXML();
}
else
{
StringBuilder builder = new StringBuilder("<");
builder.append(getElementName());
@Override
public CharSequence toXML()
{
if (configForm == null)
{
return super.toXML();
}
else
{
StringBuilder builder = new StringBuilder("<");
builder.append(getElementName());
if (getNode() != null)
{
builder.append(" node='");
builder.append(getNode());
builder.append("'>");
}
else
builder.append('>');
builder.append(configForm.getDataFormToSend().toXML());
builder.append("</");
builder.append(getElementName() + '>');
return builder.toString();
}
}
if (getNode() != null)
{
builder.append(" node='");
builder.append(getNode());
builder.append("'>");
}
else
builder.append('>');
builder.append(configForm.getDataFormToSend().toXML());
builder.append("</");
builder.append(getElementName() + '>');
return builder.toString();
}
}
}

View file

@ -27,29 +27,29 @@ import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
*/
public enum FormNodeType
{
/** Form for configuring an existing node. */
CONFIGURE_OWNER,
/** Form for configuring an existing node. */
CONFIGURE_OWNER,
/** Form for configuring a node during creation. */
CONFIGURE,
/** Form for configuring a node during creation. */
CONFIGURE,
/** Form for configuring subscription options. */
OPTIONS,
/** Form for configuring subscription options. */
OPTIONS,
/** Form which represents the default node configuration options. */
DEFAULT;
/** Form which represents the default node configuration options. */
DEFAULT;
public PubSubElementType getNodeElement()
{
return PubSubElementType.valueOf(toString());
}
public PubSubElementType getNodeElement()
{
return PubSubElementType.valueOf(toString());
}
public static FormNodeType valueOfFromElementName(String elem, String configNamespace)
{
if ("configure".equals(elem) && PubSubNamespace.OWNER.getXmlns().equals(configNamespace))
{
return CONFIGURE_OWNER;
}
return valueOf(elem.toUpperCase(Locale.US));
}
public static FormNodeType valueOfFromElementName(String elem, String configNamespace)
{
if ("configure".equals(elem) && PubSubNamespace.OWNER.getXmlns().equals(configNamespace))
{
return CONFIGURE_OWNER;
}
return valueOf(elem.toUpperCase(Locale.US));
}
}

View file

@ -25,42 +25,42 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
*/
public class GetItemsRequest extends NodeExtension
{
protected final String subId;
protected final int maxItems;
protected final String subId;
protected final int maxItems;
public GetItemsRequest(String nodeId)
{
this(nodeId, null, -1);
}
public GetItemsRequest(String nodeId)
{
this(nodeId, null, -1);
}
public GetItemsRequest(String nodeId, String subscriptionId)
{
public GetItemsRequest(String nodeId, String subscriptionId)
{
this(nodeId, subscriptionId, -1);
}
}
public GetItemsRequest(String nodeId, int maxItemsToReturn)
{
public GetItemsRequest(String nodeId, int maxItemsToReturn)
{
this(nodeId, null, maxItemsToReturn);
}
}
public GetItemsRequest(String nodeId, String subscriptionId, int maxItemsToReturn)
{
public GetItemsRequest(String nodeId, String subscriptionId, int maxItemsToReturn)
{
super(PubSubElementType.ITEMS, nodeId);
maxItems = maxItemsToReturn;
subId = subscriptionId;
}
subId = subscriptionId;
}
public String getSubscriptionId()
{
return subId;
}
public String getSubscriptionId()
{
return subId;
}
public int getMaxItems()
{
return maxItems;
}
public int getMaxItems()
{
return maxItems;
}
@Override
@Override
public XmlStringBuilder toXML() {
XmlStringBuilder xml = new XmlStringBuilder();
xml.halfOpenElement(getElementName());

View file

@ -50,94 +50,92 @@ import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
*/
public class Item extends NodeExtension
{
private String id;
private String id;
/**
* Create an empty <tt>Item</tt> with no id. This is a valid item for nodes which are configured
* so that {@link ConfigureForm#isDeliverPayloads()} is false. In most cases an id will be generated by the server.
* For nodes configured with {@link ConfigureForm#isDeliverPayloads()} and {@link ConfigureForm#isPersistItems()}
* set to false, no <tt>Item</tt> is sent to the node, you have to use {@link LeafNode#send()} or {@link LeafNode#publish()}
* methods in this case.
*/
public Item()
{
super(PubSubElementType.ITEM);
}
/**
* Create an <tt>Item</tt> with an id but no payload. This is a valid item for nodes which are configured
* so that {@link ConfigureForm#isDeliverPayloads()} is false.
*
* @param itemId The id if the item. It must be unique within the node unless overwriting and existing item.
* Passing null is the equivalent of calling {@link #Item()}.
*/
public Item(String itemId)
{
// The element type is actually irrelevant since we override getNamespace() to return null
super(PubSubElementType.ITEM);
id = itemId;
}
/**
* Create an <tt>Item</tt> with an id and a node id.
* <p>
* <b>Note:</b> This is not valid for publishing an item to a node, only receiving from
* one as part of {@link Message}. If used to create an Item to publish
* (via {@link LeafNode#publish(Item)}, the server <i>may</i> return an
* error for an invalid packet.
*
* @param itemId The id of the item.
* @param nodeId The id of the node which the item was published to.
*/
public Item(String itemId, String nodeId)
/**
* Create an empty <tt>Item</tt> with no id. This is a valid item for nodes which are configured
* so that {@link ConfigureForm#isDeliverPayloads()} is false. In most cases an id will be generated by the server.
* For nodes configured with {@link ConfigureForm#isDeliverPayloads()} and {@link ConfigureForm#isPersistItems()}
* set to false, no <tt>Item</tt> is sent to the node, you have to use {@link LeafNode#send()} or {@link LeafNode#publish()}
* methods in this case.
*/
public Item()
{
// CHECKSTYLE:OFF
super(PubSubElementType.ITEM_EVENT, nodeId);
// CHECKSTYLE:ON
super(PubSubElementType.ITEM);
}
/**
* Create an <tt>Item</tt> with an id but no payload. This is a valid item for nodes which are configured
* so that {@link ConfigureForm#isDeliverPayloads()} is false.
*
* @param itemId The id if the item. It must be unique within the node unless overwriting and existing item.
* Passing null is the equivalent of calling {@link #Item()}.
*/
public Item(String itemId)
{
// The element type is actually irrelevant since we override getNamespace() to return null
super(PubSubElementType.ITEM);
id = itemId;
}
/**
* Get the item id. Unique to the node it is associated with.
*
* @return The id
*/
public String getId()
{
return id;
}
/**
* Create an <tt>Item</tt> with an id and a node id.
* <p>
* <b>Note:</b> This is not valid for publishing an item to a node, only receiving from
* one as part of {@link Message}. If used to create an Item to publish
* (via {@link LeafNode#publish(Item)}, the server <i>may</i> return an
* error for an invalid packet.
*
* @param itemId The id of the item.
* @param nodeId The id of the node which the item was published to.
*/
public Item(String itemId, String nodeId)
{
super(PubSubElementType.ITEM_EVENT, nodeId);
id = itemId;
}
@Override
public String getNamespace()
{
return null;
}
/**
* Get the item id. Unique to the node it is associated with.
*
* @return The id
*/
public String getId()
{
return id;
}
@Override
public String toXML()
{
StringBuilder builder = new StringBuilder("<item");
@Override
public String getNamespace()
{
return null;
}
if (id != null)
{
builder.append(" id='");
builder.append(id);
builder.append('\'');
}
@Override
public String toXML()
{
StringBuilder builder = new StringBuilder("<item");
if (id != null)
{
builder.append(" id='");
builder.append(id);
builder.append('\'');
}
if (getNode() != null) {
builder.append(" node='");
builder.append(getNode());
builder.append('\'');
}
builder.append("/>");
builder.append("/>");
return builder.toString();
}
return builder.toString();
}
@Override
public String toString()
{
return getClass().getName() + " | Content [" + toXML() + "]";
}
@Override
public String toString()
{
return getClass().getName() + " | Content [" + toXML() + "]";
}
}

View file

@ -26,40 +26,40 @@ import java.util.List;
*/
public class ItemDeleteEvent extends SubscriptionEvent
{
private List<String> itemIds = Collections.emptyList();
private List<String> itemIds = Collections.emptyList();
/**
* Constructs an <tt>ItemDeleteEvent</tt> that indicates the the supplied
* items (by id) have been deleted, and that the event matches the listed
* subscriptions. The subscriptions would have been created by calling
* {@link LeafNode#subscribe(String)}.
*
* @param nodeId The id of the node the event came from
* @param deletedItemIds The item ids of the items that were deleted.
* @param subscriptionIds The subscriptions that match the event.
*/
public ItemDeleteEvent(String nodeId, List<String> deletedItemIds, List<String> subscriptionIds)
{
super(nodeId, subscriptionIds);
/**
* Constructs an <tt>ItemDeleteEvent</tt> that indicates the the supplied
* items (by id) have been deleted, and that the event matches the listed
* subscriptions. The subscriptions would have been created by calling
* {@link LeafNode#subscribe(String)}.
*
* @param nodeId The id of the node the event came from
* @param deletedItemIds The item ids of the items that were deleted.
* @param subscriptionIds The subscriptions that match the event.
*/
public ItemDeleteEvent(String nodeId, List<String> deletedItemIds, List<String> subscriptionIds)
{
super(nodeId, subscriptionIds);
if (deletedItemIds == null)
throw new IllegalArgumentException("deletedItemIds cannot be null");
itemIds = deletedItemIds;
}
if (deletedItemIds == null)
throw new IllegalArgumentException("deletedItemIds cannot be null");
itemIds = deletedItemIds;
}
/**
* Get the item id's of the items that have been deleted.
*
* @return List of item id's
*/
public List<String> getItemIds()
{
return Collections.unmodifiableList(itemIds);
}
/**
* Get the item id's of the items that have been deleted.
*
* @return List of item id's
*/
public List<String> getItemIds()
{
return Collections.unmodifiableList(itemIds);
}
@Override
public String toString()
{
return getClass().getName() + " [subscriptions: " + getSubscriptions() + "], [Deleted Items: " + itemIds + ']';
}
@Override
public String toString()
{
return getClass().getName() + " [subscriptions: " + getSubscriptions() + "], [Deleted Items: " + itemIds + ']';
}
}

View file

@ -27,98 +27,98 @@ import java.util.List;
*/
public class ItemPublishEvent<T extends Item> extends SubscriptionEvent
{
private List<T> items;
private Date originalDate;
private List<T> items;
private Date originalDate;
/**
* Constructs an <tt>ItemPublishEvent</tt> with the provided list
* of {@link Item} that were published.
*
* @param nodeId The id of the node the event came from
* @param eventItems The list of {@link Item} that were published
*/
public ItemPublishEvent(String nodeId, List<T> eventItems)
{
super(nodeId);
items = eventItems;
}
/**
* Constructs an <tt>ItemPublishEvent</tt> with the provided list
* of {@link Item} that were published.
*
* @param nodeId The id of the node the event came from
* @param eventItems The list of {@link Item} that were published
*/
public ItemPublishEvent(String nodeId, List<T> eventItems)
{
super(nodeId);
items = eventItems;
}
/**
* Constructs an <tt>ItemPublishEvent</tt> with the provided list
* of {@link Item} that were published. The list of subscription ids
* represents the subscriptions that matched the event, in the case
* of the user having multiple subscriptions.
*
* @param nodeId The id of the node the event came from
* @param eventItems The list of {@link Item} that were published
* @param subscriptionIds The list of subscriptionIds
*/
public ItemPublishEvent(String nodeId, List<T> eventItems, List<String> subscriptionIds)
{
super(nodeId, subscriptionIds);
items = eventItems;
}
/**
* Constructs an <tt>ItemPublishEvent</tt> with the provided list
* of {@link Item} that were published. The list of subscription ids
* represents the subscriptions that matched the event, in the case
* of the user having multiple subscriptions.
*
* @param nodeId The id of the node the event came from
* @param eventItems The list of {@link Item} that were published
* @param subscriptionIds The list of subscriptionIds
*/
public ItemPublishEvent(String nodeId, List<T> eventItems, List<String> subscriptionIds)
{
super(nodeId, subscriptionIds);
items = eventItems;
}
/**
* Constructs an <tt>ItemPublishEvent</tt> with the provided list
* of {@link Item} that were published in the past. The published
* date signifies that this is delayed event. The list of subscription ids
* represents the subscriptions that matched the event, in the case
* of the user having multiple subscriptions.
*
* @param nodeId The id of the node the event came from
* @param eventItems The list of {@link Item} that were published
* @param subscriptionIds The list of subscriptionIds
*/
public ItemPublishEvent(String nodeId, List<T> eventItems, List<String> subscriptionIds, Date publishedDate)
{
super(nodeId, subscriptionIds);
items = eventItems;
/**
* Constructs an <tt>ItemPublishEvent</tt> with the provided list
* of {@link Item} that were published in the past. The published
* date signifies that this is delayed event. The list of subscription ids
* represents the subscriptions that matched the event, in the case
* of the user having multiple subscriptions.
*
* @param nodeId The id of the node the event came from
* @param eventItems The list of {@link Item} that were published
* @param subscriptionIds The list of subscriptionIds
*/
public ItemPublishEvent(String nodeId, List<T> eventItems, List<String> subscriptionIds, Date publishedDate)
{
super(nodeId, subscriptionIds);
items = eventItems;
if (publishedDate != null)
originalDate = publishedDate;
}
if (publishedDate != null)
originalDate = publishedDate;
}
/**
* Get the list of {@link Item} that were published.
*
* @return The list of published {@link Item}
*/
public List<T> getItems()
{
return Collections.unmodifiableList(items);
}
/**
* Get the list of {@link Item} that were published.
*
* @return The list of published {@link Item}
*/
public List<T> getItems()
{
return Collections.unmodifiableList(items);
}
/**
* Indicates whether this event was delayed. That is, the items
* were published to the node at some time in the past. This will
* typically happen if there is an item already published to the node
* before a user subscribes to it. In this case, when the user
* subscribes, the server may send the last item published to the node
* with a delay date showing its time of original publication.
*
* @return true if the items are delayed, false otherwise.
*/
public boolean isDelayed()
{
return (originalDate != null);
}
/**
* Indicates whether this event was delayed. That is, the items
* were published to the node at some time in the past. This will
* typically happen if there is an item already published to the node
* before a user subscribes to it. In this case, when the user
* subscribes, the server may send the last item published to the node
* with a delay date showing its time of original publication.
*
* @return true if the items are delayed, false otherwise.
*/
public boolean isDelayed()
{
return (originalDate != null);
}
/**
* Gets the original date the items were published. This is only
* valid if {@link #isDelayed()} is true.
*
*/
public Date getPublishedDate()
{
return originalDate;
}
/**
* Gets the original date the items were published. This is only
* valid if {@link #isDelayed()} is true.
*
*/
public Date getPublishedDate()
{
return originalDate;
}
@Override
public String toString()
{
return getClass().getName() + " [subscriptions: " + getSubscriptions() + "], [Delayed: " +
(isDelayed() ? originalDate.toString() : "false") + ']';
}
@Override
public String toString()
{
return getClass().getName() + " [subscriptions: " + getSubscriptions() + "], [Delayed: " +
(isDelayed() ? originalDate.toString() : "false") + ']';
}
}

View file

@ -24,9 +24,9 @@ package org.jivesoftware.smackx.pubsub;
*/
public enum ItemReply
{
/** The node owner. */
owner,
/** The node owner. */
owner,
/** The item publisher. */
publisher;
/** The item publisher. */
publisher;
}

View file

@ -36,168 +36,169 @@ import org.jivesoftware.smack.packet.ExtensionElement;
*/
public class ItemsExtension extends NodeExtension implements EmbeddedPacketExtension
{
protected ItemsElementType type;
protected Boolean notify;
protected List<? extends ExtensionElement> items;
protected ItemsElementType type;
protected Boolean notify;
protected List<? extends ExtensionElement> items;
public enum ItemsElementType
{
/** An items element, which has an optional <b>max_items</b> attribute when requesting items. */
items(PubSubElementType.ITEMS, "max_items"),
public enum ItemsElementType
{
/** An items element, which has an optional <b>max_items</b> attribute when requesting items. */
items(PubSubElementType.ITEMS, "max_items"),
/** A retract element, which has an optional <b>notify</b> attribute when publishing deletions. */
retract(PubSubElementType.RETRACT, "notify");
/** A retract element, which has an optional <b>notify</b> attribute when publishing deletions. */
retract(PubSubElementType.RETRACT, "notify");
private PubSubElementType elem;
private String att;
private final PubSubElementType elem;
private final String att;
private ItemsElementType(PubSubElementType nodeElement, String attribute)
{
elem = nodeElement;
att = attribute;
}
private ItemsElementType(PubSubElementType nodeElement, String attribute)
{
elem = nodeElement;
att = attribute;
}
public PubSubElementType getNodeElement()
{
return elem;
}
public PubSubElementType getNodeElement()
{
return elem;
}
public String getElementAttribute()
{
return att;
}
}
public String getElementAttribute()
{
return att;
}
}
/**
* Construct an instance with a list representing items that have been published or deleted.
*
* <p>Valid scenarios are:</p>
* <ul>
* <li>Request items from node - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and an
* optional value for the <b>max_items</b> attribute.
* <li>Request to delete items - itemsType = {@link ItemsElementType#retract}, items = list of {@link Item} containing
* only id's and an optional value for the <b>notify</b> attribute.
* <li>Items published event - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and
* attributeValue = <code>null</code>
* <li>Items deleted event - itemsType = {@link ItemsElementType#items}, items = list of {@link RetractItem} and
* attributeValue = <code>null</code>
* </ul>
*
* @param itemsType Type of representation
* @param nodeId The node to which the items are being sent or deleted
* @param items The list of {@link Item} or {@link RetractItem}
*/
public ItemsExtension(ItemsElementType itemsType, String nodeId, List<? extends ExtensionElement> items)
{
super(itemsType.getNodeElement(), nodeId);
type = itemsType;
this.items = items;
}
/**
* Construct an instance with a list representing items that have been published or deleted.
*
* <p>Valid scenarios are:</p>
* <ul>
* <li>Request items from node - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and an
* optional value for the <b>max_items</b> attribute.
* <li>Request to delete items - itemsType = {@link ItemsElementType#retract}, items = list of {@link Item} containing
* only id's and an optional value for the <b>notify</b> attribute.
* <li>Items published event - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and
* attributeValue = <code>null</code>
* <li>Items deleted event - itemsType = {@link ItemsElementType#items}, items = list of {@link RetractItem} and
* attributeValue = <code>null</code>
* </ul>
*
* @param itemsType Type of representation
* @param nodeId The node to which the items are being sent or deleted
* @param items The list of {@link Item} or {@link RetractItem}
*/
public ItemsExtension(ItemsElementType itemsType, String nodeId, List<? extends ExtensionElement> items)
{
super(itemsType.getNodeElement(), nodeId);
type = itemsType;
this.items = items;
}
/**
* Construct an instance with a list representing items that have been published or deleted.
*
* <p>Valid scenarios are:</p>
* <ul>
* <li>Request items from node - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and an
* optional value for the <b>max_items</b> attribute.
* <li>Request to delete items - itemsType = {@link ItemsElementType#retract}, items = list of {@link Item} containing
* only id's and an optional value for the <b>notify</b> attribute.
* <li>Items published event - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and
* attributeValue = <code>null</code>
* <li>Items deleted event - itemsType = {@link ItemsElementType#items}, items = list of {@link RetractItem} and
* attributeValue = <code>null</code>
* </ul>
*
* @param nodeId The node to which the items are being sent or deleted
* @param items The list of {@link Item} or {@link RetractItem}
*/
public ItemsExtension(String nodeId, List<? extends ExtensionElement> items, boolean notify)
{
super(ItemsElementType.retract.getNodeElement(), nodeId);
type = ItemsElementType.retract;
this.items = items;
this.notify = notify;
}
/**
* Construct an instance with a list representing items that have been published or deleted.
*
* <p>Valid scenarios are:</p>
* <ul>
* <li>Request items from node - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and an
* optional value for the <b>max_items</b> attribute.
* <li>Request to delete items - itemsType = {@link ItemsElementType#retract}, items = list of {@link Item} containing
* only id's and an optional value for the <b>notify</b> attribute.
* <li>Items published event - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and
* attributeValue = <code>null</code>
* <li>Items deleted event - itemsType = {@link ItemsElementType#items}, items = list of {@link RetractItem} and
* attributeValue = <code>null</code>
* </ul>
*
* @param nodeId The node to which the items are being sent or deleted
* @param items The list of {@link Item} or {@link RetractItem}
*/
public ItemsExtension(String nodeId, List<? extends ExtensionElement> items, boolean notify)
{
super(ItemsElementType.retract.getNodeElement(), nodeId);
type = ItemsElementType.retract;
this.items = items;
this.notify = notify;
}
/**
* Get the type of element.
*
* @return The element type
*/
public ItemsElementType getItemsElementType()
{
return type;
}
/**
* Get the type of element.
*
* @return The element type
*/
public ItemsElementType getItemsElementType()
{
return type;
}
@SuppressWarnings("unchecked")
public List<ExtensionElement> getExtensions()
{
return (List<ExtensionElement>)getItems();
}
@Override
@SuppressWarnings("unchecked")
public List<ExtensionElement> getExtensions()
{
return (List<ExtensionElement>)getItems();
}
/**
* Gets the items related to the type of request or event.
*
* return List of {@link Item}, {@link RetractItem}, or null
*/
public List<? extends ExtensionElement> getItems()
{
return items;
}
/**
* Gets the items related to the type of request or event.
*
* return List of {@link Item}, {@link RetractItem}, or null
*/
public List<? extends ExtensionElement> getItems()
{
return items;
}
/**
* Gets the value of the optional attribute related to the {@link ItemsElementType}.
*
* @return The attribute value
*/
public boolean getNotify()
{
return notify;
}
/**
* Gets the value of the optional attribute related to the {@link ItemsElementType}.
*
* @return The attribute value
*/
public boolean getNotify()
{
return notify;
}
@Override
public CharSequence toXML()
{
if ((items == null) || (items.size() == 0))
{
return super.toXML();
}
else
{
StringBuilder builder = new StringBuilder("<");
builder.append(getElementName());
builder.append(" node='");
builder.append(getNode());
@Override
public CharSequence toXML()
{
if ((items == null) || (items.size() == 0))
{
return super.toXML();
}
else
{
StringBuilder builder = new StringBuilder("<");
builder.append(getElementName());
builder.append(" node='");
builder.append(getNode());
if (notify != null)
{
builder.append("' ");
builder.append(type.getElementAttribute());
builder.append("='");
builder.append(notify.equals(Boolean.TRUE) ? 1 : 0);
builder.append("'>");
}
else
{
builder.append("'>");
for (ExtensionElement item : items)
{
builder.append(item.toXML());
}
}
if (notify != null)
{
builder.append("' ");
builder.append(type.getElementAttribute());
builder.append("='");
builder.append(notify.equals(Boolean.TRUE) ? 1 : 0);
builder.append("'>");
}
else
{
builder.append("'>");
for (ExtensionElement item : items)
{
builder.append(item.toXML());
}
}
builder.append("</");
builder.append(getElementName());
builder.append('>');
return builder.toString();
}
}
builder.append("</");
builder.append(getElementName());
builder.append('>');
return builder.toString();
}
}
@Override
public String toString()
{
return getClass().getName() + "Content [" + toXML() + "]";
}
@Override
public String toString()
{
return getClass().getName() + "Content [" + toXML() + "]";
}
}

View file

@ -38,125 +38,125 @@ import org.jivesoftware.smackx.pubsub.packet.PubSub;
*/
public class LeafNode extends Node
{
LeafNode(PubSubManager pubSubManager, String nodeId)
{
super(pubSubManager, nodeId);
}
LeafNode(PubSubManager pubSubManager, String nodeId)
{
super(pubSubManager, nodeId);
}
/**
* Get information on the items in the node in standard
* {@link DiscoverItems} format.
*
* @return The item details in {@link DiscoverItems} format
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public DiscoverItems discoverItems() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
DiscoverItems items = new DiscoverItems();
items.setTo(pubSubManager.getServiceJid());
items.setNode(getId());
/**
* Get information on the items in the node in standard
* {@link DiscoverItems} format.
*
* @return The item details in {@link DiscoverItems} format
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public DiscoverItems discoverItems() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
DiscoverItems items = new DiscoverItems();
items.setTo(pubSubManager.getServiceJid());
items.setNode(getId());
return pubSubManager.getConnection().createStanzaCollectorAndSend(items).nextResultOrThrow();
}
}
/**
* Get the current items stored in the node.
*
* @return List of {@link Item} in the node
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> List<T> getItems() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
/**
* Get the current items stored in the node.
*
* @return List of {@link Item} in the node
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> List<T> getItems() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
return getItems((List<ExtensionElement>) null, (List<ExtensionElement>) null);
}
}
/**
* Get the current items stored in the node based
* on the subscription associated with the provided
* subscription id.
*
* @param subscriptionId - The subscription id for the
* associated subscription.
* @return List of {@link Item} in the node
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> List<T> getItems(String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub request = createPubsubPacket(Type.get, new GetItemsRequest(getId(), subscriptionId));
/**
* Get the current items stored in the node based
* on the subscription associated with the provided
* subscription id.
*
* @param subscriptionId - The subscription id for the
* associated subscription.
* @return List of {@link Item} in the node
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> List<T> getItems(String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub request = createPubsubPacket(Type.get, new GetItemsRequest(getId(), subscriptionId));
return getItems(request);
}
}
/**
* Get the items specified from the node. This would typically be
* used when the server does not return the payload due to size
* constraints. The user would be required to retrieve the payload
* after the items have been retrieved via {@link #getItems()} or an
* event, that did not include the payload.
*
* @param ids Item ids of the items to retrieve
*
* @return The list of {@link Item} with payload
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> List<T> getItems(Collection<String> ids) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
List<Item> itemList = new ArrayList<Item>(ids.size());
/**
* Get the items specified from the node. This would typically be
* used when the server does not return the payload due to size
* constraints. The user would be required to retrieve the payload
* after the items have been retrieved via {@link #getItems()} or an
* event, that did not include the payload.
*
* @param ids Item ids of the items to retrieve
*
* @return The list of {@link Item} with payload
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> List<T> getItems(Collection<String> ids) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
List<Item> itemList = new ArrayList<Item>(ids.size());
for (String id : ids)
{
itemList.add(new Item(id));
}
PubSub request = createPubsubPacket(Type.get, new ItemsExtension(ItemsExtension.ItemsElementType.items, getId(), itemList));
for (String id : ids)
{
itemList.add(new Item(id));
}
PubSub request = createPubsubPacket(Type.get, new ItemsExtension(ItemsExtension.ItemsElementType.items, getId(), itemList));
return getItems(request);
}
}
/**
* Get items persisted on the node, limited to the specified number.
*
* @param maxItems Maximum number of items to return
*
* @return List of {@link Item}
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> List<T> getItems(int maxItems) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub request = createPubsubPacket(Type.get, new GetItemsRequest(getId(), maxItems));
/**
* Get items persisted on the node, limited to the specified number.
*
* @param maxItems Maximum number of items to return
*
* @return List of {@link Item}
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> List<T> getItems(int maxItems) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub request = createPubsubPacket(Type.get, new GetItemsRequest(getId(), maxItems));
return getItems(request);
}
}
/**
* Get items persisted on the node, limited to the specified number
* based on the subscription associated with the provided subscriptionId.
*
* @param maxItems Maximum number of items to return
* @param subscriptionId The subscription which the retrieval is based
* on.
*
* @return List of {@link Item}
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> List<T> getItems(int maxItems, String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub request = createPubsubPacket(Type.get, new GetItemsRequest(getId(), subscriptionId, maxItems));
/**
* Get items persisted on the node, limited to the specified number
* based on the subscription associated with the provided subscriptionId.
*
* @param maxItems Maximum number of items to return
* @param subscriptionId The subscription which the retrieval is based
* on.
*
* @return List of {@link Item}
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> List<T> getItems(int maxItems, String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub request = createPubsubPacket(Type.get, new GetItemsRequest(getId(), subscriptionId, maxItems));
return getItems(request);
}
}
/**
* Get items persisted on the node.
@ -200,206 +200,206 @@ public class LeafNode extends Node
return (List<T>) itemsElem.getItems();
}
/**
* Publishes an event to the node. This is an empty event
* with no item.
*
* This is only acceptable for nodes with {@link ConfigureForm#isPersistItems()}=false
* and {@link ConfigureForm#isDeliverPayloads()}=false.
*
* This is an asynchronous call which returns as soon as the
* stanza(/packet) has been sent.
*
* For synchronous calls use {@link #send() send()}.
* @throws NotConnectedException
* @throws InterruptedException
*/
public void publish() throws NotConnectedException, InterruptedException
{
PubSub packet = createPubsubPacket(Type.set, new NodeExtension(PubSubElementType.PUBLISH, getId()));
/**
* Publishes an event to the node. This is an empty event
* with no item.
*
* This is only acceptable for nodes with {@link ConfigureForm#isPersistItems()}=false
* and {@link ConfigureForm#isDeliverPayloads()}=false.
*
* This is an asynchronous call which returns as soon as the
* stanza(/packet) has been sent.
*
* For synchronous calls use {@link #send() send()}.
* @throws NotConnectedException
* @throws InterruptedException
*/
public void publish() throws NotConnectedException, InterruptedException
{
PubSub packet = createPubsubPacket(Type.set, new NodeExtension(PubSubElementType.PUBLISH, getId()));
pubSubManager.getConnection().sendStanza(packet);
}
pubSubManager.getConnection().sendStanza(packet);
}
/**
* Publishes an event to the node. This is a simple item
* with no payload.
*
* If the id is null, an empty item (one without an id) will be sent.
* Please note that this is not the same as {@link #send()}, which
* publishes an event with NO item.
*
* This is an asynchronous call which returns as soon as the
* stanza(/packet) has been sent.
*
* For synchronous calls use {@link #send(Item) send(Item))}.
*
* @param item - The item being sent
* @throws NotConnectedException
* @throws InterruptedException
*/
@SuppressWarnings("unchecked")
public <T extends Item> void publish(T item) throws NotConnectedException, InterruptedException
{
Collection<T> items = new ArrayList<T>(1);
items.add((T)(item == null ? new Item() : item));
publish(items);
}
/**
* Publishes an event to the node. This is a simple item
* with no payload.
*
* If the id is null, an empty item (one without an id) will be sent.
* Please note that this is not the same as {@link #send()}, which
* publishes an event with NO item.
*
* This is an asynchronous call which returns as soon as the
* stanza(/packet) has been sent.
*
* For synchronous calls use {@link #send(Item) send(Item))}.
*
* @param item - The item being sent
* @throws NotConnectedException
* @throws InterruptedException
*/
@SuppressWarnings("unchecked")
public <T extends Item> void publish(T item) throws NotConnectedException, InterruptedException
{
Collection<T> items = new ArrayList<T>(1);
items.add((T)(item == null ? new Item() : item));
publish(items);
}
/**
* Publishes multiple events to the node. Same rules apply as in {@link #publish(Item)}.
*
* In addition, if {@link ConfigureForm#isPersistItems()}=false, only the last item in the input
* list will get stored on the node, assuming it stores the last sent item.
*
* This is an asynchronous call which returns as soon as the
* stanza(/packet) has been sent.
*
* For synchronous calls use {@link #send(Collection) send(Collection))}.
*
* @param items - The collection of items being sent
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> void publish(Collection<T> items) throws NotConnectedException, InterruptedException
{
PubSub packet = createPubsubPacket(Type.set, new PublishItem<T>(getId(), items));
/**
* Publishes multiple events to the node. Same rules apply as in {@link #publish(Item)}.
*
* In addition, if {@link ConfigureForm#isPersistItems()}=false, only the last item in the input
* list will get stored on the node, assuming it stores the last sent item.
*
* This is an asynchronous call which returns as soon as the
* stanza(/packet) has been sent.
*
* For synchronous calls use {@link #send(Collection) send(Collection))}.
*
* @param items - The collection of items being sent
* @throws NotConnectedException
* @throws InterruptedException
*/
public <T extends Item> void publish(Collection<T> items) throws NotConnectedException, InterruptedException
{
PubSub packet = createPubsubPacket(Type.set, new PublishItem<T>(getId(), items));
pubSubManager.getConnection().sendStanza(packet);
}
pubSubManager.getConnection().sendStanza(packet);
}
/**
* Publishes an event to the node. This is an empty event
* with no item.
*
* This is only acceptable for nodes with {@link ConfigureForm#isPersistItems()}=false
* and {@link ConfigureForm#isDeliverPayloads()}=false.
*
* This is a synchronous call which will throw an exception
* on failure.
*
* For asynchronous calls, use {@link #publish() publish()}.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
public void send() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub packet = createPubsubPacket(Type.set, new NodeExtension(PubSubElementType.PUBLISH, getId()));
/**
* Publishes an event to the node. This is an empty event
* with no item.
*
* This is only acceptable for nodes with {@link ConfigureForm#isPersistItems()}=false
* and {@link ConfigureForm#isDeliverPayloads()}=false.
*
* This is a synchronous call which will throw an exception
* on failure.
*
* For asynchronous calls, use {@link #publish() publish()}.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
public void send() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub packet = createPubsubPacket(Type.set, new NodeExtension(PubSubElementType.PUBLISH, getId()));
pubSubManager.getConnection().createStanzaCollectorAndSend(packet).nextResultOrThrow();
}
pubSubManager.getConnection().createStanzaCollectorAndSend(packet).nextResultOrThrow();
}
/**
* Publishes an event to the node. This can be either a simple item
* with no payload, or one with it. This is determined by the Node
* configuration.
*
* If the node has <b>deliver_payload=false</b>, the Item must not
* have a payload.
*
* If the id is null, an empty item (one without an id) will be sent.
* Please note that this is not the same as {@link #send()}, which
* publishes an event with NO item.
*
* This is a synchronous call which will throw an exception
* on failure.
*
* For asynchronous calls, use {@link #publish(Item) publish(Item)}.
*
* @param item - The item being sent
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
@SuppressWarnings("unchecked")
public <T extends Item> void send(T item) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
Collection<T> items = new ArrayList<T>(1);
items.add((item == null ? (T)new Item() : item));
send(items);
}
/**
* Publishes an event to the node. This can be either a simple item
* with no payload, or one with it. This is determined by the Node
* configuration.
*
* If the node has <b>deliver_payload=false</b>, the Item must not
* have a payload.
*
* If the id is null, an empty item (one without an id) will be sent.
* Please note that this is not the same as {@link #send()}, which
* publishes an event with NO item.
*
* This is a synchronous call which will throw an exception
* on failure.
*
* For asynchronous calls, use {@link #publish(Item) publish(Item)}.
*
* @param item - The item being sent
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
@SuppressWarnings("unchecked")
public <T extends Item> void send(T item) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
Collection<T> items = new ArrayList<T>(1);
items.add((item == null ? (T)new Item() : item));
send(items);
}
/**
* Publishes multiple events to the node. Same rules apply as in {@link #send(Item)}.
*
* In addition, if {@link ConfigureForm#isPersistItems()}=false, only the last item in the input
* list will get stored on the node, assuming it stores the last sent item.
*
* This is a synchronous call which will throw an exception
* on failure.
*
* For asynchronous calls, use {@link #publish(Collection) publish(Collection))}.
*
* @param items - The collection of {@link Item} objects being sent
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
public <T extends Item> void send(Collection<T> items) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub packet = createPubsubPacket(Type.set, new PublishItem<T>(getId(), items));
/**
* Publishes multiple events to the node. Same rules apply as in {@link #send(Item)}.
*
* In addition, if {@link ConfigureForm#isPersistItems()}=false, only the last item in the input
* list will get stored on the node, assuming it stores the last sent item.
*
* This is a synchronous call which will throw an exception
* on failure.
*
* For asynchronous calls, use {@link #publish(Collection) publish(Collection))}.
*
* @param items - The collection of {@link Item} objects being sent
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
public <T extends Item> void send(Collection<T> items) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub packet = createPubsubPacket(Type.set, new PublishItem<T>(getId(), items));
pubSubManager.getConnection().createStanzaCollectorAndSend(packet).nextResultOrThrow();
}
pubSubManager.getConnection().createStanzaCollectorAndSend(packet).nextResultOrThrow();
}
/**
* Purges the node of all items.
*
* <p>Note: Some implementations may keep the last item
* sent.
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public void deleteAllItems() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub request = createPubsubPacket(Type.set, new NodeExtension(PubSubElementType.PURGE_OWNER, getId()), PubSubElementType.PURGE_OWNER.getNamespace());
/**
* Purges the node of all items.
*
* <p>Note: Some implementations may keep the last item
* sent.
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public void deleteAllItems() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub request = createPubsubPacket(Type.set, new NodeExtension(PubSubElementType.PURGE_OWNER, getId()), PubSubElementType.PURGE_OWNER.getNamespace());
pubSubManager.getConnection().createStanzaCollectorAndSend(request).nextResultOrThrow();
}
pubSubManager.getConnection().createStanzaCollectorAndSend(request).nextResultOrThrow();
}
/**
* Delete the item with the specified id from the node.
*
* @param itemId The id of the item
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void deleteItem(String itemId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
Collection<String> items = new ArrayList<String>(1);
items.add(itemId);
deleteItem(items);
}
/**
* Delete the item with the specified id from the node.
*
* @param itemId The id of the item
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void deleteItem(String itemId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
Collection<String> items = new ArrayList<String>(1);
items.add(itemId);
deleteItem(items);
}
/**
* Delete the items with the specified id's from the node.
*
* @param itemIds The list of id's of items to delete
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public void deleteItem(Collection<String> itemIds) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
List<Item> items = new ArrayList<Item>(itemIds.size());
/**
* Delete the items with the specified id's from the node.
*
* @param itemIds The list of id's of items to delete
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public void deleteItem(Collection<String> itemIds) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
List<Item> items = new ArrayList<Item>(itemIds.size());
for (String id : itemIds)
{
items.add(new Item(id));
}
PubSub request = createPubsubPacket(Type.set, new ItemsExtension(ItemsExtension.ItemsElementType.retract, getId(), items));
pubSubManager.getConnection().createStanzaCollectorAndSend(request).nextResultOrThrow();
}
for (String id : itemIds)
{
items.add(new Item(id));
}
PubSub request = createPubsubPacket(Type.set, new ItemsExtension(ItemsExtension.ItemsElementType.retract, getId(), items));
pubSubManager.getConnection().createStanzaCollectorAndSend(request).nextResultOrThrow();
}
}

View file

@ -48,97 +48,97 @@ abstract public class Node
protected final PubSubManager pubSubManager;
protected final String id;
protected ConcurrentHashMap<ItemEventListener<Item>, StanzaListener> itemEventToListenerMap = new ConcurrentHashMap<ItemEventListener<Item>, StanzaListener>();
protected ConcurrentHashMap<ItemDeleteListener, StanzaListener> itemDeleteToListenerMap = new ConcurrentHashMap<ItemDeleteListener, StanzaListener>();
protected ConcurrentHashMap<NodeConfigListener, StanzaListener> configEventToListenerMap = new ConcurrentHashMap<NodeConfigListener, StanzaListener>();
protected ConcurrentHashMap<ItemEventListener<Item>, StanzaListener> itemEventToListenerMap = new ConcurrentHashMap<ItemEventListener<Item>, StanzaListener>();
protected ConcurrentHashMap<ItemDeleteListener, StanzaListener> itemDeleteToListenerMap = new ConcurrentHashMap<ItemDeleteListener, StanzaListener>();
protected ConcurrentHashMap<NodeConfigListener, StanzaListener> configEventToListenerMap = new ConcurrentHashMap<NodeConfigListener, StanzaListener>();
/**
* Construct a node associated to the supplied connection with the specified
* node id.
*
* @param connection The connection the node is associated with
* @param nodeName The node id
*/
Node(PubSubManager pubSubManager, String nodeId)
{
this.pubSubManager = pubSubManager;
id = nodeId;
}
/**
* Construct a node associated to the supplied connection with the specified
* node id.
*
* @param connection The connection the node is associated with
* @param nodeName The node id
*/
Node(PubSubManager pubSubManager, String nodeId)
{
this.pubSubManager = pubSubManager;
id = nodeId;
}
/**
* Get the NodeId.
*
* @return the node id
*/
public String getId()
{
return id;
}
/**
* Returns a configuration form, from which you can create an answer form to be submitted
* via the {@link #sendConfigurationForm(Form)}.
*
* @return the configuration form
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public ConfigureForm getNodeConfiguration() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
/**
* Get the NodeId.
*
* @return the node id
*/
public String getId()
{
return id;
}
/**
* Returns a configuration form, from which you can create an answer form to be submitted
* via the {@link #sendConfigurationForm(Form)}.
*
* @return the configuration form
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public ConfigureForm getNodeConfiguration() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub pubSub = createPubsubPacket(Type.get, new NodeExtension(
PubSubElementType.CONFIGURE_OWNER, getId()), PubSubNamespace.OWNER);
Stanza reply = sendPubsubPacket(pubSub);
return NodeUtils.getFormFromPacket(reply, PubSubElementType.CONFIGURE_OWNER);
}
Stanza reply = sendPubsubPacket(pubSub);
return NodeUtils.getFormFromPacket(reply, PubSubElementType.CONFIGURE_OWNER);
}
/**
* Update the configuration with the contents of the new {@link Form}.
*
* @param submitForm
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void sendConfigurationForm(Form submitForm) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
/**
* Update the configuration with the contents of the new {@link Form}.
*
* @param submitForm
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void sendConfigurationForm(Form submitForm) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub packet = createPubsubPacket(Type.set, new FormNode(FormNodeType.CONFIGURE_OWNER,
getId(), submitForm), PubSubNamespace.OWNER);
pubSubManager.getConnection().createStanzaCollectorAndSend(packet).nextResultOrThrow();
}
}
/**
* Discover node information in standard {@link DiscoverInfo} format.
*
* @return The discovery information about the node.
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public DiscoverInfo discoverInfo() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
DiscoverInfo info = new DiscoverInfo();
info.setTo(pubSubManager.getServiceJid());
info.setNode(getId());
return pubSubManager.getConnection().createStanzaCollectorAndSend(info).nextResultOrThrow();
}
/**
* Discover node information in standard {@link DiscoverInfo} format.
*
* @return The discovery information about the node.
* @throws XMPPErrorException
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public DiscoverInfo discoverInfo() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
DiscoverInfo info = new DiscoverInfo();
info.setTo(pubSubManager.getServiceJid());
info.setNode(getId());
return pubSubManager.getConnection().createStanzaCollectorAndSend(info).nextResultOrThrow();
}
/**
* Get the subscriptions currently associated with this node.
*
* @return List of {@link Subscription}
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
public List<Subscription> getSubscriptions() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
/**
* Get the subscriptions currently associated with this node.
*
* @return List of {@link Subscription}
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
public List<Subscription> getSubscriptions() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
return getSubscriptions(null, null);
}
}
/**
* Get the subscriptions currently associated with this node.
@ -223,15 +223,15 @@ abstract public class Node
return subElem.getSubscriptions();
}
/**
* Get the affiliations of this node.
*
* @return List of {@link Affiliation}
* @throws NoResponseException
* @throws XMPPErrorException
* @throws NotConnectedException
* @throws InterruptedException
*/
/**
* Get the affiliations of this node.
*
* @return List of {@link Affiliation}
* @throws NoResponseException
* @throws XMPPErrorException
* @throws NotConnectedException
* @throws InterruptedException
*/
public List<Affiliation> getAffiliations() throws NoResponseException, XMPPErrorException,
NotConnectedException, InterruptedException {
return getAffiliations(null, null);
@ -346,398 +346,396 @@ abstract public class Node
return sendPubsubPacket(pubSub);
}
/**
* The user subscribes to the node using the supplied jid. The
* bare jid portion of this one must match the jid for the connection.
*
* Please note that the {@link Subscription.State} should be checked
* on return since more actions may be required by the caller.
* {@link Subscription.State#pending} - The owner must approve the subscription
* request before messages will be received.
* {@link Subscription.State#unconfigured} - If the {@link Subscription#isConfigRequired()} is true,
* the caller must configure the subscription before messages will be received. If it is false
* the caller can configure it but is not required to do so.
* @param jid The jid to subscribe as.
* @return The subscription
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public Subscription subscribe(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
// CHECKSTYLE:OFF
PubSub pubSub = createPubsubPacket(Type.set, new SubscribeExtension(jid, getId()));
// CHECKSTYLE:ON
PubSub reply = sendPubsubPacket(pubSub);
return reply.getExtension(PubSubElementType.SUBSCRIPTION);
}
/**
* The user subscribes to the node using the supplied jid. The
* bare jid portion of this one must match the jid for the connection.
*
* Please note that the {@link Subscription.State} should be checked
* on return since more actions may be required by the caller.
* {@link Subscription.State#pending} - The owner must approve the subscription
* request before messages will be received.
* {@link Subscription.State#unconfigured} - If the {@link Subscription#isConfigRequired()} is true,
* the caller must configure the subscription before messages will be received. If it is false
* the caller can configure it but is not required to do so.
* @param jid The jid to subscribe as.
* @return The subscription
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public Subscription subscribe(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub pubSub = createPubsubPacket(Type.set, new SubscribeExtension(jid, getId()));
PubSub reply = sendPubsubPacket(pubSub);
return reply.getExtension(PubSubElementType.SUBSCRIPTION);
}
/**
* The user subscribes to the node using the supplied jid and subscription
* options. The bare jid portion of this one must match the jid for the
* connection.
*
* Please note that the {@link Subscription.State} should be checked
* on return since more actions may be required by the caller.
* {@link Subscription.State#pending} - The owner must approve the subscription
* request before messages will be received.
* {@link Subscription.State#unconfigured} - If the {@link Subscription#isConfigRequired()} is true,
* the caller must configure the subscription before messages will be received. If it is false
* the caller can configure it but is not required to do so.
* @param jid The jid to subscribe as.
* @return The subscription
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public Subscription subscribe(String jid, SubscribeForm subForm) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
// CHECKSTYLE:OFF
PubSub request = createPubsubPacket(Type.set, new SubscribeExtension(jid, getId()));
// CHECKSTYLE:ON
request.addExtension(new FormNode(FormNodeType.OPTIONS, subForm));
PubSub reply = sendPubsubPacket(request);
return reply.getExtension(PubSubElementType.SUBSCRIPTION);
}
/**
* The user subscribes to the node using the supplied jid and subscription
* options. The bare jid portion of this one must match the jid for the
* connection.
*
* Please note that the {@link Subscription.State} should be checked
* on return since more actions may be required by the caller.
* {@link Subscription.State#pending} - The owner must approve the subscription
* request before messages will be received.
* {@link Subscription.State#unconfigured} - If the {@link Subscription#isConfigRequired()} is true,
* the caller must configure the subscription before messages will be received. If it is false
* the caller can configure it but is not required to do so.
* @param jid The jid to subscribe as.
* @return The subscription
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public Subscription subscribe(String jid, SubscribeForm subForm) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub request = createPubsubPacket(Type.set, new SubscribeExtension(jid, getId()));
request.addExtension(new FormNode(FormNodeType.OPTIONS, subForm));
PubSub reply = sendPubsubPacket(request);
return reply.getExtension(PubSubElementType.SUBSCRIPTION);
}
/**
* Remove the subscription related to the specified JID. This will only
* work if there is only 1 subscription. If there are multiple subscriptions,
* use {@link #unsubscribe(String, String)}.
*
* @param jid The JID used to subscribe to the node
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
public void unsubscribe(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
unsubscribe(jid, null);
}
/**
* Remove the subscription related to the specified JID. This will only
* work if there is only 1 subscription. If there are multiple subscriptions,
* use {@link #unsubscribe(String, String)}.
*
* @param jid The JID used to subscribe to the node
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
public void unsubscribe(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
unsubscribe(jid, null);
}
/**
* Remove the specific subscription related to the specified JID.
*
* @param jid The JID used to subscribe to the node
* @param subscriptionId The id of the subscription being removed
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void unsubscribe(String jid, String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
sendPubsubPacket(createPubsubPacket(Type.set, new UnsubscribeExtension(jid, getId(), subscriptionId)));
}
/**
* Remove the specific subscription related to the specified JID.
*
* @param jid The JID used to subscribe to the node
* @param subscriptionId The id of the subscription being removed
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public void unsubscribe(String jid, String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
sendPubsubPacket(createPubsubPacket(Type.set, new UnsubscribeExtension(jid, getId(), subscriptionId)));
}
/**
* Returns a SubscribeForm for subscriptions, from which you can create an answer form to be submitted
* via the {@link #sendConfigurationForm(Form)}.
*
* @return A subscription options form
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public SubscribeForm getSubscriptionOptions(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
return getSubscriptionOptions(jid, null);
}
/**
* Returns a SubscribeForm for subscriptions, from which you can create an answer form to be submitted
* via the {@link #sendConfigurationForm(Form)}.
*
* @return A subscription options form
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*/
public SubscribeForm getSubscriptionOptions(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
return getSubscriptionOptions(jid, null);
}
/**
* Get the options for configuring the specified subscription.
*
* @param jid JID the subscription is registered under
* @param subscriptionId The subscription id
*
* @return The subscription option form
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
public SubscribeForm getSubscriptionOptions(String jid, String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub packet = sendPubsubPacket(createPubsubPacket(Type.get, new OptionsExtension(jid, getId(), subscriptionId)));
FormNode ext = packet.getExtension(PubSubElementType.OPTIONS);
return new SubscribeForm(ext.getForm());
}
/**
* Get the options for configuring the specified subscription.
*
* @param jid JID the subscription is registered under
* @param subscriptionId The subscription id
*
* @return The subscription option form
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
* @throws InterruptedException
*
*/
public SubscribeForm getSubscriptionOptions(String jid, String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
PubSub packet = sendPubsubPacket(createPubsubPacket(Type.get, new OptionsExtension(jid, getId(), subscriptionId)));
FormNode ext = packet.getExtension(PubSubElementType.OPTIONS);
return new SubscribeForm(ext.getForm());
}
/**
* Register a listener for item publication events. This
* listener will get called whenever an item is published to
* this node.
*
* @param listener The handler for the event
*/
@SuppressWarnings("unchecked")
/**
* Register a listener for item publication events. This
* listener will get called whenever an item is published to
* this node.
*
* @param listener The handler for the event
*/
@SuppressWarnings("unchecked")
public void addItemEventListener(@SuppressWarnings("rawtypes") ItemEventListener listener)
{
StanzaListener conListener = new ItemEventTranslator(listener);
itemEventToListenerMap.put(listener, conListener);
pubSubManager.getConnection().addSyncStanzaListener(conListener, new EventContentFilter(EventElementType.items.toString(), "item"));
}
{
StanzaListener conListener = new ItemEventTranslator(listener);
itemEventToListenerMap.put(listener, conListener);
pubSubManager.getConnection().addSyncStanzaListener(conListener, new EventContentFilter(EventElementType.items.toString(), "item"));
}
/**
* Unregister a listener for publication events.
*
* @param listener The handler to unregister
*/
public void removeItemEventListener(@SuppressWarnings("rawtypes") ItemEventListener listener)
{
StanzaListener conListener = itemEventToListenerMap.remove(listener);
/**
* Unregister a listener for publication events.
*
* @param listener The handler to unregister
*/
public void removeItemEventListener(@SuppressWarnings("rawtypes") ItemEventListener listener)
{
StanzaListener conListener = itemEventToListenerMap.remove(listener);
if (conListener != null)
pubSubManager.getConnection().removeSyncStanzaListener(conListener);
}
if (conListener != null)
pubSubManager.getConnection().removeSyncStanzaListener(conListener);
}
/**
* Register a listener for configuration events. This listener
* will get called whenever the node's configuration changes.
*
* @param listener The handler for the event
*/
public void addConfigurationListener(NodeConfigListener listener)
{
StanzaListener conListener = new NodeConfigTranslator(listener);
configEventToListenerMap.put(listener, conListener);
pubSubManager.getConnection().addSyncStanzaListener(conListener, new EventContentFilter(EventElementType.configuration.toString()));
}
/**
* Register a listener for configuration events. This listener
* will get called whenever the node's configuration changes.
*
* @param listener The handler for the event
*/
public void addConfigurationListener(NodeConfigListener listener)
{
StanzaListener conListener = new NodeConfigTranslator(listener);
configEventToListenerMap.put(listener, conListener);
pubSubManager.getConnection().addSyncStanzaListener(conListener, new EventContentFilter(EventElementType.configuration.toString()));
}
/**
* Unregister a listener for configuration events.
*
* @param listener The handler to unregister
*/
public void removeConfigurationListener(NodeConfigListener listener)
{
StanzaListener conListener = configEventToListenerMap .remove(listener);
/**
* Unregister a listener for configuration events.
*
* @param listener The handler to unregister
*/
public void removeConfigurationListener(NodeConfigListener listener)
{
StanzaListener conListener = configEventToListenerMap .remove(listener);
if (conListener != null)
pubSubManager.getConnection().removeSyncStanzaListener(conListener);
}
if (conListener != null)
pubSubManager.getConnection().removeSyncStanzaListener(conListener);
}
/**
* Register an listener for item delete events. This listener
* gets called whenever an item is deleted from the node.
*
* @param listener The handler for the event
*/
public void addItemDeleteListener(ItemDeleteListener listener)
{
StanzaListener delListener = new ItemDeleteTranslator(listener);
itemDeleteToListenerMap.put(listener, delListener);
EventContentFilter deleteItem = new EventContentFilter(EventElementType.items.toString(), "retract");
EventContentFilter purge = new EventContentFilter(EventElementType.purge.toString());
/**
* Register an listener for item delete events. This listener
* gets called whenever an item is deleted from the node.
*
* @param listener The handler for the event
*/
public void addItemDeleteListener(ItemDeleteListener listener)
{
StanzaListener delListener = new ItemDeleteTranslator(listener);
itemDeleteToListenerMap.put(listener, delListener);
EventContentFilter deleteItem = new EventContentFilter(EventElementType.items.toString(), "retract");
EventContentFilter purge = new EventContentFilter(EventElementType.purge.toString());
pubSubManager.getConnection().addSyncStanzaListener(delListener, new OrFilter(deleteItem, purge));
}
pubSubManager.getConnection().addSyncStanzaListener(delListener, new OrFilter(deleteItem, purge));
}
/**
* Unregister a listener for item delete events.
*
* @param listener The handler to unregister
*/
public void removeItemDeleteListener(ItemDeleteListener listener)
{
StanzaListener conListener = itemDeleteToListenerMap .remove(listener);
/**
* Unregister a listener for item delete events.
*
* @param listener The handler to unregister
*/
public void removeItemDeleteListener(ItemDeleteListener listener)
{
StanzaListener conListener = itemDeleteToListenerMap .remove(listener);
if (conListener != null)
pubSubManager.getConnection().removeSyncStanzaListener(conListener);
}
if (conListener != null)
pubSubManager.getConnection().removeSyncStanzaListener(conListener);
}
@Override
public String toString()
{
return super.toString() + " " + getClass().getName() + " id: " + id;
}
@Override
public String toString()
{
return super.toString() + " " + getClass().getName() + " id: " + id;
}
protected PubSub createPubsubPacket(Type type, ExtensionElement ext)
{
return createPubsubPacket(type, ext, null);
}
protected PubSub createPubsubPacket(Type type, ExtensionElement ext)
{
return createPubsubPacket(type, ext, null);
}
protected PubSub createPubsubPacket(Type type, ExtensionElement ext, PubSubNamespace ns)
{
protected PubSub createPubsubPacket(Type type, ExtensionElement ext, PubSubNamespace ns)
{
return PubSub.createPubsubPacket(pubSubManager.getServiceJid(), type, ext, ns);
}
}
protected PubSub sendPubsubPacket(PubSub packet) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
return pubSubManager.sendPubsubPacket(packet);
}
protected PubSub sendPubsubPacket(PubSub packet) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
{
return pubSubManager.sendPubsubPacket(packet);
}
private static List<String> getSubscriptionIds(Stanza packet)
{
HeadersExtension headers = (HeadersExtension)packet.getExtension("headers", "http://jabber.org/protocol/shim");
List<String> values = null;
private static List<String> getSubscriptionIds(Stanza packet)
{
HeadersExtension headers = (HeadersExtension)packet.getExtension("headers", "http://jabber.org/protocol/shim");
List<String> values = null;
if (headers != null)
{
values = new ArrayList<String>(headers.getHeaders().size());
if (headers != null)
{
values = new ArrayList<String>(headers.getHeaders().size());
for (Header header : headers.getHeaders())
{
values.add(header.getValue());
}
}
return values;
}
for (Header header : headers.getHeaders())
{
values.add(header.getValue());
}
}
return values;
}
/**
* This class translates low level item publication events into api level objects for
* user consumption.
*
* @author Robin Collier
*/
public class ItemEventTranslator implements StanzaListener
{
@SuppressWarnings("rawtypes")
/**
* This class translates low level item publication events into api level objects for
* user consumption.
*
* @author Robin Collier
*/
public class ItemEventTranslator implements StanzaListener
{
@SuppressWarnings("rawtypes")
private ItemEventListener listener;
public ItemEventTranslator(@SuppressWarnings("rawtypes") ItemEventListener eventListener)
{
listener = eventListener;
}
public ItemEventTranslator(@SuppressWarnings("rawtypes") ItemEventListener eventListener)
{
listener = eventListener;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public void processStanza(Stanza packet)
{
{
// CHECKSTYLE:OFF
EventElement event = (EventElement)packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
EventElement event = (EventElement)packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
// CHECKSTYLE:ON
ItemsExtension itemsElem = (ItemsExtension)event.getEvent();
ItemsExtension itemsElem = (ItemsExtension)event.getEvent();
ItemPublishEvent eventItems = new ItemPublishEvent(itemsElem.getNode(), itemsElem.getItems(), getSubscriptionIds(packet), DelayInformationManager.getDelayTimestamp(packet));
listener.handlePublishedItems(eventItems);
}
}
listener.handlePublishedItems(eventItems);
}
}
/**
* This class translates low level item deletion events into api level objects for
* user consumption.
*
* @author Robin Collier
*/
public class ItemDeleteTranslator implements StanzaListener
{
private ItemDeleteListener listener;
/**
* This class translates low level item deletion events into api level objects for
* user consumption.
*
* @author Robin Collier
*/
public class ItemDeleteTranslator implements StanzaListener
{
private ItemDeleteListener listener;
public ItemDeleteTranslator(ItemDeleteListener eventListener)
{
listener = eventListener;
}
public ItemDeleteTranslator(ItemDeleteListener eventListener)
{
listener = eventListener;
}
public void processStanza(Stanza packet)
{
@Override
public void processStanza(Stanza packet)
{
// CHECKSTYLE:OFF
EventElement event = (EventElement)packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
EventElement event = (EventElement)packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
List<ExtensionElement> extList = event.getExtensions();
List<ExtensionElement> extList = event.getExtensions();
if (extList.get(0).getElementName().equals(PubSubElementType.PURGE_EVENT.getElementName()))
{
listener.handlePurge();
}
else
{
ItemsExtension itemsElem = (ItemsExtension)event.getEvent();
@SuppressWarnings("unchecked")
if (extList.get(0).getElementName().equals(PubSubElementType.PURGE_EVENT.getElementName()))
{
listener.handlePurge();
}
else
{
ItemsExtension itemsElem = (ItemsExtension)event.getEvent();
@SuppressWarnings("unchecked")
Collection<RetractItem> pubItems = (Collection<RetractItem>) itemsElem.getItems();
List<String> items = new ArrayList<String>(pubItems.size());
List<String> items = new ArrayList<String>(pubItems.size());
for (RetractItem item : pubItems)
{
items.add(item.getId());
}
for (RetractItem item : pubItems)
{
items.add(item.getId());
}
ItemDeleteEvent eventItems = new ItemDeleteEvent(itemsElem.getNode(), items, getSubscriptionIds(packet));
listener.handleDeletedItems(eventItems);
}
ItemDeleteEvent eventItems = new ItemDeleteEvent(itemsElem.getNode(), items, getSubscriptionIds(packet));
listener.handleDeletedItems(eventItems);
}
// CHECKSTYLE:ON
}
}
}
}
/**
* This class translates low level node configuration events into api level objects for
* user consumption.
*
* @author Robin Collier
*/
public class NodeConfigTranslator implements StanzaListener
{
private NodeConfigListener listener;
/**
* This class translates low level node configuration events into api level objects for
* user consumption.
*
* @author Robin Collier
*/
public static class NodeConfigTranslator implements StanzaListener
{
private NodeConfigListener listener;
public NodeConfigTranslator(NodeConfigListener eventListener)
{
listener = eventListener;
}
public NodeConfigTranslator(NodeConfigListener eventListener)
{
listener = eventListener;
}
public void processStanza(Stanza packet)
{
// CHECKSTYLE:OFF
EventElement event = (EventElement)packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
ConfigurationEvent config = (ConfigurationEvent)event.getEvent();
// CHECKSTYLE:ON
@Override
public void processStanza(Stanza packet)
{
EventElement event = (EventElement)packet.getExtension("event", PubSubNamespace.EVENT.getXmlns());
ConfigurationEvent config = (ConfigurationEvent)event.getEvent();
listener.handleNodeConfiguration(config);
}
}
listener.handleNodeConfiguration(config);
}
}
/**
* Filter for {@link StanzaListener} to filter out events not specific to the
* event type expected for this node.
*
* @author Robin Collier
*/
class EventContentFilter extends FlexibleStanzaTypeFilter<Message>
{
/**
* Filter for {@link StanzaListener} to filter out events not specific to the
* event type expected for this node.
*
* @author Robin Collier
*/
class EventContentFilter extends FlexibleStanzaTypeFilter<Message>
{
private final String firstElement;
private final String secondElement;
private final boolean allowEmpty;
EventContentFilter(String elementName)
{
EventContentFilter(String elementName)
{
this(elementName, null);
}
}
EventContentFilter(String firstLevelEelement, String secondLevelElement)
{
firstElement = firstLevelEelement;
secondElement = secondLevelElement;
EventContentFilter(String firstLevelEelement, String secondLevelElement)
{
firstElement = firstLevelEelement;
secondElement = secondLevelElement;
allowEmpty = firstElement.equals(EventElementType.items.toString())
&& "item".equals(secondLevelElement);
}
}
@Override
public boolean acceptSpecific(Message message) {
EventElement event = EventElement.from(message);
if (event == null)
return false;
if (event == null)
return false;
NodeExtension embedEvent = event.getEvent();
NodeExtension embedEvent = event.getEvent();
if (embedEvent == null)
return false;
if (embedEvent == null)
return false;
if (embedEvent.getElementName().equals(firstElement))
{
if (!embedEvent.getNode().equals(getId()))
return false;
if (embedEvent.getElementName().equals(firstElement))
{
if (!embedEvent.getNode().equals(getId()))
return false;
if (secondElement == null)
return true;
if (secondElement == null)
return true;
if (embedEvent instanceof EmbeddedPacketExtension)
{
List<ExtensionElement> secondLevelList = ((EmbeddedPacketExtension)embedEvent).getExtensions();
if (embedEvent instanceof EmbeddedPacketExtension)
{
List<ExtensionElement> secondLevelList = ((EmbeddedPacketExtension)embedEvent).getExtensions();
// XEP-0060 allows no elements on second level for notifications. See schema or
// for example § 4.3:
@ -746,11 +744,11 @@ abstract public class Node
return true;
}
if (secondLevelList.size() > 0 && secondLevelList.get(0).getElementName().equals(secondElement))
return true;
}
}
return false;
}
}
if (secondLevelList.size() > 0 && secondLevelList.get(0).getElementName().equals(secondElement))
return true;
}
}
return false;
}
}
}

View file

@ -18,15 +18,15 @@ package org.jivesoftware.smackx.pubsub;
abstract public class NodeEvent
{
private String nodeId;
private String nodeId;
protected NodeEvent(String id)
{
nodeId = id;
}
protected NodeEvent(String id)
{
nodeId = id;
}
public String getNodeId()
{
return nodeId;
}
public String getNodeId()
{
return nodeId;
}
}

View file

@ -28,61 +28,64 @@ import org.jivesoftware.smack.packet.ExtensionElement;
*/
public class NodeExtension implements ExtensionElement
{
private final PubSubElementType element;
private final String node;
private final PubSubElementType element;
private final String node;
/**
* Constructs a <tt>NodeExtension</tt> with an element name specified
* by {@link PubSubElementType} and the specified node id.
*
* @param elem Defines the element name and namespace
* @param nodeId Specifies the id of the node
*/
public NodeExtension(PubSubElementType elem, String nodeId)
{
element = elem;
this.node = nodeId;
}
/**
* Constructs a <tt>NodeExtension</tt> with an element name specified
* by {@link PubSubElementType} and the specified node id.
*
* @param elem Defines the element name and namespace
* @param nodeId Specifies the id of the node
*/
public NodeExtension(PubSubElementType elem, String nodeId)
{
element = elem;
this.node = nodeId;
}
/**
* Constructs a <tt>NodeExtension</tt> with an element name specified
* by {@link PubSubElementType}.
*
* @param elem Defines the element name and namespace
*/
public NodeExtension(PubSubElementType elem)
{
this(elem, null);
}
/**
* Constructs a <tt>NodeExtension</tt> with an element name specified
* by {@link PubSubElementType}.
*
* @param elem Defines the element name and namespace
*/
public NodeExtension(PubSubElementType elem)
{
this(elem, null);
}
/**
* Gets the node id.
*
* @return The node id
*/
public String getNode()
{
return node;
}
/**
* Gets the node id.
*
* @return The node id
*/
public String getNode()
{
return node;
}
public String getElementName()
{
return element.getElementName();
}
@Override
public String getElementName()
{
return element.getElementName();
}
public String getNamespace()
{
return element.getNamespace().getXmlns();
}
@Override
public String getNamespace()
{
return element.getNamespace().getXmlns();
}
public CharSequence toXML()
{
return '<' + getElementName() + (node == null ? "" : " node='" + node + '\'') + "/>";
}
@Override
public CharSequence toXML()
{
return '<' + getElementName() + (node == null ? "" : " node='" + node + '\'') + "/>";
}
@Override
public String toString()
{
return getClass().getName() + " - content [" + toXML() + "]";
}
@Override
public String toString()
{
return getClass().getName() + " - content [" + toXML() + "]";
}
}

View file

@ -23,6 +23,6 @@ package org.jivesoftware.smackx.pubsub;
*/
public enum NodeType
{
leaf,
collection;
leaf,
collection;
}

View file

@ -25,35 +25,35 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
*/
public class OptionsExtension extends NodeExtension
{
protected String jid;
protected String id;
protected String jid;
protected String id;
public OptionsExtension(String subscriptionJid)
{
this(subscriptionJid, null, null);
}
public OptionsExtension(String subscriptionJid)
{
this(subscriptionJid, null, null);
}
public OptionsExtension(String subscriptionJid, String nodeId)
{
this(subscriptionJid, nodeId, null);
}
public OptionsExtension(String subscriptionJid, String nodeId)
{
this(subscriptionJid, nodeId, null);
}
public OptionsExtension(String jid, String nodeId, String subscriptionId)
{
super(PubSubElementType.OPTIONS, nodeId);
this.jid = jid;
id = subscriptionId;
}
public OptionsExtension(String jid, String nodeId, String subscriptionId)
{
super(PubSubElementType.OPTIONS, nodeId);
this.jid = jid;
id = subscriptionId;
}
public String getJid()
{
return jid;
}
public String getJid()
{
return jid;
}
public String getId()
{
return id;
}
public String getId()
{
return id;
}
@Override
public XmlStringBuilder toXML() {

Some files were not shown because too many files have changed in this diff Show more