CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-opensearch--opensearch

OpenSearch is a distributed, RESTful search and analytics engine built as a community-driven fork of Elasticsearch.

Pending
Overview
Eval results
Files

plugin-framework.mddocs/

Plugin Framework

Extensible plugin system for adding custom functionality including actions, search components, analysis, and storage engines. OpenSearch provides comprehensive extension points throughout the system for building custom plugins and integrations.

Capabilities

Core Plugin System

Base plugin architecture and lifecycle management for extending OpenSearch functionality.

/**
 * Base plugin class providing extension points for all OpenSearch functionality
 */
abstract class Plugin implements Closeable {
    /**
     * Get plugin description information
     */
    String getDescription();
    
    /**
     * Create Guice modules for dependency injection
     * @return Collection of Guice modules to register
     */
    Collection<Module> createGuiceModules();
    
    /**
     * Provide additional settings that should be added to the cluster
     * @return Settings to add to cluster configuration
     */
    Settings additionalSettings();
    
    /**
     * Get list of setting definitions for this plugin
     * @return List of setting definitions
     */
    List<Setting<?>> getSettings();
    
    /**
     * Get list of settings that require keystore access
     * @return List of secure setting definitions
     */
    List<Setting<?>> getSecureSettings();
    
    /**
     * Called when plugin is closed during shutdown
     */
    void close() throws IOException;
    
    /**
     * Get plugin classloader for loading plugin resources
     */
    ClassLoader getPluginClassLoader();
}

/**
 * Plugin information container with metadata and dependencies
 */
class PluginInfo implements Streamable {
    /**
     * Create plugin info
     * @param name Plugin name
     * @param description Plugin description
     * @param version Plugin version
     * @param classname Main plugin class name
     * @param hasNativeController Whether plugin has native controller
     */
    PluginInfo(String name, String description, String version, String classname, 
               boolean hasNativeController);
    
    /**
     * Get plugin name
     */
    String getName();
    
    /**
     * Get plugin description
     */
    String getDescription();
    
    /**
     * Get plugin version
     */
    String getVersion();
    
    /**
     * Get main plugin class name
     */
    String getClassname();
    
    /**
     * Check if plugin has native controller
     */
    boolean hasNativeController();
    
    /**
     * Get OpenSearch version compatibility
     */
    String getOpenSearchVersion();
    
    /**
     * Get Java version requirement
     */
    String getJavaVersion();
}

/**
 * Service for managing plugin lifecycle and registration
 */
class PluginsService {
    /**
     * Create plugins service with configuration
     * @param settings OpenSearch settings
     * @param modulesDirectory Modules directory path
     * @param pluginsDirectory Plugins directory path
     * @param classpathPlugins Classpath plugin classes
     */
    PluginsService(Settings settings, Path modulesDirectory, Path pluginsDirectory, 
                   Collection<Class<? extends Plugin>> classpathPlugins);
    
    /**
     * Get all loaded plugins
     */
    List<Tuple<PluginInfo, Plugin>> plugins();
    
    /**
     * Get plugins filtered by type
     * @param type Plugin interface class
     */
    <T> List<T> filterPlugins(Class<T> type);
    
    /**
     * Get plugin info by name
     * @param name Plugin name
     */
    PluginInfo getPluginInfo(String name);
    
    /**
     * Check if plugin is loaded
     * @param name Plugin name
     */
    boolean isPluginLoaded(String name);
}

Action Plugin Interface

Plugin interface for adding custom actions and REST endpoints to OpenSearch.

/**
 * Plugin interface for providing custom actions and REST handlers
 */
interface ActionPlugin {
    /**
     * Get list of action handlers provided by this plugin
     * @return List of action handler registrations
     */
    List<ActionHandler<? extends ActionRequest, ? extends ActionResponse>> getActions();
    
