1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-09-09 09:09:38 +02:00

Prefix subprojects with 'smack-'

instead of using the old baseName=smack appendix=project.name approach,
we are now going convention over configuration and renaming the
subprojects directories to the proper name.

Having a prefix is actually very helpful, because the resulting
libraries will be named like the subproject. And a core-4.0.0-rc1.jar is
not as explicit about what it actually *is* as a
smack-core-4.0.0-rc1.jar.

SMACK-265
This commit is contained in:
Florian Schmaus 2014-04-28 19:27:53 +02:00
parent b6fb1f3743
commit 91fd15ad86
758 changed files with 42 additions and 42 deletions

View file

@ -0,0 +1,11 @@
description = """\
Smack experimental extensions.
Classes and methods for XEPs that are in status 'experimental' or that should
otherwise carefully considered for deployment. The API may change even
between patch versions."""
dependencies {
compile project(':smack-core')
compile project(':smack-extensions')
testCompile project(':smack-core').sourceSets.test.runtimeClasspath
}

View file

@ -0,0 +1,33 @@
/**
*
* Copyright 2013 Robin Collier
*
* 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;
import org.jivesoftware.smack.initializer.UrlProviderFileInitializer;
/**
* Initializes the providers in the experimental code stream.
*
* @author Robin Collier
*
*/
public class ExperimentalProviderInitializer extends UrlProviderFileInitializer {
@Override
protected String getFilePath() {
return "classpath:org.jivesoftware.smackx/experimental.providers";
}
}

View file

@ -0,0 +1,54 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.initializer.SmackInitializer;
import org.jivesoftware.smack.util.FileUtils;
import java.io.InputStream;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* {@link SmackInitializer} implementation for experimental module.
*/
public class ExperimentalStartupClasses implements SmackInitializer {
private static final String EXTENSIONS_XML = "classpath:org.jivesoftware.smackx/extensions.xml";
private List<Exception> exceptions = new LinkedList<Exception>();
// TODO log
@Override
public void initialize() {
InputStream is;
try {
is = FileUtils.getStreamForUrl(EXTENSIONS_XML, null);
SmackConfiguration.processConfigFile(is, exceptions);;
}
catch (Exception e) {
exceptions.add(e);
}
}
@Override
public List<Exception> getExceptions() {
return Collections.unmodifiableList(exceptions);
}
}

View file

@ -0,0 +1,208 @@
/**
*
* Copyright 2013 Georg Lukas
*
* 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.carbons;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.filter.IQReplyFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
/**
* Packet extension for XEP-0280: Message Carbons. This class implements
* the manager for registering {@link CarbonExtension} support, enabling and disabling
* message carbons.
*
* You should call enableCarbons() before sending your first undirected
* presence.
*
* @author Georg Lukas
*/
public class CarbonManager extends Manager {
private static Map<XMPPConnection, CarbonManager> instances =
Collections.synchronizedMap(new WeakHashMap<XMPPConnection, CarbonManager>());
static {
XMPPConnection.addConnectionCreationListener(new ConnectionCreationListener() {
public void connectionCreated(XMPPConnection connection) {
getInstanceFor(connection);
}
});
}
private volatile boolean enabled_state = false;
private CarbonManager(XMPPConnection connection) {
super(connection);
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
sdm.addFeature(CarbonExtension.NAMESPACE);
instances.put(connection, this);
}
/**
* Obtain the CarbonManager responsible for a connection.
*
* @param connection the connection object.
*
* @return a CarbonManager instance
*/
public static synchronized CarbonManager getInstanceFor(XMPPConnection connection) {
CarbonManager carbonManager = instances.get(connection);
if (carbonManager == null) {
carbonManager = new CarbonManager(connection);
}
return carbonManager;
}
private IQ carbonsEnabledIQ(final boolean new_state) {
IQ setIQ = new IQ() {
public String getChildElementXML() {
return "<" + (new_state? "enable" : "disable") + " xmlns='" + CarbonExtension.NAMESPACE + "'/>";
}
};
setIQ.setType(IQ.Type.SET);
return setIQ;
}
/**
* Returns true if XMPP Carbons are supported by the server.
*
* @return true if supported
* @throws SmackException if there was no response from the server.
* @throws XMPPException
*/
public boolean isSupportedByServer() throws XMPPException, SmackException {
return ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(
connection().getServiceName(), CarbonExtension.NAMESPACE);
}
/**
* Notify server to change the carbons state. This method returns
* immediately and changes the variable when the reply arrives.
*
* You should first check for support using isSupportedByServer().
*
* @param new_state whether carbons should be enabled or disabled
* @throws NotConnectedException
*/
public void sendCarbonsEnabled(final boolean new_state) throws NotConnectedException {
IQ setIQ = carbonsEnabledIQ(new_state);
connection().addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
IQ result = (IQ)packet;
if (result.getType() == IQ.Type.RESULT) {
enabled_state = new_state;
}
connection().removePacketListener(this);
}
}, new IQReplyFilter(setIQ, connection()));
connection().sendPacket(setIQ);
}
/**
* Notify server to change the carbons state. This method blocks
* some time until the server replies to the IQ and returns true on
* success.
*
* You should first check for support using isSupportedByServer().
*
* @param new_state whether carbons should be enabled or disabled
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
*
*/
public synchronized void setCarbonsEnabled(final boolean new_state) throws NoResponseException,
XMPPErrorException, NotConnectedException {
if (enabled_state == new_state)
return;
IQ setIQ = carbonsEnabledIQ(new_state);
connection().createPacketCollectorAndSend(setIQ).nextResultOrThrow();
enabled_state = new_state;
}
/**
* Helper method to enable carbons.
*
* @throws XMPPException
* @throws SmackException if there was no response from the server.
*/
public void enableCarbons() throws XMPPException, SmackException {
setCarbonsEnabled(true);
}
/**
* Helper method to disable carbons.
*
* @throws XMPPException
* @throws SmackException if there was no response from the server.
*/
public void disableCarbons() throws XMPPException, SmackException {
setCarbonsEnabled(false);
}
/**
* Check if carbons are enabled on this connection.
*/
public boolean getCarbonsEnabled() {
return this.enabled_state;
}
/**
* Obtain a Carbon from a message, if available.
*
* @param msg Message object to check for carbons
*
* @return a Carbon if available, null otherwise.
*/
public static CarbonExtension getCarbon(Message msg) {
CarbonExtension cc = (CarbonExtension)msg.getExtension("received", CarbonExtension.NAMESPACE);
if (cc == null)
cc = (CarbonExtension)msg.getExtension("sent", CarbonExtension.NAMESPACE);
return cc;
}
/**
* Mark a message as "private", so it will not be carbon-copied.
*
* @param msg Message object to mark private
*/
public static void disableCarbons(Message msg) {
msg.addExtension(new CarbonExtension.Private());
}
}

View file

@ -0,0 +1,117 @@
/**
*
* Copyright 2013 Georg Lukas
*
* 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.carbons.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smackx.forward.Forwarded;
/**
* Packet extension for XEP-0280: Message Carbons. The extension
* <a href="http://xmpp.org/extensions/xep-0280.html">XEP-0280</a> is
* meant to synchronize a message flow to multiple presences of a user.
*
* <p>
* It accomplishes this by wrapping a {@link Forwarded} packet in a <b>sent</b>
* or <b>received</b> element
*
* @author Georg Lukas
*/
public class CarbonExtension implements PacketExtension {
public static final String NAMESPACE = "urn:xmpp:carbons:2";
private Direction dir;
private Forwarded fwd;
/**
* Construct a Carbon message extension.
*
* @param dir Determines if the carbon is being sent/received
* @param fwd The forwarded message.
*/
public CarbonExtension(Direction dir, Forwarded fwd) {
this.dir = dir;
this.fwd = fwd;
}
/**
* Get the direction (sent or received) of the carbon.
*
* @return the {@link Direction} of the carbon.
*/
public Direction getDirection() {
return dir;
}
/**
* Get the forwarded packet.
*
* @return the {@link Forwarded} message contained in this Carbon.
*/
public Forwarded getForwarded() {
return fwd;
}
@Override
public String getElementName() {
return dir.toString();
}
@Override
public String getNamespace() {
return NAMESPACE;
}
@Override
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(getElementName()).append(" xmlns=\"")
.append(getNamespace()).append("\">");
buf.append(fwd.toXML());
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
/**
* Defines the direction of a {@link CarbonExtension} message.
*/
public static enum Direction {
received,
sent
}
/**
* Packet extension indicating that a message may not be carbon-copied. Adding this
* extension to any message will disallow that message from being copied.
*/
public static class Private implements PacketExtension {
public static final String ELEMENT = "private";
public String getElementName() {
return ELEMENT;
}
public String getNamespace() {
return CarbonExtension.NAMESPACE;
}
public String toXML() {
return "<" + ELEMENT + " xmlns=\"" + CarbonExtension.NAMESPACE + "\"/>";
}
}
}

View file

@ -0,0 +1,53 @@
/**
*
* Copyright 2013 Georg Lukas
*
* 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.carbons.provider;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension.Direction;
import org.jivesoftware.smackx.forward.Forwarded;
import org.xmlpull.v1.XmlPullParser;
/**
* This class implements the {@link PacketExtensionProvider} to parse
* cabon copied messages from a packet. It will return a {@link CarbonExtension} packet extension.
*
* @author Georg Lukas
*
*/
public class CarbonManagerProvider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
Direction dir = Direction.valueOf(parser.getName());
Forwarded fwd = null;
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG && parser.getName().equals("forwarded")) {
fwd = (Forwarded) PacketParserUtils.parsePacketExtension(Forwarded.ELEMENT_NAME, Forwarded.NAMESPACE, parser);
}
else if (eventType == XmlPullParser.END_TAG && dir == Direction.valueOf(parser.getName()))
done = true;
}
if (fwd == null)
throw new Exception("sent/received must contain exactly one <forwarded> tag");
return new CarbonExtension(dir, fwd);
}
}

View file

@ -0,0 +1,61 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
/**
* Manager for HTTP ove XMPP transport (XEP-0332) extension.
*
* @author Andriy Tsykholyas
* @see <a href="http://xmpp.org/extensions/xep-0332.html">XEP-0332: HTTP over XMPP transport</a>
*/
public class HOXTManager {
/**
* Namespace for this extension.
*/
public static final String NAMESPACE = "urn:xmpp:http";
static {
XMPPConnection.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(NAMESPACE);
}
});
}
/**
* Returns true if the given entity understands the HTTP ove XMPP transport format and allows the exchange of such.
*
* @param jid jid
* @param connection connection
* @return true if the given entity understands the HTTP ove XMPP transport format and exchange.
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
*/
public static boolean isSupported(String jid, XMPPConnection connection) throws NoResponseException, XMPPErrorException, NotConnectedException {
return ServiceDiscoveryManager.getInstanceFor(connection).supportsFeature(jid, NAMESPACE);
}
}

View file

@ -0,0 +1,361 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smackx.shim.packet.HeadersExtension;
/**
* Abstract parent for Req and Resp IQ packets.
*
* @author Andriy Tsykholyas
* @see <a href="http://xmpp.org/extensions/xep-0332.html">XEP-0332: HTTP over XMPP transport</a>
*/
public abstract class AbstractHttpOverXmpp extends IQ {
/**
* Abstract representation of parent of Req and Resp elements.
*/
public static abstract class AbstractBody {
private HeadersExtension headers;
private Data data;
protected String version;
/**
* Returns string containing xml representation of this object.
*
* @return xml representation of this object
*/
public String toXML() {
StringBuilder builder = new StringBuilder();
builder.append(getStartTag());
builder.append(headers.toXML());
builder.append(data.toXML());
builder.append(getEndTag());
return builder.toString();
}
/**
* Returns start tag.
*
* @return start tag
*/
protected abstract String getStartTag();
/**
* Returns end tag.
*
* @return end tag
*/
protected abstract String getEndTag();
/**
* Returns version attribute.
*
* @return version attribute
*/
public String getVersion() {
return version;
}
/**
* Sets version attribute.
*
* @param version version attribute
*/
public void setVersion(String version) {
this.version = version;
}
/**
* Returns Headers element.
*
* @return Headers element
*/
public HeadersExtension getHeaders() {
return headers;
}
/**
* Sets Headers element.
*
* @param headers Headers element
*/
public void setHeaders(HeadersExtension headers) {
this.headers = headers;
}
/**
* Returns Data element.
*
* @return Data element
*/
public Data getData() {
return data;
}
/**
* Sets Data element.
*
* @param data Headers element
*/
public void setData(Data data) {
this.data = data;
}
}
/**
* Representation of Data element.<p>
* This class is immutable.
*/
public static class Data {
private final DataChild child;
/**
* Creates Data element.
*
* @param child element nested by Data
*/
public Data(DataChild child) {
this.child = child;
}
/**
* Returns string containing xml representation of this object.
*
* @return xml representation of this object
*/
public String toXML() {
StringBuilder builder = new StringBuilder();
builder.append("<data>");
builder.append(child.toXML());
builder.append("</data>");
return builder.toString();
}
/**
* Returns element nested by Data.
*
* @return element nested by Data
*/
public DataChild getChild() {
return child;
}
}
/**
* Interface for child elements of Data element.
*/
public static interface DataChild {
/**
* Returns string containing xml representation of this object.
*
* @return xml representation of this object
*/
public String toXML();
}
/**
* Representation of Text element.<p>
* This class is immutable.
*/
public static class Text implements DataChild {
private final String text;
/**
* Creates this element.
*
* @param text value of text
*/
public Text(String text) {
this.text = text;
}
@Override
public String toXML() {
StringBuilder builder = new StringBuilder();
builder.append("<text>");
if (text != null) {
builder.append(text);
}
builder.append("</text>");
return builder.toString();
}
/**
* Returns text of this element.
*
* @return text
*/
public String getText() {
return text;
}
}
/**
* Representation of Base64 element.<p>
* This class is immutable.
*/
public static class Base64 implements DataChild {
private final String text;
/**
* Creates this element.
*
* @param text value of text
*/
public Base64(String text) {
this.text = text;
}
@Override
public String toXML() {
StringBuilder builder = new StringBuilder();
builder.append("<base64>");
if (text != null) {
builder.append(text);
}
builder.append("</base64>");
return builder.toString();
}
/**
* Returns text of this element.
*
* @return text
*/
public String getText() {
return text;
}
}
/**
* Representation of Xml element.<p>
* This class is immutable.
*/
public static class Xml implements DataChild {
private final String text;
/**
* Creates this element.
*
* @param text value of text
*/
public Xml(String text) {
this.text = text;
}
@Override
public String toXML() {
StringBuilder builder = new StringBuilder();
builder.append("<xml>");
if (text != null) {
builder.append(text);
}
builder.append("</xml>");
return builder.toString();
}
/**
* Returns text of this element.
*
* @return text
*/
public String getText() {
return text;
}
}
/**
* Representation of ChunkedBase64 element.<p>
* This class is immutable.
*/
public static class ChunkedBase64 implements DataChild {
private final String streamId;
/**
* Creates ChunkedBase86 element.
*
* @param streamId streamId attribute
*/
public ChunkedBase64(String streamId) {
this.streamId = streamId;
}
@Override
public String toXML() {
StringBuilder builder = new StringBuilder();
builder.append("<chunkedBase64 streamId='");
builder.append(streamId);
builder.append("'/>");
return builder.toString();
}
/**
* Returns streamId attribute.
*
* @return streamId attribute
*/
public String getStreamId() {
return streamId;
}
}
/**
* Representation of Ibb element.<p>
* This class is immutable.
*/
public static class Ibb implements DataChild {
private final String sid;
/**
* Creates Ibb element.
*
* @param sid sid attribute
*/
public Ibb(String sid) {
this.sid = sid;
}
@Override
public String toXML() {
StringBuilder builder = new StringBuilder();
builder.append("<ibb sid='");
builder.append(sid);
builder.append("'/>");
return builder.toString();
}
/**
* Returns sid attribute.
*
* @return sid attribute
*/
public String getSid() {
return sid;
}
}
}

View file

@ -0,0 +1,111 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smackx.hoxt.HOXTManager;
/**
* Packet extension for base64 binary chunks.<p>
* This class is immutable.
*
* @author Andriy Tsykholyas
* @see <a href="http://xmpp.org/extensions/xep-0332.html">XEP-0332: HTTP over XMPP transport</a>
*/
public class Base64BinaryChunk implements PacketExtension {
public static final String ELEMENT_CHUNK = "chunk";
public static final String ATTRIBUTE_STREAM_ID = "streamId";
public static final String ATTRIBUTE_LAST = "last";
private final String streamId;
private final boolean last;
private final String text;
/**
* Creates the extension.
*
* @param text value of text attribute
* @param streamId value of streamId attribute
* @param last value of last attribute
*/
public Base64BinaryChunk(String text, String streamId, boolean last) {
this.text = text;
this.streamId = streamId;
this.last = last;
}
/**
* Creates the extension. Last attribute will be initialized with default value (false).
*
* @param text value of text attribute
* @param streamId value of streamId attribute
*/
public Base64BinaryChunk(String text, String streamId) {
this(text, streamId, false);
}
/**
* Returns streamId attribute.
*
* @return streamId attribute
*/
public String getStreamId() {
return streamId;
}
/**
* Returns last attribute.
*
* @return last attribute
*/
public boolean isLast() {
return last;
}
/**
* Returns text attribute.
*
* @return text attribute
*/
public String getText() {
return text;
}
@Override
public String getElementName() {
return ELEMENT_CHUNK;
}
@Override
public String getNamespace() {
return HOXTManager.NAMESPACE;
}
@Override
public String toXML() {
StringBuilder builder = new StringBuilder();
builder.append("<chunk xmlns='urn:xmpp:http' streamId='");
builder.append(streamId);
builder.append("' last='");
builder.append(Boolean.toString(last));
builder.append("'>");
builder.append(text);
builder.append("</chunk>");
return builder.toString();
}
}

View file

@ -0,0 +1,34 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.packet;
/**
* Enum containing HTTP methods.
*
* @author Andriy Tsykholyas
* @see <a href="http://xmpp.org/extensions/xep-0332.html">XEP-0332: HTTP over XMPP transport</a>
*/
public enum HttpMethod {
OPTIONS,
GET,
HEAD,
POST,
PUT,
DELETE,
TRACE,
PATCH
}

View file

@ -0,0 +1,203 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.packet;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.hoxt.HOXTManager;
/**
* Represents Req IQ packet.
*
* @author Andriy Tsykholyas
* @see <a href="http://xmpp.org/extensions/xep-0332.html">XEP-0332: HTTP over XMPP transport</a>
*/
public class HttpOverXmppReq extends AbstractHttpOverXmpp {
private Req req;
@Override
public String getChildElementXML() {
return req.toXML();
}
/**
* Returns Req element.
*
* @return Req element
*/
public Req getReq() {
return req;
}
/**
* Sets Req element.
*
* @param req Req element
*/
public void setReq(Req req) {
this.req = req;
}
/**
* Represents Req element.
*/
public static class Req extends AbstractBody {
private HttpMethod method;
private String resource;
// TODO: validate: xs:minInclusive value='256' xs:maxInclusive value='65536'
private int maxChunkSize = 0; // 0 means not set
private boolean sipub = true;
private boolean ibb = true;
private boolean jingle = true;
/**
* Creates this object.
*
* @param method method attribute
* @param resource resource attribute
*/
public Req(HttpMethod method, String resource) {
this.method = method;
this.resource = resource;
}
@Override
protected String getStartTag() {
StringBuilder builder = new StringBuilder();
builder.append("<req");
builder.append(" ");
builder.append("xmlns='").append(HOXTManager.NAMESPACE).append("'");
builder.append(" ");
builder.append("method='").append(method.toString()).append("'");
builder.append(" ");
builder.append("resource='").append(StringUtils.escapeForXML(resource)).append("'");
builder.append(" ");
builder.append("version='").append(StringUtils.escapeForXML(version)).append("'");
if (maxChunkSize != 0) {
builder.append(" ");
builder.append("maxChunkSize='").append(Integer.toString(maxChunkSize)).append("'");
}
builder.append(" ");
builder.append("sipub='").append(Boolean.toString(sipub)).append("'");
builder.append(" ");
builder.append("ibb='").append(Boolean.toString(ibb)).append("'");
builder.append(" ");
builder.append("jingle='").append(Boolean.toString(jingle)).append("'");
builder.append(">");
return builder.toString();
}
@Override
protected String getEndTag() {
return "</req>";
}
/**
* Returns method attribute.
*
* @return method attribute
*/
public HttpMethod getMethod() {
return method;
}
/**
* Returns resource attribute.
*
* @return resource attribute
*/
public String getResource() {
return resource;
}
/**
* Returns maxChunkSize attribute.
*
* @return maxChunkSize attribute
*/
public int getMaxChunkSize() {
return maxChunkSize;
}
/**
* Sets maxChunkSize attribute.
*
* @param maxChunkSize maxChunkSize attribute
*/
public void setMaxChunkSize(int maxChunkSize) {
this.maxChunkSize = maxChunkSize;
}
/**
* Returns sipub attribute.
*
* @return sipub attribute
*/
public boolean isSipub() {
return sipub;
}
/**
* Sets sipub attribute.
*
* @param sipub sipub attribute
*/
public void setSipub(boolean sipub) {
this.sipub = sipub;
}
/**
* Returns ibb attribute.
*
* @return ibb attribute
*/
public boolean isIbb() {
return ibb;
}
/**
* Sets ibb attribute.
*
* @param ibb ibb attribute
*/
public void setIbb(boolean ibb) {
this.ibb = ibb;
}
/**
* Returns jingle attribute.
*
* @return jingle attribute
*/
public boolean isJingle() {
return jingle;
}
/**
* Sets jingle attribute.
*
* @param jingle jingle attribute
*/
public void setJingle(boolean jingle) {
this.jingle = jingle;
}
}
}

View file

@ -0,0 +1,122 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.packet;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.hoxt.HOXTManager;
/**
* Represents Resp IQ packet.
*
* @author Andriy Tsykholyas
* @see <a href="http://xmpp.org/extensions/xep-0332.html">XEP-0332: HTTP over XMPP transport</a>
*/
public class HttpOverXmppResp extends AbstractHttpOverXmpp {
private Resp resp;
@Override
public String getChildElementXML() {
return resp.toXML();
}
/**
* Returns Resp element.
*
* @return Resp element
*/
public Resp getResp() {
return resp;
}
/**
* Sets Resp element.
*
* @param resp Resp element
*/
public void setResp(Resp resp) {
this.resp = resp;
}
/**
* Represents Resp element.
*/
public static class Resp extends AbstractBody {
private int statusCode;
private String statusMessage = null;
@Override
protected String getStartTag() {
StringBuilder builder = new StringBuilder();
builder.append("<resp");
builder.append(" ");
builder.append("xmlns='").append(HOXTManager.NAMESPACE).append("'");
builder.append(" ");
builder.append("version='").append(StringUtils.escapeForXML(version)).append("'");
builder.append(" ");
builder.append("statusCode='").append(Integer.toString(statusCode)).append("'");
if (statusMessage != null) {
builder.append(" ");
builder.append("statusMessage='").append(StringUtils.escapeForXML(statusMessage)).append("'");
}
builder.append(">");
return builder.toString();
}
@Override
protected String getEndTag() {
return "</resp>";
}
/**
* Returns statusCode attribute.
*
* @return statusCode attribute
*/
public int getStatusCode() {
return statusCode;
}
/**
* Sets statusCode attribute.
*
* @param statusCode statusCode attribute
*/
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
/**
* Returns statusMessage attribute.
*
* @return statusMessage attribute
*/
public String getStatusMessage() {
return statusMessage;
}
/**
* Sets statusMessage attribute.
*
* @param statusMessage statusMessage attribute
*/
public void setStatusMessage(String statusMessage) {
this.statusMessage = statusMessage;
}
}
}

View file

