Uploaded image for project: 'XWiki Platform'
  1. XWiki Platform
  2. XWIKI-25046

Importing an extension fails when the extension page holds a legacy version object with a blank version

    XMLWordPrintable

Details

    • Unknown

    Description

      Importing an extension onto an existing extension page aborts with an 

      {{IllegalArgumentException}}

      when that page carries a legacy

       {ExtensionCode.ExtensionVersionClass}} 

      object whose

      {{version}} 

      property is empty. Nothing is imported: the page keeps its old metadata and the extension stays unusable by the Extension Manager.

       This affects old, hand-made extension pages created before the Repository Application managed them. They are precisely the pages that most need importing.

      Steps to reproduce

      1. Take an extension page whose ExtensionCode.ExtensionClass.id is set, and which has an ExtensionCode.ExtensionVersionClass object with an empty version property.
      2. Go to ExtensionCode.ImportExtension and import that extension id from a Maven repository.

      Reproduced on extensions.xwiki.org (XWiki 18.4.3) with Extension.Skin Extension Plugin, whose legacy version object had every property empty but download.

      Actual result

        Failed to import extension: java.lang.IllegalArgumentException: An Entity Reference name cannot be null or empty
          at org.xwiki.model.reference.EntityReference.setName(EntityReference.java:222)
          at org.xwiki.model.reference.EntityReference.<init>(EntityReference.java:164)
          at org.xwiki.model.reference.AbstractLocalizedEntityReference.<init>(AbstractLocalizedEntityReference.java:76)
          at org.xwiki.model.reference.PageReference.<init>(PageReference.java:113)
          at org.xwiki.model.reference.PageReference.<init>(PageReference.java:101)
          at org.xwiki.repository.internal.ExtensionStore.getVersionDocument(ExtensionStore.java:503)
          at org.xwiki.repository.internal.ExtensionStore.getExtensionVersionDocument(ExtensionStore.java:458)
          at org.xwiki.repository.internal.ExtensionStore.getExtensionVersionDocument(ExtensionStore.java:441)
          at org.xwiki.repository.internal.RepositoryManager.moveLegacyVersion(RepositoryManager.java:1925)
          at org.xwiki.repository.internal.RepositoryManager.updateExtensionVersions(RepositoryManager.java:1024)
      

      Expected result

       The import succeeds. A version object with a blank version carries no information and should simply be dropped, which is what the code already says it wants to do.

      Cause

      RepositoryManager.updateExtensionVersions (master, lines 859-872) decides to remove the object
      for any of three reasons, one of them being a blank version, and then migrates it to a dedicated
      version page whenever version-page mode is on – without re-checking that the version is non-blank:

        // Remove the object if:
        // * versions should be stored in dedicated pages
        // * the version is blank
        // * versions should be proxied
        if (versionPageEnabled || StringUtils.isBlank(version) || (versionProxyEnabled
            && !new DefaultVersion(version).equals(extension.getId().getVersion()))) {
            extensionDocument.removeXObject(versionObject);
            needSave = true;
      
            // When moving from legacy storage to dedicated version page storage, we need to migrate the
            // object and not just deleted it
            if (versionPageEnabled) {
                moveLegacyVersion(extensionDocument, versionObject);
            }
        

      moveLegacyVersion passes that blank version to
      ExtensionStore.getVersionDocument, which builds new PageReference(version, ...) and throws.

      The two conditions are always both true on a legacy page, because updateExtension calls
      extensionStore.setVersionPageEnabled(extensionObject) earlier in the same import – so
      versionPageEnabled is on by the time this loop runs, and every blank-version legacy object
      hits the failing branch.

      Suggested fix

        Only migrate an object that has a version to migrate:

       

        if (versionPageEnabled && StringUtils.isNotBlank(version)) {
            moveLegacyVersion(extensionDocument, versionObject);
        }
        

        A unit test in RepositoryManagerTest covering an extension document that carries a
        blank-version legacy version object would lock this in.

      Attachments

        Activity

          People

            tmortagne Thomas Mortagne
            ecojocariu Eleni
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated: