Create custom token filter

Elasticsearch version : 8.19.9
Elasticsearch version : 9.2.2

Hello,

I try to create a custom TokenFilter who is able to cypher index content.

I create the class who cypher tokens and extends TokenFilter class and I create the factory who extend TokenFilterFactory with the NamedComponent decorator.

I can deploy the plugin in elastic with elasticsearch-plugin command.

Whane I try to create an index who use this plugin with this config

{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_ecies_analyzer": {
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "cypher"  
          ]
        }
      },
      "filter": {
        "cypher": {
          "type": "cypher-token" 
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "encrypted_text": {
        "type": "text",
        "analyzer": "my_ecies_analyzer"  
      }
    }
  }
}

I got the error

 {
     "error": {
         "root_cause": \[
             {
                 "type": "illegal_argument_exception",
                 "reason": "Unknown filter type \[cypher-token\] for \[cypher\]"
             }
         \],
         "type": "illegal_argument_exception",
         "reason": "Unknown filter type \[cypher-token\] for \[cypher\]"
     },
     "status": 400
 }

I give you the code for the TokenFilter

 public class CypheringTokenFilter extends TokenFilter {
 private final CharTermAttribute charTermAttribute = addAttribute(CharTermAttribute.class);
 private final Cipher cipher;

 
 public CypheringTokenFilter(TokenStream input, Cipher cipher) throws Exception {
     super(input);
     this.cipher = cipher;
 }
 
 @Override
 public boolean incrementToken() throws IOException {
     if (!input.incrementToken()) {
         return false;
     }
     String plainToken = charTermAttribute.toString();

     byte[] encryptedBytes;
     try {
         encryptedBytes = cipher.doFinal(plainToken.getBytes());
     } catch (Exception e) {
         throw new IOException("Erreur lors du chiffrement du token", e);
     }
 
     // Encoder en Base64
     String encryptedToken = Base64.getEncoder().encodeToString(encryptedBytes);
 
     // Remplacer le token par sa version chiffrée
     charTermAttribute.setEmpty();
     charTermAttribute.append(encryptedToken);
 
     return true;
 }
 

 }

and the code for the factory

 @NamedComponentNamedComponent(value = "cypher-token")
 public class CypheringTokenFilterFactory implements TokenFilterFactory  {
 IPublicKeyUtil publicKeyUtil;

public CypheringTokenFilterFactory() throws Exception {
	super();
	publicKeyUtil = new RSAPublicKeyUtil();
}


@Override
public TokenStream create(TokenStream tokenStream) {
	try {
		return new CypheringTokenFilter(tokenStream, publicKeyUtil.getCipher());			
	}
	catch (Exception e) {
		throw new RuntimeException(e);
	}
}

@Override
public TokenStream normalize(TokenStream tokenStream) {
 	try {
 		return new CypheringTokenFilter(tokenStream, publicKeyUtil.getCipher());		 		
 	}
	catch (Exception e) {
		throw new RuntimeException(e);
	}
}

@Override
public AnalysisMode getAnalysisMode() {
   return TokenFilterFactory.super.getAnalysisMode();
}


}