CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-ch-qos-logback--logback-core

Core infrastructure and basic components for the Logback logging framework, providing appenders, encoders, layouts, filters, and event processing pipeline

Pending
Overview
Eval results
Files

model-framework.mddocs/

Model Framework

Configuration model system that provides hierarchical representation of logback components with processing, state tracking, serialization support, and integration with the Joran configuration framework. The Model framework serves as the bridge between XML configuration and component instantiation.

Capabilities

Core Model Architecture

Model Base Class

The foundational class representing configuration components in a hierarchical structure.

/**
 * Base class for all configuration models in the logback framework.
 * Provides hierarchical structure, processing state, and serialization support.
 */
public class Model implements Serializable {
    /**
     * Get the line number where this model was defined in configuration.
     * @return line number in source configuration
     */
    public int getLineNumber();
    
    /**
     * Set the line number for this model.
     * @param lineNumber line number in source configuration
     */
    public void setLineNumber(int lineNumber);
    
    /**
     * Get the parent model in the hierarchy.
     * @return parent model or null if this is root
     */
    public Model getParent();
    
    /**
     * Set the parent model.
     * @param parent parent model
     */
    public void setParent(Model parent);
    
    /**
     * Add a child model to this model.
     * @param child child model to add
     */
    public void addSubModel(Model child);
    
    /**
     * Get all child models.
     * @return list of child models
     */
    public List<Model> getSubModels();
    
    /**
     * Get processing state for this model.
     * @return true if model has been processed
     */
    public boolean isProcessed();
    
    /**
     * Mark this model as processed.
     * @param processed processing state
     */
    public void setProcessed(boolean processed);
    
    /**
     * Get the tag name associated with this model.
     * @return XML tag name
     */
    public String getTag();
    
    /**
     * Set the tag name for this model.
     * @param tag XML tag name
     */
    public void setTag(String tag);
    
    /**
     * Get the body text content of this model.
     * @return body text or null
     */
    public String getBodyText();
    
    /**
     * Set the body text content.
     * @param bodyText text content
     */
    public void setBodyText(String bodyText);
    
    /**
     * Check if this model has been marked.
     * Used for processing control and cycle detection.
     * @return true if marked
     */
    public boolean isMarked();
    
    /**
     * Mark this model for processing control.
     * @param marked marking state
     */
    public void setMarked(boolean marked);
}

Component Model Hierarchy

ComponentModel

Base class for models representing configurable components.

/**
 * Model for configurable components with class name and property support.
 */
public class ComponentModel extends Model {
    /**
     * Get the component class name.
     * @return fully qualified class name
     */
    public String getClassName();
    
    /**
     * Set the component class name.
     * @param className fully qualified class name
     */
    public void setClassName(String className);
    
    /**
     * Get the component class object.
     * @return Class object or null
     */
    public Class<?> getClazz();
    
    /**
     * Set the component class object.
     * @param clazz Class object
     */
    public void setClazz(Class<?> clazz);
}

NamedComponentModel

Model for components that have names (like appenders, filters).

/**
 * Model for named components like appenders and filters.
 */
public class NamedComponentModel extends ComponentModel implements INamedModel {
    /**
     * Get the component name.
     * @return component name
     */
    public String getName();
    
    /**
     * Set the component name.
     * @param name component name
     */
    public void setName(String name);
}

INamedModel Interface

Interface for models that have names.

/**
 * Interface for models that can be identified by name.
 */
public interface INamedModel {
    /**
     * Get the model name.
     * @return model name
     */
    String getName();
    
    /**
     * Set the model name.
     * @param name model name
     */
    void setName(String name);
}

Configuration Models

AppenderModel

Model representing appender configuration.

/**
 * Model for appender configuration with encoder and filter support.
 */
public class AppenderModel extends NamedComponentModel {
    /**
     * Get the encoder model.
     * @return encoder model or null
     */
    public EncoderModel getEncoder();
    
    /**
     * Set the encoder model.
     * @param encoder encoder model
     */
    public void setEncoder(EncoderModel encoder);
    
    /**
     * Get all filter models.
     * @return list of filter models
     */
    public List<FilterModel> getFilterModels();
    
    /**
     * Add a filter model.
     * @param filterModel filter model to add
     */
    public void addFilterModel(FilterModel filterModel);
}

PropertyModel

Model for property definitions and references.

/**
 * Model for property definitions with name, value, and scope.
 */
public class PropertyModel extends Model {
    /**
     * Get the property name.
     * @return property name
     */
    public String getName();
    
    /**
     * Set the property name.
     * @param name property name
     */
    public void setName(String name);
    
    /**
     * Get the property value.
     * @return property value
     */
    public String getValue();
    
    /**
     * Set the property value.
     * @param value property value
     */
    public void setValue(String value);
    
    /**
     * Get the property scope.
     * @return property scope (context, system, local)
     */
    public String getScope();
    
    /**
     * Set the property scope.
     * @param scope property scope
     */
    public void setScope(String scope);
    
    /**
     * Get the source for property value.
     * @return source reference (file, resource, url)
     */
    public String getSource();
    
    /**
     * Set the source for property value.
     * @param source source reference
     */
    public void setSource(String source);
}

ConditionalModel

Model for conditional configuration logic.

/**
 * Model for conditional configuration based on properties or expressions.
 */
public class ConditionalModel extends Model {
    /**
     * Get the condition expression.
     * @return condition expression
     */
    public String getCondition();
    
    /**
     * Set the condition expression.
     * @param condition condition to evaluate
     */
    public void setCondition(String condition);
    
    /**
     * Get the then models (executed if condition is true).
     * @return list of then models
     */
    public List<Model> getThenModels();
    
    /**
     * Add a model to the then branch.
     * @param model model to add
     */
    public void addThenModel(Model model);
    
    /**
     * Get the else models (executed if condition is false).
     * @return list of else models
     */
    public List<Model> getElseModels();
    
    /**
     * Add a model to the else branch.
     * @param model model to add
     */
    public void addElseModel(Model model);
}

Model Processing Framework

ModelHandlerBase

Base class for model handlers that process specific model types.

/**
 * Base class for handlers that process specific model types.
 * Provides context access and common processing utilities.
 */
public abstract class ModelHandlerBase extends ContextAwareBase {
    protected ModelInterpretationContext mic;
    
    /**
     * Check if this handler can handle the given model.
     * @param model model to check
     * @return true if this handler can process the model
     */
    public abstract boolean isSuitableForModel(Model model);
    
    /**
     * Handle the model processing.
     * @param mic model interpretation context
     * @param model model to process
     * @throws ModelHandlerException if processing fails
     */
    public abstract void handle(ModelInterpretationContext mic, Model model) 
        throws ModelHandlerException;
    
    /**
     * Post-handle processing after all children are processed.
     * @param mic model interpretation context
     * @param model model being processed
     * @throws ModelHandlerException if post-processing fails
     */
    public void postHandle(ModelInterpretationContext mic, Model model) 
        throws ModelHandlerException;
}

ModelInterpretationContext

Context for model processing providing access to objects, properties, and processing state.

/**
 * Context for model interpretation providing access to processing state.
 */
public class ModelInterpretationContext extends ContextAwareBase {
    /**
     * Get an object by key.
     * @param key object key
     * @return stored object or null
     */
    public Object getObject(String key);
    
    /**
     * Store an object by key.
     * @param key object key
     * @param value object to store
     */
    public void putObject(String key, Object value);
    
    /**
     * Push an object onto the processing stack.
     * @param obj object to push
     */
    public void pushObject(Object obj);
    
    /**
     * Pop an object from the processing stack.
     * @return popped object
     */
    public Object popObject();
    
    /**
     * Peek at the top object on the stack.
     * @return top object without removing it
     */
    public Object peekObject();
    
    /**
     * Check if the stack is empty.
     * @return true if stack is empty
     */
    public boolean isObjectStackEmpty();
    
    /**
     * Get property value with variable substitution.
     * @param key property key
     * @return property value with substitutions applied
     */
    public String getProperty(String key);
    
    /**
     * Substitute variables in the given value.
     * @param value value with potential variables
     * @return value with variables substituted
     */
    public String subst(String value);
    
