/** {@inheritDoc} */
  @Override
  public OperationResult execute(
      OperationContext context, ModelNode operation, ResultHandler resultHandler)
      throws OperationFailedException {

    validator.validate(operation);

    String name = operation.require(NAME).asString();
    String runtimeName =
        operation.hasDefined(RUNTIME_NAME) ? operation.get(RUNTIME_NAME).asString() : name;
    byte[] hash;
    if (operation.hasDefined(INPUT_STREAM_INDEX) && operation.hasDefined(HASH)) {
      throw new OperationFailedException(
          new ModelNode().set("Can't pass in both an input-stream-index and a hash"));
    } else if (operation.hasDefined(INPUT_STREAM_INDEX)) {
      InputStream in = getContents(context, operation);
      try {
        hash = deploymentRepository.addDeploymentContent(in);
      } catch (IOException e) {
        throw new OperationFailedException(new ModelNode().set(e.toString()));
      }
    } else if (operation.hasDefined(HASH)) {

      hash = operation.get(HASH).asBytes();
      if (!deploymentRepository.hasDeploymentContent(hash)) {
        throw new OperationFailedException(
            new ModelNode()
                .set(
                    String.format(
                        "No deployment content with hash %s is available in the deployment content repository.",
                        HashUtil.bytesToHexString(hash))));
      }
    } else {
      throw new OperationFailedException(
          new ModelNode().set("Neither an attachment or a hash were passed in"));
    }

    ModelNode rootModel = context.getSubModel();
    ModelNode deployments = rootModel.get(DEPLOYMENT);

    ModelNode replaceNode = deployments.hasDefined(name) ? deployments.get(name) : null;
    if (replaceNode == null) {
      throw new OperationFailedException(
          new ModelNode().set(String.format("No deployment with name %s found", name)));
    }

    boolean start = replaceNode.get(ENABLED).asBoolean();

    ModelNode deployNode = new ModelNode();
    deployNode.get(NAME).set(name);
    deployNode.get(RUNTIME_NAME).set(runtimeName);
    deployNode.get(HASH).set(hash);
    deployNode.get(ENABLED).set(start);

    deployments.get(name).set(deployNode);

    ModelNode compensatingOp = operation.clone();
    compensatingOp.get(RUNTIME_NAME).set(replaceNode.get(RUNTIME_NAME).asString());
    compensatingOp.get(HASH).set(replaceNode.get(HASH).asBytes());
    if (operation.hasDefined(INPUT_STREAM_INDEX)) {
      operation.remove(INPUT_STREAM_INDEX);
    }

    if (start) {
      DeploymentHandlerUtil.replace(deployNode, name, context, resultHandler);
    } else {
      resultHandler.handleResultComplete();
    }

    return new BasicOperationResult(compensatingOp);
  }