Search in sources :

Example 1 with State

use of org.springframework.webflow.engine.State in project cas by apereo.

the class BaseMultifactorWebflowConfigurerTests method ensureAllTransitionDestinationsExistInFlow.

/**
 * Ensures that, for every transition within this MFA flow, the target
 * state is present within the flow.
 */
@Test
public void ensureAllTransitionDestinationsExistInFlow() {
    val registry = getMultifactorFlowDefinitionRegistry();
    assertTrue(registry.containsFlowDefinition(getMultifactorEventId()));
    val flow = (Flow) registry.getFlowDefinition(getMultifactorEventId());
    val states = Arrays.asList(flow.getStateIds());
    states.forEach(stateId -> {
        val state = (State) flow.getState(stateId);
        if (state instanceof TransitionableState) {
            ((TransitionableState) state).getTransitionSet().forEach(t -> {
                assertTrue(flow.containsState(t.getTargetStateId()), () -> String.format("Destination of transition [%s]-%s->[%s] must be in flow definition", stateId, t.getId(), t.getTargetStateId()));
            });
        }
    });
}
Also used : lombok.val(lombok.val) SubflowState(org.springframework.webflow.engine.SubflowState) ActionState(org.springframework.webflow.engine.ActionState) State(org.springframework.webflow.engine.State) TransitionableState(org.springframework.webflow.engine.TransitionableState) TransitionableState(org.springframework.webflow.engine.TransitionableState) Flow(org.springframework.webflow.engine.Flow) Test(org.junit.jupiter.api.Test)

Example 2 with State

use of org.springframework.webflow.engine.State in project cas by apereo.

the class SpringWebflowEndpoint method getStateDetails.

private static Map<String, Object> getStateDetails(final Flow flowDefinition, final String st) {
    val state = (State) flowDefinition.getState(st);
    val stateMap = new LinkedHashMap<String, Object>();
    if (!state.getAttributes().asMap().isEmpty()) {
        stateMap.put("attributes", CollectionUtils.wrap(state.getAttributes()));
    }
    if (StringUtils.isNotBlank(state.getCaption())) {
        stateMap.put("caption", state.getCaption());
    }
    var acts = StreamSupport.stream(state.getEntryActionList().spliterator(), false).map(SpringWebflowEndpoint::convertActionToString).collect(Collectors.toList());
    if (!acts.isEmpty()) {
        stateMap.put("entryActions", acts);
    }
    if (state instanceof ActionState) {
        acts = StreamSupport.stream(((ActionState) state).getActionList().spliterator(), false).map(SpringWebflowEndpoint::convertActionToString).collect(Collectors.toList());
        if (!acts.isEmpty()) {
            stateMap.put("actionList", acts);
        }
    }
    if (state instanceof EndState) {
        stateMap.put("isEndState", Boolean.TRUE);
    }
    if (state.isViewState()) {
        val viewState = (ViewState) state;
        stateMap.put("isViewState", state.isViewState());
        stateMap.put("isRedirect", viewState.getRedirect());
        acts = StreamSupport.stream(state.getEntryActionList().spliterator(), false).map(Object::toString).collect(Collectors.toList());
        if (!acts.isEmpty()) {
            stateMap.put("renderActions", viewState.getRenderActionList());
        }
        acts = Arrays.stream(viewState.getVariables()).map(variable -> variable.getName() + " -> " + variable.getValueFactory().toString()).collect(Collectors.toList());
        if (!acts.isEmpty()) {
            stateMap.put("viewVariables", acts);
        }
        val field = ReflectionUtils.findField(viewState.getViewFactory().getClass(), "viewId");
        if (field != null) {
            ReflectionUtils.makeAccessible(field);
            val exp = (Expression) ReflectionUtils.getField(field, viewState.getViewFactory());
            stateMap.put("viewId", StringUtils.defaultIfBlank(Objects.requireNonNull(exp).getExpressionString(), exp.getValue(null).toString()));
        } else if (viewState.getViewFactory() instanceof ActionExecutingViewFactory) {
            val factory = (ActionExecutingViewFactory) viewState.getViewFactory();
            if (factory.getAction() instanceof ExternalRedirectAction) {
                val redirect = (ExternalRedirectAction) factory.getAction();
                val uri = ReflectionUtils.findField(redirect.getClass(), "resourceUri");
                ReflectionUtils.makeAccessible(Objects.requireNonNull(uri));
                val exp = (Expression) ReflectionUtils.getField(uri, redirect);
                stateMap.put("viewId", "externalRedirect -> #{" + Objects.requireNonNull(exp).getExpressionString() + '}');
            } else {
                stateMap.put("viewId", factory.getAction().toString());
            }
        } else {
            LOGGER.info("Field viewId cannot be located on view state [{}]", state);
        }
    }
    if (state instanceof TransitionableState) {
        val stDef = (TransitionableState) state;
        acts = StreamSupport.stream(stDef.getExitActionList().spliterator(), false).map(Object::toString).collect(Collectors.toList());
        if (!acts.isEmpty()) {
            stateMap.put("exitActions", acts);
        }
        acts = Arrays.stream(stDef.getTransitions()).map(tr -> tr.getId() + " -> " + tr.getTargetStateId()).collect(Collectors.toList());
        if (!acts.isEmpty()) {
            stateMap.put("transitions", acts);
        }
    }
    return stateMap;
}
Also used : lombok.val(lombok.val) ViewState(org.springframework.webflow.engine.ViewState) TransitionableState(org.springframework.webflow.engine.TransitionableState) ExternalRedirectAction(org.springframework.webflow.action.ExternalRedirectAction) LinkedHashMap(java.util.LinkedHashMap) Expression(org.springframework.binding.expression.Expression) ActionState(org.springframework.webflow.engine.ActionState) TransitionableState(org.springframework.webflow.engine.TransitionableState) State(org.springframework.webflow.engine.State) EndState(org.springframework.webflow.engine.EndState) ViewState(org.springframework.webflow.engine.ViewState) ActionExecutingViewFactory(org.springframework.webflow.engine.support.ActionExecutingViewFactory) ActionState(org.springframework.webflow.engine.ActionState) EndState(org.springframework.webflow.engine.EndState)