    /**
     * Get list of REST handlers provided by this plugin
     * @param settings Cluster settings
     * @param restController REST controller for registration
     * @param clusterSettings Cluster settings manager
     * @param indexScopedSettings Index-scoped settings manager
     * @param settingsFilter Settings filter for security
     * @param indexNameExpressionResolver Index name pattern resolver
     * @param nodesInCluster Supplier for cluster nodes information
     * @return List of REST handler implementations
     */
    List<RestHandler> getRestHandlers(Settings settings, RestController restController,
        ClusterSettings clusterSettings, IndexScopedSettings indexScopedSettings,
        SettingsFilter settingsFilter, IndexNameExpressionResolver indexNameExpressionResolver,
        Supplier<DiscoveryNodes> nodesInCluster);
    
    /**
     * Get list of action filters for intercepting requests
     * @return List of action filter implementations
     */
    default List<ActionFilter> getActionFilters() {
        return Collections.emptyList();
    }
    
    /**
     * Get list of task headers that should be preserved across requests
     * @return Collection of header names to preserve
     */
    default Collection<String> getTaskHeaders() {
        return Collections.emptyList();
    }
}

/**
 * Registration container for action handlers
 */
class ActionHandler<Request extends ActionRequest, Response extends ActionResponse> {
    /**
     * Create action handler registration
     * @param action Action type definition
     * @param transportAction Transport action implementation class
     */
    ActionHandler(ActionType<Response> action, 
                  Class<? extends TransportAction<Request, Response>> transportAction);
    
    /**
     * Create action handler with support actions
     * @param action Action type definition
     * @param transportAction Transport action implementation class
     * @param supportTransportActions Additional support action classes
     */
    ActionHandler(ActionType<Response> action,
                  Class<? extends TransportAction<Request, Response>> transportAction,
                  Class<?>... supportTransportActions);
    
    /**
     * Get action type
     */
    ActionType<Response> getAction();
    
    /**
     * Get transport action class
     */
    Class<? extends TransportAction<Request, Response>> getTransportAction();
    
    /**
     * Get support transport action classes
     */
    Class<?>[] getSupportTransportActions();
}

/**
 * Base class for REST request handlers
 */
abstract class BaseRestHandler implements RestHandler {
    /**
     * Get routes supported by this handler
     * @return List of route definitions
     */
    abstract List<Route> routes();
    
    /**
     * Handle REST request
     * @param request REST request
     * @param channel Response channel
     * @param client OpenSearch client
     */
    abstract RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) 
        throws IOException;
    
    /**
     * Check if request can be handled without content
     */
    protected boolean canTripCircuitBreaker() {
        return true;
    }
    
    /**
     * Check if handler supports working with content streams
     */
    protected boolean supportsContentStream() {
        return false;
    }
}

Search Plugin Interface

Plugin interface for extending search functionality with custom queries, aggregations, and processors.

/**
 * Plugin interface for extending search functionality
 */
interface SearchPlugin {
    /**
     * Get custom query builders provided by this plugin
     * @return List of query builder registrations
     */
    default List<QuerySpec<?>> getQueries() {
        return Collections.emptyList();
    }
    
    /**
     * Get custom aggregation builders provided by this plugin
     * @return List of aggregation builder registrations
     */
    default List<AggregationSpec> getAggregations() {
        return Collections.emptyList();
    }
    
    /**
     * Get custom pipeline aggregations provided by this plugin
     * @return List of pipeline aggregation registrations
     */
    default List<PipelineAggregationSpec> getPipelineAggregations() {
        return Collections.emptyList();
    }
    
    /**
     * Get custom function score functions provided by this plugin
     * @return List of score function registrations
     */
    default List<ScoreFunctionSpec<?>> getScoreFunctions() {
        return Collections.emptyList();
    }
    
    /**
     * Get custom significance heuristics provided by this plugin
     * @return List of significance heuristic registrations
     */
    default List<SignificanceHeuristicSpec<?>> getSignificanceHeuristics() {
        return Collections.emptyList();
    }
    
    /**
     * Get custom MovAvg models provided by this plugin
     * @return List of moving average model registrations
     */
    default List<MovAvgModelSpec> getMovingAverageModels() {
        return Collections.emptyList();
    }
    
    /**
     * Get custom fetch sub-phases provided by this plugin
     * @return List of fetch sub-phase implementations
     */
    default List<FetchSubPhase> getFetchSubPhases(FetchPhaseConstructionContext context) {
        return Collections.emptyList();
    }
    
    /**
     * Get custom search extensions provided by this plugin
     * @return List of search extension implementations
     */
    default List<SearchExtension> getSearchExtensions() {
        return Collections.emptyList();
    }
}

/**
 * Query builder specification for plugin registration
 */
class QuerySpec<T extends QueryBuilder> implements NamedWriteable.Entry<QueryBuilder> {
    /**
     * Create query spec
     * @param name Query name for parsing
     * @param reader Reader function for deserialization
     * @param parser Parser function for XContent parsing
     */
    QuerySpec(String name, Writeable.Reader<T> reader, CheckedFunction<XContentParser, T, IOException> parser);
    
    /**
     * Get query name
     */
    String getName();
    
    /**
     * Get query class
     */
    Class<T> getQueryClass();
}

/**
 * Aggregation specification for plugin registration
 */
class AggregationSpec implements NamedWriteable.Entry<AggregationBuilder> {
    /**
     * Create aggregation spec
     * @param name Aggregation name
     * @param reader Reader function for deserialization
     * @param parser Parser function for XContent parsing
     */
    AggregationSpec(String name, Writeable.Reader<? extends AggregationBuilder> reader,
        AggregationParser parser);
    
    /**
     * Get aggregation name
     */
    String getName();
    
    /**
     * Get aggregation builder class
     */
    Class<? extends AggregationBuilder> getBuilderClass();
}

Analysis Plugin Interface

Plugin interface for providing custom text analysis components including analyzers, tokenizers, and filters.

/**
 * Plugin interface for providing text analysis components
 */
interface AnalysisPlugin {
    /**
     * Get custom analyzers provided by this plugin
     * @return Map of analyzer name to analyzer provider
     */
    default Map<String, AnalysisProvider<AnalyzerProvider<? extends Analyzer>>> getAnalyzers() {
        return Collections.emptyMap();
    }
    
    /**
     * Get custom character filters provided by this plugin
     * @return Map of char filter name to char filter provider
     */
    default Map<String, AnalysisProvider<CharFilterFactory>> getCharFilters() {
        return Collections.emptyMap();
    }
    
    /**
     * Get custom tokenizers provided by this plugin
     * @return Map of tokenizer name to tokenizer provider
     */
    default Map<String, AnalysisProvider<TokenizerFactory>> getTokenizers() {
        return Collections.emptyMap();
    }
    
    /**
     * Get custom token filters provided by this plugin
     * @return Map of token filter name to token filter provider
     */
    default Map<String, AnalysisProvider<TokenFilterFactory>> getTokenFilters() {
        return Collections.emptyMap();
    }
    
    /**
     * Get custom hunspell dictionaries provided by this plugin
     * @return Map of language to hunspell dictionary
     */
    default Map<String, Dictionary> getHunspellDictionaries() {
        return Collections.emptyMap();
    }
    
    /**
     * Get custom normalizers provided by this plugin
     * @return Map of normalizer name to normalizer provider
     */
    default Map<String, AnalysisProvider<AnalyzerProvider<? extends Analyzer>>> getNormalizers() {
        return Collections.emptyMap();
    }
}

/**
 * Provider interface for analysis components
 */
interface AnalysisProvider<T> {
    /**
     * Create analysis component instance
     * @param indexSettings Index settings context
     * @param environment Plugin environment
     * @param name Component name
     * @param settings Component settings
     */
    T get(IndexSettings indexSettings, Environment environment, String name, Settings settings);
}

/**
 * Factory interface for creating analyzers
 */
interface AnalyzerProvider<T extends Analyzer> extends Closeable {
    /**
     * Get analyzer instance
     */
    T get();
    
    /**
     * Close analyzer and release resources
     */
    void close();
}

/**
 * Factory interface for creating character filters
 */
interface CharFilterFactory {
    /**
     * Get character filter name
     */
    String name();
    
    /**
     * Create character filter reader
     * @param reader Input character reader
     */
    Reader create(Reader reader);
}

