StupidBeauty
Read times:1147Posted at:Tue Mar 18 03:20:43 2014
- no title specified

Smack3.4.1文档翻译:提供者架构:数据包扩展及自定义信息/查询对,Provider Architecture: Packet Extensions and Custom IQ's

介绍

Smack提供 者架构, 是一个用于插入针对 数据包扩展和信息/查询对数据包 的自定义XML解析功能的系统。标准 Smack扩展 就是使用这个提供者架构来开发的。 有两种类型的提供者:

  • •. IQProvider -- 将信息/查询(IQ)请求解析为Java 对象。

  • •. 扩展提供 者( Extension Provider -- 将附加于数据包上的 XML 子文档解析为PacketExtension 实例。

默认情况下,Smack只知道如何处理少数几个命名空间中的一些标准数据包和子数据包,例如:

  • •.jabber:iq:auth

  • •.jabber:iq:roster

  • •.jabber:iq:register

XMPP 标准中还有狠多其它的信息/查询类型和扩展,并且,显然可以以自定义扩展的形式加入无限种新的类型。为了支持这种情况,我们通过Smack 和用户自行开发的提供者来构造出一种可扩展的解析机制。

每当 从某个数据包中发现了一个数据包扩展时,对应 的解析工作会被传递给正确的提供者。每个提供 者,或者实现 了PacketExtensionProvider 接口,或者是一个标准的Java Bean。 在第一种情况下,每个扩展提供 者都要通过 XML 拉解析器 来解析原始的XML 流,以构造一个对象。 在第二种情况下, 会使用豆子内省(bean introspection)机制来尝试自动根据数据包扩展 子元素中的值来设置 该类的属性。

如果对于某个元素名字和命名空间的组合不存在对应注册的扩展提供者的话,Smack会将该子数据包中所有的顶级元素储存在一个DefaultPacketExtension 对象中,然后将它附加到数据包中。

对于 这些提供者的管理是由 ProviderManager 类来实现的。 有多种方法可将提供者添加到管理器中。

  • •.调用addXXProvider方法 - 妳可以直接调用适当的添加方法。

    ProviderManager.getInstance().addIQProvider("element", "namespace", new MyIQProvider());

    ProviderManager.getInstance().addExtensionProvider("element", "namespace", new MyExtProvider());

  • •.添加一个载入器 - 妳可以添加一个ProviderLoader,它会将用来向载入多个提供者(两种类型的都可以)的手段注入到管理器中去。这是Smack 用来从Smack 的文件格式中(具体地是使用ProviderFileLoader)载入提供者的机制。在具体的实现中,可以从任意来源处提供 用来载入提供者的手段,或者也可以简单地复用ProviderFileLoader来从自己的提供者文件中载入提供者。

    ProviderManager.getInstance().addLoader(new ProviderFileLoader(FileUtils.getStreamForUrl("classpath:com/myco/provider/myco_custom.providers", null)));

  • •.虚拟机参数 - 妳可以通过虚拟机参数 smack.provider.file 来添加一个提供者文件。这会在启动时,Smack 进行初始化的时候载入指定的URL 处的文件。这也会假设采用默认的配置选项,因为它要求 VmArgInitializer 存在于启动配置选项中。

    -Dsmack.provider.file=classpath:com/myco/provider/myco_custom.providers

    -Dsmack.provider.file=file:///c:/myco/provider/myco_custom.providers

信息/查询 对( IQ )提供者

信息/查询对提供者类,可以实现IQProvider接口,或者也可以继承IQ类。在前一种情况下,每个IQProvider都要解析原始的XML流,以用来创建一个IQ实例。在后一种情况下,会通过豆子内省(bean introspection)来尝试自动使用从IQ 数据包XML 中找到的值来设置该IQ 实例的属性。例如,一个XMPP时间数据包会是以下的样子:

内省

时间数据包

<iq type='result' to='joe@example.com' from='mary@example.com' id='time_1'>

<query xmlns='jabber:iq:time'>

<utc>20020910T17:58:35</utc>

<tz>MDT</tz>

<display>Tue Sep 10 12:58:35 2002</display>

</query>

</iq>

时间IQ

class Time extends IQ {

private Date utc;

private TimeZone timeZone;

private String display;

@Override

public String getChildElementXML() {

return null;

}

public void setUtc(String utcString) {

try {

utc = StringUtils.parseDate(utcString);

} catch (ParseException e) {

}

}

public void setTimeZone(String zone) {

timeZone = TimeZone.getTimeZone(zone);

}

public void setDisplay(String timeDisplay) {

display = timeDisplay;

}

}

内省服务会自动地尝试根据该IQ 实例预期的类型来将XML 中的字符串(String)值转换成逻辑值(boolean)、整数值(int)、长整数值(long)、浮点数值(float)、双精度浮点数值(double)或类(Class)。

IQProvider实现

探索发现(Disco)条目(Item)数据包

<iq type='result' from='shakespeare.lit' to='romeo@montague.net/orchard' id='items1'>

<query xmlns='http://jabber.org/protocol/disco#items'>

<item jid='people.shakespeare.lit' name='Directory of Characters'/>

<item jid='plays.shakespeare.lit' name='Play-Specific Chatrooms'/>

<item jid='mim.shakespeare.lit' name='Gateway to Marlowe IM'/>

<item jid='words.shakespeare.lit' name='Shakespearean Lexicon'/>

<item jid='globe.shakespeare.lit' name='Calendar of Performances'/>

<item jid='headlines.shakespeare.lit' name='Latest Shakespearean News'/>

<item jid='catalog.shakespeare.lit' name='Buy Shakespeare Stuff!'/>

<item jid='en2fr.shakespeare.lit' name='French Translation Service'/>

</query>

</iq>

探索发现条目IQProvider

public class DiscoverItemsProvider implements IQProvider {

public IQ parseIQ(XmlPullParser parser) throws Exception {

DiscoverItems discoverItems = new DiscoverItems();

boolean done = false;

DiscoverItems.Item item;

String jid = "";

String name = "";

String action = "";

String node = "";

discoverItems.setNode(parser.getAttributeValue("", "node"));

while (!done) {

int eventType = parser.next();

if (eventType == XmlPullParser.START_TAG && "item".equals(parser.getName())) {

// 从解析的XML中初始化对应的变量

jid = parser.getAttributeValue("", "jid");

name = parser.getAttributeValue("", "name");

node = parser.getAttributeValue("", "node");

action = parser.getAttributeValue("", "action");

}

else if (eventType == XmlPullParser.END_TAG && "item".equals(parser.getName())) {

// 创建 一个新的 Item ,将它添加到 DiscoverItems

item = new DiscoverItems.Item(jid);

item.setName(name);

item.setNode(node);

item.setAction(action);

discoverItems.addItem(item);

}

else if (eventType == XmlPullParser.END_TAG && "query".equals(parser.getName())) {

done = true;

}

}

return discoverItems;

}

}

扩展提供

数据包扩展提供者负责解析数据包扩展,它们是信息/查询对、消息及在线状态数据包中某个自定义命名空间中的子元素。

Pubsub Subscription数据包

<iq type='result' from='pubsub.shakespeare.lit' to='francisco@denmark.lit/barracks' id='sub1'>

<pubsub xmlns='http://jabber.org/protocol/pubsub'>

<subscription node='princely_musings' jid='francisco@denmark.lit' subscription='unconfigured'>

<subscribe-options>

<required/>

</subscribe-options>

</subscription>

</pubsub>

</iq>

Subscription PacketExtensionProvider实现

public class SubscriptionProvider implements PacketExtensionProvider {

public PacketExtension parseExtension(XmlPullParser parser) throws Exception {

String jid = parser.getAttributeValue(null, "jid");

String nodeId = parser.getAttributeValue(null, "node");

String subId = parser.getAttributeValue(null, "subid");

String state = parser.getAttributeValue(null, "subscription");

boolean isRequired = false;

int tag = parser.next();

if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("subscribe-options")) {

tag = parser.next();

if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("required"))

isRequired = true;

while (parser.next() != XmlPullParser.END_TAG && parser.getName() != "subscribe-options");

}

while (parser.getEventType() != XmlPullParser.END_TAG) parser.next();

return new Subscription(jid, nodeId, subId, (state == null ? null : Subscription.State.valueOf(state)), isRequired);

}

}

Provider文件格式

这是可由 ProviderFileLoader 解析的提供者文件的格式。

<?xml version="1.0"?>

<smackProviders>

<iqProvider>

<elementName>query</elementName>

<namespace>jabber:iq:time</namespace>

<className>org.jivesoftware.smack.packet.Time</className>

</iqProvider>

<iqProvider>

<elementName>query</elementName>

<namespace>http://jabber.org/protocol/disco#items</namespace>

<className>org.jivesoftware.smackx.provider.DiscoverItemsProvider</className>

</iqProvider>

<extensionProvider>

<elementName>subscription</elementName>

<namespace>http://jabber.org/protocol/pubsub</namespace>

<className>org.jivesoftware.smackx.pubsub.provider.SubscriptionProvider</className>

</extensionProvider>

</smackProviders>

每个提供者都与一个元素名和一个命名空间关联。如果多个提供者条目都尝试着注册为处理同一个命名空间中的内容的话,则,最后添加到 ProviderManager 的那个条目会覆盖掉之前载入的任何提供者。

石咏莉

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands