private UserIsDnResourceDefintion() {
   super(
       UserSearchType.USERNAME_IS_DN,
       ControllerResolver.getResolver(
           "core.management.security-realm.authorization.ldap.user-search.username-to-dn"),
       new LdapAuthorizationChildAddHandler(false, ATTRIBUTE_DEFINITIONS),
       LdapAuthorizationResourceDefinition.REMOVE_INSTANCE);
 }
 public PropertyResourceDefinition() {
   super(
       PathElement.pathElement(ModelDescriptionConstants.PROPERTY),
       ControllerResolver.getResolver("core.management.security-realm.property"),
       new SecurityRealmChildAddHandler(true, VALUE),
       new SecurityRealmChildRemoveHandler(true, false),
       OperationEntry.Flag.RESTART_RESOURCE_SERVICES,
       OperationEntry.Flag.RESTART_RESOURCE_SERVICES);
 }
 public InterfaceDefinition(
     InterfaceAddHandler addHandler, InterfaceRemoveHandler removeHandler, boolean updateRuntime) {
   super(
       PathElement.pathElement(INTERFACE),
       ControllerResolver.getResolver(INTERFACE),
       addHandler,
       removeHandler);
   this.updateRuntime = updateRuntime;
 }
 public LdapAuthenticationResourceDefinition() {
   super(
       PathElement.pathElement(
           ModelDescriptionConstants.AUTHENTICATION, ModelDescriptionConstants.LDAP),
       ControllerResolver.getResolver("core.management.security-realm.authentication.ldap"),
       new LdapAuthenticationAddHandler(),
       new SecurityRealmChildRemoveHandler(true),
       OperationEntry.Flag.RESTART_RESOURCE_SERVICES,
       OperationEntry.Flag.RESTART_RESOURCE_SERVICES);
 }
 public PlugInAuthenticationResourceDefinition() {
   super(
       PathElement.pathElement(
           ModelDescriptionConstants.AUTHENTICATION, ModelDescriptionConstants.PLUG_IN),
       ControllerResolver.getResolver("core.management.security-realm.authentication.plug-in"),
       new SecurityRealmChildAddHandler(true, ATTRIBUTE_DEFINITIONS),
       new SecurityRealmChildRemoveHandler(true),
       OperationEntry.Flag.RESTART_RESOURCE_SERVICES,
       OperationEntry.Flag.RESTART_RESOURCE_SERVICES);
 }
 public SecretServerIdentityResourceDefinition() {
   super(
       PathElement.pathElement(
           ModelDescriptionConstants.SERVER_IDENTITY, ModelDescriptionConstants.SECRET),
       ControllerResolver.getResolver(
           "core", "management", "security-realm", "server-identity", "secret"),
       new SecurityRealmChildAddHandler(false, VALUE),
       new SecurityRealmChildRemoveHandler(false),
       OperationEntry.Flag.RESTART_RESOURCE_SERVICES,
       OperationEntry.Flag.RESTART_RESOURCE_SERVICES);
 }
/**
 * An operation that lists the snapshots taken of the current configuration
 *
 * @author <a href="*****@*****.**">Kabir Khan</a>
 * @version $Revision: 1.1 $
 */
public class SnapshotListHandler implements OperationStepHandler {

  private static final String OPERATION_NAME = "list-snapshots";

  private static final SimpleAttributeDefinition DIRECTORY =
      new SimpleAttributeDefinitionBuilder(ModelDescriptionConstants.DIRECTORY, ModelType.STRING)
          .setAllowNull(false)
          .build();
  private static final AttributeDefinition NAMES =
      new StringListAttributeDefinition.Builder(ModelDescriptionConstants.NAMES).build();

  public static final OperationDefinition DEFINITION =
      new SimpleOperationDefinitionBuilder(
              OPERATION_NAME, ControllerResolver.getResolver("snapshot"))
          .setReplyParameters(DIRECTORY, NAMES)
          .setReadOnly()
          .setRuntimeOnly()
          .withFlag(OperationEntry.Flag.MASTER_HOST_CONTROLLER_ONLY)
          .addAccessConstraint(SensitiveTargetAccessConstraintDefinition.SNAPSHOTS)
          .build();

  private final ConfigurationPersister persister;

  public SnapshotListHandler(ConfigurationPersister persister) {
    this.persister = persister;
  }

  @Override
  public void execute(OperationContext context, ModelNode operation)
      throws OperationFailedException {
    AuthorizationResult authorizationResult = context.authorize(operation);
    if (authorizationResult.getDecision() == AuthorizationResult.Decision.DENY) {
      throw ControllerLogger.ROOT_LOGGER.unauthorized(
          operation.get(OP).asString(),
          context.getCurrentAddress(),
          authorizationResult.getExplanation());
    }

    try {
      SnapshotInfo info = persister.listSnapshots();
      ModelNode result = context.getResult();
      result.get(ModelDescriptionConstants.DIRECTORY).set(info.getSnapshotDirectory());
      result.get(ModelDescriptionConstants.NAMES).setEmptyList();
      for (String name : info.names()) {
        result.get(ModelDescriptionConstants.NAMES).add(name);
      }
    } catch (Exception e) {
      throw new OperationFailedException(e);
    }
    context.completeStep(OperationContext.RollbackHandler.NOOP_ROLLBACK_HANDLER);
  }
}
 public LdapAuthenticationResourceDefinition() {
   super(
       PathElement.pathElement(
           ModelDescriptionConstants.AUTHENTICATION, ModelDescriptionConstants.LDAP),
       ControllerResolver.getDeprecatedResolver(
           SecurityRealmResourceDefinition.DEPRECATED_PARENT_CATEGORY,
           "core.management.security-realm.authentication.ldap"),
       new LdapAuthenticationAddHandler(),
       new SecurityRealmChildRemoveHandler(true),
       OperationEntry.Flag.RESTART_RESOURCE_SERVICES,
       OperationEntry.Flag.RESTART_RESOURCE_SERVICES);
   setDeprecated(ModelVersion.create(1, 7));
 }
  public static void initOperations(
      final ManagementResourceRegistration root,
      final ContentRepository contentRepository,
      final ExtensibleConfigurationPersister extensibleConfigurationPersister,
      final ServerEnvironment serverEnvironment,
      final ControlledProcessState processState,
      final RunningModeControl runningModeControl,
      final AbstractVaultReader vaultReader,
      final ExtensionRegistry extensionRegistry,
      final boolean parallelBoot,
      final PathManagerService pathManager) {

    // System Properties
    root.registerSubModel(
        SystemPropertyResourceDefinition.createForStandaloneServer(serverEnvironment));

    // vault
    root.registerSubModel(new VaultResourceDefinition(vaultReader));

    // Central Management
    // Start with the base /core-service=management MNR. The Resource for this is added by
    // ServerService itself, so there is no add/remove op handlers
    ManagementResourceRegistration management =
        root.registerSubModel(CoreManagementDefinition.INSTANCE);

    management.registerSubModel(SecurityRealmResourceDefinition.INSTANCE);
    management.registerSubModel(LdapConnectionResourceDefinition.INSTANCE);
    management.registerSubModel(NativeManagementResourceDefinition.INSTANCE);
    management.registerSubModel(NativeRemotingManagementResourceDefinition.INSTANCE);
    management.registerSubModel(HttpManagementResourceDefinition.INSTANCE);

    // Other core services
    ManagementResourceRegistration serviceContainer =
        root.registerSubModel(
            new SimpleResourceDefinition(
                PathElement.pathElement(CORE_SERVICE, SERVICE_CONTAINER),
                ControllerResolver.getResolver("core", SERVICE_CONTAINER)));
    serviceContainer.registerOperationHandler(
        DumpServicesHandler.DEFINITION, DumpServicesHandler.INSTANCE);

    // Platform MBeans
    PlatformMBeanResourceRegistrar.registerPlatformMBeanResources(root);

    // Paths
    root.registerSubModel(PathResourceDefinition.createSpecified(pathManager));

    // Interfaces
    ManagementResourceRegistration interfaces =
        root.registerSubModel(
            new InterfaceDefinition(
                SpecifiedInterfaceAddHandler.INSTANCE,
                SpecifiedInterfaceRemoveHandler.INSTANCE,
                true));
    interfaces.registerReadOnlyAttribute(
        NetworkInterfaceRuntimeHandler.RESOLVED_ADDRESS, NetworkInterfaceRuntimeHandler.INSTANCE);
    interfaces.registerOperationHandler(
        SpecifiedInterfaceResolveHandler.DEFINITION, SpecifiedInterfaceResolveHandler.INSTANCE);

    // TODO socket-binding-group currently lives in controller and the child RDs live in server so
    // they currently need passing in from here
    root.registerSubModel(
        new SocketBindingGroupResourceDefinition(
            BindingGroupAddHandler.INSTANCE,
            SocketBindingGroupRemoveHandler.INSTANCE,
            false,
            SocketBindingResourceDefinition.INSTANCE,
            RemoteDestinationOutboundSocketBindingResourceDefinition.INSTANCE,
            LocalDestinationOutboundSocketBindingResourceDefinition.INSTANCE));

    // Deployments
    ManagementResourceRegistration deployments =
        root.registerSubModel(
            ServerDeploymentResourceDescription.create(contentRepository, vaultReader));

    // deployment overlays
    root.registerSubModel(
        new DeploymentOverlayDefinition(DeploymentOverlayPriority.SERVER, contentRepository, null));

    // The sub-deployments registry
    deployments.registerSubModel(
        new SimpleResourceDefinition(
            PathElement.pathElement(SUBDEPLOYMENT), DeploymentAttributes.DEPLOYMENT_RESOLVER));

    // Extensions
    root.registerSubModel(new ExtensionResourceDefinition(extensionRegistry, parallelBoot, false));
    if (extensionRegistry != null) {
      // extension registry may be null during testing
      extensionRegistry.setSubsystemParentResourceRegistrations(root, deployments);
      extensionRegistry.setPathManager(pathManager);
    }

    // Util
    root.registerOperationHandler(
        DeployerChainAddHandler.DEFINITION, DeployerChainAddHandler.INSTANCE, false);
  }