/**
 * Factory interface for creating tokenizers
 */
interface TokenizerFactory {
    /**
     * Create tokenizer instance
     */
    Tokenizer create();
}

/**
 * Factory interface for creating token filters
 */
interface TokenFilterFactory {
    /**
     * Create token filter instance
     * @param tokenStream Input token stream
     */
    TokenStream create(TokenStream tokenStream);
}

Mapper Plugin Interface

Plugin interface for providing custom field mappers and data type support.

/**
 * Plugin interface for providing custom field mappers
 */
interface MapperPlugin {
    /**
     * Get custom field mappers provided by this plugin
     * @return Map of type name to mapper parser
     */
    Map<String, Mapper.TypeParser> getMappers();
    
    /**
     * Get custom metadata mappers provided by this plugin
     * @return Map of name to metadata mapper parser
     */
    default Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
        return Collections.emptyMap();
    }
    
    /**
     * Get custom field filter provided by this plugin
     * @return Field filter implementation
     */
    default Function<String, Predicate<String>> getFieldFilter() {
        return MapperPlugin.NOOP_FIELD_FILTER;
    }
    
    /**
     * No-op field filter that allows all fields
     */
    Function<String, Predicate<String>> NOOP_FIELD_FILTER = index -> field -> true;
}

/**
 * Base mapper for field mapping implementations
 */
abstract class Mapper implements Streamable {
    /**
     * Get mapper name
     */
    String name();
    
    /**
     * Get mapper type name
     */
    abstract String typeName();
    
    /**
     * Merge with another mapper
     * @param mergeWith Mapper to merge with
     * @param mergeReason Reason for merge operation
     */
    abstract Mapper merge(Mapper mergeWith, MergeReason mergeReason);
    
    /**
     * Validate field mapping configuration
     * @param indexSettings Index settings context
     */
    abstract void validate(MappingLookup mappers, IndexSettings indexSettings);
    
    /**
     * Type parser interface for creating mapper instances
     */
    interface TypeParser {
        /**
         * Parse mapper configuration and create mapper builder
         * @param name Field name
         * @param node Mapping configuration
         * @param parserContext Parser context
         */
        Builder parse(String name, Map<String, Object> node, ParserContext parserContext)
            throws MapperParsingException;
    }
    
    /**
     * Builder interface for constructing mappers
     */
    abstract static class Builder {
        /**
         * Build mapper instance
         * @param context Build context
         */
        abstract Mapper build(ContentPath contentPath, MapperBuilderContext context);
    }
}

Ingest Plugin Interface

Plugin interface for providing custom ingest processors for document processing pipelines.

/**
 * Plugin interface for providing custom ingest processors
 */
interface IngestPlugin {
    /**
     * Get custom processors provided by this plugin
     * @param processorFactories Existing processor factories
     * @return Map of processor name to processor factory
     */
    Map<String, Processor.Factory> getProcessors(Processor.Parameters processorFactories);
    
    /**
     * Get additional ingest capabilities provided by this plugin
     * @return List of ingest capability extensions
     */
    default List<IngestCapability> getIngestCapabilities() {
        return Collections.emptyList();
    }
}

/**
 * Base processor interface for document processing in ingest pipelines
 */
interface Processor {
    /**
     * Get processor type name
     */
    String getType();
    
    /**
     * Get processor tag for identification
     */
    String getTag();
    
    /**
     * Get processor description
     */
    String getDescription();
    
    /**
     * Execute processor on ingest document
     * @param ingestDocument Document to process
     * @return Processed ingest document
     */
    IngestDocument execute(IngestDocument ingestDocument) throws Exception;
    
    /**
     * Factory interface for creating processor instances
     */
    interface Factory {
        /**
         * Create processor instance
         * @param processorFactories Available processor factories
         * @param tag Processor tag
         * @param description Processor description
         * @param config Processor configuration
         */
        Processor create(Map<String, Factory> processorFactories, String tag, 
                        String description, Map<String, Object> config) throws Exception;
    }
    
    /**
     * Parameters container for processor factory access
     */
    class Parameters {
        /**
         * Get environment configuration
         */
        public Environment env;
        
