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.Date;
014import java.util.List;
015
016public class LDAPWithWriteback extends SyncDestination {
017    private static final String ARG_NAME_EXTERNAL_SERVER = "external-server";
018    public static final String ARG_NAME_MIN_CX = "min-connections";
019    private static final String ARG_NAME_MAX_CX = "max-connections";
020    public static final String ARG_CREATION_ATTRIBUTE_NAME = "creation-attribute-name";
021    public static final String ARG_UPDATE_ATTRIBUTE_NAME = "update-attribute-name";
022    private static final String ATTACHMENT_ID = "connection";
023    private LDAPConnectionPool ldapConnectionPool;
024    private SyncServerContext serverContext;
025    private String creationAttributeName;
026    private String updateAttributeName;
027
028    @Override
029    public String getExtensionName() {
030        return "LDAPWithWriteback";
031    }
032
033    @Override
034    public String[] getExtensionDescription() {
035        return new String[]{"LDAP Destination with write-back to the source"};
036    }
037
038    @Override
039    public void defineConfigArguments(ArgumentParser parser) throws ArgumentException {
040        StringArgument externalServerArg = new StringArgument(null, ARG_NAME_EXTERNAL_SERVER, true, 1,
041                "{external-server}", "The name of the external server to issue requests to.");
042        parser.addArgument(externalServerArg);
043        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);
044        parser.addArgument(minConnectionsArg);
045        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);
046        parser.addArgument(maxConnectionsArg);
047        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");
048        creationAttributeNameArg.addValueValidator(new AttributeNameArgumentValueValidator());
049        parser.addArgument(creationAttributeNameArg);
050        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");
051        creationAttributeNameArg.addValueValidator(new AttributeNameArgumentValueValidator());
052        parser.addArgument(updateAttributeNameArg);
053    }
054
055    @Override
056    public void initializeSyncDestination(SyncServerContext serverContext, SyncDestinationConfig config, ArgumentParser parser) throws EndpointException {
057        this.serverContext = serverContext;
058        try {
059            LDAPConnection ldapConnection = serverContext.getLDAPExternalServerConnection(parser.getStringArgument(ARG_NAME_EXTERNAL_SERVER).getValue(), null);
060            Integer minCx = parser.getIntegerArgument(ARG_NAME_MIN_CX).getValue();
061            Integer maxCx = parser.getIntegerArgument(ARG_NAME_MAX_CX).getValue();
062            ldapConnectionPool = new LDAPConnectionPool(ldapConnection, minCx, maxCx);
063            creationAttributeName = parser.getStringArgument(ARG_CREATION_ATTRIBUTE_NAME).getValue();
064            updateAttributeName = parser.getStringArgument(ARG_UPDATE_ATTRIBUTE_NAME).getValue();
065        } catch (LDAPException e) {
066            throw new EndpointException(e);
067        }
068    }
069
070    @Override
071    public String getCurrentEndpointURL() {
072        return null;
073    }
074
075    @Override
076    public void createEntry(Entry entry, SyncOperation syncOperation) throws EndpointException {
077        try {
078            LDAPInterface connection = (LDAPInterface) syncOperation.getAttachment(ATTACHMENT_ID);
079            LDAPResult addResult = ldapConnectionPool.add(entry);
080            serverContext.logMessage(LogSeverity.INFO, addResult.getDiagnosticMessage());
081            if (ResultCode.SUCCESS.equals(addResult.getResultCode()) &&  connection != null ) {
082                Modification modification = new Modification(ModificationType.REPLACE,creationAttributeName,new SimpleDateFormat("yyyyMMdd-HHmmssSSS").format(new Date()));
083                LDAPResult writebackResult = connection.modify(syncOperation.getSourceEntry().getDN(), modification);
084                serverContext.logMessage(LogSeverity.DEBUG,"Writeback: "+writebackResult.getDiagnosticMessage());
085            }
086        } catch (LDAPException e) {
087            throw new EndpointException(e);
088        }
089    }
090
091    @Override
092    public void modifyEntry(Entry entry, List<Modification> modifications, SyncOperation syncOperation) throws EndpointException {
093        try {
094            LDAPInterface connection = (LDAPInterface) syncOperation.getAttachment(ATTACHMENT_ID);
095            LDAPResult modifyResult = ldapConnectionPool.modify(entry.getDN(), modifications);
096            serverContext.logMessage(LogSeverity.INFO, modifyResult.getDiagnosticMessage());
097            if (ResultCode.SUCCESS.equals(modifyResult.getResultCode()) &&  connection != null ) {
098                Modification modification = new Modification(ModificationType.REPLACE,updateAttributeName,new SimpleDateFormat("yyyyMMdd-HHmmssSSS").format(new Date()));
099                LDAPResult writebackResult = connection.modify(syncOperation.getSourceEntry().getDN(), modification);
100                serverContext.logMessage(LogSeverity.DEBUG,"Write-back: "+writebackResult.getDiagnosticMessage());
101            }
102        } catch (LDAPException e) {
103            throw new EndpointException(e);
104        }
105    }
106
107    @Override
108    public void deleteEntry(Entry entry, SyncOperation syncOperation) throws EndpointException {
109        try {
110            LDAPResult deleteResult = ldapConnectionPool.delete(entry.getDN());
111            serverContext.logMessage(LogSeverity.INFO, deleteResult.getDiagnosticMessage());
112        } catch (LDAPException e) {
113            throw new EndpointException(e);
114        }
115    }
116}