001package com.pingidentity.sync.destination; 002 003import com.unboundid.directory.sdk.common.types.LogSeverity; 004import com.unboundid.directory.sdk.sync.api.SyncDestination; 005import com.unboundid.directory.sdk.sync.config.SyncDestinationConfig; 006import com.unboundid.directory.sdk.sync.types.EndpointException; 007import com.unboundid.directory.sdk.sync.types.SyncOperation; 008import com.unboundid.directory.sdk.sync.types.SyncServerContext; 009import com.unboundid.ldap.sdk.*; 010import com.unboundid.util.args.*; 011 012import java.text.SimpleDateFormat; 013import java.util.ArrayList; 014import java.util.Date; 015import java.util.List; 016 017public class LDAPWithWriteback extends SyncDestination { 018 private static final String ARG_NAME_EXTERNAL_SERVER = "external-server"; 019 public static final String ARG_NAME_MIN_CX = "min-connections"; 020 private static final String ARG_NAME_MAX_CX = "max-connections"; 021 public static final String ARG_CREATION_ATTRIBUTE_NAME = "creation-attribute-name"; 022 public static final String ARG_UPDATE_ATTRIBUTE_NAME = "update-attribute-name"; 023 private static final String ATTACHMENT_ID = "connection"; 024 private LDAPConnectionPool ldapConnectionPool; 025 private SyncServerContext serverContext; 026 private String creationAttributeName; 027 private String updateAttributeName; 028 029 @Override 030 public String getExtensionName() { 031 return "LDAPWithWriteback"; 032 } 033 034 @Override 035 public String[] getExtensionDescription() { 036 return new String[]{"LDAP Destination with write-back to the source"}; 037 } 038 039 @Override 040 public void defineConfigArguments(ArgumentParser parser) throws ArgumentException { 041 StringArgument externalServerArg = new StringArgument(null, ARG_NAME_EXTERNAL_SERVER, true, 1, 042 "{external-server}", "The name of the external server to issue requests to."); 043 parser.addArgument(externalServerArg); 044 IntegerArgument minConnectionsArg = new IntegerArgument(null, ARG_NAME_MIN_CX, false, 1, "{min-connections}", "The minimum number of connection to maintain in the pool (default: 1)", 1); 045 parser.addArgument(minConnectionsArg); 046 IntegerArgument maxConnectionsArg = new IntegerArgument(null, ARG_NAME_MAX_CX, false, 1, "{max-connections}", "The maximum number of connection to maintain in the pool (default: 10)", 10); 047 parser.addArgument(maxConnectionsArg); 048 StringArgument creationAttributeNameArg = new StringArgument(null, ARG_CREATION_ATTRIBUTE_NAME, true, 1, "{attribute-name}", "The attribute name to write back to upon successful creation at the destination"); 049 creationAttributeNameArg.addValueValidator(new AttributeNameArgumentValueValidator()); 050 parser.addArgument(creationAttributeNameArg); 051 StringArgument updateAttributeNameArg = new StringArgument(null, ARG_UPDATE_ATTRIBUTE_NAME, true, 1, "{attribute-name}", "The attribute name to write back to upon successful update at the destination"); 052 creationAttributeNameArg.addValueValidator(new AttributeNameArgumentValueValidator()); 053 parser.addArgument(updateAttributeNameArg); 054 } 055 056 @Override 057 public void initializeSyncDestination(SyncServerContext serverContext, SyncDestinationConfig config, ArgumentParser parser) throws EndpointException { 058 this.serverContext = serverContext; 059 try { 060 LDAPConnection ldapConnection = serverContext.getLDAPExternalServerConnection(parser.getStringArgument(ARG_NAME_EXTERNAL_SERVER).getValue(), null); 061 Integer minCx = parser.getIntegerArgument(ARG_NAME_MIN_CX).getValue(); 062 Integer maxCx = parser.getIntegerArgument(ARG_NAME_MAX_CX).getValue(); 063 ldapConnectionPool = new LDAPConnectionPool(ldapConnection, minCx, maxCx); 064 creationAttributeName = parser.getStringArgument(ARG_CREATION_ATTRIBUTE_NAME).getValue(); 065 updateAttributeName = parser.getStringArgument(ARG_UPDATE_ATTRIBUTE_NAME).getValue(); 066 } catch (LDAPException e) { 067 l(e.getDiagnosticMessage()); 068 throw new EndpointException(e); 069 } 070 } 071 072 @Override 073 public String getCurrentEndpointURL() { 074 return null; 075 } 076 077 @Override 078 public void createEntry(Entry entry, SyncOperation syncOperation) throws EndpointException { 079 try { 080 LDAPInterface connection = (LDAPInterface) syncOperation.getAttachment(ATTACHMENT_ID); 081 LDAPResult addResult = ldapConnectionPool.add(entry); 082 if (ResultCode.SUCCESS.equals(addResult.getResultCode()) && connection != null) { 083 Modification modification = new Modification(ModificationType.REPLACE, creationAttributeName, new SimpleDateFormat("yyyyMMdd-HHmmss.SSS").format(new Date())); 084 LDAPResult writebackResult = connection.modify(syncOperation.getSourceEntry().getDN(), modification); 085 l( "Writeback: " + writebackResult.getDiagnosticMessage()); 086 } 087 } catch (LDAPException e) { 088 l(e.getDiagnosticMessage()); 089 throw new EndpointException(e); 090 } 091 } 092 093 @Override 094 public void modifyEntry(Entry entry, List<Modification> modifications, SyncOperation syncOperation) throws EndpointException { 095 try { 096 LDAPInterface connection = (LDAPInterface) syncOperation.getAttachment(ATTACHMENT_ID); 097 LDAPResult modifyResult = ldapConnectionPool.modify(entry.getDN(), modifications); 098 l(modifyResult.getDiagnosticMessage()); 099 if (ResultCode.SUCCESS.equals(modifyResult.getResultCode()) && connection != null) { 100 Modification modification = new Modification(ModificationType.REPLACE, updateAttributeName, new SimpleDateFormat("yyyyMMdd-HHmmss.SSS").format(new Date())); 101 LDAPResult writebackResult = connection.modify(syncOperation.getSourceEntry().getDN(), modification); 102 l("Write-back: " + writebackResult.getDiagnosticMessage()); 103 } 104 } catch (LDAPException e) { 105 l(e.getDiagnosticMessage()); 106 throw new EndpointException(e); 107 } 108 } 109 110 @Override 111 public void deleteEntry(Entry entry, SyncOperation syncOperation) throws EndpointException { 112 try { 113 LDAPResult deleteResult = ldapConnectionPool.delete(entry.getDN()); 114 l(deleteResult.getDiagnosticMessage()); 115 } catch (LDAPException e) { 116 l(e.getDiagnosticMessage()); 117 throw new EndpointException(e); 118 } 119 } 120 121 @Override 122 public List<Entry> fetchEntry(Entry destEntryMappedFromSrc, SyncOperation syncOperation) throws EndpointException { 123 List<Entry> result = new ArrayList<>(); 124 LDAPInterface connection = (LDAPInterface) syncOperation.getAttachment(ATTACHMENT_ID); 125 if (connection != null) { 126 try { 127 SearchResultEntry entry = connection.getEntry(destEntryMappedFromSrc.getDN()); 128 if ( entry != null ) { 129 l("Found entry: " + entry.getDN()); 130 result.add(entry); 131 } 132 } catch (LDAPException e) { 133 l(e.getDiagnosticMessage()); 134 throw new EndpointException(e); 135 } 136 } 137 return result; 138 } 139 140 private void l(String s){ 141 System.out.println(s); 142 serverContext.logMessage(LogSeverity.INFO, s); 143 } 144}