Update HOXT API to use the buidler pattern.

This commit is contained in:
Tibo-lg 2015-06-29 12:10:01 +02:00 committed by Florian Schmaus
parent ebcbdb75cd
commit 4d57848a0f
6 changed files with 331 additions and 174 deletions

View File

@ -31,20 +31,25 @@ public abstract class AbstractHttpOverXmpp extends IQ {
public static final String NAMESPACE = "urn:xmpp:http";
protected AbstractHttpOverXmpp(String element) {
super(element, NAMESPACE);
}
private HeadersExtension headers;
private Data data;
protected String version;
protected AbstractHttpOverXmpp(String element, Builder<?, ?> builder) {
super(element, NAMESPACE);
this.headers = builder.headers;
this.data = builder.data;
this.version = builder.version;
}
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
IQChildElementXmlStringBuilder builder = getIQHoxtChildElementBuilder(xml);
builder.optAppend(headers.toXML());
builder.optAppend(data.toXML());
builder.optAppend(headers);
/* data cannot be fed to optAppend */
if (data != null) {
builder.optAppend(data.toXML());
}
return builder;
}
@ -64,15 +69,6 @@ public abstract class AbstractHttpOverXmpp extends IQ {
return version;
}
/**
* Sets version attribute.
*
* @param version version attribute
*/
public void setVersion(String version) {
this.version = version;
}
/**
* Returns Headers element.
*
@ -82,15 +78,6 @@ public abstract class AbstractHttpOverXmpp extends IQ {
return headers;
}
/**
* Sets Headers element.
*
* @param headers Headers element
*/
public void setHeaders(HeadersExtension headers) {
this.headers = headers;
}
/**
* Returns Data element.
*
@ -101,16 +88,65 @@ public abstract class AbstractHttpOverXmpp extends IQ {
}
/**
* Sets Data element.
* A builder for XMPP connection configurations.
* <p>
* See ConnectionConfiguration Buidler for more details.
* </p>
*
* @param data Headers element
* @param <B> the builder type parameter.
* @param <C> the resulting HttpOverXmpp IQ
*/
public void setData(Data data) {
this.data = data;
public static abstract class Builder<B extends Builder<B, C>, C extends AbstractHttpOverXmpp> {
private HeadersExtension headers;
private Data data;
private String version = "1.1";
/**
* Sets Data element.
*
* @param data Headers element
*
* @return the builder
*/
public B setData(Data data) {
this.data = data;
return getThis();
}
/**
* Sets Headers element.
*
* @param headers Headers element
*
* @return the builder
*/
public B setHeaders(HeadersExtension headers) {
this.headers = headers;
return getThis();
}
/**
* Sets version attribute.
*
* @param version version attribute
*
* @return the builder
*/
public B setVersion(String version) {
this.version = version;
return getThis();
}
public abstract C build();
protected abstract B getThis();
}
/**
* Representation of Data element.<p>
* Representation of Data element.
* <p>
* This class is immutable.
*/
public static class Data {
@ -150,7 +186,8 @@ public abstract class AbstractHttpOverXmpp extends IQ {
}
/**
* Representation of Text element.<p>
* Representation of Text element.
* <p>
* This class is immutable.
*/
public static class Text implements NamedElement {
@ -193,7 +230,8 @@ public abstract class AbstractHttpOverXmpp extends IQ {
}
/**
* Representation of Base64 element.<p>
* Representation of Base64 element.
* <p>
* This class is immutable.
*/
public static class Base64 implements NamedElement {
@ -236,7 +274,8 @@ public abstract class AbstractHttpOverXmpp extends IQ {
}
/**
* Representation of Xml element.<p>
* Representation of Xml element.
* <p>
* This class is immutable.
*/
public static class Xml implements NamedElement {
@ -279,7 +318,8 @@ public abstract class AbstractHttpOverXmpp extends IQ {
}
/**
* Representation of ChunkedBase64 element.<p>
* Representation of ChunkedBase64 element.
* <p>
* This class is immutable.
*/
public static class ChunkedBase64 implements NamedElement {
@ -321,7 +361,8 @@ public abstract class AbstractHttpOverXmpp extends IQ {
}
/**
* Representation of Ibb element.<p>
* Representation of Ibb element.
* <p>
* This class is immutable.
*/
public static class Ibb implements NamedElement {

View File

@ -24,15 +24,18 @@ import org.jivesoftware.smack.util.StringUtils;
* @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 {
public final class HttpOverXmppReq extends AbstractHttpOverXmpp {
public static final String ELEMENT = "req";
public HttpOverXmppReq(HttpMethod method, String resource) {
super(ELEMENT);
this.method = method;
this.resource = resource;
private HttpOverXmppReq(Builder builder) {
super(ELEMENT, builder);
this.method = builder.method;
this.resource = builder.resource;
this.maxChunkSize = builder.maxChunkSize;
this.ibb = builder.ibb;
this.jingle = builder.jingle;
this.sipub = builder.sipub;
setType(Type.set);
}
@ -40,12 +43,12 @@ public class HttpOverXmppReq extends AbstractHttpOverXmpp {
private String resource;
// TODO: validate: xs:minInclusive value='256' xs:maxInclusive value='65536'
private int maxChunkSize = 0; // 0 means not set
private int maxChunkSize; // 0 means not set
private boolean sipub = true;
private boolean sipub;
private boolean ibb = true;
private boolean jingle = true;
private boolean ibb;
private boolean jingle;
@Override
protected IQChildElementXmlStringBuilder getIQHoxtChildElementBuilder(IQChildElementXmlStringBuilder builder) {
@ -96,15 +99,6 @@ public class HttpOverXmppReq extends AbstractHttpOverXmpp {
return maxChunkSize;
}
/**
* Sets maxChunkSize attribute.
*
* @param maxChunkSize maxChunkSize attribute
*/
public void setMaxChunkSize(int maxChunkSize) {
this.maxChunkSize = maxChunkSize;
}
/**
* Returns sipub attribute.
*
@ -114,15 +108,6 @@ public class HttpOverXmppReq extends AbstractHttpOverXmpp {
return sipub;
}
/**
* Sets sipub attribute.
*
* @param sipub sipub attribute
*/
public void setSipub(boolean sipub) {
this.sipub = sipub;
}
/**
* Returns ibb attribute.
*
@ -132,15 +117,6 @@ public class HttpOverXmppReq extends AbstractHttpOverXmpp {
return ibb;
}
/**
* Sets ibb attribute.
*
* @param ibb ibb attribute
*/
public void setIbb(boolean ibb) {
this.ibb = ibb;
}
/**
* Returns jingle attribute.
*
@ -150,12 +126,119 @@ public class HttpOverXmppReq extends AbstractHttpOverXmpp {
return jingle;
}
public static Builder builder() {
return new Builder();
}
/**
* Sets jingle attribute.
*
* @param jingle jingle attribute
* A configuration builder for HttpOverXmppReq. Use {@link HttpOverXmppReq#builder()} to obtain a new instance and
* {@link #build} to build the configuration.
*/
public void setJingle(boolean jingle) {
this.jingle = jingle;
public static final class Builder extends AbstractHttpOverXmpp.Builder<Builder, HttpOverXmppReq> {
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;
private Builder() {
}
/**
* Sets method attribute.
*
* @param method attribute
*
* @return the builder
*/
public Builder setMethod(HttpMethod method) {
this.method = method;
return this;
}
/**
* Sets resource attribute.
*
* @param resource attribute
*
* @return the builder
*/
public Builder setResource(String resource) {
this.resource = resource;
return this;
}
/**
* Sets jingle attribute.
*
* @param jingle jingle attribute
*
* @return the builder
*/
public Builder setJingle(boolean jingle) {
this.jingle = jingle;
return this;
}
/**
* Sets ibb attribute.
*
* @param ibb ibb attribute
*
* @return the builder
*/
public Builder setIbb(boolean ibb) {
this.ibb = ibb;
return this;
}
/**
* Sets sipub attribute.
*
* @param sipub sipub attribute
*
* @return the builder
*/
public Builder setSipub(boolean sipub) {
this.sipub = sipub;
return this;
}
/**
* Sets maxChunkSize attribute.
*
* @param maxChunkSize maxChunkSize attribute
*
* @return the builder
*/
public Builder setMaxChunkSize(int maxChunkSize) {
this.maxChunkSize = maxChunkSize;
return this;
}
@Override
public HttpOverXmppReq build() {
if (method == null) {
throw new IllegalArgumentException("Method cannot be null");
}
if (resource == null) {
throw new IllegalArgumentException("Resource cannot be null");
}
return new HttpOverXmppReq(this);
}
@Override
protected Builder getThis() {
return this;
}
}
}

View File

@ -24,17 +24,18 @@ import org.jivesoftware.smack.util.StringUtils;
* @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 {
public final class HttpOverXmppResp extends AbstractHttpOverXmpp {
public static final String ELEMENT = "resp";
public HttpOverXmppResp() {
super(ELEMENT);
private HttpOverXmppResp(Builder builder) {
super(ELEMENT, builder);
this.statusCode = builder.statusCode;
this.statusMessage = builder.statusMessage;
}
private int statusCode;
private String statusMessage = null;
private String statusMessage;
@Override
protected IQChildElementXmlStringBuilder getIQHoxtChildElementBuilder(IQChildElementXmlStringBuilder builder) {
@ -59,15 +60,6 @@ public class HttpOverXmppResp extends AbstractHttpOverXmpp {
return statusCode;
}
/**
* Sets statusCode attribute.
*
* @param statusCode statusCode attribute
*/
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
/**
* Returns statusMessage attribute.
*
@ -77,12 +69,53 @@ public class HttpOverXmppResp extends AbstractHttpOverXmpp {
return statusMessage;
}
/**
* Sets statusMessage attribute.
*
* @param statusMessage statusMessage attribute
*/
public void setStatusMessage(String statusMessage) {
this.statusMessage = statusMessage;
public static Builder builder() {
return new Builder();
}
/**
* A configuration builder for HttpOverXmppReq. Use {@link HttpOverXmppResp#builder()} to obtain a new instance and
* {@link #build} to build the configuration.
*/
public static final class Builder extends AbstractHttpOverXmpp.Builder<Builder, HttpOverXmppResp> {
private int statusCode = 200;
private String statusMessage = null;
/**
* Sets statusCode attribute.
*
* @param statusCode statusCode attribute
*
* @return the builder
*/
public Builder setStatusCode(int statusCode) {
this.statusCode = statusCode;
return this;
}
/**
* Sets statusMessage attribute.
*
* @param statusMessage statusMessage attribute
*
* @return the builder
*/
public Builder setStatusMessage(String statusMessage) {
this.statusMessage = statusMessage;
return this;
}
@Override
public HttpOverXmppResp build() {
return new HttpOverXmppResp(this);
}
@Override
protected Builder getThis() {
return this;
}
}
}

View File

@ -49,73 +49,78 @@ public abstract class AbstractHttpOverXmppProvider<H extends AbstractHttpOverXmp
static final String ATTRIBUTE_VERSION = "version";
/**
* Parses Headers and Data elements.
* Parses HeadersExtension element if any.
*
* @param parser parser
* @param elementName name of concrete implementation of this element
* @param body parent Body element
* @throws Exception
* @param parser parser
* @return HeadersExtension or null if no headers
* @throws Exception
*/
protected void parseHeadersAndData(XmlPullParser parser, String elementName, AbstractHttpOverXmpp body) throws Exception {
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals(HeadersExtension.ELEMENT)) {
HeadersExtension headersExtension = HeadersProvider.INSTANCE.parse(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;
}
}
protected HeadersExtension parseHeaders(XmlPullParser parser) throws Exception {
HeadersExtension headersExtension = null;
/* We are either at start of headers, start of data or end of req/res */
if (parser.next() == XmlPullParser.START_TAG && parser.getName().equals(HeadersExtension.ELEMENT)) {
headersExtension = HeadersProvider.INSTANCE.parse(parser);
parser.next();
}
return headersExtension;
}
private AbstractHttpOverXmpp.Data parseData(XmlPullParser parser) throws XmlPullParserException, IOException {
/**
* Parses Data element if any.
*
* @param parser parser
* @return Data or null if no data
*
* @throws XmlPullParserException
* @throws IOException
*/
protected AbstractHttpOverXmpp.Data parseData(XmlPullParser parser) throws XmlPullParserException, IOException {
NamedElement child = null;
boolean done = false;
AbstractHttpOverXmpp.Data data = null;
/* We are either at start of data or end of req/res */
if (parser.getEventType() == XmlPullParser.START_TAG) {
while (!done) {
int eventType = parser.next();
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;
if (eventType == XmlPullParser.START_TAG) {
switch (parser.getName()) {
case ELEMENT_TEXT:
child = parseText(parser);
break;
case ELEMENT_BASE_64:
child = parseBase64(parser);
break;
case ELEMENT_CHUNKED_BASE_64:
child = parseChunkedBase64(parser);
break;
case ELEMENT_XML:
child = parseXml(parser);
break;
case ELEMENT_IBB:
child = parseIbb(parser);
break;
case ELEMENT_SIPUB:
// TODO: sipub is allowed by xep-0332, but is not
// implemented yet
throw new UnsupportedOperationException("sipub is not supported yet");
case ELEMENT_JINGLE:
// TODO: jingle is allowed by xep-0332, but is not
// implemented yet
throw new UnsupportedOperationException("jingle is not supported yet");
default:
// 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;
}
}
}
data = new AbstractHttpOverXmpp.Data(child);
}
AbstractHttpOverXmpp.Data data = new AbstractHttpOverXmpp.Data(child);
return data;
}

View File

@ -16,8 +16,10 @@
*/
package org.jivesoftware.smackx.hoxt.provider;
import org.jivesoftware.smackx.hoxt.packet.AbstractHttpOverXmpp;
import org.jivesoftware.smackx.hoxt.packet.HttpMethod;
import org.jivesoftware.smackx.hoxt.packet.HttpOverXmppReq;
import org.jivesoftware.smackx.shim.packet.HeadersExtension;
import org.xmlpull.v1.XmlPullParser;
/**
@ -33,16 +35,13 @@ public class HttpOverXmppReqProvider extends AbstractHttpOverXmppProvider<HttpOv
private static final String ATTRIBUTE_MAX_CHUNK_SIZE = "maxChunkSize";
@Override
public HttpOverXmppReq parse(XmlPullParser parser, int initialDepth)
throws Exception {
public HttpOverXmppReq parse(XmlPullParser parser, int initialDepth) 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 = new HttpOverXmppReq(reqMethod, resource);
req.setVersion(version);
Boolean sipub = true;
Boolean jingle = true;
@ -62,16 +61,14 @@ public class HttpOverXmppReqProvider extends AbstractHttpOverXmppProvider<HttpOv
jingle = Boolean.valueOf(jingleStr);
}
req.setIbb(ibb);
req.setSipub(sipub);
req.setJingle(jingle);
int maxChunkSizeValue = 0;
if (maxChunkSize != null) {
int maxChunkSizeValue = Integer.parseInt(maxChunkSize);
req.setMaxChunkSize(maxChunkSizeValue);
maxChunkSizeValue = Integer.parseInt(maxChunkSize);
}
parseHeadersAndData(parser, HttpOverXmppReq.ELEMENT, req);
return req;
HeadersExtension headers = parseHeaders(parser);
AbstractHttpOverXmpp.Data data = parseData(parser);
return HttpOverXmppReq.builder().setMethod(reqMethod).setResource(resource).setIbb(ibb).setSipub(sipub).setJingle(jingle).setMaxChunkSize(maxChunkSizeValue).setData(data).setHeaders(headers).setVersion(version).build();
}
}

View File

@ -16,7 +16,9 @@
*/
package org.jivesoftware.smackx.hoxt.provider;
import org.jivesoftware.smackx.hoxt.packet.AbstractHttpOverXmpp;
import org.jivesoftware.smackx.hoxt.packet.HttpOverXmppResp;
import org.jivesoftware.smackx.shim.packet.HeadersExtension;
import org.xmlpull.v1.XmlPullParser;
/**
@ -31,19 +33,15 @@ public class HttpOverXmppRespProvider extends AbstractHttpOverXmppProvider<HttpO
private static final String ATTRIBUTE_STATUS_CODE = "statusCode";
@Override
public HttpOverXmppResp parse(XmlPullParser parser, int initialDepth)
throws Exception {
public HttpOverXmppResp parse(XmlPullParser parser, int initialDepth) 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 = new HttpOverXmppResp();
HeadersExtension headers = parseHeaders(parser);
AbstractHttpOverXmpp.Data data = parseData(parser);
return HttpOverXmppResp.builder().setHeaders(headers).setData(data).setStatusCode(statusCode).setStatusMessage(statusMessage).setVersion(version).build();
resp.setVersion(version);
resp.setStatusMessage(statusMessage);
resp.setStatusCode(statusCode);
parseHeadersAndData(parser, HttpOverXmppResp.ELEMENT, resp);
return resp;
}
}