        /**
         * Get script service for script processors
         */
        public ScriptService scriptService;
        
        /**
         * Get analysis registry for text analysis
         */
        public AnalysisRegistry analysisRegistry;
        
        /**
         * Get thread pool for async operations
         */
        public ThreadPool threadPool;
        
        /**
         * Get ingest service reference
         */
        public IngestService ingestService;
    }
}

/**
 * Abstract base class for simple processor implementations
 */
abstract class AbstractProcessor implements Processor {
    /**
     * Create abstract processor
     * @param tag Processor tag
     * @param description Processor description
     */
    protected AbstractProcessor(String tag, String description);
    
    /**
     * Get processor tag
     */
    String getTag();
    
    /**
     * Get processor description
     */
    String getDescription();
}

Repository Plugin Interface

Plugin interface for providing custom snapshot repository implementations.

/**
 * Plugin interface for providing custom snapshot repositories
 */
interface RepositoryPlugin {
    /**
     * Get custom repository types provided by this plugin
     * @return Map of repository type to repository factory
     */
    Map<String, Repository.Factory> getRepositories(Environment env, NamedXContentRegistry namedXContentRegistry,
        ClusterService clusterService, BigArrays bigArrays, RecoverySettings recoverySettings);
    
    /**
     * Get custom repository cleanup extensions
     * @return Map of repository type to cleanup extensions
     */
    default Map<String, Repository.Factory> getInternalRepositories(Environment env, 
        NamedXContentRegistry namedXContentRegistry, ClusterService clusterService,
        RecoverySettings recoverySettings) {
        return Collections.emptyMap();
    }
}

/**
 * Base repository interface for snapshot storage implementations
 */
interface Repository extends Closeable {
    /**
     * Get repository metadata
     */
    RepositoryMetadata getMetadata();
    
    /**
     * Initialize repository with cluster state
     * @param clusterState Current cluster state
     */
    void initializeSnapshot(SnapshotId snapshotId, List<IndexId> indices, Metadata metadata);
    
    /**
     * Finalize snapshot creation
     * @param finalizeContext Snapshot finalization context
     */
    SnapshotInfo finalizeSnapshot(FinalizeSnapshotContext finalizeContext);
    
    /**
     * Delete snapshot from repository
     * @param snapshotId Snapshot to delete
     * @param repositoryStateId Repository state version
     * @param writeShardGens Whether to write shard generation files
     * @param listener Completion callback
     */
    void deleteSnapshots(Collection<SnapshotId> snapshotIds, long repositoryStateId,
        boolean writeShardGens, ActionListener<RepositoryData> listener);
    
    /**
     * Factory interface for creating repository instances
     */
    interface Factory {
        /**
         * Create repository instance
         * @param metadata Repository metadata configuration
         */
        Repository create(RepositoryMetadata metadata) throws Exception;
        
        /**
         * Create repository instance with recovery settings
         * @param metadata Repository metadata configuration
         * @param typeLookup Type lookup for deserialization
         */
        Repository create(RepositoryMetadata metadata, Function<String, Repository.Factory> typeLookup) 
            throws Exception;
    }
}

Usage Examples

Creating a Custom Action Plugin

import org.opensearch.plugins.ActionPlugin;
import org.opensearch.plugins.Plugin;
import org.opensearch.rest.BaseRestHandler;
import org.opensearch.rest.RestRequest;
import org.opensearch.client.node.NodeClient;

/**
 * Example plugin that provides a custom action and REST endpoint
 */
public class CustomActionPlugin extends Plugin implements ActionPlugin {
    
    @Override
    public List<ActionHandler<? extends ActionRequest, ? extends ActionResponse>> getActions() {
        return List.of(
            new ActionHandler<>(CustomAction.INSTANCE, TransportCustomAction.class)
        );
    }
    
    @Override
    public List<RestHandler> getRestHandlers(Settings settings, RestController restController,
            ClusterSettings clusterSettings, IndexScopedSettings indexScopedSettings,
            SettingsFilter settingsFilter, IndexNameExpressionResolver indexNameExpressionResolver,
            Supplier<DiscoveryNodes> nodesInCluster) {
        
        return List.of(new RestCustomHandler());
    }
}