    /**
     * Get the dependency analyzer for tracking component dependencies.
     * @return dependency analyzer
     */
    public DependencyAnalyzer getDependencyAnalyzer();
}

ModelHandlerException

Exception thrown during model processing.

/**
 * Exception thrown when model processing fails.
 */
public class ModelHandlerException extends Exception {
    /**
     * Create exception with message.
     * @param msg error message
     */
    public ModelHandlerException(String msg);
    
    /**
     * Create exception with message and cause.
     * @param msg error message
     * @param cause underlying cause
     */
    public ModelHandlerException(String msg, Throwable cause);
}

DefaultProcessor

Main processor that orchestrates model processing through registered handlers.

/**
 * Default processor that handles model processing through registered handlers.
 */
public class DefaultProcessor extends ContextAwareBase {
    /**
     * Add a model handler.
     * @param modelHandler handler to add
     */
    public void addHandler(ModelHandlerBase modelHandler);
    
    /**
     * Process a model and its children.
     * @param mic model interpretation context
     * @param model model to process
     * @throws ModelHandlerException if processing fails
     */
    public void process(ModelInterpretationContext mic, Model model) 
        throws ModelHandlerException;
    
    /**
     * Find a suitable handler for the given model.
     * @param model model to find handler for
     * @return suitable handler or null
     */
    protected ModelHandlerBase getSuitableModelHandler(Model model);
}

Integration with Joran

BaseModelAction

Base action class that bridges SAX parsing and model creation.

/**
 * Base action for creating models from SAX events.
 */
public abstract class BaseModelAction extends Action {
    /**
     * Create a model instance for the current element.
     * @param ic interpretation context
     * @param localName element local name
     * @param attributes element attributes
     * @return created model instance
     */
    protected abstract Model buildCurrentModel(InterpretationContext ic, 
        String localName, Attributes attributes);
    
    /**
     * Build model from SAX start element.
     * @param ic interpretation context
     * @param localName element local name
     * @param attributes element attributes
     */
    @Override
    public void begin(InterpretationContext ic, String localName, 
        Attributes attributes) throws ActionException;
    
    /**
     * Set body text on the model.
     * @param ic interpretation context
     * @param body element body text
     */
    @Override
    public void body(InterpretationContext ic, String body) 
        throws ActionException;
    
    /**
     * Finalize model creation.
     * @param ic interpretation context
     * @param localName element local name
     */
    @Override
    public void end(InterpretationContext ic, String localName) 
        throws ActionException;
}

Utility Classes

ModelUtil

Utility methods for model processing and manipulation.

/**
 * Utility methods for model processing.
 */
public class ModelUtil {
    /**
     * Deep clone a model hierarchy.
     * @param model model to clone
     * @return cloned model
     */
    public static Model deepClone(Model model);
    
    /**
     * Find models of a specific type in the hierarchy.
     * @param root root model to search from
     * @param modelClass class of models to find
     * @return list of matching models
     */
    public static <T extends Model> List<T> findModelsOfType(Model root, 
        Class<T> modelClass);
    
    /**
     * Substitute variables in all string properties of a model.
     * @param mic model interpretation context
     * @param model model to process
     */
    public static void substituteVariables(ModelInterpretationContext mic, 
        Model model);
    
    /**
     * Reset processing state for a model hierarchy.
     * @param model root model to reset
     */
    public static void resetProcessingState(Model model);
}

Usage Examples

Creating a Custom Model

import ch.qos.logback.core.model.ComponentModel;
import ch.qos.logback.core.model.INamedModel;

public class CustomFilterModel extends ComponentModel implements INamedModel {
    private String name;
    private String pattern;
    private boolean caseSensitive = true;
    
    @Override
    public String getName() {
        return name;
    }
    
    @Override
    public void setName(String name) {
        this.name = name;
    }
    
    public String getPattern() {
        return pattern;
    }
    
    public void setPattern(String pattern) {
        this.pattern = pattern;
    }
    
    public boolean isCaseSensitive() {
        return caseSensitive;
    }
    
    public void setCaseSensitive(boolean caseSensitive) {
        this.caseSensitive = caseSensitive;
    }
}