@ -0,0 +1,298 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.provider;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.hoxt.packet.AbstractHttpOverXmpp;
import org.jivesoftware.smackx.shim.packet.Header;
import org.jivesoftware.smackx.shim.packet.HeadersExtension;
import org.jivesoftware.smackx.shim.provider.HeaderProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.HashSet;
import java.util.Set;
/**
* Abstract parent for Req and Resp packet providers.
*
* @author Andriy Tsykholyas
* @see <a href="http://xmpp.org/extensions/xep-0332.html">XEP-0332: HTTP over XMPP transport</a>
*/
public abstract class AbstractHttpOverXmppProvider implements IQProvider {
private static final String ELEMENT_HEADERS = "headers";
private static final String ELEMENT_HEADER = "header";
private static final String ELEMENT_DATA = "data";
private static final String ELEMENT_TEXT = "text";
private static final String ELEMENT_BASE_64 = "base64";
private static final String ELEMENT_CHUNKED_BASE_64 = "chunkedBase64";
private static final String ELEMENT_XML = "xml";
static final String ELEMENT_IBB = "ibb";
static final String ELEMENT_SIPUB = "sipub";
static final String ELEMENT_JINGLE = "jingle";
private static final String ATTRIBUTE_STREAM_ID = "streamId";
private static final String ATTRIBUTE_SID = "sid";
static final String ATTRIBUTE_VERSION = "version";
/**
* Parses Headers and Data elements.
*
* @param parser parser
* @param elementName name of concrete implementation of this element
* @param body parent Body element
* @throws Exception if anything goes wrong
*/
protected void parseHeadersAndData(XmlPullParser parser, String elementName, AbstractHttpOverXmpp.AbstractBody body) throws Exception {
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals(ELEMENT_HEADERS)) {
HeadersExtension headersExtension = parseHeaders(parser);
body.setHeaders(headersExtension);
} else if (parser.getName().endsWith(ELEMENT_DATA)) {
AbstractHttpOverXmpp.Data data = parseData(parser);
body.setData(data);
} else {
throw new IllegalArgumentException("unexpected tag:" + parser.getName() + "'");
}
} else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(elementName)) {
done = true;
}
}
}
}
private HeadersExtension parseHeaders(XmlPullParser parser) throws Exception {
HeaderProvider provider = new HeaderProvider();
Set<Header> set = new HashSet<Header>();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals(ELEMENT_HEADER)) {
Header header = (Header) provider.parseExtension(parser);
set.add(header);
}
} else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_HEADERS)) {
done = true;
}
}
}
return new HeadersExtension(set);
}
private AbstractHttpOverXmpp.Data parseData(XmlPullParser parser) throws Exception {
AbstractHttpOverXmpp.DataChild child = null;
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals(ELEMENT_TEXT)) {
child = parseText(parser);
} else if (parser.getName().equals(ELEMENT_BASE_64)) {
child = parseBase64(parser);
} else if (parser.getName().equals(ELEMENT_CHUNKED_BASE_64)) {
child = parseChunkedBase64(parser);
} else if (parser.getName().equals(ELEMENT_XML)) {
child = parseXml(parser);
} else if (parser.getName().equals(ELEMENT_IBB)) {
child = parseIbb(parser);
} else if (parser.getName().equals(ELEMENT_SIPUB)) {
// TODO: sipub is allowed by xep-0332, but is not implemented yet
throw new UnsupportedOperationException("sipub is not supported yet");
} else if (parser.getName().equals(ELEMENT_JINGLE)) {
// TODO: jingle is allowed by xep-0332, but is not implemented yet
throw new UnsupportedOperationException("jingle is not supported yet");
} else {
// other elements are not allowed
throw new IllegalArgumentException("unsupported child tag: " + parser.getName());
}
} else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_DATA)) {
done = true;
}
}
}
AbstractHttpOverXmpp.Data data = new AbstractHttpOverXmpp.Data(child);
return data;
}
private AbstractHttpOverXmpp.Text parseText(XmlPullParser parser) throws Exception {
String text = null;
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_TEXT)) {
done = true;
} else {
throw new IllegalArgumentException("unexpected end tag of: " + parser.getName());
}
} else if (eventType == XmlPullParser.TEXT) {
text = parser.getText();
} else {
throw new IllegalArgumentException("unexpected eventType: " + eventType);
}
}
return new AbstractHttpOverXmpp.Text(text);
}
private AbstractHttpOverXmpp.Xml parseXml(XmlPullParser parser) throws Exception {
StringBuilder builder = new StringBuilder();
boolean done = false;
boolean startClosed = true;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.END_TAG) && parser.getName().equals(ELEMENT_XML)) {
done = true;
} else { // just write everything else as text
if (eventType == XmlPullParser.START_TAG) {
if (!startClosed) {
builder.append('>');
}
builder.append('<');
builder.append(parser.getName());
appendXmlAttributes(parser, builder);
startClosed = false;
} else if (eventType == XmlPullParser.END_TAG) {
if (startClosed) {
builder.append("</");
builder.append(parser.getName());
builder.append('>');
} else {
builder.append("/>");
startClosed = true;
}
} else if (eventType == XmlPullParser.TEXT) {
if (!startClosed) {
builder.append('>');
startClosed = true;
}
builder.append(StringUtils.escapeForXML(parser.getText()));
} else {
throw new IllegalArgumentException("unexpected eventType: " + eventType);
}
}
}
return new AbstractHttpOverXmpp.Xml(builder.toString());
}
private void appendXmlAttributes(XmlPullParser parser, StringBuilder builder) throws Exception {
// NOTE: for now we ignore namespaces
int count = parser.getAttributeCount();
if (count > 0) {
for (int i = 0; i < count; i++) {
builder.append(' ');
builder.append(parser.getAttributeName(i));
builder.append("=\"");
builder.append(StringUtils.escapeForXML(parser.getAttributeValue(i)));
builder.append('"');
}
}
}
private AbstractHttpOverXmpp.Base64 parseBase64(XmlPullParser parser) throws Exception {
String text = null;
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_BASE_64)) {
done = true;
} else {
throw new IllegalArgumentException("unexpected end tag of: " + parser.getName());
}
} else if (eventType == XmlPullParser.TEXT) {
text = parser.getText();
} else {
throw new IllegalArgumentException("unexpected eventType: " + eventType);
}
}
return new AbstractHttpOverXmpp.Base64(text);
}
private AbstractHttpOverXmpp.ChunkedBase64 parseChunkedBase64(XmlPullParser parser) throws Exception {
String streamId = parser.getAttributeValue("", ATTRIBUTE_STREAM_ID);
AbstractHttpOverXmpp.ChunkedBase64 child = new AbstractHttpOverXmpp.ChunkedBase64(streamId);
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_CHUNKED_BASE_64)) {
done = true;
} else {
throw new IllegalArgumentException("unexpected end tag: " + parser.getName());
}
} else {
throw new IllegalArgumentException("unexpected event type: " + eventType);
}
}
return child;
}
private AbstractHttpOverXmpp.Ibb parseIbb(XmlPullParser parser) throws Exception {
String sid = parser.getAttributeValue("", ATTRIBUTE_SID);
AbstractHttpOverXmpp.Ibb child = new AbstractHttpOverXmpp.Ibb(sid);
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_IBB)) {
done = true;
} else {
throw new IllegalArgumentException("unexpected end tag: " + parser.getName());
}
} else {
throw new IllegalArgumentException("unexpected event type: " + eventType);
}
}
return child;
}
}

View file

@ -0,0 +1,69 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.provider;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smackx.hoxt.packet.Base64BinaryChunk;
import org.xmlpull.v1.XmlPullParser;
/**
* Packet provider for base64 binary chunks.
*
* @author Andriy Tsykholyas
* @see <a href="http://xmpp.org/extensions/xep-0332.html">XEP-0332: HTTP over XMPP transport</a>
*/
public class Base64BinaryChunkProvider implements PacketExtensionProvider {
/**
* Required no-argument constructor.
*/
public Base64BinaryChunkProvider() {
}
@Override
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
String streamId = parser.getAttributeValue("", Base64BinaryChunk.ATTRIBUTE_STREAM_ID);
String lastString = parser.getAttributeValue("", Base64BinaryChunk.ATTRIBUTE_LAST);
boolean last = false;
if (lastString != null) {
last = Boolean.parseBoolean(lastString);
}
String text = null;
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(Base64BinaryChunk.ELEMENT_CHUNK)) {
done = true;
} else {
throw new IllegalArgumentException("unexpected end tag of: " + parser.getName());
}
} else if (eventType == XmlPullParser.TEXT) {
text = parser.getText();
} else {
throw new IllegalArgumentException("unexpected eventType: " + eventType);
}
}
return new Base64BinaryChunk(text, streamId, last);
}
}

View file

@ -0,0 +1,87 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.provider;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smackx.hoxt.packet.HttpMethod;
import org.jivesoftware.smackx.hoxt.packet.HttpOverXmppReq;
import org.xmlpull.v1.XmlPullParser;
/**
* Req packet provider.
*
* @author Andriy Tsykholyas
* @see <a href="http://xmpp.org/extensions/xep-0332.html">XEP-0332: HTTP over XMPP transport</a>
*/
public class HttpOverXmppReqProvider extends AbstractHttpOverXmppProvider {
private static final String ELEMENT_REQ = "req";
private static final String ATTRIBUTE_METHOD = "method";
private static final String ATTRIBUTE_RESOURCE = "resource";
private static final String ATTRIBUTE_MAX_CHUNK_SIZE = "maxChunkSize";
/**
* Mandatory no argument constructor.
*/
public HttpOverXmppReqProvider() {
}
@Override
public IQ parseIQ(XmlPullParser parser) throws Exception {
String method = parser.getAttributeValue("", ATTRIBUTE_METHOD);
String resource = parser.getAttributeValue("", ATTRIBUTE_RESOURCE);
String version = parser.getAttributeValue("", ATTRIBUTE_VERSION);
String maxChunkSize = parser.getAttributeValue("", ATTRIBUTE_MAX_CHUNK_SIZE);
HttpMethod reqMethod = HttpMethod.valueOf(method);
HttpOverXmppReq.Req req = new HttpOverXmppReq.Req(reqMethod, resource);
req.setVersion(version);
Boolean sipub = true;
Boolean jingle = true;
Boolean ibb = true;
String sipubStr = parser.getAttributeValue("", AbstractHttpOverXmppProvider.ELEMENT_SIPUB);
String ibbStr = parser.getAttributeValue("", AbstractHttpOverXmppProvider.ELEMENT_IBB);
String jingleStr = parser.getAttributeValue("", AbstractHttpOverXmppProvider.ELEMENT_JINGLE);
if (sipubStr != null) {
sipub = Boolean.valueOf(sipubStr);
}
if (ibbStr != null) {
ibb = Boolean.valueOf(ibbStr);
}
if (jingleStr != null) {
jingle = Boolean.valueOf(jingleStr);
}
req.setIbb(ibb);
req.setSipub(sipub);
req.setJingle(jingle);
if (maxChunkSize != null) {
int maxChunkSizeValue = Integer.parseInt(maxChunkSize);
req.setMaxChunkSize(maxChunkSizeValue);
}
parseHeadersAndData(parser, ELEMENT_REQ, req);
HttpOverXmppReq packet = new HttpOverXmppReq();
packet.setReq(req);
return packet;
}
}

View file

@ -0,0 +1,60 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.provider;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smackx.hoxt.packet.HttpOverXmppResp;
import org.xmlpull.v1.XmlPullParser;
/**
* Resp packet provider.
*
* @author Andriy Tsykholyas
* @see <a href="http://xmpp.org/extensions/xep-0332.html">XEP-0332: HTTP over XMPP transport</a>
*/
public class HttpOverXmppRespProvider extends AbstractHttpOverXmppProvider {
private static final String ELEMENT_RESP = "resp";
private static final String ATTRIBUTE_STATUS_MESSAGE = "statusMessage";
private static final String ATTRIBUTE_STATUS_CODE = "statusCode";
/**
* Mandatory no argument constructor.
*/
public HttpOverXmppRespProvider() {
}
@Override
public IQ parseIQ(XmlPullParser parser) throws Exception {
String version = parser.getAttributeValue("", ATTRIBUTE_VERSION);
String statusMessage = parser.getAttributeValue("", ATTRIBUTE_STATUS_MESSAGE);
String statusCodeString = parser.getAttributeValue("", ATTRIBUTE_STATUS_CODE);
int statusCode = Integer.parseInt(statusCodeString);
HttpOverXmppResp.Resp resp = new HttpOverXmppResp.Resp();
resp.setVersion(version);
resp.setStatusMessage(statusMessage);
resp.setStatusCode(statusCode);
parseHeadersAndData(parser, ELEMENT_RESP, resp);
HttpOverXmppResp packet = new HttpOverXmppResp();
packet.setResp(resp);
return packet;
}
}

View file

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<!-- Providers for workgroup extensions -->
<smackProviders>
<!-- XEP-0332 HTTP over XMPP transport -->
<iqProvider>
<elementName>req</elementName>
<namespace>urn:xmpp:http</namespace>
<className>org.jivesoftware.smackx.hoxt.provider.HttpOverXmppReqProvider</className>
</iqProvider>
<iqProvider>
<elementName>resp</elementName>
<namespace>urn:xmpp:http</namespace>
<className>org.jivesoftware.smackx.hoxt.provider.HttpOverXmppRespProvider</className>
</iqProvider>
<extensionProvider>
<elementName>chunk</elementName>
<namespace>urn:xmpp:http</namespace>
<className>org.jivesoftware.smackx.hoxt.provider.Base64BinaryChunkProvider</className>
</extensionProvider>
<!-- XEP-0280 Message Carbons -->
<extensionProvider>
<elementName>sent</elementName>
<namespace>urn:xmpp:carbons:2</namespace>
<className>org.jivesoftware.smackx.carbons.provider.CarbonManagerProvider</className>
</extensionProvider>
<extensionProvider>
<elementName>received</elementName>
<namespace>urn:xmpp:carbons:2</namespace>
<className>org.jivesoftware.smackx.carbons.provider.CarbonManagerProvider</className>
</extensionProvider>
</smackProviders>

View file

@ -0,0 +1,5 @@
<smack>
<startupClasses>
<className>org.jivesoftware.smackx.hoxt.HOXTManager</className>
</startupClasses>
</smack>

View file

