Package org.springframework.batch.core.jsr.launch.support

Source Code of org.springframework.batch.core.jsr.launch.support.BatchPropertyBeanPostProcessor

/*
* Copyright 2013-2014 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.batch.core.jsr.launch.support;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import javax.batch.api.BatchProperty;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext;
import org.springframework.batch.core.jsr.configuration.support.JsrExpressionParser;
import org.springframework.batch.core.scope.StepScope;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.expression.StandardBeanExpressionResolver;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

/**
* <p>
* {@link BeanPostProcessor} implementation used to inject JSR-352 String properties into batch artifact fields
* that are marked with the {@link BatchProperty} annotation.
* </p>
*
* @author Chris Schaefer
* @author Michael Minella
* @since 3.0
*/
@SuppressWarnings("unchecked")
public class BatchPropertyBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
  private static final String SCOPED_TARGET_BEAN_PREFIX = "scopedTarget.";
  private static final Log LOGGER = LogFactory.getLog(BatchPropertyBeanPostProcessor.class);
  private static final Set<Class<? extends Annotation>> REQUIRED_ANNOTATIONS = new HashSet<Class<? extends Annotation>>();

  private JsrExpressionParser jsrExpressionParser;
  private BatchPropertyContext batchPropertyContext;

  static {
    ClassLoader cl = BatchPropertyBeanPostProcessor.class.getClassLoader();

    try {
      REQUIRED_ANNOTATIONS.add((Class<? extends Annotation>) cl.loadClass("javax.inject.Inject"));
    } catch (ClassNotFoundException ex) {
      LOGGER.warn("javax.inject.Inject not found - @BatchProperty marked fields will not be processed.");
    }

    REQUIRED_ANNOTATIONS.add(BatchProperty.class);
  }

  @Override
  public Object postProcessBeforeInitialization(final Object artifact, String artifactName) throws BeansException {
    Properties artifactProperties = getArtifactProperties(artifactName);

    if (artifactProperties.isEmpty()) {
      return artifact;
    }

    injectBatchProperties(artifact, artifactProperties);

    return artifact;
  }

  @Override
  public Object postProcessAfterInitialization(Object artifact, String artifactName) throws BeansException {
    return artifact;
  }

  private Properties getArtifactProperties(String artifactName) {
    String originalArtifactName = artifactName;

    if(originalArtifactName.startsWith(SCOPED_TARGET_BEAN_PREFIX)) {
      originalArtifactName = artifactName.substring(SCOPED_TARGET_BEAN_PREFIX.length());
    }

    StepContext stepContext = StepSynchronizationManager.getContext();

    if (stepContext != null) {
      return batchPropertyContext.getStepArtifactProperties(stepContext.getStepName(), originalArtifactName);
    }

    return batchPropertyContext.getArtifactProperties(originalArtifactName);
  }

  private void injectBatchProperties(final Object artifact, final Properties artifactProperties) {
    ReflectionUtils.doWithFields(artifact.getClass(), new ReflectionUtils.FieldCallback() {
      @Override
      public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
        if (isValidFieldModifier(field) && isAnnotated(field)) {
          boolean isAccessible = field.isAccessible();
          field.setAccessible(true);

          String batchProperty = getBatchPropertyFieldValue(field, artifactProperties);

          if (StringUtils.hasText(batchProperty)) {
            field.set(artifact, batchProperty);
          }

          field.setAccessible(isAccessible);
        }
      }
    });
  }

  private String getBatchPropertyFieldValue(Field field, Properties batchArtifactProperties) {
    BatchProperty batchProperty = field.getAnnotation(BatchProperty.class);

    if (!"".equals(batchProperty.name())) {
      return getBatchProperty(batchProperty.name(), batchArtifactProperties);
    }

    return getBatchProperty(field.getName(), batchArtifactProperties);
  }

  private String getBatchProperty(String propertyKey, Properties batchArtifactProperties) {
    if (batchArtifactProperties.containsKey(propertyKey)) {
      String propertyValue = (String) batchArtifactProperties.get(propertyKey);

      return jsrExpressionParser.parseExpression(propertyValue);
    }

    return null;
  }

  private boolean isAnnotated(Field field) {
    for (Class<? extends Annotation> annotation : REQUIRED_ANNOTATIONS) {
      if (!field.isAnnotationPresent(annotation)) {
        return false;
      }
    }

    return true;
  }

  private boolean isValidFieldModifier(Field field) {
    return !Modifier.isStatic(field.getModifiers()) && !Modifier.isFinal(field.getModifiers());
  }

  @Override
  public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
      throw new IllegalArgumentException(
          "BatchPropertyBeanPostProcessor requires a ConfigurableListableBeanFactory");
    }

    ConfigurableListableBeanFactory configurableListableBeanFactory = (ConfigurableListableBeanFactory) beanFactory;

    BeanExpressionContext beanExpressionContext = new BeanExpressionContext(configurableListableBeanFactory,
        configurableListableBeanFactory.getBean(StepScope.class));

    this.jsrExpressionParser = new JsrExpressionParser(new StandardBeanExpressionResolver(), beanExpressionContext);
  }

  @Autowired
  public void setBatchPropertyContext(BatchPropertyContext batchPropertyContext) {
    this.batchPropertyContext = batchPropertyContext;
  }
}
TOP

Related Classes of org.springframework.batch.core.jsr.launch.support.BatchPropertyBeanPostProcessor

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.