Creating a Custom Model Handler

import ch.qos.logback.core.model.processor.ModelHandlerBase;
import ch.qos.logback.core.model.processor.ModelInterpretationContext;
import ch.qos.logback.core.model.processor.ModelHandlerException;

public class CustomFilterModelHandler extends ModelHandlerBase {
    
    @Override
    public boolean isSuitableForModel(Model model) {
        return model instanceof CustomFilterModel;
    }
    
    @Override
    public void handle(ModelInterpretationContext mic, Model model) 
            throws ModelHandlerException {
        CustomFilterModel cfm = (CustomFilterModel) model;
        
        // Create the actual filter instance
        CustomFilter filter = new CustomFilter();
        filter.setContext(context);
        filter.setName(cfm.getName());
        filter.setPattern(cfm.getPattern());
        filter.setCaseSensitive(cfm.isCaseSensitive());
        
        // Validate configuration
        if (cfm.getPattern() == null) {
            addError("Pattern is required for CustomFilter");
            return;
        }
        
        // Store in context for reference by other components
        if (cfm.getName() != null) {
            mic.putObject(cfm.getName(), filter);
        }
        
        // Add to parent component if applicable
        Object parent = mic.peekObject();
        if (parent instanceof FilterAttachable) {
            ((FilterAttachable<?>) parent).addFilter(filter);
        }
        
        filter.start();
    }
}

Using the Default Processor

import ch.qos.logback.core.model.processor.DefaultProcessor;
import ch.qos.logback.core.model.processor.ModelInterpretationContext;

// Create processor and register handlers
DefaultProcessor processor = new DefaultProcessor();
processor.setContext(context);

// Add standard handlers
processor.addHandler(new AppenderModelHandler());
processor.addHandler(new FilterModelHandler());
processor.addHandler(new CustomFilterModelHandler());

// Create interpretation context
ModelInterpretationContext mic = new ModelInterpretationContext(context);

// Process model hierarchy
try {
    processor.process(mic, rootModel);
} catch (ModelHandlerException e) {
    addError("Failed to process model", e);
}

Model-based Configuration Action

import ch.qos.logback.core.joran.action.BaseModelAction;
import ch.qos.logback.core.joran.spi.InterpretationContext;

public class CustomFilterAction extends BaseModelAction {
    
    @Override
    protected Model buildCurrentModel(InterpretationContext ic, 
            String localName, Attributes attributes) {
        CustomFilterModel model = new CustomFilterModel();
        model.setTag(localName);
        
        // Set properties from attributes
        String name = attributes.getValue("name");
        if (name != null) {
            model.setName(name);
        }
        
        String className = attributes.getValue("class");
        if (className != null) {
            model.setClassName(className);
        }
        
        String pattern = attributes.getValue("pattern");
        if (pattern != null) {
            model.setPattern(pattern);
        }
        
        String caseSensitive = attributes.getValue("caseSensitive");
        if (caseSensitive != null) {
            model.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
        }
        
        return model;
    }
}

Model Processing Phases

The Model framework processes configuration in distinct phases:

  1. Model Creation: SAX events are converted to model objects through actions
  2. Model Assembly: Models are arranged in hierarchical structure
  3. Model Processing: Handlers process models to create actual component instances
  4. Component Configuration: Created components are configured and started
  5. Dependency Resolution: Component dependencies are resolved and injected

This separation enables sophisticated configuration processing, validation, and component lifecycle management while maintaining clean separation between parsing and instantiation concerns.

Integration Patterns

The Model framework integrates with other logback-core components:

  • Joran Configuration: Actions create models from XML elements
  • Component Factory: Handlers instantiate and configure components
  • Context Management: Models store component references in context
  • Property Substitution: Variable substitution occurs during model processing
  • Conditional Logic: Models support conditional configuration sections
  • Error Handling: Processing errors are reported through context status system

Install with Tessl CLI

npx tessl i tessl/maven-ch-qos-logback--logback-core

docs

appenders.md

configuration.md

encoders-layouts.md

filters-evaluators.md

index.md

model-framework.md

network-logging.md

patterns.md

rolling-policies.md

utilities.md

tile.json