-
Notifications
You must be signed in to change notification settings - Fork 460
/
OperationContext.java
1215 lines (1102 loc) · 58.2 KB
/
OperationContext.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
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* 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 java.io.InputStream;
import java.util.Set;
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.ResourceAuthorization;
import org.jboss.as.controller.capability.CapabilityServiceSupport;
import org.jboss.as.controller.capability.RuntimeCapability;
import org.jboss.as.controller.client.MessageSeverity;
import org.jboss.as.controller.notification.Notification;
import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.as.controller.registry.Resource;
import org.jboss.dmr.ModelNode;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.ServiceRegistry;
import org.jboss.msc.service.ServiceTarget;
/**
* The context for an operation step execution.
*
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
*/
public interface OperationContext extends ExpressionResolver {
/**
* Add an execution step to this operation process. Runtime operation steps are automatically added after
* configuration operation steps. Since only one operation may perform runtime work at a time, this method
* may block until other runtime operations have completed.
*
* @param step the step to add
* @param stage the stage at which the operation applies
* @throws IllegalArgumentException if the step handler is not valid for this controller type
*/
void addStep(OperationStepHandler step, Stage stage) throws IllegalArgumentException;
/**
* Add an execution step to this operation process. Runtime operation steps are automatically added after
* configuration operation steps. Since only one operation may perform runtime work at a time, this method
* may block until other runtime operations have completed.
*
* @param step the step to add
* @param stage the stage at which the operation applies
* @param addFirst add the handler before the others
* @throws IllegalArgumentException if the step handler is not valid for this controller type
*/
void addStep(OperationStepHandler step, Stage stage, boolean addFirst) throws IllegalArgumentException;
/**
* Add an execution step to this operation process, writing any output to the response object
* associated with the current step.
* Runtime operation steps are automatically added after configuration operation steps. Since only one operation
* may perform runtime work at a time, this method may block until other runtime operations have completed.
*
* @param operation the operation body to pass into the added step
* @param step the step to add
* @param stage the stage at which the operation applies
* @throws IllegalArgumentException if the step handler is not valid for this controller type
*/
void addStep(final ModelNode operation, final OperationStepHandler step, final Stage stage) throws IllegalArgumentException;
/**
* Add an execution step to this operation process, writing any output to the response object
* associated with the current step.
* Runtime operation steps are automatically added after configuration operation steps. Since only one operation
* may perform runtime work at a time, this method may block until other runtime operations have completed.
*
* @param operation the operation body to pass into the added step
* @param step the step to add
* @param stage the stage at which the operation applies
* @param addFirst add the handler before the others
* @throws IllegalArgumentException if the step handler is not valid for this controller type
*/
void addStep(final ModelNode operation, final OperationStepHandler step, final Stage stage, boolean addFirst) throws IllegalArgumentException;
/**
* Add an execution step to this operation process. Runtime operation steps are automatically added after
* configuration operation steps. Since only one operation may perform runtime work at a time, this method
* may block until other runtime operations have completed.
*
* @param response the response which the nested step should populate
* @param operation the operation body to pass into the added step
* @param step the step to add
* @param stage the stage at which the operation applies
* @throws IllegalArgumentException if the step handler is not valid for this controller type
*/
void addStep(ModelNode response, ModelNode operation, OperationStepHandler step, Stage stage) throws IllegalArgumentException;
/**
* Add an execution step to this operation process. Runtime operation steps are automatically added after
* configuration operation steps. Since only one operation may perform runtime work at a time, this method
* may block until other runtime operations have completed.
*
* @param response the response which the nested step should populate
* @param operation the operation body to pass into the added step
* @param step the step to add
* @param stage the stage at which the operation applies
* @param addFirst add the handler before the others
* @throws IllegalArgumentException if the step handler is not valid for this controller type
*/
void addStep(ModelNode response, ModelNode operation, OperationStepHandler step, Stage stage, boolean addFirst) throws IllegalArgumentException;
/**
* Get a stream which is attached to the request.
*
* @param index the index
* @return the input stream
*/
InputStream getAttachmentStream(int index);
/**
* Gets the number of streams attached to the request.
*
* @return the number of streams
*/
int getAttachmentStreamCount();
/**
* Get the node into which the operation result should be written.
*
* @return the result node
*/
ModelNode getResult();
/**
* Returns whether {@link #getResult()} has been invoked.
*
* @return {@code true} if {@link #getResult()} has been invoked
*/
boolean hasResult();
/**
* Attach a stream to be included as part of the response. The return value of this method should be
* used as the value of the {@link #getResult() result} for the step that invokes this method. Callers
* can then use that value to find the stream in the
* {@link org.jboss.as.controller.client.OperationResponse response} to this operation.
*
* @param mimeType the mime type of the stream. Cannot be {@code null}
* @param stream the stream. Cannot be {@code null}
* @return a uuid for the stream. Will not be {@code null}
*
* @throws IllegalStateException if {@link #isBooting()} returns {@code true}.
*/
String attachResultStream(String mimeType, InputStream stream);
/**
* Attach a stream to be included as part of the response, with a predetermined UUID.
* <p>
* This method is intended for use by core handlers related to managed domain operation
* as they propagate a stream throughout a domain. Ordinary handlers should use
* {@link #attachResultStream(String, java.io.InputStream)}.
*
* @param mimeType the mime type of the stream. Cannot be {@code null}
* @param stream the stream. Cannot be {@code null}
*
* @throws IllegalStateException if {@link #isBooting()} returns {@code true}.
*/
void attachResultStream(String uuid, String mimeType, InputStream stream);
/**
* Get the failure description response node, creating it if necessary.
*
* @return the failure description
*/
ModelNode getFailureDescription();
/**
* Returns whether {@link #getFailureDescription()} has been invoked.
*
* @return {@code true} if {@link #getFailureDescription()} has been invoked
*/
boolean hasFailureDescription();
/**
* Get the node into which the details of server results in a multi-server managed domain operation should be written.
*
* @return the server results node
*
* @throws IllegalStateException if this process is not a {@link ProcessType#HOST_CONTROLLER}
*/
ModelNode getServerResults();
/**
* Get the response-headers response node, creating it if necessary. Ordinary operation step handlers should not
* use this API for manipulating the {@code operation-requires-restart} or {@code process-state} headers. Use
* {@link #reloadRequired()} and {@link #restartRequired()} for that. (Some core operation step handlers used
* for coordinating execution of operations across different processes in a managed domain may use this
* method to manipulate the {@code operation-requires-restart} or {@code process-state} headers, but that is
* an exception.)
*
* @return the response-headers node
*/
ModelNode getResponseHeaders();
/**
* Complete a step, while registering for
* {@link RollbackHandler#handleRollback(OperationContext, ModelNode) a notification} if the work done by the
* caller needs to be rolled back}.
*
* @param rollbackHandler the handler for any rollback notification. Cannot be {@code null}.
*/
void completeStep(RollbackHandler rollbackHandler);
/**
* Complete a step, while registering for
* {@link ResultHandler#handleResult(ResultAction, OperationContext, ModelNode) a notification} when the overall
* result of the operation is known. Handlers that register for notifications will receive the notifications in
* the reverse of the order in which their steps execute.
*
* @param resultHandler the handler for the result notification. Cannot be {@code null}.
*/
void completeStep(ResultHandler resultHandler);
/**
* Called by an {@link OperationStepHandler} to indicate it has completed its handling of a step and is
* uninterested in the result of subsequent steps. This is a convenience method that is equivalent to a call to
* {@link #completeStep(ResultHandler) completeStep(OperationContext.ResultHandler.NO_OP_RESULT_HANDLER)}.
* <p>
* A common user of this method would be a {@link Stage#MODEL} handler. Typically such a handler would not need
* to take any further action in the case of a {@link ResultAction#KEEP successful result} for the overall operation.
* If the operation result is a {@link ResultAction#ROLLBACK rollback}, the {@code OperationContext} itself
* will ensure any changes made to the model are discarded, again requiring no action on the part of the handler.
* So a {@link Stage#MODEL} handler typically can be uninterested in the result of the overall operation and can
* use this method.
* </p>
*
* @deprecated invoking this method is unnecessary since if an {@code OperationStepHandler} does not call one of
* the {@link #completeStep(org.jboss.as.controller.OperationContext.ResultHandler) variants} from its
* {@code execute} method, a no-op {@code ResultHandler} will automatically be registered
*/
@Deprecated
void stepCompleted();
/**
* Get the type of process in which this operation is executing.
*
* @return the process type. Will not be {@code null}
*/
ProcessType getProcessType();
/**
* Gets the running mode of the process.
*
* @return the running mode. Will not be {@code null}
*/
RunningMode getRunningMode();
/**
* Determine whether the controller is currently performing boot tasks.
*
* @return whether the controller is currently booting
*/
boolean isBooting();
/**
* Convenience method to check if the {@link #getProcessType() process type} is {@link ProcessType#isServer() a server type}
* and the {@link #getRunningMode() running mode} is {@link RunningMode#NORMAL}. The typical usage would
* be for handlers that are only meant to execute on a normally running server, not on a host controller
* or on a {@link RunningMode#ADMIN_ONLY} server.
*
* @return {@code true} if the {@link #getProcessType() process type} is {@link ProcessType#isServer() a server type}
* and the {@link #getRunningMode() running mode} is {@link RunningMode#NORMAL}.
*/
boolean isNormalServer();
/**
* Determine whether the current operation is bound to be rolled back.
*
* @return {@code true} if the operation will be rolled back
*/
boolean isRollbackOnly();
/**
* Indicate that the operation should be rolled back, regardless of outcome.
*/
void setRollbackOnly();
/**
* Gets whether any changes made by the operation should be rolled back if an error is introduced
* by a {@link Stage#RUNTIME} or {@link Stage#VERIFY} handler.
*
* @return {@code true} if the operation should rollback if there is a runtime stage failure
*/
boolean isRollbackOnRuntimeFailure();
/**
* Gets whether {@link Stage#RUNTIME} handlers can restart (or remove) runtime services in order to
* make the operation take effect. If {@code false} and the operation cannot be effected without restarting
* or removing services, the handler should invoke {@link #reloadRequired()} or {@link #restartRequired()}.
*
* @return {@code true} if a service restart or removal is allowed
*/
boolean isResourceServiceRestartAllowed();
/**
* Notify the context that the process requires a stop and re-start of its root service (but not a full process
* restart) in order to ensure stable operation and/or to bring its running state in line with its persistent configuration.
*
* @see ControlledProcessState.State#RELOAD_REQUIRED
*/
void reloadRequired();
/**
* Notify the context that the process must be terminated and replaced with a new process in order to ensure stable
* operation and/or to bring the running state in line with the persistent configuration.
*
* @see ControlledProcessState.State#RESTART_REQUIRED
*/
void restartRequired();
/**
* Notify the context that a previous call to {@link #reloadRequired()} can be ignored (typically because the change
* that led to the need for reload has been rolled back.)
*/
void revertReloadRequired();
/**
* Notify the context that a previous call to {@link #restartRequired()} can be ignored (typically because the change
* that led to the need for restart has been rolled back.)
*/
void revertRestartRequired();
/**
* Notify the context that an update to the runtime that would normally have been made could not be made due to
* the current state of the process. As an example, a step handler that can only update the runtime when
* {@link #isBooting()} is {@code true} must invoke this method if it is executed when {@link #isBooting()}
* is {@code false}.
*/
void runtimeUpdateSkipped();
/**
* Gets the address associated with the currently executing step.
* @return the address. Will not be {@code null}
*/
PathAddress getCurrentAddress();
/**
* Gets the {@link PathElement#getValue() value} of the {@link #getCurrentAddress() current address'}
* {@link PathAddress#getLastElement() last element}.
*
* @return the last element value
*
* @throws java.lang.IllegalStateException if {@link #getCurrentAddress()} is the empty address
*/
String getCurrentAddressValue();
/**
* Get a read only view of the managed resource registration. The registration is relative to the operation address.
*
* @return the model node registration
*/
ImmutableManagementResourceRegistration getResourceRegistration();
/**
* Get a mutable view of the managed resource registration. The registration is relative to the operation address.
*
* @return the model node registration
*/
ManagementResourceRegistration getResourceRegistrationForUpdate();
/**
* Get a read only view of the root managed resource registration.
*
* @return the root resource registration
*/
ImmutableManagementResourceRegistration getRootResourceRegistration();
/**
* Get the service registry. If the step is not a runtime operation handler step, an exception will be thrown. The
* returned registry must not be used to remove services, if an attempt is made to call {@code ServiceController.setMode(REMOVE)}
* on a {@code ServiceController} returned from this registry an {@code IllegalStateException} will be thrown. To
* remove a service call {@link #removeService(org.jboss.msc.service.ServiceName)}.
*
* @param modify {@code true} if the operation may be modifying a service, {@code false} otherwise
* @return the service registry
* @throws UnsupportedOperationException if the calling step is not a runtime operation step
*/
ServiceRegistry getServiceRegistry(boolean modify) throws UnsupportedOperationException;
/**
* Initiate a service removal. If the step is not a runtime operation handler step, an exception will be thrown. Any
* subsequent step which attempts to add a service with the same name will block until the service removal completes.
* The returned controller may be used to attempt to cancel a removal in progress.
*
* @param name the service to remove
* @return the controller of the service to be removed if service of given name exists; null otherwise
* @throws UnsupportedOperationException if the calling step is not a runtime operation step
*/
ServiceController<?> removeService(ServiceName name) throws UnsupportedOperationException;
/**
* Initiate a service removal. If the step is not a runtime operation handler step, an exception will be thrown. Any
* subsequent step which attempts to add a service with the same name will block until the service removal completes.
*
* @param controller the service controller to remove
* @throws UnsupportedOperationException if the calling step is not a runtime operation step
*/
void removeService(ServiceController<?> controller) throws UnsupportedOperationException;
/**
* Get the service target. If the step is not a runtime operation handler step, an exception will be thrown. The
* returned service target is limited such that only the service add methods are supported. If a service added
* to this target was removed by a prior operation step, the install will wait until the removal completes.
*
* @return the service target
* @throws UnsupportedOperationException if the calling step is not a runtime operation step
*/
ServiceTarget getServiceTarget() throws UnsupportedOperationException;
/**
* Acquire the controlling {@link ModelController}'s exclusive lock. Holding this lock prevent other operations
* from mutating the model, the {@link ManagementResourceRegistration management resource registry} or the runtime
* service registry until the lock is released. The lock is automatically released when the
* {@link OperationStepHandler#execute(OperationContext, org.jboss.dmr.ModelNode) execute method} of the handler
* that invoked this method returns.
* <p>
* This method should be little used. The model controller's exclusive lock is acquired automatically when any
* of the operations in this interface that imply mutating the model, management resource registry or service
* registry are invoked. The only use for this method are special situations where an exclusive lock is needed
* but none of those methods will be invoked.
* </p>
*/
void acquireControllerLock();
/**
* Create a new resource, relative to the executed operation address. Since only one operation
* may write at a time, this operation may block until other writing operations have completed.
*
* @param address the (possibly empty) address where the resource should be created. Address is relative to the
* address of the operation being executed
* @return the created resource
* @throws IllegalStateException if a resource already exists at the given address
* @throws UnsupportedOperationException if the calling operation is not a model operation
*/
Resource createResource(PathAddress address) throws UnsupportedOperationException;
/**
* Add a new resource, at the executed operation address. Since only one operation
* may write at a time, this operation may block until other writing operations have completed.
*
* @param address the (possibly empty) address where the resource should be added. Address is relative to the
* address of the operation being executed
* @param toAdd the new resource
* @throws IllegalStateException if a resource already exists at the given address, or if the resource does not support ordered childred
* @throws UnsupportedOperationException if the calling operation is not a model operation
*/
void addResource(PathAddress address, Resource toAdd);
/**
* Add a new resource, at to the executed operation address. Since only one operation
* may write at a time, this operation may block until other writing operations have completed.
*
* @param address the (possibly empty) address where the resource should be added. Address is relative to the
* address of the operation being executed
* @param index the index of the resource to be created in the parent resources children of this type
* @param toAdd the new resource
* @throws IllegalStateException if a resource already exists at the given address
* @throws UnsupportedOperationException if the calling operation is not a model operation
*/
void addResource(PathAddress address, int index, Resource toAdd);
/**
* Get the resource for read only operations, relative to the executed operation address. Reads never block.
* If a write action was previously performed, the value read will be from an uncommitted copy of the the management model.<br/>
*
* Note: By default the returned resource is read-only copy of the entire sub-model. In case this is not required use
* {@link OperationContext#readResource(PathAddress, boolean)} instead.
*
* @param relativeAddress the (possibly empty) address where the resource should be added. The address is relative to the
* address of the operation being executed
* @return the resource
*/
Resource readResource(PathAddress relativeAddress);
/**
* Get the resource for read only operations, relative to the executed operation address. Reads never block.
* If a write action was previously performed, the value read will be from an uncommitted copy of the the management model.
*
* @param relativeAddress the (possibly empty) address where the resource should be added. The address is relative to the
* address of the operation being executed
* @param recursive whether the model should be read recursively or not
* @return the resource
*/
Resource readResource(PathAddress relativeAddress, boolean recursive);
/**
* Read an addressable resource from the root of the model. Reads never block. If a write action was previously performed,
* the value read will be from an uncommitted copy of the the management model.
* <p>
* Note: By default the returned resource is read-only copy of the entire sub-model. In case the entire sub-model
* is not required use {@link OperationContext#readResourceFromRoot(PathAddress, boolean)} instead.
*
* @param address the (possibly empty) address
* @return a read-only reference from the model
*/
Resource readResourceFromRoot(PathAddress address);
/**
* Read an addressable resource from the root of the model. Reads never block. If a write action was previously performed,
* the value read will be from an uncommitted copy of the the management model.
* <p>
* Use the {@code recursive} parameter to avoid the expense of making read-only copies of large portions of the
* resource tree. If {@code recursive} is {@code false}, the returned resource will only have placeholder resources
* for immediate children. Those placeholder resources will return an empty
* {@link org.jboss.as.controller.registry.Resource#getModel() model} and will not themselves have any children.
* Their presence, however, allows the caller to see what immediate children exist under the target resource.
*
* @param address the (possibly empty) address
* @param recursive whether the model should be read recursively or not
* @return a read-only reference from the model
*/
Resource readResourceFromRoot(PathAddress address, boolean recursive);
/**
* Get an addressable resource for update operations. Since only one operation may write at a time, this operation
* may block until other writing operations have completed.
*
* @param relativeAddress the (possibly empty) address where the resource should be added. The address is relative to the
* address of the operation being executed
* @return the resource
*/
Resource readResourceForUpdate(PathAddress relativeAddress);
/**
* Remove a resource relative to the executed operation address. Since only one operation
* may write at a time, this operation may block until other writing operations have completed.
*
* @param relativeAddress the (possibly empty) address where the resource should be removed. The address is relative to the
* address of the operation being executed
* @return the old value of the node
* @throws UnsupportedOperationException if the calling operation is not a model operation
*/
Resource removeResource(PathAddress relativeAddress) throws UnsupportedOperationException;
/**
* Get a read-only reference of the entire management model BEFORE any changes were made by this context.
* The structure of the returned model may depend on the context type (domain vs. server).
*
* @return the read-only original resource
*/
Resource getOriginalRootResource();
/**
* Determine whether the model has thus far been affected by this operation.
*
* @return {@code true} if the model was affected, {@code false} otherwise
*/
boolean isModelAffected();
/**
* Determine whether the {@link ManagementResourceRegistration management resource registry} has thus far been affected by this operation.
*
* @return {@code true} if the management resource registry was affected, {@code false} otherwise
*/
boolean isResourceRegistryAffected();
/**
* Determine whether the runtime container has thus far been affected by this operation.
*
* @return {@code true} if the container was affected, {@code false} otherwise
*/
boolean isRuntimeAffected();
/**
* Get the current stage of execution.
*
* @return the current stage
*/
Stage getCurrentStage();
/**
* Send a message to the client. Valid only during this operation.
*
* @param severity the message severity
* @param message the message
*/
void report(MessageSeverity severity, String message);
/**
* Marks a resource to indicate that it's backing service(s) will be restarted.
* This is to ensure that a restart only occurs once, even if there are multiple updates.
* When true is returned the caller has "acquired" the mark and should proceed with the
* restart, when false, the caller should take no additional action.
*
* The passed owner is compared by instance when a call to {@link #revertReloadRequired()}.
* This is to ensure that only the "owner" will be successful in reverting the mark.
*
* @param resource the resource that will be restarted
* @param owner the instance representing ownership of the mark
* @return true if the mark was required and the service should be restarted,
* false if no action should be taken.
*/
boolean markResourceRestarted(PathAddress resource, Object owner);
/**
* Removes the restarted marking on the specified resource, provided the passed owner is the one
* originally used to obtain the mark. The purpose of this method is to facilitate rollback processing.
* Only the "owner" of the mark should be the one to revert the service to a previous state (once again
* restarting it).When true is returned, the caller must take the required corrective
* action by restarting the resource, when false is returned the caller should take no additional action.
*
* The passed owner is compared by instance to the one provided in {@link #markResourceRestarted(PathAddress, Object)}
*
* @param resource the resource being reverted
* @param owner the owner of the mark for the resource
* @return true if the caller owns the mark and the service should be restored by restarting
* false if no action should be taken.
*/
boolean revertResourceRestarted(PathAddress resource, Object owner);
/**
* Resolves any expressions in the passed in ModelNode.
* Expressions may either represent system properties or vaulted date. For vaulted data the format is
* ${VAULT::vault_block::attribute_name::sharedKey}
*
* @param node the ModelNode containing expressions.
* @return a copy of the node with expressions resolved
*
* @throws OperationFailedException if there is a value of type {@link org.jboss.dmr.ModelType#EXPRESSION} in the node tree and
* there is no system property or environment variable that matches the expression, or if a security
* manager exists and its {@link SecurityManager#checkPermission checkPermission} method doesn't allow
* access to the relevant system property or environment variable
*/
ModelNode resolveExpressions(ModelNode node) throws OperationFailedException;
/**
* Retrieves an object that has been attached to this context.
*
* @param key the key to the attachment.
* @param <T> the value type of the attachment.
*
* @return the attachment if found otherwise {@code null}.
*/
<T> T getAttachment(AttachmentKey<T> key);
/**
* Attaches an arbitrary object to this context.
*
* @param key they attachment key used to ensure uniqueness and used for retrieval of the value.
* @param value the value to store.
* @param <T> the value type of the attachment.
*
* @return the previous value associated with the key or {@code null} if there was no previous value.
*/
<T> T attach(AttachmentKey<T> key, T value);
/**
* Attaches an arbitrary object to this context only if the object was not already attached. If a value has already
* been attached with the key provided, the current value associated with the key is returned.
*
* @param key they attachment key used to ensure uniqueness and used for retrieval of the value.
* @param value the value to store.
* @param <T> the value type of the attachment.
*
* @return the previous value associated with the key or {@code null} if there was no previous value.
*/
<T> T attachIfAbsent(AttachmentKey<T> key, T value);
/**
* Detaches or removes the value from this context.
*
* @param key the key to the attachment.
* @param <T> the value type of the attachment.
*
* @return the attachment if found otherwise {@code null}.
*/
<T> T detach(AttachmentKey<T> key);
/**
* Check for authorization of the given operation.
* @param operation the operation. Cannot be {@code null}
* @return the authorization result
*/
AuthorizationResult authorize(ModelNode operation);
/**
* Check for authorization of the given effects for the given operation.
* @param operation the operation. Cannot be {@code null}
* @param effects the relevant effects. If empty, all effects associated with the operation are tested.
* @return the authorization result
*/
AuthorizationResult authorize(ModelNode operation, Set<Action.ActionEffect> effects);
/**
* Check for authorization for the resource associated with the currently executing operation step and,
* optionally, its individual attributes
* @param attributes {@code true} if the result should include attribute authorizations
* @param isDefaultResource {@code true} if
* @return the resource authorization
*/
ResourceAuthorization authorizeResource(boolean attributes, boolean isDefaultResource);
/**
* Check for authorization to read or modify an attribute, checking all effects of the given operation
* @param operation the operation that will read or modify
* @param attribute the attribute name
* @param currentValue the current value of the attribute
* @return the authorization result
*/
AuthorizationResult authorize(ModelNode operation, String attribute, ModelNode currentValue);
/**
* Check for authorization to read or modify an attribute, limiting the check to the given effects of the operation
* @param operation the operation that will read or modify
* @param attribute the attribute name
* @param currentValue the current value of the attribute
* @param effects the effects to check, or, if empty, all effects
* @return the authorization result
*/
AuthorizationResult authorize(ModelNode operation, String attribute, ModelNode currentValue, Set<Action.ActionEffect> effects);
/**
* Check for authorization to execute an operation.
*
* @param operation the operation. Cannot be {@code null}
* @return the authorization result
*/
AuthorizationResult authorizeOperation(ModelNode operation);
/**
* Obtain the {@link Caller} for the current request.
*
* @return The current caller.
*/
Caller getCaller();
/**
* Emit a {@link org.jboss.as.controller.notification.Notification}.
*
* @param notification the notification to emit
*/
void emit(final Notification notification);
/**
* Gets the caller environment for the current request.
* @return the call environment
*/
Environment getCallEnvironment();
/**
* Registers a capability with the system. Any {@link org.jboss.as.controller.capability.RuntimeCapability#getRequirements() requirements}
* associated with the capability will be recorded as requirements.
*
* @param capability the capability. Cannot be {@code null}
* @param attribute the name of the attribute that triggered this registration, or {@code null} if no single
* attribute was responsible
*
* @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is not {@link Stage#MODEL}
*/
void registerCapability(RuntimeCapability capability, String attribute);
/**
* Registers an additional hard requirement a capability has beyond what it was aware of when {@code capability}
* was passed to {@link #registerCapability(org.jboss.as.controller.capability.RuntimeCapability, String)}. Used for cases
* where a capability optionally depends on another capability, and whether or not that requirement is needed is
* not known when the capability is first registered.
* <p>
* This method should be used in preference to {@link #requestOptionalCapability(String, String, String)}
* when, based on its own configuration, the caller knows in {@link org.jboss.as.controller.OperationContext.Stage#MODEL}
* that the optional capability is actually required in the current process.
* </p>
*
* @param required the name of the required capability. Cannot be {@code null}
* @param dependent the name of the capability that requires the other capability. Cannot be {@code null}
* @param attribute the name of the attribute that triggered this requirement, or {@code null} if no single
* attribute was responsible
*
* @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is not {@link Stage#MODEL}
* or if {@code capability} is not registered
*/
void registerAdditionalCapabilityRequirement(String required, String dependent, String attribute);
/**
* <strong>Deprecated</strong>; use {@link #hasOptionalCapability(String, String, String)}
* <p>
* Differs from {@link #hasOptionalCapability(String, String, String)} in that once the caller declares an intent
* to use the {@code required}capability by invoking this method and getting a {@code true} response, thereafter
* the system treats that as a hard requirement. However, there is no valid use case for that behavior.
* </p>
*
* @param required the name of the required capability. Cannot be {@code null}
* @param dependent the name of the capability that requires the other capability. Cannot be {@code null}
* @param attribute the name of the attribute that triggered this requirement, or {@code null} if no single
* attribute was responsible
* @return {@code true} if the requested capability is present; {@code false} if not. If {@code true}, hereafter
* {@code dependent}'s requirement for {@code required} will not be treated as optional.
*
* @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. The
* complete set of capabilities is not known until the end of the model stage.
*
* @deprecated Will be moved in WildFly 10; use {@link #hasOptionalCapability(String, String, String)}
*/
@Deprecated
boolean requestOptionalCapability(String required, String dependent, String attribute);
/**
* Checks whether one of a capability's optional and runtime-only requirements is present. Only for use in cases
* where the {@code dependent} capability's persistent configuration does not <strong>mandate</strong> the presence
* of the {@code requested} capability, but the capability will use it at runtime if it is present.
* <p>
* This method should be used in preference to {@link #registerAdditionalCapabilityRequirement(String, String, String)}
* when the caller's own configuration doesn't impose a hard requirement for the {@code requested} capability, but,
* if it is present it will be used. Once the caller declares an intent to use the capability by invoking this
* method and getting a {@code true} response, thereafter the system is aware that {@code dependent} is actually
* using {@code requested}, but <strong>will not</strong> prevent configuration changes that make {@code requested}
* unavailable.
* </p>
*
* @param requested the name of the requested capability. Cannot be {@code null}
* @param dependent the name of the capability that requires the other capability. Cannot be {@code null}
* @param attribute the name of the attribute that triggered this requirement, or {@code null} if no single
* attribute was responsible
* @return {@code true} if the requested capability is present; {@code false} if not. If {@code true}, hereafter
* {@code dependent}'s requirement for {@code requested} will not be treated as optional.
*
* @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. The
* complete set of capabilities is not known until the end of the model stage.
*/
boolean hasOptionalCapability(String requested, String dependent, String attribute);
/**
* Requests that one of a capability's optional requirements hereafter be treated as required, until the process is
* stopped or reloaded. This request will only be granted if the required capability is already present; otherwise
* an {@link org.jboss.as.controller.OperationFailedException} will be thrown.
* <p>
* This method should be used in preference to {@link #registerAdditionalCapabilityRequirement(String, String, String)}
* only if the caller is not sure whether the capability is required until {@link org.jboss.as.controller.OperationContext.Stage#RUNTIME}.
* <strong>Not knowing whether a capability is required until stage RUNTIME is an anti-pattern, so use of this
* method is strongly discouraged.</strong> It only exists to avoid the need to break backward compatibility by removing
* support for expressions from certain attributes.
* </p>
*
* @param required the name of the required capability. Cannot be {@code null}
* @param dependent the name of the capability that requires the other capability. Cannot be {@code null}
* @param attribute the name of the attribute that triggered this requirement, or {@code null} if no single
* attribute was responsible
*
* @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. The
* complete set of capabilities is not known until the end of the model stage.
* @throws org.jboss.as.controller.OperationFailedException if the requested capability is not available
*/
void requireOptionalCapability(String required, String dependent, String attribute) throws OperationFailedException;
/**
* Record that a previously registered requirement for a capability will no longer exist.
* <p>
* <strong>Semantics with "reload-required" and "restart-required":</strong>
* Deregistering a capability requirement does not obligate the caller to cease using a
* {@link #getCapabilityRuntimeAPI(String, Class) previously obtained} reference to that
* capability's {@link org.jboss.as.controller.capability.RuntimeCapability#getRuntimeAPI() runtime API}. But, if
* the caller will not cease using the capability, it must put the process in {@link #reloadRequired() reload-required}
* or {@link #restartRequired() restart-required} state. This will reflect the fact that the model says the
* capability is not required, but in the runtime it still is.
* </p>
*
* @param required the name of the no longer required capability
* @param dependent the name of the capability that no longer has the requirement
*
* @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is not {@link Stage#MODEL}
*/
void deregisterCapabilityRequirement(String required, String dependent);
/**
* Record that a previously registered capability will no longer be available. Invoking this operation will also
* automatically {@link #deregisterCapabilityRequirement(String, String) deregister any requirements} that are
* associated with this capability, including optional ones.
* <p><strong>Semantics with "reload-required" and "restart-required":</strong>
* Deregistering a capability does not eliminate the obligation to other capabilities that have
* previously depended upon it to support them by providing expected runtime services. It does require that those other
* capabilities also {@link #deregisterCapabilityRequirement(String, String) deregister their requirements} as
* part of the same operation. Requiring that they do so ensures that the management model is consistent.
* However, those other capabilities may simply put the process in {@code reload-required}
* or {@code restart-required} state and then continue to use the existing services. So, an operation that invokes
* this method should also always put the process into {@code reload-required} or {@code restart-required} state.
* This will reflect the fact that the model says the capability is not present, but in the runtime it still is.
* </p>
*
* @param capabilityName the name of the capability
*
* @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is not {@link Stage#MODEL}
*/
void deregisterCapability(String capabilityName);
/**
* Gets the runtime API associated with a given capability, if there is one.
* @param capabilityName the name of the capability. Cannot be {@code null}
* @param apiType class of the java type that exposes the API. Cannot be {@code null}
* @param <T> the java type that exposes the API
* @return the runtime API. Will not return {@code null}
*
* @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. The
* complete set of capabilities is not known until the end of the model stage.
* @throws java.lang.IllegalArgumentException if the capability does not provide a runtime API
* @throws java.lang.ClassCastException if the runtime API exposed by the capability cannot be cast to type {code T}
*/
<T> T getCapabilityRuntimeAPI(String capabilityName, Class<T> apiType);
/**
* Gets the runtime API associated with a given {@link RuntimeCapability#isDynamicallyNamed() dynamically named}
* capability, if there is one.
*
* @param capabilityBaseName the base name of the capability. Cannot be {@code null}
* @param dynamicPart the dynamic part of the capability name. Cannot be {@code null}
* @param apiType class of the java type that exposes the API. Cannot be {@code null}
* @param <T> the java type that exposes the API
* @return the runtime API. Will not return {@code null}
*
* @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. The
* complete set of capabilities is not known until the end of the model stage.
* @throws java.lang.IllegalArgumentException if the capability does not provide a runtime API
* @throws java.lang.ClassCastException if the runtime API exposed by the capability cannot be cast to type {code T}
*/
<T> T getCapabilityRuntimeAPI(String capabilityBaseName, String dynamicPart, Class<T> apiType);
/**
* Gets the name of a service associated with a given capability, if there is one.
* @param capabilityName the name of the capability. Cannot be {@code null}
* @param serviceType class of the java type that exposes by the service. Cannot be {@code null}
* @return the name of the service. Will not return {@code null}
*
* @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. The
* complete set of capabilities is not known until the end of the model stage.
* @throws IllegalArgumentException if {@code serviceType} is {@code null } or
* the capability does not provide a service of type {@code serviceType}
*/
ServiceName getCapabilityServiceName(String capabilityName, Class<?> serviceType);
/**
* Gets the name of a service associated with a given {@link RuntimeCapability#isDynamicallyNamed() dynamically named}
* capability, if there is one.
*
* @param capabilityBaseName the base name of the capability. Cannot be {@code null}
* @param dynamicPart the dynamic part of the capability name. Cannot be {@code null}
* @param serviceType class of the java type that exposes by the service. Cannot be {@code null}
* @return the name of the service. Will not return {@code null}
*
* @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. The
* complete set of capabilities is not known until the end of the model stage.
* @throws IllegalArgumentException if {@code serviceType} is {@code null } or
* the capability does not provide a service of type {@code serviceType}
*/
ServiceName getCapabilityServiceName(String capabilityBaseName, String dynamicPart, Class<?> serviceType);
/**
* Gets a support object that allows service implementations installed from this context to
* integrate with capabilities.
*
* @return the support object. Will not return {@code null}
*
* * @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}.
* Service integration is not supported in the model stage.
*/
CapabilityServiceSupport getCapabilityServiceSupport();
/**
* Whether normally this operation would require a runtime step. It returns {@code true in the following cases}
* <ul>
* <li>The process is a server, and it is running in NORMAL (i.e. not admin-only) mode.</li>
* <li>The process is a HC, and the address of the operation is a subsystem in the host model or a child thereof</li>
*/
boolean isDefaultRequiresRuntime();
/**
* The stage at which a step should apply.
*/
enum Stage {
/**
* The step applies to the model (read or write).
*/
MODEL,
/**