/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, 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.extension;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PROFILE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;
import javax.xml.namespace.QName;
import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.ExtensionContext;
import org.jboss.as.controller.ModelVersion;
import org.jboss.as.controller.ModelVersionRange;
import org.jboss.as.controller.NotificationDefinition;
import org.jboss.as.controller.OperationDefinition;
import org.jboss.as.controller.OperationStepHandler;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.PathElement;
import org.jboss.as.controller.ProcessType;
import org.jboss.as.controller.ProxyController;
import org.jboss.as.controller.ResourceDefinition;
import org.jboss.as.controller.RunningMode;
import org.jboss.as.controller.RunningModeControl;
import org.jboss.as.controller.SimpleResourceDefinition;
import org.jboss.as.controller.SubsystemRegistration;
import org.jboss.as.controller.access.Action;
import org.jboss.as.controller.access.AuthorizationResult;
import org.jboss.as.controller.access.Caller;
import org.jboss.as.controller.access.Environment;
import org.jboss.as.controller.access.JmxAction;
import org.jboss.as.controller.access.JmxTarget;
import org.jboss.as.controller.access.TargetAttribute;
import org.jboss.as.controller.access.TargetResource;
import org.jboss.as.controller.access.management.AccessConstraintDefinition;
import org.jboss.as.controller.access.management.JmxAuthorizer;
import org.jboss.as.controller.audit.AuditLogger;
import org.jboss.as.controller.audit.ManagedAuditLogger;
import org.jboss.as.controller.capability.RuntimeCapability;
import org.jboss.as.controller.descriptions.DescriptionProvider;
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
import org.jboss.as.controller.descriptions.NonResolvingResourceDescriptionResolver;
import org.jboss.as.controller.descriptions.OverrideDescriptionProvider;
import org.jboss.as.controller.logging.ControllerLogger;
import org.jboss.as.controller.parsing.ExtensionParsingContext;
import org.jboss.as.controller.parsing.ProfileParsingCompletionHandler;
import org.jboss.as.controller.persistence.SubsystemMarshallingContext;
import org.jboss.as.controller.persistence.SubsystemXmlWriterRegistry;
import org.jboss.as.controller.registry.AliasEntry;
import org.jboss.as.controller.registry.AttributeAccess;
import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.as.controller.registry.NotificationEntry;
import org.jboss.as.controller.registry.OperationEntry;
import org.jboss.as.controller.registry.Resource;
import org.jboss.as.controller.services.path.PathManager;
import org.jboss.as.controller.transform.CombinedTransformer;
import org.jboss.as.controller.transform.OperationTransformer;
import org.jboss.as.controller.transform.ResourceTransformer;
import org.jboss.as.controller.transform.TransformerRegistry;
import org.jboss.as.controller.transform.TransformersSubRegistration;
import org.jboss.dmr.ModelNode;
import org.jboss.staxmapper.XMLElementReader;
import org.jboss.staxmapper.XMLElementWriter;
import org.jboss.staxmapper.XMLMapper;
import org.wildfly.security.auth.server.SecurityIdentity;
/**
* A registry for information about {@link org.jboss.as.controller.Extension}s to the core application server.
* In server/standalone mode there will be one extension registry for the whole server process. In domain mode,
* there will be:
* <ul>
* <li>One extension registry for extensions in the domain model</li>
* <li>One extension registry for extension in the host model</li>
* </ul>
* @author Brian Stansberry (c) 2011 Red Hat Inc.
*/
public class ExtensionRegistry {
// Hack to restrict the extensions to which we expose ExtensionContextSupplement
private static final Set<String> legallySupplemented;
static {
Set<String> set = new HashSet<>(4);
set.add("org.jboss.as.jmx");
set.add("Test"); // used by shared subsystem test fixture TestModelControllerService
legallySupplemented = Collections.unmodifiableSet(set);
}
private final ProcessType processType;
private SubsystemXmlWriterRegistry writerRegistry;
private volatile PathManager pathManager;
private final ConcurrentMap<String, ExtensionInfo> extensions = new ConcurrentHashMap<String, ExtensionInfo>();
// subsystem -> extension
private final ConcurrentMap<String, String> reverseMap = new ConcurrentHashMap<String, String>();
private final RunningModeControl runningModeControl;
private final ManagedAuditLogger auditLogger;
private final JmxAuthorizer authorizer;
private final Supplier<SecurityIdentity> securityIdentitySupplier;
private final ConcurrentHashMap<String, SubsystemInformation> subsystemsInfo = new ConcurrentHashMap<String, SubsystemInformation>();
private volatile TransformerRegistry transformerRegistry = TransformerRegistry.Factory.create();
private final RuntimeHostControllerInfoAccessor hostControllerInfoAccessor;
/**
* Constructor
*
* @param processType the type of the process
* @param runningModeControl the process' running mode
* @param auditLogger logger for auditing changes
* @param authorizer hook for exposing access control information to the JMX subsystem
* @param hostControllerInfoAccessor the host controller
*/
public ExtensionRegistry(ProcessType processType, RunningModeControl runningModeControl, ManagedAuditLogger auditLogger, JmxAuthorizer authorizer,
Supplier<SecurityIdentity> securityIdentitySupplier, RuntimeHostControllerInfoAccessor hostControllerInfoAccessor) {
this.processType = processType;
this.runningModeControl = runningModeControl;
this.auditLogger = auditLogger != null ? auditLogger : AuditLogger.NO_OP_LOGGER;
this.authorizer = authorizer != null ? authorizer : NO_OP_AUTHORIZER;
this.securityIdentitySupplier = securityIdentitySupplier;
this.hostControllerInfoAccessor = hostControllerInfoAccessor;
}
/**
* Constructor
*
* @param processType the type of the process
* @param runningModeControl the process' running mode
* @deprecated Here for core-model-test and subsystem-test backwards compatibility
*/
@Deprecated
public ExtensionRegistry(ProcessType processType, RunningModeControl runningModeControl) {
this(processType, runningModeControl, null, null, null, RuntimeHostControllerInfoAccessor.SERVER);
}
/**
* Sets the {@link SubsystemXmlWriterRegistry} to use for storing subsystem marshallers.
*
* @param writerRegistry the writer registry
*/
public void setWriterRegistry(final SubsystemXmlWriterRegistry writerRegistry) {
this.writerRegistry = writerRegistry;
}
/**
* Sets the {@link PathManager} to provide {@link ExtensionContext#getPathManager() via the ExtensionContext}.
*
* @param pathManager the path manager
*/
public void setPathManager(final PathManager pathManager) {
this.pathManager = pathManager;
}
public SubsystemInformation getSubsystemInfo(final String name) {
return subsystemsInfo.get(name);
}
/**
* Gets the module names of all known {@link org.jboss.as.controller.Extension}s.
*
* @return the names. Will not return {@code null}
*/
public Set<String> getExtensionModuleNames() {
return Collections.unmodifiableSet(extensions.keySet());
}
/**
* Gets information about the subsystems provided by a given {@link org.jboss.as.controller.Extension}.
*
* @param moduleName the name of the extension's module. Cannot be {@code null}
* @return map of subsystem names to information about the subsystem.
*/
public Map<String, SubsystemInformation> getAvailableSubsystems(String moduleName) {
Map<String, SubsystemInformation> result = null;
final ExtensionInfo info = extensions.get(moduleName);
if (info != null) {
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (info) {
result = Collections.unmodifiableMap(new HashMap<String, SubsystemInformation>(info.subsystems));
}
}
return result;
}
/**
* Gets an {@link ExtensionParsingContext} for use when
* {@link org.jboss.as.controller.Extension#initializeParsers(ExtensionParsingContext) initializing the extension's parsers}.
*
* @param moduleName the name of the extension's module. Cannot be {@code null}
* @param xmlMapper the {@link XMLMapper} handling the extension parsing. Can be {@code null} if there won't
* be any actual parsing (e.g. in a slave Host Controller or in a server in a managed domain)
* @return the {@link ExtensionParsingContext}. Will not return {@code null}
*/
public ExtensionParsingContext getExtensionParsingContext(final String moduleName, final XMLMapper xmlMapper) {
return new ExtensionParsingContextImpl(moduleName, xmlMapper);
}
/**
* Gets an {@link ExtensionContext} for use when handling an {@code add} operation for
* a resource representing an {@link org.jboss.as.controller.Extension}.
*
* @param moduleName the name of the extension's module. Cannot be {@code null}
* @param rootRegistration the root management resource registration
* @param isMasterDomainController set to {@code true} if we are the master domain controller, in which case transformers get registered
*
* @return the {@link ExtensionContext}. Will not return {@code null}
*
* @deprecated use {@link #getExtensionContext(String, ManagementResourceRegistration, ExtensionRegistryType)}. Main code should be using this, but this is left behind in case any tests need to use this code.
*/
@Deprecated
public ExtensionContext getExtensionContext(final String moduleName, ManagementResourceRegistration rootRegistration, boolean isMasterDomainController) {
ExtensionRegistryType type = isMasterDomainController ? ExtensionRegistryType.MASTER : ExtensionRegistryType.SLAVE;
return getExtensionContext(moduleName, rootRegistration, type);
}
/**
* Gets an {@link ExtensionContext} for use when handling an {@code add} operation for
* a resource representing an {@link org.jboss.as.controller.Extension}.
*
* @param moduleName the name of the extension's module. Cannot be {@code null}
* @param rootRegistration the root management resource registration
* @param extensionRegistryType the type of registry we are working on, which has an effect on things like whether extensions get registered etc.
*
* @return the {@link ExtensionContext}. Will not return {@code null}
*/
public ExtensionContext getExtensionContext(final String moduleName, ManagementResourceRegistration rootRegistration, ExtensionRegistryType extensionRegistryType) {
// Can't use processType.isServer() to determine where to look for profile reg because a lot of test infrastructure
// doesn't add the profile mrr even in HC-based tests
ManagementResourceRegistration profileRegistration = rootRegistration.getSubModel(PathAddress.pathAddress(PathElement.pathElement(PROFILE)));
if (profileRegistration == null) {
profileRegistration = rootRegistration;
}
ManagementResourceRegistration deploymentsRegistration = processType.isServer() ? rootRegistration.getSubModel(PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT))) : null;
// Hack to restrict extra data to specified extension(s)
boolean allowSupplement = legallySupplemented.contains(moduleName);
ManagedAuditLogger al = allowSupplement ? auditLogger : null;
return new ExtensionContextImpl(moduleName, profileRegistration, deploymentsRegistration, pathManager, extensionRegistryType, al);
}
public Set<ProfileParsingCompletionHandler> getProfileParsingCompletionHandlers() {
Set<ProfileParsingCompletionHandler> result = new HashSet<ProfileParsingCompletionHandler>();
for (ExtensionInfo extensionInfo : extensions.values()) {
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (extensionInfo) {
if (extensionInfo.parsingCompletionHandler != null) {
result.add(extensionInfo.parsingCompletionHandler);
}
}
}
return Collections.unmodifiableSet(result);
}
/**
* Cleans up a extension module's subsystems from the resource registration model.
*
* @param rootResource the model root resource
* @param moduleName the name of the extension's module. Cannot be {@code null}
* @throws IllegalStateException if the extension still has subsystems present in {@code rootResource} or its children
*/
public void removeExtension(Resource rootResource, String moduleName, ManagementResourceRegistration rootRegistration) throws IllegalStateException {
final ManagementResourceRegistration profileReg;
if (rootRegistration.getPathAddress().size() == 0) {
//domain or server extension
// Can't use processType.isServer() to determine where to look for profile reg because a lot of test infrastructure
// doesn't add the profile mrr even in HC-based tests
ManagementResourceRegistration reg = rootRegistration.getSubModel(PathAddress.pathAddress(PathElement.pathElement(PROFILE)));
if (reg == null) {
reg = rootRegistration;
}
profileReg = reg;
} else {
//host model extension
profileReg = rootRegistration;
}
ManagementResourceRegistration deploymentsReg = processType.isServer() ? rootRegistration.getSubModel(PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT))) : null;
ExtensionInfo extension = extensions.remove(moduleName);
if (extension != null) {
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (extension) {
Set<String> subsystemNames = extension.subsystems.keySet();
final boolean dcExtension = processType == ProcessType.HOST_CONTROLLER ?
rootRegistration.getPathAddress().size() == 0 : false;
for (String subsystem : subsystemNames) {
if (hasSubsystemsRegistered(rootResource, subsystem, dcExtension)) {
// Restore the data
extensions.put(moduleName, extension);
throw ControllerLogger.ROOT_LOGGER.removingExtensionWithRegisteredSubsystem(moduleName, subsystem);
}
}
for (Map.Entry<String, SubsystemInformation> entry : extension.subsystems.entrySet()) {
String subsystem = entry.getKey();
profileReg.unregisterSubModel(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, subsystem));
if (deploymentsReg != null) {
deploymentsReg.unregisterSubModel(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, subsystem));
deploymentsReg.unregisterSubModel(PathElement.pathElement(ModelDescriptionConstants.SUBDEPLOYMENT, subsystem));
}
if (extension.xmlMapper != null) {
SubsystemInformationImpl subsystemInformation = SubsystemInformationImpl.class.cast(entry.getValue());
for (String namespace : subsystemInformation.getXMLNamespaces()) {
extension.xmlMapper.unregisterRootElement(new QName(namespace, SUBSYSTEM));
}
}
}
}
}
}
private boolean hasSubsystemsRegistered(Resource rootResource, String subsystem, boolean dcExtension) {
if (!dcExtension) {
return rootResource.getChild(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, subsystem)) != null;
}
for (Resource profile : rootResource.getChildren(PROFILE)) {
if (profile.getChild(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, subsystem)) != null) {
return true;
}
}
return false;
}
/**
* Clears the registry to prepare for re-registration (e.g. as part of a reload).
*/
public void clear() {
synchronized (extensions) { // we synchronize just to guard unnamedMerged
transformerRegistry = TransformerRegistry.Factory.create();
extensions.clear();
reverseMap.clear();
subsystemsInfo.clear();
}
}
/**
* Records the versions of the subsystems associated with the given {@code moduleName} as properties in the
* provided {@link ModelNode}. Each subsystem property key will be the subsystem name and the value will be
* a string composed of the subsystem major version dot appended to its minor version.
*
* @param moduleName the name of the extension module
* @param subsystems a model node of type {@link org.jboss.dmr.ModelType#UNDEFINED} or type {@link org.jboss.dmr.ModelType#OBJECT}
*/
public void recordSubsystemVersions(String moduleName, ModelNode subsystems) {
final Map<String, SubsystemInformation> subsystemsInfo = getAvailableSubsystems(moduleName);
if(subsystemsInfo != null && ! subsystemsInfo.isEmpty()) {
for(final Map.Entry<String, SubsystemInformation> entry : subsystemsInfo.entrySet()) {
SubsystemInformation subsystem = entry.getValue();
subsystems.add(entry.getKey(),
subsystem.getManagementInterfaceMajorVersion() + "."
+ subsystem.getManagementInterfaceMinorVersion()
+ "." + subsystem.getManagementInterfaceMicroVersion());
}
}
}
private ExtensionInfo getExtensionInfo(final String extensionModuleName) {
ExtensionInfo result = extensions.get(extensionModuleName);
if (result == null) {
result = new ExtensionInfo(extensionModuleName);
ExtensionInfo existing = extensions.putIfAbsent(extensionModuleName, result);
result = existing == null ? result : existing;
}
return result;
}
private void checkNewSubystem(final String extensionModuleName, final String subsystemName) {
String existingModule = reverseMap.putIfAbsent(subsystemName, extensionModuleName);
if (existingModule != null && !extensionModuleName.equals(existingModule)) {
throw ControllerLogger.ROOT_LOGGER.duplicateSubsystem(subsystemName, extensionModuleName, existingModule);
}
}
public TransformerRegistry getTransformerRegistry() {
return transformerRegistry;
}
private class ExtensionParsingContextImpl implements ExtensionParsingContext {
private final ExtensionInfo extension;
private ExtensionParsingContextImpl(String extensionName, XMLMapper xmlMapper) {
extension = getExtensionInfo(extensionName);
if (xmlMapper != null) {
synchronized (extension) {
extension.xmlMapper = xmlMapper;
}
}
}
@Override
public ProcessType getProcessType() {
return processType;
}
@Override
public RunningMode getRunningMode() {
return runningModeControl.getRunningMode();
}
@Override
public void setSubsystemXmlMapping(String subsystemName, String namespaceUri, XMLElementReader<List<ModelNode>> reader) {
assert subsystemName != null : "subsystemName is null";
assert namespaceUri != null : "namespaceUri is null";
synchronized (extension) {
extension.getSubsystemInfo(subsystemName).addParsingNamespace(namespaceUri);
if (extension.xmlMapper != null) {
extension.xmlMapper.registerRootElement(new QName(namespaceUri, SUBSYSTEM), reader);
}
}
}
@Override
public void setSubsystemXmlMapping(String subsystemName, String namespaceUri, Supplier<XMLElementReader<List<ModelNode>>> supplier){
assert subsystemName != null : "subsystemName is null";
assert namespaceUri != null : "namespaceUri is null";
synchronized (extension) {
extension.getSubsystemInfo(subsystemName).addParsingNamespace(namespaceUri);
if (extension.xmlMapper != null) {
extension.xmlMapper.registerRootElement(new QName(namespaceUri, SUBSYSTEM), supplier);
}
}
}
@Override
public void setProfileParsingCompletionHandler(ProfileParsingCompletionHandler handler) {
assert handler != null : "handler is null";
synchronized (extension) {
extension.parsingCompletionHandler = handler;
}
}
}
@SuppressWarnings("deprecation")
private class ExtensionContextImpl implements ExtensionContext, ExtensionContextSupplement {
private final ExtensionInfo extension;
private final PathManager pathManager;
private final boolean registerTransformers;
private final ManagedAuditLogger auditLogger;
private final boolean allowSupplement;
private final ManagementResourceRegistration profileRegistration;
private final ManagementResourceRegistration deploymentsRegistration;
private final ExtensionRegistryType extensionRegistryType;
private ExtensionContextImpl(String extensionName, ManagementResourceRegistration profileResourceRegistration,
ManagementResourceRegistration deploymentsResourceRegistration, PathManager pathManager,
ExtensionRegistryType extensionRegistryType, ManagedAuditLogger auditLogger) {
assert pathManager != null || !processType.isServer() : "pathManager is null";
this.pathManager = pathManager;
this.extension = getExtensionInfo(extensionName);
this.registerTransformers = extensionRegistryType == ExtensionRegistryType.MASTER;
this.auditLogger = auditLogger;
this.allowSupplement = auditLogger != null;
this.profileRegistration = profileResourceRegistration;
if (deploymentsResourceRegistration != null) {
PathAddress subdepAddress = PathAddress.pathAddress(PathElement.pathElement(ModelDescriptionConstants.SUBDEPLOYMENT));
final ManagementResourceRegistration subdeployments = deploymentsResourceRegistration.getSubModel(subdepAddress);
this.deploymentsRegistration = subdeployments == null ? deploymentsResourceRegistration
: new DeploymentManagementResourceRegistration(deploymentsResourceRegistration, subdeployments);
} else {
this.deploymentsRegistration = null;
}
this.extensionRegistryType = extensionRegistryType;
}
@Override
public SubsystemRegistration registerSubsystem(String name, ModelVersion version) {
return registerSubsystem(name, version, false);
}
@Override
@Deprecated
@SuppressWarnings("deprecation")
public SubsystemRegistration registerSubsystem(String name, int majorVersion, int minorVersion) throws IllegalArgumentException, IllegalStateException {
return registerSubsystem(name, majorVersion, minorVersion, 0);
}
@Override
@Deprecated
@SuppressWarnings("deprecation")
public SubsystemRegistration registerSubsystem(String name, int majorVersion, int minorVersion, int microVersion) {
return registerSubsystem(name, majorVersion, minorVersion, microVersion, false);
}
@Override
@Deprecated
public SubsystemRegistration registerSubsystem(String name, int majorVersion, int minorVersion, int microVersion, boolean deprecated) {
return registerSubsystem(name, ModelVersion.create(majorVersion, minorVersion, microVersion), deprecated);
}
public SubsystemRegistration registerSubsystem(String name, ModelVersion version, boolean deprecated) {
assert name != null : "name is null";
checkNewSubystem(extension.extensionModuleName, name);
SubsystemInformationImpl info = extension.getSubsystemInfo(name);
info.setVersion(version);
subsystemsInfo.put(name, info);
if (deprecated){
ControllerLogger.DEPRECATED_LOGGER.extensionDeprecated(name);
}
SubsystemRegistrationImpl result = new SubsystemRegistrationImpl(name, version,
profileRegistration, deploymentsRegistration, extensionRegistryType, extension.extensionModuleName, processType);
if (registerTransformers){
transformerRegistry.loadAndRegisterTransformers(name, version, extension.extensionModuleName);
}
return result;
}
@Override
public ProcessType getProcessType() {
return processType;
}
@Override
public RunningMode getRunningMode() {
return runningModeControl.getRunningMode();
}
@Override
public boolean isRuntimeOnlyRegistrationValid() {
if (processType.isServer()) {
return true;
}
if (processType == ProcessType.HOST_CONTROLLER && extensionRegistryType == ExtensionRegistryType.HOST) {
return true;
}
return false;
}
@Override
public PathManager getPathManager() {
if (!processType.isServer()) {
throw ControllerLogger.ROOT_LOGGER.pathManagerNotAvailable(processType);
}
return pathManager;
}
@Override
@Deprecated
public boolean isRegisterTransformers() {
return registerTransformers;
}
// ExtensionContextSupplement implementation
/**
* This method is only for internal use. We do NOT currently want to expose it on the ExtensionContext interface.
*/
@Override
public AuditLogger getAuditLogger(boolean inheritConfiguration, boolean manualCommit) {
if (!allowSupplement) {
throw new UnsupportedOperationException();
}
if (inheritConfiguration) {
return auditLogger;
}
return auditLogger.createNewConfiguration(manualCommit);
}
/**
* This method is only for internal use. We do NOT currently want to expose it on the ExtensionContext interface.
*/
@Override
public JmxAuthorizer getAuthorizer() {
if (!allowSupplement) {
throw new UnsupportedOperationException();
}
return authorizer;
}
/**
* This method is only for internal use. We do NOT currently want to expose it on the ExtensionContext interface.
*/
@Override
public Supplier<SecurityIdentity> getSecurityIdentitySupplier() {
if (!allowSupplement) {
throw new UnsupportedOperationException();
}
return securityIdentitySupplier;
}
@Override
public RuntimeHostControllerInfoAccessor getHostControllerInfoAccessor() {
if (!allowSupplement) {
throw new UnsupportedOperationException();
}
return hostControllerInfoAccessor;
}
}
private class SubsystemInformationImpl implements SubsystemInformation {
private ModelVersion version;
private final List<String> parsingNamespaces = new ArrayList<String>();
@Override
public List<String> getXMLNamespaces() {
return Collections.unmodifiableList(parsingNamespaces);
}
void addParsingNamespace(final String namespace) {
parsingNamespaces.add(namespace);
}
@Override
public Integer getManagementInterfaceMajorVersion() {
return version != null ? version.getMajor() : null;
}
@Override
public Integer getManagementInterfaceMinorVersion() {
return version != null ? version.getMinor() : null;
}
@Override
public Integer getManagementInterfaceMicroVersion() {
return version != null ? version.getMicro() : null;
}
@Override
public ModelVersion getManagementInterfaceVersion() {
return version;
}
private void setVersion(ModelVersion version) {
this.version = version;
}
}
private class SubsystemRegistrationImpl implements SubsystemRegistration {
private final String name;
private final ModelVersion version;
private final ManagementResourceRegistration profileRegistration;
private final ManagementResourceRegistration deploymentsRegistration;
private final ExtensionRegistryType extensionRegistryType;
private final String extensionModuleName;
private volatile boolean hostCapable;
private volatile boolean modelsRegistered;
private SubsystemRegistrationImpl(String name, ModelVersion version,
ManagementResourceRegistration profileRegistration,
ManagementResourceRegistration deploymentsRegistration,
ExtensionRegistryType extensionRegistryType,
String extensionModuleName,
ProcessType processType) {
assert profileRegistration != null;
this.name = name;
this.profileRegistration = profileRegistration;
if (deploymentsRegistration == null){
this.deploymentsRegistration = ManagementResourceRegistration.Factory.forProcessType(processType).createRegistration(new SimpleResourceDefinition(null, NonResolvingResourceDescriptionResolver.INSTANCE));
}else {
this.deploymentsRegistration = deploymentsRegistration;
}
this.version = version;
this.extensionRegistryType = extensionRegistryType;
this.extensionModuleName = extensionModuleName;
}
@Override
public void setHostCapable() {
if (modelsRegistered) {
throw ControllerLogger.ROOT_LOGGER.registerHostCapableMustHappenFirst(name);
}
hostCapable = true;
}
@Override
public ManagementResourceRegistration registerSubsystemModel(ResourceDefinition resourceDefinition) {
assert resourceDefinition != null : "resourceDefinition is null";
checkHostCapable();
return profileRegistration.registerSubModel(resourceDefinition);
}
@Override
public ManagementResourceRegistration registerDeploymentModel(ResourceDefinition resourceDefinition) {
assert resourceDefinition != null : "resourceDefinition is null";
return deploymentsRegistration.registerSubModel(resourceDefinition);
}
@Override
public void registerXMLElementWriter(XMLElementWriter<SubsystemMarshallingContext> writer) {
writerRegistry.registerSubsystemWriter(name, writer);
}
@Override
public TransformersSubRegistration registerModelTransformers(final ModelVersionRange range, final ResourceTransformer subsystemTransformer) {
modelsRegistered = true;
checkHostCapable();
return transformerRegistry.registerSubsystemTransformers(name, range, subsystemTransformer);
}
@Override
public TransformersSubRegistration registerModelTransformers(ModelVersionRange version, ResourceTransformer resourceTransformer, OperationTransformer operationTransformer, boolean placeholder) {
modelsRegistered = true;
checkHostCapable();
return transformerRegistry.registerSubsystemTransformers(name, version, resourceTransformer, operationTransformer, placeholder);
}
@Override
@Deprecated
public TransformersSubRegistration registerModelTransformers(ModelVersionRange version, ResourceTransformer resourceTransformer, OperationTransformer operationTransformer) {
modelsRegistered = true;
checkHostCapable();
return transformerRegistry.registerSubsystemTransformers(name, version, resourceTransformer, operationTransformer, false);
}
@Override
public TransformersSubRegistration registerModelTransformers(ModelVersionRange version, CombinedTransformer combinedTransformer) {
modelsRegistered = true;
checkHostCapable();
return transformerRegistry.registerSubsystemTransformers(name, version, combinedTransformer, combinedTransformer, false);
}
@Override
public ModelVersion getSubsystemVersion() {
return version;
}
private void checkHostCapable() {
if (extensionRegistryType == ExtensionRegistryType.HOST && !hostCapable) {
throw ControllerLogger.ROOT_LOGGER.nonHostCapableSubsystemInHostModel(name, extensionModuleName);
}
}
}
private class ExtensionInfo {
private final Map<String, SubsystemInformation> subsystems = new HashMap<String, SubsystemInformation>();
private final String extensionModuleName;
private XMLMapper xmlMapper;
private ProfileParsingCompletionHandler parsingCompletionHandler;
public ExtensionInfo(String extensionModuleName) {
this.extensionModuleName = extensionModuleName;
}
private SubsystemInformationImpl getSubsystemInfo(final String subsystemName) {
checkNewSubystem(extensionModuleName, subsystemName);
synchronized (this) {
SubsystemInformationImpl subsystem = SubsystemInformationImpl.class.cast(subsystems.get(subsystemName));
if (subsystem == null) {
subsystem = new SubsystemInformationImpl();
subsystems.put(subsystemName, subsystem);
}
return subsystem;
}
}
}
private static class DeploymentManagementResourceRegistration implements ManagementResourceRegistration {
@Override
public boolean isOrderedChildResource() {
return false;
}
@Override
public Set<String> getOrderedChildTypes() {
return Collections.emptySet();
}
private final ManagementResourceRegistration deployments;
private final ManagementResourceRegistration subdeployments;
private DeploymentManagementResourceRegistration(final ManagementResourceRegistration deployments,
final ManagementResourceRegistration subdeployments) {
this.deployments = deployments;
this.subdeployments = subdeployments;
}
@Override
public PathAddress getPathAddress() {
return deployments.getPathAddress();
}
@Override
public ImmutableManagementResourceRegistration getParent() {
ManagementResourceRegistration deplParent = (ManagementResourceRegistration) deployments.getParent();
ManagementResourceRegistration subParent = (ManagementResourceRegistration) subdeployments.getParent();
if (deployments == subParent) {
return deplParent;
}
return new DeploymentManagementResourceRegistration(deplParent, subParent);
}
@Override
public int getMaxOccurs() {
return deployments.getMaxOccurs();
}
@Override
public int getMinOccurs() {
return deployments.getMinOccurs();
}
@Override
public boolean isRuntimeOnly() {
return deployments.isRuntimeOnly();
}
@Override
@SuppressWarnings("deprecation")
public void setRuntimeOnly(final boolean runtimeOnly) {
deployments.setRuntimeOnly(runtimeOnly);
subdeployments.setRuntimeOnly(runtimeOnly);
}
@Override
public boolean isRemote() {
return deployments.isRemote();
}
@Override
public OperationStepHandler getOperationHandler(PathAddress address, String operationName) {
return deployments.getOperationHandler(address, operationName);
}
@Override
public DescriptionProvider getOperationDescription(PathAddress address, String operationName) {
return deployments.getOperationDescription(address, operationName);
}
@Override
public Set<OperationEntry.Flag> getOperationFlags(PathAddress address, String operationName) {
return deployments.getOperationFlags(address, operationName);
}
@Override
public OperationEntry getOperationEntry(PathAddress address, String operationName) {
return deployments.getOperationEntry(address, operationName);
}
@Override
public Set<String> getAttributeNames(PathAddress address) {
return deployments.getAttributeNames(address);
}
@Override
public AttributeAccess getAttributeAccess(PathAddress address, String attributeName) {
return deployments.getAttributeAccess(address, attributeName);
}
@Override
public Map<String, NotificationEntry> getNotificationDescriptions(PathAddress address, boolean inherited) {
return deployments.getNotificationDescriptions(address, inherited);
}
@Override
public Set<String> getChildNames(PathAddress address) {
return deployments.getChildNames(address);
}
@Override
public Set<PathElement> getChildAddresses(PathAddress address) {
return deployments.getChildAddresses(address);
}
@Override
public DescriptionProvider getModelDescription(PathAddress address) {
return deployments.getModelDescription(address);
}
@Override
public Map<String, OperationEntry> getOperationDescriptions(PathAddress address, boolean inherited) {
return deployments.getOperationDescriptions(address, inherited);
}
@Override
public ProxyController getProxyController(PathAddress address) {
return deployments.getProxyController(address);
}
@Override
public Set<ProxyController> getProxyControllers(PathAddress address) {
return deployments.getProxyControllers(address);
}
@Override
public ManagementResourceRegistration getOverrideModel(String name) {
return deployments.getOverrideModel(name);
}
@Override
public ManagementResourceRegistration getSubModel(PathAddress address) {
return deployments.getSubModel(address);
}
@Override
public List<AccessConstraintDefinition> getAccessConstraints() {
return deployments.getAccessConstraints();
}
@Override
public ManagementResourceRegistration registerSubModel(ResourceDefinition resourceDefinition) {
ManagementResourceRegistration depl = deployments.registerSubModel(resourceDefinition);
ManagementResourceRegistration subdepl = subdeployments.registerSubModel(resourceDefinition);
return new DeploymentManagementResourceRegistration(depl, subdepl);
}
@Override
public void unregisterSubModel(PathElement address) {
deployments.unregisterSubModel(address);
subdeployments.unregisterSubModel(address);
}
@Override
public boolean isAllowsOverride() {
return deployments.isAllowsOverride();
}
@Override
public ManagementResourceRegistration registerOverrideModel(String name, OverrideDescriptionProvider descriptionProvider) {
ManagementResourceRegistration depl = deployments.registerOverrideModel(name, descriptionProvider);
ManagementResourceRegistration subdepl = subdeployments.registerOverrideModel(name, descriptionProvider);
return new DeploymentManagementResourceRegistration(depl, subdepl);
}
@Override
public void unregisterOverrideModel(String name) {
deployments.unregisterOverrideModel(name);
subdeployments.unregisterOverrideModel(name);
}
@Override
public void registerOperationHandler(OperationDefinition definition, OperationStepHandler handler) {
registerOperationHandler(definition, handler, false);
}
@Override
public void registerOperationHandler(OperationDefinition definition, OperationStepHandler handler, boolean inherited) {
deployments.registerOperationHandler(definition, handler, inherited);
subdeployments.registerOperationHandler(definition, handler, inherited);
}
@Override
public void unregisterOperationHandler(String operationName) {
deployments.unregisterOperationHandler(operationName);
subdeployments.unregisterOperationHandler(operationName);
}
@Override
public void registerReadWriteAttribute(AttributeDefinition definition, OperationStepHandler readHandler, OperationStepHandler writeHandler) {
deployments.registerReadWriteAttribute(definition, readHandler, writeHandler);
subdeployments.registerReadWriteAttribute(definition, readHandler, writeHandler);
}
@Override
public void registerReadOnlyAttribute(AttributeDefinition definition, OperationStepHandler readHandler) {
deployments.registerReadOnlyAttribute(definition, readHandler);
subdeployments.registerReadOnlyAttribute(definition, readHandler);
}
@Override
public void registerMetric(AttributeDefinition definition, OperationStepHandler metricHandler) {
deployments.registerMetric(definition, metricHandler);
subdeployments.registerMetric(definition, metricHandler);
}
@Override
public void unregisterAttribute(String attributeName) {
deployments.unregisterAttribute(attributeName);
subdeployments.unregisterAttribute(attributeName);
}
@Override
public void registerNotification(NotificationDefinition notification, boolean inherited) {
deployments.registerNotification(notification, inherited);
subdeployments.registerNotification(notification, inherited);
}
@Override
public void registerNotification(NotificationDefinition notification) {
deployments.registerNotification(notification);
subdeployments.registerNotification(notification);
}
@Override
public void unregisterNotification(String notificationType) {
deployments.unregisterNotification(notificationType);
subdeployments.unregisterNotification(notificationType);
}
@Override
public void registerProxyController(PathElement address, ProxyController proxyController) {
deployments.registerProxyController(address, proxyController);
subdeployments.registerProxyController(address, proxyController);
}
@Override
public void unregisterProxyController(PathElement address) {
deployments.unregisterProxyController(address);
subdeployments.unregisterProxyController(address);
}
@Override
public void registerAlias(PathElement address, AliasEntry alias) {
deployments.registerAlias(address, alias);
subdeployments.registerAlias(address, alias);
}
@Override
public void unregisterAlias(PathElement address) {
deployments.unregisterAlias(address);
subdeployments.unregisterAlias(address);
}
@Override
public void registerCapability(RuntimeCapability capability) {
deployments.registerCapability(capability);
subdeployments.registerCapability(capability);
}
@Override
public void registerIncorporatingCapabilities(Set<RuntimeCapability> capabilities) {
deployments.registerIncorporatingCapabilities(capabilities);
subdeployments.registerIncorporatingCapabilities(capabilities);
}
@Override
public AliasEntry getAliasEntry() {
return deployments.getAliasEntry();
}
@Override
public boolean isAlias() {
return deployments.isAlias();
}
@Override
public Set<RuntimeCapability> getCapabilities() {
return deployments.getCapabilities();
}
@Override
public Set<RuntimeCapability> getIncorporatingCapabilities() {
return deployments.getIncorporatingCapabilities();
}
}
private static final JmxAuthorizer NO_OP_AUTHORIZER = new JmxAuthorizer() {
@Override
public AuthorizationResult authorize(Caller caller, Environment callEnvironment, Action action, TargetResource target) {
return AuthorizationResult.PERMITTED;
}
@Override
public AuthorizerDescription getDescription() {
return new AuthorizerDescription() {
@Override
public boolean isRoleBased() {
return false;
}
@Override
public Set<String> getStandardRoles() {
return Collections.emptySet();
}
};
}
@Override
public AuthorizationResult authorize(Caller caller, Environment callEnvironment, Action action, TargetAttribute target) {
return AuthorizationResult.PERMITTED;
}
@Override
public AuthorizationResult authorizeJmxOperation(Caller caller, Environment callEnvironment, JmxAction action, JmxTarget target) {
return AuthorizationResult.PERMITTED;
}
@Override
public Set<String> getCallerRoles(Caller caller, Environment callEnvironment, Set<String> runAsRoles) {
return null;
}
@Override
public void setNonFacadeMBeansSensitive(boolean sensitive) {
}
@Override
public boolean isNonFacadeMBeansSensitive() {
return false;
}
};
}