Provider Architecture: Stanza Extensions and Custom IQ's ======================================================== [Back](index.md) Introduction ------------ The Smack provider architecture is a system for plugging in custom XML parsing of packet extensions and IQ packets. The standard [Smack Extensions](extensions/index.md) are built using the provider architecture. There are two types of providers: * `IQProvider` -- parses IQ requests into Java objects. * `Extension Provider` -- parses XML sub-documents attached to packets into ExtensionElement instances. By default, Smack only knows how to process a few standard packets and sub-packets that are in a few namespaces such as: * jabber:iq:auth * jabber:iq:roster * jabber:iq:register There are many more IQ types and extensions that are part of XMPP standards, and of course an endless number that can be added as custom extensions. To support this, an extensible parsing mechanism is provided via Smack and user build providers. Whenever a packet extension is found in a packet, parsing will be passed to the correct provider. Each provider must extend the ExtensionElementProvider abstract class. Each extension provider is responsible for parsing the raw XML stream, via the Smack's `XmlPullParser` interface, to construct an object. You can also create an introspection provider (`provider.IntrospectionProvider.PacketExtensionIntrospectionProvider`). Here, bean introspection is used to try to automatically set the properties of the class using the values in the packet extension sub-element. When no extension provider is registered for an element name and namespace combination, Smack will store all top-level elements of the sub-packet in the StandardExtensionElement object and then attach it to the packet. Management of these providers is accomplished via the [ProviderManager]() class. There are multiple ways to add providers to the manager. * Call addXXProvider methods - You can call the appropriate add methods directly. ``` ProviderManager.addIQProvider("element", "namespace", new MyIQProvider()); ProviderManager.addExtensionProvider("element", "namespace", new MyExtProvider()); ``` * Add a loader - You can add a ProviderLoader which will inject a means of loading multiple providers (both types) into the manager. This is the mechanism used by Smack to load from the Smack specific file format (via ProviderFileLoader). Implementers can provide the means to load providers from any source they wish, or simply reuse the ProviderFileLoader to load from their own provider files. ``` ProviderManager.addLoader(new ProviderFileLoader(FileUtils.getStreamForUrl("classpath:com/myco/provider/myco_custom.providers", null))); ``` * VM Argument - You can add a provider file via the VM argument _smack.provider.file_. This will load the file at the specified URL during startup when Smack initializes. This also assumes the default configuration, since it requires that the **VmArgInitializer** was part of the startup configuration. `-Dsmack.provider.file=classpath:com/myco/provider/myco_custom.providers` or `-Dsmack.provider.file=file:///c:/myco/provider/myco_custom.providers` IQ Providers ------------ The IQ provider class must extend the IQProvider abstract class. Each IQProvider is responsible for parsing the raw XML stream to create an IQ instance. You can also create an introspection provider (`provider.IntrospectionProvider.IQIntrospectionProvider`). Which uses bean introspection to try to automatically set properties of the IQ instance using the values found in the IQ packet XML. For example, an XMPP time packet resembles the following: ### Introspection _Time Stanza_ 20020910T17:58:35 MDT Tue Sep 10 12:58:35 2002 _Time IQ Class_ 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; } } _Time Provider_ ```java public class TimeProvider extends IQIntrospectionProvider