@ -0,0 +1,31 @@
/**
*
* Copyright © 2014 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;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class ExperimentalProviderInitializerTest {
@Test
public void testExperimentalProviderInitialzer() {
ExperimentalProviderInitializer epi = new ExperimentalProviderInitializer();
epi.initialize();
assertTrue(epi.getExceptions().size() == 0);
}
}

View file

@ -0,0 +1,114 @@
/**
*
* Copyright the original author or authors
*
* 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.carbons;
import static org.junit.Assert.assertEquals;
import java.util.Properties;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
import org.jivesoftware.smackx.carbons.provider.CarbonManagerProvider;
import org.jivesoftware.smackx.forward.Forwarded;
import org.jivesoftware.smackx.forward.provider.ForwardedProvider;
import org.junit.BeforeClass;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
import com.jamesmurty.utils.XMLBuilder;
public class CarbonTest {
private static Properties outputProperties = new Properties();
static {
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
}
@BeforeClass
public static void setup() {
ProviderManager.getInstance().addExtensionProvider("forwarded", "urn:xmpp:forward:0", new ForwardedProvider());
}
@Test
public void carbonSentTest() throws Exception {
XmlPullParser parser;
String control;
CarbonExtension cc;
Forwarded fwd;
control = XMLBuilder.create("sent")
.e("forwarded")
.a("xmlns", "urn:xmpp:forwarded:0")
.e("message")
.a("from", "romeo@montague.com")
.asString(outputProperties);
parser = TestUtils.getParser(control, "sent");
cc = (CarbonExtension) new CarbonManagerProvider().parseExtension(parser);
fwd = cc.getForwarded();
// meta
assertEquals(CarbonExtension.Direction.sent, cc.getDirection());
// no delay in packet
assertEquals(null, fwd.getDelayInfo());
// check message
assertEquals("romeo@montague.com", fwd.getForwardedPacket().getFrom());
// check end of tag
assertEquals(XmlPullParser.END_TAG, parser.getEventType());
assertEquals("sent", parser.getName());
}
@Test
public void carbonReceivedTest() throws Exception {
XmlPullParser parser;
String control;
CarbonExtension cc;
control = XMLBuilder.create("received")
.e("forwarded")
.a("xmlns", "urn:xmpp:forwarded:0")
.e("message")
.a("from", "romeo@montague.com")
.asString(outputProperties);
parser = TestUtils.getParser(control, "received");
cc = (CarbonExtension) new CarbonManagerProvider().parseExtension(parser);
assertEquals(CarbonExtension.Direction.received, cc.getDirection());
// check end of tag
assertEquals(XmlPullParser.END_TAG, parser.getEventType());
assertEquals("received", parser.getName());
}
@Test(expected=Exception.class)
public void carbonEmptyTest() throws Exception {
XmlPullParser parser;
String control;
control = XMLBuilder.create("sent")
.a("xmlns", "urn:xmpp:forwarded:0")
.asString(outputProperties);
parser = TestUtils.getParser(control, "sent");
new CarbonManagerProvider().parseExtension(parser);
}
}

View file

@ -0,0 +1,203 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.provider;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smackx.hoxt.packet.AbstractHttpOverXmpp;
import org.jivesoftware.smackx.hoxt.packet.HttpOverXmppReq;
import org.jivesoftware.smackx.hoxt.packet.HttpOverXmppResp;
import org.jivesoftware.smackx.shim.packet.Header;
import org.jivesoftware.smackx.shim.packet.HeadersExtension;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Tests correct headers and data parsing in 'req' and 'resp' elements.
*/
public class AbstractHttpOverXmppProviderTest {
@Test
public void areRespHeadersParsedCorrectly() throws Exception {
String string = "<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>"
+ "<headers xmlns='http://jabber.org/protocol/shim'>"
+ "<header name='Date'>Fri, 03 May 2013 13:52:10 GMT-4</header>"
+ "<header name='Allow'>OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE</header>"
+ "<header name='Content-Length'>0</header>"
+ "</headers>"
+ "</resp>";
Map<String, String> expectedHeaders = new HashMap<String, String>();
expectedHeaders.put("Date", "Fri, 03 May 2013 13:52:10 GMT-4");
expectedHeaders.put("Allow", "OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE");
expectedHeaders.put("Content-Length", "0");
AbstractHttpOverXmppProvider provider = new HttpOverXmppRespProvider();
XmlPullParser parser = TestUtils.getParser(string, "resp");
IQ iq = provider.parseIQ(parser);
assertTrue(iq instanceof HttpOverXmppResp);
AbstractHttpOverXmpp.AbstractBody body = ((HttpOverXmppResp) iq).getResp();
checkHeaders(body.getHeaders(), expectedHeaders);
}
@Test
public void areReqHeadersParsedCorrectly() throws Exception {
String string = "<req xmlns='urn:xmpp:http' method='GET' resource='/rdf/xep' version='1.1'>"
+ "<headers xmlns='http://jabber.org/protocol/shim'>"
+ "<header name='Host'>clayster.com</header>"
+ "</headers>"
+ "</req>";
Map<String, String> expectedHeaders = new HashMap<String, String>();
expectedHeaders.put("Host", "clayster.com");
AbstractHttpOverXmppProvider provider = new HttpOverXmppReqProvider();
XmlPullParser parser = TestUtils.getParser(string, "req");
IQ iq = provider.parseIQ(parser);
assertTrue(iq instanceof HttpOverXmppReq);
AbstractHttpOverXmpp.AbstractBody body = ((HttpOverXmppReq) iq).getReq();
checkHeaders(body.getHeaders(), expectedHeaders);
}
@Test
public void isTextDataParsedCorrectly() throws Exception {
String expectedText = "@prefix dc: <http://purl.org/dc/elements/1.1/>."
+ "@base <http://clayster.com/>."
+ "<xep> dc:title \"HTTP over XMPP\";"
+ "dc:creator <PeterWaher>;"
+ "dc:publisher <XSF>.";
String encodedText = "@prefix dc: &lt;http://purl.org/dc/elements/1.1/&gt;."
+ "@base &lt;http://clayster.com/&gt;."
+ "&lt;xep&gt; dc:title \"HTTP over XMPP\";"
+ "dc:creator &lt;PeterWaher&gt;;"
+ "dc:publisher &lt;XSF&gt;.";
String string = "<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>"
+ "<headers xmlns='http://jabber.org/protocol/shim'><header name='Server'>Clayster</header></headers>"
+ "<data><text>"
+ encodedText
+ "</text></data></resp>";
AbstractHttpOverXmpp.Text text = (AbstractHttpOverXmpp.Text) parseAbstractBody(
string, "resp").getData().getChild();
assertEquals(expectedText, text.getText());
}
@Test
public void isXmlDataParsedCorrectly() throws Exception {
String expectedXml = "<sparql><head><variable name=\"title\"/><variable name=\"creator\"/>" // no xmlns here
+ "</head><results><result>"
+ "<binding name=\"title\">"
+ "<literal>HTTP over XMPP</literal>"
+ "</binding>"
+ "<binding name=\"creator\">"
+ "<uri>http://clayster.com/PeterWaher</uri>"
+ "</binding>"
+ "</result>"
+ "</results>"
+ "</sparql>";
String encodedXml = "<sparql xmlns=\"http://www.w3.org/2005/sparql-results#\"><head><variable name=\"title\"/><variable name=\"creator\"/>"
+ "</head><results><result>"
+ "<binding name=\"title\">"
+ "<literal>HTTP over XMPP</literal>"
+ "</binding>"
+ "<binding name=\"creator\">"
+ "<uri>http://clayster.com/PeterWaher</uri>"
+ "</binding>"
+ "</result>"
+ "</results>"
+ "</sparql>";
String string = "<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>"
+ "<headers xmlns='http://jabber.org/protocol/shim'><header name='Server'>Clayster</header></headers>"
+ "<data><xml>"
+ encodedXml
+ "</xml></data></resp>";
AbstractHttpOverXmpp.Xml xmlProviderValue = (AbstractHttpOverXmpp.Xml) parseAbstractBody(
string, "resp").getData().getChild();
assertEquals(expectedXml, xmlProviderValue.getText());
}
@Test
public void isBase64DataParsedCorrectly() throws Exception {
String base64Data = "iVBORw0KGgoAAAANSUhEUgAAASwAAAGQCAYAAAAUdV17AAAAAXNSR0 ... tVWJd+e+y1AAAAABJRU5ErkJggg==";
String string = "<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>"
+ "<headers xmlns='http://jabber.org/protocol/shim'><header name='Server'>Clayster</header></headers>"
+ "<data><base64>"
+ base64Data
+ "</base64></data></resp>";
AbstractHttpOverXmpp.Base64 base64ProviderValue = (AbstractHttpOverXmpp.Base64) parseAbstractBody(
string, "resp").getData().getChild();
assertEquals(base64Data, base64ProviderValue.getText());
}
@Test
public void isChunkedBase64DataParsedCorrectly() throws Exception {
String streamId = "Stream0001";
String chunkBase64Data = " <chunkedBase64 streamId='" + streamId + "'/>";
String string = "<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>"
+ "<headers xmlns='http://jabber.org/protocol/shim'><header name='Server'>Clayster</header></headers>"
+ "<data>"
+ chunkBase64Data
+ "</data></resp>";
AbstractHttpOverXmpp.ChunkedBase64 chunkedBase64Value = (AbstractHttpOverXmpp.ChunkedBase64) parseAbstractBody(
string, "resp").getData().getChild();
assertEquals(streamId, chunkedBase64Value.getStreamId());
}
@Test
public void isIbbDataParsedCorrectly() throws Exception {
String sid = "Stream0002";
String ibbData = " <ibb sid='" + sid + "'/>";
String string = "<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>"
+ "<headers xmlns='http://jabber.org/protocol/shim'><header name='Server'>Clayster</header></headers>"
+ "<data>"
+ ibbData
+ "</data></resp>";
AbstractHttpOverXmpp.Ibb ibbValue = (AbstractHttpOverXmpp.Ibb) parseAbstractBody(
string, "resp").getData().getChild();
assertEquals(sid, ibbValue.getSid());
}
private AbstractHttpOverXmpp.AbstractBody parseAbstractBody(String string, String tag) throws Exception {
AbstractHttpOverXmppProvider provider = new HttpOverXmppRespProvider();
XmlPullParser parser = TestUtils.getParser(string, tag);
IQ iq = provider.parseIQ(parser);
assertTrue(iq instanceof HttpOverXmppResp);
AbstractHttpOverXmpp.AbstractBody body = ((HttpOverXmppResp) iq).getResp();
return body;
}
private void checkHeaders(HeadersExtension headers, Map<String, String> expectedHeaders) {
Collection<Header> collection = headers.getHeaders();
assertEquals(collection.size(), expectedHeaders.size());
for (Header header : collection) {
assertTrue(expectedHeaders.containsKey(header.getName()));
assertEquals(expectedHeaders.get(header.getName()), header.getValue());
}
}
}

View file

@ -0,0 +1,65 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.provider;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smackx.hoxt.packet.Base64BinaryChunk;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
import static org.junit.Assert.*;
/**
* Tests correct parsing of 'chunk' elements in Message stanza.
*/
public class Base64BinaryChunkProviderTest {
@Test
public void isNonLatsChunkParsedCorrectly() throws Exception {
String base64Text = "iVBORw0KGgoAAAANSUhEUgAAASwAAAGQCAYAA";
String string = "<chunk xmlns='urn:xmpp:http' streamId='Stream0001'>" + base64Text + "</chunk>";
Base64BinaryChunkProvider provider = new Base64BinaryChunkProvider();
XmlPullParser parser = TestUtils.getParser(string, "chunk");
PacketExtension extension = provider.parseExtension(parser);
assertTrue(extension instanceof Base64BinaryChunk);
Base64BinaryChunk chunk = (Base64BinaryChunk) extension;
assertEquals("Stream0001", chunk.getStreamId());
assertFalse(chunk.isLast());
assertEquals(base64Text, chunk.getText());
}
@Test
public void isLatsChunkParsedCorrectly() throws Exception {
String base64Text = "2uPzi9u+tVWJd+e+y1AAAAABJRU5ErkJggg==";
String string = "<chunk xmlns='urn:xmpp:http' streamId='Stream0001' last='true'>" + base64Text + "</chunk>";
Base64BinaryChunkProvider provider = new Base64BinaryChunkProvider();
XmlPullParser parser = TestUtils.getParser(string, "chunk");
PacketExtension extension = provider.parseExtension(parser);
assertTrue(extension instanceof Base64BinaryChunk);
Base64BinaryChunk chunk = (Base64BinaryChunk) extension;
assertEquals("Stream0001", chunk.getStreamId());
assertTrue(chunk.isLast());
assertEquals(base64Text, chunk.getText());
}
}

View file

@ -0,0 +1,76 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.provider;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smackx.hoxt.packet.HttpMethod;
import org.jivesoftware.smackx.hoxt.packet.HttpOverXmppReq;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class HttpOverXmppReqProviderTest {
@Test
public void areAllReqAttributesCorrectlyParsed() throws Exception {
String string = "<req xmlns='urn:xmpp:http' method='OPTIONS' resource='*' version='1.1'/>";
HttpOverXmppReq.Req req = parseReq(string);
assertEquals(req.getVersion(), "1.1");
assertEquals(req.getMethod(), HttpMethod.OPTIONS);
assertEquals(req.getResource(), "*");
}
@Test
public void areGetRequestAttributesCorrectlyParsed() throws Exception {
String string = "<req xmlns='urn:xmpp:http' method='GET' resource='/rdf/xep' version='1.1'/>";
HttpOverXmppReq.Req req = parseReq(string);
assertEquals(req.getVersion(), "1.1");
assertEquals(req.getMethod(), HttpMethod.GET);
assertEquals(req.getResource(), "/rdf/xep");
}
@Test
public void getReqOptionAttributesCorrectlyParsed() throws Exception {
String string = "<req xmlns='urn:xmpp:http' method='OPTIONS' resource='*' version='1.1' maxChunkSize='256' sipub='false' ibb='true' jingle='false'/>";
HttpOverXmppReq.Req req = parseReq(string);
assertEquals(req.getMaxChunkSize(), 256);
assertEquals(req.isSipub(), false);
assertEquals(req.isIbb(), true);
assertEquals(req.isJingle(), false);
}
@Test
public void getReqOptionalAttributesDefaultValues() throws Exception {
String string = "<req xmlns='urn:xmpp:http' method='OPTIONS' resource='*' version='1.1'/>";
HttpOverXmppReq.Req req = parseReq(string);
assertEquals(req.isSipub(), true);
assertEquals(req.isIbb(), true);
assertEquals(req.isJingle(), true);
}
private HttpOverXmppReq.Req parseReq(String string) throws Exception {
HttpOverXmppReqProvider provider = new HttpOverXmppReqProvider();
XmlPullParser parser = TestUtils.getParser(string, "req");
IQ iq = provider.parseIQ(parser);
assertTrue(iq instanceof HttpOverXmppReq);
HttpOverXmppReq castedIq = (HttpOverXmppReq) iq;
return castedIq.getReq();
}
}

View file

@ -0,0 +1,63 @@
/**
*
* Copyright 2014 Andriy Tsykholyas
*
* 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.hoxt.provider;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smackx.hoxt.packet.HttpOverXmppResp;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
import static org.junit.Assert.*;
/**
* Tests correct attribute parsing in 'resp' element.
*/
public class HttpOverXmppRespProviderTest {
@Test
public void areAllRespAttributesCorrectlyParsed() throws Exception {
String string = "<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'/>";
HttpOverXmppRespProvider provider = new HttpOverXmppRespProvider();
XmlPullParser parser = TestUtils.getParser(string, "resp");
IQ iq = provider.parseIQ(parser);
assertTrue(iq instanceof HttpOverXmppResp);
HttpOverXmppResp castedIq = (HttpOverXmppResp) iq;
HttpOverXmppResp.Resp resp = castedIq.getResp();
assertEquals(resp.getVersion(), "1.1");
assertEquals(resp.getStatusCode(), 200);
assertEquals(resp.getStatusMessage(), "OK");
}
@Test
public void areRespAttributesWothoutMessageCorrectlyParsed() throws Exception {
String string = "<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200'/>";
HttpOverXmppRespProvider provider = new HttpOverXmppRespProvider();
XmlPullParser parser = TestUtils.getParser(string, "resp");
IQ iq = provider.parseIQ(parser);
assertTrue(iq instanceof HttpOverXmppResp);
HttpOverXmppResp castedIq = (HttpOverXmppResp) iq;
HttpOverXmppResp.Resp resp = castedIq.getResp();
assertEquals(resp.getVersion(), "1.1");
assertEquals(resp.getStatusCode(), 200);
assertNull(resp.getStatusMessage());
}
}