From 779718755c22b6a6ad1c8a4b5d040f8a65cc4058 Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Tue, 25 Jun 2013 17:03:15 +0200 Subject: More intelligent import of module resources. If resources or outcomes have been modified by a different user, do no overwrite them. Reset the properties and workflow though (should be fairly stateless), but leave the collections. --- .../predefined/entitycreation/CreateNewItem.java | 2 +- .../predefined/entitycreation/NewItem.java | 89 ++++++++++++++++++---- src/main/java/com/c2kernel/process/Bootstrap.java | 14 ++-- .../java/com/c2kernel/process/module/Module.java | 13 +--- .../com/c2kernel/process/module/ModuleManager.java | 6 +- 5 files changed, 91 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewItem.java b/src/main/java/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewItem.java index 824ca4f..5776a5a 100644 --- a/src/main/java/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewItem.java +++ b/src/main/java/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewItem.java @@ -36,7 +36,7 @@ public class CreateNewItem extends PredefinedStep try { NewItem item = (NewItem)Gateway.getMarshaller().unmarshall(requestData); - item.create(agent.getSysKey()); + item.create(agent.getSysKey(), false); } catch (Exception ex) { Logger.error(ex); throw new InvalidDataException("Error creating item", ""); diff --git a/src/main/java/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewItem.java b/src/main/java/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewItem.java index dfb19b8..1a9e2fa 100644 --- a/src/main/java/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewItem.java +++ b/src/main/java/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewItem.java @@ -3,8 +3,12 @@ package com.c2kernel.lifecycle.instance.predefined.entitycreation; import java.util.ArrayList; +import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.XMLUnit; + import com.c2kernel.collection.MembershipException; import com.c2kernel.common.CannotManageException; +import com.c2kernel.common.InvalidDataException; import com.c2kernel.common.ObjectAlreadyExistsException; import com.c2kernel.common.ObjectCannotBeUpdated; import com.c2kernel.common.ObjectNotFoundException; @@ -16,6 +20,7 @@ import com.c2kernel.lifecycle.instance.stateMachine.States; import com.c2kernel.lifecycle.instance.stateMachine.Transitions; import com.c2kernel.lookup.DomainPath; import com.c2kernel.lookup.EntityPath; +import com.c2kernel.persistency.ClusterStorage; import com.c2kernel.persistency.ClusterStorageException; import com.c2kernel.persistency.outcome.Viewpoint; import com.c2kernel.process.Gateway; @@ -60,16 +65,21 @@ public class NewItem extends ModuleImport { return ns; } - public void create(int agentId) throws ObjectCannotBeUpdated, ObjectNotFoundException, CannotManageException, ObjectAlreadyExistsException { + public void create(int agentId, boolean reset) throws ObjectCannotBeUpdated, ObjectNotFoundException, CannotManageException, ObjectAlreadyExistsException { DomainPath domPath = new DomainPath(new DomainPath(initialPath), name); - if (domPath.exists()) - throw new ObjectAlreadyExistsException(domPath+" already exists!", ""); - - // create item - EntityPath entPath = Gateway.getLDAPLookup().getNextKeyManager().generateNextEntityKey(); - TraceableEntity newItem = (TraceableEntity)Gateway.getCorbaServer().createEntity(entPath); - Gateway.getLDAPLookup().add(entPath); + EntityPath entPath; TraceableEntity newItem; + if (domPath.exists()) { + entPath = domPath.getEntity(); + newItem = Gateway.getCorbaServer().getItem(entPath.getSysKey()); + } + else { + // create item + entPath = Gateway.getLDAPLookup().getNextKeyManager().generateNextEntityKey(); + newItem = (TraceableEntity)Gateway.getCorbaServer().createEntity(entPath); + Gateway.getLDAPLookup().add(entPath); + } + // set the name property properties.add(new Property("Name", name)); @@ -89,27 +99,66 @@ public class NewItem extends ModuleImport { } // import outcomes - + XMLUnit.setIgnoreWhitespace(true); + XMLUnit.setIgnoreComments(true); History hist = new History(entPath.getSysKey(), null); for (Outcome thisOutcome : outcomes) { - Event newEvent = hist.addEvent("system", "Admin", Transitions.DONE, "Import", "Import", "Import", thisOutcome.viewname.equals("last")?null:thisOutcome.viewname, States.FINISHED); - com.c2kernel.persistency.outcome.Outcome newOutcome = new com.c2kernel.persistency.outcome.Outcome(newEvent.getID(), thisOutcome.getData(ns), thisOutcome.schema, thisOutcome.version); - Viewpoint newLastView = new Viewpoint(entPath.getSysKey(), thisOutcome.schema, thisOutcome.viewname, thisOutcome.version, newEvent.getID()); + com.c2kernel.persistency.outcome.Outcome newOutcome = new com.c2kernel.persistency.outcome.Outcome(-1, thisOutcome.getData(ns), thisOutcome.schema, thisOutcome.version); + Viewpoint impView; + try { + impView = (Viewpoint)Gateway.getStorage().get(entPath.getSysKey(), ClusterStorage.VIEWPOINT+"/"+thisOutcome.schema+"/"+thisOutcome.viewname, null); + String oldData = impView.getOutcome().getData(); + + Diff xmlDiff = new Diff(newOutcome.getDOM(), impView.getOutcome().getDOM()); + if (xmlDiff.identical()) { + Logger.msg(5, "NewItem.create() - View "+thisOutcome.schema+"/"+thisOutcome.viewname+" in "+name+" identical, no update required"); + return; + } + else { + Logger.msg("NewItem.create() - Difference found in view "+thisOutcome.schema+"/"+thisOutcome.viewname+" in "+name+": "+xmlDiff.toString()); + if (!reset && !impView.getEvent().getStepPath().equals("Import")) { + Logger.msg("Last edit was not done by import, and reset not requested. Not overwriting."); + continue; + } + } + } catch (ObjectNotFoundException ex) { + Logger.msg(3, "View "+thisOutcome.schema+"/"+thisOutcome.viewname+" not found in "+name+". Creating."); + impView = new Viewpoint(entPath.getSysKey(), thisOutcome.schema, thisOutcome.viewname, thisOutcome.version, -1); + } catch (ClusterStorageException e) { + throw new ObjectCannotBeUpdated("Could not check data for view "+thisOutcome.schema+"/"+thisOutcome.viewname+" in "+name); + } catch (InvalidDataException e) { + throw new ObjectCannotBeUpdated("Could not check previous event for view "+thisOutcome.schema+"/"+thisOutcome.viewname+" in "+name); + } + + // write new view/outcome/event + Event newEvent = hist.addEvent("system", "Admin", Transitions.DONE, "Import", "Import", "Import", thisOutcome.viewname, States.FINISHED); + newOutcome.setID(newEvent.getID()); + impView.setEventId(newEvent.getID()); try { Gateway.getStorage().put(entPath.getSysKey(), newOutcome, null); - Gateway.getStorage().put(entPath.getSysKey(), newLastView, null); + Gateway.getStorage().put(entPath.getSysKey(), impView, null); } catch (ClusterStorageException e) { throw new ObjectCannotBeUpdated("Could not store data for view "+thisOutcome.schema+"/"+thisOutcome.viewname+" in "+name); } } // register domain path (before collections in case of recursive collections) - domPath.setEntity(entPath); - Gateway.getLDAPLookup().add(domPath); + if (!domPath.exists()) { + domPath.setEntity(entPath); + Gateway.getLDAPLookup().add(domPath); + } // create collections for (Dependency element: dependencyList) { try { + com.c2kernel.collection.Dependency newDep = element.create(); + if (!reset) { + try { + Gateway.getStorage().get(entPath.getSysKey(), ClusterStorage.COLLECTION+"/"+newDep.getName(), null); + Logger.msg("Not overwriting dependency "+newDep.getName()); + continue; // TODO: a proper compare here + } catch (ObjectNotFoundException ex) { } // doesn't exist, ok to create + } Gateway.getStorage().put(entPath.getSysKey(), element.create(), null); } catch (ClusterStorageException ex) { Logger.error(ex); @@ -122,7 +171,15 @@ public class NewItem extends ModuleImport { for (Aggregation element : aggregationList) { try { - Gateway.getStorage().put(entPath.getSysKey(), element.create(), null); + com.c2kernel.collection.Aggregation newAgg = element.create(); + if (!reset) { + try { + Gateway.getStorage().get(entPath.getSysKey(), ClusterStorage.COLLECTION+"/"+newAgg.getName(), null); + Logger.msg("Not overwriting aggregation "+newAgg.getName()); + continue; // TODO: a proper compare here + } catch (ObjectNotFoundException ex) { } // doesn't exist, ok to create + } + Gateway.getStorage().put(entPath.getSysKey(), newAgg, null); } catch (ClusterStorageException ex) { Logger.error(ex); throw new CannotManageException("Could not create Aggregation "+element.name, ""); diff --git a/src/main/java/com/c2kernel/process/Bootstrap.java b/src/main/java/com/c2kernel/process/Bootstrap.java index 065ef1a..6a87d34 100644 --- a/src/main/java/com/c2kernel/process/Bootstrap.java +++ b/src/main/java/com/c2kernel/process/Bootstrap.java @@ -73,7 +73,7 @@ public class Bootstrap Gateway.getModuleManager().registerModules(); Logger.msg("Bootstrap.run() - Bootstrapping complete"); - } catch (Exception e) { + } catch (Throwable e) { Logger.error(e); Logger.die("Exception performing bootstrap. Check that everything is OK."); } @@ -88,11 +88,11 @@ public class Bootstrap String bootItems; Logger.msg(1, "Verifying kernel boot items"); bootItems = FileStringUtility.url2String(Resource.getKernelResourceURL("boot/allbootitems.txt")); - verifyBootDataItems(bootItems, null); + verifyBootDataItems(bootItems, null, true); Logger.msg(1, "Boot data items complete"); } - private static void verifyBootDataItems(String bootList, String ns) { + private static void verifyBootDataItems(String bootList, String ns, boolean reset) { StringTokenizer str = new StringTokenizer(bootList, "\n\r"); while (str.hasMoreTokens()) { String thisItem = str.nextToken(); @@ -103,7 +103,7 @@ public class Bootstrap String data = Resource.getTextResource(ns, "boot/"+thisItem+(itemType.equals("OD")?".xsd":".xml")); if (data == null) Logger.die("No data found for "+getDataType(itemType)+" "+itemName); - verifyResource(ns, itemName, itemType, data); + verifyResource(ns, itemName, itemType, data, reset); } catch (Exception e) { Logger.error(e); Logger.die("Error importing bootstrap items. Unsafe to continue."); @@ -112,7 +112,7 @@ public class Bootstrap } - public static void verifyResource(String ns, String itemName, String itemType, String data) throws Exception { + public static void verifyResource(String ns, String itemName, String itemType, String data, boolean reset) throws Exception { Logger.msg(1, "Bootstrap.verifyResource() - Verifying data of "+getDataType(itemType)+" "+itemName); Enumeration en = Gateway.getLDAPLookup().search(getTypeRoot(itemType), itemName); ItemProxy thisProxy; @@ -137,6 +137,10 @@ public class Bootstrap } else { Logger.msg("Difference found in "+itemName+": "+xmlDiff.toString()); + if (!reset && !currentData.getEvent().getStepPath().equals("Bootstrap")) { + Logger.msg("Last import was not done by Bootstrap, and reset not requested. Not overwriting."); + return; + } } } catch (ObjectNotFoundException ex) { diff --git a/src/main/java/com/c2kernel/process/module/Module.java b/src/main/java/com/c2kernel/process/module/Module.java index a7a85bb..c93a695 100644 --- a/src/main/java/com/c2kernel/process/module/Module.java +++ b/src/main/java/com/c2kernel/process/module/Module.java @@ -11,7 +11,6 @@ import com.c2kernel.lifecycle.instance.predefined.entitycreation.NewAgent; import com.c2kernel.lifecycle.instance.predefined.entitycreation.NewItem; import com.c2kernel.lifecycle.instance.predefined.entitycreation.NewRole; import com.c2kernel.lifecycle.instance.predefined.entitycreation.Outcome; -import com.c2kernel.lookup.DomainPath; import com.c2kernel.lookup.RolePath; import com.c2kernel.process.Bootstrap; import com.c2kernel.process.Gateway; @@ -74,13 +73,13 @@ public class Module { imports.list.add(moduleItem); } - public void importAll(ItemProxy serverEntity, String moduleXML) throws Exception { + public void importAll(ItemProxy serverEntity, String moduleXML, boolean reset) throws Exception { addModuleItem(moduleXML); int systemAgentId = Gateway.getLDAPLookup().getRoleManager().getAgentPath("system").getSysKey(); for (ModuleResource thisRes : imports.getResources()) { try { - Bootstrap.verifyResource(ns, thisRes.name, thisRes.resourceType, Resource.getTextResource(ns, thisRes.resourceLocation)); + Bootstrap.verifyResource(ns, thisRes.name, thisRes.resourceType, Resource.getTextResource(ns, thisRes.resourceLocation), reset); } catch (Exception ex) { Logger.error(ex); } @@ -112,13 +111,7 @@ public class Module { for (NewItem thisItem : imports.getItems()) { thisItem.setNamespace(ns); - try { - new DomainPath(new DomainPath(thisItem.initialPath), thisItem.name).getEntity(); - Logger.msg(3, "Module.importAll() - Item '"+thisItem.name+"' found."); - continue; - } catch (ObjectNotFoundException ex) { } - Logger.msg("Module.importAll() - Item '"+thisItem.name+"' not found. Creating."); - thisItem.create(systemAgentId); + thisItem.create(systemAgentId, reset); } } diff --git a/src/main/java/com/c2kernel/process/module/ModuleManager.java b/src/main/java/com/c2kernel/process/module/ModuleManager.java index b4c990f..f072f66 100644 --- a/src/main/java/com/c2kernel/process/module/ModuleManager.java +++ b/src/main/java/com/c2kernel/process/module/ModuleManager.java @@ -144,11 +144,15 @@ public class ModuleManager { } Logger.debug(3, "Registering modules"); + boolean reset = Gateway.getProperty("Module.reset", "false").equals("true"); + for (Module thisMod : modules) { Logger.msg("Registering module "+thisMod.getName()); try { - thisMod.importAll(serverEntity, modulesXML.get(thisMod.ns)); + String nsReset = Gateway.getProperty("Module."+thisMod.ns+".reset"); + boolean thisReset = nsReset == null?reset:nsReset.equals("true"); + thisMod.importAll(serverEntity, modulesXML.get(thisMod.ns), thisReset); } catch (Exception e) { Logger.error(e); throw new ModuleException("Error importing items for module "+thisMod.getName()); -- cgit v1.2.3