/**
 * {@link org.jboss.as.controller.OperationStepHandler} returning the type description of a single
 * operation description.
 *
 * @author <a href="*****@*****.**">Kabir Khan</a>
 * @author Brian Stansberry (c) 2012 Red Hat Inc.
 */
public class ReadOperationDescriptionHandler implements OperationStepHandler {

  static final SimpleAttributeDefinition ACCESS_CONTROL =
      new SimpleAttributeDefinitionBuilder(
              ModelDescriptionConstants.ACCESS_CONTROL, ModelType.BOOLEAN)
          .setAllowNull(true)
          .setDefaultValue(new ModelNode(false))
          .build();

  static final OperationDefinition DEFINITION =
      new SimpleOperationDefinitionBuilder(
              READ_OPERATION_DESCRIPTION_OPERATION, ControllerResolver.getResolver("global"))
          .setParameters(NAME, LOCALE, ACCESS_CONTROL)
          .setReplyType(ModelType.OBJECT)
          .setReadOnly()
          .setRuntimeOnly()
          .build();

  static final OperationStepHandler INSTANCE = new ReadOperationDescriptionHandler();

  @Override
  public void execute(OperationContext context, ModelNode operation)
      throws OperationFailedException {

    String operationName = NAME.resolveModelAttribute(context, operation).asString();
    boolean accessControl = ACCESS_CONTROL.resolveModelAttribute(context, operation).asBoolean();

    final DescribedOp describedOp =
        getDescribedOp(context, operationName, operation, !accessControl);
    if (describedOp == null
        || (context.getProcessType() == ProcessType.DOMAIN_SERVER
            && !describedOp.flags.contains(OperationEntry.Flag.RUNTIME_ONLY))) {
      throw new OperationFailedException(
          ControllerLogger.ROOT_LOGGER.operationNotRegistered(
              operationName, context.getCurrentAddress()));
    } else {
      ModelNode result = describedOp.getDescription();

      if (accessControl) {
        final PathAddress address = context.getCurrentAddress();
        ModelNode operationToCheck = Util.createOperation(operationName, address);
        operationToCheck.get(OPERATION_HEADERS).set(operation.get(OPERATION_HEADERS));
        AuthorizationResult authorizationResult = context.authorizeOperation(operationToCheck);
        result
            .get(ACCESS_CONTROL.getName(), EXECUTE)
            .set(authorizationResult.getDecision() == Decision.PERMIT);
      }

      context.getResult().set(result);
    }
  }

  private static DescribedOp getDescribedOp(
      OperationContext context, String operationName, ModelNode operation, boolean lenient)
      throws OperationFailedException {
    DescribedOp result = null;
    OperationEntry operationEntry;
    // First try to get the current resource registration to give authz a chance to reject this
    // request
    ImmutableManagementResourceRegistration registry = context.getResourceRegistration();
    if (registry != null) {
      operationEntry = registry.getOperationEntry(PathAddress.EMPTY_ADDRESS, operationName);
    } else {
      // We know the user is authorized to read this address.
      // There's no MRR at that address, but see if the MRR tree can resolve an operation entry
      // (e.g. an inherited one)
      operationEntry =
          context
              .getRootResourceRegistration()
              .getOperationEntry(context.getCurrentAddress(), operationName);
    }

    if (operationEntry != null) {
      Locale locale = GlobalOperationHandlers.getLocale(context, operation);
      result = new DescribedOp(operationEntry, locale);
    } else if (lenient) {
      // For wildcard elements, check specific registrations where the same OSH is used
      // for all such registrations
      PathAddress address = context.getCurrentAddress();
      if (address.size() > 0) {
        PathElement pe = address.getLastElement();
        if (pe.isWildcard()) {
          ImmutableManagementResourceRegistration rootRegistration =
              context.getRootResourceRegistration();
          String type = pe.getKey();
          PathAddress parent = address.subAddress(0, address.size() - 1);
          Set<PathElement> children = rootRegistration.getChildAddresses(parent);
          if (children != null) {
            Locale locale = GlobalOperationHandlers.getLocale(context, operation);
            DescribedOp found = null;
            for (PathElement child : children) {
              if (type.equals(child.getKey())) {
                OperationEntry oe =
                    rootRegistration.getOperationEntry(parent.append(child), operationName);
                DescribedOp describedOp = oe == null ? null : new DescribedOp(oe, locale);
                if (describedOp == null || (found != null && !found.equals(describedOp))) {
                  // Not all children have the same handler; give up
                  found = null;
                  break;
                }
                // We have a candidate OSH
                found = describedOp;
              }
            }
            result = found;
          }
        }
      }
    }
    return result;
  }

  static class DescribedOp {
    private final ModelNode description;
    private final Set<OperationEntry.Flag> flags;

    DescribedOp(OperationEntry operationEntry, Locale locale) {
      this.description = operationEntry.getDescriptionProvider().getModelDescription(locale);
      this.flags = operationEntry.getFlags();
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      DescribedOp that = (DescribedOp) o;

      return description.equals(that.description) && flags.equals(that.flags);
    }

    @Override
    public int hashCode() {
      int result = description.hashCode();
      result = 31 * result + flags.hashCode();
      return result;
    }

    /** @return the description of the operation augmented of the operation's entry flags. */
    ModelNode getDescription() {
      final ModelNode result = description.clone();
      boolean readOnly = flags.contains(OperationEntry.Flag.READ_ONLY);
      result.get(READ_ONLY).set(readOnly);
      if (!readOnly) {
        if (flags.contains(OperationEntry.Flag.RESTART_ALL_SERVICES)) {
          result.get(RESTART_REQUIRED).set(ALL_SERVICES);
        } else if (flags.contains(OperationEntry.Flag.RESTART_RESOURCE_SERVICES)) {
          result.get(RESTART_REQUIRED).set(RESOURCE_SERVICES);
        } else if (flags.contains(OperationEntry.Flag.RESTART_JVM)) {
          result.get(RESTART_REQUIRED).set(JVM);
        }
      }

      boolean runtimeOnly = flags.contains(OperationEntry.Flag.RUNTIME_ONLY);
      result.get(RUNTIME_ONLY).set(runtimeOnly);
      return result;
    }
  }
}
Example #11
0
/**
 * {@link org.jboss.as.controller.OperationStepHandler} querying the children resources of a given
 * "child-type".
 *
 * @author <a href="*****@*****.**">Kabir Khan</a>
 */
public class ReadChildrenResourcesHandler implements OperationStepHandler {

  static final OperationDefinition DEFINITION =
      new SimpleOperationDefinitionBuilder(
              READ_CHILDREN_RESOURCES_OPERATION, ControllerResolver.getResolver("global"))
          .setParameters(
              CHILD_TYPE, RECURSIVE, RECURSIVE_DEPTH, PROXIES, INCLUDE_RUNTIME, INCLUDE_DEFAULTS)
          .setReadOnly()
          .setRuntimeOnly()
          .setReplyType(ModelType.LIST)
          .setReplyValueType(ModelType.OBJECT)
          .build();

  static final OperationStepHandler INSTANCE = new ReadChildrenResourcesHandler();

  @Override
  public void execute(OperationContext context, ModelNode operation)
      throws OperationFailedException {

    final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR));
    final String childType = CHILD_TYPE.resolveModelAttribute(context, operation).asString();

    // Build up the op we're going to repeatedly execute
    final ModelNode readOp = new ModelNode();
    readOp.get(OP).set(READ_RESOURCE_OPERATION);
    INCLUDE_RUNTIME.validateAndSet(operation, readOp);
    RECURSIVE.validateAndSet(operation, readOp);
    RECURSIVE_DEPTH.validateAndSet(operation, readOp);
    PROXIES.validateAndSet(operation, readOp);
    INCLUDE_DEFAULTS.validateAndSet(operation, readOp);

    final Map<PathElement, ModelNode> resources = new HashMap<PathElement, ModelNode>();

    final Resource resource = context.readResource(PathAddress.EMPTY_ADDRESS, false);
    final ImmutableManagementResourceRegistration registry = context.getResourceRegistration();
    Map<String, Set<String>> childAddresses =
        GlobalOperationHandlers.getChildAddresses(context, address, registry, resource, childType);
    Set<String> childNames = childAddresses.get(childType);
    if (childNames == null) {
      throw new OperationFailedException(
          new ModelNode().set(ControllerLogger.ROOT_LOGGER.unknownChildType(childType)));
    }

    // Track any excluded items
    FilteredData filteredData = new FilteredData(address);

    // We're going to add a bunch of steps that should immediately follow this one. We are going to
    // add them
    // in reverse order of how they should execute, building up a stack.

    // Last to execute is the handler that assembles the overall response from the pieces created by
    // all the other steps
    final ReadChildrenResourcesAssemblyHandler assemblyHandler =
        new ReadChildrenResourcesAssemblyHandler(resources, filteredData, address, childType);
    context.addStep(assemblyHandler, OperationContext.Stage.MODEL, true);

    for (final String key : childNames) {
      final PathElement childPath = PathElement.pathElement(childType, key);
      final PathAddress childAddress =
          PathAddress.EMPTY_ADDRESS.append(PathElement.pathElement(childType, key));

      final ModelNode readResOp = readOp.clone();
      readResOp.get(OP_ADDR).set(PathAddress.pathAddress(address, childPath).toModelNode());

      // See if there was an override registered for the standard :read-resource handling
      // (unlikely!!!)
      OperationStepHandler overrideHandler =
          context
              .getResourceRegistration()
              .getOperationHandler(childAddress, READ_RESOURCE_OPERATION);
      if (overrideHandler == null) {
        throw new OperationFailedException(
            new ModelNode().set(ControllerLogger.ROOT_LOGGER.noOperationHandler()));
      } else if (overrideHandler.getClass() == ReadResourceHandler.class) {
        // not an override
        overrideHandler = null;
      }
      OperationStepHandler rrHandler =
          new ReadResourceHandler(filteredData, overrideHandler, false);
      final ModelNode rrRsp = new ModelNode();
      resources.put(childPath, rrRsp);
      context.addStep(rrRsp, readResOp, rrHandler, OperationContext.Stage.MODEL, true);
    }

    context.stepCompleted();
  }

  /**
   * Assembles the response to a read-resource request from the components gathered by earlier
   * steps.
   */
  private static class ReadChildrenResourcesAssemblyHandler implements OperationStepHandler {

    private final Map<PathElement, ModelNode> resources;
    private final FilteredData filteredData;
    private final PathAddress address;
    private final String childType;

    /**
     * Creates a ReadResourceAssemblyHandler that will assemble the response using the contents of
     * the given maps.
     *
     * @param resources read-resource response from child resources, where the key is the path of
     *     the resource relative to the address of the operation this handler is handling and the
     *     value is the full read-resource response. Will not be {@code null}
     * @param filteredData record of any excluded data
     * @param address the address of the targeted resource
     * @param childType the type of child being read
     */
    private ReadChildrenResourcesAssemblyHandler(
        final Map<PathElement, ModelNode> resources,
        FilteredData filteredData,
        PathAddress address,
        String childType) {
      this.resources = resources;
      this.filteredData = filteredData;
      this.address = address;
      this.childType = childType;
    }

    @Override
    public void execute(OperationContext context, ModelNode operation)
        throws OperationFailedException {

      context.addStep(
          new OperationStepHandler() {
            @Override
            public void execute(OperationContext context, ModelNode operation)
                throws OperationFailedException {
              Map<String, ModelNode> sortedChildren = new TreeMap<String, ModelNode>();
              boolean failed = false;
              for (Map.Entry<PathElement, ModelNode> entry : resources.entrySet()) {
                PathElement path = entry.getKey();
                ModelNode value = entry.getValue();
                if (!value.has(FAILURE_DESCRIPTION)) {
                  sortedChildren.put(path.getValue(), value.get(RESULT));
                } else if (!failed && value.hasDefined(FAILURE_DESCRIPTION)) {
                  context.getFailureDescription().set(value.get(FAILURE_DESCRIPTION));
                  failed = true;
                }
              }

              if (!failed) {
                boolean hasFilteredData = filteredData.hasFilteredData();
                final ModelNode result = context.getResult();
                result.setEmptyObject();

                for (Map.Entry<String, ModelNode> entry : sortedChildren.entrySet()) {
                  if (!hasFilteredData
                      || !filteredData.isAddressFiltered(
                          address, PathElement.pathElement(childType, entry.getKey()))) {
                    result.get(entry.getKey()).set(entry.getValue());
                  }
                }

                if (hasFilteredData) {
                  context.getResponseHeaders().get(ACCESS_CONTROL).set(filteredData.toModelNode());
                }
              }

              context.stepCompleted();
            }
          },
          OperationContext.Stage.VERIFY);

      context.stepCompleted();
    }
  }
}
/**
 * {@link org.jboss.as.controller.OperationStepHandler} writing a single attribute. The required
 * request parameter "name" represents the attribute name.
 *
 * @author <a href="*****@*****.**">Kabir Khan</a>
 */
public class WriteAttributeHandler implements OperationStepHandler {

  public static final OperationDefinition DEFINITION =
      new SimpleOperationDefinitionBuilder(
              ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION,
              ControllerResolver.getResolver("global"))
          .setParameters(NAME, VALUE)
          .build();

  public static final OperationStepHandler INSTANCE = new WriteAttributeHandler();

  WriteAttributeHandler() {}

  @Override
  public void execute(OperationContext context, ModelNode operation)
      throws OperationFailedException {
    NAME.validateOperation(operation);
    final ModelNode nameModel =
        GlobalOperationAttributes.NAME.resolveModelAttribute(context, operation);
    final PathAddress address = context.getCurrentAddress();
    final ImmutableManagementResourceRegistration registry = context.getResourceRegistration();
    if (registry == null) {
      throw new OperationFailedException(ControllerLogger.ROOT_LOGGER.noSuchResourceType(address));
    }
    final boolean useEnhancedSyntax = containsEnhancedSyntax(nameModel.asString(), registry);
    final String attributeName;
    final String attributeExpression;
    if (useEnhancedSyntax) {
      attributeExpression = nameModel.asString();
      attributeName = extractAttributeName(nameModel.asString());
    } else {
      attributeName = nameModel.asString();
      attributeExpression = attributeName;
    }

    final AttributeAccess attributeAccess =
        registry.getAttributeAccess(PathAddress.EMPTY_ADDRESS, attributeName);
    if (attributeAccess == null) {
      throw new OperationFailedException(
          ControllerLogger.ROOT_LOGGER.unknownAttribute(attributeName));
    } else if (attributeAccess.getAccessType() != AttributeAccess.AccessType.READ_WRITE) {
      throw new OperationFailedException(
          ControllerLogger.ROOT_LOGGER.attributeNotWritable(attributeName));
    } else {

      // Authorize
      ModelNode currentValue;
      if (attributeAccess.getStorageType() == AttributeAccess.Storage.CONFIGURATION) {
        ModelNode model = context.readResourceForUpdate(PathAddress.EMPTY_ADDRESS).getModel();
        currentValue = model.has(attributeName) ? model.get(attributeName) : new ModelNode();
      } else {
        currentValue = new ModelNode();
      }
      AuthorizationResult authorizationResult =
          context.authorize(operation, attributeName, currentValue);
      if (authorizationResult.getDecision() == AuthorizationResult.Decision.DENY) {
        throw ControllerLogger.ROOT_LOGGER.unauthorized(
            operation.require(OP).asString(), address, authorizationResult.getExplanation());
      }

      if (attributeAccess.getStorageType() == AttributeAccess.Storage.CONFIGURATION
          && !registry.isRuntimeOnly()) {
        // if the attribute is stored in the configuration, we can read its
        // old and new value from the resource's model before and after executing its write handler
        final ModelNode oldValue = currentValue.clone();
        doExecuteInternal(
            context,
            operation,
            attributeAccess,
            attributeName,
            currentValue,
            useEnhancedSyntax,
            attributeExpression);
        ModelNode model = context.readResource(PathAddress.EMPTY_ADDRESS).getModel();
        ModelNode newValue = model.has(attributeName) ? model.get(attributeName) : new ModelNode();
        emitAttributeValueWrittenNotification(context, address, attributeName, oldValue, newValue);

      } else {
        assert attributeAccess.getStorageType() == AttributeAccess.Storage.RUNTIME;

        // if the attribute is a runtime attribute, its old and new values must
        // be read using the attribute's read handler and the write operation
        // must be sandwiched between the 2 calls to the read handler.
        // Each call to the read handlers will have their own results while
        // the call to the write handler will use this OSH context result.

        OperationContext.Stage currentStage = context.getCurrentStage();

        final ModelNode readAttributeOperation =
            Util.createOperation(READ_ATTRIBUTE_OPERATION, address);
        readAttributeOperation.get(NAME.getName()).set(attributeName);
        ReadAttributeHandler readAttributeHandler = new ReadAttributeHandler(null, null, false);

        // create 2 model nodes to store the result of the read-attribute operations
        // before and after writing the value
        final ModelNode oldValue = new ModelNode();
        final ModelNode newValue = new ModelNode();

        // We're going to add a bunch of steps, but we want them to execute right away
        // so we use the 'addFirst=true' param to addStep. That means we add them
        // in reverse order of how they will execute

        // 4th OSH is to emit the notification
        context.addStep(
            new OperationStepHandler() {
              @Override
              public void execute(OperationContext context, ModelNode operation)
                  throws OperationFailedException {
                // aggregate data from the 2 read-attribute operations
                emitAttributeValueWrittenNotification(
                    context, address, attributeName, oldValue.get(RESULT), newValue.get(RESULT));
              }
            },
            currentStage,
            true);

        // 3rd OSH is to read the new value
        context.addStep(newValue, readAttributeOperation, readAttributeHandler, currentStage, true);

        // 2nd OSH is to write the value
        context.addStep(
            new OperationStepHandler() {
              @Override
              public void execute(OperationContext context, ModelNode operation)
                  throws OperationFailedException {
                doExecuteInternal(
                    context,
                    operation,
                    attributeAccess,
                    attributeName,
                    oldValue.get(RESULT),
                    useEnhancedSyntax,
                    attributeExpression);
              }
            },
            currentStage,
            true);

        // 1st OSH is to read the old value
        context.addStep(oldValue, readAttributeOperation, readAttributeHandler, currentStage, true);
      }
    }
  }

  private void doExecuteInternal(
      OperationContext context,
      ModelNode operation,
      AttributeAccess attributeAccess,
      String attributeName,
      ModelNode currentValue,
      boolean useEnhancedSyntax,
      String attributeExpression)
      throws OperationFailedException {
    if (useEnhancedSyntax) {
      operation =
          getEnhancedSyntaxResolvedOperation(
              operation, currentValue, attributeName, attributeExpression);
    }
    OperationStepHandler writeHandler = attributeAccess.getWriteHandler();
    ClassLoader oldTccl =
        WildFlySecurityManager.setCurrentContextClassLoaderPrivileged(writeHandler.getClass());
    try {
      writeHandler.execute(context, operation);
    } finally {
      WildFlySecurityManager.setCurrentContextClassLoaderPrivileged(oldTccl);
    }
  }

  private void emitAttributeValueWrittenNotification(
      OperationContext context,
      PathAddress address,
      String attributeName,
      ModelNode oldValue,
      ModelNode newValue) {
    // only emit a notification if the value has been successfully changed
    if (oldValue.equals(newValue)) {
      return;
    }
    ModelNode data = new ModelNode();
    data.get(NAME.getName()).set(attributeName);
    data.get(GlobalNotifications.OLD_VALUE).set(oldValue);
    data.get(GlobalNotifications.NEW_VALUE).set(newValue);
    Notification notification =
        new Notification(
            ATTRIBUTE_VALUE_WRITTEN_NOTIFICATION,
            address,
            ControllerLogger.ROOT_LOGGER.attributeValueWritten(attributeName, oldValue, newValue),
            data);
    context.emit(notification);
  }

  private ModelNode getEnhancedSyntaxResolvedOperation(
      ModelNode originalOperation,
      ModelNode currentModel,
      String attributeName,
      String attributeExpression)
      throws OperationFailedException {
    ModelNode writeOp = originalOperation.clone();
    ModelNode diffValue = originalOperation.get(ModelDescriptionConstants.VALUE);
    ModelNode old = new ModelNode();
    old.get(attributeName).set(currentModel);
    ModelNode fullValue =
        EnhancedSyntaxSupport.updateWithEnhancedSyntax(attributeExpression, old, diffValue);
    writeOp.get(ModelDescriptionConstants.NAME).set(attributeName);
    writeOp.get(ModelDescriptionConstants.VALUE).set(fullValue.get(attributeName));
    return writeOp;
  }
}
/** @author Tomaz Cerar (c) 2014 Red Hat Inc. */
public class MapOperations {
  public static final OperationDefinition MAP_CLEAR_DEFINITION =
      new SimpleOperationDefinitionBuilder("map-clear", ControllerResolver.getResolver("global"))
          .setParameters(AbstractMapHandler.NAME)
          .setRuntimeOnly()
          .build();
  public static final OperationDefinition MAP_REMOVE_DEFINITION =
      new SimpleOperationDefinitionBuilder("map-remove", ControllerResolver.getResolver("global"))
          .setParameters(AbstractMapHandler.NAME, AbstractMapHandler.KEY)
          .setRuntimeOnly()
          .build();
  public static final OperationDefinition MAP_GET_DEFINITION =
      new SimpleOperationDefinitionBuilder("map-get", ControllerResolver.getResolver("global"))
          .setParameters(AbstractMapHandler.NAME, AbstractMapHandler.KEY)
          .setRuntimeOnly()
          .setReadOnly()
          .build();
  public static final OperationDefinition MAP_PUT_DEFINITION =
      new SimpleOperationDefinitionBuilder("map-put", ControllerResolver.getResolver("global"))
          .setParameters(AbstractMapHandler.NAME, AbstractMapHandler.KEY, AbstractMapHandler.VALUE)
          .setRuntimeOnly()
          .build();

  public static final OperationStepHandler MAP_CLEAR_HANDLER = new MapClearHandler();
  public static final OperationStepHandler MAP_GET_HANDLER = new MapGetHandler();
  public static final OperationStepHandler MAP_REMOVE_HANDLER = new MapRemoveHandler();
  public static final OperationStepHandler MAP_PUT_HANDLER = new MapPutHandler();

  public static final Set<String> MAP_OPERATION_NAMES =
      new HashSet<>(
          Arrays.asList(
              MAP_CLEAR_DEFINITION.getName(),
              MAP_REMOVE_DEFINITION.getName(),
              MAP_PUT_DEFINITION.getName(),
              MAP_GET_DEFINITION.getName()));

  /** @author Tomaz Cerar (c) 2014 Red Hat Inc. */
  abstract static class AbstractMapHandler extends AbstractCollectionHandler {
    static final SimpleAttributeDefinition KEY =
        new SimpleAttributeDefinition("key", ModelType.STRING, false);

    AbstractMapHandler(AttributeDefinition... attributes) {
      super(attributes);
    }

    AbstractMapHandler(boolean requiredReadWrite, AttributeDefinition... attributes) {
      super(requiredReadWrite, attributes);
    }

    abstract void updateModel(
        final OperationContext context,
        ModelNode model,
        AttributeDefinition attributeDefinition,
        ModelNode attribute)
        throws OperationFailedException;
  }

  /**
   * Empty map, note that is not the same as :undefine(name=name-of-attribute)
   *
   * <p>
   *
   * <pre>map-clear(name=name-of-attribute)</pre>
   *
   * @author Tomaz Cerar (c) 2014 Red Hat Inc.
   */
  public static class MapClearHandler extends AbstractMapHandler {
    private MapClearHandler() {
      super(true);
    }

    void updateModel(
        final OperationContext context,
        ModelNode model,
        AttributeDefinition attributeDefinition,
        ModelNode attribute)
        throws OperationFailedException {
      attribute.setEmptyObject();
    }
  }

  /**
   * Get entry from map:
   *
   * <p>
   *
   * <pre>:map-get(name=name-of-attribute, key=some-key)</pre>
   *
   * @author Tomaz Cerar (c) 2014 Red Hat Inc.
   */
  public static class MapGetHandler extends AbstractMapHandler {
    private MapGetHandler() {
      super(false, KEY);
    }

    void updateModel(
        final OperationContext context,
        ModelNode model,
        AttributeDefinition attributeDefinition,
        ModelNode attribute)
        throws OperationFailedException {
      String key = KEY.resolveModelAttribute(context, model).asString();
      context.getResult().set(attribute.get(key));
    }
  }

  /**
   * put entry to map
   *
   * <p>
   *
   * <pre>:map-put(name=name-of-attribute, key=some-key, value="newvalue")</pre>
   *
   * @author Tomaz Cerar (c) 2014 Red Hat Inc.
   */
  public static class MapPutHandler extends AbstractMapHandler {
    private MapPutHandler() {
      super(KEY, VALUE);
    }

    void updateModel(
        final OperationContext context,
        ModelNode model,
        AttributeDefinition attributeDefinition,
        ModelNode attribute)
        throws OperationFailedException {
      String key = KEY.resolveModelAttribute(context, model).asString();
      ModelNode value = VALUE.resolveModelAttribute(context, model);
      attribute.get(key).set(value);
    }
  }

  /**
   * Remove entry from map
   *
   * <p>
   *
   * <pre>:map-remove(name=name-of-attribute, key=some-key)</pre>
   *
   * @author Tomaz Cerar (c) 2014 Red Hat Inc.
   */
  public static class MapRemoveHandler extends AbstractMapHandler {
    private MapRemoveHandler() {
      super(KEY);
    }

    void updateModel(
        final OperationContext context,
        ModelNode model,
        AttributeDefinition attributeDefinition,
        ModelNode attribute)
        throws OperationFailedException {
      String key = KEY.resolveModelAttribute(context, model).asString();
      attribute.remove(key);
    }
  }
}
Example #14
0
/**
 * {@link org.jboss.as.controller.OperationStepHandler} reading a part of the model. The result will
 * only contain the current attributes of a node by default, excluding all addressable children and
 * runtime attributes. Setting the request parameter "recursive" to "true" will recursively include
 * all children and configuration attributes. Non-recursive queries can include runtime attributes
 * by setting the request parameter "include-runtime" to "true".
 *
 * @author <a href="*****@*****.**">Kabir Khan</a>
 */
public class ReadResourceHandler extends GlobalOperationHandlers.AbstractMultiTargetHandler
    implements OperationStepHandler {

  private static final SimpleAttributeDefinition ATTRIBUTES_ONLY =
      new SimpleAttributeDefinitionBuilder(
              ModelDescriptionConstants.ATTRIBUTES_ONLY, ModelType.BOOLEAN)
          .setAllowNull(true)
          .setDefaultValue(new ModelNode(false))
          .build();

  public static final OperationDefinition DEFINITION =
      new SimpleOperationDefinitionBuilder(
              READ_RESOURCE_OPERATION, ControllerResolver.getResolver("global"))
          .setParameters(
              RECURSIVE,
              RECURSIVE_DEPTH,
              PROXIES,
              INCLUDE_RUNTIME,
              INCLUDE_DEFAULTS,
              ATTRIBUTES_ONLY,
              INCLUDE_ALIASES)
          .setReadOnly()
          .setRuntimeOnly()
          .setReplyType(ModelType.OBJECT)
          .build();

  public static final OperationStepHandler INSTANCE = new ReadResourceHandler();

  private final ParametersValidator validator =
      new ParametersValidator() {

        @Override
        public void validate(ModelNode operation) throws OperationFailedException {
          super.validate(operation);
          if (operation.hasDefined(ModelDescriptionConstants.ATTRIBUTES_ONLY)) {
            if (operation.hasDefined(ModelDescriptionConstants.RECURSIVE)) {
              throw MESSAGES.cannotHaveBothParameters(
                  ModelDescriptionConstants.ATTRIBUTES_ONLY, ModelDescriptionConstants.RECURSIVE);
            }
            if (operation.hasDefined(ModelDescriptionConstants.RECURSIVE_DEPTH)) {
              throw MESSAGES.cannotHaveBothParameters(
                  ModelDescriptionConstants.ATTRIBUTES_ONLY,
                  ModelDescriptionConstants.RECURSIVE_DEPTH);
            }
          }
        }
      };

  public ReadResourceHandler() {
    // todo use AD for validation
    validator.registerValidator(
        ModelDescriptionConstants.RECURSIVE, new ModelTypeValidator(ModelType.BOOLEAN, true));
    validator.registerValidator(
        ModelDescriptionConstants.RECURSIVE_DEPTH, new ModelTypeValidator(ModelType.INT, true));
    validator.registerValidator(
        ModelDescriptionConstants.INCLUDE_RUNTIME, new ModelTypeValidator(ModelType.BOOLEAN, true));
    validator.registerValidator(
        ModelDescriptionConstants.PROXIES, new ModelTypeValidator(ModelType.BOOLEAN, true));
    validator.registerValidator(
        ModelDescriptionConstants.INCLUDE_DEFAULTS,
        new ModelTypeValidator(ModelType.BOOLEAN, true));
    validator.registerValidator(
        ModelDescriptionConstants.ATTRIBUTES_ONLY, new ModelTypeValidator(ModelType.BOOLEAN, true));
  }

  @Override
  void doExecute(OperationContext context, ModelNode operation) throws OperationFailedException {

    validator.validate(operation);

    final String opName = operation.require(OP).asString();
    final ModelNode opAddr = operation.get(OP_ADDR);
    final PathAddress address = PathAddress.pathAddress(opAddr);
    final int recursiveDepth = operation.get(ModelDescriptionConstants.RECURSIVE_DEPTH).asInt(0);
    final boolean recursive =
        recursiveDepth > 0
            ? true
            : operation.get(ModelDescriptionConstants.RECURSIVE).asBoolean(false);
    final boolean queryRuntime =
        operation.get(ModelDescriptionConstants.INCLUDE_RUNTIME).asBoolean(false);
    final boolean proxies = operation.get(ModelDescriptionConstants.PROXIES).asBoolean(false);
    final boolean aliases =
        operation.get(ModelDescriptionConstants.INCLUDE_ALIASES).asBoolean(false);
    final boolean defaults =
        operation.get(ModelDescriptionConstants.INCLUDE_DEFAULTS).asBoolean(true);
    final boolean attributesOnly =
        operation.get(ModelDescriptionConstants.ATTRIBUTES_ONLY).asBoolean(false);

    // Attributes read directly from the model with no special read handler step in the middle
    final Map<String, ModelNode> directAttributes = new HashMap<String, ModelNode>();
    // Children names read directly from the model with no special read handler step in the middle
    final Map<String, ModelNode> directChildren = new HashMap<String, ModelNode>();
    // Attributes of AccessType.METRIC
    final Map<String, ModelNode> metrics =
        queryRuntime ? new HashMap<String, ModelNode>() : Collections.<String, ModelNode>emptyMap();
    // Non-AccessType.METRIC attributes with a special read handler registered
    final Map<String, ModelNode> otherAttributes = new HashMap<String, ModelNode>();
    // Child resources recursively read
    final Map<PathElement, ModelNode> childResources =
        recursive
            ? new LinkedHashMap<PathElement, ModelNode>()
            : Collections.<PathElement, ModelNode>emptyMap();

    // We're going to add a bunch of steps that should immediately follow this one. We are going to
    // add them
    // in reverse order of how they should execute, as that is the way adding a Stage.IMMEDIATE step
    // works

    // Last to execute is the handler that assembles the overall response from the pieces created by
    // all the other steps
    final ReadResourceAssemblyHandler assemblyHandler =
        new ReadResourceAssemblyHandler(
            directAttributes, metrics, otherAttributes, directChildren, childResources);
    context.addStep(
        assemblyHandler,
        queryRuntime ? OperationContext.Stage.VERIFY : OperationContext.Stage.MODEL,
        true);
    final ImmutableManagementResourceRegistration registry = context.getResourceRegistration();

    // Get the model for this resource.
    final Resource resource = nullSafeReadResource(context, registry);

    final Map<String, Set<String>> childrenByType =
        registry != null
            ? GlobalOperationHandlers.getChildAddresses(context, address, registry, resource, null)
            : Collections.<String, Set<String>>emptyMap();
    final ModelNode model = resource.getModel();

    if (model.isDefined()) {
      // Store direct attributes first
      for (String key : model.keys()) {
        // In case someone put some garbage in it
        if (!childrenByType.containsKey(key)) {
          directAttributes.put(key, model.get(key));
        }
      }
    }

    if (defaults) {
      // get the model description
      final DescriptionProvider descriptionProvider =
          registry.getModelDescription(PathAddress.EMPTY_ADDRESS);
      final Locale locale = GlobalOperationHandlers.getLocale(context, operation);
      final ModelNode nodeDescription = descriptionProvider.getModelDescription(locale);

      if (nodeDescription.isDefined() && nodeDescription.hasDefined(ATTRIBUTES)) {
        for (String key : nodeDescription.get(ATTRIBUTES).keys()) {
          if ((!childrenByType.containsKey(key))
              && (!directAttributes.containsKey(key) || !directAttributes.get(key).isDefined())
              && nodeDescription.get(ATTRIBUTES).hasDefined(key)
              && nodeDescription.get(ATTRIBUTES, key).hasDefined(DEFAULT)) {
            directAttributes.put(key, nodeDescription.get(ATTRIBUTES, key, DEFAULT));
          }
        }
      }
    }

    if (!attributesOnly) {
      // Next, process child resources
      for (Map.Entry<String, Set<String>> entry : childrenByType.entrySet()) {
        String childType = entry.getKey();
        Set<String> children = entry.getValue();
        if (children.isEmpty()) {
          // Just treat it like an undefined attribute
          directAttributes.put(childType, new ModelNode());
        } else {
          for (String child : children) {
            if (recursive) {
              PathElement childPE = PathElement.pathElement(childType, child);
              PathAddress relativeAddr = PathAddress.pathAddress(childPE);
              ImmutableManagementResourceRegistration childReg = registry.getSubModel(relativeAddr);
              if (childReg == null) {
                throw new OperationFailedException(
                    new ModelNode().set(MESSAGES.noChildRegistry(childType, child)));
              }
              // Decide if we want to invoke on this child resource
              boolean proxy = childReg.isRemote();
              boolean runtimeResource = childReg.isRuntimeOnly();
              boolean getChild = !runtimeResource || (queryRuntime && !proxy) || (proxies && proxy);
              if (!aliases && childReg.isAlias()) {
                getChild = false;
              }
              if (getChild) {
                final int newDepth = recursiveDepth > 0 ? recursiveDepth - 1 : 0;
                // Add a step to read the child resource
                ModelNode rrOp = new ModelNode();
                rrOp.get(OP).set(opName);
                rrOp.get(OP_ADDR).set(PathAddress.pathAddress(address, childPE).toModelNode());
                rrOp.get(ModelDescriptionConstants.RECURSIVE)
                    .set(operation.get(ModelDescriptionConstants.RECURSIVE));
                rrOp.get(ModelDescriptionConstants.RECURSIVE_DEPTH).set(newDepth);
                rrOp.get(ModelDescriptionConstants.PROXIES).set(proxies);
                rrOp.get(ModelDescriptionConstants.INCLUDE_RUNTIME).set(queryRuntime);
                rrOp.get(ModelDescriptionConstants.INCLUDE_ALIASES).set(aliases);
                rrOp.get(ModelDescriptionConstants.INCLUDE_DEFAULTS).set(defaults);
                ModelNode rrRsp = new ModelNode();
                childResources.put(childPE, rrRsp);

                OperationStepHandler rrHandler =
                    childReg.getOperationHandler(PathAddress.EMPTY_ADDRESS, opName);
                context.addStep(rrRsp, rrOp, rrHandler, OperationContext.Stage.MODEL, true);
              }
            } else {
              ModelNode childMap = directChildren.get(childType);
              if (childMap == null) {
                childMap = new ModelNode();
                childMap.setEmptyObject();
                directChildren.put(childType, childMap);
              }
              // Add a "child" => undefined
              childMap.get(child);
            }
          }
        }
      }
    }

    // Last, handle attributes with read handlers registered
    final Set<String> attributeNames =
        registry != null
            ? registry.getAttributeNames(PathAddress.EMPTY_ADDRESS)
            : Collections.<String>emptySet();
    for (final String attributeName : attributeNames) {
      final AttributeAccess access =
          registry.getAttributeAccess(PathAddress.EMPTY_ADDRESS, attributeName);
      if (access == null || access.getFlags().contains(AttributeAccess.Flag.ALIAS) && !aliases) {
        continue;
      } else {
        final AttributeAccess.Storage storage = access.getStorageType();

        if (!queryRuntime && storage != AttributeAccess.Storage.CONFIGURATION) {
          continue;
        }
        final AttributeAccess.AccessType type = access.getAccessType();
        final OperationStepHandler handler = access.getReadHandler();
        if (handler != null) {
          // Discard any directAttribute map entry for this, as the read handler takes precedence
          directAttributes.remove(attributeName);
          // Create the attribute operation
          final ModelNode attributeOperation = new ModelNode();
          attributeOperation.get(OP_ADDR).set(opAddr);
          attributeOperation.get(OP).set(READ_ATTRIBUTE_OPERATION);
          attributeOperation.get(GlobalOperationHandlers.NAME.getName()).set(attributeName);

          final ModelNode attrResponse = new ModelNode();
          if (type == AttributeAccess.AccessType.METRIC) {
            metrics.put(attributeName, attrResponse);
          } else {
            otherAttributes.put(attributeName, attrResponse);
          }
          context.addStep(
              attrResponse, attributeOperation, handler, OperationContext.Stage.MODEL, true);
        }
      }
    }
    context.stepCompleted();
  }

  /**
   * Provides a resource for the current step, either from the context, if the context doesn't have
   * one and {@code registry} is runtime-only, it creates a dummy resource.
   */
  private static Resource nullSafeReadResource(
      final OperationContext context, final ImmutableManagementResourceRegistration registry) {

    Resource result;
    if (registry != null && registry.isRuntimeOnly()) {
      try {
        result = context.readResource(PathAddress.EMPTY_ADDRESS, false);
      } catch (RuntimeException e) {
        result = PlaceholderResource.INSTANCE;
      }
    } else {
      result = context.readResource(PathAddress.EMPTY_ADDRESS, false);
    }
    return result;
  }

  /**
   * Assembles the response to a read-resource request from the components gathered by earlier
   * steps.
   */
  private static class ReadResourceAssemblyHandler implements OperationStepHandler {

    private final Map<String, ModelNode> directAttributes;
    private final Map<String, ModelNode> directChildren;
    private final Map<String, ModelNode> metrics;
    private final Map<String, ModelNode> otherAttributes;
    private final Map<PathElement, ModelNode> childResources;

    /**
     * Creates a ReadResourceAssemblyHandler that will assemble the response using the contents of
     * the given maps.
     *
     * @param directAttributes map of attributes read directly from the model with no special read
     *     handler step in the middle
     * @param metrics map of attributes of AccessType.METRIC. Keys are the attribute names, values
     *     are the full read-attribute response from invoking the attribute's read handler. Will not
     *     be {@code null}
     * @param otherAttributes map of attributes not of AccessType.METRIC that have a read handler
     *     registered. Keys are the attribute names, values are the full read-attribute response
     *     from invoking the attribute's read handler. Will not be {@code null}
     * @param directChildren
     * @param childResources read-resource response from child resources, where the key is the
     *     PathAddress relative to the address of the operation this handler is handling and the
     *     value is the full read-resource response. Will not be {@code null}
     */
    private ReadResourceAssemblyHandler(
        final Map<String, ModelNode> directAttributes,
        final Map<String, ModelNode> metrics,
        final Map<String, ModelNode> otherAttributes,
        final Map<String, ModelNode> directChildren,
        final Map<PathElement, ModelNode> childResources) {
      this.directAttributes = directAttributes;
      this.metrics = metrics;
      this.otherAttributes = otherAttributes;
      this.directChildren = directChildren;
      this.childResources = childResources;
    }

    @Override
    public void execute(OperationContext context, ModelNode operation)
        throws OperationFailedException {

      Map<String, ModelNode> sortedAttributes = new TreeMap<String, ModelNode>();
      Map<String, ModelNode> sortedChildren = new TreeMap<String, ModelNode>();
      boolean failed = false;
      for (Map.Entry<String, ModelNode> entry : otherAttributes.entrySet()) {
        ModelNode value = entry.getValue();
        if (!value.has(FAILURE_DESCRIPTION)) {
          sortedAttributes.put(entry.getKey(), value.get(RESULT));
        } else if (!failed && value.hasDefined(FAILURE_DESCRIPTION)) {
          context.getFailureDescription().set(value.get(FAILURE_DESCRIPTION));
          failed = true;
          break;
        }
      }
      if (!failed) {
        for (Map.Entry<PathElement, ModelNode> entry : childResources.entrySet()) {
          PathElement path = entry.getKey();
          ModelNode value = entry.getValue();
          if (!value.has(FAILURE_DESCRIPTION)) {
            ModelNode childTypeNode = sortedChildren.get(path.getKey());
            if (childTypeNode == null) {
              childTypeNode = new ModelNode();
              sortedChildren.put(path.getKey(), childTypeNode);
            }
            childTypeNode.get(path.getValue()).set(value.get(RESULT));
          } else if (!failed && value.hasDefined(FAILURE_DESCRIPTION)) {
            context.getFailureDescription().set(value.get(FAILURE_DESCRIPTION));
            failed = true;
          }
        }
      }
      if (!failed) {
        for (Map.Entry<String, ModelNode> simpleAttribute : directAttributes.entrySet()) {
          sortedAttributes.put(simpleAttribute.getKey(), simpleAttribute.getValue());
        }
        for (Map.Entry<String, ModelNode> directChild : directChildren.entrySet()) {
          sortedChildren.put(directChild.getKey(), directChild.getValue());
        }
        for (Map.Entry<String, ModelNode> metric : metrics.entrySet()) {
          ModelNode value = metric.getValue();
          if (!value.has(FAILURE_DESCRIPTION)) {
            sortedAttributes.put(metric.getKey(), value.get(RESULT));
          }
          // we ignore metric failures
          // TODO how to prevent the metric failure screwing up the overall context?
        }

        final ModelNode result = context.getResult();
        result.setEmptyObject();
        for (Map.Entry<String, ModelNode> entry : sortedAttributes.entrySet()) {
          result.get(entry.getKey()).set(entry.getValue());
        }

        for (Map.Entry<String, ModelNode> entry : sortedChildren.entrySet()) {
          result.get(entry.getKey()).set(entry.getValue());
        }
      }

      context.stepCompleted();
    }
  }
}
Example #15
0
/** @author Tomaz Cerar (c) 2014 Red Hat Inc. */
public class ListOperations {

  public static final OperationDefinition LIST_ADD_DEFINITION =
      new SimpleOperationDefinitionBuilder("list-add", ControllerResolver.getResolver("global"))
          .setParameters(
              AbstractCollectionHandler.NAME,
              AbstractCollectionHandler.VALUE,
              AbstractListHandler.INDEX)
          .setRuntimeOnly()
          .build();
  public static final OperationDefinition LIST_GET_DEFINITION =
      new SimpleOperationDefinitionBuilder("list-get", ControllerResolver.getResolver("global"))
          .setParameters(AbstractCollectionHandler.NAME, AbstractListHandler.INDEX)
          .setRuntimeOnly()
          .setReadOnly()
          .build();
  public static final OperationDefinition LIST_REMOVE_DEFINITION =
      new SimpleOperationDefinitionBuilder("list-remove", ControllerResolver.getResolver("global"))
          .setParameters(
              AbstractCollectionHandler.NAME,
              AbstractCollectionHandler.VALUE,
              AbstractListHandler.INDEX)
          .setRuntimeOnly()
          .build();
  public static final OperationDefinition LIST_CLEAR_DEFINITION =
      new SimpleOperationDefinitionBuilder("list-clear", ControllerResolver.getResolver("global"))
          .setParameters(AbstractCollectionHandler.NAME)
          .setRuntimeOnly()
          .build();
  public static final OperationStepHandler LIST_ADD_HANDLER = new ListAddHandler();
  public static final OperationStepHandler LIST_REMOVE_HANDLER = new ListRemoveHandler();
  public static final OperationStepHandler LIST_GET_HANDLER = new ListGetHandler();
  public static final OperationStepHandler LIST_CLEAR_HANDLER = new ListClearHandler();

  public static final Set<String> LIST_OPERATION_NAMES =
      new HashSet<>(
          Arrays.asList(
              LIST_CLEAR_DEFINITION.getName(),
              LIST_REMOVE_DEFINITION.getName(),
              LIST_ADD_DEFINITION.getName(),
              LIST_GET_DEFINITION.getName()));

  /** @author Tomaz Cerar (c) 2014 Red Hat Inc. */
  abstract static class AbstractListHandler extends AbstractCollectionHandler {
    static final SimpleAttributeDefinition INDEX =
        new SimpleAttributeDefinition("index", ModelType.INT, true);

    AbstractListHandler(AttributeDefinition... attributes) {
      super(attributes);
    }

    AbstractListHandler(boolean requiredReadWrite, AttributeDefinition... attributes) {
      super(requiredReadWrite, attributes);
    }

    @Override
    public void updateModel(
        OperationContext context,
        ModelNode model,
        AttributeDefinition attributeDefinition,
        ModelNode attribute)
        throws OperationFailedException {
      if (attribute.getType() != ModelType.LIST
          && attributeDefinition.getType() != ModelType.LIST) {
        throw ControllerLogger.MGMT_OP_LOGGER.attributeIsWrongType(
            attributeDefinition.getName(), ModelType.LIST, attributeDefinition.getType());
      }
      updateModel(context, model, attribute);
    }

    abstract void updateModel(
        final OperationContext context, ModelNode model, ModelNode listAttribute)
        throws OperationFailedException;
  }

  /**
   * Add element to list, with optional index where to put it
   *
   * <p>
   *
   * <pre>:list-add(name=list-attribute, value="some value", [index=5])</pre>
   *
   * @author Tomaz Cerar (c) 2014 Red Hat Inc.
   */
  public static class ListAddHandler extends AbstractListHandler {
    private ListAddHandler() {
      super(VALUE, INDEX);
    }

    void updateModel(final OperationContext context, ModelNode model, ModelNode listAttribute)
        throws OperationFailedException {
      String value = VALUE.resolveModelAttribute(context, model).asString();
      ModelNode indexNode = INDEX.resolveModelAttribute(context, model);

      LinkedList<ModelNode> res =
          new LinkedList<>(
              listAttribute.isDefined()
                  ? listAttribute.asList()
                  : Collections.<ModelNode>emptyList());
      if (indexNode.isDefined()) {
        res.add(indexNode.asInt(), new ModelNode(value));
      } else {
        res.add(new ModelNode(value));
      }
      listAttribute.set(res);
    }
  }

  /**
   * Add element to list, with optional index where to put it
   *
   * <p>
   *
   * <pre>:list-remove(name=list-attribute, value="some value")</pre>
   *
   * @author Tomaz Cerar (c) 2014 Red Hat Inc.
   */
  public static class ListRemoveHandler extends AbstractListHandler {
    private ListRemoveHandler() {
      super(VALUE, INDEX);
    }

    void updateModel(final OperationContext context, ModelNode model, ModelNode listAttribute)
        throws OperationFailedException {
      ModelNode value = VALUE.resolveModelAttribute(context, model);
      ModelNode index = INDEX.resolveModelAttribute(context, model);
      List<ModelNode> res = new ArrayList<>(listAttribute.asList());
      if (index.isDefined()) {
        res.remove(index.asInt());
      } else {
        res.remove(value);
      }
      listAttribute.set(res);
    }
  }

  /**
   * Add element to list, with optional index where to put it
   *
   * <p>
   *
   * <pre>:list-remove(name=list-attribute, value="some value")</pre>
   *
   * @author Tomaz Cerar (c) 2014 Red Hat Inc.
   */
  public static class ListGetHandler extends AbstractListHandler {
    private ListGetHandler() {
      super(false, INDEX);
    }

    void updateModel(final OperationContext context, ModelNode model, ModelNode listAttribute)
        throws OperationFailedException {
      int index = INDEX.resolveModelAttribute(context, model).asInt();
      if (listAttribute.hasDefined(index)) {
        context.getResult().set(listAttribute.get(index));
      }
    }
  }

  /**
   * Add element to list, with optional index where to put it
   *
   * <p>
   *
   * <pre>:list-remove(name=list-attribute, value="some value")</pre>
   *
   * @author Tomaz Cerar (c) 2014 Red Hat Inc.
   */
  public static class ListClearHandler extends AbstractListHandler {
    private ListClearHandler() {
      super();
    }

    void updateModel(final OperationContext context, ModelNode model, ModelNode listAttribute)
        throws OperationFailedException {
      listAttribute.setEmptyList();
    }
  }
}