PageRenderTime 44ms CodeModel.GetById 31ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/jboss-as-7.1.1.Final/controller/src/main/java/org/jboss/as/controller/RestartParentResourceHandlerBase.java

#
Java | 205 lines | 100 code | 24 blank | 81 comment | 20 complexity | 8ba39cae1babf3d3dc249ff61d93c411 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
  1/*
  2 * JBoss, Home of Professional Open Source.
  3 * Copyright 2011, 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 */
 22package org.jboss.as.controller;
 23
 24import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
 25
 26import java.util.NoSuchElementException;
 27
 28import org.jboss.as.controller.operations.common.Util;
 29import org.jboss.as.controller.registry.Resource;
 30import org.jboss.dmr.ModelNode;
 31import org.jboss.msc.service.ServiceController;
 32import org.jboss.msc.service.ServiceName;
 33
 34/**
 35 * Simple remove handler that, if allowed, restarts a parent resource when a child is removed.
 36 * Otherwise the server is put into a forced reload.
 37 *
 38 * @author Jason T. Greene
 39 */
 40public abstract class RestartParentResourceHandlerBase implements OperationStepHandler {
 41    private final String parentKeyName;
 42
 43    protected RestartParentResourceHandlerBase(String parentKeyName) {
 44        this.parentKeyName = parentKeyName;
 45    }
 46
 47    @Override
 48    public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
 49
 50        // Do the simple model part
 51        updateModel(context, operation);
 52
 53        if (!context.isBooting() && requiresRuntime(context)) {
 54            context.addStep(new OperationStepHandler() {
 55                @Override
 56                public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
 57
 58                    PathAddress address = getParentAddress(PathAddress.pathAddress(operation.require(OP_ADDR)));
 59                    ServiceName serviceName = getParentServiceName(address);
 60                    final ServiceController<?> service = serviceName != null ?
 61                            context.getServiceRegistry(false).getService(serviceName) : null;
 62
 63                    ModelNode parentModel = null;
 64                    boolean servicesRestarted = false;
 65                    final boolean reloadRequired = service != null && !isResourceServiceRestartAllowed(context, service);
 66                    if (reloadRequired) {
 67                        context.reloadRequired();
 68                    } else if (service != null ) {
 69                        parentModel = getModel(context, address);
 70                        if (parentModel != null && context.markResourceRestarted(address, this)) {
 71                            removeServices(context, serviceName, parentModel);
 72                            final ServiceVerificationHandler verificationHandler = new ServiceVerificationHandler();
 73                            recreateParentService(context, address, parentModel, verificationHandler);
 74                            context.addStep(verificationHandler, OperationContext.Stage.VERIFY);
 75                            servicesRestarted = true;
 76                        }
 77                    } // else  No parent service, nothing to do
 78
 79                    // If we restarted services, keep the model that drove the new services so we can
 80                    // revert the change on rollback
 81                    final ModelNode invalidatedParentModel = servicesRestarted ? parentModel : null;
 82
 83                    context.completeStep(new OperationContext.RollbackHandler() {
 84                        @Override
 85                        public void handleRollback(OperationContext context, ModelNode operation) {
 86                            if (reloadRequired) {
 87                                context.revertReloadRequired();
 88                            } else if (invalidatedParentModel != null) {
 89                                recoverServices(context, operation, invalidatedParentModel);
 90                            }
 91                        }
 92                    });
 93                }
 94            }, OperationContext.Stage.RUNTIME);
 95        }
 96        context.completeStep(OperationContext.RollbackHandler.NOOP_ROLLBACK_HANDLER);
 97    }
 98
 99    /**
100     * Gets whether this operation needs to update the runtime. The default implementation returns {@code true}
101     * if {@link OperationContext#getProcessType() the process type} is not {@link ProcessType#HOST_CONTROLLER}.
102     *
103     * @param context the operation context
104     * @return {@code true} if the operation should update the runtime; {@code false} if it only updates the configuration
105     *         model
106     */
107    protected boolean requiresRuntime(OperationContext context) {
108        return context.getProcessType() != ProcessType.HOST_CONTROLLER;
109    }
110
111    /**
112     * Gets whether a restart of the parent resource's services is allowed. This default implementation
113     * checks whether {@link OperationContext#isResourceServiceRestartAllowed() the context allows resource service restarts};
114     * subclasses could also check the state of the {@code service}.
115     *
116     * @param context the operation context
117     * @param service the parent service
118     * @return {@code true} if a restart is allowed; {@code false}
119     */
120    protected boolean isResourceServiceRestartAllowed(final OperationContext context, final ServiceController<?> service) {
121        return context.isResourceServiceRestartAllowed();
122    }
123
124    /**
125     * Removes services. This default implementation simply
126     * {@link OperationContext#removeService(ServiceController) instructs the context to remove the parentService}.
127     * Subclasses could use the provided {@code parentModel} to identify and remove other services.
128     *
129     * @param context the operation context
130     * @param parentService the name of the parent service
131     * @param parentModel the model associated with the parent resource, including nodes for any child resources
132     *
133     * @throws OperationFailedException if there is a problem removing the services
134     */
135    protected void removeServices(final OperationContext context, final ServiceName parentService, final ModelNode parentModel) throws OperationFailedException {
136        context.removeService(parentService);
137    }
138
139    /**
140     * Performs the update to the persistent configuration model.
141     *
142     * @param context the operation context
143     * @param operation  the operation
144     * @throws OperationFailedException if there is a problem updating the model
145     */
146    protected abstract void updateModel(final OperationContext context, final ModelNode operation) throws OperationFailedException;
147
148    /**
149     * Recreate the parent service(s) using the given model.
150     *
151     * @param context the operation context
152     * @param parentAddress the address of the parent resource
153     * @param parentModel the current configuration model for the parent resource and its children
154     * @param verificationHandler handler for verifying newly installed services
155     *
156     * @throws OperationFailedException if there is a problem installing the services
157     */
158    protected abstract void recreateParentService(OperationContext context, PathAddress parentAddress, ModelNode parentModel, ServiceVerificationHandler verificationHandler) throws OperationFailedException;
159
160    /**
161     * Gets the name of the parent service.
162     *
163     * @param parentAddress the address of the parent resource
164     * @return  the service name
165     */
166    protected abstract ServiceName getParentServiceName(PathAddress parentAddress);
167
168
169    protected PathAddress getParentAddress(PathAddress address) {
170        return Util.getParentAddressByKey(address, parentKeyName);
171    }
172
173    private void recoverServices(final OperationContext context, final ModelNode operation, final ModelNode invalidatedParentModel) {
174        PathAddress address = getParentAddress(PathAddress.pathAddress(operation.require(OP_ADDR)));
175        ServiceName serviceName = getParentServiceName(address);
176
177        ModelNode parentModel = getOriginalModel(context, address);
178        if (parentModel != null && context.revertResourceRestarted(address, this)) {
179            try {
180                removeServices(context, serviceName, invalidatedParentModel);
181                recreateParentService(context, address, parentModel, null);
182            } catch (OperationFailedException e) {
183                throw ControllerMessages.MESSAGES.failedToRecoverServices(e);
184            }
185        }
186    }
187
188    private ModelNode getModel(OperationContext ctx, PathAddress address) {
189        try {
190            Resource resource = ctx.readResourceFromRoot(address);
191            return Resource.Tools.readModel(resource);
192        } catch (NoSuchElementException e) {
193            return null;
194        }
195    }
196
197    private ModelNode getOriginalModel(OperationContext ctx, PathAddress address) {
198        try {
199            Resource resource = ctx.getOriginalRootResource().navigate(address);
200            return Resource.Tools.readModel(resource);
201        } catch (NoSuchElementException e) {
202            return null;
203        }
204    }
205}