This repository has been archived by the owner on Jan 5, 2021. It is now read-only.
forked from wildfly/wildfly
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AbstractControllerService.java
392 lines (352 loc) · 19 KB
/
AbstractControllerService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
/*
* 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;
import static org.jboss.as.controller.ControllerLogger.ROOT_LOGGER;
import static org.jboss.as.controller.ControllerMessages.MESSAGES;
import java.util.List;
import java.util.concurrent.ExecutorService;
import org.jboss.as.controller.access.management.DelegatingConfigurableAuthorizer;
import org.jboss.as.controller.audit.AuditLogger;
import org.jboss.as.controller.audit.ManagedAuditLogger;
import org.jboss.as.controller.client.OperationAttachments;
import org.jboss.as.controller.client.OperationMessageHandler;
import org.jboss.as.controller.descriptions.DescriptionProvider;
import org.jboss.as.controller.persistence.ConfigurationPersistenceException;
import org.jboss.as.controller.persistence.ConfigurationPersister;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.as.controller.registry.Resource;
import org.jboss.dmr.ModelNode;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceContainer;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceTarget;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
import org.jboss.msc.value.InjectedValue;
import org.wildfly.security.manager.WildFlySecurityManager;
/**
* A base class for controller services.
*
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
*/
public abstract class AbstractControllerService implements Service<ModelController> {
/**
* Name of the system property to set to control the stack size for the thread used to process boot operations.
* The boot sequence can have a very deep stack, so if needed setting this property can be used to create a larger
* memory area for storing data on the stack.
*
* @see #DEFAULT_BOOT_STACK_SIZE
*/
public static final String BOOT_STACK_SIZE_PROPERTY = "jboss.boot.thread.stack.size";
/**
* The default stack size for the thread used to process boot operations.
*
* @see #BOOT_STACK_SIZE_PROPERTY
*/
public static final int DEFAULT_BOOT_STACK_SIZE = 2 * 1024 * 1024;
private static int getBootStackSize() {
String prop = WildFlySecurityManager.getPropertyPrivileged(BOOT_STACK_SIZE_PROPERTY, null);
if (prop == null) {
return DEFAULT_BOOT_STACK_SIZE;
} else {
int base = 1;
String multiple = prop;
int lastIdx = prop.length() - 1;
if (lastIdx > 0) {
char last = prop.charAt(lastIdx);
if ('k' == last || 'K' == last) {
multiple = prop.substring(0, lastIdx);
base = 1024;
} else if ('m' == last || 'M' == last) {
multiple = prop.substring(0, lastIdx);
base = 1024 * 1024;
}
}
try {
return Integer.parseInt(multiple) * base;
} catch (NumberFormatException e) {
ROOT_LOGGER.invalidSystemPropertyValue(prop, BOOT_STACK_SIZE_PROPERTY, DEFAULT_BOOT_STACK_SIZE);
return DEFAULT_BOOT_STACK_SIZE;
}
}
}
protected final ProcessType processType;
protected final DelegatingConfigurableAuthorizer authorizer;
private final RunningModeControl runningModeControl;
private final DescriptionProvider rootDescriptionProvider;
private final ResourceDefinition rootResourceDefinition;
private final ControlledProcessState processState;
private final OperationStepHandler prepareStep;
private final InjectedValue<ExecutorService> injectedExecutorService = new InjectedValue<ExecutorService>();
private final ExpressionResolver expressionResolver;
private volatile ModelControllerImpl controller;
private ConfigurationPersister configurationPersister;
private final ManagedAuditLogger auditLogger;
/**
* Construct a new instance.
*
* @param processType the type of process being controlled
* @param runningModeControl the controller of the process' running mode
* @param configurationPersister the configuration persister
* @param processState the controlled process state
* @param rootDescriptionProvider the root description provider
* @param prepareStep the prepare step to prepend to operation execution
* @param expressionResolver the expression resolver
* @param auditLogger the audit logger
*/
@Deprecated
protected AbstractControllerService(final ProcessType processType, final RunningModeControl runningModeControl,
final ConfigurationPersister configurationPersister,
final ControlledProcessState processState, final DescriptionProvider rootDescriptionProvider,
final OperationStepHandler prepareStep, final ExpressionResolver expressionResolver,
final ManagedAuditLogger auditLogger, DelegatingConfigurableAuthorizer authorizer) {
this(processType, runningModeControl, configurationPersister, processState, null, rootDescriptionProvider,
prepareStep, expressionResolver, auditLogger, authorizer);
}
/**
* Construct a new instance.
*
* @param processType the type of process being controlled
* @param runningModeControl the controller of the process' running mode
* @param configurationPersister the configuration persister
* @param processState the controlled process state
* @param rootResourceDefinition the root resource definition
* @param prepareStep the prepare step to prepend to operation execution
* @param expressionResolver the expression resolver
* @param auditLogger the audit logger
*/
protected AbstractControllerService(final ProcessType processType, final RunningModeControl runningModeControl,
final ConfigurationPersister configurationPersister,
final ControlledProcessState processState, final ResourceDefinition rootResourceDefinition,
final OperationStepHandler prepareStep, final ExpressionResolver expressionResolver,
final ManagedAuditLogger auditLogger, final DelegatingConfigurableAuthorizer authorizer) {
this(processType, runningModeControl, configurationPersister, processState, rootResourceDefinition, null,
prepareStep, expressionResolver, auditLogger, authorizer);
}
/**
* Construct a new instance.
* Simplified constructor for test case subclasses.
*
* @param processType the type of process being controlled
* @param runningModeControl the controller of the process' running mode
* @param configurationPersister the configuration persister
* @param processState the controlled process state
* @param rootDescriptionProvider the root description provider
* @param prepareStep the prepare step to prepend to operation execution
* @param expressionResolver the expression resolver
*
* @deprecated Here for backwards compatibility for ModelTestModelControllerService
*/
@Deprecated
protected AbstractControllerService(final ProcessType processType, final RunningModeControl runningModeControl,
final ConfigurationPersister configurationPersister,
final ControlledProcessState processState, final DescriptionProvider rootDescriptionProvider,
final OperationStepHandler prepareStep, final ExpressionResolver expressionResolver) {
this(processType, runningModeControl, configurationPersister, processState, null, rootDescriptionProvider,
prepareStep, expressionResolver, AuditLogger.NO_OP_LOGGER, new DelegatingConfigurableAuthorizer());
}
/**
* Construct a new instance.
*
* @param processType the type of process being controlled
* @param runningModeControl the controller of the process' running mode
* @param configurationPersister the configuration persister
* @param processState the controlled process state
* @param rootResourceDefinition the root resource definition
* @param prepareStep the prepare step to prepend to operation execution
* @param expressionResolver the expression resolver
*
* @deprecated Here for backwards compatibility for ModelTestModelControllerService
*/
protected AbstractControllerService(final ProcessType processType, final RunningModeControl runningModeControl,
final ConfigurationPersister configurationPersister,
final ControlledProcessState processState, final ResourceDefinition rootResourceDefinition,
final OperationStepHandler prepareStep, final ExpressionResolver expressionResolver) {
this(processType, runningModeControl, configurationPersister, processState, rootResourceDefinition, null,
prepareStep, expressionResolver, AuditLogger.NO_OP_LOGGER, new DelegatingConfigurableAuthorizer());
}
private AbstractControllerService(final ProcessType processType, final RunningModeControl runningModeControl,
final ConfigurationPersister configurationPersister, final ControlledProcessState processState,
final ResourceDefinition rootResourceDefinition, final DescriptionProvider rootDescriptionProvider,
final OperationStepHandler prepareStep, final ExpressionResolver expressionResolver, final ManagedAuditLogger auditLogger,
final DelegatingConfigurableAuthorizer authorizer) {
assert rootDescriptionProvider != null || rootResourceDefinition != null: rootDescriptionProvider == null ? "Null root description provider" : "Null root resource definition";
assert expressionResolver != null : "Null expressionResolver";
assert auditLogger != null : "Null auditLogger";
assert authorizer != null : "Null authorizer";
this.processType = processType;
this.runningModeControl = runningModeControl;
this.configurationPersister = configurationPersister;
this.rootDescriptionProvider = rootDescriptionProvider;
this.rootResourceDefinition = rootResourceDefinition;
this.processState = processState;
this.prepareStep = prepareStep;
this.expressionResolver = expressionResolver;
this.auditLogger = auditLogger;
this.authorizer = authorizer;
}
public void start(final StartContext context) throws StartException {
if (configurationPersister == null) {
throw MESSAGES.persisterNotInjected();
}
final ServiceController<?> serviceController = context.getController();
final ServiceContainer container = serviceController.getServiceContainer();
final ServiceTarget target = context.getChildTarget();
final ExecutorService executorService = injectedExecutorService.getOptionalValue();
ManagementResourceRegistration rootResourceRegistration = rootDescriptionProvider != null ? ManagementResourceRegistration.Factory.create(rootDescriptionProvider) : ManagementResourceRegistration.Factory.create(rootResourceDefinition);
final ModelControllerImpl controller = new ModelControllerImpl(container, target,
rootResourceRegistration,
new ContainerStateMonitor(container),
configurationPersister, processType, runningModeControl, prepareStep,
processState, executorService, expressionResolver, authorizer, auditLogger);
// Initialize the model
initModel(controller.getRootResource(), controller.getRootRegistration());
this.controller = controller;
final long bootStackSize = getBootStackSize();
final Thread bootThread = new Thread(null, new Runnable() {
public void run() {
try {
try {
boot(new BootContext() {
public ServiceTarget getServiceTarget() {
return target;
}
});
} finally {
processState.setRunning();
}
} catch (Throwable t) {
container.shutdown();
if (t instanceof StackOverflowError) {
ROOT_LOGGER.errorBootingContainer(t, bootStackSize, BOOT_STACK_SIZE_PROPERTY);
} else {
ROOT_LOGGER.errorBootingContainer(t);
}
} finally {
bootThreadDone();
}
}
}, "Controller Boot Thread", bootStackSize);
bootThread.start();
}
/**
* Boot the controller. Called during service start.
*
* @param context the boot context
* @throws ConfigurationPersistenceException
* if the configuration failed to be loaded
*/
protected void boot(final BootContext context) throws ConfigurationPersistenceException {
runPerformControllerInitialization(context);
boot(configurationPersister.load(), false);
finishBoot();
}
protected boolean boot(List<ModelNode> bootOperations, boolean rollbackOnRuntimeFailure) throws ConfigurationPersistenceException {
return controller.boot(bootOperations, OperationMessageHandler.logging, ModelController.OperationTransactionControl.COMMIT, rollbackOnRuntimeFailure);
}
protected ModelNode internalExecute(final ModelNode operation, final OperationMessageHandler handler, final ModelController.OperationTransactionControl control, final OperationAttachments attachments, final OperationStepHandler prepareStep) {
return controller.internalExecute(operation, handler, control, attachments, prepareStep, false);
}
protected ModelNode internalExecute(final ModelNode operation, final OperationMessageHandler handler, final ModelController.OperationTransactionControl control, final OperationAttachments attachments, final OperationStepHandler prepareStep, final boolean attemptLock) {
return controller.internalExecute(operation, handler, control, attachments, prepareStep, attemptLock);
}
/**
* @deprecated internal use only
*/
@Deprecated
protected ModelNode executeReadOnlyOperation(final ModelNode operation, final OperationMessageHandler handler, final ModelController.OperationTransactionControl control, final OperationAttachments attachments, final OperationStepHandler prepareStep, int lockPermit) {
return controller.executeReadOnlyOperation(operation, handler, control, attachments, prepareStep, lockPermit);
}
protected void finishBoot() throws ConfigurationPersistenceException {
controller.finishBoot();
configurationPersister.successfulBoot();
}
protected void bootThreadDone() {
}
public void stop(final StopContext context) {
controller = null;
context.asynchronous();
Runnable r = new Runnable() {
@Override
public void run() {
try {
stopAsynchronous(context);
} finally {
try {
authorizer.shutdown();
} finally {
context.complete();
}
}
}
};
ExecutorService executorService = injectedExecutorService.getOptionalValue();
if (executorService != null) {
injectedExecutorService.getValue().execute(r);
} else {
Thread executorShutdown = new Thread(r, getClass().getSimpleName() + " Shutdown Thread");
executorShutdown.start();
}
}
/**
* Hook for subclasses to perform work during the asynchronous task started by
* {@link #stop(org.jboss.msc.service.StopContext)}. This base method does nothing.
* <p><strong>Subclasses must not invoke {@link org.jboss.msc.service.StopContext#complete()}</strong></p>
* @param context the stop context
*/
protected void stopAsynchronous(StopContext context) {
// no-op
}
/**
* {@inheritDoc}
*
* @throws SecurityException if the caller does not have {@link ModelController#ACCESS_PERMISSION}
*/
public ModelController getValue() throws IllegalStateException, IllegalArgumentException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(ModelController.ACCESS_PERMISSION);
}
final ModelController controller = this.controller;
if (controller == null) {
throw new IllegalStateException();
}
return controller;
}
public InjectedValue<ExecutorService> getExecutorServiceInjector() {
return injectedExecutorService;
}
protected void setConfigurationPersister(final ConfigurationPersister persister) {
this.configurationPersister = persister;
}
protected void runPerformControllerInitialization(BootContext context) {
performControllerInitialization(context.getServiceTarget(), controller.getRootResource(), controller.getRootRegistration());
}
protected void performControllerInitialization(ServiceTarget target, Resource rootResource, ManagementResourceRegistration rootRegistration) {
//
}
protected abstract void initModel(Resource rootResource, ManagementResourceRegistration rootRegistration);
protected ManagedAuditLogger getAuditLogger() {
return auditLogger;
}
}