@Override
  public void setContentStream(
      CallContext callContext,
      String repositoryId,
      Holder<String> objectId,
      boolean overwriteFlag,
      ContentStream contentStream,
      Holder<String> changeToken) {

    exceptionService.invalidArgumentRequiredHolderString("objectId", objectId);

    Lock lock = threadLockService.getWriteLock(repositoryId, objectId.getValue());
    try {
      lock.lock();
      // //////////////////
      // General Exception
      // //////////////////

      exceptionService.invalidArgumentRequired("contentStream", contentStream);
      Document doc = (Document) contentService.getContent(repositoryId, objectId.getValue());
      exceptionService.objectNotFound(DomainType.OBJECT, doc, objectId.getValue());
      exceptionService.permissionDenied(
          callContext, repositoryId, PermissionMapping.CAN_SET_CONTENT_DOCUMENT, doc);
      DocumentTypeDefinition td =
          (DocumentTypeDefinition) typeManager.getTypeDefinition(repositoryId, doc.getObjectType());
      exceptionService.constraintImmutable(repositoryId, doc, td);

      // //////////////////
      // Specific Exception
      // //////////////////
      exceptionService.contentAlreadyExists(doc, overwriteFlag);
      exceptionService.streamNotSupported(td, contentStream);
      exceptionService.updateConflict(doc, changeToken);
      exceptionService.versioning(doc);
      Folder parent = contentService.getParent(repositoryId, objectId.getValue());
      exceptionService.objectNotFoundParentFolder(repositoryId, objectId.getValue(), parent);

      // //////////////////
      // Body of the method
      // //////////////////
      String oldId = objectId.getValue();

      // TODO Externalize versioningState
      if (doc.isPrivateWorkingCopy()) {
        Document result = contentService.replacePwc(callContext, repositoryId, doc, contentStream);
        objectId.setValue(result.getId());
      } else {
        Document result =
            contentService.createDocumentWithNewStream(
                callContext, repositoryId, doc, contentStream);
        objectId.setValue(result.getId());
      }

      nemakiCachePool.get(repositoryId).removeCmisCache(oldId);
    } finally {
      lock.unlock();
    }
  }