/**
 * Custom action type definition
 */
public class CustomAction extends ActionType<CustomResponse> {
    public static final CustomAction INSTANCE = new CustomAction();
    public static final String NAME = "cluster:admin/custom_action";
    
    private CustomAction() {
        super(NAME, CustomResponse::new);
    }
}

/**
 * Custom action request
 */
public class CustomRequest extends ActionRequest {
    private String parameter;
    
    public CustomRequest(String parameter) {
        this.parameter = parameter;
    }
    
    public String getParameter() {
        return parameter;
    }
    
    @Override
    public ActionRequestValidationException validate() {
        if (parameter == null || parameter.isEmpty()) {
            ActionRequestValidationException validationException = new ActionRequestValidationException();
            validationException.addValidationError("parameter cannot be null or empty");
            return validationException;
        }
        return null;
    }
}

/**
 * Custom action response
 */
public class CustomResponse extends ActionResponse {
    private String result;
    
    public CustomResponse(String result) {
        this.result = result;
    }
    
    public String getResult() {
        return result;
    }
    
    @Override
    public void writeTo(StreamOutput out) throws IOException {
        out.writeString(result);
    }
}

/**
 * REST handler for custom action
 */
public class RestCustomHandler extends BaseRestHandler {
    
    @Override
    public List<Route> routes() {
        return List.of(
            new Route(GET, "/_custom/{param}"),
            new Route(POST, "/_custom/{param}")
        );
    }
    
    @Override
    public String getName() {
        return "custom_action_handler";
    }
    
    @Override
    protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
        String param = request.param("param");
        CustomRequest customRequest = new CustomRequest(param);
        
        return channel -> client.execute(CustomAction.INSTANCE, customRequest,
            new RestToXContentListener<>(channel));
    }
}

Creating a Custom Query Plugin

import org.opensearch.plugins.SearchPlugin;
import org.opensearch.index.query.QueryBuilder;
import org.opensearch.index.query.AbstractQueryBuilder;

/**
 * Plugin providing a custom query builder
 */
public class CustomQueryPlugin extends Plugin implements SearchPlugin {
    
    @Override
    public List<QuerySpec<?>> getQueries() {
        return List.of(
            new QuerySpec<>(
                CustomQueryBuilder.NAME,
                CustomQueryBuilder::new,
                CustomQueryBuilder::fromXContent
            )
        );
    }
}

/**
 * Custom query builder implementation
 */
public class CustomQueryBuilder extends AbstractQueryBuilder<CustomQueryBuilder> {
    public static final String NAME = "custom_query";
    
    private final String field;
    private final String value;
    private final float boost;
    
    public CustomQueryBuilder(String field, String value) {
        this.field = field;
        this.value = value;
        this.boost = 1.0f;
    }
    
    public CustomQueryBuilder boost(float boost) {
        return new CustomQueryBuilder(field, value).boost(boost);
    }
    
    @Override
    protected void doWriteTo(StreamOutput out) throws IOException {
        out.writeString(field);
        out.writeString(value);
        out.writeFloat(boost);
    }
    
    @Override
    protected void doXContent(XContentBuilder builder, Params params) throws IOException {
        builder.startObject(NAME);
        builder.startObject(field);
        builder.field("value", value);
        if (boost != 1.0f) {
            builder.field("boost", boost);
        }
        builder.endObject();
        builder.endObject();
    }
    
    public static CustomQueryBuilder fromXContent(XContentParser parser) throws IOException {
        // Implementation for parsing from XContent
        // ... parsing logic here
        return new CustomQueryBuilder("field", "value");
    }
    
    @Override
    protected Query doToQuery(QueryShardContext context) throws IOException {
        // Convert to Lucene query
        return new TermQuery(new Term(field, value));
    }
    
    @Override
    protected boolean doEquals(CustomQueryBuilder other) {
        return Objects.equals(field, other.field) &&
               Objects.equals(value, other.value) &&
               Float.compare(boost, other.boost) == 0;
    }
    
