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.LogSeverity; 007import com.unboundid.directory.sdk.common.types.UpdatableEntry; 008import com.unboundid.directory.sdk.ds.api.Plugin; 009import com.unboundid.directory.sdk.ds.config.PluginConfig; 010import com.unboundid.directory.sdk.ds.types.DirectoryServerContext; 011import com.unboundid.directory.sdk.ds.types.PreParsePluginResult; 012import com.unboundid.ldap.sdk.*; 013import com.unboundid.util.args.*; 014 015import java.util.concurrent.atomic.AtomicLong; 016 017public class UniqueMod7IDGenerator extends Plugin { 018 019 public static final String ARG_NAME_ATTRIBUTE_NAME = "attribute-name"; 020 public static final String ARG_NAME_EXTERNAL_SERVER = "external-server"; 021 public static final String ARG_NAME_MIN_CX = "min-connections"; 022 private static final String ARG_NAME_MAX_CX = "max-connections"; 023 private static final String ARG_NAME_SEED = "seed"; 024 public static final String ARG_NAME_BASE = "base"; 025 public static final String ARG_NAME_SCOPE = "scope"; 026 public static final String ARG_NAME_FILTER_ATTRIBUTE = "filter-attribute"; 027 public static final String ARG_NAME_MAX_RETRIES = "max-retries"; 028 029 030 private String attributeName; 031 private LDAPConnectionPool ldapConnectionPool; 032 private Integer seed; 033 private DN base; 034 private SearchScope scope; 035 private String filterAttr; 036 private AtomicLong id; 037 private Integer maxRetries; 038 private DirectoryServerContext serverContext; 039 040 @Override 041 public String getExtensionName() { 042 return "Unique mod7 UID Generator"; 043 } 044 045 @Override 046 public String[] getExtensionDescription() { 047 return new String[] {"generates a unique mod7 uid attribute value"}; 048 } 049 050 @Override 051 public void defineConfigArguments(ArgumentParser parser) throws ArgumentException { 052 StringArgument attributeNameArg = new StringArgument(null, ARG_NAME_ATTRIBUTE_NAME,false,1,"{attribute-name}","the name of the attribute (default: uid)","uid"); 053 parser.addArgument(attributeNameArg); 054 StringArgument externalServerArgument = new StringArgument(null, ARG_NAME_EXTERNAL_SERVER, false, 1, 055 "{external-server}", "The name of the external server to issue the persistent search request to."); 056 parser.addArgument(externalServerArgument); 057 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); 058 parser.addArgument(minConnections); 059 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); 060 parser.addArgument(maxConnections); 061 IntegerArgument seedArg = new IntegerArgument(null, ARG_NAME_SEED,false,1,"{seed}","The seed to use for generation",89000000); 062 parser.addArgument(seedArg); 063 DNArgument baseArg = new DNArgument(null, ARG_NAME_BASE,false,1,"{base}","The base to issue searches against", DN.NULL_DN); 064 parser.addArgument(baseArg); 065 ScopeArgument scopeArg = new ScopeArgument(null, ARG_NAME_SCOPE,false,"{scope}","The scope to use to locate entries (default: sub)", SearchScope.SUB); 066 parser.addArgument(scopeArg); 067 StringArgument filterArg=new StringArgument(null, ARG_NAME_FILTER_ATTRIBUTE,false,1,"{filter-attribute}","The filter attribute to use to locate entries (default: uid )","uid"); 068 parser.addArgument(filterArg); 069 IntegerArgument retriesArg = new IntegerArgument(null, ARG_NAME_MAX_RETRIES,false,1,"{max-retries}","Maximum number of retries when looking up an entry",10); 070 parser.addArgument(retriesArg); 071 } 072 073 @Override 074 public void initializePlugin(DirectoryServerContext serverContext, PluginConfig config, ArgumentParser parser) throws LDAPException { 075 attributeName = parser.getStringArgument(ARG_NAME_ATTRIBUTE_NAME).getValue(); 076 077 this.serverContext = serverContext; 078 LDAPConnectionOptions options = new LDAPConnectionOptions(); 079 options.setUseSynchronousMode(true); 080 options.setUseTCPNoDelay(true); 081 options.setConnectTimeoutMillis(5000); 082 options.setResponseTimeoutMillis(OperationType.SEARCH,23000L); 083 options.setResponseTimeoutMillis(OperationType.ADD,31000L); 084 options.setResponseTimeoutMillis(OperationType.MODIFY,37000L); 085 options.setResponseTimeoutMillis(57000L); 086 LDAPConnection ldapConnection = serverContext.getLDAPExternalServerConnection(parser.getStringArgument(ARG_NAME_EXTERNAL_SERVER).getValue(), options); 087 Integer minCx = parser.getIntegerArgument(ARG_NAME_MIN_CX).getValue(); 088 Integer maxCx = parser.getIntegerArgument(ARG_NAME_MAX_CX).getValue(); 089 ldapConnectionPool = new LDAPConnectionPool(ldapConnection,minCx,maxCx); 090 seed= parser.getIntegerArgument(ARG_NAME_SEED).getValue(); 091 base = parser.getDNArgument(ARG_NAME_BASE).getValue(); 092 scope = parser.getScopeArgument(ARG_NAME_SCOPE).getValue(); 093 filterAttr = parser.getStringArgument(ARG_NAME_FILTER_ATTRIBUTE).getValue(); 094 id = new AtomicLong(seed); 095 maxRetries = parser.getIntegerArgument(ARG_NAME_MAX_RETRIES).getValue(); 096 } 097 098 private synchronized String generateValue(){ 099 Integer retries = 0; 100 l("starting unique ID generation"); 101 while (retries++<maxRetries){ 102 try { 103 Long thisID = id.incrementAndGet(); 104 String filter = filterAttr+"="+thisID; 105 l("Remote System checking for: "+filter); 106 SearchResult searchResult = ldapConnectionPool.search(base.toString(), scope, filter, "1.1"); 107 serverContext.logMessage(LogSeverity.DEBUG,"Remote System result code: "+searchResult.getResultCode()); 108 if ( ResultCode.SUCCESS.equals(searchResult.getResultCode()) && searchResult.getEntryCount() == 0 ) { 109 l("finishing unique ID generation"); 110 return String.format("%d",id.addAndGet(id.get() % 7 )); 111 } 112 } catch (LDAPSearchException e) { 113 l("Unique ID generation: Error with remote system "+e.getDiagnosticMessage()); 114 } 115 } 116 l("failed unique ID generation"); 117 return null; 118 } 119 120 @Override 121 public PreParsePluginResult doPreParse(ActiveOperationContext operationContext, UpdatableAddRequest request, UpdatableAddResult result) { 122 l("calling generateValue"); 123 String value = generateValue(); 124 l("generateValue() +> "+value); 125 if (value == null ) { 126 result.setDiagnosticMessage("Could not obtain value probably due to issue on remote system"); 127 result.setResultCode(ResultCode.UNWILLING_TO_PERFORM); 128 return new PreParsePluginResult(false,false,true,true); 129 } else { 130 request.getEntry().setAttribute(new Attribute(attributeName,value)); 131 return PreParsePluginResult.SUCCESS; 132 } 133 } 134 135 private void l(String s){ 136 System.out.println(s); 137 serverContext.logMessage(LogSeverity.INFO, s); 138 } 139}