|
| 1 | +/* |
| 2 | + * JBoss, Home of Professional Open Source. |
| 3 | + * Copyright 2012, Red Hat, Inc., and individual contributors |
| 4 | + * as indicated by the @author tags. See the copyright.txt file in the |
| 5 | + * distribution for a full listing of individual contributors. |
| 6 | + * |
| 7 | + * This is free software; you can redistribute it and/or modify it |
| 8 | + * under the terms of the GNU Lesser General Public License as |
| 9 | + * published by the Free Software Foundation; either version 2.1 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This software is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 | + * Lesser General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Lesser General Public |
| 18 | + * License along with this software; if not, write to the Free |
| 19 | + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA |
| 20 | + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. |
| 21 | + */ |
| 22 | + |
| 23 | +package org.jboss.as.domain.controller.operations; |
| 24 | + |
| 25 | +import org.jboss.as.controller.Extension; |
| 26 | +import org.jboss.as.controller.OperationContext; |
| 27 | +import org.jboss.as.controller.OperationFailedException; |
| 28 | +import org.jboss.as.controller.OperationStepHandler; |
| 29 | +import org.jboss.as.controller.PathAddress; |
| 30 | +import org.jboss.as.controller.PathElement; |
| 31 | +import org.jboss.as.controller.ProxyController; |
| 32 | +import org.jboss.as.controller.descriptions.DescriptionProvider; |
| 33 | +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DOMAIN_MODEL; |
| 34 | +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.EXTENSION; |
| 35 | +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HOST; |
| 36 | +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP; |
| 37 | +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; |
| 38 | +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER; |
| 39 | +import org.jboss.as.controller.extension.ExtensionRegistry; |
| 40 | +import org.jboss.as.controller.extension.ExtensionResource; |
| 41 | +import org.jboss.as.controller.registry.Resource; |
| 42 | +import static org.jboss.as.domain.controller.DomainControllerLogger.ROOT_LOGGER; |
| 43 | +import org.jboss.as.domain.controller.DomainControllerMessages; |
| 44 | +import org.jboss.as.domain.controller.LocalHostControllerInfo; |
| 45 | +import org.jboss.as.domain.controller.ServerIdentity; |
| 46 | +import org.jboss.as.domain.controller.operations.coordination.DomainServerUtils; |
| 47 | +import org.jboss.as.host.controller.ignored.IgnoredDomainResourceRegistry; |
| 48 | +import org.jboss.as.server.operations.ServerRestartRequiredHandler; |
| 49 | +import org.jboss.dmr.ModelNode; |
| 50 | +import org.jboss.modules.Module; |
| 51 | +import org.jboss.modules.ModuleIdentifier; |
| 52 | +import org.jboss.modules.ModuleLoadException; |
| 53 | + |
| 54 | +import java.util.HashSet; |
| 55 | +import java.util.Locale; |
| 56 | +import java.util.Map; |
| 57 | +import java.util.Set; |
| 58 | + |
| 59 | +/** |
| 60 | + * Step handler responsible for adding the extensions as part of the host registration process. |
| 61 | + * |
| 62 | + * @author Emanuel Muckenhuber |
| 63 | + */ |
| 64 | +public class ApplyExtensionsHandler implements OperationStepHandler, DescriptionProvider { |
| 65 | + |
| 66 | + public static final String OPERATION_NAME = "resolve-subsystems"; |
| 67 | + private final Set<String> appliedExtensions = new HashSet<String>(); |
| 68 | + private final ExtensionRegistry extensionRegistry; |
| 69 | + private final LocalHostControllerInfo localHostInfo; |
| 70 | + private final IgnoredDomainResourceRegistry ignoredResourceRegistry; |
| 71 | + |
| 72 | + public ApplyExtensionsHandler(ExtensionRegistry extensionRegistry, LocalHostControllerInfo localHostInfo, final IgnoredDomainResourceRegistry ignoredResourceRegistry) { |
| 73 | + this.extensionRegistry = extensionRegistry; |
| 74 | + this.localHostInfo = localHostInfo; |
| 75 | + this.ignoredResourceRegistry = ignoredResourceRegistry; |
| 76 | + } |
| 77 | + |
| 78 | + @Override |
| 79 | + public void execute(OperationContext context, ModelNode operation) throws OperationFailedException { |
| 80 | + // We get the model as a list of resources descriptions |
| 81 | + final ModelNode domainModel = operation.get(DOMAIN_MODEL); |
| 82 | + final ModelNode startRoot = Resource.Tools.readModel(context.readResourceFromRoot(PathAddress.EMPTY_ADDRESS)); |
| 83 | + |
| 84 | + final Resource rootResource = context.readResourceForUpdate(PathAddress.EMPTY_ADDRESS); |
| 85 | + for(Resource.ResourceEntry entry : rootResource.getChildren(EXTENSION)) { |
| 86 | + rootResource.removeChild(entry.getPathElement()); |
| 87 | + } |
| 88 | + |
| 89 | + for (final ModelNode resourceDescription : domainModel.asList()) { |
| 90 | + final PathAddress resourceAddress = PathAddress.pathAddress(resourceDescription.require("domain-resource-address")); |
| 91 | + if (ignoredResourceRegistry.isResourceExcluded(resourceAddress)) { |
| 92 | + continue; |
| 93 | + } |
| 94 | + |
| 95 | + final Resource resource = getResource(resourceAddress, rootResource, context); |
| 96 | + if (resourceAddress.size() == 1 && resourceAddress.getElement(0).getKey().equals(EXTENSION)) { |
| 97 | + final String module = resourceAddress.getElement(0).getValue(); |
| 98 | + if (!appliedExtensions.contains(module)) { |
| 99 | + appliedExtensions.add(module); |
| 100 | + initializeExtension(module); |
| 101 | + } |
| 102 | + } else { |
| 103 | + continue; |
| 104 | + } |
| 105 | + resource.writeModel(resourceDescription.get("domain-resource-model")); |
| 106 | + } |
| 107 | + if (!context.isBooting()) { |
| 108 | + final Resource domainRootResource = context.readResourceForUpdate(PathAddress.EMPTY_ADDRESS); |
| 109 | + final ModelNode endRoot = Resource.Tools.readModel(domainRootResource); |
| 110 | + final Set<ServerIdentity> affectedServers = new HashSet<ServerIdentity>(); |
| 111 | + final ModelNode hostModel = endRoot.require(HOST).asPropertyList().iterator().next().getValue(); |
| 112 | + final Map<String, ProxyController> serverProxies = DomainServerUtils.getServerProxies(localHostInfo.getLocalHostName(), domainRootResource, context.getResourceRegistration()); |
| 113 | + |
| 114 | + final ModelNode startExtensions = startRoot.get(EXTENSION); |
| 115 | + final ModelNode finishExtensions = endRoot.get(EXTENSION); |
| 116 | + if (!startExtensions.equals(finishExtensions)) { |
| 117 | + // This affects all servers |
| 118 | + affectedServers.addAll(DomainServerUtils.getAllRunningServers(hostModel, localHostInfo.getLocalHostName(), serverProxies)); |
| 119 | + } |
| 120 | + |
| 121 | + if (!affectedServers.isEmpty()) { |
| 122 | + ROOT_LOGGER.domainModelChangedOnReConnect(affectedServers); |
| 123 | + final Set<ServerIdentity> runningServers = DomainServerUtils.getAllRunningServers(hostModel, localHostInfo.getLocalHostName(), serverProxies); |
| 124 | + for (ServerIdentity serverIdentity : affectedServers) { |
| 125 | + if(!runningServers.contains(serverIdentity)) { |
| 126 | + continue; |
| 127 | + } |
| 128 | + final PathAddress serverAddress = PathAddress.pathAddress(PathElement.pathElement(HOST, serverIdentity.getHostName()), PathElement.pathElement(SERVER, serverIdentity.getServerName())); |
| 129 | + final OperationStepHandler handler = context.getResourceRegistration().getOperationHandler(serverAddress, ServerRestartRequiredHandler.OPERATION_NAME); |
| 130 | + final ModelNode op = new ModelNode(); |
| 131 | + op.get(OP).set(ServerRestartRequiredHandler.OPERATION_NAME); |
| 132 | + op.get(OP_ADDR).set(serverAddress.toModelNode()); |
| 133 | + context.addStep(op, handler, OperationContext.Stage.IMMEDIATE); |
| 134 | + } |
| 135 | + } |
| 136 | + } |
| 137 | + |
| 138 | + context.completeStep(); |
| 139 | + } |
| 140 | + |
| 141 | + private Resource getResource(PathAddress resourceAddress, Resource rootResource, OperationContext context) { |
| 142 | + if(resourceAddress.size() == 0) { |
| 143 | + return rootResource; |
| 144 | + } |
| 145 | + Resource temp = rootResource; |
| 146 | + int idx = 0; |
| 147 | + for(PathElement element : resourceAddress) { |
| 148 | + temp = temp.getChild(element); |
| 149 | + if(temp == null) { |
| 150 | + if (idx == 0) { |
| 151 | + String type = element.getKey(); |
| 152 | + if (type.equals(EXTENSION)) { |
| 153 | + // Needs a specialized resource type |
| 154 | + temp = new ExtensionResource(element.getValue(), extensionRegistry); |
| 155 | + context.addResource(resourceAddress, temp); |
| 156 | + } |
| 157 | + } |
| 158 | + if (temp == null) { |
| 159 | + temp = context.createResource(resourceAddress); |
| 160 | + } |
| 161 | + break; |
| 162 | + } |
| 163 | + idx++; |
| 164 | + } |
| 165 | + return temp; |
| 166 | + } |
| 167 | + |
| 168 | + protected void initializeExtension(String module) throws OperationFailedException { |
| 169 | + try { |
| 170 | + for (final Extension extension : Module.loadServiceFromCallerModuleLoader(ModuleIdentifier.fromString(module), Extension.class)) { |
| 171 | + ClassLoader oldTccl = SecurityActions.setThreadContextClassLoader(extension.getClass()); |
| 172 | + try { |
| 173 | + extension.initializeParsers(extensionRegistry.getExtensionParsingContext(module, null)); |
| 174 | + extension.initialize(extensionRegistry.getExtensionContext(module)); |
| 175 | + } finally { |
| 176 | + SecurityActions.setThreadContextClassLoader(oldTccl); |
| 177 | + } |
| 178 | + } |
| 179 | + } catch (ModuleLoadException e) { |
| 180 | + throw DomainControllerMessages.MESSAGES.failedToLoadModule(e, module); |
| 181 | + } |
| 182 | + } |
| 183 | + |
| 184 | + @Override |
| 185 | + public ModelNode getModelDescription(Locale locale) { |
| 186 | + return new ModelNode(); // PRIVATE operation requires no description |
| 187 | + } |
| 188 | + |
| 189 | +} |
0 commit comments