Package org.springframework.webflow.config

Source Code of org.springframework.webflow.config.FlowExecutorFactoryBean

/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.webflow.config;

import java.util.Set;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.binding.convert.ConversionExecutor;
import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.convert.service.DefaultConversionService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.webflow.conversation.ConversationManager;
import org.springframework.webflow.conversation.impl.SessionBindingConversationManager;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
import org.springframework.webflow.execution.FlowExecutionFactory;
import org.springframework.webflow.execution.factory.FlowExecutionListenerLoader;
import org.springframework.webflow.execution.repository.FlowExecutionRepository;
import org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository;
import org.springframework.webflow.execution.repository.snapshot.FlowExecutionSnapshotFactory;
import org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshotFactory;
import org.springframework.webflow.execution.repository.snapshot.SimpleFlowExecutionSnapshotFactory;
import org.springframework.webflow.executor.FlowExecutor;
import org.springframework.webflow.executor.FlowExecutorImpl;
import org.springframework.webflow.mvc.builder.MvcEnvironment;

/**
* This factory encapsulates the construction and assembly of a {@link FlowExecutor}, including the provision of its
* {@link FlowExecutionRepository} strategy. As a <code>FactoryBean</code>, this class has been designed for use as a
* Spring managed bean.
* <p>
* The definition locator property is required, all other properties are optional.
*
* @author Keith Donald
* @author Erwin Vervaet
*/
class FlowExecutorFactoryBean implements FactoryBean<FlowExecutor>, ApplicationContextAware, BeanClassLoaderAware,
    InitializingBean {

  private static final String ALWAYS_REDIRECT_ON_PAUSE = "alwaysRedirectOnPause";

  private static final String REDIRECT_IN_SAME_STATE = "redirectInSameState";

  private FlowDefinitionLocator flowDefinitionLocator;

  private Integer maxFlowExecutions;

  private Integer maxFlowExecutionSnapshots;

  private Set<FlowElementAttribute> flowExecutionAttributes;

  private FlowExecutionListenerLoader flowExecutionListenerLoader;

  private ConversationManager conversationManager;

  private ConversionService conversionService;

  private FlowExecutor flowExecutor;

  private MvcEnvironment environment;

  private ClassLoader classLoader;

  /**
   * Sets the flow definition locator that will locate flow definitions needed for execution. Typically also a
   * {@link FlowDefinitionRegistry}. Required.
   * @param flowDefinitionLocator the flow definition locator (registry)
   */
  public void setFlowDefinitionLocator(FlowDefinitionLocator flowDefinitionLocator) {
    this.flowDefinitionLocator = flowDefinitionLocator;
  }

  /**
   * Set the maximum number of allowed flow executions allowed per user.
   */
  public void setMaxFlowExecutions(int maxFlowExecutions) {
    this.maxFlowExecutions = maxFlowExecutions;
  }

  /**
   * Set the maximum number of history snapshots allowed per flow execution.
   */
  public void setMaxFlowExecutionSnapshots(int maxFlowExecutionSnapshots) {
    this.maxFlowExecutionSnapshots = maxFlowExecutionSnapshots;
  }

  /**
   * Sets the system attributes that apply to flow executions launched by the executor created by this factory.
   * Execution attributes may affect flow execution behavior.
   * @param flowExecutionAttributes the flow execution system attributes
   */
  public void setFlowExecutionAttributes(Set<FlowElementAttribute> flowExecutionAttributes) {
    this.flowExecutionAttributes = flowExecutionAttributes;
  }

  /**
   * Sets the strategy for loading the listeners that will observe executions of a flow definition. Allows full
   * control over what listeners should apply to executions of a flow definition launched by the executor created by
   * this factory.
   */
  public void setFlowExecutionListenerLoader(FlowExecutionListenerLoader flowExecutionListenerLoader) {
    this.flowExecutionListenerLoader = flowExecutionListenerLoader;
  }

  /**
   * Sets the service type that manages conversations and effectively controls how state is stored physically when a
   * flow execution is paused.
   */
  public void setConversationManager(ConversationManager conversationManager) {
    this.conversationManager = conversationManager;
  }

  // implementing ApplicationContextAware

  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    environment = MvcEnvironment.environmentFor(applicationContext);
  }

  // implement BeanClassLoaderAware

  public void setBeanClassLoader(ClassLoader classLoader) {
    this.classLoader = classLoader;
  }

  // implementing InitializingBean

  public void afterPropertiesSet() throws Exception {
    Assert.notNull(flowDefinitionLocator, "The flow definition locator property is required");
    if (conversionService == null) {
      conversionService = new DefaultConversionService();
    }
    MutableAttributeMap<Object> executionAttributes = createFlowExecutionAttributes();
    FlowExecutionImplFactory executionFactory = createFlowExecutionFactory(executionAttributes);
    DefaultFlowExecutionRepository executionRepository = createFlowExecutionRepository(executionFactory);
    executionFactory.setExecutionKeyFactory(executionRepository);
    flowExecutor = new FlowExecutorImpl(flowDefinitionLocator, executionFactory, executionRepository);
  }

  // implementing FactoryBean

  public Class<?> getObjectType() {
    return FlowExecutor.class;
  }

  public boolean isSingleton() {
    return true;
  }

  public FlowExecutor getObject() throws Exception {
    return flowExecutor;
  }

  private MutableAttributeMap<Object> createFlowExecutionAttributes() {
    LocalAttributeMap<Object> executionAttributes = new LocalAttributeMap<Object>();
    if (flowExecutionAttributes != null) {
      for (FlowElementAttribute attribute : flowExecutionAttributes) {
        executionAttributes.put(attribute.getName(), getConvertedValue(attribute));
      }
    }
    putDefaultFlowExecutionAttributes(executionAttributes);
    return executionAttributes;
  }

  private void putDefaultFlowExecutionAttributes(LocalAttributeMap<Object> executionAttributes) {
    if (!executionAttributes.contains(ALWAYS_REDIRECT_ON_PAUSE)) {
      Boolean redirect = (environment != MvcEnvironment.PORTLET);
      executionAttributes.put(ALWAYS_REDIRECT_ON_PAUSE, redirect);
    }
    if (!executionAttributes.contains(REDIRECT_IN_SAME_STATE)) {
      Boolean redirect = (environment != MvcEnvironment.PORTLET);
      executionAttributes.put(REDIRECT_IN_SAME_STATE, redirect);
    }
  }

  private DefaultFlowExecutionRepository createFlowExecutionRepository(FlowExecutionFactory executionFactory) {
    ConversationManager conversationManager = createConversationManager();
    FlowExecutionSnapshotFactory snapshotFactory = createFlowExecutionSnapshotFactory(executionFactory);
    DefaultFlowExecutionRepository rep = new DefaultFlowExecutionRepository(conversationManager, snapshotFactory);
    if (maxFlowExecutionSnapshots != null) {
      rep.setMaxSnapshots(maxFlowExecutionSnapshots);
    }
    return rep;
  }

  private ConversationManager createConversationManager() {
    if (conversationManager == null) {
      conversationManager = new SessionBindingConversationManager();
      if (maxFlowExecutions != null) {
        ((SessionBindingConversationManager) conversationManager).setMaxConversations(maxFlowExecutions);
      }
    }
    return this.conversationManager;
  }

  private FlowExecutionSnapshotFactory createFlowExecutionSnapshotFactory(FlowExecutionFactory executionFactory) {
    if (maxFlowExecutionSnapshots != null && maxFlowExecutionSnapshots == 0) {
      maxFlowExecutionSnapshots = 1;
      return new SimpleFlowExecutionSnapshotFactory(executionFactory, flowDefinitionLocator);
    } else {
      return new SerializedFlowExecutionSnapshotFactory(executionFactory, flowDefinitionLocator);
    }
  }

  private FlowExecutionImplFactory createFlowExecutionFactory(AttributeMap<Object> executionAttributes) {
    FlowExecutionImplFactory executionFactory = new FlowExecutionImplFactory();
    executionFactory.setExecutionAttributes(executionAttributes);
    if (flowExecutionListenerLoader != null) {
      executionFactory.setExecutionListenerLoader(flowExecutionListenerLoader);
    }
    return executionFactory;
  }

  // utility methods

  private Object getConvertedValue(FlowElementAttribute attribute) {
    if (attribute.needsTypeConversion()) {
      Class<?> targetType = fromStringToClass(attribute.getType());
      ConversionExecutor converter = conversionService.getConversionExecutor(String.class, targetType);
      return converter.execute(attribute.getValue());
    } else {
      return attribute.getValue();
    }
  }

  private Class<?> fromStringToClass(String name) {
    Class<?> clazz = conversionService.getClassForAlias(name);
    if (clazz != null) {
      return clazz;
    } else {
      try {
        return ClassUtils.forName(name, classLoader);
      } catch (ClassNotFoundException e) {
        throw new IllegalArgumentException("Unable to load class '" + name + "'");
      }
    }
  }

}
TOP

Related Classes of org.springframework.webflow.config.FlowExecutorFactoryBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.