001package com.pingidentity.ds.plugin; 002 003import com.unboundid.directory.sdk.common.operation.UpdatableAddRequest; 004import com.unboundid.directory.sdk.common.operation.UpdatableAddResult; 005import com.unboundid.directory.sdk.common.types.ActiveOperationContext; 006import com.unboundid.directory.sdk.common.types.UpdatableEntry; 007import com.unboundid.directory.sdk.ds.api.Plugin; 008import com.unboundid.directory.sdk.ds.config.PluginConfig; 009import com.unboundid.directory.sdk.ds.types.DirectoryServerContext; 010import com.unboundid.directory.sdk.ds.types.PreParsePluginResult; 011import com.unboundid.ldap.sdk.*; 012import com.unboundid.util.args.*; 013 014import java.util.concurrent.atomic.AtomicLong; 015 016public class UniqueMod7IDGenerator extends Plugin { 017 018 public static final String ARG_NAME_ATTRIBUTE_NAME = "attribute-name"; 019 public static final String ARG_NAME_EXTERNAL_SERVER = "external-server"; 020 public static final String ARG_NAME_MIN_CX = "min-connections"; 021 private static final String ARG_NAME_MAX_CX = "max-connections"; 022 private static final String ARG_NAME_SEED = "seed"; 023 public static final String ARG_NAME_BASE = "base"; 024 public static final String ARG_NAME_SCOPE = "scope"; 025 public static final String ARG_NAME_FILTER_ATTRIBUTE = "filter-attribute"; 026 public static final String ARG_NAME_MAX_RETRIES = "max-retries"; 027 028 029 private String attributeName; 030 private LDAPConnectionPool ldapConnectionPool; 031 private Integer seed; 032 private DN base; 033 private SearchScope scope; 034 private String filterAttr; 035 private AtomicLong id; 036 private Integer maxRetries; 037 038 @Override 039 public String getExtensionName() { 040 return "Unique mod7 UID Generator"; 041 } 042 043 @Override 044 public String[] getExtensionDescription() { 045 return new String[] {"generates a unique mod7 uid attribute value"}; 046 } 047 048 @Override 049 public void defineConfigArguments(ArgumentParser parser) throws ArgumentException { 050 StringArgument attributeNameArg = new StringArgument(null, ARG_NAME_ATTRIBUTE_NAME,false,1,"{attribute-name}","the name of the attribute (default: uid)","uid"); 051 parser.addArgument(attributeNameArg); 052 StringArgument externalServerArgument = new StringArgument(null, ARG_NAME_EXTERNAL_SERVER, false, 1, 053 "{external-server}", "The name of the external server to issue the persistent search request to."); 054 parser.addArgument(externalServerArgument); 055 IntegerArgument minConnections = new IntegerArgument(null, ARG_NAME_MIN_CX,false,1,"{min-connections}","The minimum number of connection to maintain in the pool (default: 1)",1); 056 parser.addArgument(minConnections); 057 IntegerArgument maxConnections = new IntegerArgument(null, ARG_NAME_MAX_CX,false,1,"{max-connections}","The maximum number of connection to maintain in the pool (default: 10)",10); 058 parser.addArgument(maxConnections); 059 IntegerArgument seedArg = new IntegerArgument(null, ARG_NAME_SEED,false,1,"{seed}","The seed to use for generation",89000000); 060 parser.addArgument(seedArg); 061 DNArgument baseArg = new DNArgument(null, ARG_NAME_BASE,false,1,"{base}","The base to issue searches against", DN.NULL_DN); 062 parser.addArgument(baseArg); 063 ScopeArgument scopeArg = new ScopeArgument(null, ARG_NAME_SCOPE,false,"{scope}","The scope to use to locate entries (default: sub)", SearchScope.SUB); 064 parser.addArgument(scopeArg); 065 StringArgument filterArg=new StringArgument(null, ARG_NAME_FILTER_ATTRIBUTE,false,1,"{filter-attribute}","The filter attribute to use to locate entries (default: uid )","uid"); 066 parser.addArgument(filterArg); 067 IntegerArgument retriesArg = new IntegerArgument(null, ARG_NAME_MAX_RETRIES,false,1,"{max-retries}","Maximum number of retries when looking up an entry",10); 068 parser.addArgument(retriesArg); 069 } 070 071 @Override 072 public void initializePlugin(DirectoryServerContext serverContext, PluginConfig config, ArgumentParser parser) throws LDAPException { 073 attributeName = parser.getStringArgument(ARG_NAME_ATTRIBUTE_NAME).getValue(); 074 075 076 LDAPConnection ldapConnection = serverContext.getLDAPExternalServerConnection(parser.getStringArgument(ARG_NAME_EXTERNAL_SERVER).getValue(), null); 077 Integer minCx = parser.getIntegerArgument(ARG_NAME_MIN_CX).getValue(); 078 Integer maxCx = parser.getIntegerArgument(ARG_NAME_MAX_CX).getValue(); 079 ldapConnectionPool = new LDAPConnectionPool(ldapConnection,minCx,maxCx); 080 seed= parser.getIntegerArgument(ARG_NAME_SEED).getValue(); 081 base = parser.getDNArgument(ARG_NAME_BASE).getValue(); 082 scope = parser.getScopeArgument(ARG_NAME_SCOPE).getValue(); 083 filterAttr = parser.getStringArgument(ARG_NAME_FILTER_ATTRIBUTE).getValue(); 084 id = new AtomicLong(seed); 085 maxRetries = parser.getIntegerArgument(ARG_NAME_MAX_RETRIES).getValue(); 086 } 087 088 private synchronized String generateValue(){ 089 String result = null; 090 Integer retries = 0; 091 while (retries<maxRetries){ 092 try { 093 SearchResult searchResult = ldapConnectionPool.search(base.toString(), scope, filterAttr+"="+id.incrementAndGet(), "1.1"); 094 if ( ResultCode.SUCCESS.equals(searchResult.getResultCode()) && searchResult.getEntryCount() == 0 ) { 095 result = String.format("%.0f",id.addAndGet(id.get() % 7 )); 096 break; 097 } 098 } catch (LDAPSearchException e) { 099 retries++; 100 } 101 } 102 return result; 103 } 104 105 @Override 106 public PreParsePluginResult doPreParse(ActiveOperationContext operationContext, UpdatableAddRequest request, UpdatableAddResult result) { 107 UpdatableEntry entry = request.getEntry(); 108 entry.removeAttribute(attributeName); 109 entry.addAttribute(new Attribute( attributeName,generateValue())); 110 return PreParsePluginResult.SUCCESS; 111 } 112}