Package org.jibeframework.core.util

Source Code of org.jibeframework.core.util.ViewComponentFactory

package org.jibeframework.core.util;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

import org.codehaus.groovy.control.CompilationFailedException;
import org.jibeframework.core.Context;
import org.jibeframework.core.annotation.Service;
import org.jibeframework.core.annotation.UIComponent;
import org.jibeframework.core.annotation.UIController;
import org.jibeframework.core.ui.UIComponentMixin;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.scripting.ScriptCompilationException;
import org.springframework.scripting.ScriptFactory;
import org.springframework.scripting.ScriptSource;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;

@SuppressWarnings("unchecked")
public class ViewComponentFactory implements ScriptFactory, BeanFactoryAware, ApplicationContextAware,
    BeanClassLoaderAware {
  private File file;
  private long lastModified = -1;
  private GroovyClassLoader groovyClassLoader;

  private ApplicationContext applicationContext;

  private AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();

  private Class scriptClass;

  private String scriptSourceLocator;

  private Map<Field, Object> injectionCache = new HashMap<Field, Object>();

  private final Object scriptClassMonitor = new Object();

  private ViewComponentFactory(File scriptSource) {
    this.scriptSourceLocator = "file:" + scriptSource.getAbsolutePath();
    file = scriptSource;

  }

  public Object getScriptedObject(ScriptSource scriptSource, Class[] actualInterfaces) throws IOException,
      ScriptCompilationException {
    if (file.lastModified() != lastModified) {
      compileScriptClass(scriptSource);
    }
    try {

      GroovyObject goo = (GroovyObject) scriptClass.newInstance();
      UIComponent ann = AnnotationUtils.findAnnotation(scriptClass, UIComponent.class);
      if (ann != null) {
        UIComponentMixin.applyMixin(ann.value(), goo, applicationContext);
      }
      Context context = Context.getCurrentContext();
      for (Map.Entry<Field, Object> f : injectionCache.entrySet()) {
        ReflectionUtils.makeAccessible(f.getKey());
        Object dependency = null;
        if (f.getValue() instanceof String) {
          String beanId = (String) f.getValue();
          if (context.containsViewBean(beanId)) {
            dependency = context.getViewBean(beanId);
          } else {
            dependency = applicationContext.getBean(beanId);
          }
        } else {
          dependency = applicationContext.getBean((Class) f.getValue());
        }
        ReflectionUtils.setField(f.getKey(), goo, dependency);
      }
      processor.processInjection(goo);
      return goo;
    } catch (InstantiationException ex) {
      throw new ScriptCompilationException(scriptSource, "Could not instantiate Groovy script class: "
          + scriptClass.getName(), ex);
    } catch (IllegalAccessException ex) {
      throw new ScriptCompilationException(scriptSource, "Could not access Groovy script constructor: "
          + scriptClass.getName(), ex);
    }
  }

  public Class getScriptedObjectType(ScriptSource scriptSource) throws IOException, ScriptCompilationException {
    if (file.lastModified() != lastModified) {
      compileScriptClass(scriptSource);
    }
    return this.scriptClass;
  }

  private void compileScriptClass(ScriptSource scriptSource) throws IOException {
    try {
      synchronized (this.scriptClassMonitor) {
        if (file.lastModified() != lastModified) {
          this.scriptClass = getGroovyClassLoader().parseClass(scriptSource.getScriptAsString(),
              scriptSource.suggestedClassName());
          this.lastModified = file.lastModified();

          injectionCache.clear();
          Class<?> targetClass = this.scriptClass;
          while (targetClass != null && targetClass != Object.class) {
            for (Field field : targetClass.getDeclaredFields()) {
              if (!Modifier.isStatic(field.getModifiers())) {
                UIComponent dann = field.getAnnotation(UIComponent.class);
                if (dann != null) {
                  injectionCache.put(field, dann.value());
                } else {
                  UIController cann = field.getAnnotation(UIController.class);
                  if (cann != null) {
                    injectionCache.put(field, cann.value());
                  } else {
                    Service sann = field.getAnnotation(Service.class);
                    if (sann != null) {
                      injectionCache.put(field, field.getType());
                    }
                  }
                }

              }
            }
            targetClass = targetClass.getSuperclass();
          }
        }
      }
    } catch (CompilationFailedException ex) {
      throw new ScriptCompilationException(scriptSource, ex);
    }
  }

  /**
   * Return the GroovyClassLoader used by this script factory.
   */
  public GroovyClassLoader getGroovyClassLoader() {
    synchronized (this.scriptClassMonitor) {
      if (this.groovyClassLoader == null) {
        this.groovyClassLoader = new GroovyClassLoader(ClassUtils.getDefaultClassLoader());
      }
      return this.groovyClassLoader;
    }
  }

  public Class[] getScriptInterfaces() {
    return null;
  }

  public String getScriptSourceLocator() {
    return scriptSourceLocator;
  }

  public boolean requiresConfigInterface() {
    return false;
  }

  public boolean requiresScriptedObjectRefresh(ScriptSource scriptSource) {
    return false;
  }

  public void setBeanClassLoader(ClassLoader classLoader) {
    this.groovyClassLoader = new GroovyClassLoader(classLoader);

  }

  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
  }

  public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    processor.setBeanFactory(beanFactory);

  }

}
TOP

Related Classes of org.jibeframework.core.util.ViewComponentFactory

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.