    @Override
    protected int doHashCode() {
        return Objects.hash(field, value, boost);
    }
    
    @Override
    public String getWriteableName() {
        return NAME;
    }
}

Creating a Custom Analysis Plugin

import org.opensearch.plugins.AnalysisPlugin;
import org.opensearch.index.analysis.TokenFilterFactory;

/**
 * Plugin providing custom text analysis components
 */
public class CustomAnalysisPlugin extends Plugin implements AnalysisPlugin {
    
    @Override
    public Map<String, AnalysisProvider<TokenFilterFactory>> getTokenFilters() {
        return Map.of("custom_filter", CustomTokenFilterFactory::new);
    }
    
    @Override
    public Map<String, AnalysisProvider<AnalyzerProvider<? extends Analyzer>>> getAnalyzers() {
        return Map.of("custom_analyzer", CustomAnalyzerProvider::new);
    }
}

/**
 * Custom token filter factory
 */
public class CustomTokenFilterFactory implements TokenFilterFactory {
    private final Settings settings;
    
    public CustomTokenFilterFactory(IndexSettings indexSettings, Environment environment,
                                    String name, Settings settings) {
        this.settings = settings;
    }
    
    @Override
    public String name() {
        return "custom_filter";
    }
    
    @Override
    public TokenStream create(TokenStream tokenStream) {
        return new CustomTokenFilter(tokenStream, settings);
    }
}

/**
 * Custom token filter implementation
 */
public class CustomTokenFilter extends TokenFilter {
    private final CharTermAttribute termAttribute;
    private final Settings settings;
    
    public CustomTokenFilter(TokenStream input, Settings settings) {
        super(input);
        this.settings = settings;
        this.termAttribute = addAttribute(CharTermAttribute.class);
    }
    
    @Override
    public boolean incrementToken() throws IOException {
        if (input.incrementToken()) {
            // Custom token processing logic
            String term = termAttribute.toString();
            String processed = processTerm(term);
            termAttribute.setEmpty().append(processed);
            return true;
        }
        return false;
    }
    
    private String processTerm(String term) {
        // Custom processing logic
        return term.toLowerCase();
    }
}

/**
 * Custom analyzer provider
 */
public class CustomAnalyzerProvider implements AnalyzerProvider<Analyzer> {
    private final Analyzer analyzer;
    
    public CustomAnalyzerProvider(IndexSettings indexSettings, Environment environment,
                                  String name, Settings settings) {
        this.analyzer = new CustomAnalyzer(settings);
    }
    
    @Override
    public Analyzer get() {
        return analyzer;
    }
    
    @Override
    public void close() {
        // Cleanup if needed
    }
}

Creating a Custom Ingest Processor Plugin

import org.opensearch.plugins.IngestPlugin;
import org.opensearch.ingest.Processor;
import org.opensearch.ingest.AbstractProcessor;
import org.opensearch.ingest.IngestDocument;

/**
 * Plugin providing custom ingest processors
 */
public class CustomIngestPlugin extends Plugin implements IngestPlugin {
    
    @Override
    public Map<String, Processor.Factory> getProcessors(Processor.Parameters parameters) {
        return Map.of("custom_processor", new CustomProcessorFactory());
    }
}

/**
 * Factory for creating custom processor instances
 */
public class CustomProcessorFactory implements Processor.Factory {
    
    @Override
    public CustomProcessor create(Map<String, Processor.Factory> processorFactories,
                                  String tag, String description, Map<String, Object> config) {
        String field = ConfigurationUtils.readStringProperty("custom_processor", tag, config, "field");
        String value = ConfigurationUtils.readStringProperty("custom_processor", tag, config, "value");
        boolean ignoreMissing = ConfigurationUtils.readBooleanProperty("custom_processor", tag, config, 
            "ignore_missing", false);
        
        return new CustomProcessor(tag, description, field, value, ignoreMissing);
    }
}

/**
 * Custom ingest processor implementation
 */
public class CustomProcessor extends AbstractProcessor {
    public static final String TYPE = "custom_processor";
    
