Package org.jboss.as.controller.operations.global

Source Code of org.jboss.as.controller.operations.global.GlobalOperationHandlers$ReadChildrenResourcesOperationHandler

/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.controller.operations.global;

import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ACCESS_TYPE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ATTRIBUTES;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CHILDREN;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CHILD_TYPE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INCLUDE_RUNTIME;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.LOCALE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MODEL_DESCRIPTION;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OPERATIONS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_RESOURCE_DESCRIPTION_OPERATION;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_RESOURCE_OPERATION;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RECURSIVE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.STORAGE;

import java.util.Collection;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.jboss.as.controller.BasicOperationResult;
import org.jboss.as.controller.ModelAddOperationHandler;
import org.jboss.as.controller.ModelQueryOperationHandler;
import org.jboss.as.controller.ModelUpdateOperationHandler;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.OperationHandler;
import org.jboss.as.controller.OperationResult;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.PathElement;
import org.jboss.as.controller.ProxyController;
import org.jboss.as.controller.ResultHandler;
import org.jboss.as.controller.client.Operation;
import org.jboss.as.controller.client.OperationBuilder;
import org.jboss.as.controller.descriptions.DescriptionProvider;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.as.controller.registry.AttributeAccess;
import org.jboss.as.controller.registry.AttributeAccess.AccessType;
import org.jboss.as.controller.registry.AttributeAccess.Storage;
import org.jboss.as.controller.registry.ModelNodeRegistration;
import org.jboss.as.controller.registry.OperationEntry;
import org.jboss.dmr.ModelNode;

/**
* Global {@code OperationHanlder}s.
*
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
*/
public class GlobalOperationHandlers {

    public static final OperationHandler READ_RESOURCE = new ReadResourceHandler();
    public static final OperationHandler READ_ATTRIBUTE = new ReadAttributeHandler();
    public static final OperationHandler READ_CHILDREN_NAMES = new ReadChildrenNamesOperationHandler();
    public static final OperationHandler READ_CHILDREN_RESOURCES = new ReadChildrenResourcesOperationHandler();
    public static final OperationHandler WRITE_ATTRIBUTE = new WriteAttributeHandler();
    public static final ResolveAddressOperationHandler RESOLVE = new ResolveAddressOperationHandler();

    private GlobalOperationHandlers() {
        //
    }

    /**
     * {@link OperationHandler} 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".
     */
    public static class ReadResourceHandler implements ModelQueryOperationHandler {

        static final String PROXIES = "proxies";

