Skip to content

Commit

Permalink
add a create/update/changeId/delete posthook (#193)
Browse files Browse the repository at this point in the history
  • Loading branch information
David Coutadeur committed Oct 25, 2023
1 parent eacf33d commit 6d51dfe
Show file tree
Hide file tree
Showing 12 changed files with 624 additions and 2 deletions.
15 changes: 15 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,21 @@
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
</dependencies>

<distributionManagement>
Expand Down
151 changes: 151 additions & 0 deletions src/main/java/org/lsc/Hooks.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
****************************************************************************
* Ldap Synchronization Connector provides tools to synchronize
* electronic identities from a list of data sources including
* any database with a JDBC connector, another LDAP directory,
* flat files...
*
* ==LICENSE NOTICE==
*
* Copyright (c) 2008 - 2011 LSC Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*    * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*     * Neither the name of the LSC Project nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ==LICENSE NOTICE==
*
* (c) 2008 - 2011 LSC Project
****************************************************************************
*/
package org.lsc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.ProcessBuilder;
import java.io.IOException;
import java.io.StringWriter;
import java.io.PrintWriter;
import com.fasterxml.jackson.databind.ObjectMapper; // For encoding object to JSON
import com.fasterxml.jackson.databind.ObjectWriter;



/**
* This object is managing posthook scripts
*/
public class Hooks {

static final Logger LOGGER = LoggerFactory.getLogger(AbstractSynchronize.class);
/**
* Method calling a postSyncHook if necessary
*
* return nothing
*/
public final static void postSyncHook(final String hook, final LscModifications lm) {

if( hook != null && ! hook.equals("") )
{
// Compute json modifications
String jsonModifications = null;

switch (lm.getOperation()) {
case CREATE_OBJECT:
jsonModifications = getJsonModifications(lm);
callHook("create", hook, lm.getMainIdentifier(), jsonModifications);
break;

case UPDATE_OBJECT:
jsonModifications = getJsonModifications(lm);
callHook("update", hook, lm.getMainIdentifier(), jsonModifications);
break;

case CHANGE_ID:
jsonModifications = getJsonModifications(lm);
callHook("changeId", hook, lm.getMainIdentifier(), jsonModifications);
break;

case DELETE_OBJECT:
callHook("delete", hook, lm.getMainIdentifier(), jsonModifications);
break;

default:
LOGGER.info("Error: unknown operation for posthook {}", hook);
}
}
}

public final static void callHook( String operationType,
String hook,
String identifier,
String jsonModifications) {

LOGGER.info("Calling {} posthook {} for {}", operationType, hook, identifier);
try {
if( jsonModifications != null ) {
Process p = new ProcessBuilder(
hook,
identifier,
operationType,
jsonModifications)
.start();
}
else {
Process p = new ProcessBuilder(
hook,
identifier,
operationType)
.start();
}
}
catch(IOException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
LOGGER.error("Error while calling {} posthook {} for {}: {}",
operationType,hook, identifier, sw.toString());
}
}

/**
* Method computing modifications as json
*
* @return modifications in a json String
*/
public final static String getJsonModifications(final LscModifications lm) {
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = "";
try {
json = ow.writeValueAsString(lm.getLscAttributeModifications());
}
catch(Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
LOGGER.error("Error while encoding LSC modifications to json", sw.toString());
}
return json;
}

}
20 changes: 20 additions & 0 deletions src/main/java/org/lsc/beans/syncoptions/ForceSyncOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,26 @@ public String getCondition(LscModificationType operation) {
return DEFAULT_CONDITION;
}

public String getCreatePostHook() {
return "";
}

public String getDeletePostHook() {
return "";
}

public String getUpdatePostHook() {
return "";
}

public String getChangeIdPostHook() {
return "";
}

public String getPostHook(LscModificationType operation) {
return "";
}

public String getDn() {
return null;//((Ldap)task.getDestinationService()).getDn();
}
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/org/lsc/beans/syncoptions/ISyncOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,37 @@ public interface ISyncOptions {

String getCondition(LscModificationType operation);

/**
* Returns the posthook for a creation
*
* @return the posthook or "" if none is specified (default)
*/
String getCreatePostHook();

/**
* Returns the posthook for an update
*
* @return the posthook or "" if none is specified (default)
*/
String getUpdatePostHook();

/**
* Returns the posthook for a delete
*
* @return the posthook or "" if none is specified (default)
*/
String getDeletePostHook();

/**
* Returns the posthook for a id change
*
* @return the posthook or "" if none is specified (default)
*/
String getChangeIdPostHook();


String getPostHook(LscModificationType operation);

/**
* Return the expression used to infer the new object DN
* @return the new object dn pattern
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,53 @@ public String getCondition(LscModificationType operation) {
}
return result;
}

public String getCreatePostHook() {
if (conf.getHooks() == null || conf.getHooks().getCreatePostHook() == null) {
return "";
}
return conf.getHooks().getCreatePostHook();
}

public String getDeletePostHook() {
if (conf.getHooks() == null || conf.getHooks().getDeletePostHook() == null) {
return "";
}
return conf.getHooks().getDeletePostHook();
}

public String getUpdatePostHook() {
if (conf.getHooks() == null || conf.getHooks().getUpdatePostHook() == null) {
return "";
}
return conf.getHooks().getUpdatePostHook();
}

public String getChangeIdPostHook() {
if (conf.getHooks() == null || conf.getHooks().getChangeIdPostHook() == null) {
return "";
}
return conf.getHooks().getChangeIdPostHook();
}

public String getPostHook(LscModificationType operation) {
String result = "";
switch (operation) {
case CREATE_OBJECT:
result = this.getCreatePostHook();
break;
case UPDATE_OBJECT:
result = this.getUpdatePostHook();
break;
case DELETE_OBJECT:
result = this.getDeletePostHook();
break;
case CHANGE_ID:
result = this.getChangeIdPostHook();
break;
}
return result;
}

public String getDelimiter(String name) {
DatasetType dataset = LscConfiguration.getDataset(conf, name);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/lsc/configuration/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/AuditType.java
/AuditsType.java
/ConditionsType.java
/HooksType.java
/ConnectionType.java
/ConnectionsType.java
/CsvAuditType.java
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/lsc/runnable/CleanEntryRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.lsc.utils.ScriptingEvaluator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.lsc.Hooks;

/**
* @author sfroger
Expand Down Expand Up @@ -108,6 +109,9 @@ public void run() {
// if we got here, we have a modification to apply - let's
// do it!
if (task.getDestinationService().apply(lm)) {
// Retrieve posthook for the current operation
String hook = syncOptions.getDeletePostHook();
Hooks.postSyncHook(hook, lm);
counter.incrementCountCompleted();
abstractSynchronize.logAction(lm, id, task.getName());
} else {
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/org/lsc/runnable/SynchronizeEntryRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.lsc.utils.ScriptingEvaluator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.lsc.Hooks;

/**
* @author sbahloul
Expand Down Expand Up @@ -137,6 +138,9 @@ public boolean run(IBean entry) {

// if we got here, we have a modification to apply - let's do it!
if (task.getDestinationService().apply(lm)) {
// Retrieve posthook for the current operation
String hook = task.getSyncOptions().getPostHook(modificationType);
Hooks.postSyncHook(hook, lm);
counter.incrementCountCompleted();
abstractSynchronize.logAction(lm, id, syncName);
return true;
Expand All @@ -160,4 +164,5 @@ public boolean run(IBean entry) {
}
}

}
}

12 changes: 11 additions & 1 deletion src/main/resources/schemas/lsc-core-2.2.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,16 @@
<xsd:element name="changeId" type="xsd:string" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>


<xsd:complexType name="hooksType">
<xsd:sequence>
<xsd:element name="createPostHook" type="xsd:string" minOccurs="0" />
<xsd:element name="updatePostHook" type="xsd:string" minOccurs="0" />
<xsd:element name="deletePostHook" type="xsd:string" minOccurs="0" />
<xsd:element name="changeIdPostHook" type="xsd:string" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="propertiesBasedSyncOptionsType">
<xsd:complexContent>
<xsd:extension base="syncOptionsType">
Expand All @@ -334,6 +343,7 @@
default="FORCE" />
<xsd:element name="conditions" type="conditionsType"
minOccurs="0" />
<xsd:element name="hooks" type="hooksType" minOccurs="0" />
<xsd:element name="dataset" type="datasetType"
minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
Expand Down
Loading

0 comments on commit 6d51dfe

Please sign in to comment.