Package jodd.madvoc.config

Source Code of jodd.madvoc.config.AutomagicMadvocConfigurator

// Copyright (c) 2003-2014, Jodd Team (jodd.org). All Rights Reserved.

package jodd.madvoc.config;

import jodd.introspector.ClassDescriptor;
import jodd.introspector.ClassIntrospector;
import jodd.introspector.MethodDescriptor;
import jodd.io.findfile.ClassFinder;
import jodd.madvoc.MadvocException;
import jodd.madvoc.WebApplication;
import jodd.madvoc.component.ActionsManager;
import jodd.madvoc.component.MadvocConfig;
import jodd.madvoc.component.ResultsManager;
import jodd.madvoc.meta.ActionAnnotation;
import jodd.madvoc.meta.MadvocAction;
import jodd.madvoc.meta.Action;
import jodd.madvoc.result.ActionResult;
import jodd.util.ClassLoaderUtil;
import jodd.util.ReflectUtil;
import jodd.petite.meta.PetiteInject;
import jodd.log.Logger;
import jodd.log.LoggerFactory;

import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
* Default Madvoc configurator uses auto-magic to configure {@link WebApplication}.
* It searches the class path for all classes which names ends with 'Action' and 'Result'
* suffixes. Each such class will be loaded and introspected to determine
* if it represents valid Madvoc entity and then registered into the web application.
* <p>
* Action class is scanned for the {@link MadvocAction}. All public methods with {@link Action}
* are registered as Madvoc actions.
*/
public class AutomagicMadvocConfigurator extends ClassFinder implements MadvocConfigurator {

  private static final Logger log = LoggerFactory.getLogger(AutomagicMadvocConfigurator.class);

  @PetiteInject
  protected MadvocConfig madvocConfig;

  @PetiteInject
  protected ActionsManager actionsManager;

  @PetiteInject
  protected ResultsManager resultsManager;

  protected String actionClassSuffix;         // default action class suffix, for class path search
  protected String resultClassSuffix;         // default action result class suffix, for class path search
  protected long elapsed;

  public AutomagicMadvocConfigurator() {
    actionClassSuffix = "Action";
    resultClassSuffix = "Result";
    elapsed = 0;
  }

  /**
   * Configures web application from system classpath
   * @see #configure(java.io.File[])
   */
  public void configure() {
    configure(ClassLoaderUtil.getDefaultClasspath());
  }

  /**
   * Configures web application from specified classpath. The whole process is done in the following steps:
   * <ol>
   * <li>scanning web application classpath</li>
   * <li>invoking external configurations, if exist</li>
   * <li>applying defaults</li>
   * </ol>
   * @see #configure()
   */
  public void configure(File[] classpath) {
    elapsed = System.currentTimeMillis();

    rulesEntries.smartMode();

    try {
      scanPaths(classpath);
    } catch (Exception ex) {
      throw new MadvocException("Scan classpath error", ex);
    }
    elapsed = System.currentTimeMillis() - elapsed;
    log.info("Madvoc configured in " + elapsed + " ms. Total actions: " + actionsManager.getActionsCount());
  }


  /**
   * Parses class name that matches madvoc-related names.
   */
  @Override
  protected void onEntry(EntryData entryData) {
    String entryName = entryData.getName();
    if (entryName.endsWith(actionClassSuffix) == true) {
      try {
        onActionClass(entryName);
      } catch (ClassNotFoundException cnfex) {
        throw new MadvocException("Invalid Madvoc action class: " + entryName, cnfex);
      }
    } else if (entryName.endsWith(resultClassSuffix) == true) {
      try {
        onResultClass(entryName);
      } catch (ClassNotFoundException cnfex) {
        throw new MadvocException("Invalid Madvoc result class: " + entryName, cnfex);
      }
    }
  }

  // ---------------------------------------------------------------- class check

  /**
   * Determines if class should be examined for Madvoc annotations.
   * Array, anonymous, primitive, interfaces and so on should be
   * ignored. Sometimes, checking may fail due to e.g. <code>NoClassDefFoundError</code>;
   * we should continue searching anyway.
   */
  public boolean checkClass(Class clazz) {
    try {
      if (clazz.isAnonymousClass()) {
        return false;
      }
      if (clazz.isArray() || clazz.isEnum()) {
        return false;
      }
      if (clazz.isInterface()) {
        return false;
      }
      if (clazz.isLocalClass()) {
        return false;
      }
      if ((clazz.isMemberClass() ^ Modifier.isStatic(clazz.getModifiers()))) {
        return false;
      }
      if (clazz.isPrimitive()) {
        return false;
      }
      int modifiers = clazz.getModifiers();
      if (Modifier.isAbstract(modifiers)) {
        return false;
      }
      return true;
    } catch (Throwable ignore) {
      return false;
    }
  }

  // ---------------------------------------------------------------- handlers

  /**
   * Builds action configuration on founded action class.
   * Action classes are annotated with {@link jodd.madvoc.meta.MadvocAction} annotation.
   */
  @SuppressWarnings("NonConstantStringShouldBeStringBuffer")
  protected void onActionClass(String className) throws ClassNotFoundException {
    Class<?> actionClass = loadClass(className);

    if (actionClass == null) {
      return;
    }

    if (checkClass(actionClass) == false) {
      return;
    }

    if (actionClass.getAnnotation(MadvocAction.class) == null) {
      return;
    }

    ClassDescriptor cd = ClassIntrospector.lookup(actionClass);

    MethodDescriptor[] allMethodDescriptors = cd.getAllMethodDescriptors();
    for (MethodDescriptor methodDescriptor : allMethodDescriptors) {
      if (!methodDescriptor.isPublic()) {
        continue;
      }
      // just public methods
      Method method = methodDescriptor.getMethod();

      boolean hasAnnotation = false;
      for (ActionAnnotation<?> actionAnnotation : madvocConfig.getActionAnnotationInstances()) {
        if (actionAnnotation.hasAnnotation(method)) {
          hasAnnotation = true;
          break;
        }
      }
      if (hasAnnotation == false) {
        continue;
      }
      actionsManager.register(actionClass, method);
    }
  }

  /**
   * Loads madvoc result from founded {@link jodd.madvoc.result.ActionResult} instance.
   */
  @SuppressWarnings({"unchecked"})
  protected void onResultClass(String className) throws ClassNotFoundException {
    Class resultClass = loadClass(className);

    if (resultClass == null) {
      return;
    }

    if (checkClass(resultClass) == false) {
      return;
    }
    if (ReflectUtil.isTypeOf(resultClass, ActionResult.class) == true) {
      resultsManager.register(resultClass);
    }
  }

}
TOP

Related Classes of jodd.madvoc.config.AutomagicMadvocConfigurator

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.