/* * * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat Middleware LLC, 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; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.jboss.as.controller.capability.Capability; import org.jboss.as.controller.capability.RuntimeCapability; import org.jboss.as.controller.descriptions.ResourceDescriptionResolver; import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver; import org.jboss.as.controller.registry.AttributeAccess; import org.jboss.as.controller.registry.ManagementResourceRegistration; /** * @author <a href="mailto:tomaz.cerar@redhat.com">Tomaz Cerar</a> (c) 2012 Red Hat Inc. */ class ResourceBuilderRoot implements ResourceBuilder { private final PathElement pathElement; private final StandardResourceDescriptionResolver resourceResolver; private final List<AttributeBinding> attributes = new LinkedList<>(); private final List<OperationBinding> operations = new LinkedList<>(); private final List<Capability> capabilities = new LinkedList<>(); private ResourceDescriptionResolver attributeResolver = null; // TODO field is never read except in copy c'tor private OperationStepHandler addHandler; private OperationStepHandler removeHandler; private DeprecationData deprecationData; private final List<ResourceBuilderRoot> children = new LinkedList<ResourceBuilderRoot>(); private final ResourceBuilderRoot parent; private boolean isRuntime = false; private Set<RuntimeCapability> incorporatingCapabilities; /** Normal constructor */ private ResourceBuilderRoot(PathElement pathElement, StandardResourceDescriptionResolver resourceResolver, OperationStepHandler addHandler, OperationStepHandler removeHandler, ResourceBuilderRoot parent) { this.pathElement = pathElement; this.resourceResolver = resourceResolver; this.parent = parent; this.addHandler = addHandler; this.removeHandler = removeHandler; } /** * Copy constructor for {@link #pushChild(ResourceBuilder)} to use when integrating a child built externally. */ private ResourceBuilderRoot(final ResourceBuilderRoot toCopy, final ResourceBuilderRoot parent) { this(toCopy.pathElement, toCopy.resourceResolver, toCopy.addHandler, toCopy.removeHandler, parent); this.attributes.addAll(toCopy.attributes); this.operations.addAll(toCopy.operations); this.capabilities.addAll(toCopy.capabilities); this.children.addAll(toCopy.children); if (toCopy.incorporatingCapabilities != null) { this.incorporatingCapabilities = new HashSet<>(toCopy.incorporatingCapabilities); } this.addHandler = toCopy.addHandler; this.removeHandler = toCopy.removeHandler; this.deprecationData = toCopy.deprecationData; this.isRuntime = parent.isRuntime; this.attributeResolver = toCopy.attributeResolver; // TODO Remove if this field is unneeded } static ResourceBuilder create(PathElement pathElement, StandardResourceDescriptionResolver resourceDescriptionResolver) { return new ResourceBuilderRoot(pathElement, resourceDescriptionResolver, null, null, null); } static ResourceBuilder create(PathElement pathElement, StandardResourceDescriptionResolver resourceResolver, OperationStepHandler addHandler, OperationStepHandler removeHandler) { return new ResourceBuilderRoot(pathElement, resourceResolver, addHandler, removeHandler, null); } @Override public ResourceBuilder setAddOperation(final AbstractAddStepHandler handler) { this.addHandler = handler; return this; } @Override public ResourceBuilder setRemoveOperation(final AbstractRemoveStepHandler handler) { this.removeHandler = handler; return this; } @Override public ResourceBuilder setAddOperation(RestartParentResourceAddHandler handler) { this.addHandler = handler; return this; } @Override public ResourceBuilder setRemoveOperation(RestartParentResourceRemoveHandler handler) { this.removeHandler = handler; return this; } @Override public ResourceBuilder addReadWriteAttribute(AttributeDefinition attributeDefinition, OperationStepHandler reader, OperationStepHandler writer) { attributes.add(new AttributeBinding(attributeDefinition, reader, writer, AttributeAccess.AccessType.READ_WRITE)); return this; } @Override public ResourceBuilder addReadWriteAttributes(OperationStepHandler reader, OperationStepHandler writer, final AttributeDefinition... attributes) { for (AttributeDefinition ad : attributes) { this.attributes.add(new AttributeBinding(ad, reader, writer, AttributeAccess.AccessType.READ_WRITE)); } return this; } @Override public ResourceBuilder addReadOnlyAttribute(AttributeDefinition attributeDefinition) { attributes.add(new AttributeBinding(attributeDefinition, null, null, AttributeAccess.AccessType.READ_ONLY)); return this; } @Override public ResourceBuilder addMetric(AttributeDefinition attributeDefinition, OperationStepHandler handler) { attributes.add(new AttributeBinding(attributeDefinition, handler, null, AttributeAccess.AccessType.METRIC)); return this; } @Override public ResourceBuilder addMetrics(OperationStepHandler metricHandler, final AttributeDefinition... attributes) { for (AttributeDefinition ad : attributes) { this.attributes.add(new AttributeBinding(ad, metricHandler, null, AttributeAccess.AccessType.METRIC)); } return this; } @Override public ResourceBuilder setAttributeResolver(ResourceDescriptionResolver resolver) { this.attributeResolver = resolver; return this; } @Override public ResourceBuilder addOperation(final OperationDefinition operationDefinition, final OperationStepHandler handler) { return addOperation(operationDefinition, handler, false); } @Override public ResourceBuilder addOperation(final OperationDefinition operationDefinition, final OperationStepHandler handler, boolean inherited) { operations.add(new OperationBinding(operationDefinition, handler, inherited)); return this; } @Override public ResourceBuilder deprecated(ModelVersion since) { this.deprecationData = new DeprecationData(since); return this; } @Override public ResourceBuilder setRuntime() { this.isRuntime = true; return this; } @Override public ResourceBuilder addCapability(Capability capability) { capabilities.add(capability); return this; } @Override public ResourceBuilder addCapabilities(Capability... capabilities) { this.capabilities.addAll(Arrays.asList(capabilities)); return this; } @Override public ResourceBuilder setIncorporatingCapabilities(Set<RuntimeCapability> incorporating) { this.incorporatingCapabilities = incorporating; return this; } public ResourceBuilder pushChild(final PathElement pathElement) { return pushChild(pathElement, resourceResolver.getChildResolver(pathElement.getKey())); } @Override public ResourceBuilder pushChild(final PathElement pathElement, final OperationStepHandler addHandler, final OperationStepHandler removeHandler) { return pushChild(pathElement, resourceResolver.getChildResolver(pathElement.getKey()), addHandler, removeHandler); } public ResourceBuilder pushChild(final PathElement pathElement, StandardResourceDescriptionResolver resolver) { return pushChild(pathElement, resolver, null, null); } @Override public ResourceBuilder pushChild(final PathElement pathElement, StandardResourceDescriptionResolver resolver, final OperationStepHandler addHandler, final OperationStepHandler removeHandler) { ResourceBuilderRoot child = new ResourceBuilderRoot(pathElement, resolver, addHandler, removeHandler, this); children.add(child); return child; } @Override public ResourceBuilder pushChild(final ResourceBuilder child) { ResourceBuilderRoot childDelegate = new ResourceBuilderRoot((ResourceBuilderRoot) child, this); children.add(childDelegate); return childDelegate; } @Override public ResourceBuilder pop() { if (parent == null) { return this; } return parent; } @Override public ResourceDefinition build() { if (parent != null) { return parent.build(); } return new BuilderResourceDefinition(this); } List<AttributeBinding> getAttributes() { return attributes; } List<OperationBinding> getOperations() { return operations; } List<ResourceBuilderRoot> getChildren() { return children; } private static class BuilderResourceDefinition extends SimpleResourceDefinition { final ResourceBuilderRoot builder; private BuilderResourceDefinition(ResourceBuilderRoot builder) { //super(builder.pathElement, builder.resourceResolver, builder.addHandler, builder.removeHandler, null, null, builder.deprecationData, builder.isRuntime); super(new Parameters(builder.pathElement, builder.resourceResolver) .setAddHandler(builder.addHandler) .setRemoveHandler(builder.removeHandler) .setDeprecationData(builder.deprecationData) .setRuntime(builder.isRuntime) .setCapabilities(builder.capabilities.toArray(new RuntimeCapability[builder.capabilities.size()])) .setIncorporatingCapabilities(builder.incorporatingCapabilities) ); this.builder = builder; } @Override public void registerOperations(ManagementResourceRegistration resourceRegistration) { super.registerOperations(resourceRegistration); for (OperationBinding ob : builder.operations) { ob.register(resourceRegistration); } } @Override public void registerAttributes(ManagementResourceRegistration resourceRegistration) { super.registerAttributes(resourceRegistration); for (AttributeBinding ab : builder.attributes) { ab.register(resourceRegistration); } } @Override public void registerChildren(ManagementResourceRegistration resourceRegistration) { super.registerChildren(resourceRegistration); for (ResourceBuilderRoot child : builder.children) { resourceRegistration.registerSubModel(new BuilderResourceDefinition(child)); } } } private static final class AttributeBinding { private final AttributeDefinition attribute; private final OperationStepHandler readOp; private final OperationStepHandler writeOp; private final AttributeAccess.AccessType accessType; AttributeBinding(AttributeDefinition attribute, OperationStepHandler readOp, OperationStepHandler writeOp, AttributeAccess.AccessType accessType) { this.attribute = attribute; this.readOp = readOp; this.writeOp = writeOp; this.accessType = accessType; } void register(ManagementResourceRegistration registration) { if (accessType == AttributeAccess.AccessType.READ_ONLY) { registration.registerReadOnlyAttribute(attribute, readOp); } else if (accessType == AttributeAccess.AccessType.READ_WRITE) { registration.registerReadWriteAttribute(attribute, readOp, writeOp); } else if (accessType == AttributeAccess.AccessType.METRIC) { registration.registerMetric(attribute, readOp); } } } private static final class OperationBinding { private OperationDefinition definition; private OperationStepHandler handler; private boolean inherited; OperationBinding(OperationDefinition definition, OperationStepHandler handler, boolean inherited) { this.definition = definition; this.handler = handler; this.inherited = inherited; } public void register(ManagementResourceRegistration registration) { registration.registerOperationHandler(definition, handler, inherited); } } }