/**
   * Constrain for AO version - current AO version must be less than provided version.
   *
   * @param version expected version constrain
   * @return true if current version is less than provided
   */
  private boolean isBeforeAOVersion(String version) {
    String aoVersion =
        pluginAccessor
            .getPlugin("com.atlassian.activeobjects.activeobjects-plugin")
            .getPluginInformation()
            .getVersion();

    String[] aoVersionComponents = aoVersion.split("\\.");
    String[] versionCompoennts = version.split("\\.");

    for (int i = 0; i < versionCompoennts.length; i++) {
      if (aoVersionComponents.length < i) {
        break;
      }

      try {
        boolean isLast = versionCompoennts.length == i;
        int aoVersionComponent = Integer.parseInt(aoVersionComponents[i]);
        int versionComponent = Integer.parseInt(versionCompoennts[i]);

        if (aoVersionComponent > versionComponent
            || (isLast && aoVersionComponent == versionComponent)) {
          return false;
        }
      } catch (NumberFormatException e) {
        return false;
      }
    }

    return true;
  }
 void validateCustomFieldPluginVersions(
     final BackupProject backupProject,
     final Collection backupPluginVersions,
     final MessageSet messageSet,
     final I18nHelper i18n) {
   for (final Iterator iterator = backupProject.getCustomFields().iterator();
       iterator.hasNext(); ) {
     final ExternalCustomFieldConfiguration customFieldConfiguration =
         (ExternalCustomFieldConfiguration) iterator.next();
     String key = customFieldConfiguration.getCustomField().getTypeKey();
     // The key is the plugin container key, a colon, then the module key (e.g.
     // com.atlassian.jira.plugin.system.customfieldtypes:textarea)
     // We just get the plugin container key, as this is where the version exists.
     final int index = key.indexOf(":");
     // This should never happen unless there was a bad plugin module installed in the backup data,
     // if this is
     // the case then we just want to use the key as specified and let the error propagate to the
     // user screen
     if (index != -1) {
       key = key.substring(0, index);
     }
     // Does this plugin exist in the current JIRA instance
     final Plugin plugin = pluginAccessor.getPlugin(key);
     if (plugin != null) {
       final String currentPluginVersion = plugin.getPluginInformation().getVersion();
       String backupVersion = null;
       for (final Iterator iterator1 = backupPluginVersions.iterator(); iterator1.hasNext(); ) {
         final PluginVersion pluginVersion = (PluginVersion) iterator1.next();
         if (pluginVersion.getKey().equals(key)) {
           backupVersion = pluginVersion.getVersion();
           break;
         }
       }
       if (!currentPluginVersion.equals(backupVersion)) {
         final String customFieldName = customFieldConfiguration.getCustomField().getName();
         if (backupVersion == null) {
           messageSet.addErrorMessage(
               i18n.getText(
                   "admin.error.project.import.plugin.wrong.version.null.backup",
                   backupProject.getProject().getName(),
                   customFieldName,
                   customFieldConfiguration.getCustomField().getTypeKey(),
                   currentPluginVersion));
         } else {
           messageSet.addErrorMessage(
               i18n.getText(
                   "admin.error.project.import.plugin.wrong.version",
                   backupProject.getProject().getName(),
                   customFieldName,
                   customFieldConfiguration.getCustomField().getTypeKey(),
                   currentPluginVersion,
                   backupVersion));
         }
       }
     }
   }
 }
  protected AbstractWorkflowModuleDescriptor getWorkflowModuleDescriptor(
      String className, final String pluginType) throws PluginParseException {
    final Collection moduleDescriptors =
        pluginAccessor.getEnabledModuleDescriptorsByType(pluginType);

    for (Iterator iterator = moduleDescriptors.iterator(); iterator.hasNext(); ) {
      AbstractWorkflowModuleDescriptor abstractWorkflowModuleDescriptor =
          (AbstractWorkflowModuleDescriptor) iterator.next();
      if (abstractWorkflowModuleDescriptor.getImplementationClass().getName().equals(className)) {
        return abstractWorkflowModuleDescriptor;
      }
    }

    return null;
  }
 @Override
 protected List<ContentLinkResolver> create() throws Exception {
   final List<ContentLinkResolverDescriptor> descriptors =
       Lists.newArrayList(
           accessor.getEnabledModuleDescriptorsByClass(
               ContentLinkResolverDescriptor.class));
   Collections.sort(descriptors, ModuleDescriptorComparator.COMPARATOR);
   return ImmutableList.copyOf(
       Collections2.transform(
           descriptors,
           new Function<ContentLinkResolverDescriptor, ContentLinkResolver>() {
             @Override
             public ContentLinkResolver apply(
                 @Nullable ContentLinkResolverDescriptor from) {
               return from.getModule();
             }
           }));
 }
  @Before
  public void setUp() throws Exception {
    Mockito.when(defaultRenderer.isDefaultHandler()).thenReturn(true);
    Mockito.when(badDescriptorRenderer.isDefaultHandler())
        .thenThrow(new RuntimeException("Misbehaving plugin exception"));

    Mockito.when(goodDescriptorRenderer.handlesApplicationType("application")).thenReturn(true);
    Mockito.when(badDescriptorRenderer.handlesApplicationType(Mockito.anyString()))
        .thenThrow(new RuntimeException("Misbehaving plugin exception"));

    Mockito.when(
            pluginAccessor.getEnabledModuleDescriptorsByClass(
                IssueLinkRendererModuleDescriptor.class))
        .thenReturn(
            ImmutableList.of(badDescriptorRenderer, goodDescriptorRenderer, defaultRenderer));

    Mockito.when(goodDescriptorRenderer.getModule()).thenReturn(renderer);
  }