final boolean ops = OPERATIONS.resolveModelAttribute(context, operation).asBoolean();
final boolean aliases = INCLUDE_ALIASES.resolveModelAttribute(context, operation).asBoolean();
final boolean inheritedOps = INHERITED.resolveModelAttribute(context, operation).asBoolean();
//Get hold of the real registry if it was an alias
final ImmutableManagementResourceRegistration registry = context.getResourceRegistration();
AliasEntry aliasEntry = registry.getAliasEntry();
final ImmutableManagementResourceRegistration realRegistry = aliasEntry == null ? registry : context.getRootResourceRegistration().getSubModel(aliasEntry.convertToTargetAddress(PathAddress.pathAddress(opAddr)));
final DescriptionProvider descriptionProvider = realRegistry.getModelDescription(PathAddress.EMPTY_ADDRESS);
final Locale locale = GlobalOperationHandlers.getLocale(context, operation);
final ModelNode nodeDescription = descriptionProvider.getModelDescription(locale);
final Map<String, ModelNode> operations = new HashMap<String, ModelNode>();
final Map<PathElement, ModelNode> childResources = recursive ? new HashMap<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 ReadResourceDescriptionAssemblyHandler assemblyHandler = new ReadResourceDescriptionAssemblyHandler(nodeDescription, operations, childResources);
context.addStep(assemblyHandler, OperationContext.Stage.IMMEDIATE);
if (ops) {
for (final Map.Entry<String, OperationEntry> entry : realRegistry.getOperationDescriptions(PathAddress.EMPTY_ADDRESS, inheritedOps).entrySet()) {
if (entry.getValue().getType() == OperationEntry.EntryType.PUBLIC) {
if (context.getProcessType() != ProcessType.DOMAIN_SERVER || entry.getValue().getFlags().contains(OperationEntry.Flag.RUNTIME_ONLY)) {
final DescriptionProvider provider = entry.getValue().getDescriptionProvider();
operations.put(entry.getKey(), provider.getModelDescription(locale));
}
}
}
}
if (nodeDescription.hasDefined(ATTRIBUTES)) {
for (final String attr : nodeDescription.require(ATTRIBUTES).keys()) {
final AttributeAccess access = realRegistry.getAttributeAccess(PathAddress.EMPTY_ADDRESS, attr);
// If there is metadata for an attribute but no AttributeAccess, assume RO. Can't
// be writable without a registered handler. This opens the possibility that out-of-date metadata
// for attribute "foo" can lead to a read of non-existent-in-model "foo" with
// an unexpected undefined value returned. But it removes the possibility of a
// dev forgetting to call registry.registerReadOnlyAttribute("foo", null) resulting
// in the valid attribute "foo" not being readable
final AttributeAccess.AccessType accessType = access == null ? AttributeAccess.AccessType.READ_ONLY : access.getAccessType();
final AttributeAccess.Storage storage = access == null ? AttributeAccess.Storage.CONFIGURATION : access.getStorageType();
final ModelNode attrNode = nodeDescription.get(ATTRIBUTES, attr);
//AS7-3085 - For a domain mode server show writable attributes as read-only
String displayedAccessType =
context.getProcessType() == ProcessType.DOMAIN_SERVER && storage == AttributeAccess.Storage.CONFIGURATION ?
AttributeAccess.AccessType.READ_ONLY.toString() : accessType.toString();
attrNode.get(ACCESS_TYPE).set(displayedAccessType);
attrNode.get(STORAGE).set(storage.toString());
if (accessType == AttributeAccess.AccessType.READ_WRITE) {
Set<AttributeAccess.Flag> flags = access.getFlags();
if (flags.contains(AttributeAccess.Flag.RESTART_ALL_SERVICES)) {
attrNode.get(RESTART_REQUIRED).set("all-services");
} else if (flags.contains(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES)) {
attrNode.get(RESTART_REQUIRED).set("resource-services");
} else if (flags.contains(AttributeAccess.Flag.RESTART_JVM)) {
attrNode.get(RESTART_REQUIRED).set("jvm");
} else {
attrNode.get(RESTART_REQUIRED).set("no-services");
}
}
}
}
if (recursive) {
for (final PathElement element : realRegistry.getChildAddresses(PathAddress.EMPTY_ADDRESS)) {
PathAddress relativeAddr = PathAddress.pathAddress(element);
ImmutableManagementResourceRegistration childReg = realRegistry.getSubModel(relativeAddr);
boolean readChild = true;
if (childReg.isRemote() && !proxies) {
readChild = false;
}
if (childReg.isAlias() && !aliases) {
readChild = false;
}
if (readChild) {
final int newDepth = recursiveDepth > 0 ? recursiveDepth - 1 : 0;
ModelNode rrOp = new ModelNode();
rrOp.get(OP).set(opName);
try {
rrOp.get(OP_ADDR).set(PathAddress.pathAddress(address, element).toModelNode());
} catch (Exception e) {
continue;
}
rrOp.get(RECURSIVE.getName()).set(operation.get(RECURSIVE.getName()));
rrOp.get(RECURSIVE_DEPTH.getName()).set(newDepth);
rrOp.get(PROXIES.getName()).set(proxies);
rrOp.get(OPERATIONS.getName()).set(ops);
rrOp.get(INHERITED.getName()).set(inheritedOps);
rrOp.get(LOCALE.getName()).set(operation.get(LOCALE.getName()));
rrOp.get(INCLUDE_ALIASES.getName()).set(aliases);
ModelNode rrRsp = new ModelNode();
childResources.put(element, rrRsp);
final OperationStepHandler handler = childReg.isRemote() ? childReg.getOperationHandler(PathAddress.EMPTY_ADDRESS, opName) :
new OperationStepHandler() {
@Override
public void execute(final OperationContext context, final ModelNode operation) throws OperationFailedException {
doExecute(context, operation);
}