ProviderFileLoader.java

  1. /**
  2.  *
  3.  * Copyright the original author or authors
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smack.provider;

  18. import java.io.InputStream;
  19. import java.util.Collection;
  20. import java.util.Collections;
  21. import java.util.LinkedList;
  22. import java.util.List;
  23. import java.util.logging.Level;
  24. import java.util.logging.Logger;

  25. import org.jivesoftware.smack.packet.ExtensionElement;
  26. import org.jivesoftware.smack.packet.IQ;

  27. import org.xmlpull.v1.XmlPullParser;
  28. import org.xmlpull.v1.XmlPullParserFactory;

  29. /**
  30.  * Loads the {@link IQProvider} and {@link ExtensionElementProvider} information from a standard provider file in preparation
  31.  * for loading into the {@link ProviderManager}.
  32.  *
  33.  * @author Robin Collier
  34.  *
  35.  */
  36. public class ProviderFileLoader implements ProviderLoader {
  37.     private static final Logger LOGGER = Logger.getLogger(ProviderFileLoader.class.getName());

  38.     private final Collection<IQProviderInfo> iqProviders = new LinkedList<IQProviderInfo>();
  39.     private final Collection<ExtensionProviderInfo> extProviders  = new LinkedList<ExtensionProviderInfo>();
  40.     private final Collection<StreamFeatureProviderInfo> sfProviders = new LinkedList<StreamFeatureProviderInfo>();

  41.     private List<Exception> exceptions = new LinkedList<Exception>();

  42.     public ProviderFileLoader(InputStream providerStream) {
  43.         this(providerStream, ProviderFileLoader.class.getClassLoader());
  44.     }

  45.     @SuppressWarnings("unchecked")
  46.     public ProviderFileLoader(InputStream providerStream, ClassLoader classLoader) {
  47.         // Load processing providers.
  48.         try {
  49.             XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
  50.             parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
  51.             parser.setInput(providerStream, "UTF-8");
  52.             int eventType = parser.getEventType();
  53.             do {
  54.                 if (eventType == XmlPullParser.START_TAG) {
  55.                     final String typeName = parser.getName();

  56.                     try {
  57.                         if (!"smackProviders".equals(typeName)) {
  58.                             parser.next();
  59.                             parser.next();
  60.                             String elementName = parser.nextText();
  61.                             parser.next();
  62.                             parser.next();
  63.                             String namespace = parser.nextText();
  64.                             parser.next();
  65.                             parser.next();
  66.                             String className = parser.nextText();

  67.                             try {
  68.                                 final Class<?> provider = classLoader.loadClass(className);
  69.                                 switch (typeName) {
  70.                                 case "iqProvider":
  71.                                     // Attempt to load the provider class and then create
  72.                                     // a new instance if it's an IQProvider. Otherwise, if it's
  73.                                     // an IQ class, add the class object itself, then we'll use
  74.                                     // reflection later to create instances of the class.
  75.                                     // Add the provider to the map.
  76.                                     if (IQProvider.class.isAssignableFrom(provider)) {
  77.                                         IQProvider<IQ> iqProvider = (IQProvider<IQ>) provider.getConstructor().newInstance();
  78.                                         iqProviders.add(new IQProviderInfo(elementName, namespace, iqProvider));
  79.                                     }
  80.                                     else {
  81.                                         exceptions.add(new IllegalArgumentException(className + " is not a IQProvider"));
  82.                                     }
  83.                                     break;
  84.                                 case "extensionProvider":
  85.                                     // Attempt to load the provider class and then create
  86.                                     // a new instance if it's an ExtensionProvider. Otherwise, if it's
  87.                                     // a PacketExtension, add the class object itself and
  88.                                     // then we'll use reflection later to create instances
  89.                                     // of the class.
  90.                                     if (ExtensionElementProvider.class.isAssignableFrom(provider)) {
  91.                                         ExtensionElementProvider<ExtensionElement> extensionElementProvider = (ExtensionElementProvider<ExtensionElement>) provider.getConstructor().newInstance();
  92.                                         extProviders.add(new ExtensionProviderInfo(elementName, namespace,
  93.                                                         extensionElementProvider));
  94.                                     }
  95.                                     else {
  96.                                         exceptions.add(new IllegalArgumentException(className
  97.                                                         + " is not a PacketExtensionProvider"));
  98.                                     }
  99.                                     break;
  100.                                 case "streamFeatureProvider":
  101.                                     ExtensionElementProvider<ExtensionElement> streamFeatureProvider = (ExtensionElementProvider<ExtensionElement>) provider.getConstructor().newInstance();
  102.                                     sfProviders.add(new StreamFeatureProviderInfo(elementName,
  103.                                                     namespace,
  104.                                                     streamFeatureProvider));
  105.                                     break;
  106.                                 default:
  107.                                     LOGGER.warning("Unknown provider type: " + typeName);
  108.                                 }
  109.                             }
  110.                             catch (ClassNotFoundException cnfe) {
  111.                                 LOGGER.log(Level.SEVERE, "Could not find provider class", cnfe);
  112.                                 exceptions.add(cnfe);
  113.                             }
  114.                             catch (InstantiationException ie) {
  115.                                 LOGGER.log(Level.SEVERE, "Could not instanciate " + className, ie);
  116.                                 exceptions.add(ie);
  117.                             }
  118.                         }
  119.                     }
  120.                     catch (IllegalArgumentException illExc) {
  121.                         LOGGER.log(Level.SEVERE, "Invalid provider type found [" + typeName + "] when expecting iqProvider or extensionProvider", illExc);
  122.                         exceptions.add(illExc);
  123.                     }
  124.                 }
  125.                 eventType = parser.next();
  126.             }
  127.             while (eventType != XmlPullParser.END_DOCUMENT);
  128.         }
  129.         catch (Exception e) {
  130.             LOGGER.log(Level.SEVERE, "Unknown error occurred while parsing provider file", e);
  131.             exceptions.add(e);
  132.         }
  133.         finally {
  134.             try {
  135.                 providerStream.close();
  136.             }
  137.             catch (Exception e) {
  138.                 // Ignore.
  139.             }
  140.         }
  141.     }

  142.     @Override
  143.     public Collection<IQProviderInfo> getIQProviderInfo() {
  144.         return iqProviders;
  145.     }

  146.     @Override
  147.     public Collection<ExtensionProviderInfo> getExtensionProviderInfo() {
  148.         return extProviders;
  149.     }

  150.     @Override
  151.     public Collection<StreamFeatureProviderInfo> getStreamFeatureProviderInfo() {
  152.         return sfProviders;
  153.     }

  154.     public List<Exception> getLoadingExceptions() {
  155.         return Collections.unmodifiableList(exceptions);
  156.     }
  157. }