        @Override
        public OperationResult execute(final OperationContext context, final ModelNode operation, final ResultHandler resultHandler) throws OperationFailedException {

            final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR));
            final ModelNode result = readModel(context, operation, resultHandler, address);
            resultHandler.handleResultFragment(Util.NO_LOCATION, result);
            resultHandler.handleResultComplete();
            return new BasicOperationResult();
        }

        protected ModelNode readModel(final OperationContext context, final ModelNode readOperation,
                final ResultHandler resultHandler, final PathAddress address) throws OperationFailedException {
            final ModelNodeRegistration registry = context.getRegistry();
            final ModelNode model = context.getSubModel(address);
            final ModelNode result;
                if (readOperation.get(RECURSIVE).asBoolean(false)) {
                    // FIXME security checks JBAS-8842
                    result = model.clone();
                    if(readOperation.get(PROXIES).asBoolean(true)) {
                        addProxyNodes(context, address, readOperation, result, registry);
                    }
                } else {
                    result = new ModelNode();

                    final Set<String> childNames = registry.getChildNames(address);

                    final ModelNode subModel = model.clone();
                    for (final String key : subModel.keys()) {
                        final ModelNode child = subModel.get(key);
                        if (childNames.contains(key)) {
                            //Prune the value for this child
                            if (subModel.get(key).isDefined()) {
                                for (final String childKey : child.keys()) {
                                    subModel.get(key, childKey).set(new ModelNode());
                                }
                            }

                            result.get(key).set(child);
                        } else {
                            result.get(key).set(child);
                        }
                    }
                    // Handle attributes
                    final boolean queryRuntime = readOperation.get(INCLUDE_RUNTIME).asBoolean(false);
                    final Set<String> attributeNames = registry.getAttributeNames(address);
                    for(final String attributeName : attributeNames) {
                        final AttributeAccess access = registry.getAttributeAccess(address, attributeName);
                        if(access == null) {
                            continue;
                        } else {
                            final AttributeAccess.Storage storage = access.getStorageType();
                            if(! queryRuntime && storage != AttributeAccess.Storage.CONFIGURATION) {
                                continue;
                            }
                            final AccessType type = access.getAccessType();
                            final OperationHandler handler = access.getReadHandler();
                            if(handler != null) {
                                // Create the attribute operation
                                final ModelNode attributeOperation = readOperation.clone();
                                attributeOperation.get(NAME).set(attributeName);
                                // TODO this assumes the ResultHandler is invoked synchronously
                                handler.execute(context, attributeOperation, new ResultHandler() {
                                    @Override
                                    public void handleResultFragment(final String[] location, final ModelNode attributeResult) {
                                        result.get(attributeName).set(attributeResult);
                                    }
                                    @Override
                                    public void handleResultComplete() {
                                        // TODO
                                    }
                                    @Override
                                    public void handleFailed(ModelNode failureDescription) {
                                        if(type != AccessType.METRIC) {
                                            resultHandler.handleFailed(failureDescription);
                                        }
                                    }
                                    @Override
                                    public void handleCancellation() {
                                        resultHandler.handleCancellation();
                                    }
                                });
                            }
                        }
                    }
                    handleNonRecursiveProxyEntries(context, address, readOperation, result, registry);
                }
            return result;
        }

        protected void handleNonRecursiveProxyEntries(final OperationContext context, final PathAddress address, final ModelNode originalOperation, final ModelNode result, final ModelNodeRegistration registry) {
        }

        protected void addProxyNodes(final OperationContext context, final PathAddress address, final ModelNode originalOperation, final ModelNode result, final ModelNodeRegistration registry) {
            Set<ProxyController> proxyControllers = registry.getProxyControllers(address);
            if (proxyControllers.size() > 0) {
                final ModelNode operation = new ModelNode();
                operation.get(OP).set(READ_RESOURCE_OPERATION);
                operation.get(RECURSIVE).set(true);
                operation.get(OP_ADDR).set(new ModelNode());

                for (ProxyController proxyController : proxyControllers) {
                    final ModelNode proxyResult = proxyController.execute(OperationBuilder.Factory.copy(context, operation).build());

                    //Trim the address to not include the host=>hostB part if this is a slave controller
                    PathAddress proxyAddress = proxyController.getProxyNodeAddress();
//                    if (proxyAddress.size() > 1) {
//                        if (proxyAddress.getElement(0).getKey().equals(HOST)) {
//                            proxyAddress = proxyAddress.subAddress(1);
//                            proxyResult =
//                        }
//                    }

                    addProxyResultToMainResult(proxyAddress, result, proxyResult);
                }
            }
        }

        protected void addProxyResultToMainResult(final PathAddress address, final ModelNode mainResult, final ModelNode proxyResult) {
            ModelNode resultNode = mainResult;
            for (Iterator<PathElement> it = address.iterator() ; it.hasNext() ; ) {
                PathElement element = it.next();
                resultNode = resultNode.get(element.getKey()).get(element.getValue());
            }
            resultNode.set(proxyResult.get(RESULT).clone());
        }

    };

    /**
     * {@link OperationHandler} reading a single attribute at the given operation address. The required request parameter "name" represents the attribute name.
     */
    public static class ReadAttributeHandler implements ModelQueryOperationHandler {
        @Override
        public OperationResult execute(final OperationContext context, final ModelNode operation, final ResultHandler resultHandler) throws OperationFailedException {
            OperationResult handlerResult = new BasicOperationResult();

            final String attributeName = operation.require(NAME).asString();
            final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR));
            final AttributeAccess attributeAccess = context.getRegistry().getAttributeAccess(address, attributeName);
            if (attributeAccess == null) {
                final Set<String> children = context.getRegistry().getChildNames(address);
                if(children.contains(attributeName)) {
                    throw new OperationFailedException(new ModelNode().set(String.format("'%s' is a registered child of resource (%s)", attributeName, address))); // TODO i18n
                } else if(context.getSubModel().has(attributeName)) {
                    final ModelNode result = context.getSubModel().get(attributeName).clone();
                    resultHandler.handleResultFragment(Util.NO_LOCATION, result);
                    resultHandler.handleResultComplete();
                } else {
                    throw new OperationFailedException(new ModelNode().set("No known attribute called " + attributeName)); // TODO i18n
                }
            } else if (attributeAccess.getReadHandler() == null) {
                final ModelNode result = context.getSubModel().get(attributeName).clone();
                resultHandler.handleResultFragment(Util.NO_LOCATION, result);
                resultHandler.handleResultComplete();
            } else {
                handlerResult = attributeAccess.getReadHandler().execute(context, operation, resultHandler);
            }

            return handlerResult;
        }
    };

    /**
     * {@link OperationHandler} writing a single attribute. The required request parameter "name" represents the attribute name.
     */
    public static class WriteAttributeHandler implements ModelUpdateOperationHandler {
        @Override
        public OperationResult execute(final OperationContext context, final ModelNode operation, final ResultHandler resultHandler) throws OperationFailedException {
            OperationResult handlerResult = null;

            final String attributeName = operation.require(NAME).asString();
            final AttributeAccess attributeAccess = context.getRegistry().getAttributeAccess(PathAddress.pathAddress(operation.get(OP_ADDR)), attributeName);
            if (attributeAccess == null) {
                throw new OperationFailedException(new ModelNode().set("No known attribute called " + attributeName)); // TODO i18n
            } else if (attributeAccess.getAccessType() != AccessType.READ_WRITE) {
                throw new OperationFailedException(new ModelNode().set("Attribute " + attributeName + " is not writeable")); // TODO i18n
            } else {
                handlerResult = attributeAccess.getWriteHandler().execute(context, operation, resultHandler);
            }

            return handlerResult;
        }
    };

    /**
     * {@link OperationHandler} querying the children names of a given "child-type".
     */
    public static class ReadChildrenNamesOperationHandler implements ModelQueryOperationHandler {
        @Override
        public OperationResult execute(final OperationContext context, final ModelNode operation, final ResultHandler resultHandler) throws OperationFailedException {

            String childName = operation.require(CHILD_TYPE).asString();

            ModelNode subModel = context.getSubModel().clone();
            if (!subModel.isDefined()) {
                final ModelNode result = new ModelNode();
                result.setEmptyList();
                resultHandler.handleResultFragment(new String[0], result);
            } else {
                final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR));
                final Set<String> childNames = context.getRegistry().getChildNames(address);
                if (!childNames.contains(childName)) {
                    throw new OperationFailedException(new ModelNode().set("No known child called " + childName)); //TODO i18n
                } else {
                    final ModelNode result = new ModelNode();
                    subModel = subModel.get(childName);
                    if (!subModel.isDefined()) {
                        result.setEmptyList();
                    } else {
                        for (final String key : subModel.keys()) {
                            final ModelNode node = new ModelNode();
                            node.set(key);
                            result.add(node);
                        }
                    }
                    resultHandler.handleResultFragment(Util.NO_LOCATION, result);
                }
            }

            resultHandler.handleResultComplete();
            return new BasicOperationResult();
        }
    };

    /**
     * {@link OperationHandler} querying the children resources of a given "child-type".
     */
    public static class ReadChildrenResourcesOperationHandler extends ReadResourceHandler {
        @Override
        public OperationResult execute(final OperationContext context, final ModelNode operation, final ResultHandler resultHandler) throws OperationFailedException {

            String childName = operation.require(CHILD_TYPE).asString();

            ModelNode subModel = context.getSubModel().clone();
            if (!subModel.isDefined()) {
                final ModelNode result = new ModelNode();
                result.setEmptyList();
                resultHandler.handleResultFragment(new String[0], result);
                resultHandler.handleResultComplete();
            } else {
                final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR));
                final Set<String> childNames = context.getRegistry().getChildNames(address);
                if (!childNames.contains(childName)) {
                    throw new OperationFailedException(new ModelNode().set("No known child called " + childName)); //TODO i18n
                } else {
                    final AtomicBoolean ok = new AtomicBoolean(true);
                    final ModelNode result = new ModelNode();
                    subModel = subModel.get(childName);
                    if (!subModel.isDefined()) {
                        result.setEmptyList();
                    } else {

                        for (final String key : subModel.keys()) {
                            if (!ok.get()) {
                                break;
                            }
                            final PathAddress childAddress = address.append(PathElement.pathElement(childName, key));

                            final ModelNode readOp = operation.clone();
                            readOp.get(OP_ADDR).set(childAddress.toModelNode());

                            if(operation.hasDefined(INCLUDE_RUNTIME))
                                readOp.get(INCLUDE_RUNTIME).set(operation.get(INCLUDE_RUNTIME).asBoolean());

                            final ModelNode readResult = readModel(context, readOp, new ResultHandler() {
                                public void handleResultFragment(String[] location, ModelNode result) {
                                    // TODO
                                }
                                public void handleResultComplete() {
                                    // TODO
                                }
                                public void handleFailed(ModelNode failureDescription) {
                                    ok.set(false);
                                    resultHandler.handleFailed(failureDescription);
                                }
                                public void handleCancellation() {
                                    ok.set(false);
                                    resultHandler.handleCancellation();
                                }
                            }, childAddress);
                            result.add(key, readResult);
                        }
                    }

                    if (ok.get()) {
                        resultHandler.handleResultFragment(Util.NO_LOCATION, result);
                        resultHandler.handleResultComplete();
                    }
                }
            }

            return new BasicOperationResult();
        }
    };

    /**
     * {@link OperationHandler} querying the child types of a given node.
     */
    public static final ModelQueryOperationHandler READ_CHILDREN_TYPES = new ModelQueryOperationHandler() {
        @Override
        public OperationResult execute(final OperationContext context, final ModelNode operation, final ResultHandler resultHandler) throws OperationFailedException {

            ModelNode subModel = context.getSubModel().clone();
            if (!subModel.isDefined()) {
                final ModelNode result = new ModelNode();
                result.setEmptyList();
                resultHandler.handleResultFragment(new String[0], result);
            } else {

                Set<String> childTypes = context.getRegistry().getChildNames(PathAddress.pathAddress(operation.get(OP_ADDR)));
                final ModelNode result = new ModelNode();
                for (final String key : childTypes) {
                    final ModelNode node = new ModelNode();
                    node.set(key);
                    result.add(node);
                }

                resultHandler.handleResultFragment(Util.NO_LOCATION, result);
            }

            resultHandler.handleResultComplete();

            return new BasicOperationResult();
        }
    };

    /**
     * {@link OperationHandler} returning the names of the defined operations at a given model address.
     */
    public static final ModelQueryOperationHandler READ_OPERATION_NAMES = new ModelQueryOperationHandler() {

        @Override
        public OperationResult execute(final OperationContext context, final ModelNode operation, final ResultHandler resultHandler) throws OperationFailedException {

            final ModelNodeRegistration registry = context.getRegistry();
            final Map<String, OperationEntry> operations = registry.getOperationDescriptions(PathAddress.pathAddress(operation.get(OP_ADDR)), true);

            final ModelNode result = new ModelNode();
            if (operations.size() > 0) {
                for(final Entry<String, OperationEntry> entry : operations.entrySet()) {
                    if(entry.getValue().getType() == OperationEntry.EntryType.PUBLIC) {
                        result.add(entry.getKey());
                    }
                }
            } else {
                result.setEmptyList();
            }
            resultHandler.handleResultFragment(Util.NO_LOCATION, result);
            resultHandler.handleResultComplete();

            return new BasicOperationResult();
        }
    };

    /**
     * {@link OperationHandler} returning the type description of a single operation description.
     */
    public static final ModelQueryOperationHandler READ_OPERATION_DESCRIPTION = new ModelQueryOperationHandler() {

        @Override
        public OperationResult execute(final OperationContext context, final ModelNode operation, final ResultHandler resultHandler) throws OperationFailedException {

            String operationName = operation.require(NAME).asString();

            final ModelNodeRegistration registry = context.getRegistry();
            final DescriptionProvider descriptionProvider = registry.getOperationDescription(PathAddress.pathAddress(operation.get(OP_ADDR)), operationName);

            final ModelNode result = descriptionProvider == null ? new ModelNode() : descriptionProvider.getModelDescription(getLocale(operation));

            resultHandler.handleResultFragment(Util.NO_LOCATION, result);
            resultHandler.handleResultComplete();

            return new BasicOperationResult();
        }
    };

    /**
     * {@link OperationHandler} querying the complete type description of a given model node.
     */
    public static final ModelQueryOperationHandler READ_RESOURCE_DESCRIPTION = new ModelQueryOperationHandler() {

        @Override
        public OperationResult execute(final OperationContext context, final ModelNode operation, final ResultHandler resultHandler) throws OperationFailedException {

            final boolean operations = operation.get(OPERATIONS).isDefined() ? operation.get(OPERATIONS).asBoolean() : false;
            final boolean recursive = operation.get(RECURSIVE).isDefined() ? operation.get(RECURSIVE).asBoolean() : false;

            final ModelNodeRegistration registry = context.getRegistry();
            final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR));
            final DescriptionProvider descriptionProvider = registry.getModelDescription(address);
            final Locale locale = getLocale(operation);
            final ModelNode result = descriptionProvider.getModelDescription(locale);

            addDescription(context, result, recursive, operations, registry, address, locale);

            resultHandler.handleResultFragment(Util.NO_LOCATION, result);
            resultHandler.handleResultComplete();

            return new BasicOperationResult();
        }

        private void addDescription(final OperationContext context, final ModelNode result, final boolean recursive, final boolean operations, final ModelNodeRegistration registry, final PathAddress address, final Locale locale) throws OperationFailedException {

            if (operations) {
                final Map<String, OperationEntry> ops = registry.getOperationDescriptions(address, true);
                if (ops.size() > 0) {

                    for (final Map.Entry<String, OperationEntry> entry : ops.entrySet()) {
                        if(entry.getValue().getType() == OperationEntry.EntryType.PUBLIC) {
                            final DescriptionProvider provider = entry.getValue().getDescriptionProvider();
                            result.get(OPERATIONS, entry.getKey()).set(provider.getModelDescription(locale));
                        }
                    }

                } else {
                    result.get(OPERATIONS).setEmptyList();
                }
            }

            if (result.hasDefined(ATTRIBUTES)) {
                for (final String attr : result.require(ATTRIBUTES).keys()) {
                     final AttributeAccess access = registry.getAttributeAccess(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 AccessType accessType = access == null ? AccessType.READ_ONLY : access.getAccessType();
                     final Storage storage = access == null ? Storage.CONFIGURATION : access.getStorageType();
                     result.get(ATTRIBUTES, attr, ACCESS_TYPE).set(accessType.toString()); //TODO i18n
                     result.get(ATTRIBUTES, attr, STORAGE).set(storage.toString());
                }
            }
            if (recursive && result.hasDefined(CHILDREN)) {
                for (final PathElement element : registry.getChildAddresses(address)) {
                    final PathAddress childAddress = address.append(element);
                    final DescriptionProvider provider = registry.getModelDescription(childAddress);
                    final ModelNode child;
                    if (provider == null) {
                        //It is probably a proxy
                        Set<ProxyController> proxyControllers = registry.getProxyControllers(childAddress);
                        if (proxyControllers.size() != 1) {
                            throw new IllegalStateException("No description provider found for " + childAddress +
                                    ". Tried to search for proxies, expected to find 1 proxy controller, found: " + proxyControllers.size());
                        }

                        final ModelNode operation = new ModelNode();
                        operation.get(OP).set(READ_RESOURCE_DESCRIPTION_OPERATION);
                        operation.get(OP_ADDR).set(new ModelNode());
                        operation.get(RECURSIVE).set(true);
                        operation.get(OPERATIONS).set(operations);
                        if (locale != null) {
                            operation.get(OPERATIONS).set(locale.toString());
                        }
                        child = proxyControllers.iterator().next().execute(OperationBuilder.Factory.copy(context, operation).build()).get(RESULT);

                    } else {
                        child = provider.getModelDescription(locale);
                        addDescription(context, child, recursive, operations, registry, childAddress, locale);
                    }
                    result.get(CHILDREN, element.getKey(),MODEL_DESCRIPTION, element.getValue()).set(child);
                }
            }
        }
    };


    public static final class ResolveAddressOperationHandler implements ModelQueryOperationHandler, DescriptionProvider {

        public static final String OPERATION_NAME = "resolve-address";
        public static final String ADDRESS_PARAM = "address-to-resolve";
        public static final String ORIGINAL_OPERATION = "original-operation";

        /** {@inheritDoc} */
        @Override
        public OperationResult execute(final OperationContext context, final ModelNode operation, final ResultHandler resultHandler) throws OperationFailedException {
            final PathAddress address = PathAddress.pathAddress(operation.require(ADDRESS_PARAM));
            final String operationName = operation.require(ORIGINAL_OPERATION).asString();
            // First check if the address is handled by a proxy
            final Collection<ProxyController> proxies = context.getRegistry().getProxyControllers(address);
            final int size = proxies.size();
            if(size > 0) {
                final AtomicInteger count = new AtomicInteger(size);
                final AtomicInteger status = new AtomicInteger();
                final ModelNode failureResult = new ModelNode();
                for(final ProxyController proxy : proxies) {
                    final PathAddress proxyAddress = proxy.getProxyNodeAddress();
                    final ModelNode newOperation = operation.clone();
                    newOperation.get(OP_ADDR).set(address.subAddress(proxyAddress.size()).toModelNode());
                    final Operation operationContext = OperationBuilder.Factory.create(newOperation).build();
                    proxy.execute(operationContext, new ResultHandler() {
                        @Override
                        public void handleResultFragment(String[] location, ModelNode result) {
                            synchronized(failureResult) {
                                if(status.get() == 0) {
                                    // Addresses are aggregated as list by the controller
                                    final PathAddress resolved = PathAddress.pathAddress(result);
                                    resultHandler.handleResultFragment(Util.NO_LOCATION, proxyAddress.append(resolved).toModelNode());
                                }
                            }
                        }
                        @Override
                        public void handleResultComplete() {
                            synchronized(failureResult) {
                                status.compareAndSet(0, 1);
                                if(count.decrementAndGet() == 0) {
                                    handleComplete();
                                }
                            }
                        }
                        @Override
                        public void handleFailed(ModelNode failureDescription) {
                            synchronized(failureResult) {
                                if(failureDescription != null)  {
                                    failureResult.add(failureDescription);
                                }
                                status.compareAndSet(0, 2);
                                if(count.decrementAndGet() == 0) {
                                    handleComplete();
                                }
                            }
                        }
                        @Override
                        public void handleCancellation() {
                            synchronized(failureResult) {
                                status.compareAndSet(0, 3);
                                if(count.decrementAndGet() == 0) {
                                    handleComplete();
                                }
                            }
                        }
                        private void handleComplete() {
                            final int s = status.get();
                            switch(s) {
                                case 1: resultHandler.handleResultComplete(); break;
                                case 2: resultHandler.handleFailed(new ModelNode()); break;
                                case 3: resultHandler.handleCancellation(); break;
                                default : throw new IllegalStateException();
                            }
                        }
                    });
                    return new BasicOperationResult();
                }
            }
            final OperationHandler operationHandler = context.getRegistry().getOperationHandler(address, operationName);
            if(operationHandler == null) {
                resultHandler.handleFailed(new ModelNode().set("no operation handler" + operationName));
                return new BasicOperationResult();
            }
            final Collection<PathAddress> resolved;
            if(operationHandler instanceof ModelQueryOperationHandler) {
                resolved = PathAddress.resolve(address, context.getSubModel(), operationHandler instanceof ModelAddOperationHandler);
            } else {
                resolved = context.getRegistry().resolveAddress(address);
            }
            if(! resolved.isEmpty()) {
                for(PathAddress a : resolved) {
                    // Addresses are aggregated as list by the controller
                    resultHandler.handleResultFragment(Util.NO_LOCATION, a.toModelNode());
                }
            }
            resultHandler.handleResultComplete();
            return new BasicOperationResult();
        }

        /** {@inheritDoc} */
        @Override
        public ModelNode getModelDescription(Locale locale) {
            return new ModelNode();
        }

    }

    private static Locale getLocale(final ModelNode operation) {
        if (!operation.hasDefined(LOCALE)) {
            return null;
        }
        return new Locale(operation.get(LOCALE).asString());
    }


}
TOP

Related Classes of org.jboss.as.controller.operations.global.GlobalOperationHandlers$ReadChildrenResourcesOperationHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.