private CriteriaDefinitionContribution[] readCriteriaDefinitionContributions(String locale) {
    CriteriaDefinitionContribution[] cached;
    List<CriteriaDefinitionContribution> contributions = new ArrayList<>();
    AbstractCriteriaDefinitionProvider[] providers = getCriteriaDefinitionProviders();
    for (int i = 0; i < providers.length; ++i) {
      ICriteriaDefinitionContribution[] contrib;
      try {
        contrib = providers[i].getCriteriaDefinitionContributions(locale);
      } catch (Throwable t) {
        // log, and skip the offending provider
        String msg =
            "Error getting help criteria definition data from provider: "
                + providers[i].getClass().getName()
                + " (skipping provider)"; //$NON-NLS-1$ //$NON-NLS-2$
        HelpPlugin.logError(msg, t);
        continue;
      }

      // check for nulls and root element
      for (int j = 0; j < contrib.length; ++j) {
        if (contrib[j] == null) {
          String msg =
              "Help criteria definition provider \""
                  + providers[i].getClass().getName()
                  + "\" returned a null contribution (skipping)"; //$NON-NLS-1$ //$NON-NLS-2$
          HelpPlugin.logError(msg);
        } else if (contrib[j].getCriteriaDefinition() == null) {
          String msg =
              "Help criteria definition provider \""
                  + providers[i].getClass().getName()
                  + "\" returned a contribution with a null root element (expected a \""
                  + CriteriaDefinition.NAME
                  + "\" element; skipping)"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
          HelpPlugin.logError(msg);
        } else {
          CriteriaDefinitionContribution contribution = new CriteriaDefinitionContribution();
          contribution.setId(contrib[j].getId());
          contribution.setLocale(contrib[j].getLocale());
          ICriteriaDefinition criteria = contrib[j].getCriteriaDefinition();
          contribution.setCriteriaDefinition(
              criteria instanceof CriteriaDefinition
                  ? (CriteriaDefinition) criteria
                  : (CriteriaDefinition) UAElementFactory.newElement(criteria));
          contributions.add(contribution);
        }
      }
    }
    cached = contributions.toArray(new CriteriaDefinitionContribution[contributions.size()]);
    return cached;
  }
 /*
  * Internal hook for unit testing.
  */
 public AbstractCriteriaDefinitionProvider[] getCriteriaDefinitionProviders() {
   if (null == criteriaDefinitionProviders) {
     List<AbstractCriteriaDefinitionProvider> providers = new ArrayList<>();
     IExtensionRegistry registry = Platform.getExtensionRegistry();
     IConfigurationElement[] elements =
         registry.getConfigurationElementsFor(EXTENSION_POINT_ID_CRITERIA_DEFINITION);
     for (int i = 0; i < elements.length; ++i) {
       IConfigurationElement elem = elements[i];
       if (elem.getName().equals(ELEMENT_NAME_CRITERIA_DEFINITION_PROVIDER)) {
         try {
           AbstractCriteriaDefinitionProvider provider =
               (AbstractCriteriaDefinitionProvider)
                   elem.createExecutableExtension(ATTRIBUTE_NAME_CLASS);
           providers.add(provider);
         } catch (CoreException e) {
           // log and skip
           String msg =
               "Error instantiating help keyword index provider class \""
                   + elem.getAttribute(ATTRIBUTE_NAME_CLASS)
                   + '"'; //$NON-NLS-1$
           HelpPlugin.logError(msg, e);
         }
       }
     }
     criteriaDefinitionProviders =
         providers.toArray(new AbstractCriteriaDefinitionProvider[providers.size()]);
   }
   return criteriaDefinitionProviders;
 }