CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-eclipse-jetty--jetty-xml

XML-based configuration utilities for Eclipse Jetty providing IoC mechanism for component configuration.

Pending
Overview
Eval results
Files

configuration-extension.mddocs/

Configuration Extension and Customization

Extensible configuration processing system supporting custom configuration formats and processors. The library provides service provider interfaces that allow alternative configuration formats (e.g., Spring XML, YAML, JSON) to be plugged in instead of or alongside the default Jetty XML format.

Capabilities

ConfigurationProcessor Interface

Interface for implementing custom configuration processors that can handle alternative configuration formats.

/**
 * Interface for alternative configuration processors
 * Allows non-XML configuration formats to be used instead of Jetty XML
 */
interface ConfigurationProcessor {
    /**
     * Initialize processor with configuration context
     * @param resource configuration resource being processed
     * @param root root node of parsed document (may be null for non-XML formats)
     * @param configuration XmlConfiguration instance for context
     * @throws Exception if initialization fails
     */
    void init(Resource resource, XmlParser.Node root, XmlConfiguration configuration) throws Exception;
    
    /**
     * Configure existing object
     * @param obj object to configure
     * @return configured object
     * @throws Exception if configuration fails
     */
    Object configure(Object obj) throws Exception;
    
    /**
     * Create and configure new object
     * @return configured object instance
     * @throws Exception if configuration fails
     */
    Object configure() throws Exception;
}

ConfigurationProcessorFactory Interface

Service provider interface for creating configuration processors based on document characteristics.

/**
 * Factory interface for creating configuration processors
 * Implementations are discovered via ServiceLoader
 */
interface ConfigurationProcessorFactory {
    /**
     * Get processor for specific DTD and root tag combination
     * @param dtd DTD identifier (may be null if validation disabled)
     * @param tag root element tag name
     * @return configuration processor instance, or null if not supported
     */
    ConfigurationProcessor getConfigurationProcessor(String dtd, String tag);
}

BaseClassCatalog Class

Custom XML catalog implementation that supports runtime determination of base URI for entity resolution.

/**
 * XML catalog where xml:base is defined externally
 * Allows runtime determination of base URI for entity resolution
 */
class BaseClassCatalog implements Catalog, EntityResolver {
    /**
     * Factory method to load catalog from XML file
     * @param uriToCatalogXml URI to catalog XML file
     * @param baseClass base class for relative URI resolution
     * @return loaded catalog instance
     * @throws IllegalArgumentException if catalog cannot be loaded
     */
    static BaseClassCatalog load(URI uriToCatalogXml, Class<?> baseClass);
}

Catalog Interface Implementation

Standard XML catalog operations for entity resolution.

/**
 * Return stream of alternative catalogs (always empty for BaseClassCatalog)
 * @return empty stream
 */
Stream<Catalog> catalogs();

/**
 * Match public ID to system URI
 * @param publicId public identifier to match
 * @return system URI or null if no match
 */
String matchPublic(String publicId);

/**
 * Match system ID to URI
 * @param systemId system identifier to match
 * @return resolved URI or null if no match
 */
String matchSystem(String systemId);

/**
 * Match URI to identifier
 * @param uri URI to match
 * @return matched identifier or null if no match
 */
String matchURI(String uri);

EntityResolver Implementation

SAX EntityResolver implementation for custom entity resolution.

/**
 * Resolve external entity references
 * @param publicId public identifier
 * @param systemId system identifier
 * @return InputSource for resolved entity, or null for default behavior
 * @throws SAXException if resolution fails
 * @throws IOException if I/O error occurs
 */
InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException;

EnvironmentBuilder Class

Builder for creating isolated runtime environments with custom classpaths and module paths.

/**
 * Builder for Environment instances used in XML configuration
 * Supports custom classpaths and module paths
 */
class EnvironmentBuilder {
    /**
     * Create builder with environment name
     * @param name environment name
     */
    EnvironmentBuilder(@Name("name") String name);
}

Environment Configuration

Configure environment with custom paths and modules.

/**
 * Add paths to classpath
 * @param classPaths classpath entries to add
 */
void addClassPath(String... classPaths);

/**
 * Add path to module path
 * @param modulePath module path entry to add
 */
void addModulePath(String modulePath);

/**
 * Create configured Environment instance
 * @return built environment
 */
Environment build();

Usage Examples

Custom Configuration Processor

import org.eclipse.jetty.xml.ConfigurationProcessor;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.eclipse.jetty.xml.XmlParser;
import org.eclipse.jetty.util.resource.Resource;

public class JsonConfigurationProcessor implements ConfigurationProcessor {
    private Resource resource;
    private XmlConfiguration xmlConfig;
    private JsonNode configRoot;
    
    @Override
    public void init(Resource resource, XmlParser.Node root, XmlConfiguration configuration) 
            throws Exception {
        this.resource = resource;
        this.xmlConfig = configuration;
        
        // Parse JSON configuration
        ObjectMapper mapper = new ObjectMapper();
        try (InputStream in = resource.newInputStream()) {
            this.configRoot = mapper.readTree(in);
        }
    }
    
    @Override
    public Object configure() throws Exception {
        // Create object from JSON configuration
        String className = configRoot.get("class").asText();
        Class<?> clazz = Class.forName(className);
        Object instance = clazz.getDeclaredConstructor().newInstance();
        
        return configure(instance);
    }
    
    @Override
    public Object configure(Object obj) throws Exception {
        // Apply JSON configuration to object
        JsonNode properties = configRoot.get("properties");
        if (properties != null) {
            properties.fields().forEachRemaining(entry -> {
                try {
                    String name = entry.getKey();
                    String value = entry.getValue().asText();
                    
                    // Use reflection to set property
                    setProperty(obj, name, value);
                } catch (Exception e) {
                    throw new RuntimeException("Failed to set property: " + entry.getKey(), e);
                }
            });
        }
        
        return obj;
    }
    
    private void setProperty(Object obj, String name, String value) throws Exception {
        // Reflection-based property setting logic
        String setterName = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
        Method setter = obj.getClass().getMethod(setterName, String.class);
        setter.invoke(obj, value);
    }
}

Configuration Processor Factory

import org.eclipse.jetty.xml.ConfigurationProcessorFactory;
import org.eclipse.jetty.xml.ConfigurationProcessor;

public class JsonConfigurationProcessorFactory implements ConfigurationProcessorFactory {
    
    @Override
    public ConfigurationProcessor getConfigurationProcessor(String dtd, String tag) {
        // Support JSON configuration files
        if (tag != null && tag.equals("json-config")) {
            return new JsonConfigurationProcessor();
        }
        
        // Support Spring-style XML
        if (dtd != null && dtd.contains("springframework")) {
            return new SpringConfigurationProcessor();
        }
        
        return null; // Not supported
    }
}

Service Provider Registration

Create META-INF/services/org.eclipse.jetty.xml.ConfigurationProcessorFactory file:

com.example.JsonConfigurationProcessorFactory
com.example.SpringConfigurationProcessorFactory

Using Custom Catalog

import org.eclipse.jetty.xml.BaseClassCatalog;
import org.eclipse.jetty.xml.XmlParser;
import java.net.URI;

// Load custom catalog
BaseClassCatalog catalog = BaseClassCatalog.load(
    URI.create("file:///path/to/custom-catalog.xml"),
    MyClass.class
);

// Use catalog with parser
XmlParser parser = new XmlParser();
parser.addCatalog(catalog.getURI(), MyClass.class);

// Parse with custom entity resolution
XmlParser.Node root = parser.parse("config-with-entities.xml");

Environment Builder Usage

import org.eclipse.jetty.xml.EnvironmentBuilder;
import org.eclipse.jetty.util.component.Environment;

// Create isolated environment
EnvironmentBuilder builder = new EnvironmentBuilder("test-env");
builder.addClassPath("/path/to/additional/classes");
builder.addClassPath("/path/to/lib/*.jar");
builder.addModulePath("/path/to/modules");

Environment env = builder.build();

// Use environment for configuration
// (Environment usage depends on broader Jetty context)

XML Configuration with Custom Processor

Example JSON configuration file (server.json):

{
  "class": "com.example.Server",
  "properties": {
    "port": "8080",
    "host": "localhost",
    "maxThreads": "200"
  },
  "handlers": [
    {
      "class": "com.example.WebAppHandler",
      "properties": {
        "contextPath": "/",
        "resourceBase": "./webapps"
      }
    }
  ]
}

XML wrapper to invoke JSON processor:

<?xml version="1.0" encoding="UTF-8"?>
<json-config file="server.json"/>

Catalog XML Example

Custom catalog file (custom-catalog.xml):

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
  <public publicId="-//MyCompany//DTD Config//EN" 
          uri="config.dtd"/>
  <system systemId="http://example.com/schemas/config.xsd" 
          uri="schemas/config.xsd"/>
</catalog>

Extension Points

1. Configuration Formats

Support alternative configuration formats by implementing:

  • ConfigurationProcessor for format-specific processing logic
  • ConfigurationProcessorFactory for format detection and processor creation

2. Entity Resolution

Customize XML entity resolution by:

  • Creating custom Catalog implementations
  • Using BaseClassCatalog for runtime base URI determination
  • Adding catalogs to XmlParser instances

3. Environment Isolation

Create isolated runtime environments by:

  • Using EnvironmentBuilder to configure custom classpaths
  • Adding module path entries for Java 9+ module system support
  • Building environments for sandboxed configuration processing

Service Discovery

The extension system uses Java's ServiceLoader mechanism:

  1. Implement ConfigurationProcessorFactory
  2. Create service file in META-INF/services/
  3. List implementation classes in the service file
  4. Ensure classes are on classpath at runtime

The XmlConfiguration class automatically discovers and uses registered processors based on DTD and root element matching.

Best Practices

  1. DTD/Tag Matching: Use specific DTD or root tag patterns for processor selection
  2. Error Handling: Provide clear error messages for configuration failures
  3. Resource Management: Properly close resources in processor implementations
  4. Thread Safety: Ensure processor implementations are thread-safe if needed
  5. Fallback Behavior: Return null from factory if format is not supported
  6. Documentation: Document supported configuration formats and syntax

Install with Tessl CLI

npx tessl i tessl/maven-org-eclipse-jetty--jetty-xml

docs

configuration-extension.md

index.md

xml-configuration.md

xml-generation.md

xml-parser.md

tile.json