/jboss-as-7.1.1.Final/controller/src/main/java/org/jboss/as/controller/ProxyStepHandler.java
Java | 197 lines | 133 code | 31 blank | 33 comment | 22 complexity | 0903ea4f1663decf482009673c533e47 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 */
22
23package org.jboss.as.controller;
24
25import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILURE_DESCRIPTION;
26import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
27import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
28import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT;
29import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER_GROUPS;
30
31import java.io.IOException;
32import java.io.InputStream;
33import java.util.ArrayList;
34import java.util.List;
35import java.util.concurrent.atomic.AtomicReference;
36
37import org.jboss.as.controller.client.MessageSeverity;
38import org.jboss.as.controller.client.OperationAttachments;
39import org.jboss.as.controller.client.OperationMessageHandler;
40import org.jboss.dmr.ModelNode;
41
42/**
43 * Step handler that uses a proxied {@link ModelController} to execute the step.
44 *
45 * @author Brian Stansberry (c) 2011 Red Hat Inc.
46 */
47public class ProxyStepHandler implements OperationStepHandler {
48
49 private final ProxyController proxyController;
50
51 public ProxyStepHandler(final ProxyController proxyController) {
52 this.proxyController = proxyController;
53 }
54
55 @Override
56 public void execute(OperationContext context, ModelNode operation) {
57 OperationMessageHandler messageHandler = new DelegatingMessageHandler(context);
58
59 final AtomicReference<ModelController.OperationTransaction> txRef = new AtomicReference<ModelController.OperationTransaction>();
60 final AtomicReference<ModelNode> preparedResultRef = new AtomicReference<ModelNode>();
61 final AtomicReference<ModelNode> finalResultRef = new AtomicReference<ModelNode>();
62 final ProxyController.ProxyOperationControl proxyControl = new ProxyController.ProxyOperationControl() {
63
64 @Override
65 public void operationPrepared(ModelController.OperationTransaction transaction, ModelNode result) {
66 txRef.set(transaction);
67 preparedResultRef.set(result);
68 }
69
70 @Override
71 public void operationFailed(ModelNode response) {
72 finalResultRef.set(response);
73 }
74
75 @Override
76 public void operationCompleted(ModelNode response) {
77 finalResultRef.set(response);
78 }
79 };
80
81 proxyController.execute(operation, messageHandler, proxyControl, new DelegatingOperationAttachments(context));
82 ModelNode finalResult = finalResultRef.get();
83 if (finalResult != null) {
84 // operation failed before it could commit
85 context.getResult().set(finalResult.get(RESULT));
86 context.getFailureDescription().set(finalResult.get(FAILURE_DESCRIPTION));
87 context.completeStep();
88 } else {
89
90 completeRemoteTransaction(context, operation, txRef, preparedResultRef, finalResultRef);
91
92 }
93 }
94
95 private void completeRemoteTransaction(OperationContext context, ModelNode operation, AtomicReference<ModelController.OperationTransaction> txRef, AtomicReference<ModelNode> preparedResultRef, AtomicReference<ModelNode> finalResultRef) {
96
97 boolean txCompleted = false;
98 try {
99
100 ModelNode preparedResponse = preparedResultRef.get();
101 ModelNode preparedResult = preparedResponse.get(RESULT);
102 if (preparedResponse.hasDefined(FAILURE_DESCRIPTION)) {
103 context.getFailureDescription().set(preparedResponse.get(FAILURE_DESCRIPTION));
104 if (preparedResult.isDefined()) {
105 context.getResult().set(preparedResult);
106 }
107 }
108 else {
109 context.getResult().set(preparedResult);
110 }
111
112 OperationContext.ResultAction resultAction = context.completeStep();
113 ModelController.OperationTransaction tx = txRef.get();
114 try {
115 if (resultAction == OperationContext.ResultAction.KEEP) {
116 tx.commit();
117 } else {
118 tx.rollback();
119 }
120 } finally {
121 txCompleted = true;
122 }
123
124 // Get the final result from the proxy and use it to update our response.
125 // Per the ProxyOperationControl contract, this will have been provided via operationCompleted
126 // by the time the call to OperationTransaction.commit/rollback returns
127
128 ModelNode finalResponse = finalResultRef.get();
129 if (finalResponse != null) {
130 ModelNode finalResult = finalResponse.get(RESULT);
131 if (finalResponse.hasDefined(FAILURE_DESCRIPTION)) {
132 context.getFailureDescription().set(finalResponse.get(FAILURE_DESCRIPTION));
133 if (finalResult.isDefined()) {
134 context.getResult().set(finalResult);
135 }
136 } else {
137 context.getResult().set(finalResult);
138 }
139 if (context.getProcessType() == ProcessType.HOST_CONTROLLER && finalResponse.has(SERVER_GROUPS)) {
140 context.getServerResults().set(finalResponse.get(SERVER_GROUPS));
141 }
142 } else {
143 // This is an error condition
144 ControllerLogger.SERVER_MANAGEMENT_LOGGER.noFinalProxyOutcomeReceived(operation.get(OP),
145 operation.get(OP_ADDR), proxyController.getProxyNodeAddress().toModelNode());
146 }
147 } finally {
148 // Ensure the remote side gets a transaction outcome if we can't commit/rollback above
149 if (!txCompleted && txRef.get() != null) {
150 txRef.get().rollback();
151 }
152 }
153 }
154
155
156 private static class DelegatingMessageHandler implements OperationMessageHandler {
157
158 private final OperationContext context;
159
160 DelegatingMessageHandler(final OperationContext context) {
161 this.context = context;
162 }
163
164 @Override
165 public void handleReport(MessageSeverity severity, String message) {
166 context.report(severity, message);
167 }
168 }
169
170 private static class DelegatingOperationAttachments implements OperationAttachments {
171
172 private final OperationContext context;
173 private DelegatingOperationAttachments(final OperationContext context) {
174 this.context = context;
175 }
176
177 @Override
178 public boolean isAutoCloseStreams() {
179 return false;
180 }
181
182 @Override
183 public List<InputStream> getInputStreams() {
184 int count = context.getAttachmentStreamCount();
185 List<InputStream> result = new ArrayList<InputStream>(count);
186 for (int i = 0; i < count; i++) {
187 result.add(context.getAttachmentStream(i));
188 }
189 return result;
190 }
191
192 @Override
193 public void close() throws IOException {
194 //
195 }
196 }
197}