    private final String field;
    private final String value;
    private final boolean ignoreMissing;
    
    public CustomProcessor(String tag, String description, String field, String value, boolean ignoreMissing) {
        super(tag, description);
        this.field = field;
        this.value = value;
        this.ignoreMissing = ignoreMissing;
    }
    
    @Override
    public String getType() {
        return TYPE;
    }
    
    @Override
    public IngestDocument execute(IngestDocument ingestDocument) throws Exception {
        if (!ingestDocument.hasField(field)) {
            if (ignoreMissing) {
                return ingestDocument;
            } else {
                throw new IllegalArgumentException("Field [" + field + "] does not exist");
            }
        }
        
        // Custom processing logic
        String currentValue = ingestDocument.getFieldValue(field, String.class);
        String processedValue = processValue(currentValue);
        ingestDocument.setFieldValue(field, processedValue);
        
        return ingestDocument;
    }
    
    private String processValue(String input) {
        // Custom value processing
        return input + "_" + value;
    }
}

Types

/**
 * Plugin environment providing access to configuration and resources
 */
class Environment {
    /**
     * Get settings configuration
     */
    Settings settings();
    
    /**
     * Get config directory path
     */
    Path configDir();
    
    /**
     * Get plugins directory path
     */
    Path pluginsDir();
    
    /**
     * Get modules directory path
     */
    Path modulesDir();
    
    /**
     * Get logs directory path
     */
    Path logsDir();
    
    /**
     * Get temporary directory path
     */
    Path tmpDir();
}

/**
 * Route definition for REST handlers
 */
class Route {
    /**
     * Create route with method and path
     * @param method HTTP method
     * @param path URL path pattern
     */
    Route(RestRequest.Method method, String path);
    
    /**
     * Create route with method, path, and deprecation message
     * @param method HTTP method
     * @param path URL path pattern
     * @param deprecationMessage Deprecation warning message
     */
    Route(RestRequest.Method method, String path, String deprecationMessage);
    
    /**
     * Get HTTP method
     */
    RestRequest.Method getMethod();
    
    /**
     * Get path pattern
     */
    String getPath();
    
    /**
     * Get deprecation message
     */
    String getDeprecationMessage();
}

/**
 * Transport action base class for handling cluster operations
 */
abstract class TransportAction<Request extends ActionRequest, Response extends ActionResponse> {
    /**
     * Execute action with request and response listener
     * @param task Task context
     * @param request Action request
     * @param listener Response callback
     */
    protected abstract void doExecute(Task task, Request request, ActionListener<Response> listener);
    
    /**
     * Get action name
     */
    String actionName();
    
    /**
     * Get transport service
     */
    protected TransportService transportService();
    
    /**
     * Get cluster service
     */
    protected ClusterService clusterService();
}

/**
 * Setting definition for plugin configuration
 */
class Setting<T> {
    /**
     * Create setting with key and default value
     * @param key Setting key
     * @param defaultValue Default value
     * @param parser Value parser function
     * @param properties Setting properties
     */
    static <T> Setting<T> simpleString(String key, String defaultValue, Property... properties);
    
    /**
     * Create integer setting
     * @param key Setting key
     * @param defaultValue Default integer value
     * @param minValue Minimum allowed value
     * @param properties Setting properties
     */
    static Setting<Integer> intSetting(String key, int defaultValue, int minValue, Property... properties);
    
    /**
     * Create boolean setting
     * @param key Setting key
     * @param defaultValue Default boolean value
     * @param properties Setting properties
     */
    static Setting<Boolean> boolSetting(String key, boolean defaultValue, Property... properties);
    
    /**
     * Get setting key
     */
    String getKey();
    
    /**
     * Get default value
     */
    T getDefault(Settings settings);
    
    /**
     * Setting properties enumeration
     */
    enum Property {
        DYNAMIC, INDEX_SCOPE, CLUSTER_SCOPE, DEPRECATED, FILTERED
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-opensearch--opensearch

docs

action-framework.md

client-apis.md

cluster-management.md

index-management.md

index.md

plugin-framework.md

search-apis.md

tile.json