mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 14:22:05 +01:00
Apply builder pattern to DiscoverInfo
This is the first transformation of an IQ type to the builder type.
This commit is contained in:
parent
36072fb25a
commit
6e32305987
30 changed files with 749 additions and 233 deletions
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.smack.packet;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.id.StanzaIdSource;
|
||||||
|
import org.jivesoftware.smack.util.ToStringUtil;
|
||||||
|
|
||||||
|
public abstract class AbstractIqBuilder<IB extends AbstractIqBuilder<IB>> extends StanzaBuilder<IB> implements IqView {
|
||||||
|
|
||||||
|
protected IQ.Type type = IQ.Type.get;
|
||||||
|
|
||||||
|
AbstractIqBuilder(AbstractIqBuilder<?> other) {
|
||||||
|
super(other);
|
||||||
|
type = other.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractIqBuilder(StanzaIdSource stanzaIdSource) {
|
||||||
|
super(stanzaIdSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractIqBuilder(String stanzaId) {
|
||||||
|
super(stanzaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IqBuilder createResponse(IqView request) {
|
||||||
|
return createResponse(request, IQ.ResponseType.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IqBuilder createErrorResponse(IqView request) {
|
||||||
|
return createResponse(request, IQ.ResponseType.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static IqBuilder createResponse(IqView request, IQ.ResponseType responseType) {
|
||||||
|
if (!(request.getType() == IQ.Type.get || request.getType() == IQ.Type.set)) {
|
||||||
|
throw new IllegalArgumentException("IQ request must be of type 'set' or 'get'. Original IQ: " + request);
|
||||||
|
}
|
||||||
|
|
||||||
|
IqBuilder commonResponseIqData = buildResponse(request, s -> {
|
||||||
|
return StanzaBuilder.buildIq(s);
|
||||||
|
});
|
||||||
|
commonResponseIqData.ofType(responseType.getType());
|
||||||
|
|
||||||
|
return commonResponseIqData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final void addStanzaSpecificAttributes(ToStringUtil.Builder builder) {
|
||||||
|
builder.addValue("type", getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final IQ.Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ public class EmptyResultIQ extends IQ {
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmptyResultIQ(IQ request) {
|
public EmptyResultIQ(IQ request) {
|
||||||
this(StanzaBuilder.buildIqResultFor(request));
|
this(AbstractIqBuilder.createResponse(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -68,7 +68,7 @@ public abstract class IQ extends Stanza implements IqView {
|
||||||
this(IqBuilder.EMPTY, childElementName, childElementNamespace);
|
this(IqBuilder.EMPTY, childElementName, childElementNamespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IQ(IqBuilder iqBuilder, String childElementName, String childElementNamespace) {
|
protected IQ(AbstractIqBuilder<?> iqBuilder, String childElementName, String childElementNamespace) {
|
||||||
super(iqBuilder);
|
super(iqBuilder);
|
||||||
|
|
||||||
type = iqBuilder.type;
|
type = iqBuilder.type;
|
||||||
|
@ -376,6 +376,25 @@ public abstract class IQ extends Stanza implements IqView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ResponseType {
|
||||||
|
|
||||||
|
result(Type.result),
|
||||||
|
|
||||||
|
error(Type.error),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
final Type type;
|
||||||
|
|
||||||
|
ResponseType(Type type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class IQChildElementXmlStringBuilder extends XmlStringBuilder {
|
public static class IQChildElementXmlStringBuilder extends XmlStringBuilder {
|
||||||
private final String element;
|
private final String element;
|
||||||
|
|
||||||
|
|
|
@ -16,16 +16,18 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.packet;
|
package org.jivesoftware.smack.packet;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.IQ.Type;
|
|
||||||
import org.jivesoftware.smack.packet.id.StandardStanzaIdSource;
|
import org.jivesoftware.smack.packet.id.StandardStanzaIdSource;
|
||||||
import org.jivesoftware.smack.packet.id.StanzaIdSource;
|
import org.jivesoftware.smack.packet.id.StanzaIdSource;
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
import org.jivesoftware.smack.util.ToStringUtil;
|
|
||||||
|
|
||||||
public final class IqBuilder extends StanzaBuilder<IqBuilder> implements IqView {
|
// TODO: Rename to IqData.
|
||||||
|
public final class IqBuilder extends AbstractIqBuilder<IqBuilder> {
|
||||||
|
|
||||||
static final IqBuilder EMPTY = new IqBuilder(StandardStanzaIdSource.DEFAULT);
|
static final IqBuilder EMPTY = new IqBuilder(StandardStanzaIdSource.DEFAULT);
|
||||||
|
|
||||||
IQ.Type type = Type.get;
|
IqBuilder(IqBuilder other) {
|
||||||
|
super(other);
|
||||||
|
}
|
||||||
|
|
||||||
IqBuilder(StanzaIdSource stanzaIdSource) {
|
IqBuilder(StanzaIdSource stanzaIdSource) {
|
||||||
super(stanzaIdSource);
|
super(stanzaIdSource);
|
||||||
|
@ -35,11 +37,6 @@ public final class IqBuilder extends StanzaBuilder<IqBuilder> implements IqView
|
||||||
super(stanzaId);
|
super(stanzaId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addStanzaSpecificAttributes(ToStringUtil.Builder builder) {
|
|
||||||
builder.addValue("type", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IqBuilder ofType(IQ.Type type) {
|
public IqBuilder ofType(IQ.Type type) {
|
||||||
this.type = Objects.requireNonNull(type);
|
this.type = Objects.requireNonNull(type);
|
||||||
return getThis();
|
return getThis();
|
||||||
|
@ -49,9 +46,4 @@ public final class IqBuilder extends StanzaBuilder<IqBuilder> implements IqView
|
||||||
public IqBuilder getThis() {
|
public IqBuilder getThis() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IQ.Type getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.smack.packet;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.util.Objects;
|
||||||
|
|
||||||
|
// TODO: Rename to IqBuilder.
|
||||||
|
public abstract class IqBuilderWithBuild<IB extends IqBuilderWithBuild<IB, I>, I extends IQ>
|
||||||
|
extends AbstractIqBuilder<IB> {
|
||||||
|
|
||||||
|
protected IqBuilderWithBuild(AbstractIqBuilder<?> other) {
|
||||||
|
super(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IqBuilderWithBuild(XMPPConnection connection) {
|
||||||
|
super(connection.getStanzaFactory().getStanzaIdSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IqBuilderWithBuild(String stanzaId) {
|
||||||
|
super(stanzaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IB ofType(IQ.Type type) {
|
||||||
|
this.type = Objects.requireNonNull(type);
|
||||||
|
return getThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract I build();
|
||||||
|
|
||||||
|
}
|
|
@ -21,8 +21,8 @@ import java.util.List;
|
||||||
|
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.IQ.Type;
|
|
||||||
import org.jivesoftware.smack.packet.id.StanzaIdSource;
|
import org.jivesoftware.smack.packet.id.StanzaIdSource;
|
||||||
|
import org.jivesoftware.smack.util.Function;
|
||||||
import org.jivesoftware.smack.util.MultiMap;
|
import org.jivesoftware.smack.util.MultiMap;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smack.util.ToStringUtil;
|
import org.jivesoftware.smack.util.ToStringUtil;
|
||||||
|
@ -46,6 +46,17 @@ public abstract class StanzaBuilder<B extends StanzaBuilder<B>> implements Stanz
|
||||||
|
|
||||||
MultiMap<QName, ExtensionElement> extensionElements = new MultiMap<>();
|
MultiMap<QName, ExtensionElement> extensionElements = new MultiMap<>();
|
||||||
|
|
||||||
|
protected StanzaBuilder(StanzaBuilder<?> other) {
|
||||||
|
stanzaIdSource = other.stanzaIdSource;
|
||||||
|
stanzaId = other.stanzaId;
|
||||||
|
|
||||||
|
to = other.to;
|
||||||
|
from = other.from;
|
||||||
|
stanzaError = other.stanzaError;
|
||||||
|
language = other.language;
|
||||||
|
extensionElements = other.extensionElements.clone();
|
||||||
|
}
|
||||||
|
|
||||||
protected StanzaBuilder(StanzaIdSource stanzaIdSource) {
|
protected StanzaBuilder(StanzaIdSource stanzaIdSource) {
|
||||||
this.stanzaIdSource = stanzaIdSource;
|
this.stanzaIdSource = stanzaIdSource;
|
||||||
this.stanzaId = null;
|
this.stanzaId = null;
|
||||||
|
@ -282,20 +293,14 @@ public abstract class StanzaBuilder<B extends StanzaBuilder<B>> implements Stanz
|
||||||
return new IqBuilder(stanzaId);
|
return new IqBuilder(stanzaId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IqBuilder buildIqResultFor(IQ request) {
|
public static <SB extends StanzaBuilder<?>> SB buildResponse(StanzaView request, Function<SB, String> builderFromStanzaId) {
|
||||||
if (!(request.getType() == Type.get || request.getType() == Type.set)) {
|
SB responseBuilder = builderFromStanzaId.apply(request.getStanzaId());
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"IQ request must be of type 'set' or 'get'. Original IQ: " + request.toXML());
|
|
||||||
}
|
|
||||||
|
|
||||||
return buildIq(request.getStanzaId())
|
responseBuilder.to(request.getFrom())
|
||||||
.to(request.getFrom())
|
.from(request.getTo())
|
||||||
.from(request.getTo())
|
;
|
||||||
.ofType(IQ.Type.result);
|
|
||||||
|
return responseBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EmptyResultIQ buildEmptyIqResultFor(IQ request) {
|
|
||||||
IqBuilder iqBuilder = buildIqResultFor(request);
|
|
||||||
return new EmptyResultIQ(iqBuilder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,10 @@ public final class StanzaFactory {
|
||||||
|
|
||||||
private final StanzaIdSource stanzaIdSource;
|
private final StanzaIdSource stanzaIdSource;
|
||||||
|
|
||||||
|
StanzaIdSource getStanzaIdSource() {
|
||||||
|
return stanzaIdSource;
|
||||||
|
}
|
||||||
|
|
||||||
public StanzaFactory(StanzaIdSource stanzaIdSource) {
|
public StanzaFactory(StanzaIdSource stanzaIdSource) {
|
||||||
this.stanzaIdSource = stanzaIdSource;
|
this.stanzaIdSource = stanzaIdSource;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.smack.provider;
|
||||||
|
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.Element;
|
||||||
|
|
||||||
|
public class AbstractProvider<E extends Element> {
|
||||||
|
|
||||||
|
private final Class<E> elementClass;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected AbstractProvider() {
|
||||||
|
Type currentType = getClass().getGenericSuperclass();
|
||||||
|
while (!(currentType instanceof ParameterizedType)) {
|
||||||
|
Class<?> currentClass = (Class<?>) currentType;
|
||||||
|
currentType = currentClass.getGenericSuperclass();
|
||||||
|
}
|
||||||
|
ParameterizedType parameterizedGenericSuperclass = (ParameterizedType) currentType;
|
||||||
|
Type[] actualTypeArguments = parameterizedGenericSuperclass.getActualTypeArguments();
|
||||||
|
Type elementType = actualTypeArguments[0];
|
||||||
|
|
||||||
|
elementClass = (Class<E>) elementType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Class<E> getElementClass() {
|
||||||
|
return elementClass;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,15 +17,53 @@
|
||||||
|
|
||||||
package org.jivesoftware.smack.provider;
|
package org.jivesoftware.smack.provider;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
import org.jivesoftware.smack.packet.IqBuilder;
|
||||||
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
|
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||||
|
import org.jivesoftware.smack.util.ParserUtils;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <p>
|
||||||
|
* <b>Deprecation Notice:</b> This class is deprecated, use {@link IQProvider} instead.
|
||||||
|
* </p>
|
||||||
* An abstract class for parsing custom IQ packets. Each IQProvider must be registered with
|
* An abstract class for parsing custom IQ packets. Each IQProvider must be registered with
|
||||||
* the ProviderManager class for it to be used. Every implementation of this
|
* the ProviderManager class for it to be used. Every implementation of this
|
||||||
* abstract class <b>must</b> have a public, no-argument constructor.
|
* abstract class <b>must</b> have a public, no-argument constructor.
|
||||||
*
|
*
|
||||||
* @author Matt Tucker
|
* @author Matt Tucker
|
||||||
*/
|
*/
|
||||||
public abstract class IQProvider<I extends IQ> extends Provider<I> {
|
public abstract class IQProvider<I extends IQ> extends IqProvider<I> {
|
||||||
|
|
||||||
|
public final I parse(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException {
|
||||||
|
return parse(parser, (XmlEnvironment) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final I parse(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws IOException, XmlPullParserException, SmackParsingException {
|
||||||
|
// XPP3 calling convention assert: Parser should be at start tag
|
||||||
|
ParserUtils.assertAtStartTag(parser);
|
||||||
|
|
||||||
|
final int initialDepth = parser.getDepth();
|
||||||
|
final XmlEnvironment xmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
|
||||||
|
|
||||||
|
I e = parse(parser, initialDepth, xmlEnvironment);
|
||||||
|
|
||||||
|
// XPP3 calling convention assert: Parser should be at end tag of the consumed/parsed element
|
||||||
|
ParserUtils.forwardToEndTagOfDepth(parser, initialDepth);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final I parse(XmlPullParser parser, int initialDepth, IqBuilder iqData, XmlEnvironment xmlEnvironment)
|
||||||
|
throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
|
// Old-style IQ parsers do not need IqData.
|
||||||
|
return parse(parser, initialDepth, xmlEnvironment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract I parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public final class IQProviderInfo extends AbstractProviderInfo {
|
||||||
* @param namespace Namespace that provider parses.
|
* @param namespace Namespace that provider parses.
|
||||||
* @param iqProvider The provider implementation.
|
* @param iqProvider The provider implementation.
|
||||||
*/
|
*/
|
||||||
public IQProviderInfo(String elementName, String namespace, IQProvider<IQ> iqProvider) {
|
public IQProviderInfo(String elementName, String namespace, IqProvider<IQ> iqProvider) {
|
||||||
super(elementName, namespace, iqProvider);
|
super(elementName, namespace, iqProvider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.smack.provider;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
import org.jivesoftware.smack.packet.IqBuilder;
|
||||||
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
|
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
|
public abstract class IqProvider<I extends IQ> extends AbstractProvider<I> {
|
||||||
|
|
||||||
|
public final I parse(XmlPullParser parser, IqBuilder iqCommon)
|
||||||
|
throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
|
return parse(parser, iqCommon, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final I parse(XmlPullParser parser, IqBuilder iqData, XmlEnvironment outerXmlEnvironment)
|
||||||
|
throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
|
final int initialDepth = parser.getDepth();
|
||||||
|
final XmlEnvironment xmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
|
||||||
|
|
||||||
|
return parse(parser, initialDepth, iqData, xmlEnvironment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract I parse(XmlPullParser parser, int initialDepth, IqBuilder iqData, XmlEnvironment xmlEnvironment)
|
||||||
|
throws XmlPullParserException, IOException, SmackParsingException;
|
||||||
|
|
||||||
|
}
|
|
@ -18,8 +18,6 @@
|
||||||
package org.jivesoftware.smack.provider;
|
package org.jivesoftware.smack.provider;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.Element;
|
import org.jivesoftware.smack.packet.Element;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
|
@ -40,27 +38,7 @@ import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
* @author Florian Schmaus
|
* @author Florian Schmaus
|
||||||
* @param <E> the type of the resulting element.
|
* @param <E> the type of the resulting element.
|
||||||
*/
|
*/
|
||||||
public abstract class Provider<E extends Element> {
|
public abstract class Provider<E extends Element> extends AbstractProvider<E> {
|
||||||
|
|
||||||
private final Class<E> elementClass;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected Provider() {
|
|
||||||
Type currentType = getClass().getGenericSuperclass();
|
|
||||||
while (!(currentType instanceof ParameterizedType)) {
|
|
||||||
Class<?> currentClass = (Class<?>) currentType;
|
|
||||||
currentType = currentClass.getGenericSuperclass();
|
|
||||||
}
|
|
||||||
ParameterizedType parameterizedGenericSuperclass = (ParameterizedType) currentType;
|
|
||||||
Type[] actualTypeArguments = parameterizedGenericSuperclass.getActualTypeArguments();
|
|
||||||
Type elementType = actualTypeArguments[0];
|
|
||||||
|
|
||||||
elementClass = (Class<E>) elementType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final Class<E> getElementClass() {
|
|
||||||
return elementClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final E parse(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException {
|
public final E parse(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException {
|
||||||
return parse(parser, null);
|
return parse(parser, null);
|
||||||
|
|
|
@ -80,8 +80,8 @@ public class ProviderFileLoader implements ProviderLoader {
|
||||||
// an IQ class, add the class object itself, then we'll use
|
// an IQ class, add the class object itself, then we'll use
|
||||||
// reflection later to create instances of the class.
|
// reflection later to create instances of the class.
|
||||||
// Add the provider to the map.
|
// Add the provider to the map.
|
||||||
if (IQProvider.class.isAssignableFrom(provider)) {
|
if (IqProvider.class.isAssignableFrom(provider)) {
|
||||||
IQProvider<IQ> iqProvider = (IQProvider<IQ>) provider.getConstructor().newInstance();
|
IqProvider<IQ> iqProvider = (IqProvider<IQ>) provider.getConstructor().newInstance();
|
||||||
iqProviders.add(new IQProviderInfo(elementName, namespace, iqProvider));
|
iqProviders.add(new IQProviderInfo(elementName, namespace, iqProvider));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -113,7 +113,7 @@ import org.jivesoftware.smack.util.XmppElementUtil;
|
||||||
public final class ProviderManager {
|
public final class ProviderManager {
|
||||||
|
|
||||||
private static final Map<QName, ExtensionElementProvider<ExtensionElement>> extensionProviders = new ConcurrentHashMap<>();
|
private static final Map<QName, ExtensionElementProvider<ExtensionElement>> extensionProviders = new ConcurrentHashMap<>();
|
||||||
private static final Map<QName, IQProvider<IQ>> iqProviders = new ConcurrentHashMap<>();
|
private static final Map<QName, IqProvider<IQ>> iqProviders = new ConcurrentHashMap<>();
|
||||||
private static final Map<QName, ExtensionElementProvider<ExtensionElement>> streamFeatureProviders = new ConcurrentHashMap<>();
|
private static final Map<QName, ExtensionElementProvider<ExtensionElement>> streamFeatureProviders = new ConcurrentHashMap<>();
|
||||||
private static final Map<QName, NonzaProvider<? extends Nonza>> nonzaProviders = new ConcurrentHashMap<>();
|
private static final Map<QName, NonzaProvider<? extends Nonza>> nonzaProviders = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ public final class ProviderManager {
|
||||||
* @param namespace the XML namespace.
|
* @param namespace the XML namespace.
|
||||||
* @return the IQ provider.
|
* @return the IQ provider.
|
||||||
*/
|
*/
|
||||||
public static IQProvider<IQ> getIQProvider(String elementName, String namespace) {
|
public static IqProvider<IQ> getIQProvider(String elementName, String namespace) {
|
||||||
QName key = getQName(elementName, namespace);
|
QName key = getQName(elementName, namespace);
|
||||||
return iqProviders.get(key);
|
return iqProviders.get(key);
|
||||||
}
|
}
|
||||||
|
@ -179,8 +179,8 @@ public final class ProviderManager {
|
||||||
*
|
*
|
||||||
* @return all IQProvider instances.
|
* @return all IQProvider instances.
|
||||||
*/
|
*/
|
||||||
public static List<IQProvider<IQ>> getIQProviders() {
|
public static List<IqProvider<IQ>> getIQProviders() {
|
||||||
List<IQProvider<IQ>> providers = new ArrayList<>(iqProviders.size());
|
List<IqProvider<IQ>> providers = new ArrayList<>(iqProviders.size());
|
||||||
providers.addAll(iqProviders.values());
|
providers.addAll(iqProviders.values());
|
||||||
return providers;
|
return providers;
|
||||||
}
|
}
|
||||||
|
@ -200,10 +200,10 @@ public final class ProviderManager {
|
||||||
validate(elementName, namespace);
|
validate(elementName, namespace);
|
||||||
// First remove existing providers
|
// First remove existing providers
|
||||||
QName key = removeIQProvider(elementName, namespace);
|
QName key = removeIQProvider(elementName, namespace);
|
||||||
if (provider instanceof IQProvider) {
|
if (provider instanceof IqProvider) {
|
||||||
iqProviders.put(key, (IQProvider<IQ>) provider);
|
iqProviders.put(key, (IqProvider<IQ>) provider);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Provider must be an IQProvider");
|
throw new IllegalArgumentException("Provider must be an instance of IqProvider");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.jivesoftware.smack.packet.EmptyResultIQ;
|
||||||
import org.jivesoftware.smack.packet.ErrorIQ;
|
import org.jivesoftware.smack.packet.ErrorIQ;
|
||||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
import org.jivesoftware.smack.packet.IqBuilder;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
import org.jivesoftware.smack.packet.MessageBuilder;
|
import org.jivesoftware.smack.packet.MessageBuilder;
|
||||||
import org.jivesoftware.smack.packet.Presence;
|
import org.jivesoftware.smack.packet.Presence;
|
||||||
|
@ -51,7 +52,7 @@ import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||||
import org.jivesoftware.smack.parsing.StandardExtensionElementProvider;
|
import org.jivesoftware.smack.parsing.StandardExtensionElementProvider;
|
||||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||||
import org.jivesoftware.smack.provider.IQProvider;
|
import org.jivesoftware.smack.provider.IqProvider;
|
||||||
import org.jivesoftware.smack.provider.ProviderManager;
|
import org.jivesoftware.smack.provider.ProviderManager;
|
||||||
import org.jivesoftware.smack.xml.SmackXmlParser;
|
import org.jivesoftware.smack.xml.SmackXmlParser;
|
||||||
import org.jivesoftware.smack.xml.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
@ -542,9 +543,16 @@ public class PacketParserUtils {
|
||||||
StanzaError error = null;
|
StanzaError error = null;
|
||||||
|
|
||||||
final String id = parser.getAttributeValue("", "id");
|
final String id = parser.getAttributeValue("", "id");
|
||||||
|
IqBuilder iqData = StanzaBuilder.buildIq(id);
|
||||||
|
|
||||||
final Jid to = ParserUtils.getJidAttribute(parser, "to");
|
final Jid to = ParserUtils.getJidAttribute(parser, "to");
|
||||||
|
iqData.to(to);
|
||||||
|
|
||||||
final Jid from = ParserUtils.getJidAttribute(parser, "from");
|
final Jid from = ParserUtils.getJidAttribute(parser, "from");
|
||||||
|
iqData.from(from);
|
||||||
|
|
||||||
final IQ.Type type = IQ.Type.fromString(parser.getAttributeValue("", "type"));
|
final IQ.Type type = IQ.Type.fromString(parser.getAttributeValue("", "type"));
|
||||||
|
iqData.ofType(type);
|
||||||
|
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
XmlPullParser.Event eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
|
@ -560,9 +568,9 @@ public class PacketParserUtils {
|
||||||
// Otherwise, see if there is a registered provider for
|
// Otherwise, see if there is a registered provider for
|
||||||
// this element name and namespace.
|
// this element name and namespace.
|
||||||
default:
|
default:
|
||||||
IQProvider<IQ> provider = ProviderManager.getIQProvider(elementName, namespace);
|
IqProvider<IQ> provider = ProviderManager.getIQProvider(elementName, namespace);
|
||||||
if (provider != null) {
|
if (provider != null) {
|
||||||
iqPacket = provider.parse(parser, outerXmlEnvironment);
|
iqPacket = provider.parse(parser, iqData, outerXmlEnvironment);
|
||||||
}
|
}
|
||||||
// Note that if we reach this code, it is guranteed that the result IQ contained a child element
|
// Note that if we reach this code, it is guranteed that the result IQ contained a child element
|
||||||
// (RFC 6120 § 8.2.3 6) because otherwhise we would have reached the END_ELEMENT first.
|
// (RFC 6120 § 8.2.3 6) because otherwhise we would have reached the END_ELEMENT first.
|
||||||
|
@ -915,6 +923,18 @@ public class PacketParserUtils {
|
||||||
return new Session.Feature(optional);
|
return new Session.Feature(optional);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void addExtensionElement(StanzaBuilder<?> stanzaBuilder, XmlPullParser parser, XmlEnvironment outerXmlEnvironment)
|
||||||
|
throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
|
ParserUtils.assertAtStartTag(parser);
|
||||||
|
addExtensionElement(stanzaBuilder, parser, parser.getName(), parser.getNamespace(), outerXmlEnvironment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addExtensionElement(StanzaBuilder<?> stanzaBuilder, XmlPullParser parser, String elementName,
|
||||||
|
String namespace, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
|
ExtensionElement extensionElement = parseExtensionElement(elementName, namespace, parser, outerXmlEnvironment);
|
||||||
|
stanzaBuilder.addExtension(extensionElement);
|
||||||
|
}
|
||||||
|
|
||||||
public static void addExtensionElement(Stanza packet, XmlPullParser parser, XmlEnvironment outerXmlEnvironment)
|
public static void addExtensionElement(Stanza packet, XmlPullParser parser, XmlEnvironment outerXmlEnvironment)
|
||||||
throws XmlPullParserException, IOException, SmackParsingException {
|
throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
ParserUtils.assertAtStartTag(parser);
|
ParserUtils.assertAtStartTag(parser);
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.iot.control.element;
|
package org.jivesoftware.smackx.iot.control.element;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.AbstractIqBuilder;
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
import org.jivesoftware.smack.packet.IqBuilder;
|
import org.jivesoftware.smack.packet.IqBuilder;
|
||||||
import org.jivesoftware.smack.packet.StanzaBuilder;
|
|
||||||
|
|
||||||
public class IoTSetResponse extends IQ {
|
public class IoTSetResponse extends IQ {
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public class IoTSetResponse extends IQ {
|
||||||
}
|
}
|
||||||
|
|
||||||
public IoTSetResponse(IoTSetRequest iotSetRequest) {
|
public IoTSetResponse(IoTSetRequest iotSetRequest) {
|
||||||
this(StanzaBuilder.buildIqResultFor(iotSetRequest));
|
this(AbstractIqBuilder.createResponse(iotSetRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -68,6 +68,8 @@ import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Feature;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Feature;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
||||||
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder;
|
||||||
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfoView;
|
||||||
import org.jivesoftware.smackx.xdata.FormField;
|
import org.jivesoftware.smackx.xdata.FormField;
|
||||||
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
||||||
|
|
||||||
|
@ -521,16 +523,19 @@ public final class EntityCapsManager extends Manager {
|
||||||
private void updateLocalEntityCaps() {
|
private void updateLocalEntityCaps() {
|
||||||
XMPPConnection connection = connection();
|
XMPPConnection connection = connection();
|
||||||
|
|
||||||
DiscoverInfo discoverInfo = new DiscoverInfo();
|
DiscoverInfoBuilder discoverInfoBuilder = DiscoverInfo.builder("synthetized-disco-info-response")
|
||||||
discoverInfo.setType(IQ.Type.result);
|
.ofType(IQ.Type.result);
|
||||||
sdm.addDiscoverInfoTo(discoverInfo);
|
sdm.addDiscoverInfoTo(discoverInfoBuilder);
|
||||||
|
|
||||||
// getLocalNodeVer() will return a result only after currentCapsVersion is set. Therefore
|
// getLocalNodeVer() will return a result only after currentCapsVersion is set. Therefore
|
||||||
// set it first and then call getLocalNodeVer()
|
// set it first and then call getLocalNodeVer()
|
||||||
currentCapsVersion = generateVerificationString(discoverInfo);
|
currentCapsVersion = generateVerificationString(discoverInfoBuilder);
|
||||||
final String localNodeVer = getLocalNodeVer();
|
final String localNodeVer = getLocalNodeVer();
|
||||||
discoverInfo.setNode(localNodeVer);
|
discoverInfoBuilder.setNode(localNodeVer);
|
||||||
|
|
||||||
|
final DiscoverInfo discoverInfo = discoverInfoBuilder.build();
|
||||||
addDiscoverInfoByNode(localNodeVer, discoverInfo);
|
addDiscoverInfoByNode(localNodeVer, discoverInfo);
|
||||||
|
|
||||||
if (lastLocalCapsVersions.size() > 10) {
|
if (lastLocalCapsVersions.size() > 10) {
|
||||||
CapsVersionAndHash oldCapsVersion = lastLocalCapsVersions.poll();
|
CapsVersionAndHash oldCapsVersion = lastLocalCapsVersions.poll();
|
||||||
sdm.removeNodeInformationProvider(entityNode + '#' + oldCapsVersion.version);
|
sdm.removeNodeInformationProvider(entityNode + '#' + oldCapsVersion.version);
|
||||||
|
@ -630,7 +635,7 @@ public final class EntityCapsManager extends Manager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static CapsVersionAndHash generateVerificationString(DiscoverInfo discoverInfo) {
|
protected static CapsVersionAndHash generateVerificationString(DiscoverInfoView discoverInfo) {
|
||||||
return generateVerificationString(discoverInfo, null);
|
return generateVerificationString(discoverInfo, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,7 +651,7 @@ public final class EntityCapsManager extends Manager {
|
||||||
* @return The generated verification String or null if the hash is not
|
* @return The generated verification String or null if the hash is not
|
||||||
* supported
|
* supported
|
||||||
*/
|
*/
|
||||||
protected static CapsVersionAndHash generateVerificationString(DiscoverInfo discoverInfo, String hash) {
|
protected static CapsVersionAndHash generateVerificationString(DiscoverInfoView discoverInfo, String hash) {
|
||||||
if (hash == null) {
|
if (hash == null) {
|
||||||
hash = DEFAULT_HASH;
|
hash = DEFAULT_HASH;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ import org.jivesoftware.smack.util.StringUtils;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
||||||
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverItems;
|
import org.jivesoftware.smackx.disco.packet.DiscoverItems;
|
||||||
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
||||||
|
|
||||||
|
@ -159,34 +160,33 @@ public final class ServiceDiscoveryManager extends Manager {
|
||||||
public IQ handleIQRequest(IQ iqRequest) {
|
public IQ handleIQRequest(IQ iqRequest) {
|
||||||
DiscoverInfo discoverInfo = (DiscoverInfo) iqRequest;
|
DiscoverInfo discoverInfo = (DiscoverInfo) iqRequest;
|
||||||
// Answer the client's supported features if the request is of the GET type
|
// Answer the client's supported features if the request is of the GET type
|
||||||
DiscoverInfo response = new DiscoverInfo();
|
DiscoverInfoBuilder responseBuilder = DiscoverInfoBuilder.buildResponseFor(discoverInfo, IQ.ResponseType.result);
|
||||||
response.setType(IQ.Type.result);
|
|
||||||
response.setTo(discoverInfo.getFrom());
|
|
||||||
response.setStanzaId(discoverInfo.getStanzaId());
|
|
||||||
response.setNode(discoverInfo.getNode());
|
|
||||||
// Add the client's identity and features only if "node" is null
|
// Add the client's identity and features only if "node" is null
|
||||||
// and if the request was not send to a node. If Entity Caps are
|
// and if the request was not send to a node. If Entity Caps are
|
||||||
// enabled the client's identity and features are may also added
|
// enabled the client's identity and features are may also added
|
||||||
// if the right node is chosen
|
// if the right node is chosen
|
||||||
if (discoverInfo.getNode() == null) {
|
if (discoverInfo.getNode() == null) {
|
||||||
addDiscoverInfoTo(response);
|
addDiscoverInfoTo(responseBuilder);
|
||||||
} else {
|
} else {
|
||||||
// Disco#info was sent to a node. Check if we have information of the
|
// Disco#info was sent to a node. Check if we have information of the
|
||||||
// specified node
|
// specified node
|
||||||
NodeInformationProvider nodeInformationProvider = getNodeInformationProvider(discoverInfo.getNode());
|
NodeInformationProvider nodeInformationProvider = getNodeInformationProvider(discoverInfo.getNode());
|
||||||
if (nodeInformationProvider != null) {
|
if (nodeInformationProvider != null) {
|
||||||
// Node was found. Add node features
|
// Node was found. Add node features
|
||||||
response.addFeatures(nodeInformationProvider.getNodeFeatures());
|
responseBuilder.addFeatures(nodeInformationProvider.getNodeFeatures());
|
||||||
// Add node identities
|
// Add node identities
|
||||||
response.addIdentities(nodeInformationProvider.getNodeIdentities());
|
responseBuilder.addIdentities(nodeInformationProvider.getNodeIdentities());
|
||||||
// Add packet extensions
|
// Add packet extensions
|
||||||
response.addExtensions(nodeInformationProvider.getNodePacketExtensions());
|
responseBuilder.addExtensions(nodeInformationProvider.getNodePacketExtensions());
|
||||||
} else {
|
} else {
|
||||||
// Return <item-not-found/> error since specified node was not found
|
// Return <item-not-found/> error since specified node was not found
|
||||||
response.setType(IQ.Type.error);
|
responseBuilder.ofType(IQ.Type.error);
|
||||||
response.setError(StanzaError.getBuilder(StanzaError.Condition.item_not_found).build());
|
responseBuilder.setError(StanzaError.getBuilder(StanzaError.Condition.item_not_found).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DiscoverInfo response = responseBuilder.build();
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -299,7 +299,7 @@ public final class ServiceDiscoveryManager extends Manager {
|
||||||
*
|
*
|
||||||
* @param response the discover info response packet
|
* @param response the discover info response packet
|
||||||
*/
|
*/
|
||||||
public synchronized void addDiscoverInfoTo(DiscoverInfo response) {
|
public synchronized void addDiscoverInfoTo(DiscoverInfoBuilder response) {
|
||||||
// First add the identities of the connection
|
// First add the identities of the connection
|
||||||
response.addIdentities(getIdentities());
|
response.addIdentities(getIdentities());
|
||||||
|
|
||||||
|
@ -307,7 +307,9 @@ public final class ServiceDiscoveryManager extends Manager {
|
||||||
for (String feature : getFeatures()) {
|
for (String feature : getFeatures()) {
|
||||||
response.addFeature(feature);
|
response.addFeature(feature);
|
||||||
}
|
}
|
||||||
response.addExtension(extendedInfo);
|
if (extendedInfo != null) {
|
||||||
|
response.addExtension(extendedInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -522,13 +524,15 @@ public final class ServiceDiscoveryManager extends Manager {
|
||||||
* @throws InterruptedException if the calling thread was interrupted.
|
* @throws InterruptedException if the calling thread was interrupted.
|
||||||
*/
|
*/
|
||||||
public DiscoverInfo discoverInfo(Jid entityID, String node) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
public DiscoverInfo discoverInfo(Jid entityID, String node) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
// Discover the entity's info
|
XMPPConnection connection = connection();
|
||||||
DiscoverInfo disco = new DiscoverInfo();
|
|
||||||
disco.setType(IQ.Type.get);
|
|
||||||
disco.setTo(entityID);
|
|
||||||
disco.setNode(node);
|
|
||||||
|
|
||||||
Stanza result = connection().createStanzaCollectorAndSend(disco).nextResultOrThrow();
|
// Discover the entity's info
|
||||||
|
DiscoverInfo discoInfoRequest = DiscoverInfo.builder(connection)
|
||||||
|
.to(entityID)
|
||||||
|
.setNode(node)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Stanza result = connection.createStanzaCollectorAndSend(discoInfoRequest).nextResultOrThrow();
|
||||||
|
|
||||||
return (DiscoverInfo) result;
|
return (DiscoverInfo) result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,9 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
import org.jivesoftware.smack.packet.IqBuilder;
|
||||||
import org.jivesoftware.smack.util.EqualsUtil;
|
import org.jivesoftware.smack.util.EqualsUtil;
|
||||||
import org.jivesoftware.smack.util.HashCode;
|
import org.jivesoftware.smack.util.HashCode;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
|
@ -42,18 +44,53 @@ import org.jxmpp.util.XmppStringUtils;
|
||||||
*
|
*
|
||||||
* @author Gaston Dombiak
|
* @author Gaston Dombiak
|
||||||
*/
|
*/
|
||||||
public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
public class DiscoverInfo extends IQ implements DiscoverInfoView, TypedCloneable<DiscoverInfo> {
|
||||||
|
|
||||||
public static final String ELEMENT = QUERY_ELEMENT;
|
public static final String ELEMENT = QUERY_ELEMENT;
|
||||||
public static final String NAMESPACE = "http://jabber.org/protocol/disco#info";
|
public static final String NAMESPACE = "http://jabber.org/protocol/disco#info";
|
||||||
|
|
||||||
private final List<Feature> features = new LinkedList<>();
|
private final List<Feature> features = new ArrayList<>();
|
||||||
private final Set<Feature> featuresSet = new HashSet<>();
|
private final Set<Feature> featuresSet = new HashSet<>();
|
||||||
private final List<Identity> identities = new LinkedList<>();
|
private final List<Identity> identities = new ArrayList<>();
|
||||||
private final Set<String> identitiesSet = new HashSet<>();
|
private final Set<String> identitiesSet = new HashSet<>();
|
||||||
private String node;
|
private String node;
|
||||||
private boolean containsDuplicateFeatures;
|
private boolean containsDuplicateFeatures;
|
||||||
|
|
||||||
|
DiscoverInfo(DiscoverInfoBuilder builder, boolean validate) {
|
||||||
|
super(builder, ELEMENT, NAMESPACE);
|
||||||
|
|
||||||
|
features.addAll(builder.getFeatures());
|
||||||
|
identities.addAll(builder.getIdentities());
|
||||||
|
node = builder.getNode();
|
||||||
|
|
||||||
|
|
||||||
|
for (Feature feature : features) {
|
||||||
|
boolean featureIsNew = featuresSet.add(feature);
|
||||||
|
if (!featureIsNew) {
|
||||||
|
containsDuplicateFeatures = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Identity identity : identities) {
|
||||||
|
identitiesSet.add(identity.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (containsDuplicateFeatures) {
|
||||||
|
throw new IllegalArgumentException("The disco#info request contains duplicate features.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated.
|
||||||
|
*
|
||||||
|
* @deprecated use {@link DiscoverInfoBuilder} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
// TODO: Remove in Smack 4.5.
|
||||||
public DiscoverInfo() {
|
public DiscoverInfo() {
|
||||||
super(ELEMENT, NAMESPACE);
|
super(ELEMENT, NAMESPACE);
|
||||||
}
|
}
|
||||||
|
@ -67,17 +104,15 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
||||||
super(d);
|
super(d);
|
||||||
|
|
||||||
// Set node
|
// Set node
|
||||||
setNode(d.getNode());
|
node = d.getNode();
|
||||||
|
|
||||||
// Copy features
|
// Copy features
|
||||||
for (Feature f : d.features) {
|
features.addAll(d.features);
|
||||||
addFeature(f.clone());
|
featuresSet.addAll(d.featuresSet);
|
||||||
}
|
|
||||||
|
|
||||||
// Copy identities
|
// Copy identities
|
||||||
for (Identity i : d.identities) {
|
identities.addAll(d.identities);
|
||||||
addIdentity(i.clone());
|
identitiesSet.addAll(d.identitiesSet);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,7 +120,10 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
||||||
*
|
*
|
||||||
* @param feature the discovered feature
|
* @param feature the discovered feature
|
||||||
* @return true if the feature did not already exist.
|
* @return true if the feature did not already exist.
|
||||||
|
* @deprecated use {@link DiscoverInfoBuilder#addFeature(String)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
|
// TODO: Remove in Smack 4.5.
|
||||||
public boolean addFeature(String feature) {
|
public boolean addFeature(String feature) {
|
||||||
return addFeature(new Feature(feature));
|
return addFeature(new Feature(feature));
|
||||||
}
|
}
|
||||||
|
@ -94,7 +132,10 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
||||||
* Adds a collection of features to the packet. Does noting if featuresToAdd is null.
|
* Adds a collection of features to the packet. Does noting if featuresToAdd is null.
|
||||||
*
|
*
|
||||||
* @param featuresToAdd TODO javadoc me please
|
* @param featuresToAdd TODO javadoc me please
|
||||||
|
* @deprecated use {@link DiscoverInfoBuilder#addFeatures(Collection)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
|
// TODO: Remove in Smack 4.5.
|
||||||
public void addFeatures(Collection<String> featuresToAdd) {
|
public void addFeatures(Collection<String> featuresToAdd) {
|
||||||
if (featuresToAdd == null) return;
|
if (featuresToAdd == null) return;
|
||||||
for (String feature : featuresToAdd) {
|
for (String feature : featuresToAdd) {
|
||||||
|
@ -102,6 +143,15 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated.
|
||||||
|
*
|
||||||
|
* @param feature the future.
|
||||||
|
* @return true if the feature is new.
|
||||||
|
* @deprecated use {@link DiscoverInfoBuilder#addFeature(Feature)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
// TODO: Remove in Smack 4.5.
|
||||||
public boolean addFeature(Feature feature) {
|
public boolean addFeature(Feature feature) {
|
||||||
features.add(feature);
|
features.add(feature);
|
||||||
boolean featureIsNew = featuresSet.add(feature);
|
boolean featureIsNew = featuresSet.add(feature);
|
||||||
|
@ -111,11 +161,7 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
||||||
return featureIsNew;
|
return featureIsNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns the discovered features of an XMPP entity.
|
|
||||||
*
|
|
||||||
* @return an unmodifiable list of the discovered features of an XMPP entity
|
|
||||||
*/
|
|
||||||
public List<Feature> getFeatures() {
|
public List<Feature> getFeatures() {
|
||||||
return Collections.unmodifiableList(features);
|
return Collections.unmodifiableList(features);
|
||||||
}
|
}
|
||||||
|
@ -124,7 +170,10 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
||||||
* Adds a new identity of the requested entity to the discovered information.
|
* Adds a new identity of the requested entity to the discovered information.
|
||||||
*
|
*
|
||||||
* @param identity the discovered entity's identity
|
* @param identity the discovered entity's identity
|
||||||
|
* @deprecated use {@link DiscoverInfoBuilder#addIdentity(Identity)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
|
// TODO: Remove in Smack 4.5.
|
||||||
public void addIdentity(Identity identity) {
|
public void addIdentity(Identity identity) {
|
||||||
identities.add(identity);
|
identities.add(identity);
|
||||||
identitiesSet.add(identity.getKey());
|
identitiesSet.add(identity.getKey());
|
||||||
|
@ -134,7 +183,10 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
||||||
* Adds identities to the DiscoverInfo stanza.
|
* Adds identities to the DiscoverInfo stanza.
|
||||||
*
|
*
|
||||||
* @param identitiesToAdd TODO javadoc me please
|
* @param identitiesToAdd TODO javadoc me please
|
||||||
|
* @deprecated use {@link DiscoverInfoBuilder#addIdentities(Collection)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
|
// TODO: Remove in Smack 4.5.
|
||||||
public void addIdentities(Collection<Identity> identitiesToAdd) {
|
public void addIdentities(Collection<Identity> identitiesToAdd) {
|
||||||
if (identitiesToAdd == null) return;
|
if (identitiesToAdd == null) return;
|
||||||
for (Identity identity : identitiesToAdd) {
|
for (Identity identity : identitiesToAdd) {
|
||||||
|
@ -142,11 +194,7 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns the discovered identities of an XMPP entity.
|
|
||||||
*
|
|
||||||
* @return an unmodifiable list of the discovered identities
|
|
||||||
*/
|
|
||||||
public List<Identity> getIdentities() {
|
public List<Identity> getIdentities() {
|
||||||
return Collections.unmodifiableList(identities);
|
return Collections.unmodifiableList(identities);
|
||||||
}
|
}
|
||||||
|
@ -180,15 +228,7 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns the node attribute that supplements the 'jid' attribute. A node is merely
|
|
||||||
* something that is associated with a JID and for which the JID can provide information.<p>
|
|
||||||
*
|
|
||||||
* Node attributes SHOULD be used only when trying to provide or query information which
|
|
||||||
* is not directly addressable.
|
|
||||||
*
|
|
||||||
* @return the node attribute that supplements the 'jid' attribute
|
|
||||||
*/
|
|
||||||
public String getNode() {
|
public String getNode() {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +241,10 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
||||||
* is not directly addressable.
|
* is not directly addressable.
|
||||||
*
|
*
|
||||||
* @param node the node attribute that supplements the 'jid' attribute
|
* @param node the node attribute that supplements the 'jid' attribute
|
||||||
|
* @deprecated use {@link DiscoverInfoBuilder#setNode(String)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
|
// TODO: Remove in Smack 4.5.
|
||||||
public void setNode(String node) {
|
public void setNode(String node) {
|
||||||
this.node = StringUtils.requireNullOrNotEmpty(node, "The node can not be the empty string");
|
this.node = StringUtils.requireNullOrNotEmpty(node, "The node can not be the empty string");
|
||||||
}
|
}
|
||||||
|
@ -256,11 +299,28 @@ public class DiscoverInfo extends IQ implements TypedCloneable<DiscoverInfo> {
|
||||||
return containsDuplicateFeatures;
|
return containsDuplicateFeatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DiscoverInfoBuilder asBuilder() {
|
||||||
|
return new DiscoverInfoBuilder(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Deprecate in favor of asBuilder().
|
||||||
@Override
|
@Override
|
||||||
public DiscoverInfo clone() {
|
public DiscoverInfo clone() {
|
||||||
return new DiscoverInfo(this);
|
return new DiscoverInfo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static DiscoverInfoBuilder builder(XMPPConnection connection) {
|
||||||
|
return new DiscoverInfoBuilder(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DiscoverInfoBuilder builder(IqBuilder iqData) {
|
||||||
|
return new DiscoverInfoBuilder(iqData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DiscoverInfoBuilder builder(String stanzaId) {
|
||||||
|
return new DiscoverInfoBuilder(stanzaId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the identity of a given XMPP entity. An entity may have many identities but all
|
* Represents the identity of a given XMPP entity. An entity may have many identities but all
|
||||||
* the identities SHOULD have the same name.<p>
|
* the identities SHOULD have the same name.<p>
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.disco.packet;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
import org.jivesoftware.smack.packet.IqBuilder;
|
||||||
|
import org.jivesoftware.smack.packet.IqBuilderWithBuild;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Feature;
|
||||||
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
||||||
|
|
||||||
|
public class DiscoverInfoBuilder extends IqBuilderWithBuild<DiscoverInfoBuilder, DiscoverInfo>
|
||||||
|
implements DiscoverInfoView {
|
||||||
|
|
||||||
|
private final List<Feature> features = new ArrayList<>();
|
||||||
|
private final List<Identity> identities = new ArrayList<>();
|
||||||
|
|
||||||
|
private String node;
|
||||||
|
|
||||||
|
DiscoverInfoBuilder(IqBuilder iqCommon) {
|
||||||
|
super(iqCommon);
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscoverInfoBuilder(XMPPConnection connection) {
|
||||||
|
super(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscoverInfoBuilder(String stanzaId) {
|
||||||
|
super(stanzaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscoverInfoBuilder(DiscoverInfo discoverInfo) {
|
||||||
|
super(discoverInfo.getStanzaId());
|
||||||
|
features.addAll(discoverInfo.getFeatures());
|
||||||
|
identities.addAll(discoverInfo.getIdentities());
|
||||||
|
node = discoverInfo.getNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoverInfoBuilder getThis() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscoverInfoBuilder addFeatures(Collection<String> features) {
|
||||||
|
for (String feature : features) {
|
||||||
|
addFeature(feature);
|
||||||
|
}
|
||||||
|
return getThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscoverInfoBuilder addFeature(String feature) {
|
||||||
|
return addFeature(new Feature(feature));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscoverInfoBuilder addFeature(Feature feature) {
|
||||||
|
features.add(feature);
|
||||||
|
return getThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscoverInfoBuilder addIdentities(Collection<Identity> identities) {
|
||||||
|
this.identities.addAll(identities);
|
||||||
|
return getThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscoverInfoBuilder addIdentity(Identity identity) {
|
||||||
|
identities.add(identity);
|
||||||
|
return getThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscoverInfoBuilder setNode(String node) {
|
||||||
|
this.node = node;
|
||||||
|
return getThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscoverInfo build() {
|
||||||
|
return new DiscoverInfo(this, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscoverInfo buildWithoutValidiation() {
|
||||||
|
return new DiscoverInfo(this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Feature> getFeatures() {
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Identity> getIdentities() {
|
||||||
|
return identities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNode() {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DiscoverInfoBuilder buildResponseFor(DiscoverInfo request, IQ.ResponseType responseType) {
|
||||||
|
DiscoverInfoBuilder builder = new DiscoverInfoBuilder(createResponse(request, responseType));
|
||||||
|
builder.setNode(request.getNode());
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.disco.packet;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.IqView;
|
||||||
|
|
||||||
|
public interface DiscoverInfoView extends IqView {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the discovered features of an XMPP entity.
|
||||||
|
*
|
||||||
|
* @return an unmodifiable list of the discovered features of an XMPP entity
|
||||||
|
*/
|
||||||
|
List<DiscoverInfo.Feature> getFeatures();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the discovered identities of an XMPP entity.
|
||||||
|
*
|
||||||
|
* @return an unmodifiable list of the discovered identities
|
||||||
|
*/
|
||||||
|
List<DiscoverInfo.Identity> getIdentities();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node attribute that supplements the 'jid' attribute. A node is merely
|
||||||
|
* something that is associated with a JID and for which the JID can provide information.<p>
|
||||||
|
*
|
||||||
|
* Node attributes SHOULD be used only when trying to provide or query information which
|
||||||
|
* is not directly addressable.
|
||||||
|
*
|
||||||
|
* @return the node attribute that supplements the 'jid' attribute
|
||||||
|
*/
|
||||||
|
String getNode();
|
||||||
|
}
|
|
@ -19,34 +19,34 @@ package org.jivesoftware.smackx.disco.provider;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.IqBuilder;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||||
import org.jivesoftware.smack.provider.IQProvider;
|
import org.jivesoftware.smack.provider.IqProvider;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
import org.jivesoftware.smack.util.ParserUtils;
|
||||||
import org.jivesoftware.smack.xml.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.jivesoftware.smack.xml.XmlPullParserException;
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||||
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The DiscoverInfoProvider parses Service Discovery information packets.
|
* The DiscoverInfoProvider parses Service Discovery information packets.
|
||||||
*
|
*
|
||||||
* @author Gaston Dombiak
|
* @author Gaston Dombiak
|
||||||
*/
|
*/
|
||||||
public class DiscoverInfoProvider extends IQProvider<DiscoverInfo> {
|
public class DiscoverInfoProvider extends IqProvider<DiscoverInfo> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DiscoverInfo parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
|
public DiscoverInfo parse(XmlPullParser parser, int initialDepth, IqBuilder iqData, XmlEnvironment xmlEnvironment)
|
||||||
DiscoverInfo discoverInfo = new DiscoverInfo();
|
throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
boolean done = false;
|
DiscoverInfoBuilder discoverInfoBuilder = DiscoverInfo.builder(iqData);
|
||||||
DiscoverInfo.Identity identity;
|
|
||||||
String category = "";
|
String node = parser.getAttributeValue("node");
|
||||||
String identityName = "";
|
discoverInfoBuilder.setNode(node);
|
||||||
String type = "";
|
|
||||||
String variable = "";
|
outerloop: while (true) {
|
||||||
String lang = "";
|
|
||||||
discoverInfo.setNode(parser.getAttributeValue("", "node"));
|
|
||||||
while (!done) {
|
|
||||||
XmlPullParser.Event eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
if (eventType == XmlPullParser.Event.START_ELEMENT) {
|
if (eventType == XmlPullParser.Event.START_ELEMENT) {
|
||||||
final String name = parser.getName();
|
final String name = parser.getName();
|
||||||
|
@ -54,39 +54,31 @@ public class DiscoverInfoProvider extends IQProvider<DiscoverInfo> {
|
||||||
if (namespace.equals(DiscoverInfo.NAMESPACE)) {
|
if (namespace.equals(DiscoverInfo.NAMESPACE)) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "identity":
|
case "identity":
|
||||||
// Initialize the variables from the parsed XML
|
String category = parser.getAttributeValue("category");
|
||||||
category = parser.getAttributeValue("", "category");
|
String identityName = parser.getAttributeValue("name");
|
||||||
identityName = parser.getAttributeValue("", "name");
|
String type = parser.getAttributeValue("type");
|
||||||
type = parser.getAttributeValue("", "type");
|
String lang = ParserUtils.getXmlLang(parser);
|
||||||
lang = parser.getAttributeValue(parser.getNamespace("xml"), "lang");
|
DiscoverInfo.Identity identity = new DiscoverInfo.Identity(category, type, identityName, lang);
|
||||||
|
discoverInfoBuilder.addIdentity(identity);
|
||||||
break;
|
break;
|
||||||
case "feature":
|
case "feature":
|
||||||
// Initialize the variables from the parsed XML
|
String feature = parser.getAttributeValue("var");
|
||||||
variable = parser.getAttributeValue("", "var");
|
discoverInfoBuilder.addFeature(feature);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Otherwise, it must be a packet extension.
|
// Otherwise, it must be a packet extension.
|
||||||
else {
|
else {
|
||||||
PacketParserUtils.addExtensionElement(discoverInfo, parser, xmlEnvironment);
|
PacketParserUtils.addExtensionElement(discoverInfoBuilder, parser, xmlEnvironment);
|
||||||
}
|
}
|
||||||
} else if (eventType == XmlPullParser.Event.END_ELEMENT) {
|
} else if (eventType == XmlPullParser.Event.END_ELEMENT) {
|
||||||
if (parser.getName().equals("identity")) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
// Create a new identity and add it to the discovered info.
|
break outerloop;
|
||||||
identity = new DiscoverInfo.Identity(category, type, identityName, lang);
|
|
||||||
discoverInfo.addIdentity(identity);
|
|
||||||
}
|
|
||||||
if (parser.getName().equals("feature")) {
|
|
||||||
// Create a new feature and add it to the discovered info.
|
|
||||||
boolean notADuplicateFeature = discoverInfo.addFeature(variable);
|
|
||||||
assert notADuplicateFeature;
|
|
||||||
}
|
|
||||||
if (parser.getName().equals("query")) {
|
|
||||||
done = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DiscoverInfo discoverInfo = discoverInfoBuilder.buildWithoutValidiation();
|
||||||
return discoverInfo;
|
return discoverInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
import org.jivesoftware.smack.StanzaListener;
|
import org.jivesoftware.smack.StanzaListener;
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||||
import org.jivesoftware.smack.filter.FlexibleStanzaTypeFilter;
|
import org.jivesoftware.smack.filter.FlexibleStanzaTypeFilter;
|
||||||
import org.jivesoftware.smack.filter.OrFilter;
|
import org.jivesoftware.smack.filter.OrFilter;
|
||||||
|
@ -120,10 +121,12 @@ public abstract class Node {
|
||||||
* @throws InterruptedException if the calling thread was interrupted.
|
* @throws InterruptedException if the calling thread was interrupted.
|
||||||
*/
|
*/
|
||||||
public DiscoverInfo discoverInfo() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
public DiscoverInfo discoverInfo() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||||
DiscoverInfo info = new DiscoverInfo();
|
XMPPConnection connection = pubSubManager.getConnection();
|
||||||
info.setTo(pubSubManager.getServiceJid());
|
DiscoverInfo discoverInfoRequest = DiscoverInfo.builder(connection)
|
||||||
info.setNode(getId());
|
.to(pubSubManager.getServiceJid())
|
||||||
return pubSubManager.getConnection().createStanzaCollectorAndSend(info).nextResultOrThrow();
|
.setNode(getId())
|
||||||
|
.build();
|
||||||
|
return connection.createStanzaCollectorAndSend(discoverInfoRequest).nextResultOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -289,11 +289,13 @@ public final class PubSubManager extends Manager {
|
||||||
Node node = nodeMap.get(id);
|
Node node = nodeMap.get(id);
|
||||||
|
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
DiscoverInfo info = new DiscoverInfo();
|
XMPPConnection connection = connection();
|
||||||
info.setTo(pubSubService);
|
DiscoverInfo info = DiscoverInfo.builder(connection)
|
||||||
info.setNode(id);
|
.to(pubSubService)
|
||||||
|
.setNode(id)
|
||||||
|
.build();
|
||||||
|
|
||||||
DiscoverInfo infoReply = connection().createStanzaCollectorAndSend(info).nextResultOrThrow();
|
DiscoverInfo infoReply = connection.createStanzaCollectorAndSend(info).nextResultOrThrow();
|
||||||
|
|
||||||
if (infoReply.hasIdentity(PubSub.ELEMENT, "leaf")) {
|
if (infoReply.hasIdentity(PubSub.ELEMENT, "leaf")) {
|
||||||
node = new LeafNode(this, id);
|
node = new LeafNode(this, id);
|
||||||
|
|
|
@ -25,9 +25,11 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.Element;
|
import org.jivesoftware.smack.packet.Element;
|
||||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||||
import org.jivesoftware.smack.packet.Stanza;
|
import org.jivesoftware.smack.packet.StanzaView;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
|
||||||
|
@ -44,6 +46,8 @@ public class DataForm implements ExtensionElement {
|
||||||
public static final String NAMESPACE = "jabber:x:data";
|
public static final String NAMESPACE = "jabber:x:data";
|
||||||
public static final String ELEMENT = "x";
|
public static final String ELEMENT = "x";
|
||||||
|
|
||||||
|
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
/**
|
/**
|
||||||
* This stanza contains a form to fill out. Display it to the user (if your program can).
|
* This stanza contains a form to fill out. Display it to the user (if your program can).
|
||||||
|
@ -351,12 +355,13 @@ public class DataForm implements ExtensionElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get data form from stanza.
|
* Get data form from a stanza.
|
||||||
* @param packet TODO javadoc me please
|
*
|
||||||
|
* @param stanzaView the stanza to get data form from.
|
||||||
* @return the DataForm or null
|
* @return the DataForm or null
|
||||||
*/
|
*/
|
||||||
public static DataForm from(Stanza packet) {
|
public static DataForm from(StanzaView stanzaView) {
|
||||||
return (DataForm) packet.getExtension(ELEMENT, NAMESPACE);
|
return (DataForm) stanzaView.getExtension(QNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -49,6 +49,7 @@ import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost;
|
||||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
||||||
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverItems;
|
import org.jivesoftware.smackx.disco.packet.DiscoverItems;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverItems.Item;
|
import org.jivesoftware.smackx.disco.packet.DiscoverItems.Item;
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ public class Socks5ByteStreamManagerTest {
|
||||||
|
|
||||||
FeatureNotSupportedException e = assertThrows(FeatureNotSupportedException.class, () -> {
|
FeatureNotSupportedException e = assertThrows(FeatureNotSupportedException.class, () -> {
|
||||||
// build empty discover info as reply if targets features are queried
|
// build empty discover info as reply if targets features are queried
|
||||||
DiscoverInfo discoverInfo = new DiscoverInfo();
|
DiscoverInfo discoverInfo = DiscoverInfo.builder("disco-1").build();
|
||||||
protocol.addResponse(discoverInfo);
|
protocol.addResponse(discoverInfo);
|
||||||
|
|
||||||
// start SOCKS5 Bytestream
|
// start SOCKS5 Bytestream
|
||||||
|
@ -181,11 +182,11 @@ public class Socks5ByteStreamManagerTest {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// build discover info that supports the SOCKS5 feature
|
// build discover info that supports the SOCKS5 feature
|
||||||
DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
||||||
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
||||||
|
|
||||||
// return that SOCKS5 is supported if target is queried
|
// return that SOCKS5 is supported if target is queried
|
||||||
protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover items with no proxy items
|
// build discover items with no proxy items
|
||||||
|
@ -233,11 +234,11 @@ public class Socks5ByteStreamManagerTest {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// build discover info that supports the SOCKS5 feature
|
// build discover info that supports the SOCKS5 feature
|
||||||
DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
||||||
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
||||||
|
|
||||||
// return that SOCKS5 is supported if target is queried
|
// return that SOCKS5 is supported if target is queried
|
||||||
protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover items containing a proxy item
|
// build discover items containing a proxy item
|
||||||
|
@ -252,12 +253,12 @@ public class Socks5ByteStreamManagerTest {
|
||||||
|
|
||||||
// build discover info for proxy containing information about NOT being a Socks5
|
// build discover info for proxy containing information about NOT being a Socks5
|
||||||
// proxy
|
// proxy
|
||||||
DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
||||||
Identity identity = new Identity("noproxy", proxyJID.toString(), "bytestreams");
|
Identity identity = new Identity("noproxy", proxyJID.toString(), "bytestreams");
|
||||||
proxyInfo.addIdentity(identity);
|
proxyInfo.addIdentity(identity);
|
||||||
|
|
||||||
// return the proxy identity if proxy is queried
|
// return the proxy identity if proxy is queried
|
||||||
protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
SmackException e = assertThrows(SmackException.class, () -> {
|
SmackException e = assertThrows(SmackException.class, () -> {
|
||||||
|
@ -294,9 +295,10 @@ public class Socks5ByteStreamManagerTest {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// build discover info that supports the SOCKS5 feature
|
// build discover info that supports the SOCKS5 feature
|
||||||
DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
DiscoverInfoBuilder discoverInfoBuilder = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
||||||
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
discoverInfoBuilder.addFeature(Bytestream.NAMESPACE);
|
||||||
|
|
||||||
|
DiscoverInfo discoverInfo = discoverInfoBuilder.build();
|
||||||
// return that SOCKS5 is supported if target is queried
|
// return that SOCKS5 is supported if target is queried
|
||||||
protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
@ -313,12 +315,12 @@ public class Socks5ByteStreamManagerTest {
|
||||||
|
|
||||||
// build discover info for proxy containing information about NOT being a Socks5
|
// build discover info for proxy containing information about NOT being a Socks5
|
||||||
// proxy
|
// proxy
|
||||||
DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
||||||
Identity identity = new Identity("noproxy", proxyJID.toString(), "bytestreams");
|
Identity identity = new Identity("noproxy", proxyJID.toString(), "bytestreams");
|
||||||
proxyInfo.addIdentity(identity);
|
proxyInfo.addIdentity(identity);
|
||||||
|
|
||||||
// return the proxy identity if proxy is queried
|
// return the proxy identity if proxy is queried
|
||||||
protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
SmackException e = assertThrows(SmackException.class, () -> {
|
SmackException e = assertThrows(SmackException.class, () -> {
|
||||||
|
@ -376,11 +378,11 @@ public class Socks5ByteStreamManagerTest {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// build discover info that supports the SOCKS5 feature
|
// build discover info that supports the SOCKS5 feature
|
||||||
DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
||||||
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
||||||
|
|
||||||
// return that SOCKS5 is supported if target is queried
|
// return that SOCKS5 is supported if target is queried
|
||||||
protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover items containing a proxy item
|
// build discover items containing a proxy item
|
||||||
|
@ -394,12 +396,12 @@ public class Socks5ByteStreamManagerTest {
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover info for proxy containing information about being a SOCKS5 proxy
|
// build discover info for proxy containing information about being a SOCKS5 proxy
|
||||||
DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
||||||
Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams");
|
Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams");
|
||||||
proxyInfo.addIdentity(identity);
|
proxyInfo.addIdentity(identity);
|
||||||
|
|
||||||
// return the socks5 bytestream proxy identity if proxy is queried
|
// return the socks5 bytestream proxy identity if proxy is queried
|
||||||
protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build a socks5 stream host info containing the address and the port of the
|
// build a socks5 stream host info containing the address and the port of the
|
||||||
|
@ -458,11 +460,11 @@ public class Socks5ByteStreamManagerTest {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// build discover info that supports the SOCKS5 feature
|
// build discover info that supports the SOCKS5 feature
|
||||||
DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
||||||
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
||||||
|
|
||||||
// return that SOCKS5 is supported if target is queried
|
// return that SOCKS5 is supported if target is queried
|
||||||
protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover items containing a proxy item
|
// build discover items containing a proxy item
|
||||||
|
@ -476,12 +478,12 @@ public class Socks5ByteStreamManagerTest {
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover info for proxy containing information about being a SOCKS5 proxy
|
// build discover info for proxy containing information about being a SOCKS5 proxy
|
||||||
DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
||||||
Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams");
|
Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams");
|
||||||
proxyInfo.addIdentity(identity);
|
proxyInfo.addIdentity(identity);
|
||||||
|
|
||||||
// return the socks5 bytestream proxy identity if proxy is queried
|
// return the socks5 bytestream proxy identity if proxy is queried
|
||||||
protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build a socks5 stream host info containing the address and the port of the
|
// build a socks5 stream host info containing the address and the port of the
|
||||||
|
@ -545,11 +547,11 @@ public class Socks5ByteStreamManagerTest {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// build discover info that supports the SOCKS5 feature
|
// build discover info that supports the SOCKS5 feature
|
||||||
DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
DiscoverInfoBuilder discoverInfoBuilder = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
||||||
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
discoverInfoBuilder.addFeature(Bytestream.NAMESPACE);
|
||||||
|
|
||||||
// return that SOCKS5 is supported if target is queried
|
// return that SOCKS5 is supported if target is queried
|
||||||
protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(discoverInfoBuilder.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover items containing a proxy item
|
// build discover items containing a proxy item
|
||||||
|
@ -563,12 +565,12 @@ public class Socks5ByteStreamManagerTest {
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover info for proxy containing information about being a SOCKS5 proxy
|
// build discover info for proxy containing information about being a SOCKS5 proxy
|
||||||
DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
||||||
Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams");
|
Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams");
|
||||||
proxyInfo.addIdentity(identity);
|
proxyInfo.addIdentity(identity);
|
||||||
|
|
||||||
// return the socks5 bytestream proxy identity if proxy is queried
|
// return the socks5 bytestream proxy identity if proxy is queried
|
||||||
protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build a socks5 stream host info containing the address and the port of the
|
// build a socks5 stream host info containing the address and the port of the
|
||||||
|
@ -639,11 +641,11 @@ public class Socks5ByteStreamManagerTest {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// build discover info that supports the SOCKS5 feature
|
// build discover info that supports the SOCKS5 feature
|
||||||
DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
||||||
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
||||||
|
|
||||||
// return that SOCKS5 is supported if target is queried
|
// return that SOCKS5 is supported if target is queried
|
||||||
protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover items containing a proxy item
|
// build discover items containing a proxy item
|
||||||
|
@ -657,12 +659,12 @@ public class Socks5ByteStreamManagerTest {
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover info for proxy containing information about being a SOCKS5 proxy
|
// build discover info for proxy containing information about being a SOCKS5 proxy
|
||||||
DiscoverInfo proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
DiscoverInfoBuilder proxyInfo = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
||||||
Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams");
|
Identity identity = new Identity("proxy", proxyJID.toString(), "bytestreams");
|
||||||
proxyInfo.addIdentity(identity);
|
proxyInfo.addIdentity(identity);
|
||||||
|
|
||||||
// return the socks5 bytestream proxy identity if proxy is queried
|
// return the socks5 bytestream proxy identity if proxy is queried
|
||||||
protocol.addResponse(proxyInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(proxyInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build a socks5 stream host info containing the address and the port of the
|
// build a socks5 stream host info containing the address and the port of the
|
||||||
|
@ -765,11 +767,11 @@ public class Socks5ByteStreamManagerTest {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// build discover info that supports the SOCKS5 feature
|
// build discover info that supports the SOCKS5 feature
|
||||||
DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
||||||
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
||||||
|
|
||||||
// return that SOCKS5 is supported if target is queried
|
// return that SOCKS5 is supported if target is queried
|
||||||
protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover items containing no proxy item
|
// build discover items containing no proxy item
|
||||||
|
@ -1009,11 +1011,11 @@ public class Socks5ByteStreamManagerTest {
|
||||||
Verification<Bytestream, Bytestream> streamHostUsedVerification, Socks5TestProxy socks5TestProxy)
|
Verification<Bytestream, Bytestream> streamHostUsedVerification, Socks5TestProxy socks5TestProxy)
|
||||||
throws XmppStringprepException {
|
throws XmppStringprepException {
|
||||||
// build discover info that supports the SOCKS5 feature
|
// build discover info that supports the SOCKS5 feature
|
||||||
DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
DiscoverInfoBuilder discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
|
||||||
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
discoverInfo.addFeature(Bytestream.NAMESPACE);
|
||||||
|
|
||||||
// return that SOCKS5 is supported if target is queried
|
// return that SOCKS5 is supported if target is queried
|
||||||
protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver,
|
protocol.addResponse(discoverInfo.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover items containing a proxy item
|
// build discover items containing a proxy item
|
||||||
|
@ -1030,22 +1032,22 @@ public class Socks5ByteStreamManagerTest {
|
||||||
* build discover info for proxy "proxy2.xmpp-server" containing information about being a
|
* build discover info for proxy "proxy2.xmpp-server" containing information about being a
|
||||||
* SOCKS5 proxy
|
* SOCKS5 proxy
|
||||||
*/
|
*/
|
||||||
DiscoverInfo proxyInfo1 = Socks5PacketUtils.createDiscoverInfo(JidCreate.from("proxy2.xmpp-server"),
|
DiscoverInfoBuilder proxyInfo1 = Socks5PacketUtils.createDiscoverInfo(JidCreate.from("proxy2.xmpp-server"),
|
||||||
initiatorJID);
|
initiatorJID);
|
||||||
Identity identity1 = new Identity("proxy", "proxy2.xmpp-server", "bytestreams");
|
Identity identity1 = new Identity("proxy", "proxy2.xmpp-server", "bytestreams");
|
||||||
proxyInfo1.addIdentity(identity1);
|
proxyInfo1.addIdentity(identity1);
|
||||||
|
|
||||||
// return the SOCKS5 bytestream proxy identity if proxy is queried
|
// return the SOCKS5 bytestream proxy identity if proxy is queried
|
||||||
protocol.addResponse(proxyInfo1, Verification.correspondingSenderReceiver,
|
protocol.addResponse(proxyInfo1.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
// build discover info for proxy containing information about being a SOCKS5 proxy
|
// build discover info for proxy containing information about being a SOCKS5 proxy
|
||||||
DiscoverInfo proxyInfo2 = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
DiscoverInfoBuilder proxyInfo2 = Socks5PacketUtils.createDiscoverInfo(proxyJID, initiatorJID);
|
||||||
Identity identity2 = new Identity("proxy", proxyJID.toString(), "bytestreams");
|
Identity identity2 = new Identity("proxy", proxyJID.toString(), "bytestreams");
|
||||||
proxyInfo2.addIdentity(identity2);
|
proxyInfo2.addIdentity(identity2);
|
||||||
|
|
||||||
// return the SOCKS5 bytestream proxy identity if proxy is queried
|
// return the SOCKS5 bytestream proxy identity if proxy is queried
|
||||||
protocol.addResponse(proxyInfo2, Verification.correspondingSenderReceiver,
|
protocol.addResponse(proxyInfo2.build(), Verification.correspondingSenderReceiver,
|
||||||
Verification.requestTypeGET);
|
Verification.requestTypeGET);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.jivesoftware.smack.packet.IQ;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream;
|
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||||
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverItems;
|
import org.jivesoftware.smackx.disco.packet.DiscoverItems;
|
||||||
|
|
||||||
import org.jxmpp.jid.Jid;
|
import org.jxmpp.jid.Jid;
|
||||||
|
@ -88,11 +89,12 @@ public class Socks5PacketUtils {
|
||||||
* @param to the initiator
|
* @param to the initiator
|
||||||
* @return response to an info discovery request
|
* @return response to an info discovery request
|
||||||
*/
|
*/
|
||||||
public static DiscoverInfo createDiscoverInfo(Jid from, Jid to) {
|
public static DiscoverInfoBuilder createDiscoverInfo(Jid from, Jid to) {
|
||||||
DiscoverInfo discoverInfo = new DiscoverInfo();
|
DiscoverInfoBuilder discoverInfo = DiscoverInfo.builder("disco-1")
|
||||||
discoverInfo.setFrom(from);
|
.from(from)
|
||||||
discoverInfo.setTo(to);
|
.to(to)
|
||||||
discoverInfo.setType(IQ.Type.result);
|
.ofType(IQ.Type.result)
|
||||||
|
;
|
||||||
return discoverInfo;
|
return discoverInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.jivesoftware.smackx.InitExtensions;
|
||||||
import org.jivesoftware.smackx.caps.cache.EntityCapsPersistentCache;
|
import org.jivesoftware.smackx.caps.cache.EntityCapsPersistentCache;
|
||||||
import org.jivesoftware.smackx.caps.cache.SimpleDirectoryPersistentCache;
|
import org.jivesoftware.smackx.caps.cache.SimpleDirectoryPersistentCache;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||||
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder;
|
||||||
import org.jivesoftware.smackx.xdata.FormField;
|
import org.jivesoftware.smackx.xdata.FormField;
|
||||||
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
||||||
|
|
||||||
|
@ -97,11 +98,10 @@ public class EntityCapsManagerTest extends InitExtensions {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DiscoverInfo createComplexSamplePacket() throws XmppStringprepException {
|
private static DiscoverInfo createComplexSamplePacket() throws XmppStringprepException {
|
||||||
DiscoverInfo di = new DiscoverInfo();
|
DiscoverInfoBuilder di = DiscoverInfo.builder("disco1");
|
||||||
di.setFrom(JidCreate.from("benvolio@capulet.lit/230193"));
|
di.from(JidCreate.from("benvolio@capulet.lit/230193"));
|
||||||
di.setStanzaId("disco1");
|
di.to(JidCreate.from("juliet@capulet.lit/chamber"));
|
||||||
di.setTo(JidCreate.from("juliet@capulet.lit/chamber"));
|
di.ofType(IQ.Type.result);
|
||||||
di.setType(IQ.Type.result);
|
|
||||||
|
|
||||||
Collection<DiscoverInfo.Identity> identities = new LinkedList<DiscoverInfo.Identity>();
|
Collection<DiscoverInfo.Identity> identities = new LinkedList<DiscoverInfo.Identity>();
|
||||||
DiscoverInfo.Identity i = new DiscoverInfo.Identity("client", "pc", "Psi 0.11", "en");
|
DiscoverInfo.Identity i = new DiscoverInfo.Identity("client", "pc", "Psi 0.11", "en");
|
||||||
|
@ -144,15 +144,14 @@ public class EntityCapsManagerTest extends InitExtensions {
|
||||||
df.addField(ff.build());
|
df.addField(ff.build());
|
||||||
|
|
||||||
di.addExtension(df);
|
di.addExtension(df);
|
||||||
return di;
|
return di.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DiscoverInfo createMalformedDiscoverInfo() throws XmppStringprepException {
|
private static DiscoverInfo createMalformedDiscoverInfo() throws XmppStringprepException {
|
||||||
DiscoverInfo di = new DiscoverInfo();
|
DiscoverInfoBuilder di = DiscoverInfo.builder("disco1");
|
||||||
di.setFrom(JidCreate.from("benvolio@capulet.lit/230193"));
|
di.from("benvolio@capulet.lit/230193");
|
||||||
di.setStanzaId("disco1");
|
di.to(")juliet@capulet.lit/chamber");
|
||||||
di.setTo(JidCreate.from(")juliet@capulet.lit/chamber"));
|
di.ofType(IQ.Type.result);
|
||||||
di.setType(IQ.Type.result);
|
|
||||||
|
|
||||||
Collection<DiscoverInfo.Identity> identities = new LinkedList<DiscoverInfo.Identity>();
|
Collection<DiscoverInfo.Identity> identities = new LinkedList<DiscoverInfo.Identity>();
|
||||||
DiscoverInfo.Identity i = new DiscoverInfo.Identity("client", "pc", "Psi 0.11", "en");
|
DiscoverInfo.Identity i = new DiscoverInfo.Identity("client", "pc", "Psi 0.11", "en");
|
||||||
|
@ -217,7 +216,8 @@ public class EntityCapsManagerTest extends InitExtensions {
|
||||||
|
|
||||||
di.addExtension(df);
|
di.addExtension(df);
|
||||||
|
|
||||||
return di;
|
DiscoverInfo discoverInfo = di.buildWithoutValidiation();
|
||||||
|
return discoverInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File createTempDirectory() throws IOException {
|
public static File createTempDirectory() throws IOException {
|
||||||
|
|
|
@ -30,8 +30,9 @@ public class RoomInfoTest {
|
||||||
public void validateRoomWithEmptyForm() {
|
public void validateRoomWithEmptyForm() {
|
||||||
DataForm dataForm = new DataForm(DataForm.Type.result);
|
DataForm dataForm = new DataForm(DataForm.Type.result);
|
||||||
|
|
||||||
DiscoverInfo discoInfo = new DiscoverInfo();
|
DiscoverInfo discoInfo = DiscoverInfo.builder("disco1")
|
||||||
discoInfo.addExtension(dataForm);
|
.addExtension(dataForm)
|
||||||
|
.build();
|
||||||
RoomInfo roomInfo = new RoomInfo(discoInfo);
|
RoomInfo roomInfo = new RoomInfo(discoInfo);
|
||||||
assertTrue(roomInfo.getDescription().isEmpty());
|
assertTrue(roomInfo.getDescription().isEmpty());
|
||||||
assertTrue(roomInfo.getSubject().isEmpty());
|
assertTrue(roomInfo.getSubject().isEmpty());
|
||||||
|
@ -54,8 +55,9 @@ public class RoomInfoTest {
|
||||||
occupants.addValue("3");
|
occupants.addValue("3");
|
||||||
dataForm.addField(occupants.build());
|
dataForm.addField(occupants.build());
|
||||||
|
|
||||||
DiscoverInfo discoInfo = new DiscoverInfo();
|
DiscoverInfo discoInfo = DiscoverInfo.builder("disco1")
|
||||||
discoInfo.addExtension(dataForm);
|
.addExtension(dataForm)
|
||||||
|
.build();
|
||||||
RoomInfo roomInfo = new RoomInfo(discoInfo);
|
RoomInfo roomInfo = new RoomInfo(discoInfo);
|
||||||
assertEquals("The place for all good witches!", roomInfo.getDescription());
|
assertEquals("The place for all good witches!", roomInfo.getDescription());
|
||||||
assertEquals("Spells", roomInfo.getSubject());
|
assertEquals("Spells", roomInfo.getSubject());
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.ThreadedDummyConnection;
|
import org.jivesoftware.smack.ThreadedDummyConnection;
|
||||||
import org.jivesoftware.smack.XMPPException;
|
import org.jivesoftware.smack.XMPPException;
|
||||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||||
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
import org.jivesoftware.smack.packet.IQ.Type;
|
import org.jivesoftware.smack.packet.IQ.Type;
|
||||||
import org.jivesoftware.smack.packet.StanzaError;
|
import org.jivesoftware.smack.packet.StanzaError;
|
||||||
import org.jivesoftware.smack.packet.StanzaError.Condition;
|
import org.jivesoftware.smack.packet.StanzaError.Condition;
|
||||||
|
@ -33,6 +34,7 @@ import org.jivesoftware.smack.packet.StanzaError.Condition;
|
||||||
import org.jivesoftware.smackx.InitExtensions;
|
import org.jivesoftware.smackx.InitExtensions;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
||||||
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfoBuilder;
|
||||||
import org.jivesoftware.smackx.pubsub.packet.PubSub;
|
import org.jivesoftware.smackx.pubsub.packet.PubSub;
|
||||||
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
||||||
|
|
||||||
|
@ -55,12 +57,14 @@ public class ConfigureFormTest extends InitExtensions {
|
||||||
public void getConfigFormWithInsufficientPrivileges() throws XMPPException, SmackException, IOException, InterruptedException {
|
public void getConfigFormWithInsufficientPrivileges() throws XMPPException, SmackException, IOException, InterruptedException {
|
||||||
ThreadedDummyConnection con = ThreadedDummyConnection.newInstance();
|
ThreadedDummyConnection con = ThreadedDummyConnection.newInstance();
|
||||||
PubSubManager mgr = new PubSubManager(con, PubSubManagerTest.DUMMY_PUBSUB_SERVICE);
|
PubSubManager mgr = new PubSubManager(con, PubSubManagerTest.DUMMY_PUBSUB_SERVICE);
|
||||||
DiscoverInfo info = new DiscoverInfo();
|
DiscoverInfoBuilder info = DiscoverInfo.builder("disco-result")
|
||||||
info.setType(Type.result);
|
.ofType(IQ.Type.result)
|
||||||
info.setFrom(PubSubManagerTest.DUMMY_PUBSUB_SERVICE);
|
.from(PubSubManagerTest.DUMMY_PUBSUB_SERVICE);
|
||||||
Identity ident = new Identity("pubsub", null, "leaf");
|
Identity ident = new Identity("pubsub", null, "leaf");
|
||||||
info.addIdentity(ident);
|
info.addIdentity(ident);
|
||||||
con.addIQReply(info);
|
|
||||||
|
DiscoverInfo discoverInfo = info.build();
|
||||||
|
con.addIQReply(discoverInfo);
|
||||||
|
|
||||||
Node node = mgr.getNode("princely_musings");
|
Node node = mgr.getNode("princely_musings");
|
||||||
|
|
||||||
|
@ -84,10 +88,12 @@ public class ConfigureFormTest extends InitExtensions {
|
||||||
public void getConfigFormWithTimeout() throws XMPPException, SmackException, InterruptedException {
|
public void getConfigFormWithTimeout() throws XMPPException, SmackException, InterruptedException {
|
||||||
ThreadedDummyConnection con = new ThreadedDummyConnection();
|
ThreadedDummyConnection con = new ThreadedDummyConnection();
|
||||||
PubSubManager mgr = new PubSubManager(con, PubSubManagerTest.DUMMY_PUBSUB_SERVICE);
|
PubSubManager mgr = new PubSubManager(con, PubSubManagerTest.DUMMY_PUBSUB_SERVICE);
|
||||||
DiscoverInfo info = new DiscoverInfo();
|
DiscoverInfoBuilder info = DiscoverInfo.builder("disco-result");
|
||||||
Identity ident = new Identity("pubsub", null, "leaf");
|
Identity ident = new Identity("pubsub", null, "leaf");
|
||||||
info.addIdentity(ident);
|
info.addIdentity(ident);
|
||||||
con.addIQReply(info);
|
|
||||||
|
DiscoverInfo discoverInfo = info.build();
|
||||||
|
con.addIQReply(discoverInfo);
|
||||||
|
|
||||||
Node node = mgr.getNode("princely_musings");
|
Node node = mgr.getNode("princely_musings");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue