All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.anaptecs.jeaf.xfun.api.trace.TraceConfiguration Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2004 - 2019 anaptecs GmbH, Burgstr. 96, 72764 Reutlingen, Germany
 *
 * All rights reserved.
 */
package com.anaptecs.jeaf.xfun.api.trace;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Locale.Category;
import java.util.Map;

import com.anaptecs.jeaf.xfun.annotations.TraceConfig;
import com.anaptecs.jeaf.xfun.annotations.TraceObjectFormatter;
import com.anaptecs.jeaf.xfun.api.XFun;
import com.anaptecs.jeaf.xfun.api.XFunRuntimeException;
import com.anaptecs.jeaf.xfun.api.config.AnnotationBasedConfiguration;
import com.anaptecs.jeaf.xfun.api.config.ConfigurationReader;
import com.anaptecs.jeaf.xfun.bootstrap.Check;

/**
 * Class is responsible to resolve the current configuration for tracing. As all JEAf configurations also trace
 * configuration is based on annotations ({@link TraceConfig} and {@link TraceObjectFormatter}).
 * 
 * All implementations of this interface must be able to be executed in a multi-threaded environment and must provide an
 * empty public default constructor.
 */
public final class TraceConfiguration extends AnnotationBasedConfiguration implements StartupInfoWriter {
  /**
   * Only instance of this class.
   */
  private static final TraceConfiguration INSTANCE = new TraceConfiguration();

  /**
   * Map contains all trace object formatters that were configured.
   */
  private final Map, ObjectFormatter> objectFormatters = new HashMap<>();

  /**
   * Initialize object. During initialization all configuration parameters are read from the defined annotations.
   */
  private TraceConfiguration( ) {
    // Load all configuration parameters from annotations.
    this(TraceConfig.TRACE_CONFIG_RESOURCE_NAME, XFun.X_FUN_BASE_PATH, false);
  }

  /**
   * Initialize object. During initialization all configuration parameters are read from the defined annotations.
   * 
   * @param pCustomConfigurationResourceName Name of the file which contains the class name of the custom configuration
   * class. The parameter must not be null.
   * @param pBasePackagePath Path under which the file should be found in the classpath. The parameter may be null.
   * @param pExceptionOnError If parameter is set to true then an exception will be thrown in case of configuration
   * errors.
   */
  @SuppressWarnings("rawtypes")
  public TraceConfiguration( String pCustomConfigurationResourceName, String pCustomConfigurationBasePackagePath,
      boolean pExceptionOnError ) {

    // Class super class constructor.
    super(pCustomConfigurationResourceName, pCustomConfigurationBasePackagePath, pExceptionOnError);

    // Load custom trace object formatters.
    ConfigurationReader lReader = new ConfigurationReader();
    List> lObjectFormatters =
        lReader.readClassesFromConfigFile(this.objectFormattersResourcePath(), ObjectFormatter.class);

    // Create new instance of all object formatters.
    for (Class lNextClass : lObjectFormatters) {
      try {
        TraceObjectFormatter lAnnotation = lNextClass.getAnnotation(TraceObjectFormatter.class);
        for (Class lSupportedClass : lAnnotation.supportedClasses()) {
          objectFormatters.put(lSupportedClass, lNextClass.newInstance());
        }
      }
      catch (ReflectiveOperationException e) {
        throw new XFunRuntimeException("Unable to create new ObjectFormatter instance of class " + lNextClass.getName(),
            e);
      }
    }
  }

  /**
   * Method returns only instance of this class.
   * 
   * @return {@link TraceConfiguration} Only instance of this class. The method never returns null.
   */
  public static TraceConfiguration getInstance( ) {
    return INSTANCE;
  }

  @Override
  protected Class getAnnotationClass( ) {
    return TraceConfig.class;
  }

  @Override
  protected String getDefaultConfigurationClass( ) {
    return XFun.DEFAULT_CONFIGURATION_CLASS;
  }

  @Override
  public TraceConfig getEmptyConfiguration( ) {
    return new TraceConfig() {

      @Override
      public Class annotationType( ) {
        return TraceConfig.class;
      }

      @Override
      public String defaultLoggerName( ) {
        return TraceConfig.DEFAULT_LOGGER_NAME;
      }

      @Override
      public boolean traceWithSystemLocale( ) {
        return TraceConfig.TRACE_WITH_SYSTEM_LOCALE;
      }

      @Override
      public String traceMessageFormat( ) {
        return TraceConfig.DEFAULT_FORMAT;
      }

      @Override
      public boolean indentTrace( ) {
        return TraceConfig.INDENT_TRACE;
      }

      @Override
      public int indentSize( ) {
        return TraceConfig.DEFAULT_INDENT_SIZE;
      }

      @Override
      public boolean exposeLoggersViaJMX( ) {
        return true;
      }

      @Override
      public String customTraceLocale( ) {
        return TraceConfig.CUSTOM_TRACE_LOCALE;
      }

      @Override
      public boolean showCurrentUserInTraces( ) {
        return TraceConfig.SHOW_CURRENT_USER_IN_TRACES;
      }

      @Override
      public boolean useApplicationIDAsPrefix( ) {
        return TraceConfig.USE_APPLICATION_ID_AS_PREFIX;
      }

      @Override
      public String objectFormattersResourcePath( ) {
        return XFun.X_FUN_BASE_PATH + "/" + TraceConfig.TRACE_CONFIG_RESOURCE_NAME;
      }
    };
  }

  /**
   * Method checks the passed custom configuration. During check we check all params of the configuration as we assume
   * that there is not default configuration.
   * 
   * @param pCustomConfiguration
   * @return String Describing the found problems in the passed custom configuration or null if everything is fine.
   */
  @Override
  public List checkCustomConfiguration( TraceConfig pCustomConfiguration ) {
    // As the configuration just defines classes of interface implementations we just have to ensure that
    // the defined classes are real classes and not just interfaces.
    List lConfigErrors = new ArrayList<>(0);

    // Check indent size
    if (pCustomConfiguration.indentSize() < 0) {
      lConfigErrors.add("Trace indentation size must be zero or greater.");
    }

    // Check custom trace locale
    if (pCustomConfiguration.traceWithSystemLocale() == false) {
      String lLocaleString = pCustomConfiguration.customTraceLocale();
      Locale lLocale = Locale.forLanguageTag(lLocaleString);
      if (lLocale.getLanguage().isEmpty()) {
        lConfigErrors.add("Configuration contains invalid locale '" + lLocaleString + "' for tracing.");
      }
    }

    // Return result of configuration check.
    return lConfigErrors;
  }

  /**
   * @see TraceConfig#defaultLoggerName()
   */
  public String getDefaultLoggerName( ) {
    return theConfig.defaultLoggerName();
  }

  /**
   * @see TraceConfig#traceMessageFormat()
   */
  public String getTraceMessageFormat( ) {
    return theConfig.traceMessageFormat();
  }

  /**
   * @see TraceConfig#indentTrace()
   */
  public boolean isTraceIndentationEnabled( ) {
    return theConfig.indentTrace();
  }

  /**
   * @see TraceConfig#indentSize()
   */
  public int getIndentSize( ) {
    return theConfig.indentSize();
  }

  /**
   * @see TraceConfig#exposeLoggersViaJMX()
   */
  public boolean exposeLoggersViaJMX( ) {
    return theConfig.exposeLoggersViaJMX();
  }

  /**
   * @see TraceConfig#traceWithSystemLocale()
   */
  public boolean isTraceWithSystemLocaleEnabled( ) {
    return theConfig.traceWithSystemLocale();
  }

  /**
   * @see TraceConfig#customTraceLocale()
   */
  public Locale getCustomTraceLocale( ) {
    String lLocaleString = theConfig.customTraceLocale();

    // Convert string into real locale object.
    Locale lLocale = Locale.forLanguageTag(lLocaleString);

    // Ensure that locale really exists. If not we will switch to default locale
    if (lLocale.getLanguage().isEmpty() == true) {
      lLocale = Locale.getDefault(Category.DISPLAY);
    }
    return lLocale;
  }

  /**
   * @see TraceConfig#showCurrentUserInTraces()
   */
  public boolean showCurrentUserInTraces( ) {
    return theConfig.showCurrentUserInTraces();
  }

  /**
   * @see TraceConfig#useApplicationIDAsPrefix()
   */
  public boolean useApplicationIDAsPrefix( ) {
    return theConfig.useApplicationIDAsPrefix();
  }

  /**
   * @see TraceConfig#objectFormattersResourcePath()
   */
  public String objectFormattersResourcePath( ) {
    return theConfig.objectFormattersResourcePath();
  }

  /**
   * Method returns the object formatter for the passed class. If no formatter is defined for the class itself then we
   * recursively check for its super classes.
   * 
   * @param pType Class for which an object formatter should be returned. The parameter must not be null.
   * @return {@link ObjectFormatter} for the passed class or null if none could be found.
   */
  @SuppressWarnings("rawtypes")
  public ObjectFormatter getObjectFormatter( Class pType ) {
    // Check parameter
    Check.checkInvalidParameterNull(pType, "pType");

    ObjectFormatter lFormatter = objectFormatters.get(pType);
    // No formatter found for passed class. May be we found one for its base class.
    if (lFormatter == null) {
      // Resolve super class
      Class lSuperclass = pType.getSuperclass();
      if (lSuperclass != null) {
        lFormatter = this.getObjectFormatter(lSuperclass);
      }
      // We are at the very top of the class hierarchy
      else {
        lFormatter = null;
      }
    }
    return lFormatter;
  }

  @Override
  public Class getStartupCompletedEventSource( ) {
    return XFun.class;
  }

  @Override
  public void traceStartupInfo( Trace pTrace, TraceLevel pTraceLevel ) {
    pTrace.writeInitInfo("JEAF X-Fun uses the following trace configuration:", pTraceLevel);
    pTrace.info("Default Logger name:      " + this.getDefaultLoggerName());
    pTrace.info("Indentation enabled:      " + this.isTraceIndentationEnabled());
    pTrace.info("Trace message format:     " + this.getTraceMessageFormat());
    pTrace.info("Trace indentation size:   " + this.getIndentSize());
    pTrace.info("Trace with system locale: " + this.isTraceWithSystemLocaleEnabled());
    pTrace.info("Show current user:        " + this.showCurrentUserInTraces());
    pTrace.info("Custom trace locale:      " + this.getCustomTraceLocale());
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy