diff --git a/pom.xml b/pom.xml index a7b330f6..7a0f41e9 100644 --- a/pom.xml +++ b/pom.xml @@ -872,6 +872,21 @@ xml-apis 1.4.01 + + com.fasterxml.jackson.core + jackson-core + 2.9.6 + + + com.fasterxml.jackson.core + jackson-annotations + 2.9.6 + + + com.fasterxml.jackson.core + jackson-databind + 2.9.6 + diff --git a/src/main/java/org/lsc/AbstractSynchronize.java b/src/main/java/org/lsc/AbstractSynchronize.java index 3e19b925..350d0d86 100644 --- a/src/main/java/org/lsc/AbstractSynchronize.java +++ b/src/main/java/org/lsc/AbstractSynchronize.java @@ -53,6 +53,12 @@ import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.TimeUnit; +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; import javax.naming.CommunicationException; @@ -257,6 +263,9 @@ protected final boolean clean2Ldap(Task task) { // 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(); logAction(lm, id, task.getName()); } else { @@ -828,6 +837,10 @@ 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; @@ -939,3 +952,101 @@ public synchronized int getCountCompleted() { return countCompleted; } } + +/** + * This object is managing posthook scripts + */ +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; + } + +} diff --git a/src/main/java/org/lsc/beans/syncoptions/ForceSyncOptions.java b/src/main/java/org/lsc/beans/syncoptions/ForceSyncOptions.java index f5f6c1ba..8157887e 100644 --- a/src/main/java/org/lsc/beans/syncoptions/ForceSyncOptions.java +++ b/src/main/java/org/lsc/beans/syncoptions/ForceSyncOptions.java @@ -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(); } diff --git a/src/main/java/org/lsc/beans/syncoptions/ISyncOptions.java b/src/main/java/org/lsc/beans/syncoptions/ISyncOptions.java index 9df18858..d60bfee5 100644 --- a/src/main/java/org/lsc/beans/syncoptions/ISyncOptions.java +++ b/src/main/java/org/lsc/beans/syncoptions/ISyncOptions.java @@ -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 diff --git a/src/main/java/org/lsc/beans/syncoptions/PropertiesBasedSyncOptions.java b/src/main/java/org/lsc/beans/syncoptions/PropertiesBasedSyncOptions.java index aa04944d..deff1099 100644 --- a/src/main/java/org/lsc/beans/syncoptions/PropertiesBasedSyncOptions.java +++ b/src/main/java/org/lsc/beans/syncoptions/PropertiesBasedSyncOptions.java @@ -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); diff --git a/src/main/java/org/lsc/configuration/.gitignore b/src/main/java/org/lsc/configuration/.gitignore index faf60484..e83453ba 100644 --- a/src/main/java/org/lsc/configuration/.gitignore +++ b/src/main/java/org/lsc/configuration/.gitignore @@ -4,6 +4,7 @@ /AuditType.java /AuditsType.java /ConditionsType.java +/HooksType.java /ConnectionType.java /ConnectionsType.java /CsvAuditType.java diff --git a/src/main/resources/schemas/lsc-core-2.2.xsd b/src/main/resources/schemas/lsc-core-2.2.xsd index 968c0227..8f416e87 100644 --- a/src/main/resources/schemas/lsc-core-2.2.xsd +++ b/src/main/resources/schemas/lsc-core-2.2.xsd @@ -323,7 +323,16 @@ - + + + + + + + + + + @@ -334,6 +343,7 @@ default="FORCE" /> +