Example 3 with State

use of org.springframework.webflow.engine.State in project cas by apereo.

the class SpringWebflowEndpoint method getReport.

/**
 * Get SWF report.
 *
 * @param flowId  the flow id
 * @param stateId the state id
 * @return JSON representing the current state of SWF.
 */
@ReadOperation
@Operation(summary = "Get Spring webflow report using an optional flow id", parameters = { @Parameter(name = "flowId"), @Parameter(name = "stateId") })
public Map<?, ?> getReport(@Nullable final String flowId, @Nullable final String stateId) {
    val jsonMap = new LinkedHashMap<String, Object>();
    val executionPlan = applicationContext.getBean(CasWebflowExecutionPlan.BEAN_NAME, CasWebflowExecutionPlan.class);
    executionPlan.execute();
    val map = applicationContext.getBeansOfType(FlowDefinitionRegistry.class);
    map.forEach((k, value) -> Arrays.stream(value.getFlowDefinitionIds()).filter(currentId -> StringUtils.isBlank(flowId) || flowId.equalsIgnoreCase(currentId)).forEach(id -> {
        val flowDefinition = (Flow) value.getFlowDefinition(id);
        val flowDetails = new LinkedHashMap<String, Object>();
        flowDetails.put("startState", flowDefinition.getStartState().getId());
        val startActions = StreamSupport.stream(flowDefinition.getStartActionList().spliterator(), false).map(SpringWebflowEndpoint::convertActionToString).collect(Collectors.toList());
        if (!startActions.isEmpty()) {
            flowDetails.put("startActions", startActions);
        }
        val states = new LinkedHashMap<String, Map>();
        Arrays.stream(flowDefinition.getStateIds()).filter(st -> StringUtils.isBlank(stateId) || RegexUtils.find(stateId, st)).forEach(st -> {
            val stateMap = getStateDetails(flowDefinition, st);
            states.put(st, stateMap);
        });
        flowDetails.put("states", states);
        flowDetails.put("possibleOutcomes", flowDefinition.getPossibleOutcomes());
        flowDetails.put("stateCount", flowDefinition.getStateCount());
        var acts = StreamSupport.stream(flowDefinition.getEndActionList().spliterator(), false).map(SpringWebflowEndpoint::convertActionToString).collect(Collectors.toList());
        if (!acts.isEmpty()) {
            flowDetails.put("endActions", acts);
        }
        acts = StreamSupport.stream(flowDefinition.getGlobalTransitionSet().spliterator(), false).map(tr -> tr.getId() + " -> " + tr.getTargetStateId() + " @ " + tr.getExecutionCriteria().toString()).collect(Collectors.toList());
        if (!acts.isEmpty()) {
            flowDetails.put("globalTransitions", acts);
        }
        acts = Arrays.stream(flowDefinition.getExceptionHandlerSet().toArray()).map(Object::toString).collect(Collectors.toList());
        if (!acts.isEmpty()) {
            flowDetails.put("exceptionHandlers", acts);
        }
        val vars = Arrays.stream(flowDefinition.getVariables()).map(FlowVariable::getName).collect(Collectors.joining(","));
        if (StringUtils.isNotBlank(vars)) {
            flowDetails.put("variables", vars);
        }
        jsonMap.put(id, flowDetails);
    }));
    return jsonMap;
}
Also used : lombok.val(lombok.val) CasConfigurationProperties(org.apereo.cas.configuration.CasConfigurationProperties) ActionState(org.springframework.webflow.engine.ActionState) Arrays(java.util.Arrays) ReadOperation(org.springframework.boot.actuate.endpoint.annotation.ReadOperation) SetAction(org.springframework.webflow.action.SetAction) ExternalRedirectAction(org.springframework.webflow.action.ExternalRedirectAction) AnnotatedAction(org.springframework.webflow.execution.AnnotatedAction) ActionExecutingViewFactory(org.springframework.webflow.engine.support.ActionExecutingViewFactory) CasWebflowExecutionPlan(org.apereo.cas.web.flow.CasWebflowExecutionPlan) StringUtils(org.apache.commons.lang3.StringUtils) TransitionableState(org.springframework.webflow.engine.TransitionableState) LinkedHashMap(java.util.LinkedHashMap) Operation(io.swagger.v3.oas.annotations.Operation) Map(java.util.Map) CollectionUtils(org.apereo.cas.util.CollectionUtils) Nullable(org.springframework.lang.Nullable) StreamSupport(java.util.stream.StreamSupport) FlowDefinitionRegistry(org.springframework.webflow.definition.registry.FlowDefinitionRegistry) FlowVariable(org.springframework.webflow.engine.FlowVariable) State(org.springframework.webflow.engine.State) Endpoint(org.springframework.boot.actuate.endpoint.annotation.Endpoint) lombok.val(lombok.val) Expression(org.springframework.binding.expression.Expression) EvaluateAction(org.springframework.webflow.action.EvaluateAction) Flow(org.springframework.webflow.engine.Flow) Action(org.springframework.webflow.execution.Action) Field(java.lang.reflect.Field) ApplicationContext(org.springframework.context.ApplicationContext) Collectors(java.util.stream.Collectors) RegexUtils(org.apereo.cas.util.RegexUtils) BaseCasActuatorEndpoint(org.apereo.cas.web.BaseCasActuatorEndpoint) Parameter(io.swagger.v3.oas.annotations.Parameter) Objects(java.util.Objects) Slf4j(lombok.extern.slf4j.Slf4j) EndState(org.springframework.webflow.engine.EndState) ViewState(org.springframework.webflow.engine.ViewState) ReflectionUtils(org.springframework.util.ReflectionUtils) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) FlowVariable(org.springframework.webflow.engine.FlowVariable) ReadOperation(org.springframework.boot.actuate.endpoint.annotation.ReadOperation) ReadOperation(org.springframework.boot.actuate.endpoint.annotation.ReadOperation) Operation(io.swagger.v3.oas.annotations.Operation)

Aggregations

lombok.val (lombok.val)3 ActionState (org.springframework.webflow.engine.ActionState)3 State (org.springframework.webflow.engine.State)3 TransitionableState (org.springframework.webflow.engine.TransitionableState)3 LinkedHashMap (java.util.LinkedHashMap)2 Expression (org.springframework.binding.expression.Expression)2 ExternalRedirectAction (org.springframework.webflow.action.ExternalRedirectAction)2 EndState (org.springframework.webflow.engine.EndState)2 Flow (org.springframework.webflow.engine.Flow)2 ViewState (org.springframework.webflow.engine.ViewState)2 ActionExecutingViewFactory (org.springframework.webflow.engine.support.ActionExecutingViewFactory)2 Operation (io.swagger.v3.oas.annotations.Operation)1 Parameter (io.swagger.v3.oas.annotations.Parameter)1 Field (java.lang.reflect.Field)1 Arrays (java.util.Arrays)1 Map (java.util.Map)1 Objects (java.util.Objects)1 Collectors (java.util.stream.Collectors)1 StreamSupport (java.util.stream.StreamSupport)1 Slf4j (lombok.extern.slf4j.Slf4j)1