Esempio n. 1
0
  @Test
  public void hiddenTargetHandlingAtRoot() throws Exception {
    // test subject
    final DefaultFSPeer subject = new DefaultFSPeer();

    // repo base
    File repoBase = new File("target/repoId");

    // the file we want to store
    File target = new File(repoBase, "archetype-catalog.xml");
    target.getParentFile().mkdirs();

    final StorageFileItem file = Mockito.mock(StorageFileItem.class);
    Mockito.when(file.getPath()).thenReturn("/archetype-catalog.xml");
    Mockito.when(file.getParentPath()).thenReturn("/");

    // getting hidden target for target
    File hiddenTarget = subject.getHiddenTarget(null, repoBase, target, file);
    assertThat(hiddenTarget, notNullValue());
    assertThat(hiddenTarget, isFile());
    // startsWith, as garbage is appended to it's end
    assertThat(hiddenTarget.getName(), startsWith("archetype-catalog.xml"));
    // contains, as OS path from root is prefixing this, and garbage at the end suffixing it
    assertThat(
        hiddenTarget.getPath(),
        containsString(
            "target/repoId/.nexus/tmp/archetype-catalog.xml".replace("/", File.separator)));

    // writing to hidden target is handled elsewhere, so we simulate content being written out
    final String PAYLOAD = "dummy payload";
    FileUtils.write(hiddenTarget, PAYLOAD);

    // handle the rename
    subject.handleRenameOperation(hiddenTarget, target);

    // hidden should cease to exist
    assertThat(hiddenTarget, not(exists()));
    // target should exists
    assertThat(target, exists());
    // name should be not garbaged anymore
    assertThat(target.getName(), equalTo("archetype-catalog.xml"));
    // path prefixed by OS from root, no garbage at tail
    assertThat(
        target.getPath(),
        endsWith("target/repoId/archetype-catalog.xml".replace("/", File.separator)));
    // content is fine too
    assertThat(FileUtils.readFileToString(target), equalTo(PAYLOAD));
  }
  @Override
  public void storeItem(
      final Repository repository,
      final File repositoryBaseDir,
      final StorageItem item,
      final File target,
      final ContentLocator cl)
      throws UnsupportedStorageOperationException, LocalStorageException {
    // create parents down to the file itself (this will make those if needed, otherwise return
    // silently)
    mkParentDirs(repository, target);

    if (cl != null) {
      // we have _content_ (content or link), hence we store a file
      final File hiddenTarget = getHiddenTarget(repository, repositoryBaseDir, target, item);

      // NEXUS-4550: Part One, saving to "hidden" (temp) file
      // In case of error cleaning up only what needed
      // No locking needed, AbstractRepository took care of that
      FileOutputStream os = null;
      InputStream is = null;

      try {
        os = new FileOutputStream(hiddenTarget);

        is = cl.getContent();

        IOUtil.copy(is, os, getCopyStreamBufferSize());

        os.flush();
      } catch (EOFException e) {
        if (hiddenTarget != null) {
          hiddenTarget.delete();
        }

        throw new LocalStorageEofException(
            String.format(
                "EOF during storing on path \"%s\" (while writing to hiddenTarget: \"%s\")",
                item.getRepositoryItemUid().toString(), hiddenTarget.getAbsolutePath()),
            e);
      } catch (IOException e) {
        if (hiddenTarget != null) {
          hiddenTarget.delete();
        }

        throw new LocalStorageException(
            String.format(
                "Got exception during storing on path \"%s\" (while writing to hiddenTarget: \"%s\")",
                item.getRepositoryItemUid().toString(), hiddenTarget.getAbsolutePath()),
            e);
      } finally {
        IOUtil.close(is);

        IOUtil.close(os);
      }

      // NEXUS-4550: Part Two, moving the "hidden" (temp) file to final location
      // In case of error cleaning up both files
      // Locking is needed, AbstractRepository got shared lock only for destination

      // NEXUS-4550: FSPeer is the one that handles the rename in case of FS LS,
      // so we need here to claim exclusive lock on actual UID to perform the rename
      final RepositoryItemUidLock uidLock = item.getRepositoryItemUid().getLock();
      uidLock.lock(Action.create);

      try {
        handleRenameOperation(hiddenTarget, target);

        target.setLastModified(item.getModified());
      } catch (IOException e) {
        // if we ARE NOT handling attributes, do proper cleanup in case of IOEx
        // if we ARE handling attributes, leave backups in case of IOEx
        final boolean isCleanupNeeded =
            !item.getRepositoryItemUid()
                .getBooleanAttributeValue(IsItemAttributeMetacontentAttribute.class);

        if (target != null
            && (isCleanupNeeded
                ||
                // NEXUS-4871 prevent zero length/corrupt files
                target.length() == 0)) {
          target.delete();
        }

        if (hiddenTarget != null
            && (isCleanupNeeded
                ||
                // NEXUS-4871 prevent zero length/corrupt files
                hiddenTarget.length() == 0)) {
          hiddenTarget.delete();
        }

        if (!isCleanupNeeded) {
          getLogger()
              .warn(
                  "No cleanup done for error that happened while trying to save attibutes of item {}, the backup is left as {}!",
                  item.getRepositoryItemUid().toString(),
                  hiddenTarget.getAbsolutePath());
        }

        throw new LocalStorageException(
            String.format(
                "Got exception during storing on path \"%s\" (while moving to final destination)",
                item.getRepositoryItemUid().toString()),
            e);
      } finally {
        uidLock.unlock();
      }
    } else {
      // we have no content, we talk about directory
      target.mkdir();

      target.setLastModified(item.getModified());
    }
  }