From 0ed2c1124cf1b9e49a2ec1fa0126a8df09f9e758 Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Tue, 7 Oct 2014 09:18:11 +0200 Subject: Repackage to org.cristalise --- .../cristalise/kernel/collection/Aggregation.java | 178 +++++++ .../kernel/collection/AggregationDescription.java | 82 +++ .../kernel/collection/AggregationInstance.java | 69 +++ .../kernel/collection/AggregationMember.java | 170 ++++++ .../collection/AggregationVertexFactory.java | 59 +++ .../AggregationVertexOutlineCreator.java | 68 +++ .../cristalise/kernel/collection/Collection.java | 262 ++++++++++ .../kernel/collection/CollectionArrayList.java | 60 +++ .../kernel/collection/CollectionDescription.java | 41 ++ .../kernel/collection/CollectionMember.java | 99 ++++ .../kernel/collection/CollectionMemberList.java | 39 ++ .../cristalise/kernel/collection/Dependency.java | 147 ++++++ .../kernel/collection/DependencyDescription.java | 79 +++ .../kernel/collection/DependencyMember.java | 165 ++++++ .../cristalise/kernel/collection/package-info.java | 27 + .../cristalise/kernel/entity/C2KLocalObject.java | 52 ++ .../org/cristalise/kernel/entity/CorbaServer.java | 204 ++++++++ .../kernel/entity/ItemImplementation.java | 333 ++++++++++++ .../cristalise/kernel/entity/TraceableEntity.java | 154 ++++++ .../cristalise/kernel/entity/TraceableLocator.java | 90 ++++ .../kernel/entity/agent/ActiveEntity.java | 156 ++++++ .../kernel/entity/agent/ActiveLocator.java | 100 ++++ .../kernel/entity/agent/AgentImplementation.java | 137 +++++ .../org/cristalise/kernel/entity/agent/Job.java | 484 +++++++++++++++++ .../kernel/entity/agent/JobArrayList.java | 42 ++ .../cristalise/kernel/entity/agent/JobList.java | 138 +++++ .../kernel/entity/agent/package-info.java | 32 ++ .../cristalise/kernel/entity/imports/Geometry.java | 48 ++ .../kernel/entity/imports/ImportAgent.java | 118 +++++ .../kernel/entity/imports/ImportAggregation.java | 91 ++++ .../entity/imports/ImportAggregationMember.java | 55 ++ .../kernel/entity/imports/ImportDependency.java | 107 ++++ .../entity/imports/ImportDependencyMember.java | 48 ++ .../kernel/entity/imports/ImportItem.java | 280 ++++++++++ .../kernel/entity/imports/ImportOutcome.java | 48 ++ .../kernel/entity/imports/ImportRole.java | 75 +++ .../org/cristalise/kernel/entity/package-info.java | 39 ++ .../cristalise/kernel/entity/proxy/AgentProxy.java | 323 ++++++++++++ .../kernel/entity/proxy/DomainPathSubscriber.java | 38 ++ .../cristalise/kernel/entity/proxy/ItemProxy.java | 390 ++++++++++++++ .../kernel/entity/proxy/MemberSubscription.java | 141 +++++ .../kernel/entity/proxy/ProxyClientConnection.java | 208 ++++++++ .../kernel/entity/proxy/ProxyManager.java | 277 ++++++++++ .../kernel/entity/proxy/ProxyMessage.java | 129 +++++ .../kernel/entity/proxy/ProxyObserver.java | 47 ++ .../kernel/entity/proxy/ProxyServer.java | 129 +++++ .../kernel/entity/proxy/ProxyServerConnection.java | 145 ++++++ .../kernel/entity/proxy/package-info.java | 76 +++ .../kernel/entity/transfer/TransferItem.java | 177 +++++++ .../kernel/entity/transfer/TransferSet.java | 94 ++++ .../kernel/entity/transfer/package-info.java | 36 ++ .../java/org/cristalise/kernel/events/Event.java | 369 +++++++++++++ .../java/org/cristalise/kernel/events/History.java | 152 ++++++ .../org/cristalise/kernel/events/package-info.java | 29 ++ .../kernel/graph/event/ClearedEvent.java | 26 + .../kernel/graph/event/EdgeRemovedEvent.java | 26 + .../kernel/graph/event/EdgesChangedEvent.java | 26 + .../graph/event/EntireModelChangedEvent.java | 26 + .../kernel/graph/event/ForcedNotifyEvent.java | 26 + .../kernel/graph/event/GraphModelEvent.java | 26 + .../kernel/graph/event/GraphModelResizedEvent.java | 26 + .../graph/event/NewEdgeEndPointChangedEvent.java | 26 + .../graph/event/StartVertexIdChangedEvent.java | 26 + .../kernel/graph/event/VertexAddedEvent.java | 26 + .../kernel/graph/event/VertexCreatedEvent.java | 26 + .../kernel/graph/event/VertexMovedEvent.java | 26 + .../kernel/graph/event/VertexRemovedEvent.java | 26 + .../kernel/graph/event/VerticesChangedEvent.java | 26 + .../graph/layout/DefaultGraphLayoutGenerator.java | 139 +++++ .../kernel/graph/model/DirectedEdge.java | 118 +++++ .../cristalise/kernel/graph/model/EdgeFactory.java | 34 ++ .../cristalise/kernel/graph/model/GraphModel.java | 544 +++++++++++++++++++ .../kernel/graph/model/GraphModelCastorData.java | 50 ++ .../kernel/graph/model/GraphModelManager.java | 157 ++++++ .../cristalise/kernel/graph/model/GraphPoint.java | 37 ++ .../cristalise/kernel/graph/model/Graphable.java | 75 +++ .../kernel/graph/model/GraphableEdge.java | 91 ++++ .../kernel/graph/model/GraphableVertex.java | 284 ++++++++++ .../graph/model/TypeNameAndConstructionInfo.java | 43 ++ .../org/cristalise/kernel/graph/model/Vertex.java | 327 ++++++++++++ .../kernel/graph/model/VertexFactory.java | 33 ++ .../kernel/graph/model/VertexOutlineCreator.java | 30 ++ .../org/cristalise/kernel/graph/package-info.java | 29 ++ .../kernel/graph/traversal/GraphTraversal.java | 106 ++++ .../cristalise/kernel/lifecycle/ActivityDef.java | 163 ++++++ .../kernel/lifecycle/ActivitySlotDef.java | 201 ++++++++ .../cristalise/kernel/lifecycle/AndSplitDef.java | 135 +++++ .../kernel/lifecycle/CompositeActivityDef.java | 266 ++++++++++ .../org/cristalise/kernel/lifecycle/JoinDef.java | 88 ++++ .../org/cristalise/kernel/lifecycle/LoopDef.java | 98 ++++ .../org/cristalise/kernel/lifecycle/NextDef.java | 115 +++++ .../cristalise/kernel/lifecycle/OrSplitDef.java | 44 ++ .../kernel/lifecycle/WfCastorHashMap.java | 48 ++ .../cristalise/kernel/lifecycle/WfVertexDef.java | 112 ++++ .../lifecycle/WfVertexDefOutlineCreator.java | 70 +++ .../cristalise/kernel/lifecycle/XOrSplitDef.java | 48 ++ .../kernel/lifecycle/instance/Activity.java | 573 +++++++++++++++++++++ .../lifecycle/instance/AdvancementCalculator.java | 243 +++++++++ .../kernel/lifecycle/instance/AndSplit.java | 49 ++ .../lifecycle/instance/CompositeActivity.java | 469 +++++++++++++++++ .../kernel/lifecycle/instance/JobPusher.java | 81 +++ .../cristalise/kernel/lifecycle/instance/Join.java | 233 +++++++++ .../cristalise/kernel/lifecycle/instance/Loop.java | 130 +++++ .../cristalise/kernel/lifecycle/instance/Next.java | 103 ++++ .../kernel/lifecycle/instance/OrSplit.java | 90 ++++ .../kernel/lifecycle/instance/Split.java | 239 +++++++++ .../kernel/lifecycle/instance/WfVertex.java | 223 ++++++++ .../lifecycle/instance/WfVertexOutlineCreator.java | 69 +++ .../kernel/lifecycle/instance/Workflow.java | 266 ++++++++++ .../kernel/lifecycle/instance/XOrSplit.java | 84 +++ .../instance/predefined/AddC2KObject.java | 67 +++ .../instance/predefined/AddDomainPath.java | 62 +++ .../instance/predefined/AddMemberToCollection.java | 105 ++++ .../predefined/AddNewCollectionDescription.java | 110 ++++ .../lifecycle/instance/predefined/AddNewSlot.java | 128 +++++ .../instance/predefined/AssignItemToSlot.java | 121 +++++ .../lifecycle/instance/predefined/ClearSlot.java | 114 ++++ .../predefined/CreateNewCollectionVersion.java | 103 ++++ .../lifecycle/instance/predefined/Import.java | 106 ++++ .../instance/predefined/PredefinedStep.java | 191 +++++++ .../predefined/PredefinedStepContainer.java | 79 +++ .../instance/predefined/RemoveC2KObject.java | 70 +++ .../instance/predefined/RemoveDomainPath.java | 73 +++ .../predefined/RemoveSlotFromCollection.java | 131 +++++ .../instance/predefined/ReplaceDomainWorkflow.java | 77 +++ .../instance/predefined/WriteProperty.java | 80 +++ .../instance/predefined/WriteViewpoint.java | 88 ++++ .../agent/AgentPredefinedStepContainer.java | 47 ++ .../agent/CreateAgentFromDescription.java | 137 +++++ .../instance/predefined/agent/RemoveAgent.java | 90 ++++ .../predefined/agent/SetAgentPassword.java | 70 +++ .../instance/predefined/agent/SetAgentRoles.java | 94 ++++ .../predefined/item/CreateItemFromDescription.java | 195 +++++++ .../lifecycle/instance/predefined/item/Erase.java | 80 +++ .../item/ItemPredefinedStepContainer.java | 45 ++ .../predefined/server/AddDomainContext.java | 67 +++ .../instance/predefined/server/CreateNewAgent.java | 68 +++ .../instance/predefined/server/CreateNewItem.java | 63 +++ .../instance/predefined/server/CreateNewRole.java | 60 +++ .../predefined/server/RemoveDomainContext.java | 65 +++ .../instance/predefined/server/RemoveRole.java | 68 +++ .../server/ServerPredefinedStepContainer.java | 62 +++ .../lifecycle/instance/stateMachine/State.java | 101 ++++ .../instance/stateMachine/StateMachine.java | 178 +++++++ .../instance/stateMachine/Transition.java | 345 +++++++++++++ .../instance/stateMachine/TransitionOutcome.java | 57 ++ .../instance/stateMachine/TransitionResource.java | 29 ++ .../instance/stateMachine/TransitionScript.java | 48 ++ .../cristalise/kernel/lifecycle/package-info.java | 30 ++ .../routingHelpers/ViewpointDataHelper.java | 86 ++++ .../org/cristalise/kernel/lookup/AgentPath.java | 159 ++++++ .../org/cristalise/kernel/lookup/DomainPath.java | 136 +++++ .../kernel/lookup/InvalidAgentPathException.java | 33 ++ .../kernel/lookup/InvalidItemPathException.java | 33 ++ .../kernel/lookup/InvalidPathException.java | 33 ++ .../org/cristalise/kernel/lookup/ItemPath.java | 120 +++++ .../java/org/cristalise/kernel/lookup/Lookup.java | 175 +++++++ .../cristalise/kernel/lookup/LookupManager.java | 124 +++++ .../java/org/cristalise/kernel/lookup/Path.java | 243 +++++++++ .../org/cristalise/kernel/lookup/RolePath.java | 116 +++++ .../kernel/persistency/ClusterStorage.java | 296 +++++++++++ .../kernel/persistency/ClusterStorageManager.java | 413 +++++++++++++++ .../cristalise/kernel/persistency/RemoteMap.java | 398 ++++++++++++++ .../kernel/persistency/TransactionManager.java | 353 +++++++++++++ .../kernel/persistency/outcome/Outcome.java | 290 +++++++++++ .../persistency/outcome/OutcomeInitiator.java | 31 ++ .../persistency/outcome/OutcomeValidator.java | 207 ++++++++ .../kernel/persistency/outcome/Schema.java | 73 +++ .../persistency/outcome/SchemaValidator.java | 55 ++ .../kernel/persistency/outcome/Viewpoint.java | 191 +++++++ .../cristalise/kernel/process/AbstractMain.java | 178 +++++++ .../org/cristalise/kernel/process/Bootstrap.java | 394 ++++++++++++++ .../org/cristalise/kernel/process/ClientShell.java | 71 +++ .../org/cristalise/kernel/process/Gateway.java | 426 +++++++++++++++ .../cristalise/kernel/process/ShutdownHandler.java | 26 + .../cristalise/kernel/process/StandardClient.java | 31 ++ .../cristalise/kernel/process/StandardServer.java | 67 +++ .../cristalise/kernel/process/UserCodeProcess.java | 276 ++++++++++ .../kernel/process/auth/Authenticator.java | 93 ++++ .../kernel/process/auth/ConsoleAuth.java | 65 +++ .../cristalise/kernel/process/auth/ProxyLogin.java | 42 ++ .../cristalise/kernel/process/module/Module.java | 224 ++++++++ .../kernel/process/module/ModuleConfig.java | 42 ++ .../kernel/process/module/ModuleException.java | 29 ++ .../kernel/process/module/ModuleImport.java | 87 ++++ .../kernel/process/module/ModuleImports.java | 78 +++ .../kernel/process/module/ModuleInfo.java | 34 ++ .../kernel/process/module/ModuleManager.java | 211 ++++++++ .../kernel/process/module/ModuleResource.java | 80 +++ .../kernel/process/module/ModuleScript.java | 53 ++ .../process/resource/BadArgumentsException.java | 37 ++ .../resource/DefaultResourceImportHandler.java | 106 ++++ .../kernel/process/resource/Resource.java | 196 +++++++ .../process/resource/ResourceImportHandler.java | 68 +++ .../kernel/process/resource/ResourceLoader.java | 67 +++ .../org/cristalise/kernel/property/Property.java | 112 ++++ .../kernel/property/PropertyArrayList.java | 54 ++ .../kernel/property/PropertyDescription.java | 88 ++++ .../kernel/property/PropertyDescriptionList.java | 94 ++++ .../kernel/property/PropertyUtility.java | 96 ++++ .../org/cristalise/kernel/scripting/ErrorInfo.java | 75 +++ .../org/cristalise/kernel/scripting/Parameter.java | 72 +++ .../kernel/scripting/ParameterException.java | 40 ++ .../org/cristalise/kernel/scripting/Script.java | 572 ++++++++++++++++++++ .../cristalise/kernel/scripting/ScriptConsole.java | 234 +++++++++ .../kernel/scripting/ScriptErrorException.java | 50 ++ .../kernel/scripting/ScriptLoadingException.java | 44 ++ .../kernel/scripting/ScriptParsingException.java | 41 ++ .../kernel/scripting/ScriptingEngineException.java | 40 ++ .../org/cristalise/kernel/utils/ActDefCache.java | 68 +++ .../cristalise/kernel/utils/CastorArrayList.java | 74 +++ .../org/cristalise/kernel/utils/CastorHashMap.java | 101 ++++ .../cristalise/kernel/utils/CastorXMLUtility.java | 188 +++++++ .../org/cristalise/kernel/utils/DateUtility.java | 138 +++++ .../cristalise/kernel/utils/DescriptionObject.java | 31 ++ .../kernel/utils/DescriptionObjectCache.java | 105 ++++ .../cristalise/kernel/utils/FileStringUtility.java | 450 ++++++++++++++++ .../kernel/utils/GTimeStampComparator.java | 46 ++ .../org/cristalise/kernel/utils/KeyValuePair.java | 107 ++++ .../java/org/cristalise/kernel/utils/Language.java | 86 ++++ .../cristalise/kernel/utils/LocalObjectLoader.java | 111 ++++ .../java/org/cristalise/kernel/utils/Logger.java | 207 ++++++++ .../cristalise/kernel/utils/ObjectProperties.java | 215 ++++++++ .../org/cristalise/kernel/utils/SoftCache.java | 139 +++++ .../cristalise/kernel/utils/StateMachineCache.java | 67 +++ .../cristalise/kernel/utils/TransientCache.java | 149 ++++++ .../org/cristalise/kernel/utils/WeakCache.java | 154 ++++++ .../cristalise/kernel/utils/XmlElementParser.java | 125 +++++ .../kernel/utils/server/SimpleTCPIPServer.java | 130 +++++ .../kernel/utils/server/SocketHandler.java | 35 ++ .../storage/MemoryOnlyClusterStorage.java | 166 ++++++ .../java/org/cristalise/storage/ProxyLoader.java | 160 ++++++ .../org/cristalise/storage/XMLClusterStorage.java | 178 +++++++ 233 files changed, 28929 insertions(+) create mode 100644 src/main/java/org/cristalise/kernel/collection/Aggregation.java create mode 100644 src/main/java/org/cristalise/kernel/collection/AggregationDescription.java create mode 100644 src/main/java/org/cristalise/kernel/collection/AggregationInstance.java create mode 100644 src/main/java/org/cristalise/kernel/collection/AggregationMember.java create mode 100644 src/main/java/org/cristalise/kernel/collection/AggregationVertexFactory.java create mode 100644 src/main/java/org/cristalise/kernel/collection/AggregationVertexOutlineCreator.java create mode 100644 src/main/java/org/cristalise/kernel/collection/Collection.java create mode 100644 src/main/java/org/cristalise/kernel/collection/CollectionArrayList.java create mode 100644 src/main/java/org/cristalise/kernel/collection/CollectionDescription.java create mode 100644 src/main/java/org/cristalise/kernel/collection/CollectionMember.java create mode 100644 src/main/java/org/cristalise/kernel/collection/CollectionMemberList.java create mode 100644 src/main/java/org/cristalise/kernel/collection/Dependency.java create mode 100644 src/main/java/org/cristalise/kernel/collection/DependencyDescription.java create mode 100644 src/main/java/org/cristalise/kernel/collection/DependencyMember.java create mode 100644 src/main/java/org/cristalise/kernel/collection/package-info.java create mode 100644 src/main/java/org/cristalise/kernel/entity/C2KLocalObject.java create mode 100644 src/main/java/org/cristalise/kernel/entity/CorbaServer.java create mode 100644 src/main/java/org/cristalise/kernel/entity/ItemImplementation.java create mode 100644 src/main/java/org/cristalise/kernel/entity/TraceableEntity.java create mode 100644 src/main/java/org/cristalise/kernel/entity/TraceableLocator.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/ActiveEntity.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/ActiveLocator.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/AgentImplementation.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/Job.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/JobArrayList.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/JobList.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/package-info.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/Geometry.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportAgent.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportAggregation.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportAggregationMember.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportDependency.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportDependencyMember.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportItem.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportOutcome.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportRole.java create mode 100644 src/main/java/org/cristalise/kernel/entity/package-info.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/AgentProxy.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/DomainPathSubscriber.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ItemProxy.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/MemberSubscription.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyClientConnection.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyManager.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyMessage.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyObserver.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyServer.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyServerConnection.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/package-info.java create mode 100644 src/main/java/org/cristalise/kernel/entity/transfer/TransferItem.java create mode 100644 src/main/java/org/cristalise/kernel/entity/transfer/TransferSet.java create mode 100644 src/main/java/org/cristalise/kernel/entity/transfer/package-info.java create mode 100644 src/main/java/org/cristalise/kernel/events/Event.java create mode 100644 src/main/java/org/cristalise/kernel/events/History.java create mode 100644 src/main/java/org/cristalise/kernel/events/package-info.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/ClearedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/EdgeRemovedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/EdgesChangedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/EntireModelChangedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/ForcedNotifyEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/GraphModelEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/GraphModelResizedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/NewEdgeEndPointChangedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/StartVertexIdChangedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/VertexAddedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/VertexCreatedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/VertexMovedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/VertexRemovedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/event/VerticesChangedEvent.java create mode 100644 src/main/java/org/cristalise/kernel/graph/layout/DefaultGraphLayoutGenerator.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/DirectedEdge.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/EdgeFactory.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/GraphModel.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/GraphModelCastorData.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/GraphModelManager.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/GraphPoint.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/Graphable.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/GraphableEdge.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/GraphableVertex.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/TypeNameAndConstructionInfo.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/Vertex.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/VertexFactory.java create mode 100644 src/main/java/org/cristalise/kernel/graph/model/VertexOutlineCreator.java create mode 100644 src/main/java/org/cristalise/kernel/graph/package-info.java create mode 100644 src/main/java/org/cristalise/kernel/graph/traversal/GraphTraversal.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/ActivityDef.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/ActivitySlotDef.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/AndSplitDef.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/CompositeActivityDef.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/JoinDef.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/LoopDef.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/NextDef.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/OrSplitDef.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/WfCastorHashMap.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/WfVertexDef.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/WfVertexDefOutlineCreator.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/XOrSplitDef.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/Activity.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/AdvancementCalculator.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/AndSplit.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/CompositeActivity.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/JobPusher.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/Join.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/Loop.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/Next.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/OrSplit.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/Split.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertex.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertexOutlineCreator.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/Workflow.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/XOrSplit.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddC2KObject.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddDomainPath.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddMemberToCollection.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewCollectionDescription.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewSlot.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AssignItemToSlot.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ClearSlot.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/CreateNewCollectionVersion.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/Import.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStep.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStepContainer.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveC2KObject.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveDomainPath.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveSlotFromCollection.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteProperty.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteViewpoint.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/AgentPredefinedStepContainer.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/CreateAgentFromDescription.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/RemoveAgent.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/SetAgentPassword.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/SetAgentRoles.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/CreateItemFromDescription.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/Erase.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/ItemPredefinedStepContainer.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/AddDomainContext.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewAgent.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewItem.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewRole.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveDomainContext.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveRole.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/ServerPredefinedStepContainer.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/State.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/StateMachine.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/Transition.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionOutcome.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionResource.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionScript.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/package-info.java create mode 100644 src/main/java/org/cristalise/kernel/lifecycle/routingHelpers/ViewpointDataHelper.java create mode 100644 src/main/java/org/cristalise/kernel/lookup/AgentPath.java create mode 100644 src/main/java/org/cristalise/kernel/lookup/DomainPath.java create mode 100644 src/main/java/org/cristalise/kernel/lookup/InvalidAgentPathException.java create mode 100644 src/main/java/org/cristalise/kernel/lookup/InvalidItemPathException.java create mode 100644 src/main/java/org/cristalise/kernel/lookup/InvalidPathException.java create mode 100644 src/main/java/org/cristalise/kernel/lookup/ItemPath.java create mode 100644 src/main/java/org/cristalise/kernel/lookup/Lookup.java create mode 100644 src/main/java/org/cristalise/kernel/lookup/LookupManager.java create mode 100644 src/main/java/org/cristalise/kernel/lookup/Path.java create mode 100644 src/main/java/org/cristalise/kernel/lookup/RolePath.java create mode 100644 src/main/java/org/cristalise/kernel/persistency/ClusterStorage.java create mode 100644 src/main/java/org/cristalise/kernel/persistency/ClusterStorageManager.java create mode 100644 src/main/java/org/cristalise/kernel/persistency/RemoteMap.java create mode 100644 src/main/java/org/cristalise/kernel/persistency/TransactionManager.java create mode 100644 src/main/java/org/cristalise/kernel/persistency/outcome/Outcome.java create mode 100644 src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeInitiator.java create mode 100644 src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeValidator.java create mode 100644 src/main/java/org/cristalise/kernel/persistency/outcome/Schema.java create mode 100644 src/main/java/org/cristalise/kernel/persistency/outcome/SchemaValidator.java create mode 100644 src/main/java/org/cristalise/kernel/persistency/outcome/Viewpoint.java create mode 100644 src/main/java/org/cristalise/kernel/process/AbstractMain.java create mode 100644 src/main/java/org/cristalise/kernel/process/Bootstrap.java create mode 100644 src/main/java/org/cristalise/kernel/process/ClientShell.java create mode 100644 src/main/java/org/cristalise/kernel/process/Gateway.java create mode 100644 src/main/java/org/cristalise/kernel/process/ShutdownHandler.java create mode 100644 src/main/java/org/cristalise/kernel/process/StandardClient.java create mode 100644 src/main/java/org/cristalise/kernel/process/StandardServer.java create mode 100644 src/main/java/org/cristalise/kernel/process/UserCodeProcess.java create mode 100644 src/main/java/org/cristalise/kernel/process/auth/Authenticator.java create mode 100644 src/main/java/org/cristalise/kernel/process/auth/ConsoleAuth.java create mode 100644 src/main/java/org/cristalise/kernel/process/auth/ProxyLogin.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/Module.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleConfig.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleException.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleImport.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleImports.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleInfo.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleManager.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleResource.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleScript.java create mode 100644 src/main/java/org/cristalise/kernel/process/resource/BadArgumentsException.java create mode 100644 src/main/java/org/cristalise/kernel/process/resource/DefaultResourceImportHandler.java create mode 100644 src/main/java/org/cristalise/kernel/process/resource/Resource.java create mode 100644 src/main/java/org/cristalise/kernel/process/resource/ResourceImportHandler.java create mode 100644 src/main/java/org/cristalise/kernel/process/resource/ResourceLoader.java create mode 100644 src/main/java/org/cristalise/kernel/property/Property.java create mode 100644 src/main/java/org/cristalise/kernel/property/PropertyArrayList.java create mode 100644 src/main/java/org/cristalise/kernel/property/PropertyDescription.java create mode 100644 src/main/java/org/cristalise/kernel/property/PropertyDescriptionList.java create mode 100644 src/main/java/org/cristalise/kernel/property/PropertyUtility.java create mode 100644 src/main/java/org/cristalise/kernel/scripting/ErrorInfo.java create mode 100644 src/main/java/org/cristalise/kernel/scripting/Parameter.java create mode 100644 src/main/java/org/cristalise/kernel/scripting/ParameterException.java create mode 100644 src/main/java/org/cristalise/kernel/scripting/Script.java create mode 100644 src/main/java/org/cristalise/kernel/scripting/ScriptConsole.java create mode 100644 src/main/java/org/cristalise/kernel/scripting/ScriptErrorException.java create mode 100644 src/main/java/org/cristalise/kernel/scripting/ScriptLoadingException.java create mode 100644 src/main/java/org/cristalise/kernel/scripting/ScriptParsingException.java create mode 100644 src/main/java/org/cristalise/kernel/scripting/ScriptingEngineException.java create mode 100644 src/main/java/org/cristalise/kernel/utils/ActDefCache.java create mode 100644 src/main/java/org/cristalise/kernel/utils/CastorArrayList.java create mode 100644 src/main/java/org/cristalise/kernel/utils/CastorHashMap.java create mode 100644 src/main/java/org/cristalise/kernel/utils/CastorXMLUtility.java create mode 100644 src/main/java/org/cristalise/kernel/utils/DateUtility.java create mode 100644 src/main/java/org/cristalise/kernel/utils/DescriptionObject.java create mode 100644 src/main/java/org/cristalise/kernel/utils/DescriptionObjectCache.java create mode 100644 src/main/java/org/cristalise/kernel/utils/FileStringUtility.java create mode 100644 src/main/java/org/cristalise/kernel/utils/GTimeStampComparator.java create mode 100644 src/main/java/org/cristalise/kernel/utils/KeyValuePair.java create mode 100644 src/main/java/org/cristalise/kernel/utils/Language.java create mode 100644 src/main/java/org/cristalise/kernel/utils/LocalObjectLoader.java create mode 100644 src/main/java/org/cristalise/kernel/utils/Logger.java create mode 100644 src/main/java/org/cristalise/kernel/utils/ObjectProperties.java create mode 100644 src/main/java/org/cristalise/kernel/utils/SoftCache.java create mode 100644 src/main/java/org/cristalise/kernel/utils/StateMachineCache.java create mode 100644 src/main/java/org/cristalise/kernel/utils/TransientCache.java create mode 100644 src/main/java/org/cristalise/kernel/utils/WeakCache.java create mode 100644 src/main/java/org/cristalise/kernel/utils/XmlElementParser.java create mode 100644 src/main/java/org/cristalise/kernel/utils/server/SimpleTCPIPServer.java create mode 100644 src/main/java/org/cristalise/kernel/utils/server/SocketHandler.java create mode 100644 src/main/java/org/cristalise/storage/MemoryOnlyClusterStorage.java create mode 100644 src/main/java/org/cristalise/storage/ProxyLoader.java create mode 100644 src/main/java/org/cristalise/storage/XMLClusterStorage.java (limited to 'src/main/java/org') diff --git a/src/main/java/org/cristalise/kernel/collection/Aggregation.java b/src/main/java/org/cristalise/kernel/collection/Aggregation.java new file mode 100644 index 0000000..2ae450b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/Aggregation.java @@ -0,0 +1,178 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.collection; + +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.graph.model.GraphModel; +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.graph.model.TypeNameAndConstructionInfo; +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.Language; +import org.cristalise.kernel.utils.Logger; + + +/** + * A Collection with a graph layout + */ + +abstract public class Aggregation extends Collection +{ + + protected GraphModel mLayout = new GraphModel(new AggregationVertexOutlineCreator()); + + private final TypeNameAndConstructionInfo[] mVertexTypeNameAndConstructionInfo = { + new TypeNameAndConstructionInfo(Language.translate("Slot"), "AggregationMember") + }; + + public Aggregation() + { + setName("Aggregation"); + } + + + public GraphModel getLayout() + { + return mLayout; + } + + public void setLayout(GraphModel layout) + { + mLayout = layout; + layout.setVertexOutlineCreator(new AggregationVertexOutlineCreator()); + } + + public TypeNameAndConstructionInfo[] getVertexTypeNameAndConstructionInfo() + { + return mVertexTypeNameAndConstructionInfo; + } + + public boolean exists(ItemPath itemPath) + { + for (int i=0; i +{ + + public AggregationDescription() + { + setName("AggregationDescription"); + } + + public AggregationDescription(String name) + { + setName(name); + } + + @Override + public Aggregation newInstance() throws ObjectNotFoundException + { + AggregationInstance newInstance = new AggregationInstance(getName()); + //for each desc member + for (int i=0; iIn parallel with the OO meta-model, Items can be linked to other Items in + * different ways. These links are modelled with Collections, which are local + * objects stored in an Item which reference a number of other Items in the same + * server. The Collections holds a CollectionMember, sometimes known as a slot, + * to reference each Item and store additional information about the link. + * + *

Features: + *

    + *
  • Typing - Collections can restrict membership of based on type + * information derived from Item, Property and Collection descriptions. This + * restriction may be per-slot or apply to the whole Collection. + * + *
  • Fixed or flexible slots - The CollectionMember objects of a + * Collection may be empty, individually typed, or created and removed as + * required, simulating either array, structures or lists. + * + *
  • Layout - Collections can include a {@link GraphModel} to lay out + * its slots on a two-dimensional canvas, for modelling real world compositions. + *
+ * + *

Collections are managed through predefined steps. + */ +abstract public class Collection implements C2KLocalObject +{ + + public static final short EMPTY = -1; + private int mCounter = -1; // Contains next available Member ID + protected CollectionMemberList mMembers = new CollectionMemberList(); + protected String mName = ""; // Not checked for uniqueness + protected Integer mVersion = null; + + /** + * Fetch the current highest member ID of the collection. This is found by + * scanning all the current members and kept in the mCounter field, but is + * not persistent. + * @return the current highest member ID + */ + public int getCounter() + { + if (mCounter == -1) + for (E element : mMembers.list) { + if (mCounter < element.getID()) + mCounter = element.getID(); + } + return ++mCounter; + } + + /** + * @return The total number of slots in this collection, including empty + * ones + */ + public int size() + { + return mMembers.list.size(); + } + + /** + * Sets the collection name + */ + @Override + public void setName(String name) + { + mName = name; + } + + /** + * @return The collection's name + */ + @Override + public String getName() + { + return mName; + } + + /** + * Get the collection version. Null if not set, and will be stored as 'last' + * @return Integer version + */ + public Integer getVersion() { + return mVersion; + } + + /** + * Set a named version for this collection. Must be an integer or null. + * Named versions will be stored separately to the current version ('last') + * and should not change once saved. + * + * @param Integer version + */ + public void setVersion(Integer mVersion) { + this.mVersion = mVersion; + } + + /** + * Get the version name for storage, which is 'last' unless the version + * number is set. + * + * @return + */ + public String getVersionName() { + return mVersion==null?"last":String.valueOf(mVersion); + } + + @Override + public String getClusterType() + { + return ClusterStorage.COLLECTION; + } + + public void setMembers(CollectionMemberList newMembers) + { + mMembers = newMembers; + } + + public boolean contains(ItemPath itemPath) { + for (E element : mMembers.list) { + if (element.getItemPath().equals(itemPath)) + return true; + } + return false; + } + + /** + * Gets the description version referenced by the given collection member. + * Assumes 'last' if version not given. + * + * @param mem The member in question + * @return String version tag + */ + public String getDescVer(E mem) { + String descVer = "last"; + Object descVerObj = mem.getProperties().get("Version"); + if (descVerObj != null) descVer = descVerObj.toString(); + return descVer; + } + + /** + * Check if all slots have an assigned Item + * @return boolean + */ + public boolean isFull() + { + for (E element : mMembers.list) { + if (element.getItemPath() == null) + return false; + } + return true; + } + + /** + * Find collection member by integer ID + * @param memberId to find + * @return the CollectionMember with that ID + * @throws ObjectNotFoundException when the ID wasn't found + */ + public E getMember(int memberId) throws ObjectNotFoundException { + for (E element : mMembers.list) { + if (element.getID() == memberId) + return element; + } + throw new ObjectNotFoundException("Member "+memberId+" not found in "+mName); + } + + public CollectionMemberList getMembers() + { + return mMembers; + } + + /** + * Add a member to this collection, with the given property and class properties + * and optionally an Item to assign, which may be null if the collection allows + * empty slots. + * + * @param itemPath the Item to assign to the new slot. Optional for collections + * that allow empty slots + * @param props the Properties of the new member + * @param classProps the names of the properties that dictate the type of + * assigned Items. + * @return the new CollectionMember instance + * @throws InvalidCollectionModification when the assignment was invalid because + * of collection constraints, such as global type constraints, or not allowing + * empty slots. + * @throws ObjectAlreadyExistsException some collections don't allow multiple + * slots assigned to the same Item, and throw this Exception if it is attempted + */ + public abstract E addMember(ItemPath itemPath, CastorHashMap props, String classProps) throws InvalidCollectionModification, ObjectAlreadyExistsException; + + /** + * Removes the slot with the given ID from the collection. + * + * @param memberId to remove + * @throws ObjectNotFoundException when there was no slot with this ID found. + */ + public abstract void removeMember(int memberId) throws ObjectNotFoundException; + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((mMembers == null) ? 0 : mMembers.hashCode()); + result = prime * result + ((mName == null) ? 0 : mName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Collection other = (Collection) obj; + if (mMembers == null) { + if (other.mMembers != null) + return false; + } else if (!mMembers.equals(other.mMembers)) + return false; + if (mName == null) { + if (other.mName != null) + return false; + } else if (!mName.equals(other.mName)) + return false; + return true; + } +} diff --git a/src/main/java/org/cristalise/kernel/collection/CollectionArrayList.java b/src/main/java/org/cristalise/kernel/collection/CollectionArrayList.java new file mode 100644 index 0000000..6b92e23 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/CollectionArrayList.java @@ -0,0 +1,60 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.collection; + +import java.util.ArrayList; + +import org.cristalise.kernel.utils.CastorArrayList; + + +/** + * A bundle of Collections. Used for storage and export/import using XML + * persistency via Castor, and to set up an Item's initial collections during + * initialization. + * + */ +public class CollectionArrayList extends CastorArrayList> { + public CollectionArrayList() + { + super(); + } + + public CollectionArrayList(ArrayList> aList) + { + super(); + for (Collection coll : aList) { + put(coll); + } + } + + /** This put method overwrites any collections with the same name already in + * the list. + */ + public void put(Collection c) { + for (Collection thisColl : list) { + if (thisColl.getName().equals(c.getName())) { + list.remove(thisColl); + break; + } + } + list.add(c); + } +} diff --git a/src/main/java/org/cristalise/kernel/collection/CollectionDescription.java b/src/main/java/org/cristalise/kernel/collection/CollectionDescription.java new file mode 100644 index 0000000..87a97c6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/CollectionDescription.java @@ -0,0 +1,41 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.collection; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.C2KLocalObject; + + +/** + * A collection that can be instantiated. Collection descriptions link Item + * descriptions together, which constrains membership of their instance. + * + */ +public interface CollectionDescription extends C2KLocalObject { + + /** + * Create a new instance of this collection. + * @return a new collection instance + * @throws ObjectNotFoundException When an essential piece of description + * data, such as a child Item PropertyDescription outcome, doesn't exist. + */ + public Collection newInstance() throws ObjectNotFoundException; +} diff --git a/src/main/java/org/cristalise/kernel/collection/CollectionMember.java b/src/main/java/org/cristalise/kernel/collection/CollectionMember.java new file mode 100644 index 0000000..3a0b642 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/CollectionMember.java @@ -0,0 +1,99 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.collection; + +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.utils.CastorHashMap; + + +/** + * CollectionMembers are pointers to individual Items in a collection. Under + * certain circumstances they may be empty, or they can be created and destroyed + * as required. They can hold properties containing annotations about the link, + * including information on the typing of the Item they should point to. + * Properties that dictate type information are specified in the ClassProps, and + * assignment of an Item will fail if those member properties do not match the + * Property values of the Item attempting to be assigned, throwing a + * {@link MembershipException} detailing the mismatches. + * + */ + +public interface CollectionMember { + + /** + * Returns the current assigned ItemPath + * @return the ItemPath, null if empty + */ + public ItemPath getItemPath(); + + /** + * Returns the UUID of the currently assigned Item + * @return + */ + public String getChildUUID(); + + /** + * Assign the given item to the slot, if it fits + * + * @param itemPath The item to assign + * @throws MembershipException When the Item Properties don't match the + * typing specification in ClassProps and Properties + * @throws InvalidCollectionModification + */ + public void assignItem(ItemPath itemPath) throws InvalidCollectionModification; + + /** + * De-assign the slot, leaving it empty. + */ + public void clearItem(); + + /** + * Resolve the Item currently assigned + * @return the ItemProxy of the assigned Item + * @throws ObjectNotFoundException When empty + */ + public ItemProxy resolveItem() throws ObjectNotFoundException; + + /** + * Get the integer slot ID, as generated by the parent Collection + * @return ID + */ + public int getID(); + + /** + * Gets the member properties. + * @return CastorHashMap + */ + public CastorHashMap getProperties(); + + /** + * Gets the class properties, which specify type information in child Items. + * On instantiation from a CollectionDescription, the ClassProps are + * generated from the PropertyDescriptions which have the isClassIdentifier + * boolean set to true. + * + * @return Comma-separated list of property names that relate to Item type + */ + public String getClassProps(); +} diff --git a/src/main/java/org/cristalise/kernel/collection/CollectionMemberList.java b/src/main/java/org/cristalise/kernel/collection/CollectionMemberList.java new file mode 100644 index 0000000..0d9c591 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/CollectionMemberList.java @@ -0,0 +1,39 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.collection; + +import org.cristalise.kernel.utils.CastorArrayList; + +/** + * A list of CollectionMembers, used internally in the Collection for XML + * marshalling convenience. + * * + * @param The CollectionMember implementation stored. + */ +public class CollectionMemberList extends CastorArrayList +{ + + public CollectionMemberList() + { + super(); + } + +} diff --git a/src/main/java/org/cristalise/kernel/collection/Dependency.java b/src/main/java/org/cristalise/kernel/collection/Dependency.java new file mode 100644 index 0000000..1641756 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/Dependency.java @@ -0,0 +1,147 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.collection; + + +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; +import org.cristalise.kernel.utils.Logger; + + +/** + * A Collection implementation that contains a variable number of members of the + * same type, like a variable-length array. CollectionMembers are created and + * destroyed as needed. A Dependency never contains empty slots, nor duplicated + * members. + * + *

ClassProps are stored at the collection level and duplicated in each slot. + * Slots may still have their own individual properties annotating their link. + * + * Predefined steps managing Dependencies: + * + *

    + *
  • + */ +public class Dependency extends Collection +{ + + protected CastorHashMap mProperties = new CastorHashMap(); + protected String mClassProps = ""; + + public Dependency() + { + setName("Dependency"); + } + + public Dependency(String name) + { + setName(name); + } + + public CastorHashMap getProperties() { + return mProperties; + } + + public void setProperties(CastorHashMap props) { + mProperties = props; + } + + public KeyValuePair[] getKeyValuePairs() + { + return mProperties.getKeyValuePairs(); + } + public void setKeyValuePairs(KeyValuePair[] pairs) + { + mProperties.setKeyValuePairs(pairs); + } + + public void setClassProps(String classProps) { + this.mClassProps = classProps; + } + + public String getClassProps() { + return mClassProps; + } + + public DependencyMember addMember(ItemPath itemPath) throws InvalidCollectionModification, ObjectAlreadyExistsException { + if (contains(itemPath)) throw new ObjectAlreadyExistsException("Item "+itemPath+" already exists in Dependency "+getName()); + // create member object + DependencyMember depMember = new DependencyMember(); + depMember.setID(getCounter()); + depMember.setProperties((CastorHashMap)mProperties.clone()); + depMember.setClassProps(mClassProps); + + // assign entity + depMember.assignItem(itemPath); + mMembers.list.add(depMember); + Logger.msg(8, "Dependency::addMember(" + itemPath + ") added to children."); + return depMember; + } + + @Override + public DependencyMember addMember(ItemPath itemPath, CastorHashMap props, String classProps) + throws InvalidCollectionModification, ObjectAlreadyExistsException + { + if (contains(itemPath)) throw new ObjectAlreadyExistsException("Item "+itemPath+" already exists in Dependency "+getName()); + if (classProps != null && !classProps.equals(mClassProps)) + throw new InvalidCollectionModification("Cannot change classProps in dependency member"); + DependencyMember depMember = new DependencyMember(); + depMember.setID(getCounter()); + + // merge props + CastorHashMap newProps = new CastorHashMap(); + for (Object name : props.keySet()) { + String key = (String)name; + newProps.put(key, props.get(key)); + + } + // class props override local + for (Object name : mProperties.keySet()) { + String key = (String)name; + newProps.put(key, mProperties.get(key)); + + } + depMember.setProperties(newProps); + depMember.setClassProps(mClassProps); + + // assign entity + depMember.assignItem(itemPath); + mMembers.list.add(depMember); + Logger.msg(8, "Dependency::addMember(" + itemPath + ") added to children."); + return depMember; + } + + @Override + public void removeMember(int memberId) throws ObjectNotFoundException { + for (DependencyMember element : mMembers.list) { + if (element.getID() == memberId) { + mMembers.list.remove(element); + return; + } + } + throw new ObjectNotFoundException("Member "+memberId+" not found"); + } + +} diff --git a/src/main/java/org/cristalise/kernel/collection/DependencyDescription.java b/src/main/java/org/cristalise/kernel/collection/DependencyDescription.java new file mode 100644 index 0000000..9c02245 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/DependencyDescription.java @@ -0,0 +1,79 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.collection; + +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.property.PropertyDescriptionList; +import org.cristalise.kernel.property.PropertyUtility; +import org.cristalise.kernel.utils.CastorHashMap; + + +public class DependencyDescription extends Dependency implements CollectionDescription{ + + public DependencyDescription() + { + setName("DependencyDescription"); + } + + public DependencyDescription(String name) + { + setName(name); + } + + @Override + public Collection newInstance() throws ObjectNotFoundException{ + String depName = getName().replaceFirst("\'$", ""); // HACK: Knock the special 'prime' off the end for the case of descriptions of descriptions + Dependency newDep = new Dependency(depName); + if (mMembers.list.size() == 1) { // constrain the members based on the property description + DependencyMember mem = mMembers.list.get(0); + String descVer = getDescVer(mem); + PropertyDescriptionList pdList = PropertyUtility.getPropertyDescriptionOutcome(mem.getItemPath(), descVer); + if (pdList!=null) { + newDep.setProperties(PropertyUtility.createProperty(pdList)); + newDep.setClassProps(pdList.getClassProps()); + } + } + return newDep; + } + + + @Override + public DependencyMember addMember(ItemPath itemPath) throws InvalidCollectionModification, ObjectAlreadyExistsException { + checkMembership(); + return super.addMember(itemPath); + } + + @Override + public DependencyMember addMember(ItemPath itemPath, CastorHashMap props, String classProps) + throws InvalidCollectionModification, ObjectAlreadyExistsException { + checkMembership(); + return super.addMember(itemPath, props, classProps); + } + + public void checkMembership() throws InvalidCollectionModification { + if (mMembers.list.size() > 0) + throw new InvalidCollectionModification("Dependency descriptions may not have more than one member."); + } + +} diff --git a/src/main/java/org/cristalise/kernel/collection/DependencyMember.java b/src/main/java/org/cristalise/kernel/collection/DependencyMember.java new file mode 100644 index 0000000..e631113 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/DependencyMember.java @@ -0,0 +1,165 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.collection; + +import java.util.StringTokenizer; + +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; +import org.cristalise.kernel.utils.Logger; + + + +/** +* @version $Revision: 1.10 $ $Date: 2004/10/21 08:02:23 $ +* @author $Author: abranson $ +*/ + + +public class DependencyMember implements CollectionMember +{ + + private ItemPath mItemPath = null; + private ItemProxy mItem = null; + private int mId = -1; + private CastorHashMap mProperties = null; + private String mClassProps; + + + /************************************************************************** + * + **************************************************************************/ + public DependencyMember() + { + mProperties = new CastorHashMap(); + } + + @Override + public ItemPath getItemPath() + { + return mItemPath; + } + + public void setProperties(CastorHashMap props) + { + mProperties = props; + } + + @Override + public CastorHashMap getProperties() + { + return mProperties; + } + + public KeyValuePair[] getKeyValuePairs() + { + return mProperties.getKeyValuePairs(); + } + public void setKeyValuePairs(KeyValuePair[] pairs) + { + mProperties.setKeyValuePairs(pairs); + } + + @Override + public int getID() { + return mId; + } + + public void setID(int id) { + mId = id; + } + + public void setClassProps(String props) + { + mClassProps = props; + } + + @Override + public String getClassProps() + { + return mClassProps; + } + + @Override + public void assignItem(ItemPath itemPath) throws InvalidCollectionModification + { + if (itemPath != null) { + if (mClassProps == null || getProperties() == null) + throw new InvalidCollectionModification("ClassProps not yet set. Cannot check membership validity."); + + //for each mandatory prop check if its in the member property and has the matching value + StringTokenizer sub = new StringTokenizer(mClassProps, ","); + while (sub.hasMoreTokens()) + { + String aClassProp = sub.nextToken(); + try { + String memberValue = (String)getProperties().get(aClassProp); + Property ItemProperty = (Property)Gateway.getStorage().get(itemPath, ClusterStorage.PROPERTY+"/"+aClassProp, null); + if (ItemProperty == null) + throw new InvalidCollectionModification("Property "+aClassProp+ " does not exist for item " + itemPath ); + if (!ItemProperty.getValue().equalsIgnoreCase(memberValue)) + throw new InvalidCollectionModification("DependencyMember::checkProperty() Values of mandatory prop "+aClassProp+" do not match " + ItemProperty.getValue()+"!="+memberValue); + } + catch (Exception ex) + { + Logger.error(ex); + throw new InvalidCollectionModification("Error checking properties"); + } + } + } + + mItemPath = itemPath; + mItem = null; + } + + @Override + public void clearItem() { + mItemPath = null; + mItem = null; + } + + @Override + public ItemProxy resolveItem() throws ObjectNotFoundException { + if (mItem == null && mItemPath != null) + mItem = Gateway.getProxyManager().getProxy(mItemPath); + return mItem; + } + + public void setChildUUID(String uuid) throws InvalidCollectionModification, InvalidItemPathException { + mItemPath = new ItemPath(uuid); + } + + + @Override + public String getChildUUID() { + return mItemPath.getUUID().toString(); + } + + +} diff --git a/src/main/java/org/cristalise/kernel/collection/package-info.java b/src/main/java/org/cristalise/kernel/collection/package-info.java new file mode 100644 index 0000000..ec01be2 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/package-info.java @@ -0,0 +1,27 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +/** + * Collections are Item local objects that reference other Items. + * + * @see Collection + */ + +package org.cristalise.kernel.collection; \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/C2KLocalObject.java b/src/main/java/org/cristalise/kernel/entity/C2KLocalObject.java new file mode 100644 index 0000000..18635ed --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/C2KLocalObject.java @@ -0,0 +1,52 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity; + + +/** + * Objects that are to be stored by Cristal Entities must implement this interface and be (un)marshallable by Castor + * i.e. have a map file properly registered in the kernel. Domain implementors should not create new C2KLocalObjects + *

    Each object will be stored as the path /clustertype/name in most cases. Exceptions are: + *

      + *
    • Collections - /Collection/Name/Version (default 'last') + *
    • Outcomes - /Outcome/SchemaType/SchemaVersion/EventId + *
    • Viewpoints - /ViewPoint/SchemaType/Name + *
    + * + * @see org.cristalise.kernel.persistency.ClusterStorage + * @see org.cristalise.kernel.persistency.ClusterStorageManager + * + * @author Andrew Branson + * + * $Revision: 1.5 $ + * $Date: 2004/01/22 11:10:41 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + */ + +public interface C2KLocalObject { + + public void setName(String name); + public String getName(); + + public String getClusterType(); +} diff --git a/src/main/java/org/cristalise/kernel/entity/CorbaServer.java b/src/main/java/org/cristalise/kernel/entity/CorbaServer.java new file mode 100644 index 0000000..a16d3d1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/CorbaServer.java @@ -0,0 +1,204 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity; + +import java.util.Map; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.AgentHelper; +import org.cristalise.kernel.entity.ItemHelper; +import org.cristalise.kernel.entity.agent.ActiveEntity; +import org.cristalise.kernel.entity.agent.ActiveLocator; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidAgentPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; +import org.cristalise.kernel.utils.SoftCache; +import org.omg.PortableServer.POA; +import org.omg.PortableServer.POAManager; +import org.omg.PortableServer.Servant; +import org.omg.PortableServer.POAManagerPackage.AdapterInactive; + + +/************************************************************************** + * + * $Revision: 1.8 $ + * $Date: 2005/10/13 08:13:44 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + + +public class CorbaServer { + private final Map mItemCache; + private POA mRootPOA; + private POA mItemPOA; + private POA mAgentPOA; + private POAManager mPOAManager; + + public CorbaServer() throws InvalidDataException { + mItemCache = new SoftCache(50); + + // init POA + try { + setupPOA(); + mPOAManager.activate(); + } catch (Exception ex) { + Logger.error(ex); + throw new InvalidDataException("Error initialising POA"); + } + + new Thread(new Runnable() { + @Override + public void run() { + Thread.currentThread().setName("ORB Invoker"); + Gateway.getORB().run(); + } + }).start(); + } + + public void close() { + try { + mPOAManager.deactivate(true, true); + } catch (AdapterInactive ex) { + Logger.error(ex); + } + } + + /************************************************************************** + * Initialises the C2KRootPOA with policies which are suitable for Factory objects + **************************************************************************/ + public void setupPOA() throws Exception { + + //Initialise the RootPOA + mRootPOA = org.omg.PortableServer.POAHelper.narrow( + Gateway.getORB().resolve_initial_references("RootPOA")); + + //Initilaise the default POAManager + + mPOAManager = mRootPOA.the_POAManager(); + + // Create POA for use by the entities + org.omg.CORBA.Policy[] policies = new org.omg.CORBA.Policy[6]; + + policies[0] = mRootPOA.create_id_assignment_policy( + org.omg.PortableServer.IdAssignmentPolicyValue.USER_ID); + policies[1] = mRootPOA.create_lifespan_policy( + org.omg.PortableServer.LifespanPolicyValue.PERSISTENT); + policies[2] = mRootPOA.create_servant_retention_policy( + org.omg.PortableServer.ServantRetentionPolicyValue.NON_RETAIN); + policies[3] = mRootPOA.create_id_uniqueness_policy( + org.omg.PortableServer.IdUniquenessPolicyValue.UNIQUE_ID); + policies[4] = mRootPOA.create_request_processing_policy( + org.omg.PortableServer.RequestProcessingPolicyValue. + USE_SERVANT_MANAGER); + policies[5] = mRootPOA.create_implicit_activation_policy( + org.omg.PortableServer.ImplicitActivationPolicyValue. + NO_IMPLICIT_ACTIVATION); + + mItemPOA = mRootPOA.create_POA( "Item", + mRootPOA.the_POAManager(), + policies ); + mAgentPOA = mRootPOA.create_POA( "Agent", + mRootPOA.the_POAManager(), + policies ); + + //Create the locators + TraceableLocator itemLocator = new TraceableLocator(); + mItemPOA.set_servant_manager( itemLocator._this( Gateway.getORB() ) ); + + ActiveLocator agentLocator = new ActiveLocator(); + mAgentPOA.set_servant_manager( agentLocator._this( Gateway.getORB() ) ); + + } + + + /************************************************************************** + * Returns a CORBA servant for a pre-existing entity + * @throws ObjectNotFoundException + **************************************************************************/ + public TraceableEntity getItem(ItemPath itemPath) throws ObjectNotFoundException { + Servant item = null; + if (!itemPath.exists()) throw new ObjectNotFoundException(itemPath+" does not exist"); + synchronized (mItemCache) { + item = mItemCache.get(itemPath); + if (item == null) { + Logger.msg(7, "Creating new servant for "+itemPath); + item = new TraceableEntity(itemPath, mItemPOA); + mItemCache.put(itemPath, item); + } + } + return (TraceableEntity)item; + } + + /************************************************************************** + * Returns a CORBA servant for a pre-existing entity + **************************************************************************/ + public ActiveEntity getAgent(AgentPath agentPath) throws InvalidAgentPathException, ObjectNotFoundException { + Servant agent = null; + if (!agentPath.exists()) throw new ObjectNotFoundException(agentPath+" does not exist"); + synchronized (mItemCache) { + agent = mItemCache.get(agentPath); + if (agent == null) { + Logger.msg(7, "Creating new servant for "+agentPath); + agent = new ActiveEntity(agentPath, mAgentPOA); + mItemCache.put(agentPath, agent); + } + else if (!(agent instanceof ActiveEntity)) + throw new InvalidAgentPathException("Item "+agentPath+" was not an agent"); + } + return (ActiveEntity)agent; + } + + /** + * @param itemPath + * @return + */ + public TraceableEntity createItem(ItemPath itemPath) throws CannotManageException, ObjectAlreadyExistsException { + + if (itemPath.exists()) throw new ObjectAlreadyExistsException(); + org.omg.CORBA.Object obj = mItemPOA.create_reference_with_id(itemPath.getOID(), ItemHelper.id()); + itemPath.setIOR(obj); + TraceableEntity item = new TraceableEntity(itemPath, mItemPOA); + synchronized (mItemCache) { + mItemCache.put(itemPath, item); + } + return item; + } + + public ActiveEntity createAgent(AgentPath agentPath) throws CannotManageException, ObjectAlreadyExistsException { + if (agentPath.exists()) throw new ObjectAlreadyExistsException(); + org.omg.CORBA.Object obj = mAgentPOA.create_reference_with_id(agentPath.getOID(), AgentHelper.id()); + agentPath.setIOR(obj); + ActiveEntity agent; + agent = new ActiveEntity(agentPath, mAgentPOA); + synchronized (mItemCache) { + mItemCache.put(agentPath, agent); + } + return agent; + + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/ItemImplementation.java b/src/main/java/org/cristalise/kernel/entity/ItemImplementation.java new file mode 100644 index 0000000..ccc2706 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/ItemImplementation.java @@ -0,0 +1,333 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity; + +import java.util.UUID; + +import org.cristalise.kernel.collection.Collection; +import org.cristalise.kernel.collection.CollectionArrayList; +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.entity.ItemOperations; +import org.cristalise.kernel.entity.agent.JobArrayList; +import org.cristalise.kernel.events.Event; +import org.cristalise.kernel.events.History; +import org.cristalise.kernel.lifecycle.instance.CompositeActivity; +import org.cristalise.kernel.lifecycle.instance.Workflow; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer; +import org.cristalise.kernel.lifecycle.instance.predefined.item.ItemPredefinedStepContainer; +import org.cristalise.kernel.lifecycle.instance.stateMachine.Transition; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.TransactionManager; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.utils.Logger; + + +public class ItemImplementation implements ItemOperations { + + protected final TransactionManager mStorage; + protected final ItemPath mItemPath; + + protected ItemImplementation(ItemPath key) { + this.mStorage = Gateway.getStorage(); + this.mItemPath = key; + } + + @Override + public SystemKey getSystemKey() { + return mItemPath.getSystemKey(); + } + + public UUID getUUID() { + return mItemPath.getUUID(); + } + + @Override + public void initialise(SystemKey agentId, String propString, String initWfString, + String initCollsString) throws AccessRightsException, + InvalidDataException, PersistencyException + { + Logger.msg(5, "Item::initialise("+mItemPath+") - agent:"+agentId); + Object locker = new Object(); + + AgentPath agentPath; + try { + agentPath = new AgentPath(agentId); + } catch (InvalidItemPathException e) { + throw new AccessRightsException("Invalid Agent Id:" + agentId); + } + + // must supply properties + if (propString == null || propString.length() == 0) { + throw new InvalidDataException("No properties supplied"); + } + + // store properties + try { + PropertyArrayList props = (PropertyArrayList) Gateway + .getMarshaller().unmarshall(propString); + for (Property thisProp : props.list) + mStorage.put(mItemPath, thisProp, locker); + } catch (Throwable ex) { + Logger.msg(8, "TraceableEntity::initialise(" + mItemPath + + ") - Properties were invalid: " + propString); + Logger.error(ex); + mStorage.abort(locker); + throw new InvalidDataException("Properties were invalid"); + } + + // Store an event and the initial properties + try { + Outcome initOutcome = new Outcome(0, propString, "ItemInitialization", 0); + History hist = new History(mItemPath, locker); + Transition predefDone = new Transition(0, "Done", 0, 0); + Event newEvent = hist.addEvent(new AgentPath(agentId), "", "Initialize", "", "", initOutcome.getSchemaType(), 0, "PredefinedStep", 0, predefDone, "last"); + initOutcome.setID(newEvent.getID()); + Viewpoint newLastView = new Viewpoint(mItemPath, initOutcome.getSchemaType(), "last", 0, newEvent.getID()); + Gateway.getStorage().put(mItemPath, initOutcome, locker); + Gateway.getStorage().put(mItemPath, newLastView, locker); + } catch (Throwable ex) { + Logger.msg(8, "TraceableEntity::initialise(" + mItemPath + + ") - Could not store event and outcome."); + Logger.error(ex); + mStorage.abort(locker); + throw new PersistencyException("Error storing event and outcome"); + } + + // create wf + try { + Workflow lc = null; + if (initWfString == null || initWfString.length() == 0) + lc = new Workflow(new CompositeActivity(), getNewPredefStepContainer()); + else + lc = new Workflow((CompositeActivity) Gateway + .getMarshaller().unmarshall(initWfString), getNewPredefStepContainer()); + lc.initialise(mItemPath, agentPath); + mStorage.put(mItemPath, lc, locker); + } catch (Throwable ex) { + Logger.msg(8, "TraceableEntity::initialise(" + mItemPath + + ") - Workflow was invalid: " + initWfString); + Logger.error(ex); + mStorage.abort(locker); + throw new InvalidDataException("Workflow was invalid"); + } + + // init collections + if (initCollsString != null && initCollsString.length() > 0) { + try { + CollectionArrayList colls = (CollectionArrayList) Gateway + .getMarshaller().unmarshall(initCollsString); + for (Collection thisColl : colls.list) { + mStorage.put(mItemPath, thisColl, locker); + } + } catch (Throwable ex) { + Logger.msg(8, "TraceableEntity::initialise(" + mItemPath + + ") - Collections were invalid: " + + initCollsString); + Logger.error(ex); + mStorage.abort(locker); + throw new InvalidDataException("Collections were invalid"); + } + } + + mStorage.commit(locker); + Logger.msg(3, "Initialisation of item " + mItemPath + + " was successful"); + } + + + protected PredefinedStepContainer getNewPredefStepContainer() { + + return new ItemPredefinedStepContainer(); + } + + @Override + public String requestAction(SystemKey agentId, String stepPath, int transitionID, + String requestData) throws AccessRightsException, + InvalidTransitionException, ObjectNotFoundException, + InvalidDataException, PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification { + + try { + + AgentPath agent = new AgentPath(agentId); + Logger.msg(1, "TraceableEntity::request(" + mItemPath + ") - Transition " + + transitionID + " on " + stepPath + " by " + agent); + + + Workflow lifeCycle = (Workflow) mStorage.get(mItemPath, + ClusterStorage.LIFECYCLE + "/workflow", null); + + String finalOutcome = lifeCycle.requestAction(agent, stepPath, mItemPath, + transitionID, requestData); + + // store the workflow if we've changed the state of the domain + // wf + if (!(stepPath.startsWith("workflow/predefined"))) + mStorage.put(mItemPath, lifeCycle, null); + + return finalOutcome; + // Normal operation exceptions + } catch (AccessRightsException ex) { + Logger.msg("Propagating AccessRightsException back to the calling agent"); + throw ex; + } catch (InvalidTransitionException ex) { + Logger.msg("Propagating InvalidTransitionException back to the calling agent"); + throw ex; + } catch (ObjectNotFoundException ex) { + Logger.msg("Propagating ObjectNotFoundException back to the calling agent"); + throw ex; + // errors + } catch (InvalidItemPathException ex) { + Logger.error(ex); + throw new AccessRightsException("Invalid Agent Id: " + agentId); + } catch (InvalidDataException ex) { + Logger.error(ex); + Logger.msg("Propagating InvalidDataException back to the calling agent"); + throw ex; + } catch (ObjectAlreadyExistsException ex) { + Logger.error(ex); + Logger.msg("Propagating ObjectAlreadyExistsException back to the calling agent"); + throw ex; + } catch (InvalidCollectionModification ex) { + Logger.error(ex); + Logger.msg("Propagating InvalidCollectionModification back to the calling agent"); + throw ex; + } catch (Throwable ex) { // non-CORBA exception hasn't been caught! + Logger.error("Unknown Error: requestAction on " + mItemPath + + " by " + agentId + " executing " + stepPath); + Logger.error(ex); + throw new InvalidDataException( + "Extraordinary Exception during execution:" + + ex.getClass().getName() + " - " + + ex.getMessage()); + } + } + + @Override + public String queryLifeCycle(SystemKey agentId, boolean filter) + throws AccessRightsException, ObjectNotFoundException, + PersistencyException { + Logger.msg(1, "TraceableEntity::queryLifeCycle(" + mItemPath + + ") - agent: " + agentId); + try { + AgentPath agent; + try { + agent = new AgentPath(agentId); + } catch (InvalidItemPathException e) { + throw new AccessRightsException("Agent " + agentId + + " doesn't exist"); + } + Workflow wf; + wf = (Workflow) mStorage.get(mItemPath, + ClusterStorage.LIFECYCLE + "/workflow", null); + JobArrayList jobBag = new JobArrayList(); + CompositeActivity domainWf = (CompositeActivity) wf + .search("workflow/domain"); + jobBag.list = filter ? + domainWf.calculateJobs(agent, mItemPath, true) : + domainWf.calculateAllJobs(agent, mItemPath, true); + Logger.msg(1, "TraceableEntity::queryLifeCycle(" + mItemPath + + ") - Returning " + jobBag.list.size() + " jobs."); + try { + return Gateway.getMarshaller().marshall(jobBag); + } catch (Exception e) { + Logger.error(e); + throw new PersistencyException("Error marshalling job bag"); + } + } catch (Throwable ex) { + Logger.error("TraceableEntity::queryLifeCycle(" + mItemPath + + ") - Unknown error"); + Logger.error(ex); + throw new PersistencyException( + "Unknown error querying jobs. Please see server log."); + } + } + + @Override + public String queryData(String path) throws AccessRightsException, + ObjectNotFoundException, PersistencyException { + + String result = ""; + + Logger.msg(1, "TraceableEntity::queryData(" + mItemPath + ") - " + + path); + + try { // check for cluster contents query + + if (path.endsWith("/all")) { + int allPos = path.lastIndexOf("all"); + String query = path.substring(0, allPos); + String[] ids = mStorage.getClusterContents(mItemPath, query); + + for (int i = 0; i < ids.length; i++) { + result += ids[i]; + + if (i != ids.length - 1) + result += ","; + } + } + // **************************************************************** + else { // retrieve the object instead + C2KLocalObject obj = mStorage.get(mItemPath, path, null); + + // marshall it, or in the case of an outcome get the data. + result = Gateway.getMarshaller().marshall(obj); + } + } catch (ObjectNotFoundException ex) { + throw ex; + } catch (Throwable ex) { + Logger.warning("TraceableEntity::queryData(" + mItemPath + + ") - " + path + " Failed: " + ex.getClass().getName()); + throw new PersistencyException("Server exception: " + + ex.getClass().getName()); + } + + if (Logger.doLog(9)) + Logger.msg(9, "TraceableEntity::queryData(" + mItemPath + + ") - result:" + result); + + return result; + } + + /** + * + */ + @Override + protected void finalize() throws Throwable { + Logger.msg(7, "Item "+mItemPath+" reaped"); + Gateway.getStorage().clearCache(mItemPath, null); + super.finalize(); + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/TraceableEntity.java b/src/main/java/org/cristalise/kernel/entity/TraceableEntity.java new file mode 100644 index 0000000..7b43873 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/TraceableEntity.java @@ -0,0 +1,154 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity; + + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.entity.ItemPOA; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** +* TraceableEntity is the implementation of the CORBA Item, although it +* delegates all non-CORBA functions to ItemImplementation. +* +* Traditional Pinky/Brain ASCII art: +* +*
    +*                                ,.   '\'\    ,---.
    +*                            .  | \\  l\\l_ //    |
    +*        _              _       |  \\/ `/  `.|    |
    +*      /~\\   \        //~\     | Y |   |   ||  Y |
    +*      |  \\   \      //  |     |  \|   |   |\ /  |
    +*      [   ||        ||   ]     \   |  o|o  | >  /
    +*     ] Y  ||        ||  Y [     \___\_--_ /_/__/
    +*     |  \_|l,------.l|_/  |     /.-\(____) /--.\
    +*     |   >'          `<   |     `--(______)----'
    +*     \  (/~`--____--'~\)  /         u// u / \
    +*      `-_>-__________-<_-'          / \  / /|
    +*          /(_#(__)#_)\             ( .) / / ]
    +*          \___/__\___/              `.`' /   [
    +*           /__`--'__\                |`-'    |
    +*        /\(__,>-~~ __)               |       |_
    +*     /\//\\(  `--~~ )               _l       |-:.
    +*     '\/  <^\      /^>             |  `   (  <  \\
    +*          _\ >-__-< /_           ,-\  ,-~~->. \  `:._,/
    +*        (___\    /___)         (____/    (____)   `-'
    +*             Kovax            and, paradoxically, Kovax
    +* 
    +***************************************************************************/ + +public class TraceableEntity extends ItemPOA +{ + + private final org.omg.PortableServer.POA mPoa; + private final ItemImplementation mItemImpl; + + public TraceableEntity( ItemPath key, + org.omg.PortableServer.POA poa ) + { + Logger.msg(5,"TraceableEntity::constructor() - SystemKey:" + key ); + mPoa = poa; + mItemImpl = new ItemImplementation(key); + } + + + @Override + public org.omg.PortableServer.POA _default_POA() + { + if(mPoa != null) + return mPoa; + else + return super._default_POA(); + } + + + @Override + public SystemKey getSystemKey() + { + return mItemImpl.getSystemKey(); + } + + @Override + public void initialise( SystemKey agentId, + String propString, + String initWfString, + String initCollsString + ) + throws AccessRightsException, + InvalidDataException, + PersistencyException + { + synchronized (this) { + mItemImpl.initialise(agentId, propString, initWfString, initCollsString); + } + } + + @Override + public String requestAction( SystemKey agentId, + String stepPath, + int transitionID, + String requestData + ) + throws AccessRightsException, + InvalidTransitionException, + ObjectNotFoundException, + InvalidDataException, + PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification + { + synchronized (this) { + return mItemImpl.requestAction(agentId, stepPath, transitionID, requestData); + } + } + + @Override + public String queryLifeCycle( SystemKey agentId, + boolean filter + ) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException + { + synchronized (this) { + return mItemImpl.queryLifeCycle(agentId, filter); + } + } + + @Override + public String queryData(String path) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException + { + synchronized (this) { + return mItemImpl.queryData(path); + } + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/TraceableLocator.java b/src/main/java/org/cristalise/kernel/entity/TraceableLocator.java new file mode 100644 index 0000000..f61c433 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/TraceableLocator.java @@ -0,0 +1,90 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity; + + +import java.nio.ByteBuffer; +import java.sql.Timestamp; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2005/10/05 07:39:37 $ + * @version $Revision: 1.15 $ + **************************************************************************/ +public class TraceableLocator extends org.omg.PortableServer.ServantLocatorPOA +{ + + /************************************************************************** + * + **************************************************************************/ + public TraceableLocator() + { + } + + + /************************************************************************** + * + **************************************************************************/ + @Override + public org.omg.PortableServer.Servant preinvoke( + byte[] oid, + org.omg.PortableServer.POA poa, + String operation, + org.omg.PortableServer.ServantLocatorPackage.CookieHolder cookie ) + { + ByteBuffer bb = ByteBuffer.wrap(oid); + long msb = bb.getLong(); + long lsb = bb.getLong(); + ItemPath syskey = new ItemPath(new SystemKey(msb, lsb)); + + Logger.msg(1,"==========================================================="); + Logger.msg(1,"Item called at "+new Timestamp( System.currentTimeMillis()) +": " + operation + + "(" + syskey + ")." ); + + try { + return Gateway.getCorbaServer().getItem(syskey); + } catch (ObjectNotFoundException ex) { + Logger.error("ObjectNotFoundException::TraceableLocator::preinvoke() " + ex.toString()); + throw new org.omg.CORBA.OBJECT_NOT_EXIST(); + } + } + + + /************************************************************************** + * + **************************************************************************/ + @Override + public void postinvoke( + byte[] oid, + org.omg.PortableServer.POA poa, + String operation, + java.lang.Object the_cookie, + org.omg.PortableServer.Servant the_servant ) + { } +} diff --git a/src/main/java/org/cristalise/kernel/entity/agent/ActiveEntity.java b/src/main/java/org/cristalise/kernel/entity/agent/ActiveEntity.java new file mode 100644 index 0000000..46d60ac --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/ActiveEntity.java @@ -0,0 +1,156 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.agent; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.entity.AgentPOA; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * ActiveEntity - the CORBA object representing the Agent. All functionality + * is delegated to the AgentImplementation, which extends ItemImplementation, + * as this cannot extend its equivalent TraceableEntity + * + **************************************************************************/ +public class ActiveEntity extends AgentPOA +{ + + private final org.omg.PortableServer.POA mPoa; + private final AgentImplementation mAgentImpl; + + public ActiveEntity( AgentPath key, + org.omg.PortableServer.POA poa ) + { + Logger.msg(5, "ActiveEntity::constructor() - SystemKey:" + key ); + mPoa = poa; + mAgentImpl = new AgentImplementation(key); + } + + + /************************************************************************** + * + * + **************************************************************************/ + @Override + public org.omg.PortableServer.POA _default_POA() + { + if(mPoa != null) + return mPoa; + else + return super._default_POA(); + } + + + /************************************************************************** + * + * + **************************************************************************/ + @Override + public SystemKey getSystemKey() + { + return mAgentImpl.getSystemKey(); + } + + + /************************************************************************** + * + * + **************************************************************************/ + @Override + public String queryData(String path) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException + { + synchronized (this) { + return mAgentImpl.queryData(path); + } + } + + + + /** + * Called by an activity when it reckons we need to update our joblist for it + */ + + @Override + public void refreshJobList(SystemKey sysKey, String stepPath, String newJobs) { + synchronized (this) { + mAgentImpl.refreshJobList(sysKey, stepPath, newJobs); + } + } + + @Override + public void addRole(String roleName) throws CannotManageException, ObjectNotFoundException { + synchronized (this) { + mAgentImpl.addRole(roleName); + } + } + + @Override + public void removeRole(String roleName) throws CannotManageException, ObjectNotFoundException { + synchronized (this) { + mAgentImpl.removeRole(roleName); + } + } + + @Override + public void initialise(SystemKey agentId, String propString, String initWfString, + String initCollsString) throws AccessRightsException, + InvalidDataException, PersistencyException, ObjectNotFoundException { + synchronized (this) { + mAgentImpl.initialise(agentId, propString, initWfString, initCollsString); + } + + } + + @Override + public String requestAction(SystemKey agentID, String stepPath, int transitionID, + String requestData) throws AccessRightsException, + InvalidTransitionException, ObjectNotFoundException, + InvalidDataException, PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification { + + synchronized (this) { + return mAgentImpl.requestAction(agentID, stepPath, transitionID, requestData); + } + + } + + @Override + public String queryLifeCycle(SystemKey agentId, boolean filter) + throws AccessRightsException, ObjectNotFoundException, + PersistencyException { + synchronized (this) { + return mAgentImpl.queryLifeCycle(agentId, filter); + } + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/agent/ActiveLocator.java b/src/main/java/org/cristalise/kernel/entity/agent/ActiveLocator.java new file mode 100644 index 0000000..1a55c99 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/ActiveLocator.java @@ -0,0 +1,100 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.agent; + + +import java.nio.ByteBuffer; +import java.sql.Timestamp; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2005/10/05 07:39:36 $ + * @version $Revision: 1.9 $ + **************************************************************************/ +public class ActiveLocator extends org.omg.PortableServer.ServantLocatorPOA +{ + + /************************************************************************** + * + **************************************************************************/ + public ActiveLocator() + { + } + + + /************************************************************************** + * + **************************************************************************/ + @Override + public org.omg.PortableServer.Servant preinvoke( + byte[] oid, + org.omg.PortableServer.POA poa, + String operation, + org.omg.PortableServer.ServantLocatorPackage.CookieHolder cookie ) + { + + try + { + ByteBuffer bb = ByteBuffer.wrap(oid); + long msb = bb.getLong(); + long lsb = bb.getLong(); + AgentPath syskey = new AgentPath(new SystemKey(msb, lsb)); + + Logger.msg(1,"==========================================================="); + Logger.msg(1,"Agent called at "+new Timestamp( System.currentTimeMillis()) +": " + operation + + "(" + syskey + ")." ); + + return Gateway.getCorbaServer().getAgent(syskey); + + } + catch (ObjectNotFoundException ex) + { + Logger.error("ObjectNotFoundException::ActiveLocator::preinvoke() "+ex.toString()); + throw new org.omg.CORBA.OBJECT_NOT_EXIST(); + } catch (InvalidItemPathException ex) { + Logger.error("InvalidItemPathException::ActiveLocator::preinvoke() "+ex.toString()); + throw new org.omg.CORBA.INV_OBJREF(); + } + } + + + /************************************************************************** + * + **************************************************************************/ + @Override + public void postinvoke( + byte[] oid, + org.omg.PortableServer.POA poa, + String operation, + java.lang.Object the_cookie, + org.omg.PortableServer.Servant the_servant ) + { + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/agent/AgentImplementation.java b/src/main/java/org/cristalise/kernel/entity/agent/AgentImplementation.java new file mode 100644 index 0000000..26c2f2f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/AgentImplementation.java @@ -0,0 +1,137 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.agent; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.entity.AgentOperations; +import org.cristalise.kernel.entity.ItemImplementation; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer; +import org.cristalise.kernel.lifecycle.instance.predefined.agent.AgentPredefinedStepContainer; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +/** + * Implementation of Agent, though called from the CORBA implementation ActiveEntity. + * + *

    The Agent is an extension of the Item that can execute Jobs, and in doing so + * change the state of Item workflows, submit data to them in the form of Outcomes + * and run any scripts associated with those activities. In this server object, + * none of this specific Agent work is performed - it all must be done using the + * client API. The server implementation only manages the Agent's data: its roles + * and persistent Jobs. + */ +public class AgentImplementation extends ItemImplementation implements + AgentOperations { + + private JobList currentJobs; + private final AgentPath mAgentPath; + + public AgentImplementation(AgentPath path) { + super(path); + mAgentPath = path; + } + + + /** + * Updates an Agent's list of Jobs relating to a particular activity. Only + * Activities that are assigned to a Role that is flagged to push Jobs do this. + * + */ + @Override + public synchronized void refreshJobList(SystemKey sysKey, String stepPath, String newJobs) { + try { + ItemPath itemPath = new ItemPath(sysKey); + JobArrayList newJobList = (JobArrayList)Gateway.getMarshaller().unmarshall(newJobs); + + // get our joblist + if (currentJobs == null) + currentJobs = new JobList( itemPath, null); + + // remove old jobs for this item + currentJobs.removeJobsForStep( itemPath, stepPath ); + + // merge new jobs in + for (Object name : newJobList.list) { + Job newJob = (Job)name; + Logger.msg(6, "Adding job for "+newJob.getItemPath()+"/"+newJob.getStepPath()+":"+newJob.getTransition().getId()); + currentJobs.addJob(newJob); + } + + } catch (Throwable ex) { + Logger.error("Could not refresh job list."); + Logger.error(ex); + } + + } + + /** Adds the given Role to this Agent. Called from the SetAgentRoles + * predefined step. + * + * @param roleName - the new Role to add + * @throws CannotManageException When the process has no lookup manager + * @throws ObjectNotFoundException + * + */ + @Override + public void addRole(String roleName) throws CannotManageException, ObjectNotFoundException { + RolePath newRole = Gateway.getLookup().getRolePath(roleName); + try { + Gateway.getLookupManager().addRole(mAgentPath, newRole); + } catch (ObjectCannotBeUpdated ex) { + throw new CannotManageException("Could not update role"); + } + } + + /** + * Removes the given Role from this Agent. Called by the SetAgentRoles + * predefined step. + * + * @param roleName + */ + @Override + public void removeRole(String roleName) throws CannotManageException, ObjectNotFoundException { + RolePath rolePath = Gateway.getLookup().getRolePath(roleName); + try { + Gateway.getLookupManager().removeRole(mAgentPath, rolePath); + } catch (ObjectCannotBeUpdated ex) { + throw new CannotManageException("Could not update role"); + } + } + + /** + * Agents have their own predefined step containers. They contain the standard + * predefined steps, plus special Agent ones related to Agent management and + * instantiation. + * + * @see org.cristalise.kernel.lifecycle.instance.predefined.agent.AgentPredefinedStepContainer + */ + @Override + protected PredefinedStepContainer getNewPredefStepContainer() { + return new AgentPredefinedStepContainer(); + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/agent/Job.java b/src/main/java/org/cristalise/kernel/entity/agent/Job.java new file mode 100644 index 0000000..bd74d51 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/Job.java @@ -0,0 +1,484 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.agent; + +import java.util.HashMap; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.lifecycle.instance.Activity; +import org.cristalise.kernel.lifecycle.instance.stateMachine.Transition; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidAgentPathException; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.OutcomeInitiator; +import org.cristalise.kernel.persistency.outcome.Schema; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.scripting.ErrorInfo; +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; +import org.cristalise.kernel.utils.Logger; + + +/******************************************************************************* + * @author $Author: abranson $ $Date: 2005/05/20 13:07:49 $ + * @version $Revision: 1.62 $ + ******************************************************************************/ + +public class Job implements C2KLocalObject +{ + // persistent + + private int id; + + private ItemPath itemPath; + + private String stepName; + + private String stepPath; + + private String stepType; + + private Transition transition; + + private String originStateName; + + private String targetStateName; + + private String agentRole; + + private CastorHashMap actProps = new CastorHashMap(); + + // non-persistent + + private String name; + + private AgentPath agentPath; + + private String agentName; + + private String outcomeData; + + private ErrorInfo error; + + private ItemProxy item = null; + + private boolean outcomeSet; + + // outcome initiator cache + + static private HashMap ocInitCache = new HashMap(); + + /*************************************************************************** + * Empty constructor for Castor + **************************************************************************/ + public Job() + { + } + + public Job(Activity act, ItemPath itemPath, Transition transition, AgentPath agent, String role) throws InvalidDataException, ObjectNotFoundException, InvalidAgentPathException { + + setItemPath(itemPath); + setStepPath(act.getPath()); + setTransition(transition); + setOriginStateName(act.getStateMachine().getState(transition.getOriginStateId()).getName()); + setTargetStateName(act.getStateMachine().getState(transition.getTargetStateId()).getName()); + setStepName(act.getName()); + setActProps(act.getProperties()); + setStepType(act.getType()); + if (agent != null) setAgentName(agent.getAgentName()); + setAgentRole(role); + } + + + // Castor persistent fields + + public String getOriginStateName() { + return originStateName; + } + + public void setOriginStateName(String originStateName) { + this.originStateName = originStateName; + } + + public String getTargetStateName() { + return targetStateName; + } + + public void setTargetStateName(String targetStateName) { + this.targetStateName = targetStateName; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + name = String.valueOf(id); + } + + public ItemPath getItemPath() { + return itemPath; + } + + public void setItemPath(ItemPath path) { + itemPath = path; + item = null; + } + + public void setItemUUID( String uuid ) throws InvalidItemPathException + { + setItemPath(new ItemPath(uuid)); + } + + public String getItemUUID() { + return getItemPath().getUUID().toString(); + } + + public String getStepName() { + return stepName; + } + + public void setStepName(String string) { + stepName = string; + } + + public String getStepPath() { + return stepPath; + } + + public void setStepPath(String string) { + stepPath = string; + } + + public String getStepType() { + return stepType; + } + + public void setStepType(String actType) { + stepType = actType; + } + + public Transition getTransition() { + return transition; + } + + public void setTransition(Transition transition) { + this.transition = transition; + } + + public AgentPath getAgentPath() throws ObjectNotFoundException { + if (agentPath == null && getAgentName() != null) { + agentPath = Gateway.getLookup().getAgentPath(getAgentName()); + } + return agentPath; + } + + public void setAgentPath(AgentPath agentPath) { + this.agentPath = agentPath; + agentName = agentPath.getAgentName(); + } + + public void setAgentUUID( String uuid ) + { + if (uuid != null) + try { + setAgentPath(AgentPath.fromUUIDString(uuid)); + } catch (InvalidAgentPathException e) { + Logger.error("Invalid agent path in Job: "+uuid); + } + } + + public String getAgentUUID() { + try { + if (getAgentPath() != null) + return getAgentPath().getUUID().toString(); + } catch (ObjectNotFoundException e) { } + return null; + } + + public String getAgentName() + { + if (agentName == null) + agentName = (String) actProps.get("Agent Name"); + return agentName; + } + + public void setAgentName(String agentName) throws ObjectNotFoundException + { + this.agentName = agentName; + agentPath = Gateway.getLookup().getAgentPath(agentName); + } + + public String getAgentRole() { + return agentRole; + } + + public void setAgentRole(String role) { + agentRole = role; + } + + public String getSchemaName() throws InvalidDataException, ObjectNotFoundException { + if (transition.hasOutcome(actProps)) { + Schema schema = transition.getSchema(actProps); + return schema.docType; + } + return null; + } + + public int getSchemaVersion() throws InvalidDataException, ObjectNotFoundException { + if (transition.hasOutcome(actProps)) { + Schema schema = transition.getSchema(actProps); + return schema.docVersion; + } + return -1; + } + + public boolean isOutcomeRequired() + { + return transition.hasOutcome(actProps) && transition.getOutcome().isRequired(); + } + + public String getScriptName() { + if (transition.hasScript(actProps)) { + return transition.getScript().getScriptName(); + } + return null; + } + + public int getScriptVersion() throws InvalidDataException { + if (transition.hasScript(actProps)) { + return transition.getScriptVersion(actProps); + } + return -1; + } + + public KeyValuePair[] getKeyValuePairs() { + return actProps.getKeyValuePairs(); + } + + public void setKeyValuePairs(KeyValuePair[] pairs) { + actProps.setKeyValuePairs(pairs); + } + + // Non-persistent fields + + @Override + public String getName() { + return name; + } + + @Override + public void setName(String name) { + this.name = name; + try { + id = Integer.parseInt(name); + } catch (NumberFormatException ex) { + id = -1; + } + } + + public ItemProxy getItemProxy() throws ObjectNotFoundException, InvalidItemPathException { + if (item == null) + item = Gateway.getProxyManager().getProxy(itemPath); + return item; + } + + public String getDescription() + { + String desc = (String) actProps.get("Description"); + if (desc == null) + desc = "No Description"; + return desc; + } + public void setOutcome(String outcome) + { + outcomeData = outcome; + outcomeSet = !(outcomeData == null); + } + + public void setError(ErrorInfo errors) + { + error = errors; + try { + outcomeData = Gateway.getMarshaller().marshall(error); + } catch (Exception e) { + Logger.error("Error marshalling ErrorInfo in job"); + Logger.error(e); + } + } + + public String getLastView() throws InvalidDataException { + String viewName = (String) getActProp("Viewpoint"); + if (viewName.length() > 0) { + // find schema + String schemaName; + try { + schemaName = getSchemaName(); + } catch (ObjectNotFoundException e1) { + throw new InvalidDataException("Schema "+getActProp("SchemaType")+" v"+getActProp("SchemaVersion")+" not found"); + } + + try { + Viewpoint view = (Viewpoint) Gateway.getStorage().get(itemPath, + ClusterStorage.VIEWPOINT + "/" + schemaName + "/" + viewName, null); + return view.getOutcome().getData(); + } catch (ObjectNotFoundException ex) { // viewpoint doesn't exist yet + return null; + } catch (PersistencyException e) { + Logger.error(e); + throw new InvalidDataException("ViewpointOutcomeInitiator: PersistencyException loading viewpoint " + + ClusterStorage.VIEWPOINT + "/" + schemaName + "/" + viewName+" in item "+itemPath.getUUID()); + } + } + else + return null; + } + + public OutcomeInitiator getOutcomeInitiator() throws InvalidDataException { + String ocInitName = (String) getActProp("OutcomeInit"); + OutcomeInitiator ocInit; + if (ocInitName.length() > 0) { + String ocPropName = "OutcomeInit."+ocInitName; + synchronized (ocInitCache) { + ocInit = ocInitCache.get(ocPropName); + if (ocInit == null) { + Object ocInitObj; + if (!Gateway.getProperties().containsKey(ocPropName)) { + throw new InvalidDataException("Outcome instantiator "+ocPropName+" isn't defined"); + } + try { + ocInitObj = Gateway.getProperties().getInstance(ocPropName); + } catch (Exception e) { + Logger.error(e); + throw new InvalidDataException("Outcome instantiator "+ocPropName+" couldn't be instantiated"); + } + ocInit = (OutcomeInitiator)ocInitObj; // throw runtime class cast if it isn't one + ocInitCache.put(ocPropName, ocInit); + } + } + return ocInit; + } + else + return null; + } + + public String getOutcomeString() throws InvalidDataException + { + if (outcomeData == null && transition.hasOutcome(actProps)) { + outcomeData = getLastView(); + if (outcomeData == null) { + OutcomeInitiator ocInit = getOutcomeInitiator(); + if (ocInit != null) + outcomeData = ocInit.initOutcome(this); + } + if (outcomeData != null) outcomeSet = true; + } + return outcomeData; + } + + public Outcome getOutcome() throws InvalidDataException, ObjectNotFoundException + { + return new Outcome(-1, getOutcomeString(), getSchemaName(), getSchemaVersion()); + } + + public boolean hasOutcome() { + return transition.hasOutcome(actProps); + } + + public boolean hasScript() { + return transition.hasScript(actProps); + } + + public boolean isOutcomeSet() { + return outcomeSet; + } + + @Override + public String getClusterType() + { + return ClusterStorage.JOB; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((itemPath == null) ? 0 : itemPath.hashCode()); + result = prime * result + + ((stepPath == null) ? 0 : stepPath.hashCode()); + result = prime * result + + ((transition == null) ? 0 : transition.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Job other = (Job) obj; + if (itemPath == null) { + if (other.itemPath != null) + return false; + } else if (!itemPath.equals(other.itemPath)) + return false; + if (stepPath == null) { + if (other.stepPath != null) + return false; + } else if (!stepPath.equals(other.stepPath)) + return false; + if (transition == null) { + if (other.transition != null) + return false; + } else if (!transition.equals(other.transition)) + return false; + return true; + } + + + private void setActProps(CastorHashMap actProps) { + this.actProps = actProps; + } + + public Object getActProp(String name) + { + return actProps.get(name); + } + + public String getActPropString(String name) + { + Object obj = getActProp(name); + return obj==null?null:String.valueOf(obj); + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/agent/JobArrayList.java b/src/main/java/org/cristalise/kernel/entity/agent/JobArrayList.java new file mode 100644 index 0000000..f4233fb --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/JobArrayList.java @@ -0,0 +1,42 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.agent; + +import java.util.ArrayList; + +import org.cristalise.kernel.utils.CastorArrayList; + + +public class JobArrayList extends CastorArrayList +{ + + public JobArrayList() + { + super(); + } + + public JobArrayList(ArrayList aList) + { + super(aList); + } + + +} diff --git a/src/main/java/org/cristalise/kernel/entity/agent/JobList.java b/src/main/java/org/cristalise/kernel/entity/agent/JobList.java new file mode 100644 index 0000000..b4e2a27 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/JobList.java @@ -0,0 +1,138 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.agent; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Vector; + +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.RemoteMap; +import org.cristalise.kernel.utils.Logger; + + + +/************************************************************************** +* +* @author $Author: abranson $ $Date: 2006/03/03 13:52:21 $ +* @version $Revision: 1.15 $ +***************************************************************************/ +public class JobList extends RemoteMap +{ + + /************************************************************************** + * Empty constructor for Castor + **************************************************************************/ + public JobList(ItemPath itemPath, Object locker) + { + super(itemPath, ClusterStorage.JOB, locker); + } + + + /************************************************************************** + * + **************************************************************************/ + public void addJob( Job job ) + { + synchronized(this) { + int jobId = getLastId()+1; + job.setId(jobId); + put(String.valueOf(jobId), job); + } + } + + /** + * Cannot be stored + */ + @Override + public String getClusterType() { + return null; + } + + + public Job getJob(int id) { + return get(String.valueOf(id)); + } + + + /** + * @param job + */ + public void removeJobsForItem( ItemPath itemPath ) + { + Iterator currentMembers = values().iterator(); + Job j = null; + + while( currentMembers.hasNext() ) + { + j = currentMembers.next(); + + if( j.getItemPath().equals(itemPath) ) + remove( String.valueOf(j.getId()) ); + } + + Logger.msg(5, "JobList::removeJobsWithSysKey() - " + itemPath + " DONE." ); + } + + public void removeJobsForStep( ItemPath itemPath, String stepPath ) + { + ArrayList staleJobs = new ArrayList(); + Iterator jobIter = keySet().iterator(); + while( jobIter.hasNext() ) + { + String jid = jobIter.next(); + Job j = get(jid); + if( j.getItemPath().equals(itemPath) && j.getStepPath().equals(stepPath)) + staleJobs.add(jid); + } + + Logger.msg(3, "JobList.removeJobsForStep() - removing "+staleJobs.size()); + + for (String jid : staleJobs) { + remove(jid); + } + Logger.msg(5, "JobList::removeJobsForStep() - " + itemPath + " DONE." ); + } + /** + * @param itemKey + * @param string + * @return + */ + public Vector getJobsOfItem( ItemPath itemPath ) + { + Iterator currentMembers = values().iterator(); + Job j = null; + Vector jobs = new Vector(); + + while( currentMembers.hasNext() ) + { + j = currentMembers.next(); + + if( j.getItemPath().equals(itemPath) ) + jobs.add(j); + } + + Logger.msg(5, "JobList::getJobsOfSysKey() - returning " + jobs.size() + " Jobs." ); + + return jobs; + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/agent/package-info.java b/src/main/java/org/cristalise/kernel/entity/agent/package-info.java new file mode 100644 index 0000000..f5e146b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/package-info.java @@ -0,0 +1,32 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +/** + * The implementation of Agents, and their Jobs. + * + *

    This package contains the classes for the implementation of + * Agents on the CRISTAL server. They correspond to the Item implementations in + * the parent package. + *

    This package also contains the {@link Job} object implementation, as well + * as the RemoteMap JobList, and the marshallable container JobArrayList. + * + */ + +package org.cristalise.kernel.entity.agent; \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/imports/Geometry.java b/src/main/java/org/cristalise/kernel/entity/imports/Geometry.java new file mode 100644 index 0000000..3680053 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/Geometry.java @@ -0,0 +1,48 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ + +package org.cristalise.kernel.entity.imports; + + + +public class Geometry { + + + public int x; + + public int y; + + public int width; + + public int height; + + public Geometry() { + super(); + } + + public Geometry(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportAgent.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportAgent.java new file mode 100644 index 0000000..08c13d1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportAgent.java @@ -0,0 +1,118 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.imports; + +import java.util.ArrayList; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.agent.ActiveEntity; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.process.module.ModuleImport; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.utils.Logger; + + +public class ImportAgent extends ModuleImport { + + private String password; + private ArrayList properties = new ArrayList(); + private ArrayList roles = new ArrayList(); + + public ImportAgent() { + } + + public ImportAgent(String name, String password) { + this.name = name; + this.password = password; + } + + @Override + public void create(AgentPath agentPath, boolean reset) throws ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException, ObjectAlreadyExistsException { + AgentPath newAgent = new AgentPath(getItemPath(), name); + newAgent.setPassword(password); + ActiveEntity newAgentEnt = Gateway.getCorbaServer().createAgent(newAgent); + Gateway.getLookupManager().add(newAgent); + // assemble properties + properties.add(new Property("Name", name, true)); + properties.add(new Property("Type", "Agent", false)); + try { + newAgentEnt.initialise(agentPath.getSystemKey(), Gateway.getMarshaller().marshall(new PropertyArrayList(properties)), null, null); + } catch (Exception ex) { + Logger.error(ex); + throw new CannotManageException("Error initialising new agent"); + } + for (String role : roles) { + RolePath thisRole; + try { + thisRole = Gateway.getLookup().getRolePath(role); + } catch (ObjectNotFoundException ex) { + throw new ObjectNotFoundException("Role "+role+" does not exist."); + } + Gateway.getLookupManager().addRole(newAgent, thisRole); + } + + } + + @Override + public ItemPath getItemPath() { + if (itemPath == null) { // try to find agent if it already exists + try { + AgentPath existAgent = Gateway.getLookup().getAgentPath(name); + itemPath = existAgent; + } catch (ObjectNotFoundException ex) { + itemPath = new AgentPath(new ItemPath(), name); + } + } + return itemPath; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public ArrayList getRoles() { + return roles; + } + + public void setRoles(ArrayList roles) { + this.roles = roles; + } + + public ArrayList getProperties() { + return properties; + } + + public void setProperties(ArrayList properties) { + this.properties = properties; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregation.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregation.java new file mode 100644 index 0000000..22a9b78 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregation.java @@ -0,0 +1,91 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.imports; + +import java.util.ArrayList; + +import org.cristalise.kernel.collection.Aggregation; +import org.cristalise.kernel.collection.AggregationDescription; +import org.cristalise.kernel.collection.AggregationInstance; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.property.PropertyDescription; +import org.cristalise.kernel.property.PropertyDescriptionList; +import org.cristalise.kernel.property.PropertyUtility; + + +public class ImportAggregation { + + public boolean isDescription; + public Integer version; + public ArrayList aggregationMemberList = new ArrayList(); + public String name; + + public ImportAggregation() { + super(); + } + + public ImportAggregation(String name, boolean isDescription) { + this(); + this.name = name; + this.isDescription = isDescription; + } + + public org.cristalise.kernel.collection.Aggregation create() throws InvalidCollectionModification, ObjectNotFoundException, ObjectAlreadyExistsException { + Aggregation newAgg = isDescription?new AggregationDescription(name):new AggregationInstance(name); + if (version!= null) newAgg.setVersion(version); + for (ImportAggregationMember thisMem : aggregationMemberList) { + StringBuffer classProps = new StringBuffer(); + if (thisMem.itemDescriptionPath != null && thisMem.itemDescriptionPath.length()>0) { + ItemPath itemPath; + try { + itemPath = new ItemPath(thisMem.itemDescriptionPath); + } catch (InvalidItemPathException ex) { + itemPath = new DomainPath(thisMem.itemDescriptionPath).getItemPath(); + } + + String descVer = thisMem.itemDescriptionVersion==null?"last":thisMem.itemDescriptionVersion; + PropertyDescriptionList propList = PropertyUtility.getPropertyDescriptionOutcome(itemPath, descVer); + for (PropertyDescription pd : propList.list) { + thisMem.props.put(pd.getName(), pd.getDefaultValue()); + if (pd.getIsClassIdentifier()) + classProps.append((classProps.length()>0?",":"")).append(pd.getName()); + } + } + ItemPath itemPath = null; + if (thisMem.itemPath != null && thisMem.itemPath.length()>0) { + + try { + itemPath = new ItemPath(thisMem.itemPath); + } catch (InvalidItemPathException ex) { + itemPath = new DomainPath(thisMem.itemPath).getItemPath(); + } + } + newAgg.addMember(itemPath, thisMem.props, classProps.toString(), new GraphPoint(thisMem.geometry.x, thisMem.geometry.y), thisMem.geometry.width, thisMem.geometry.height); + } + return newAgg; + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregationMember.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregationMember.java new file mode 100644 index 0000000..53b74b8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregationMember.java @@ -0,0 +1,55 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.imports; + +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; + +public class ImportAggregationMember { + + public int slotNo; + public String itemDescriptionPath; + public String itemDescriptionVersion = null; + public String itemPath; + public Geometry geometry; + public CastorHashMap props = new CastorHashMap(); + + + public ImportAggregationMember() { + super(); + } + + public ImportAggregationMember(int slotNo, String itemDescPath, String itemDescVersion, String itemPath, Geometry geometry) { + this.slotNo = slotNo; + this.itemDescriptionPath = itemDescPath; + this.itemDescriptionVersion = itemDescVersion; + this.itemPath = itemPath; + this.geometry = geometry; + } + + public KeyValuePair[] getKeyValuePairs() { + return props.getKeyValuePairs(); + } + + public void setKeyValuePairs(KeyValuePair[] pairs) { + props.setKeyValuePairs(pairs); + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportDependency.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportDependency.java new file mode 100644 index 0000000..f94cab0 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportDependency.java @@ -0,0 +1,107 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.imports; + +import java.util.ArrayList; + +import org.cristalise.kernel.collection.Dependency; +import org.cristalise.kernel.collection.DependencyDescription; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.property.PropertyDescription; +import org.cristalise.kernel.property.PropertyDescriptionList; +import org.cristalise.kernel.property.PropertyUtility; +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; + + +public class ImportDependency { + + public String name; + public Integer version; + public boolean isDescription; + public String itemDescriptionPath; + public String itemDescriptionVersion = null; + public ArrayList dependencyMemberList = new ArrayList(); + public CastorHashMap props = new CastorHashMap(); + + public ImportDependency() { + super(); + } + + public ImportDependency(String name) { + this(); + this.name = name; + } + + public KeyValuePair[] getKeyValuePairs() { + return props.getKeyValuePairs(); + } + + public void setKeyValuePairs(KeyValuePair[] pairs) { + props.setKeyValuePairs(pairs); + } + + /** + * @return + * @throws ObjectAlreadyExistsException + */ + public org.cristalise.kernel.collection.Dependency create() throws InvalidCollectionModification, ObjectNotFoundException, ObjectAlreadyExistsException { + Dependency newDep = isDescription?new DependencyDescription(name):new Dependency(name); + if (version!= null) newDep.setVersion(version); + if (itemDescriptionPath != null && itemDescriptionPath.length()>0) { + ItemPath itemPath; + try { + itemPath = new ItemPath(itemDescriptionPath); + } catch (InvalidItemPathException ex) { + itemPath = new DomainPath(itemDescriptionPath).getItemPath(); + } + String descVer = itemDescriptionVersion==null?"last":itemDescriptionVersion; + PropertyDescriptionList propList = PropertyUtility.getPropertyDescriptionOutcome(itemPath, descVer); + StringBuffer classProps = new StringBuffer(); + for (PropertyDescription pd : propList.list) { + props.put(pd.getName(), pd.getDefaultValue()); + if (pd.getIsClassIdentifier()) + classProps.append((classProps.length()>0?",":"")).append(pd.getName()); + } + newDep.setProperties(props); + newDep.setClassProps(classProps.toString()); + } + + for (ImportDependencyMember thisMem : dependencyMemberList) { + ItemPath itemPath; + try { + itemPath = new ItemPath(thisMem.itemPath); + } catch (InvalidItemPathException ex) { + itemPath = new DomainPath(thisMem.itemPath).getItemPath(); + } + + org.cristalise.kernel.collection.DependencyMember newDepMem = newDep.addMember(itemPath); + newDepMem.getProperties().putAll(thisMem.props); + } + return newDep; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportDependencyMember.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportDependencyMember.java new file mode 100644 index 0000000..5a5d6cd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportDependencyMember.java @@ -0,0 +1,48 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.imports; + +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; + +public class ImportDependencyMember { + + + public String itemPath; + public CastorHashMap props = new CastorHashMap(); + + public ImportDependencyMember() { + super(); + } + + public ImportDependencyMember(String itemPath) { + this.itemPath = itemPath; + + } + + public KeyValuePair[] getKeyValuePairs() { + return props.getKeyValuePairs(); + } + + public void setKeyValuePairs(KeyValuePair[] pairs) { + props.setKeyValuePairs(pairs); + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportItem.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportItem.java new file mode 100644 index 0000000..2a259bd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportItem.java @@ -0,0 +1,280 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.imports; + + +import java.util.ArrayList; + +import org.cristalise.kernel.collection.Aggregation; +import org.cristalise.kernel.collection.CollectionArrayList; +import org.cristalise.kernel.collection.Dependency; +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.TraceableEntity; +import org.cristalise.kernel.events.Event; +import org.cristalise.kernel.events.History; +import org.cristalise.kernel.lifecycle.CompositeActivityDef; +import org.cristalise.kernel.lifecycle.instance.stateMachine.Transition; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.process.module.ModuleImport; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.utils.LocalObjectLoader; +import org.cristalise.kernel.utils.Logger; +import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.XMLUnit; + + +/** + * Complete Structure for new item + * + * @version $Revision: 1.8 $ $Date: 2006/03/03 13:52:21 $ + */ + +public class ImportItem extends ModuleImport { + + protected String initialPath; + protected String workflow; + protected Integer workflowVer; + protected ArrayList properties = new ArrayList(); + protected ArrayList aggregationList = new ArrayList(); + protected ArrayList dependencyList = new ArrayList(); + protected ArrayList outcomes = new ArrayList(); + + public ImportItem() { + } + + public ImportItem(String ns, String name, String initialPath, ItemPath itemPath, String wf, int wfVer) { + this(); + setNamespace(ns); + setName(name); + setItemPath(itemPath); + setInitialPath(initialPath); + setWorkflow(wf); + setWorkflowVer(wfVer); + } + + @Override + public ItemPath getItemPath() { + if (itemPath == null) { // try to find item if it already exists + DomainPath existingItem = new DomainPath(initialPath+"/"+name); + if (existingItem.exists()) { + try { + itemPath = existingItem.getItemPath(); + } catch (ObjectNotFoundException ex) { } + } + } + if (itemPath == null) itemPath = new ItemPath(); + return itemPath; + } + + @Override + public void setNamespace(String ns) { + super.setNamespace(ns); + if (initialPath == null) initialPath = "/desc/"+ns; + } + + @Override + public void setName(String name) { + super.setName(name); + } + + @Override + public void create(AgentPath agentPath, boolean reset) throws ObjectCannotBeUpdated, ObjectNotFoundException, CannotManageException, ObjectAlreadyExistsException, InvalidCollectionModification { + DomainPath domPath = new DomainPath(new DomainPath(initialPath), name); + if (domPath.exists()) { + ItemPath domItem = domPath.getItemPath(); + if (!getItemPath().equals(domItem)) + throw new CannotManageException("Item "+domPath+" was found with the wrong itemPath ("+domPath.getItemPath()+" vs "+getItemPath()+")"); + } + + TraceableEntity newItem; + if (getItemPath().exists()) { + Logger.msg(1, "ImportItem.create() - Verifying module item "+getItemPath()+" at "+domPath); + newItem = Gateway.getCorbaServer().getItem(getItemPath()); + } + else { + Logger.msg(1, "ImportItem.create() - Creating module item "+getItemPath()+" at "+domPath); + newItem = Gateway.getCorbaServer().createItem(getItemPath()); + Gateway.getLookupManager().add(getItemPath()); + } + + // set the name property + properties.add(new Property("Name", name, true)); + + // find workflow def + CompositeActivityDef compact; + // default workflow version is 0 if not given + int usedWfVer; + if (workflowVer == null) usedWfVer = 0; + else usedWfVer = workflowVer.intValue(); + try { + compact = (CompositeActivityDef)LocalObjectLoader.getActDef(workflow, usedWfVer); + } catch (ObjectNotFoundException ex) { + throw new CannotManageException("Could not find workflow "+workflow+"v"+usedWfVer+" for item "+domPath); + } catch (InvalidDataException e) { + throw new CannotManageException("Workflow def "+workflow+" v"+usedWfVer+" for item "+domPath+" was not valid"); + } + + // create collections + CollectionArrayList colls = new CollectionArrayList(); + for (ImportDependency element: dependencyList) { + Dependency newDep = element.create(); + colls.put(newDep); + } + + for (ImportAggregation element : aggregationList) { + Aggregation newAgg = element.create(); + colls.put(newAgg); + } + + // (re)initialise the new item with properties, workflow and collections + try { + newItem.initialise( + agentPath.getSystemKey(), + Gateway.getMarshaller().marshall(new PropertyArrayList(properties)), + Gateway.getMarshaller().marshall(compact.instantiate()), + Gateway.getMarshaller().marshall(colls)); + } catch (Exception ex) { + Logger.error("Error initialising new item "+name ); + Logger.error(ex); + throw new CannotManageException("Problem initialising new item. See server log."); + } + + // import outcomes + XMLUnit.setIgnoreWhitespace(true); + XMLUnit.setIgnoreComments(true); + History hist = new History(getItemPath(), null); + for (ImportOutcome thisOutcome : outcomes) { + Outcome newOutcome = new Outcome(-1, thisOutcome.getData(ns), thisOutcome.schema, thisOutcome.version); + Viewpoint impView; + try { + impView = (Viewpoint)Gateway.getStorage().get(getItemPath(), ClusterStorage.VIEWPOINT+"/"+thisOutcome.schema+"/"+thisOutcome.viewname, null); + + 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"); + continue; + } + 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(getItemPath(), thisOutcome.schema, thisOutcome.viewname, thisOutcome.version, -1); + } catch (PersistencyException 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 + Transition predefDone = new Transition(0, "Done", 0, 0); + Event newEvent = hist.addEvent(agentPath, "Admin", "Import", "Import", "Import", thisOutcome.schema, thisOutcome.version, "PredefinedStep", 0, predefDone, thisOutcome.viewname); + newOutcome.setID(newEvent.getID()); + impView.setEventId(newEvent.getID()); + try { + Gateway.getStorage().put(getItemPath(), newOutcome, null); + Gateway.getStorage().put(getItemPath(), impView, null); + } catch (PersistencyException 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) + if (!domPath.exists()) { + domPath.setItemPath(getItemPath()); + Gateway.getLookupManager().add(domPath); + } + } + + public String getInitialPath() { + return initialPath; + } + + public void setInitialPath(String initialPath) { + this.initialPath = initialPath; + } + + public String getWorkflow() { + return workflow; + } + + public void setWorkflow(String workflow) { + this.workflow = workflow; + } + + public Integer getWorkflowVer() { + return workflowVer; + } + + public void setWorkflowVer(Integer workflowVer) { + this.workflowVer = workflowVer; + } + + public ArrayList getProperties() { + return properties; + } + + public void setProperties(ArrayList properties) { + this.properties = properties; + } + + public ArrayList getAggregationList() { + return aggregationList; + } + + public void setAggregationList(ArrayList aggregationList) { + this.aggregationList = aggregationList; + } + + public ArrayList getDependencyList() { + return dependencyList; + } + + public void setDependencyList(ArrayList dependencyList) { + this.dependencyList = dependencyList; + } + + public ArrayList getOutcomes() { + return outcomes; + } + + public void setOutcomes(ArrayList outcomes) { + this.outcomes = outcomes; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportOutcome.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportOutcome.java new file mode 100644 index 0000000..b3be323 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportOutcome.java @@ -0,0 +1,48 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.imports; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.process.Gateway; + + +public class ImportOutcome { + public String schema, viewname, path, data; + public int version; + + public ImportOutcome() { + } + + public ImportOutcome(String schema, int version, String viewname, String path) { + super(); + this.schema = schema; + this.version = version; + this.viewname = viewname; + this.path = path; + } + + public String getData(String ns) throws ObjectNotFoundException { + if (data == null) + data = Gateway.getResource().getTextResource(ns, path); + return data; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportRole.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportRole.java new file mode 100644 index 0000000..daf1b4c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportRole.java @@ -0,0 +1,75 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.imports; + +import java.util.Iterator; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.Path; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.process.module.ModuleImport; + + +public class ImportRole extends ModuleImport { + + private boolean jobList; + + public ImportRole() { + } + + @Override + public void create(AgentPath agentPath, boolean reset) throws ObjectAlreadyExistsException, ObjectCannotBeUpdated, CannotManageException, ObjectNotFoundException { + RolePath parent = new RolePath(); + if (name.indexOf('/') > -1) { + String[] roleComp = name.split("/"); + for (int i=0; i childIter = parent.getChildren(); + boolean found = false; + while (childIter.hasNext()) { + RolePath childRole = (RolePath)childIter.next(); + if (childRole.getName().equals(roleComp[i])) { + parent = childRole; + found = true; + break; + } + } + if (!found) throw new ObjectNotFoundException("Parent role "+roleComp[i]+" was not found"); + } + name = roleComp[roleComp.length-1]; + } + RolePath newRole = new RolePath(parent, name, jobList); + if (!newRole.exists()) Gateway.getLookupManager().createRole(newRole); + } + + public boolean hasJobList() { + return jobList; + } + + public void setJobList(boolean jobList) { + this.jobList = jobList; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/package-info.java b/src/main/java/org/cristalise/kernel/entity/package-info.java new file mode 100644 index 0000000..23ab74c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/package-info.java @@ -0,0 +1,39 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +/** + * The implementations of Items, and their core functionality. + * + *

    The CORBA IDLs generate the Item and Agent interfaces and their support + * classes in this package. In the kernel source tree, the classes + * {@link TraceableEntity} and {@link ItemImplementation} provides the + * implementing object for the Item on the server side, while the Locator class, + * plus the {@link CorbaServer} handle instantiation and caching of Items (and + * Agents) on the server. + * + *

    The corresponding implementation for Agents is located in the agent + * sub-package. + * + *

    Also in this package is the {@link C2KLocalObject} interface, which is + * implemented by all objects that may be stored in the CRISTAL persistency + * mechanism. + */ + +package org.cristalise.kernel.entity; \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/AgentProxy.java b/src/main/java/org/cristalise/kernel/entity/proxy/AgentProxy.java new file mode 100644 index 0000000..4b05764 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/AgentProxy.java @@ -0,0 +1,323 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.proxy; + +import java.util.Date; +import java.util.Iterator; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.Agent; +import org.cristalise.kernel.entity.AgentHelper; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.agent.Job; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.Path; +import org.cristalise.kernel.persistency.outcome.OutcomeValidator; +import org.cristalise.kernel.persistency.outcome.Schema; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.process.auth.Authenticator; +import org.cristalise.kernel.scripting.ErrorInfo; +import org.cristalise.kernel.scripting.Script; +import org.cristalise.kernel.scripting.ScriptErrorException; +import org.cristalise.kernel.scripting.ScriptingEngineException; +import org.cristalise.kernel.utils.LocalObjectLoader; +import org.cristalise.kernel.utils.Logger; + + +/****************************************************************************** + * It is a wrapper for the connection and communication with Agent + * It caches data loaded from the Agent to reduce communication + * + * @version $Revision: 1.37 $ $Date: 2005/10/05 07:39:36 $ + * @author $Author: abranson $ + ******************************************************************************/ +public class AgentProxy extends ItemProxy +{ + + AgentPath mAgentPath; + String mAgentName; + Authenticator auth; + /************************************************************************** + * Creates an AgentProxy without cache and change notification + **************************************************************************/ + protected AgentProxy( org.omg.CORBA.Object ior, + AgentPath agentPath) + throws ObjectNotFoundException + { + super(ior, agentPath); + mAgentPath = agentPath; + } + + public Authenticator getAuthObj() { + return auth; + } + + public void setAuthObj(Authenticator auth) { + this.auth = auth; + } + + @Override + public Agent narrow() throws ObjectNotFoundException + { + try { + return AgentHelper.narrow(mIOR); + } catch (org.omg.CORBA.BAD_PARAM ex) { } + throw new ObjectNotFoundException("CORBA Object was not an Agent, or the server is down."); + } + + /** + * Standard execution of jobs. Note that this method should always be the one used from clients - all execution + * parameters are taken from the job where they're probably going to be correct. + * + * @param job + * @throws AccessRightsException + * @throws InvalidDataException + * @throws InvalidTransitionException + * @throws ObjectNotFoundException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws ScriptErrorException + * @throws InvalidCollectionModification + */ + public String execute(Job job) + throws AccessRightsException, + InvalidDataException, + InvalidTransitionException, + ObjectNotFoundException, + PersistencyException, + ObjectAlreadyExistsException, + ScriptErrorException, InvalidCollectionModification + { + ItemProxy item = Gateway.getProxyManager().getProxy(job.getItemPath()); + OutcomeValidator validator = null; + Date startTime = new Date(); + Logger.msg(3, "AgentProxy - executing "+job.getStepPath()+" for "+mAgentPath.getAgentName()); + // get the outcome validator if present + if (job.hasOutcome()) + { + String schemaName = job.getSchemaName(); + int schemaVersion = job.getSchemaVersion(); + + Logger.msg(5, "AgentProxy - fetching schema "+schemaName+"_"+schemaVersion+" for validation"); + // retrieve schema + Schema schema = LocalObjectLoader.getSchema(schemaName, schemaVersion); + + if (schema == null) + throw new InvalidDataException("Job references outcome type "+schemaName+" version "+schemaVersion+" that does not exist in this centre."); + + try { + validator = OutcomeValidator.getValidator(schema); + } catch (Exception e) { + throw new InvalidDataException("Could not create validator: "+e.getMessage()); + } + } + + if(job.hasScript()) { + Logger.msg(3, "AgentProxy - executing script "+job.getScriptName()+" v"+job.getScriptVersion()); + try { + + // pre-validate outcome from script if there is one + if (job.getOutcomeString()!= null && validator != null) { + Logger.msg(5, "AgentProxy - validating outcome before script execution"); + String error = validator.validate(job.getOutcomeString()); + if (error.length() > 0) { + Logger.error("Outcome not valid: \n " + error); + throw new InvalidDataException(error); + } + } + + // load script + ErrorInfo scriptErrors = (ErrorInfo)callScript(item, job); + String errorString = scriptErrors.toString(); + if (scriptErrors.getFatal()) { + Logger.msg(3, "AgentProxy - fatal script error"); + throw new ScriptErrorException(scriptErrors); + } + if (errorString.length() > 0) + Logger.warning("Script errors: "+errorString); + } catch (ScriptingEngineException ex) { + Logger.error(ex); + throw new InvalidDataException(ex.getMessage()); + } + } + + if (job.isOutcomeSet()) { + Logger.msg(3, "AgentProxy - validating outcome"); + String error = validator.validate(job.getOutcomeString()); + if (error.length() > 0) + throw new InvalidDataException(error); + } + + job.setAgentPath(mAgentPath); + Logger.msg(3, "AgentProxy - submitting job to item proxy"); + String result = item.requestAction(job); + if (Logger.doLog(3)) { + Date timeNow = new Date(); + long secsNow = (timeNow.getTime()-startTime.getTime())/1000; + Logger.msg(3, "Execution took "+secsNow+" seconds"); + } + + return result; + } + + private Object callScript(ItemProxy item, Job job) throws ScriptingEngineException { + Script script = new Script(item, this, job); + return script.execute(); + } + + public String execute(ItemProxy item, String predefStep, C2KLocalObject obj) + throws AccessRightsException, + InvalidDataException, + InvalidTransitionException, + ObjectNotFoundException, + PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification + { + String param; + try { + param = marshall(obj); + } catch (Exception ex) { + Logger.error(ex); + throw new InvalidDataException("Error on marshall"); + } + return execute(item, predefStep, param); + } + + /** + * Multi-parameter execution. Wraps parameters up in a PredefinedStepOutcome + * if the schema of the requested step is such. + * + * @param item The item on which to execute the step + * @param predefStep The step name to run + * @param params An array of parameters to pass to the step. See each step's + * documentation for its required parameters + * + * @return The outcome after processing. May have been altered by the step. + * + * @throws AccessRightsException The agent was not allowed to execute this step + * @throws InvalidDataException The parameters supplied were incorrect + * @throws InvalidTransitionException The step wasn't available + * @throws ObjectNotFoundException Thrown by some steps that try to locate additional objects + * @throws PersistencyException Problem writing or reading the database + * @throws ObjectAlreadyExistsException Thrown by steps that create additional object + * @throws InvalidCollectionModification + */ + public String execute(ItemProxy item, String predefStep, String[] params) + throws AccessRightsException, + InvalidDataException, + InvalidTransitionException, + ObjectNotFoundException, + PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification + { + String schemaName = PredefinedStep.getPredefStepSchemaName(predefStep); + String param; + if (schemaName.equals("PredefinedStepOutcome")) + param = PredefinedStep.bundleData(params); + else + param = params[0]; + + return item.getItem().requestAction(mAgentPath.getSystemKey(), "workflow/predefined/"+predefStep, PredefinedStep.DONE, param); + } + + /** + * Single parameter execution + * + * @see #execute(ItemProxy, String, String[]) + * + * @param item + * @param predefStep + * @param param + * @return + * @throws AccessRightsException + * @throws InvalidDataException + * @throws InvalidTransitionException + * @throws ObjectNotFoundException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws InvalidCollectionModification + */ + + public String execute(ItemProxy item, String predefStep, String param) + throws AccessRightsException, + InvalidDataException, + InvalidTransitionException, + ObjectNotFoundException, + PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification + { + return execute(item, predefStep, new String[] {param }); + } + + /** Wrappers for scripts */ + public String marshall(Object obj) throws Exception { + return Gateway.getMarshaller().marshall(obj); + } + + public Object unmarshall(String obj) throws Exception { + return Gateway.getMarshaller().unmarshall(obj); + } + + /** Let scripts resolve items */ + public ItemProxy searchItem(String name) throws ObjectNotFoundException { + Iterator results = Gateway.getLookup().search(new DomainPath(""),name); + + Path returnPath = null; + if (!results.hasNext()) + throw new ObjectNotFoundException(name); + + while(results.hasNext()) { + Path nextMatch = results.next(); + if (returnPath != null && nextMatch.getUUID() != null && !returnPath.getUUID().equals(nextMatch.getUUID())) + throw new ObjectNotFoundException("Too many items with that name"); + returnPath = nextMatch; + } + + return Gateway.getProxyManager().getProxy(returnPath); + } + + public ItemProxy getItem(String itemPath) throws ObjectNotFoundException { + return (getItem(new DomainPath(itemPath))); + } + + @Override + public AgentPath getPath() { + return mAgentPath; + } + + public ItemProxy getItem(Path itemPath) throws ObjectNotFoundException { + return Gateway.getProxyManager().getProxy(itemPath); + } + + public ItemProxy getItemByUUID(String uuid) throws ObjectNotFoundException, InvalidItemPathException { + return Gateway.getProxyManager().getProxy(new ItemPath(uuid)); + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/DomainPathSubscriber.java b/src/main/java/org/cristalise/kernel/entity/proxy/DomainPathSubscriber.java new file mode 100644 index 0000000..bce1fa7 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/DomainPathSubscriber.java @@ -0,0 +1,38 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.proxy; + +import org.cristalise.kernel.lookup.DomainPath; + +/************************************************************************** + * + * $Revision: 1.1 $ + * $Date: 2004/02/05 16:11:57 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public interface DomainPathSubscriber { + + public void pathAdded(DomainPath path); + public void pathRemoved(DomainPath path); +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ItemProxy.java b/src/main/java/org/cristalise/kernel/entity/proxy/ItemProxy.java new file mode 100644 index 0000000..326da36 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ItemProxy.java @@ -0,0 +1,390 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.proxy; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import org.cristalise.kernel.collection.Collection; +import org.cristalise.kernel.collection.CollectionArrayList; +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.Item; +import org.cristalise.kernel.entity.ItemHelper; +import org.cristalise.kernel.entity.agent.Job; +import org.cristalise.kernel.entity.agent.JobArrayList; +import org.cristalise.kernel.lifecycle.instance.CompositeActivity; +import org.cristalise.kernel.lifecycle.instance.Workflow; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.utils.CastorXMLUtility; +import org.cristalise.kernel.utils.Logger; +import org.exolab.castor.mapping.MappingException; +import org.exolab.castor.xml.MarshalException; +import org.exolab.castor.xml.ValidationException; + + +/****************************************************************************** + * It is a wrapper for the connection and communication with Item + * It caches data loaded from the Item to reduce communication + * + * @version $Revision: 1.25 $ $Date: 2005/05/10 11:40:09 $ + * @author $Author: abranson $ + ******************************************************************************/ +public class ItemProxy +{ + + protected Item mItem = null; + protected ItemPath mItemPath; + protected org.omg.CORBA.Object mIOR; + private final HashMap, ProxyObserver> + mSubscriptions; + + /************************************************************************** + * + **************************************************************************/ + protected ItemProxy( org.omg.CORBA.Object ior, + ItemPath itemPath) + { + Logger.msg(8, "ItemProxy::initialise() - Initialising item proxy " +itemPath); + + mIOR = ior; + mItemPath = itemPath; + mSubscriptions = new HashMap, ProxyObserver>(); + + } + + public ItemPath getPath() { + return mItemPath; + } + + protected Item getItem() throws ObjectNotFoundException { + if (mItem == null) + mItem = narrow(); + return mItem; + } + + public Item narrow() throws ObjectNotFoundException + { + try { + return ItemHelper.narrow(mIOR); + } catch (org.omg.CORBA.BAD_PARAM ex) { } + throw new ObjectNotFoundException("CORBA Object was not an Item, or the server is down."); + } + + public void initialise( AgentPath agentId, + PropertyArrayList itemProps, + CompositeActivity workflow, + CollectionArrayList colls + ) + throws AccessRightsException, InvalidDataException, PersistencyException, ObjectNotFoundException, MarshalException, ValidationException, IOException, MappingException, InvalidCollectionModification + { + Logger.msg(7, "ItemProxy::initialise - started"); + CastorXMLUtility xml = Gateway.getMarshaller(); + if (itemProps == null) throw new InvalidDataException("No initial properties supplied"); + String propString = xml.marshall(itemProps); + String wfString = ""; + if (workflow != null) wfString = xml.marshall(workflow); + String collString = ""; + if (colls != null) collString = xml.marshall(colls); + + getItem().initialise( agentId.getSystemKey(), propString, wfString, collString); + } + + public void setProperty(AgentProxy agent, String name, String value) + throws AccessRightsException, + PersistencyException, InvalidDataException + { + String[] params = new String[2]; + params[0] = name; + params[1] = value; + try { + agent.execute(this, "WriteProperty", params); + } catch (AccessRightsException e) { + throw (e); + } catch (PersistencyException e) { + throw (e); + } catch (InvalidDataException e) { + throw (e); + } catch (Exception e) { + Logger.error(e); + throw new PersistencyException("Could not store property"); + } + } + + /** + * @throws InvalidCollectionModification + * + **************************************************************************/ + public String requestAction( Job thisJob ) + throws AccessRightsException, + InvalidTransitionException, + ObjectNotFoundException, + InvalidDataException, + PersistencyException, + ObjectAlreadyExistsException, + InvalidCollectionModification + { + String outcome = thisJob.getOutcomeString(); + // check fields that should have been filled in + if (outcome==null) + if (thisJob.isOutcomeRequired()) + throw new InvalidDataException("Outcome is required."); + else + outcome=""; + + if (thisJob.getAgentPath() == null) + throw new InvalidDataException("No Agent specified."); + + Logger.msg(7, "ItemProxy - executing "+thisJob.getStepPath()+" for "+thisJob.getAgentName()); + return getItem().requestAction (thisJob.getAgentPath().getSystemKey(), thisJob.getStepPath(), + thisJob.getTransition().getId(), outcome); + } + + /************************************************************************** + * + **************************************************************************/ + private ArrayList getJobList(AgentPath agentPath, boolean filter) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException + { + JobArrayList thisJobList; + try { + String jobs = getItem().queryLifeCycle(agentPath.getSystemKey(), filter); + thisJobList = (JobArrayList)Gateway.getMarshaller().unmarshall(jobs); + } + catch (Exception e) { + Logger.error(e); + throw new PersistencyException("Exception::ItemProxy::getJobList() - Cannot unmarshall the jobs"); + } + return thisJobList.list; + } + + public ArrayList getJobList(AgentProxy agent) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException + { + return getJobList(agent.getPath(), true); + } + + private Job getJobByName(String actName, AgentPath agent) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException { + + ArrayList jobList = getJobList(agent, true); + for (Job job : jobList) { + if (job.getStepName().equals(actName) && job.hasOutcome()) + return job; + } + return null; + + } + + public Collection getCollection(String collName) throws ObjectNotFoundException { + return (Collection)getObject(ClusterStorage.COLLECTION+"/"+collName+"/last"); + } + + public Workflow getWorkflow() throws ObjectNotFoundException { + return (Workflow)getObject(ClusterStorage.LIFECYCLE+"/workflow"); + } + + public Viewpoint getViewpoint(String schemaName, String viewName) throws ObjectNotFoundException { + return (Viewpoint)getObject(ClusterStorage.VIEWPOINT+"/"+schemaName+"/"+viewName); + } + + public Job getJobByName(String actName, AgentProxy agent) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException { + return getJobByName(actName, agent.getPath()); + } + + /** + * If this is reaped, clear out the cache for it too. + */ + @Override + protected void finalize() throws Throwable { + Logger.msg(7, "Proxy "+mItemPath+" reaped"); + Gateway.getStorage().clearCache(mItemPath, null); + Gateway.getProxyManager().removeProxy(mItemPath); + super.finalize(); + } + + /************************************************************************** + * + **************************************************************************/ + public String queryData( String path ) + throws ObjectNotFoundException + { + + try { + Logger.msg(7, "EntityProxy.queryData() - "+mItemPath+"/"+path); + if (path.endsWith("all")) { + Logger.msg(7, "EntityProxy.queryData() - listing contents"); + String[] result = Gateway.getStorage().getClusterContents(mItemPath, path.substring(0, path.length()-3)); + StringBuffer retString = new StringBuffer(); + for (int i = 0; i < result.length; i++) { + retString.append(result[i]); + if (i"+e.getMessage()+""; + } + } + + public String[] getContents( String path ) throws ObjectNotFoundException { + try { + return Gateway.getStorage().getClusterContents(mItemPath, path.substring(0, path.length())); + } catch (PersistencyException e) { + throw new ObjectNotFoundException(e.toString()); + } + } + + + /************************************************************************** + * + **************************************************************************/ + public C2KLocalObject getObject( String xpath ) + throws ObjectNotFoundException + { + // load from storage, falling back to proxy loader if not found in others + try + { + return Gateway.getStorage().get( mItemPath, xpath , null); + } + catch( PersistencyException ex ) + { + Logger.msg(4, "Exception loading object :"+mItemPath+"/"+xpath); + throw new ObjectNotFoundException( ex.toString() ); + } + } + + + + public String getProperty( String name ) + throws ObjectNotFoundException + { + Logger.msg(5, "Get property "+name+" from item "+mItemPath); + Property prop = (Property)getObject("Property/"+name); + try + { + return prop.getValue(); + } + catch (NullPointerException ex) + { + throw new ObjectNotFoundException(); + } + } + + public String getName() + { + try { + return getProperty("Name"); + } catch (ObjectNotFoundException ex) { + return null; + } + } + + + + + /************************************************************************** + * Subscription methods + **************************************************************************/ + + public void subscribe(MemberSubscription newSub) { + + newSub.setSubject(this); + synchronized (this){ + mSubscriptions.put( newSub, newSub.getObserver() ); + } + new Thread(newSub).start(); + Logger.msg(7, "Subscribed "+newSub.getObserver().getClass().getName()+" for "+newSub.interest); + } + + public void unsubscribe(ProxyObserver observer) + { + synchronized (this){ + for (Iterator> e = mSubscriptions.keySet().iterator(); e.hasNext();) { + MemberSubscription thisSub = e.next(); + if (mSubscriptions.get( thisSub ) == observer) { + e.remove(); + Logger.msg(7, "Unsubscribed "+observer.getClass().getName()); + } + } + } + } + + public void dumpSubscriptions(int logLevel) { + if (mSubscriptions.size() == 0) return; + Logger.msg(logLevel, "Subscriptions to proxy "+mItemPath+":"); + synchronized(this) { + for (MemberSubscription element : mSubscriptions.keySet()) { + ProxyObserver obs = element.getObserver(); + if (obs != null) + Logger.msg(logLevel, " "+element.getObserver().getClass().getName()+" subscribed to "+element.interest); + else + Logger.msg(logLevel, " Phantom subscription to "+element.interest); + } + } + } + + public void notify(ProxyMessage message) { + Logger.msg(4, "EntityProxy.notify() - Received change notification for "+message.getPath()+" on "+mItemPath); + synchronized (this){ + if (Gateway.getProxyServer()== null || !message.getServer().equals(Gateway.getProxyServer().getServerName())) + Gateway.getStorage().clearCache(mItemPath, message.getPath()); + for (Iterator> e = mSubscriptions.keySet().iterator(); e.hasNext();) { + MemberSubscription newSub = e.next(); + if (newSub.getObserver() == null) { // phantom + Logger.msg(4, "Removing phantom subscription to "+newSub.interest); + e.remove(); + } + else + newSub.update(message.getPath(), message.getState()); + } + } + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/MemberSubscription.java b/src/main/java/org/cristalise/kernel/entity/proxy/MemberSubscription.java new file mode 100644 index 0000000..2873eb8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/MemberSubscription.java @@ -0,0 +1,141 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.proxy; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.StringTokenizer; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.utils.Logger; + + +public class MemberSubscription implements Runnable { + public static final String ERROR = "Error"; + public static final String END = "theEND"; + + ItemProxy subject; + String interest; + // keep the subscriber by weak reference, so it is not kept from the garbage collector if no longer used + WeakReference> observerReference; + ArrayList contents = new ArrayList(); + boolean preLoad; + + public MemberSubscription(ProxyObserver observer, String interest, boolean preLoad) { + setObserver(observer); + this.interest = interest; + this.preLoad = preLoad; + } + + @Override + public void run() { + Thread.currentThread().setName("Member Subscription: "+subject.getPath()+":"+interest); + if (preLoad) loadChildren(); + } + + private void loadChildren() { + C newMember; + ProxyObserver observer = getObserver(); + if (observer == null) return; //reaped + try { + // fetch contents of path + String children = subject.queryData(interest+"/all"); + StringTokenizer tok = new StringTokenizer(children, ","); + ArrayList newContents = new ArrayList(); + while (tok.hasMoreTokens()) + newContents.add(tok.nextToken()); + + // look to see what's new + for (String newChild: newContents) { + + // load child object + try { + newMember = (C)subject.getObject(interest+"/"+newChild); + contents.remove(newChild); + observer.add(newMember); + } catch (ObjectNotFoundException ex) { + observer.control(ERROR, "Listed member "+newChild+" was not found."); + } catch (ClassCastException ex) { + Logger.error(ex); + observer.control(ERROR, "Listed member "+newChild+" was the wrong type."); + } + } + // report what's left in old contents as deleted + for (String oldChild: contents) { + observer.remove(interest+"/"+oldChild); + } + //replace contents arraylist + contents = newContents; + //report that we're done + observer.control(END, null); + } catch (Exception ex) { + observer.control(ERROR, "Query on "+interest+" failed with "+ex.getMessage()); + } + } + + public boolean isRelevant(String path) { + Logger.msg(7, "Checking relevance of "+path+" to "+interest); + return (path.startsWith(interest)); + } + + public void update(String path, boolean deleted) { + ProxyObserver observer = getObserver(); + if (observer == null) return; //reaped + Logger.msg(7, "Processing proxy message path "+path +" for "+observer+". Interest: "+interest+" Was Deleted:"+deleted); + if (!path.startsWith(interest)) // doesn't concern us + return; + + if (path.equals(interest)) // refresh contents + loadChildren(); + else { + String name = path.substring(interest.length()); + if (deleted) { + Logger.msg(4, "Removing "+path); + contents.remove(name); + observer.remove(name); + } + else { + try { + C newMember = (C)subject.getObject(path); + Logger.msg(4, "Adding "+path); + contents.add(name); + observer.add(newMember); + } catch (ObjectNotFoundException e) { + Logger.error("Member Subscription: could not load "+path); + Logger.error(e); + } + } + } + } + + public void setObserver(ProxyObserver observer) { + observerReference = new WeakReference>(observer); + } + + public void setSubject(ItemProxy subject) { + this.subject = subject; + } + + public ProxyObserver getObserver() { + return observerReference.get(); + } +} + diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyClientConnection.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyClientConnection.java new file mode 100644 index 0000000..9f65afa --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyClientConnection.java @@ -0,0 +1,208 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.proxy; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.InterruptedIOException; +import java.io.PrintWriter; +import java.net.Socket; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Iterator; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; +import org.cristalise.kernel.utils.server.SocketHandler; + + +/************************************************************************** + * + * $Revision: 1.18 $ + * $Date: 2005/05/10 11:40:09 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public class ProxyClientConnection implements SocketHandler { + + Socket clientSocket = null; + static int clientId = -1; + int thisClientId; + ArrayList subscribedItems; + PrintWriter response; + BufferedReader request; + boolean closing = false; + + public ProxyClientConnection() { + super(); + thisClientId = ++clientId; + Gateway.getProxyServer().registerProxyClient(this); + Logger.msg(1, "Proxy Client Connection Handler "+thisClientId+" ready."); + } + + + @Override + public String getName() { + return "Proxy Client Connection"; + } + + @Override + public boolean isBusy() { + return clientSocket != null; + } + + @Override + public synchronized void setSocket(Socket newSocket) { + try { + Logger.msg(1, "Proxy Client Connection "+thisClientId+" connect from "+newSocket.getInetAddress()+":"+newSocket.getPort()); + newSocket.setSoTimeout(500); + clientSocket = newSocket; + response = new PrintWriter(clientSocket.getOutputStream(), true); + subscribedItems = new ArrayList(); + } catch (SocketException ex) { + Logger.msg("Could not set socket timeout:"); + Logger.error(ex); + closeSocket(); + } catch (IOException ex) { + Logger.msg("Could not setup output stream:"); + Logger.error(ex); + closeSocket(); + } + } + + /** + * Main loop. Reads proxy commands from the client and acts on them. + */ + @Override + public void run() { + Thread.currentThread().setName("Proxy Client Connection: "+clientSocket.getInetAddress()); + Logger.msg(7, "ProxyClientConnection "+thisClientId+" - Setting up proxy client connection with "+clientSocket.getInetAddress()); + try { + request = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + String input = null; + ProxyMessage thisMessage; + while (clientSocket != null) { + try { + input = request.readLine(); + Logger.msg(9, "ProxyClientConnection "+thisClientId+" - received "+input); + thisMessage = new ProxyMessage(input); + processMessage(thisMessage); + } catch (InterruptedIOException ex) { //timeout + } catch (InvalidDataException ex) { // invalid proxy message + Logger.error("ProxyClientConnection "+thisClientId+" - Invalid proxy message: "+input); + } + + } + } catch (IOException ex) { + if (!closing) + Logger.error("ProxyClientConnection "+thisClientId+" - Error reading from socket."); + } + closeSocket(); + Logger.msg(1, "ProxyClientConnection "+thisClientId+" closed."); + } + + private void processMessage(ProxyMessage message) throws InvalidDataException { + + // proxy disconnection + if (message.getPath().equals(ProxyMessage.BYEPATH)) { + Logger.msg(7, "ProxyClientConnection "+thisClientId+" disconnecting"); + closeSocket(); + } + + // proxy checking connection + else if (message.getPath().equals(ProxyMessage.PINGPATH)) + response.println(ProxyMessage.pingMessage); + + // new subscription to entity changes + else if (message.getPath().equals(ProxyMessage.ADDPATH)) { + Logger.msg(7, "ProxyClientConnection "+thisClientId+" subscribed to "+message.getItemPath()); + synchronized (subscribedItems) { + subscribedItems.add(message.getItemPath()); + } + } + + // remove of subscription to entity changes + else if (message.getPath().equals(ProxyMessage.DELPATH)) { + synchronized (subscribedItems) { + subscribedItems.remove(message.getItemPath()); + } + Logger.msg(7, "ProxyClientConnection "+thisClientId+" unsubscribed from "+message.getItemPath()); + } + + else // unknown message + Logger.error("ProxyClientConnection "+thisClientId+" - Unknown message type: "+message); + + } + + public synchronized void sendMessage(ProxyMessage message) { + if (clientSocket==null) return; // idle + boolean relevant = message.getItemPath() == null; + synchronized (subscribedItems) { + for (Iterator iter = subscribedItems.iterator(); iter.hasNext() && !relevant;) { + ItemPath thisKey = iter.next(); + if (thisKey.equals(message.getItemPath())) + relevant = true; + } + } + if (!relevant) return; // not for our client + + response.println(message); + } + + @Override + public void shutdown() { + if (isBusy()) { + closing = true; + Logger.msg("ProxyClientConnection "+thisClientId+" closing."); + closeSocket(); + } + } + + @Override + public String toString() { + if (clientSocket == null) return thisClientId+": idle"; + else return thisClientId+": "+clientSocket.getInetAddress(); + } + + private synchronized void closeSocket() { + if (clientSocket==null) return; + try { + request.close(); + response.close(); + clientSocket.close(); + } catch (IOException e) { + Logger.error("ProxyClientConnection "+thisClientId+" - Could not close socket."); + Logger.error(e); + } + synchronized (subscribedItems) { + subscribedItems = null; + } + + clientSocket = null; + + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyManager.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyManager.java new file mode 100644 index 0000000..6f5bde3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyManager.java @@ -0,0 +1,277 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.proxy; + +import java.util.ArrayList; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Iterator; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.Path; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.utils.Logger; +import org.cristalise.kernel.utils.SoftCache; + + + +public class ProxyManager +{ + SoftCache proxyPool = new SoftCache(50); + HashMap treeSubscribers = new HashMap(); + HashMap connections = new HashMap(); + + /** + * Create a proxy manager to listen for proxy events and reap unused proxies + */ + public ProxyManager() + { + Logger.msg(5, "ProxyManager - Starting....."); + + Iterator servers = Gateway.getLookup().search(new DomainPath("/servers"), new Property("Type", "Server", false)); + while(servers.hasNext()) { + Path thisServerResult = servers.next(); + try { + ItemPath thisServerPath = thisServerResult.getItemPath(); + String remoteServer = ((Property)Gateway.getStorage().get(thisServerPath, ClusterStorage.PROPERTY+"/Name", null)).getValue(); + String portStr = ((Property)Gateway.getStorage().get(thisServerPath, ClusterStorage.PROPERTY+"/ProxyPort", null)).getValue(); + int remotePort = Integer.parseInt(portStr); + connectToProxyServer(remoteServer, remotePort); + + } catch (Exception ex) { + Logger.error("Exception retrieving proxy server connection data for "+thisServerResult); + Logger.error(ex); + } + } + } + + public void connectToProxyServer(String name, int port) { + ProxyServerConnection oldConn = connections.get(name); + if (oldConn != null) + oldConn.shutdown(); + connections.put(name, new ProxyServerConnection(name, port, this)); + } + + + protected void resubscribe(ProxyServerConnection conn) { + synchronized (proxyPool) { + for (ItemPath key : proxyPool.keySet()) { + ProxyMessage sub = new ProxyMessage(key, ProxyMessage.ADDPATH, false); + Logger.msg(5, "Subscribing to item "+key); + conn.sendMessage(sub); + } + } + } + + /** + * @param sub + */ + private void sendMessage(ProxyMessage sub) { + for (ProxyServerConnection element : connections.values()) { + element.sendMessage(sub); + } + + } + + public void shutdown() { + Logger.msg("ProxyManager.shutdown() - flagging shutdown of server connections"); + for (ProxyServerConnection element : connections.values()) { + element.shutdown(); + } + } + + protected void processMessage(ProxyMessage thisMessage) throws InvalidDataException { + if (Logger.doLog(9)) Logger.msg(9, thisMessage.toString()); + + if (thisMessage.getPath().equals(ProxyMessage.PINGPATH)) // ping response + return; + + if (thisMessage.getItemPath() == null) // must be domain path info + informTreeSubscribers(thisMessage.getState(), thisMessage.getPath()); + else { + // proper proxy message + Logger.msg(5, "Received proxy message: "+thisMessage.toString()); + ItemProxy relevant = proxyPool.get(thisMessage.getItemPath()); + if (relevant == null) + Logger.warning("Received proxy message for sysKey "+thisMessage.getItemPath()+" which we don't have a proxy for."); + else + try { + relevant.notify(thisMessage); + } catch (Throwable ex) { + Logger.error("Error caught notifying proxy listener "+relevant.toString()+" of "+thisMessage.toString()); + Logger.error(ex); + } + } + } + + private void informTreeSubscribers(boolean state, String path) { + DomainPath last = new DomainPath(path); + DomainPath parent; boolean first = true; + synchronized(treeSubscribers) { + while((parent = last.getParent()) != null) { + ArrayList currentKeys = new ArrayList(); + currentKeys.addAll(treeSubscribers.keySet()); + for (DomainPathSubscriber sub : currentKeys) { + DomainPath interest = treeSubscribers.get(sub); + if (interest!= null && interest.equals(parent)) { + if (state == ProxyMessage.ADDED) + sub.pathAdded(last); + else if (first) + sub.pathRemoved(last); + } + } + last = parent; + first = false; + } + } + } + + public void subscribeTree(DomainPathSubscriber sub, DomainPath interest) { + synchronized(treeSubscribers) { + treeSubscribers.put(sub, interest); + } + } + + public void unsubscribeTree(DomainPathSubscriber sub) { + synchronized(treeSubscribers) { + treeSubscribers.remove(sub); + } + } + + /************************************************************************** + * + **************************************************************************/ + private ItemProxy createProxy( org.omg.CORBA.Object ior, + ItemPath itemPath) + throws ObjectNotFoundException + { + + ItemProxy newProxy = null; + + Logger.msg(5, "ProxyManager::creating proxy on Item " + itemPath); + + if( itemPath instanceof AgentPath ) { + newProxy = new AgentProxy(ior, (AgentPath)itemPath); + } + else { + newProxy = new ItemProxy(ior, itemPath); + } + + // subscribe to changes from server + ProxyMessage sub = new ProxyMessage(itemPath, ProxyMessage.ADDPATH, false); + sendMessage(sub); + reportCurrentProxies(9); + return ( newProxy ); + } + + protected void removeProxy( ItemPath itemPath ) + { + ProxyMessage sub = new ProxyMessage(itemPath, ProxyMessage.DELPATH, true); + Logger.msg(5,"ProxyManager.removeProxy() - Unsubscribing to proxy informer for "+itemPath); + sendMessage(sub); + } + + + /************************************************************************** + * Called by the other GetProxy methods. Fills in either the ior or the + * SystemKey + **************************************************************************/ + private ItemProxy getProxy( org.omg.CORBA.Object ior, + ItemPath itemPath) + throws ObjectNotFoundException + { + + synchronized(proxyPool) { + ItemProxy newProxy; + // return it if it exists + newProxy = proxyPool.get(itemPath); + if (newProxy == null) { + // create a new one + newProxy = createProxy(ior, itemPath); + proxyPool.put(itemPath, newProxy); + } + return newProxy; + + } + } + + /************************************************************************** + * ItemProxy getProxy( String ) + * + * Proxy from Alias + **************************************************************************/ + public ItemProxy getProxy( Path path ) + throws ObjectNotFoundException + { + ItemPath itemPath; + if (path instanceof ItemPath) itemPath = (ItemPath)path; + else itemPath = path.getItemPath(); + Logger.msg(8,"ProxyManager::getProxy(" + path.toString() + ")"); + return getProxy( Gateway.getLookup().resolve(itemPath), + itemPath ); + + } + + public AgentProxy getAgentProxy( AgentPath path ) + throws ObjectNotFoundException + { + return (AgentProxy) getProxy(path); + } + + /************************************************************************** + * void reportCurrentProxies() + * + * A utility to Dump the current proxies loaded + **************************************************************************/ + public void reportCurrentProxies(int logLevel) + { + if (!Logger.doLog(logLevel)) return; + Logger.msg(logLevel, "Current proxies: "); + try { + synchronized(proxyPool) { + Iterator i = proxyPool.keySet().iterator(); + + for( int count=0; i.hasNext(); count++ ) + { + ItemPath nextProxy = i.next(); + ItemProxy thisProxy = proxyPool.get(nextProxy); + if (thisProxy != null) + Logger.msg(logLevel, + "" + count + ": " + + proxyPool.get(nextProxy).getClass().getName() + + ": " + nextProxy); + } + } + } catch (ConcurrentModificationException ex) { + Logger.msg(logLevel, "Proxy cache modified. Aborting."); + } + } + + + +} + diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyMessage.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyMessage.java new file mode 100644 index 0000000..61fdcd4 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyMessage.java @@ -0,0 +1,129 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.proxy; + +import java.io.IOException; +import java.net.DatagramPacket; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; + + + +/************************************************************************** + * + * $Revision: 1.11 $ + * $Date: 2005/05/10 11:40:09 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public class ProxyMessage { + + // special server message paths + public static final String BYEPATH = "bye"; + public static final String ADDPATH = "add"; + public static final String DELPATH = "del"; + public static final String PINGPATH = "ping"; + public static final boolean ADDED = false; + public static final boolean DELETED = true; + + static ProxyMessage byeMessage = new ProxyMessage(null, BYEPATH, ADDED); + static ProxyMessage pingMessage = new ProxyMessage(null, PINGPATH, ADDED); + + private ItemPath itemPath = null; + private String path = ""; + private String server = null; + private boolean state = ADDED; + + public ProxyMessage() { + super(); + } + public ProxyMessage(ItemPath itemPath, String path, boolean state) { + this(); + setItemPath(itemPath); + setPath(path); + setState(state); + } + + public ProxyMessage(String line) throws InvalidDataException, IOException { + if (line == null) + throw new IOException("Null proxy message"); + String[] tok = line.split(":"); + if (tok.length != 2) + throw new InvalidDataException("String '"+line+"' does not constitute a valid proxy message."); + if (tok[0].length() > 0 && !tok[0].equals("tree")) { + try { + itemPath = new ItemPath(tok[0]); + } catch (InvalidItemPathException e) { + throw new InvalidDataException("Item in proxy message "+line+" was not valid"); + } + } + path = tok[1]; + if (path.startsWith("-")) { + state = DELETED; + path = path.substring(1); + } + } + + public ProxyMessage(DatagramPacket packet) throws InvalidDataException, IOException { + this(new String(packet.getData())); + } + + public ItemPath getItemPath() { + return itemPath; + } + + public void setItemPath(ItemPath itemPath) { + this.itemPath = itemPath; + } + + public String getPath() { + return path; + } + + public void setPath(String newPath) { + this.path = newPath; + } + + public boolean getState() { + return state; + } + + public void setState(boolean state) { + this.state = state; + } + + @Override + public String toString() { + return (itemPath==null?"tree":itemPath.getUUID())+":"+(state?"-":"")+path; + } + + public String getServer() { + return server; + } + + public void setServer(String server) { + this.server = server; + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyObserver.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyObserver.java new file mode 100644 index 0000000..bd21034 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyObserver.java @@ -0,0 +1,47 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.proxy; + +import org.cristalise.kernel.entity.C2KLocalObject; + + + +public interface ProxyObserver +{ + /************************************************************************** + * Subscribed items are broken apart and fed one by one to these methods. + * Replacement after an event is done by feeding the new memberbase with the same id. + * ID could be an XPath? + **************************************************************************/ + public void add(V contents); + + /************************************************************************** + * the 'type' parameter should be an indication of the type of object + * supplied so that the subscriber can associate the call back with + * one of its subscriptions. If we go with an Xpath subscription form, + * then the id will probably be sufficient. + * Should be comparable (substring whatever) with the parameter given to + * the subscribe method of ItemProxy. + **************************************************************************/ + public void remove(String id); + + public void control(String control, String msg); +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServer.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServer.java new file mode 100644 index 0000000..249ec0f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServer.java @@ -0,0 +1,129 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.proxy; + +import java.util.ArrayList; +import java.util.concurrent.LinkedBlockingQueue; + +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; +import org.cristalise.kernel.utils.server.SimpleTCPIPServer; + + +public class ProxyServer implements Runnable { + + // server objects + ArrayList proxyClients; + SimpleTCPIPServer proxyListener = null; + String serverName = null; + boolean keepRunning = true; + LinkedBlockingQueue messageQueue; + + public ProxyServer(String serverName) { + Logger.msg(5, "ProxyManager::initServer - Starting....."); + int port = Gateway.getProperties().getInt("ItemServer.Proxy.port", 0); + this.serverName = serverName; + this.proxyClients = new ArrayList(); + this.messageQueue = new LinkedBlockingQueue(); + + if (port == 0) { + Logger.error("ItemServer.Proxy.port not defined in connect file. Remote proxies will not be informed of changes."); + return; + } + + // set up the proxy server + try { + Logger.msg(5, "ProxyManager::initServer - Initialising proxy informer on port "+port); + proxyListener = new SimpleTCPIPServer(port, ProxyClientConnection.class, 200); + proxyListener.startListening(); + } catch (Exception ex) { + Logger.error("Error setting up Proxy Server. Remote proxies will not be informed of changes."); + Logger.error(ex); + } + // start the message queue delivery thread + new Thread(this).start(); + } + + @Override + public void run() { + + while(keepRunning) { + ProxyMessage message = messageQueue.poll(); + if (message != null) { + synchronized(proxyClients) { + for (ProxyClientConnection client : proxyClients) { + client.sendMessage(message); + } + } + } else + try { + synchronized(this) { + if (messageQueue.isEmpty()) wait(); + } + } catch (InterruptedException e) { } + } + + } + + public String getServerName() { + return serverName; + } + + public void sendProxyEvent(ProxyMessage message) { + try { + synchronized(this) { + messageQueue.put(message); + notify(); + } + } catch (InterruptedException e) { } + } + + public void reportConnections(int logLevel) { + synchronized(proxyClients) { + Logger.msg(logLevel, "Currently connected proxy clients:"); + for (ProxyClientConnection client : proxyClients) { + Logger.msg(logLevel, " "+client); + } + } + } + + public void shutdownServer() { + Logger.msg(1, "ProxyManager: Closing Server."); + proxyListener.stopListening(); + synchronized(this) { + keepRunning = false; + notify(); + } + } + + public void registerProxyClient(ProxyClientConnection client) { + synchronized(proxyClients) { + proxyClients.add(client); + } + } + + public void unRegisterProxyClient(ProxyClientConnection client) { + synchronized(proxyClients) { + proxyClients.remove(client); + } + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServerConnection.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServerConnection.java new file mode 100644 index 0000000..1b4fba4 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServerConnection.java @@ -0,0 +1,145 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.proxy; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.InterruptedIOException; +import java.io.PrintWriter; +import java.net.Socket; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.utils.Logger; + + + +public class ProxyServerConnection extends Thread +{ + + public boolean serverIsActive = true; + // proxy client details + String serverName; + int serverPort; + Socket serverConnection; + ProxyManager manager; + // for talking to the proxy server + PrintWriter serverStream; + boolean listening = false; + static boolean isServer = false; + + /** + * Create an entity proxy manager to listen for proxy events and reap unused proxies + */ + public ProxyServerConnection(String host, int port, ProxyManager manager) + { + Logger.msg(5, "ProxyServerConnection - Initialising connection to "+host+":"+port); + serverName = host; + serverPort = port; + this.manager = manager; + listening = true; + start(); + } + + @Override + public void run() { + Thread.currentThread().setName("Proxy Client Connection Listener to "+serverName+":"+serverPort); + while (listening) { + try { + if (serverConnection == null) connect(); + if (serverConnection != null) { + BufferedReader request = new BufferedReader(new InputStreamReader(serverConnection.getInputStream())); + String input = null; + ProxyMessage thisMessage; + while (listening && serverConnection != null) { + try { + input = request.readLine(); + thisMessage = new ProxyMessage(input); + thisMessage.setServer(serverName); + manager.processMessage(thisMessage); + } catch (InterruptedIOException ex) { // timeout - send a ping + sendMessage(ProxyMessage.pingMessage); + } catch (InvalidDataException ex) { // invalid proxy message + if (input != null) + Logger.error("EntityProxyManager - Invalid proxy message: "+input); + } + } + } + } catch (IOException ex) { + Logger.error("ProxyServerConnection - Disconnected from "+serverName+":"+serverPort); + try { + serverStream.close(); + serverConnection.close(); + } catch (IOException e1) { } + + + serverStream = null; + serverConnection = null; + } + } + + if (serverStream != null) { + try { + Logger.msg(1, "Disconnecting from proxy server on "+serverName+":"+serverPort); + serverStream.println(ProxyMessage.byeMessage.toString()); + serverStream.close(); + serverConnection.close(); + serverConnection = null; + } catch (Exception e) { + Logger.error("Error disconnecting from proxy server."); + } + } + } + + public void connect() { + Logger.msg(3, "ProxyServerConnection - connecting to proxy server on "+serverName+":"+serverPort); + try { + serverConnection = new Socket(serverName, serverPort); + serverConnection.setKeepAlive(true); + serverIsActive = true; + serverConnection.setSoTimeout(5000); + serverStream = new PrintWriter(serverConnection.getOutputStream(), true); + Logger.msg("Connected to proxy server on "+serverName+":"+serverPort); + manager.resubscribe(this); + } catch (Exception e) { + Logger.msg(3, "Could not connect to proxy server. Retrying in 5s"); + try { Thread.sleep(5000); } catch (InterruptedException ex) { } + serverStream = null; + serverConnection = null; + serverIsActive = false; + } + } + + public void shutdown() { + Logger.msg("Proxy Client: flagging shutdown."); + listening = false; + } + + /** + * @param sub + */ + public void sendMessage(ProxyMessage sub) { + if (serverStream != null) + serverStream.println(sub); + } + +} + diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/package-info.java b/src/main/java/org/cristalise/kernel/entity/proxy/package-info.java new file mode 100644 index 0000000..6391b65 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/package-info.java @@ -0,0 +1,76 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +/** + * The Proxy API is a major part of the client-side functionality of the + * CRISTAL API, which provides client-side proxy objects that represent the + * Items and Agents on the server. It is the main entry point for many + * components, such as Scripts and Job execution. An AgentProxy is returned on + * login, and should be used as the root for all user-based CRISTAL interactions. + * + *

    The Proxy API provides the following functionality: + * + *

      + *
    • Transparent storage integration - Combines direct database access + * with remote calls to data retrieval methods on the Items. This allows client + * processes to load Item data directly from databases whenever possible + * without bothering the CRISTAL server. For example, the LDAP Lookup + * implementation allows client processes to load Item Properties directly from + * the LDAP server.
    • + * + *
    • Data object browsing and loading - The proxy objects allow client + * processes to browse through the storage cluster structure beneath the Item, + * and access the objects directly without having to unmarshall their XML forms. + * All object types have their own get methods, so there's no need to construct + * their paths nor cast. + * + *
    • Item object and directory change notification - When a proxy + * object is created, it notifies the CRISTAL server that its Item is located + * on, and it notified of all additions, deletions and modifications of objects + * within that Item so it can remain up-to-date. Client applications may use + * the {@link ProxyObserver} interface to be notified of changes, using + * {@link MemberSubscription} instances to set up push subscriptions to cluster + * contents. It also provides a mechanism for subscribing to directory paths, + * so that domain tree browsers can implement asynchronous loading and update + * themselves when the tree changes.
    • + * + *
    • Job querying - Job objects may be retrieved directly from an + * ItemProxy, and may also be filtered by Activity name.
    • + * + *
    • Job execution - The {@link AgentProxy} provides the main + * execution method for Jobs. This method performs outcome validation and + * executes required CRISTAL Scripts in the client process before the execution + * is requested on the server. Additional execution methods to call Predefined + * Steps are also available. + * + *
    • Utility methods for resolution and marshalling - The AgentProxy + * provides utility methods for finding Items in the directory by name, path, + * or system key, and gives access to the Castor XML marshalling system to + * transform CRISTAL objects to XML and back again.
    • + *
    + *

    The core object of the Proxy API is the ProxyManager, which is initialized + * as a static member of the Gateway on initialization. This object can be used + * to create a Proxy object from a Path from the directory, and maintains a + * connection to the server called the Proxy Update Notification Channel, + * through which it subscribes to Items it holds proxies for so it can be + * informed of changes to Item data through {@link ProxyMessage} objects. + * + */ +package org.cristalise.kernel.entity.proxy; \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/transfer/TransferItem.java b/src/main/java/org/cristalise/kernel/entity/transfer/TransferItem.java new file mode 100644 index 0000000..6b6901f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/transfer/TransferItem.java @@ -0,0 +1,177 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.transfer; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; + +import org.cristalise.kernel.collection.Collection; +import org.cristalise.kernel.collection.CollectionArrayList; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.TraceableEntity; +import org.cristalise.kernel.lifecycle.instance.Workflow; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.Path; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Logger; + + +public class TransferItem { + private ArrayList domainPaths; + protected ItemPath itemPath; + static AgentPath importAgentId; + + public TransferItem() throws Exception { + try { + importAgentId = Gateway.getLookup().getAgentPath("system"); + } catch (ObjectNotFoundException e) { + Logger.error("TransferItem - System user not found!"); + throw e; + } + } + + public TransferItem(ItemPath itemPath) throws Exception { + this.itemPath = itemPath; + domainPaths = new ArrayList(); + Iterator paths = Gateway.getLookup().searchAliases(itemPath); + while (paths.hasNext()) { + DomainPath thisPath = (DomainPath)paths.next(); + domainPaths.add(thisPath.toString()); + } + } + + public ArrayList getDomainPaths() { + return domainPaths; + } + + public void setDomainPaths(ArrayList domainPaths) { + this.domainPaths = domainPaths; + } + + public void setUUID( String uuid ) throws InvalidItemPathException + { + itemPath = new ItemPath(uuid); + } + + public String getUUID() { + return itemPath.getUUID().toString(); + } + + public void exportItem(File dir, String path) throws Exception { + Logger.msg("Path " + path + " in " + itemPath); + String[] contents = Gateway.getStorage().getClusterContents(itemPath, path); + if (contents.length > 0) { + FileStringUtility.createNewDir(dir.getCanonicalPath()); + for (String content : contents) { + exportItem(new File(dir, content), path + "/" + content); + } + } else { //no children, try to dump object + try { + C2KLocalObject obj = Gateway.getStorage().get(itemPath, path, null); + Logger.msg("Dumping object " + path + " in " + itemPath); + File dumpPath = new File(dir.getCanonicalPath() + ".xml"); + FileStringUtility.string2File(dumpPath, Gateway.getMarshaller().marshall(obj)); + return; + } catch (ObjectNotFoundException ex) { + } // not an object + } + } + + public void importItem(File dir) throws Exception { + // check if already exists + try { + Property name = (Property)Gateway.getStorage().get(itemPath, ClusterStorage.PROPERTY + "/Name", null); + throw new Exception("Entity " + itemPath + " already in use as " + name.getValue()); + } catch (Exception ex) { + } + + // retrieve objects + ArrayList objectFiles = FileStringUtility.listDir(dir.getCanonicalPath(), false, true); + ArrayList objects = new ArrayList(); + for (String element : objectFiles) { + String xmlFile = FileStringUtility.file2String(element); + C2KLocalObject newObj; + String choppedPath = element.substring(dir.getCanonicalPath().length()+1, element.length()-4); + Logger.msg(choppedPath); + if (choppedPath.startsWith(ClusterStorage.OUTCOME)) + newObj = new Outcome(choppedPath, xmlFile); + else + newObj = (C2KLocalObject)Gateway.getMarshaller().unmarshall(xmlFile); + + objects.add(newObj); + } + + // create item + TraceableEntity newItem = Gateway.getCorbaServer().createItem(itemPath); + Gateway.getLookupManager().add(itemPath); + + PropertyArrayList props = new PropertyArrayList(); + CollectionArrayList colls = new CollectionArrayList(); + Workflow wf = null; + // put objects + for (C2KLocalObject obj : objects) { + if (obj instanceof Property) + props.list.add((Property)obj); + else if (obj instanceof Collection) + colls.list.add((Collection)obj); + else if (obj instanceof Workflow) + wf = (Workflow)obj; + } + + if (wf == null) + throw new Exception("No workflow found in import for "+itemPath); + + // init item + newItem.initialise(importAgentId.getSystemKey(), + Gateway.getMarshaller().marshall(props), + Gateway.getMarshaller().marshall(wf.search("workflow/domain")), + Gateway.getMarshaller().marshall(colls)); + + // store objects + importByType(ClusterStorage.HISTORY, objects); + importByType(ClusterStorage.OUTCOME, objects); + importByType(ClusterStorage.VIEWPOINT, objects); + Gateway.getStorage().commit(this); + // add domPaths + for (String element : domainPaths) { + DomainPath newPath = new DomainPath(element, itemPath); + Gateway.getLookupManager().add(newPath); + } + } + + private void importByType(String type, ArrayList objects) throws Exception { + for (C2KLocalObject element : objects) { + if (element.getClusterType().equals(type)) + Gateway.getStorage().put(itemPath, element, this); + } + + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/transfer/TransferSet.java b/src/main/java/org/cristalise/kernel/entity/transfer/TransferSet.java new file mode 100644 index 0000000..c4a578a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/transfer/TransferSet.java @@ -0,0 +1,94 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.entity.transfer; + +import java.io.File; +import java.util.ArrayList; + +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * $Revision: 1.5 $ + * $Date: 2005/04/26 06:48:13 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public class TransferSet { + + public ArrayList items; + + public TransferSet() { + } + + public TransferSet(ItemPath[] itemPaths) { + items = new ArrayList(); + for (ItemPath item : itemPaths) { + try { + items.add(new TransferItem(item)); + } catch (Exception ex) { + Logger.error("Could not add item "+item); + Logger.error(ex); + } + } + } + + public void exportPackage(File dir) throws Exception { + if (items==null || items.size() == 0) + throw new Exception("Nothing to dump"); + FileStringUtility.createNewDir(dir.getAbsolutePath()); + for (TransferItem element : items) { + try { + element.exportItem(new File(dir, element.itemPath.getUUID().toString()), "/"); + } catch (Exception ex) { + Logger.error("Error dumping item "+element.itemPath); + Logger.error(ex); + } + } + + try { + String self = Gateway.getMarshaller().marshall(this); + FileStringUtility.string2File(new File(dir, "transferSet.xml"), self); + } catch (Exception ex) { + Logger.error("Error writing header file"); + Logger.error(ex); + } + } + + public void importPackage(File rootDir) { + for (TransferItem element : items) { + Logger.msg(5, "Importing "+element.itemPath); + try { + element.importItem(new File(rootDir, element.itemPath.getUUID().toString())); + } catch (Exception ex) { + Logger.error("Import of item "+element.itemPath+" failed. Rolling back"); + Logger.error(ex); + Gateway.getStorage().abort(element); + } + } + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/transfer/package-info.java b/src/main/java/org/cristalise/kernel/entity/transfer/package-info.java new file mode 100644 index 0000000..bfd8317 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/transfer/package-info.java @@ -0,0 +1,36 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +/** + * Export and Import of Items. + * + *

    {@link TransferItem} provides a mechanism for marshalling all of the + * C2KLocalObjects in an Item to XML and exporting them to disk, and then + * importing that Item on another server. {@link TransferSet} can export many + * Items at a time and preserve their domain paths. + * + *

    This package is not currently used, as with the previous system key + * integer sequence it was not possible to import collections onto other servers + * but now Items are identified using UUIDs, this may now converge with the + * module mechanism. + * + */ + +package org.cristalise.kernel.entity.transfer; \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/events/Event.java b/src/main/java/org/cristalise/kernel/events/Event.java new file mode 100644 index 0000000..192685f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/events/Event.java @@ -0,0 +1,369 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.events; + +import java.util.Calendar; + +import org.cristalise.kernel.common.GTimeStamp; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; + + + +/** + * The data structure of events, which are passed over the event service. + * + * Events are incrementaly numbered objects maintained by the History. + * + * @version $Revision: 1.13 $ $Date: 2004/11/22 09:12:28 $ + * @author $Author: abranson $ + */ +public class Event implements C2KLocalObject +{ + ItemPath mItemPath; AgentPath mAgentPath; + int mOriginState, mTransition, mTargetState; + Integer mID, mSchemaVersion, mStateMachineVersion; + String mName, mStepName, mStepPath, mStepType, mSchemaName, mStateMachineName, mViewName, mAgentRole; + GTimeStamp mTimeStamp; + + public int getOriginState() { + return mOriginState; + } + + public void setOriginState(int originState) { + this.mOriginState = originState; + } + + public int getTargetState() { + return mTargetState; + } + + public void setTargetState(int targetState) { + this.mTargetState = targetState; + } + + public Integer getStateMachineVersion() { + return mStateMachineVersion; + } + + public void setStateMachineVersion(Integer stateMachineVersion) { + this.mStateMachineVersion = stateMachineVersion; + } + + public String getStateMachineName() { + return mStateMachineName; + } + + public void setStateMachineName(String stateMachineName) { + this.mStateMachineName = stateMachineName; + } + + public void setID( Integer id ) { + mID = id; + mName = String.valueOf(id); + } + + /** + */ + public void setItemPath( ItemPath itemPath ) + { + mItemPath = itemPath; + } + + public void setItemUUID( String uuid ) throws InvalidItemPathException + { + setItemPath(new ItemPath(uuid)); + } + + public String getItemUUID() { + return getItemPath().getUUID().toString(); + } + + public void setAgentUUID( String uuid ) throws InvalidItemPathException + { + if (uuid == null || uuid.length() == 0) + mAgentPath = null; + else + setAgentPath(AgentPath.fromUUIDString(uuid)); + } + + public String getAgentUUID() { + if (mAgentPath != null) + return getAgentPath().getUUID().toString(); + else + return null; + } + + /** + * Set the Event Name, in parameter is a String + */ + @Override + public void setName(String name) + { + mName = name; + try { + mID = Integer.parseInt(name); + } catch (NumberFormatException ex) { + mID = -1; + } + } + + /** + * Set the StepPath of the Event, in parameter is a String + */ + public void setStepName(String name) + { + mStepName = name; + } + + /** + * Set the StepPath of the Event, in parameter is a String + */ + public void setStepPath(String path) + { + mStepPath = path; + } + + /** + * Set the StepType of the Event, in parameter is a String + */ + public void setStepType(String type) + { + mStepType = type; + } + + /** + * @param viewName the viewName to set + */ + public void setViewName(String viewName) { + this.mViewName = viewName; + } + + /** + * Set the AgentInfo in the Event, in parameter is an AgentInfo + */ + public void setAgentPath(AgentPath agentPath) + { + mAgentPath = agentPath; + } + + public void setAgentRole(String agentRole) + { + mAgentRole = agentRole; + } + + /** + * Set the TimeStamp in the Event, in parameter is an GTimeStamp + */ + public void setTimeStamp(GTimeStamp inTimeStamp) + { + mTimeStamp = inTimeStamp; + } + + + /** + * Return the Event's ID + */ + public Integer getID() + { + return mID; + } + + /** + */ + public ItemPath getItemPath() + { + return mItemPath; + } + + /** + * Return the Event Name + */ + @Override + public String getName() + { + return mName; + } + + /** + * Return the StepPath of the Event. + */ + public String getStepName() + { + return mStepName; + } + + /** + * Return the StepPath of the Event. + */ + public String getStepPath() + { + return mStepPath; + } + + /** + * Return the StepPath of the Event. + */ + public String getStepType() + { + return mStepType; + } + + /** + * @return the mViewName + */ + public String getViewName() { + return mViewName; + } + + /** + * Return the AgentInfo of the Event. + */ + public AgentPath getAgentPath() + { + return mAgentPath; + } + + public String getAgentRole() + { + return mAgentRole; + } + + /** + * Return the Event's TimeStamp. + */ + public GTimeStamp getTimeStamp() + { + return mTimeStamp; + } + + /** + * Return the TimeStamp in a form that will + * convert nicely to a String + * YYYY-MM-DD HH:MI:SS + */ + public String getTimeString() + { + return Event.timeToString(mTimeStamp); + } + + public static String timeToString(GTimeStamp timeStamp) { + StringBuffer time = new StringBuffer().append(timeStamp.mYear).append("-"); + + if (timeStamp.mMonth<10) time.append("0"); + time.append(timeStamp.mMonth).append("-"); + + if (timeStamp.mDay<10) time.append("0"); + time.append(timeStamp.mDay).append(" "); + + if (timeStamp.mHour<10) time.append("0"); + time.append(timeStamp.mHour).append(":"); + + if (timeStamp.mMinute<10) time.append("0"); + time.append(timeStamp.mMinute).append(":"); + + if (timeStamp.mSecond<10) time.append("0"); + time.append(timeStamp.mSecond); + + return time.toString(); + } + + public void setTimeString(String time) throws InvalidDataException + { + if (time.length() == 19) + mTimeStamp = new GTimeStamp( + Integer.parseInt(time.substring(0,4)), + Integer.parseInt(time.substring(5,7)), + Integer.parseInt(time.substring(8,10)), + Integer.parseInt(time.substring(11,13)), + Integer.parseInt(time.substring(14,16)), + Integer.parseInt(time.substring(17,19)), + Calendar.getInstance().get(Calendar.ZONE_OFFSET)); + else if (time.length() == 14) // support for some sql formats + mTimeStamp = new GTimeStamp( + Integer.parseInt(time.substring(0,4)), + Integer.parseInt(time.substring(4,6)), + Integer.parseInt(time.substring(6,8)), + Integer.parseInt(time.substring(8,10)), + Integer.parseInt(time.substring(10,12)), + Integer.parseInt(time.substring(12,14)), + Calendar.getInstance().get(Calendar.ZONE_OFFSET)); + else + throw new InvalidDataException("Unknown time format: "+time); + } + + + + static public GTimeStamp getGMT() + { + java.util.Calendar now = Calendar.getInstance(); + + return new GTimeStamp( now.get(Calendar.YEAR), + now.get(Calendar.MONTH)+1, + now.get(Calendar.DAY_OF_MONTH), + now.get(Calendar.HOUR_OF_DAY), + now.get(Calendar.MINUTE), + now.get(Calendar.SECOND), + now.get(Calendar.ZONE_OFFSET) ); + } + /** + * @see org.cristalise.kernel.entity.C2KLocalObject#getClusterType() + */ + @Override + public String getClusterType() { + return ClusterStorage.HISTORY; + } + + /** + * @return + */ + public int getTransition() { + return mTransition; + } + + /** + * @param i + */ + public void setTransition(int i) { + mTransition = i; + } + + public Integer getSchemaVersion() { + return mSchemaVersion; + } + + public void setSchemaVersion(Integer schemaVersion) { + this.mSchemaVersion = schemaVersion; + } + + public String getSchemaName() { + return mSchemaName; + } + + public void setSchemaName(String schemaName) { + this.mSchemaName = schemaName; + } + +} diff --git a/src/main/java/org/cristalise/kernel/events/History.java b/src/main/java/org/cristalise/kernel/events/History.java new file mode 100644 index 0000000..bca0fa8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/events/History.java @@ -0,0 +1,152 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.events; + + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.lifecycle.instance.stateMachine.Transition; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.RemoteMap; +import org.cristalise.kernel.utils.Logger; + + +/** + * @author Andrew Branson + * + * $Revision: 1.20 $ + * $Date: 2004/07/21 09:55:11 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + */ + +public class History extends RemoteMap { + + int lastID = -1; + + public History(ItemPath itemPath, Object locker) { + super(itemPath, ClusterStorage.HISTORY, locker); + } + public Event addEvent(AgentPath agentPath, String agentRole, + String stepName, + String stepPath, + String stepType, + String stateMachineName, + Integer stateMachineVersion, + Transition transition) { + return addEvent(agentPath, agentRole, stepName, stepPath, stepType, null, null, stateMachineName, stateMachineVersion, transition, null); + } + + public Event addEvent(AgentPath agentPath, String agentRole, + String stepName, + String stepPath, + String stepType, + String schemaName, + Integer schemaVersion, + String stateMachineName, + Integer stateMachineVersion, + Transition transition, + String viewName) { + Logger.msg(7, "History.addEvent() - creating new event for "+transition.getName()+" on "+stepName+" in "+mItemPath); + Event newEvent = new Event(); + newEvent.setItemPath(mItemPath); + newEvent.setAgentPath(agentPath); + newEvent.setAgentRole(agentRole); + newEvent.setStepName(stepName); + newEvent.setStepPath(stepPath); + newEvent.setStepType(stepType); + newEvent.setSchemaName(schemaName); + newEvent.setSchemaVersion(schemaVersion); + newEvent.setViewName(viewName); + newEvent.setOriginState(transition.getOriginStateId()); + newEvent.setTargetState(transition.getTargetStateId()); + newEvent.setTransition(transition.getId()); + newEvent.setStateMachineName(stateMachineName); + newEvent.setStateMachineVersion(stateMachineVersion); + newEvent.setTimeStamp(Event.getGMT()); + return storeNewEvent(newEvent); + } + + public Event addEvent(AgentPath agentPath, String agentRole, + String stepName, + String stepPath, + String stepType, + String stateMachineName, + Integer stateMachineVersion, + Transition transition, + String timeString) throws InvalidDataException { + return addEvent(agentPath, agentRole, stepName, stepPath, stepType, null, null, stateMachineName, stateMachineVersion, transition, null, timeString); + } + + public Event addEvent(AgentPath agentPath, String agentRole, + String stepName, + String stepPath, + String stepType, + String schemaName, + Integer schemaVersion, + String stateMachineName, + Integer stateMachineVersion, + Transition transition, + String viewName, + String timeString) throws InvalidDataException { + Logger.msg(7, "History.addEvent() - creating new event for "+transition.getName()+" on "+stepName+" in "+mItemPath); + Event newEvent = new Event(); + newEvent.setItemPath(mItemPath); + newEvent.setAgentPath(agentPath); + newEvent.setAgentRole(agentRole); + newEvent.setStepName(stepName); + newEvent.setStepPath(stepPath); + newEvent.setStepType(stepType); + newEvent.setSchemaName(schemaName); + newEvent.setSchemaVersion(schemaVersion); + newEvent.setViewName(viewName); + newEvent.setOriginState(transition.getOriginStateId()); + newEvent.setTargetState(transition.getTargetStateId()); + newEvent.setTransition(transition.getId()); + newEvent.setStateMachineName(stateMachineName); + newEvent.setStateMachineVersion(stateMachineVersion); + newEvent.setTimeString(timeString); + return storeNewEvent(newEvent); + } + + private Event storeNewEvent(Event newEvent) { + synchronized (this) { + int newEventID = getLastId()+1; + newEvent.setID(newEventID); + put(newEvent.getName(), newEvent); + lastID = newEventID; + return newEvent; + } + } + + public Event getEvent(int id) { + return get(String.valueOf(id)); + } + + @Override + public Event remove(Object key) { + // forbidden + return null; + } + +} diff --git a/src/main/java/org/cristalise/kernel/events/package-info.java b/src/main/java/org/cristalise/kernel/events/package-info.java new file mode 100644 index 0000000..3e3c37d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/events/package-info.java @@ -0,0 +1,29 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +/** + * Events are generated and stored whenever a step in an Item's lifecycle + * changes state, and provide a full record of what was done, when, and by whom. + * + *

    The History object is an instance of {@link RemoteMap} which provides a + * live view onto the Events of an Item. + */ + +package org.cristalise.kernel.events; \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/graph/event/ClearedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/ClearedEvent.java new file mode 100644 index 0000000..8589637 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/ClearedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class ClearedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/EdgeRemovedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/EdgeRemovedEvent.java new file mode 100644 index 0000000..bac5715 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/EdgeRemovedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class EdgeRemovedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/EdgesChangedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/EdgesChangedEvent.java new file mode 100644 index 0000000..c3cfe7a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/EdgesChangedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class EdgesChangedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/EntireModelChangedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/EntireModelChangedEvent.java new file mode 100644 index 0000000..1ea5fa4 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/EntireModelChangedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class EntireModelChangedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/ForcedNotifyEvent.java b/src/main/java/org/cristalise/kernel/graph/event/ForcedNotifyEvent.java new file mode 100644 index 0000000..e2801f2 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/ForcedNotifyEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class ForcedNotifyEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/GraphModelEvent.java b/src/main/java/org/cristalise/kernel/graph/event/GraphModelEvent.java new file mode 100644 index 0000000..cc066f8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/GraphModelEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public abstract class GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/GraphModelResizedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/GraphModelResizedEvent.java new file mode 100644 index 0000000..a4de89d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/GraphModelResizedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class GraphModelResizedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/NewEdgeEndPointChangedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/NewEdgeEndPointChangedEvent.java new file mode 100644 index 0000000..42a2507 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/NewEdgeEndPointChangedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class NewEdgeEndPointChangedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/StartVertexIdChangedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/StartVertexIdChangedEvent.java new file mode 100644 index 0000000..7d3d7e3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/StartVertexIdChangedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class StartVertexIdChangedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/VertexAddedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/VertexAddedEvent.java new file mode 100644 index 0000000..7f4fcbe --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/VertexAddedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class VertexAddedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/VertexCreatedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/VertexCreatedEvent.java new file mode 100644 index 0000000..e0f0eee --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/VertexCreatedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class VertexCreatedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/VertexMovedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/VertexMovedEvent.java new file mode 100644 index 0000000..9e5d8a8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/VertexMovedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class VertexMovedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/VertexRemovedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/VertexRemovedEvent.java new file mode 100644 index 0000000..29f4367 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/VertexRemovedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class VertexRemovedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/event/VerticesChangedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/VerticesChangedEvent.java new file mode 100644 index 0000000..68cc9f1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/VerticesChangedEvent.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.event; + + +public class VerticesChangedEvent extends GraphModelEvent +{ +} diff --git a/src/main/java/org/cristalise/kernel/graph/layout/DefaultGraphLayoutGenerator.java b/src/main/java/org/cristalise/kernel/graph/layout/DefaultGraphLayoutGenerator.java new file mode 100644 index 0000000..097c554 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/layout/DefaultGraphLayoutGenerator.java @@ -0,0 +1,139 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.layout; + +import java.util.Vector; + +import org.cristalise.kernel.graph.model.DirectedEdge; +import org.cristalise.kernel.graph.model.GraphModel; +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.utils.Logger; + + +public class DefaultGraphLayoutGenerator { + private static int mTopMargin = 100; + private static int mLeftMargin = 100; + private static int mHorzGap = 180; + private static int mVertGap = 100; + + private DefaultGraphLayoutGenerator() { + } + + public static void layoutGraph(GraphModel graphModel) { + Vertex start = graphModel.getStartVertex(); + Vector> rowVector = new Vector>(10, 10); + int[] midPoints = null; + int valueOfLargestMidPoint = 0; + if (start == null) { + Logger.msg(1,"Error graph must have a starting vertex to be layed out"); + return; + } + graphModel.clearTags(start); + visitVertex(graphModel, start, 0, rowVector, start); + midPoints = new int[rowVector.size()]; + valueOfLargestMidPoint = calculateRowMidPoints(rowVector, midPoints, valueOfLargestMidPoint); + fillInVertexLocations(graphModel, rowVector, valueOfLargestMidPoint, midPoints); + fillInEdgeLocations(graphModel); + graphModel.forceNotify(); + } + + private static void visitVertex(GraphModel graphModel, Vertex vertex, int rowIndex, Vector> rowVector, Object tag) { + int i = 0; + Vertex[] children = graphModel.getOutVertices(vertex); + vertex.setTag(tag); + addVertexToRow(vertex, rowIndex, rowVector); + for (i = 0; i < children.length; i++) { + if (!(children[i].hasTag(tag))) { + visitVertex(graphModel, children[i], rowIndex + 1, rowVector, tag); + } + } + } + + private static void addVertexToRow(Vertex vertex, int rowIndex, Vector> rowVector) { + Vector rowsVertices = null; + // If there is no vector of vertices already created for this row, + // then create one + if (rowVector.size() == rowIndex) { + rowVector.add(new Vector(10, 10)); + } + // Add the vertex to the row's vector of vertices + rowsVertices = rowVector.elementAt(rowIndex); + rowsVertices.add(vertex); + } + + private static int calculateRowMidPoints(Vector> rowVector, int[] midPoints, int valueOfLargestMidPoint) { + Vector rowsVertices = null; + int newValueOfLargestMidPoint = valueOfLargestMidPoint; + int rowsWidth = 0; + int i = 0; + for (i = 0; i < midPoints.length; i++) { + rowsVertices = rowVector.elementAt(i); + rowsWidth = mHorzGap * (rowsVertices.size() - 1); + midPoints[i] = rowsWidth / 2; + if (midPoints[i] > newValueOfLargestMidPoint) { + newValueOfLargestMidPoint = midPoints[i]; + } + } + return newValueOfLargestMidPoint; + } + + private static void fillInVertexLocations(GraphModel graphModel, Vector> rowVector, + int valueOfLargestMidPoint, int[] midPoints) { + Vector rowsVertices = null; + Vertex vertex = null; + int rowIndex = 0; + int column = 0; + int rowsLeftMargin = 0; + GraphPoint point = new GraphPoint(0, 0); + for (rowIndex = 0; rowIndex < rowVector.size(); rowIndex++) { + rowsVertices = rowVector.elementAt(rowIndex); + rowsLeftMargin = mLeftMargin + valueOfLargestMidPoint - midPoints[rowIndex]; + for (column = 0; column < rowsVertices.size(); column++) { + vertex = rowsVertices.elementAt(column); + point.x = rowsLeftMargin + column * mHorzGap; + point.y = mTopMargin + rowIndex * mVertGap; + vertex.moveAbsolute(point); + graphModel.checkSize(vertex); + } + } + } + + private static void fillInEdgeLocations(GraphModel graphModel) { + Vertex[] vertices = graphModel.getVertices(); + GraphPoint centrePoint = null; + DirectedEdge[] inEdges = null; + DirectedEdge[] outEdges = null; + int i = 0; + int j = 0; + for (i = 0; i < vertices.length; i++) { + centrePoint = vertices[i].getCentrePoint(); + inEdges = graphModel.getInEdges(vertices[i]); + outEdges = graphModel.getOutEdges(vertices[i]); + for (j = 0; j < inEdges.length; j++) { + inEdges[j].setTerminusPoint(centrePoint); + } + for (j = 0; j < outEdges.length; j++) { + outEdges[j].setOriginPoint(centrePoint); + } + } + } +} diff --git a/src/main/java/org/cristalise/kernel/graph/model/DirectedEdge.java b/src/main/java/org/cristalise/kernel/graph/model/DirectedEdge.java new file mode 100644 index 0000000..e384131 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/DirectedEdge.java @@ -0,0 +1,118 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.model; + + + + +public abstract class DirectedEdge +{ + // Persistent data + private int mId = -1; + private GraphPoint mOriginPoint = new GraphPoint(0, 0); + private GraphPoint mTerminusPoint = new GraphPoint(0, 0); + private int mOriginVertexId = -1; + private int mTerminusVertexId = -1; + + + public void setID(int id) + { + mId = id; + } + + + public int getID() + { + return mId; + } + + + public void setOriginPoint(GraphPoint p) + { + mOriginPoint = p; + } + + + public GraphPoint getOriginPoint() + { + return mOriginPoint; + } + + + public void setTerminusPoint(GraphPoint p) + { + mTerminusPoint = p; + } + + + public GraphPoint getTerminusPoint() + { + return mTerminusPoint; + } + + + public boolean containsPoint(GraphPoint p) + { + int midX = mOriginPoint.x + (mTerminusPoint.x - mOriginPoint.x)/2; + int midY = mOriginPoint.y + (mTerminusPoint.y - mOriginPoint.y)/2; + int minX = midX - 10; + int minY = midY - 10; + int maxX = midX + 10; + int maxY = midY + 10; + + return (p.x >= minX) && (p.x <= maxX) && (p.y >= minY) && (p.y <= maxY); + } + + + public void setOriginVertexId(int id) + { + mOriginVertexId = id; + } + + + public int getOriginVertexId() + { + return mOriginVertexId; + } + + + public void setTerminusVertexId(int id) + { + mTerminusVertexId = id; + } + + + public int getTerminusVertexId() + { + return mTerminusVertexId; + } + + + public void setName(String name) + { + } + + + public String getName() + { + return null; + } +} diff --git a/src/main/java/org/cristalise/kernel/graph/model/EdgeFactory.java b/src/main/java/org/cristalise/kernel/graph/model/EdgeFactory.java new file mode 100644 index 0000000..f4c119a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/EdgeFactory.java @@ -0,0 +1,34 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.model; + + + +public interface EdgeFactory +{ + public void create + ( + GraphModelManager graphModelManager, + Vertex origin, + Vertex terminus, + TypeNameAndConstructionInfo typeNameAndConstructionInfo + ); +} diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphModel.java b/src/main/java/org/cristalise/kernel/graph/model/GraphModel.java new file mode 100644 index 0000000..4ccbece --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphModel.java @@ -0,0 +1,544 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.model; + +import java.util.Hashtable; + +import org.cristalise.kernel.graph.event.ClearedEvent; +import org.cristalise.kernel.graph.event.EdgeRemovedEvent; +import org.cristalise.kernel.graph.event.EdgesChangedEvent; +import org.cristalise.kernel.graph.event.ForcedNotifyEvent; +import org.cristalise.kernel.graph.event.GraphModelEvent; +import org.cristalise.kernel.graph.event.GraphModelResizedEvent; +import org.cristalise.kernel.graph.event.NewEdgeEndPointChangedEvent; +import org.cristalise.kernel.graph.event.StartVertexIdChangedEvent; +import org.cristalise.kernel.graph.event.VertexAddedEvent; +import org.cristalise.kernel.graph.event.VertexCreatedEvent; +import org.cristalise.kernel.graph.event.VertexMovedEvent; +import org.cristalise.kernel.graph.event.VertexRemovedEvent; +import org.cristalise.kernel.graph.event.VerticesChangedEvent; +import org.cristalise.kernel.utils.Logger; + + +public class GraphModel { + /* Persistent data */ + + private int mWidth = 0; + private int mHeight = 0; + private int mNextId = 0; + protected int mStartVertexId = -1; + protected Hashtable mVertexHashtable = new Hashtable(); + protected Hashtable mEdgeHashtable = new Hashtable(); + private GraphableVertex mContainingVertex; + + /* Transient data */ + + protected transient Vertex mNewEdgeOriginVertex = null; + protected transient GraphPoint mNewEdgeEndPoint = null; + + private transient GraphModelManager mManager = null; + + /* External factories */ + + private VertexFactory mExternalVertexFactory = null; + private EdgeFactory mExternalEdgeFactory = null; + + /* Vertex outline creator */ + + private VertexOutlineCreator mVertexOutlineCreator = null; + + /* Notification Events */ + + private final ClearedEvent mClearedEvent = new ClearedEvent(); + private final EdgeRemovedEvent mEdgeRemovedEvent = new EdgeRemovedEvent(); + private final EdgesChangedEvent mEdgesChangedEvent = new EdgesChangedEvent(); + private final ForcedNotifyEvent mForcedNotifyEvent = new ForcedNotifyEvent(); + private final NewEdgeEndPointChangedEvent mNewEdgeEndPointChangedEvent = new NewEdgeEndPointChangedEvent(); + private final StartVertexIdChangedEvent mStartVertexIdChangedEvent = new StartVertexIdChangedEvent(); + private final VertexAddedEvent mVertexAddedEvent = new VertexAddedEvent(); + private final VertexCreatedEvent mVertexCreatedEvent = new VertexCreatedEvent(); + private final VertexMovedEvent mVertexMovedEvent = new VertexMovedEvent(); + private final VertexRemovedEvent mVertexRemovedEvent = new VertexRemovedEvent(); + private final VerticesChangedEvent mVerticesChangedEvent = new VerticesChangedEvent(); + private final GraphModelResizedEvent mGraphModelResizedEvent = new GraphModelResizedEvent(); + + // Calling this constructor does not create a vertex outline creator + // which is required by the method addVertexAndCreateId() + + private static int count=0; + + // count instances for debugging + private int number; + + public GraphModel() { + number=++count; + + } + + public int getNumber() { + return number; + } + + public void setNextId(int id) { + mNextId = id; + } + + public int getNextId() { + return mNextId; + } + + public void setManager(GraphModelManager mgr) { + mManager = mgr; + } + + public GraphModelManager getManager() { + return mManager; + } + + public GraphModel(VertexOutlineCreator vertexOutlineCreator) { + mVertexOutlineCreator = vertexOutlineCreator; + } + + public void setWidth(int width) { + + mWidth = width; + } + + public int getWidth() { + return mWidth; + } + + public void setHeight(int height) { + + mHeight = height; + } + + public int getHeight() { + return mHeight; + } + + public void checkSize(Vertex v) { + boolean resized = false; + GraphPoint centre = v.getCentrePoint(); + if (getWidth() < centre.x + v.getWidth()/2 +10 ) { + setWidth( centre.x + v.getWidth()/2 +10 ); + resized = true; + } + + if (getHeight() < centre.y + v.getHeight()/2 +10 ) { + setHeight(centre.y + v.getHeight()/2 +10 ); + resized = true; + } + + if (resized) { + publishEvent(mGraphModelResizedEvent); + } + + } + + public void setStartVertexId(int id) { + mStartVertexId = id; + publishEvent(mStartVertexIdChangedEvent); + } + + public int getStartVertexId() { + return mStartVertexId; + } + + public Vertex getStartVertex() { + return resolveVertex(getStartVertexId()); + } + + /** + * @return Returns the mParentVertex. + */ + public GraphableVertex getContainingVertex() { + return mContainingVertex; + } + /** + * @param parentVertex The mParentVertex to set. + */ + public void setContainingVertex(GraphableVertex vertex) { + mContainingVertex = vertex; + } + + public void setVertices(Vertex[] vertices) { + mVertexHashtable = new Hashtable(); + for (Vertex vertice : vertices) { + mVertexHashtable.put(String.valueOf(vertice.getID()), vertice); + checkSize(vertice); + + } + publishEvent(mVerticesChangedEvent); + } + + public Vertex[] getVertices() { + Object[] vertexObjs = mVertexHashtable.values().toArray(); + Vertex[] vertices = new Vertex[vertexObjs.length]; + int i = 0; + for (i = 0; i < vertices.length; i++) { + vertices[i] = (Vertex)vertexObjs[i]; + } + return vertices; + } + + public void setEdges(DirectedEdge[] edges) { + mEdgeHashtable = new Hashtable(); + for (DirectedEdge edge : edges) { + mEdgeHashtable.put(String.valueOf(edge.getID()), edge); + } + publishEvent(mEdgesChangedEvent); + } + + public DirectedEdge[] getEdges() { + Object[] edgeObjs = mEdgeHashtable.values().toArray(); + DirectedEdge[] edges = new DirectedEdge[edgeObjs.length]; + int i = 0; + for (i = 0; i < edges.length; i++) { + edges[i] = (DirectedEdge)edgeObjs[i]; + } + return edges; + } + + public Vertex getVertexById(int id) { + return mVertexHashtable.get(String.valueOf(id)); + } + + + public int addEdgeAndCreateId(DirectedEdge e, int originId, int terminusId) { + return addEdgeAndCreateId(e, resolveVertex(originId), resolveVertex(terminusId)); + } + + public int addEdgeAndCreateId(DirectedEdge e, Vertex origin, Vertex terminus) { + e.setID(mNextId); + e.setOriginVertexId(origin.getID()); + e.setOriginPoint(origin.getCentrePoint()); + e.setTerminusVertexId(terminus.getID()); + e.setTerminusPoint(terminus.getCentrePoint()); + origin.addOutEdgeId(mNextId); + terminus.addInEdgeId(mNextId); + mEdgeHashtable.put(String.valueOf(mNextId), e); + mNextId++; + return mNextId - 1; + } + + // Removes an edge, but does not modify the selection + public void removeEdge(DirectedEdge e) { + Vertex origin = getOrigin(e); + Vertex terminus = getTerminus(e); + int edgeId = e.getID(); + // Remove the id of the edge from the origin and terminus vertices + origin.removeOutEdgeId(edgeId); + terminus.removeInEdgeId(edgeId); + // Remove the edge + mEdgeHashtable.remove(String.valueOf(e.getID())); + publishEvent(mEdgeRemovedEvent); + } + + public int addVertexAndCreateId(Vertex v, GraphPoint location) { + if (location!= null) + { + if (mVertexOutlineCreator == null) { + Logger.msg(1,"You cannot add a vertex with no outline creator"); + return -1; + + } + mVertexHashtable.put(String.valueOf(mNextId), v); + placeVertex(v, location); + } + v.setID(mNextId); + return mNextId++; + } + + public void placeVertex(Vertex v, GraphPoint location) { + v.setCentrePoint(location); + if (mVertexOutlineCreator != null) { + mVertexOutlineCreator.setOutline(v); + } + publishEvent(mVertexAddedEvent); + checkSize(v); + } + + // Removes a vertex, but does not modify the selection + public void removeVertex(Vertex v) { + DirectedEdge[] inEdges = getInEdges(v); + DirectedEdge[] outEdges = getOutEdges(v); + Vertex origin = null; + Vertex terminus = null; + int edgeId = -1; + int i = 0; + // For each in edge + for (i = 0; i < inEdges.length; i++) { + edgeId = inEdges[i].getID(); + origin = getOrigin(inEdges[i]); + // Remove the id of the edge from the origin vertex + origin.removeOutEdgeId(edgeId); + // Remove the edge + mEdgeHashtable.remove(String.valueOf(edgeId)); + } + // Remove all the out edges + for (i = 0; i < outEdges.length; i++) { + edgeId = outEdges[i].getID(); + terminus = getTerminus(outEdges[i]); + // Remove the id of the edge from the terminus vertex + terminus.removeInEdgeId(edgeId); + // Remove the edge + mEdgeHashtable.remove(String.valueOf(edgeId)); + } + // Remove the vertex + mVertexHashtable.remove(String.valueOf(v.getID())); + publishEvent(mVertexRemovedEvent); + } + + public void moveAbsoluteVertex(Vertex v, GraphPoint p) { + // Make sure the new position stays within the graph + if (p.x < 0) p.x = 0; + if (p.y < 0) p.y = 0; + if (p.x > mWidth) p.x = mWidth; + if (p.y > mHeight) p.y = mHeight; + moveAbsoluteVertexAndConnectingEdges(v, p); + publishEvent(mVertexMovedEvent); + } + + private void moveAbsoluteVertexAndConnectingEdges(Vertex v, GraphPoint p) { + DirectedEdge[] inEdges = getInEdges(v); + DirectedEdge[] outEdges = getOutEdges(v); + int i = 0; + // Move the vertex to the new position + v.moveAbsolute(p); + // Move the ends of the incoming edges to the new position + for (i = 0; i < inEdges.length; i++) { + inEdges[i].setTerminusPoint(p); + } + // Move the ends of the outgoing edges to the new position + for (i = 0; i < outEdges.length; i++) { + outEdges[i].setOriginPoint(p); + } + checkSize(v); + } + + + + public Vertex resolveVertex(int id) { + return mVertexHashtable.get(String.valueOf(id)); + } + + public DirectedEdge resolveEdge(int id) { + return mEdgeHashtable.get(String.valueOf(id)); + } + + public DirectedEdge[] getInEdges(Vertex v) { + int[] ids = v.getInEdgeIds(); + return resolveEdges(ids); + } + + public DirectedEdge[] getOutEdges(Vertex v) { + int[] ids = v.getOutEdgeIds(); + return resolveEdges(ids); + } + + private DirectedEdge[] resolveEdges(int[] ids) { + DirectedEdge[] edges = new DirectedEdge[ids.length]; + int i = 0; + for (i = 0; i < ids.length; i++) { + edges[i] = resolveEdge(ids[i]); + } + return edges; + } + + public Vertex getOrigin(DirectedEdge e) { + return resolveVertex(e.getOriginVertexId()); + } + + public Vertex getTerminus(DirectedEdge e) { + return resolveVertex(e.getTerminusVertexId()); + } + + public Vertex[] getInVertices(Vertex v) { + DirectedEdge[] inEdges = getInEdges(v); + Vertex[] inVertices = new Vertex[inEdges.length]; + int i = 0; + for (i = 0; i < inEdges.length; i++) { + inVertices[i] = getOrigin(inEdges[i]); + } + return inVertices; + } + + public Vertex[] getOutVertices(Vertex v) { + DirectedEdge[] outEdges = getOutEdges(v); + Vertex[] outVertices = new Vertex[outEdges.length]; + int i = 0; + for (i = 0; i < outEdges.length; i++) { + outVertices[i] = getTerminus(outEdges[i]); + } + return outVertices; + } + + public DirectedEdge[] getConnectingEdges(int originVertexId, int terminusVertexId) { + Vertex origin = resolveVertex(originVertexId); + DirectedEdge[] outEdges = null; + int numEdgesFound = 0; + DirectedEdge[] edgesFound = null; + int i = 0; + int j = 0; + if (origin == null) return null; + outEdges = getOutEdges(origin); + for (i = 0; i < outEdges.length; i++) { + if (outEdges[i].getTerminusVertexId() == terminusVertexId) { + numEdgesFound++; + } + } + edgesFound = new DirectedEdge[numEdgesFound]; + for (i = 0; i < outEdges.length; i++) { + if (outEdges[i].getTerminusVertexId() == terminusVertexId) { + edgesFound[j] = outEdges[i]; + j++; + } + } + return edgesFound; + } + + public void clearTags(Object tag) { + Vertex vertex = null; + Object[] vertexObjs = mVertexHashtable.values().toArray(); + int i = 0; + for (i = 0; i < vertexObjs.length; i++) { + vertex = (Vertex)vertexObjs[i]; + vertex.clearTag(tag); + } + } + + public void forceNotify() { + publishEvent(mForcedNotifyEvent); + } + + public void clear() { + mVertexHashtable = new Hashtable(); + mEdgeHashtable = new Hashtable(); + mStartVertexId = -1; + publishEvent(mClearedEvent); + } + + + + public void setNewEdgeOriginVertex(Vertex v) { + mNewEdgeOriginVertex = v; + } + + public Vertex getNewEdgeOriginVertex() { + return mNewEdgeOriginVertex; + } + + public void setNewEdgeEndPoint(GraphPoint p) { + mNewEdgeEndPoint = p; + publishEvent(mNewEdgeEndPointChangedEvent); + } + + public GraphPoint getNewEdgeEndPoint() { + return mNewEdgeEndPoint; + } + + public void setExternalVertexFactory(VertexFactory factory) { + mExternalVertexFactory = factory; + } + + public void createVertex(GraphPoint location, TypeNameAndConstructionInfo typeNameAndConstructionInfo) throws Exception { + if (mExternalVertexFactory != null) { + mExternalVertexFactory.create(mManager, location, typeNameAndConstructionInfo); + publishEvent(mVertexCreatedEvent); + } + } + + private void publishEvent(GraphModelEvent event) { + if (mManager!=null) + mManager.notifyObservers(event); + + } + + public void setExternalEdgeFactory(EdgeFactory factory) { + mExternalEdgeFactory = factory; + } + + public void setVertexOutlineCreator(VertexOutlineCreator outlineCreator) { + mVertexOutlineCreator = outlineCreator; + } + + public void createDirectedEdge(Vertex origin, Vertex terminus, TypeNameAndConstructionInfo typeNameAndConstructionInfo) { + if (mExternalEdgeFactory != null) { + mExternalEdgeFactory.create(mManager, origin, terminus, typeNameAndConstructionInfo); + } + } + + + + public void resetVertexOutlines() { + Vertex[] vertices = getVertices(); + int i = 0; + for (i = 0; i < vertices.length; i++) { + mVertexOutlineCreator.setOutline(vertices[i]); + } + } + + public void setGraphModelCastorData(GraphModelCastorData data) { + int i = 0; + + // Create and populate the vertex hashtable + mVertexHashtable = new Hashtable(); + for (i = 0; i < data.mVertexImpls.length; i++) { + mVertexHashtable.put(String.valueOf(data.mVertexImpls[i].getID()), data.mVertexImpls[i]); + checkSize(data.mVertexImpls[i]); + } + // Create and populate the edge hastable + mEdgeHashtable = new Hashtable(); + for (i = 0; i < data.mEdgeImpls.length; i++) { + mEdgeHashtable.put(String.valueOf(data.mEdgeImpls[i].getID()), data.mEdgeImpls[i]); + } + // Set the start vertex id and the id generation counter + mStartVertexId = data.mStartVertexId; + mNextId = data.mNextId; + } + + public GraphModelCastorData getGraphModelCastorData() { + Object[] vertexObjs = mVertexHashtable.values().toArray(); + Vertex[] vertexImpls = new Vertex[vertexObjs.length]; + Object[] edgeObjs = mEdgeHashtable.values().toArray(); + DirectedEdge[] directedEdgeImpls = new DirectedEdge[edgeObjs.length]; + String className = null; + int i = 0; + // Put in the vertices + for (i = 0; i < vertexImpls.length; i++) { + vertexImpls[i] = (Vertex)vertexObjs[i]; + } + // Put in the edges + for (i = 0; i < directedEdgeImpls.length; i++) { + directedEdgeImpls[i] = (DirectedEdge)edgeObjs[i]; + } + // Disable persistency of the vertex outline creator: determined by container + // Determine the class name of the vertex outline creator +// if (mVertexOutlineCreator == null) { +// className = ""; +// } +// else { +// className = mVertexOutlineCreator.getClass().getName(); +// } + return new GraphModelCastorData(className, vertexImpls, directedEdgeImpls, mStartVertexId, mNextId); + } +} diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphModelCastorData.java b/src/main/java/org/cristalise/kernel/graph/model/GraphModelCastorData.java new file mode 100644 index 0000000..1f467a7 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphModelCastorData.java @@ -0,0 +1,50 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.model; + + +public class GraphModelCastorData +{ + // Deprecated: Vertex outline creator is now set by the container + public String mClassNameOfVertexOutlineCreator = ""; + public Vertex[] mVertexImpls = {}; + public DirectedEdge[] mEdgeImpls = {}; + public int mStartVertexId = 0; + public int mNextId = 0; + + + public GraphModelCastorData() + { + } + + public GraphModelCastorData(String classNameOfVertexOutlineCreator, + Vertex[] vertexImpls, + DirectedEdge[] edgeImpls, + int startVertexId, + int nextId) + { + mClassNameOfVertexOutlineCreator = classNameOfVertexOutlineCreator; + mVertexImpls = vertexImpls; + mEdgeImpls = edgeImpls; + mStartVertexId = startVertexId; + mNextId = nextId; + } +} diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphModelManager.java b/src/main/java/org/cristalise/kernel/graph/model/GraphModelManager.java new file mode 100644 index 0000000..1f89b50 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphModelManager.java @@ -0,0 +1,157 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.model; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Observable; +import java.util.Stack; + +import org.cristalise.kernel.graph.event.EntireModelChangedEvent; +import org.cristalise.kernel.graph.event.ForcedNotifyEvent; +import org.cristalise.kernel.graph.event.GraphModelEvent; +import org.cristalise.kernel.utils.Logger; + + + +public class GraphModelManager extends Observable +{ + + private GraphModel mGraphModel; + private EdgeFactory mEdgeFactory; + private VertexFactory mVertexFactory; + private VertexOutlineCreator mVertexOutlineCreator; + private final EntireModelChangedEvent mEntireModelChangedEvent = new EntireModelChangedEvent(); + private final ForcedNotifyEvent mForcedNotifyEvent = new ForcedNotifyEvent(); + private final Stack mParentModels = new Stack(); + private final ArrayList mParentIds = new ArrayList(); + private boolean mEditable = true; + + // Calling this constructor does not create a vertex outline creator + // which is required by the method addVertexAndCreateId() + public GraphModelManager() + { + mGraphModel = new GraphModel(); + mGraphModel.setManager(this); + } + + public GraphModelManager(GraphModel newModel) { + newModel.setManager(this); + mGraphModel = newModel; + } + + public void replace(GraphModel newModel) { + mParentModels.clear(); + + //zoom back to where we were + for (Iterator iter = mParentIds.iterator(); iter.hasNext();) { + Integer parentId = iter.next(); + GraphableVertex childModelVertex = (GraphableVertex)newModel.getVertexById(parentId.intValue()); + if (childModelVertex == null) { // we've been deleted, stay here + Logger.msg(7, "Didn't find "+parentId+" in new model tree. Stopping here."); + do { iter.remove(); } while (iter.hasNext()); + break; + } + else { + mParentModels.push(newModel); + Logger.msg(7, "Pushing model and switching to "+parentId); + newModel = childModelVertex.getChildGraphModel(); + } + } + setModel(newModel); + } + + public void setModel(GraphModel newModel) { + // reset transient data + newModel.mNewEdgeOriginVertex = null; + newModel.mNewEdgeEndPoint = null; + + // copy factories over + newModel.setExternalEdgeFactory(mEdgeFactory); + newModel.setExternalVertexFactory(mVertexFactory); + newModel.setVertexOutlineCreator(mVertexOutlineCreator); + mVertexFactory.setCreationContext(newModel.getContainingVertex()); + newModel.setManager(this); + mGraphModel.setManager(null); + mGraphModel = newModel; + + // notify + notifyObservers(mEntireModelChangedEvent); + } + + public void zoomIn(Vertex child) { + GraphModel childModel = child.getChildGraphModel(); + if (childModel != null) { + mParentModels.push(mGraphModel); + mParentIds.add(Integer.valueOf(child.getID())); + setModel(childModel); + Logger.msg(7, "ZoomIn - Stack size: "+mParentModels.size()+" ids:"+mParentIds.size()); + } + } + + public void zoomOut() { + if (!mParentModels.empty()) { + setModel(mParentModels.pop()); + mParentIds.remove(mParentIds.size()-1); + } + Logger.msg(7, "ZoomOut - Stack size: "+mParentModels.size()+" ids:"+mParentIds.size()); + + } + + public void forceNotify() + { + notifyObservers(mForcedNotifyEvent); + } + + public GraphModel getModel() { + return mGraphModel; + } + + public void setExternalEdgeFactory(EdgeFactory newEdgeFactory) { + mEdgeFactory = newEdgeFactory; + mGraphModel.setExternalEdgeFactory(newEdgeFactory); + } + + public void setExternalVertexFactory(VertexFactory newVertexFactory) { + mVertexFactory = newVertexFactory; + mGraphModel.setExternalVertexFactory(newVertexFactory); + } + + public void setVertexOutlineCreator(VertexOutlineCreator newVertexOutlineCreator) { + mVertexOutlineCreator = newVertexOutlineCreator; + mGraphModel.setVertexOutlineCreator(newVertexOutlineCreator); + } + + public void notifyObservers(GraphModelEvent ev) { + setChanged(); + super.notifyObservers(ev); + } + + public void setEditable(boolean editable) { + mEditable = editable; + } + + public boolean isEditable() { + return mEditable; + } + + +} diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphPoint.java b/src/main/java/org/cristalise/kernel/graph/model/GraphPoint.java new file mode 100644 index 0000000..a619733 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphPoint.java @@ -0,0 +1,37 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.model; + + +public class GraphPoint { + + public int x; + public int y; + + public GraphPoint() { + x=0; y=0; + } + + public GraphPoint(int x, int y) { + this.x = x; + this.y = y; + } +} diff --git a/src/main/java/org/cristalise/kernel/graph/model/Graphable.java b/src/main/java/org/cristalise/kernel/graph/model/Graphable.java new file mode 100644 index 0000000..f4acbb7 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/Graphable.java @@ -0,0 +1,75 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.model; + +/** +* @version $Revision: 1.6 $ $Date: 2003/05/12 13:10:20 $ +* @author $Author: abranson $ +*/ + +import org.cristalise.kernel.utils.CastorHashMap; + +abstract public class Graphable extends Vertex +{ + + protected CastorHashMap mProperties = null; + public GraphModel children; + + public void setProperties(CastorHashMap props) + { + mProperties = props; + } + + public CastorHashMap getProperties() + { + return mProperties; + } + /** @associates Graphable that is directly containing it*/ + private Graphable parent; + + /** + * Returns the parent. + * @return Graphable + */ + public Graphable getParent() + { + return parent; + } + + /** + * Sets the parent. + * @param parent The parent to set + */ + public void setParent(Graphable parent) + { + this.parent = parent; + } + @Override + public GraphModel getChildGraphModel() { + return children; + } + + @Override + public Object getCreationContext() { + return this; + } + +} diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphableEdge.java b/src/main/java/org/cristalise/kernel/graph/model/GraphableEdge.java new file mode 100644 index 0000000..8f6ac79 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphableEdge.java @@ -0,0 +1,91 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.model; + +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; + +/** +* @version $Revision: 1.2 $ $Date: 2003/05/12 13:10:20 $ +* @author $Author: abranson $ +*/ +public abstract class GraphableEdge extends DirectedEdge +{ + + private GraphableVertex mParent; + private CastorHashMap mProperties = null; + + public GraphableEdge() + { + mProperties = new CastorHashMap(); + } + + public GraphableEdge(GraphableVertex pre, GraphableVertex nex) + { + mProperties = new CastorHashMap(); + setParent(pre.getParent()); + pre.getParent().getChildrenGraphModel().addEdgeAndCreateId(this, pre, nex); + } + + /** + * Returns the parent. + * @return GraphableVertex + */ + public GraphableVertex getParent() + { + return mParent; + } + + /** + * Sets the parent. + * @param parent The parent to set + */ + public void setParent(GraphableVertex parent) + { + mParent = parent; + } + + /** + * Returns the properties. + * @return CastorHashMap + */ + public CastorHashMap getProperties() + { + return mProperties; + } + + /** + * Sets the properties. + * @param properties The properties to set + */ + public void setProperties(CastorHashMap properties) + { + mProperties = properties; + } + + public KeyValuePair[] getKeyValuePairs() { + return mProperties.getKeyValuePairs(); + } + + public void setKeyValuePairs(KeyValuePair[] pairs) { + mProperties.setKeyValuePairs(pairs); + } +} diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphableVertex.java b/src/main/java/org/cristalise/kernel/graph/model/GraphableVertex.java new file mode 100644 index 0000000..b82448e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphableVertex.java @@ -0,0 +1,284 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.model; +/** +* @version $Revision: 1.24 $ $Date: 2005/10/05 07:39:37 $ +* @author $Author: abranson $ +*/ + + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; + +public abstract class GraphableVertex extends Vertex +{ + private CastorHashMap mProperties = null; + private boolean mIsLayoutable; + protected boolean mIsComposite; + private GraphModel mChildrenGraphModel; + public GraphableVertex() + { + mProperties = new CastorHashMap(); + } + public void setProperties(CastorHashMap props) + { + mProperties = props; + } + public CastorHashMap getProperties() + { + return mProperties; + } + protected Integer getVersionNumberProperty(String propName) throws InvalidDataException { + Object val = getProperties().get(propName); + if (val == null || val.equals("") || val.toString().equals("-1")) return null; + try { + return Integer.valueOf(val.toString()); + } catch (NumberFormatException ex) { + throw new InvalidDataException("Invalid version number for property '"+propName+"': "+val.toString()); + } + } + public KeyValuePair[] getKeyValuePairs() + { + return mProperties.getKeyValuePairs(); + } + public void setKeyValuePairs(KeyValuePair[] pairs) + { + mProperties.setKeyValuePairs(pairs); + } + /** @associates Graphable that is directly containing it*/ + private GraphableVertex parent; + /** + * Returns the parent. + * @return Graphable + */ + public GraphableVertex getParent() + { + return parent; + } + /** + * Sets the parent. + * @param parent The parent to set + */ + public void setParent(GraphableVertex parent) + { + if (this.equals(parent)) + throw new ExceptionInInitializerError(); + this.parent = parent; + } + @Override + public GraphModel getChildGraphModel() + { + return mChildrenGraphModel; + } + @Override + public Object getCreationContext() + { + return this; + } + public Vertex[] getOutGraphables() + { + if (parent == null) + return new Vertex[0]; // none if no parent + return parent.mChildrenGraphModel.getOutVertices(this); + } + public DirectedEdge[] getOutEdges() + { + if (parent == null) + return new DirectedEdge[0]; // none if no parent + return parent.mChildrenGraphModel.getOutEdges(this); + } + public DirectedEdge[] getInEdges() + { + if (parent == null) + return new DirectedEdge[0]; // none if no parent + DirectedEdge[] edges = getParent().mChildrenGraphModel.getInEdges(this); + if (edges != null) + return edges; + else + return new DirectedEdge[0]; + } + public GraphableVertex[] getChildren() + { + return getLayoutableChildren(); + } + + public DirectedEdge[] getChildrenEdges() + { + if (getIsComposite()) + { + return getChildGraphModel().getEdges(); + } + return null; + } + + public GraphableVertex[] getLayoutableChildren() + { + if (getIsComposite()) + { + Vertex[] vs = mChildrenGraphModel.getVertices(); + GraphableVertex[] gvs = new GraphableVertex[vs.length]; + for (int i = 0; i < vs.length; i++) + { + gvs[i] = (GraphableVertex) vs[i]; + } + return gvs; + } + return null; + } + + /**@returns the Graphable searched or null if not this or children*/ + public GraphableVertex search(String ids) + { + if (getName().equals(ids)) + return this; + if (String.valueOf(getID()).equals(ids)) + return this; + if (getIsComposite()) + { + GraphableVertex[] graphables = getChildren(); + if (ids.startsWith(String.valueOf(getID()))) + ids = ids.substring(ids.indexOf("/") + 1); + else if (ids.startsWith(getName())) + ids = ids.substring(getName().length() + 1); + else if (ids.startsWith(getPath())) + ids = ids.substring(getPath().length() + 1); + else + return null; + + for (GraphableVertex graphable : graphables) { + GraphableVertex grap = graphable.search(ids); + if (grap != null) return grap; + } + } + return null; + } + /** + * Returns the isLayoutable. + * @return boolean + */ + public boolean getIsLayoutable() + { + return mIsLayoutable; + } + /** + * Sets the isLayoutable. + * @param isLayoutable The isLayoutable to set + */ + public void setIsLayoutable(boolean isLayoutable) + { + mIsLayoutable = isLayoutable; + } + /** + * Returns the isComposite. + * @return boolean + */ + public boolean getIsComposite() + { + return mIsComposite; + } + /** + * Sets the isComposite. + * @param isComposite The isComposite to set + */ + public void setIsComposite(boolean isComposite) + { + mIsComposite = isComposite; + } + + public void addChild(GraphableVertex graphableVertex, GraphPoint g) + { + getChildGraphModel().addVertexAndCreateId(graphableVertex, g); + graphableVertex.setParent(this); + } + /** + * Returns the childrenGraph. + * @return GraphModel + */ + public GraphModel getChildrenGraphModel() + { + return mChildrenGraphModel; + } + /** + * Sets the childrenGraph. + * @param childrenGraph The childrenGraph to set + */ + public void setChildrenGraphModel(GraphModel childrenGraph) + { + mChildrenGraphModel = childrenGraph; + DirectedEdge[] edges = mChildrenGraphModel.getEdges(); + GraphableVertex[] graphables = this.getLayoutableChildren(); + if (graphables != null) + for (GraphableVertex graphable : graphables) + graphable.setParent(this); + if (edges != null) + for (DirectedEdge edge : edges) + ((GraphableEdge) edge).setParent(this); + childrenGraph.setContainingVertex(this); + } + + /** + * @see org.cristalise.kernel.graph.model.Vertex#getCentrePoint() + */ + @Override + public GraphPoint getCentrePoint() + { + if (!getIsLayoutable()) + return null; + return super.getCentrePoint(); + } + /** + * @see org.cristalise.kernel.graph.model.Vertex#getInEdgeIds() + */ + @Override + public int[] getInEdgeIds() + { + if (!getIsLayoutable()) + return null; + return super.getInEdgeIds(); + } + /** + * @see org.cristalise.kernel.graph.model.Vertex#getOutEdgeIds() + */ + @Override + public int[] getOutEdgeIds() + { + if (!getIsLayoutable()) + return null; + return super.getOutEdgeIds(); + } + /** + * @see org.cristalise.kernel.graph.model.Vertex#getOutlinePoints() + */ + @Override + public GraphPoint[] getOutlinePoints() + { + if (!getIsLayoutable()) + return null; + return super.getOutlinePoints(); + } + public String getPath() + { + if (getName() != null && !getName().equals("")) + return getParent().getPath() + "/" + getName(); + return getParent().getPath() + "/" + getID(); + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/graph/model/TypeNameAndConstructionInfo.java b/src/main/java/org/cristalise/kernel/graph/model/TypeNameAndConstructionInfo.java new file mode 100644 index 0000000..a9b5572 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/TypeNameAndConstructionInfo.java @@ -0,0 +1,43 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.model; + + + +public class TypeNameAndConstructionInfo +{ + public String mName = null; + public Object mInfo = null; + + + public TypeNameAndConstructionInfo(String name, Object info) + { + mName = name; + mInfo = info; + } + + + @Override + public String toString() + { + return mName; + } +} diff --git a/src/main/java/org/cristalise/kernel/graph/model/Vertex.java b/src/main/java/org/cristalise/kernel/graph/model/Vertex.java new file mode 100644 index 0000000..122bbdd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/Vertex.java @@ -0,0 +1,327 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.graph.model; + +import java.awt.Polygon; +import java.util.Vector; + + +public class Vertex +{ + private int mId = -1; + private String mName = ""; + private GraphPoint mCentrePoint = new GraphPoint(0, 0); + private int mHeight = 0; + private int mWidth = 0; + private Vector mInEdgeIdVector = new Vector(); + private Vector mOutEdgeIdVector = new Vector(); + private final Vector mTags = new Vector(); + + // The Java Polygon class is used to determine if a point + // lies within the outline of a vertex. Unfortunately + // both the polygon and the set of outline points need to + // kept in memory because a polygon never has 0 points + // which is required by Castor's unmarshall object mechanism + private Polygon mOutlinePolygon = new Polygon(); + private GraphPoint[] mOutlinePoints = new GraphPoint[0]; + + + private GraphModel graphModel; + + public void setID(int id) + { + mId = id; + } + + + public int getID() + { + return mId; + } + + + public void setName(String n) + { + mName = n; + } + + + public String getName() + { + return mName; + } + + + public void setCentrePoint(GraphPoint p) + { + mCentrePoint = p; + } + + + public GraphPoint getCentrePoint() + { + return mCentrePoint; + } + + + public void setHeight(int h) + { + mHeight = h; + } + + + public int getHeight() + { + return mHeight; + } + + + public void setWidth(int w) + { + mWidth = w; + } + + + public int getWidth() + { + return mWidth; + } + + + // Sets the outline points and re-calculates the + // height and width + public void setOutlinePoints(GraphPoint[] outline) + { + int topLeftX = outline[0].x; + int topLeftY = outline[0].y; + int bottomRightX = 0; + int bottomRightY = 0; + int i = 0; + + mOutlinePoints = outline; + + // Construct a polygon in the outline of the vertex + // and calculate the top left and bottom right corners + mOutlinePolygon = new Polygon(); + + for(i=0; i bottomRightX) + { + bottomRightX = outline[i].x; + } + + + if(outline[i].y > bottomRightY) + { + bottomRightY = outline[i].y; + } + } + + // Set the height and width + mHeight = bottomRightY - topLeftY; + mWidth = bottomRightX - topLeftX; + } + + + public GraphPoint[] getOutlinePoints() + { + return mOutlinePoints; + } + + public void moveAbsolute(GraphPoint p) + { + int deltaX = p.x - mCentrePoint.x; + int deltaY = p.y - mCentrePoint.y; + int i = 0; + + // Update the outline points and the polygon + for(i=0; i(10, 10); + for(i=0; i(10, 10); + for(i=0; i vector) + { + int[] array = new int[vector.size()]; + Integer integer = null; + int i = 0; + + for(i=0; i path = new Vector(10, 10); + + graphModel.clearTags(startVertex); + visitVertex(startVertex, graphModel, path, direction, startVertex, ignoreBackLinks); + + return vectorToVertexArray(path); + } + + + private static void visitVertex(Vertex vertex, GraphModel graphModel, Vector path, int direction, Object tag, boolean ignoreBackLinks) + { + Vertex[] children = null; + int i = 0; + + if(direction == kDown) + { + children = graphModel.getOutVertices(vertex); + } + else + { + children = graphModel.getInVertices(vertex); + } + + vertex.setTag(tag); + path.add(vertex); + + for(i=0; i vector) + { + Vertex[] vertices = new Vertex[vector.size()]; + int i = 0; + + + for(i=0; i(0, 1); + setProperties(new WfCastorHashMap()); + setIsLayoutable(false); + } + /** + * @see org.cristalise.kernel.graph.model.Vertex#setID(int) + */ + @Override + public void setID(int id) + { + mId = id; + if (mName.equals("")) + setName(String.valueOf(id)); + } + /** + * @see org.cristalise.kernel.graph.model.Vertex#getID() + */ + @Override + public int getID() + { + return mId; + } + /** + * @see org.cristalise.kernel.graph.model.Vertex#setName(java.lang.String) + */ + @Override + public void setName(String n) + { + mName = n; + } + /** + * @see org.cristalise.kernel.graph.model.Vertex#getName() + */ + @Override + public String getName() + { + return mName; + } + + @Override + public void setVersion(int v) + { + mVersion = v; + } + /** + * @see org.cristalise.kernel.graph.model.Vertex#getName() + */ + @Override + public int getVersion() + { + return mVersion; + } + /** + * @see org.cristalise.kernel.lifecycle.WfVertexDef#getErrors() + */ + @Override + public String getErrors() + { + return super.getErrors(); + } + /** + * Method linkToSlot. + * + * @param actSl + * @param name + */ + public void linkToSlot(ActivitySlotDef actSl, String name, String name2) + { + actSl.setActivityDef(FileStringUtility.convert(name)); + actSl.getProperties().put("Name", name2.replace('/', '_')); + actSl.setName(name+" slot"); + setName(FileStringUtility.convert(name)); + } + /** + * @see org.cristalise.kernel.lifecycle.WfVertexDef#verify() + */ + @Override + public boolean verify() + { + return true; + } + /** + * @see org.cristalise.kernel.entity.C2KLocalObject#getClusterType() + */ + @Override + public String getClusterType() + { + return null; + } + public String getActName() + { + return getName(); + } + + /* + * (non-Javadoc) + * + * @see org.cristalise.kernel.lifecycle.commonInterface.ActType#getDescName() + */ + public String getDescName() + { + return getName(); + } + + @Override + public WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException{ + return instantiate(getName()); + } + public WfVertex instantiate(String name) throws ObjectNotFoundException, InvalidDataException + { + Activity act = new Activity(); + configureInstance(act); + act.setName(name); + act.setType(getName()); + return act; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/ActivitySlotDef.java b/src/main/java/org/cristalise/kernel/lifecycle/ActivitySlotDef.java new file mode 100644 index 0000000..89ddb86 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/ActivitySlotDef.java @@ -0,0 +1,201 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.graph.traversal.GraphTraversal; +import org.cristalise.kernel.lifecycle.instance.Activity; +import org.cristalise.kernel.lifecycle.instance.WfVertex; +import org.cristalise.kernel.utils.KeyValuePair; +import org.cristalise.kernel.utils.LocalObjectLoader; + +/** + * @version $Revision: 1.46 $ $Date: 2005/10/05 07:39:36 $ + * @author $Author: abranson $ + */ +public class ActivitySlotDef extends WfVertexDef +{ + private String activityDef; + + /** + * Method setActivityDef. + * + * @param oActivityDef + */ + public void setActivityDef(String oActivityDef) + { + activityDef = oActivityDef; + } + /** + * Method getActivityDef. + * + * @return String + */ + public String getActivityDef() + { + return activityDef; + } + /** + * @see java.lang.Object#Object() + */ + public ActivitySlotDef() + { + getProperties().put("Name", ""); + getProperties().put("Version", 0); + } + + public ActivityDef getTheActivityDef() throws ObjectNotFoundException, InvalidDataException + { + ActivityDef actDef = LocalObjectLoader.getActDef(getActivityDef(), getVersionNumberProperty("Version")); + if (actDef instanceof CompositeActivityDef) + mIsComposite = true; + return actDef; + } + /** + * @see org.cristalise.kernel.lifecycle.WfVertexDef#verify() + */ + /** launch the verification of the ActivityDef */ + @Override + public boolean verify() + { + mErrors.removeAllElements(); + boolean err = true; + int nbInEdgres = getInEdges().length; + int nbOutEdges = getOutEdges().length; + if (nbInEdgres == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId()) + { + mErrors.add("Unreachable"); + err = false; + } + if (nbInEdgres > 1) + { + mErrors.add("Bad nb of previous"); + err = false; + } + if (nbOutEdges > 1) + { + mErrors.add("too many next"); + err = false; + } + if (nbOutEdges == 0) + { + if (!((CompositeActivityDef) getParent()).hasGoodNumberOfActivity()) + { + mErrors.add("too many endpoints"); + err = false; + } + } + + Vertex[] allSiblings = getParent().getChildGraphModel().getVertices(); + String thisName = (String)getProperties().get("Name"); + if (thisName == null || thisName.length()==0) mErrors.add("Slot name is empty"); + else for (Vertex v : allSiblings) { + if (v instanceof ActivitySlotDef && v.getID()!=getID()) { + ActivitySlotDef otherSlot = (ActivitySlotDef)v; + String otherName = (String)otherSlot.getProperties().get("Name"); + if (otherName != null && otherName.equals(thisName)) { + mErrors.add("Duplicate slot name"); + err = false; + } + } + } + + KeyValuePair[] props; + try { + props = getTheActivityDef().getProperties().getKeyValuePairs(); + for (KeyValuePair prop : props) { + if (prop.isAbstract() && !getProperties().containsKey(prop.getKey())) { + mErrors.add("Abstract property '"+prop.getKey()+"' not defined in slot"); + err = false; + } + } + } catch (Exception ex) { } + + + // Loop check + Vertex[] outV = getOutGraphables(); + Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false); + boolean errInLoop = false; + for (Vertex element : outV) { + for (Vertex anteVertice : anteVertices) + if (!loop() && element.getID() == anteVertice.getID()) + errInLoop = true; + } + if (errInLoop) + { + mErrors.add("Problem in Loop"); + err = false; + } + return err; + } + /** + * Method getNextWfVertices. + * + * @return WfVertexDef[] + */ + public WfVertexDef[] getNextWfVertices() + { + return (WfVertexDef[]) getOutGraphables(); + } + /** + * @see org.cristalise.kernel.graph.model.GraphableVertex#isLayoutable() + */ + /** + * @see org.cristalise.kernel.graph.model.GraphableVertex#getIsLayoutable() + */ + public boolean isLayoutable() + { + return true; + } + /** + * Method getInfo. + * + * @return CastorHashMap + */ + private void configureInstance(Activity act) + { + KeyValuePair[] k = getProperties().getKeyValuePairs(); + for (KeyValuePair element : k) + act.getProperties().put(element.getKey(), element.getValue(), element.isAbstract()); + act.setCentrePoint(getCentrePoint()); + act.setOutlinePoints(getOutlinePoints()); + act.setInEdgeIds(getInEdgeIds()); + act.setOutEdgeIds(getOutEdgeIds()); + act.setName(getActName()); + act.setID(getID()); + } + + public String getActName() + { + return (String) getProperties().get("Name"); + } + + @Override + public WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException { + Activity newActivity = (Activity)getTheActivityDef().instantiate(); + configureInstance(newActivity); + if (newActivity.getProperties().getAbstract().size() > 0) { + throw new InvalidDataException("Abstract properties not overridden: "+newActivity.getProperties().getAbstract().toString()); + } + return newActivity; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/AndSplitDef.java b/src/main/java/org/cristalise/kernel/lifecycle/AndSplitDef.java new file mode 100644 index 0000000..6d6856a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/AndSplitDef.java @@ -0,0 +1,135 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle; + +import java.util.Vector; + +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.graph.traversal.GraphTraversal; +import org.cristalise.kernel.lifecycle.instance.AndSplit; +import org.cristalise.kernel.lifecycle.instance.WfVertex; + +/** + * @version $Revision: 1.19 $ $Date: 2005/09/29 10:18:31 $ + * @author $Author: abranson $ + */ + +public class AndSplitDef extends WfVertexDef +{ + /** + * @see java.lang.Object#Object() + */ + public AndSplitDef() + { + mErrors = new Vector(0, 1); + getProperties().put("RoutingScriptName", ""); + getProperties().put("RoutingScriptVersion", ""); + } + + /** + * @see org.cristalise.kernel.lifecycle.WfVertexDef#verify() + */ + @Override + public boolean verify() + { + mErrors.removeAllElements(); + boolean err = true; + int nbInEdges = getInEdges().length; + if (nbInEdges == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId()) + { + mErrors.add("Unreachable"); + err = false; + } + else if (nbInEdges > 1) + { + mErrors.add("Bad nb of previous"); + err = false; + } + else + { + if (getOutEdges().length <= 1) + { + mErrors.add("not enough next"); + err = false; + } + else if (!(this instanceof LoopDef)) + { + Vertex[] outV = getOutGraphables(); + Vertex[] anteVertices = + GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false); + boolean loop = false; + boolean errInLoop = true; + for (int i = 0; i < outV.length; i++) + { + for (int j = 0; j < anteVertices.length; j++) + if (!loop && outV[i].getID() == anteVertices[j].getID()) + { + if (outV[i] instanceof LoopDef) + { + loop = true; + j = anteVertices.length; + i = outV.length; + } + else + { + errInLoop = false; + } + } + } + if (errInLoop && loop) + { + mErrors.add("Problem in Loop"); + err = false; + } + } + } + return err; + } + + @Override + public boolean loop() + { + boolean loop2 = false; + if (!loopTested) + { + loopTested = true; + if (getOutGraphables().length != 0) + { + Vertex[] outVertices = getOutGraphables(); + for (int i = 0; i < outVertices.length; i++) + { + WfVertexDef tmp = (WfVertexDef) getOutGraphables()[i]; + loop2 = loop2 || tmp.loop(); + } + } + } + loopTested = false; + return loop2; + } + + @Override + public WfVertex instantiate() { + AndSplit newSplit = new AndSplit(); + configureInstance(newSplit); + return newSplit; + } + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/CompositeActivityDef.java b/src/main/java/org/cristalise/kernel/lifecycle/CompositeActivityDef.java new file mode 100644 index 0000000..4341fbf --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/CompositeActivityDef.java @@ -0,0 +1,266 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.graph.model.GraphModel; +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.graph.model.GraphableVertex; +import org.cristalise.kernel.graph.model.TypeNameAndConstructionInfo; +import org.cristalise.kernel.lifecycle.instance.CompositeActivity; +import org.cristalise.kernel.lifecycle.instance.Next; +import org.cristalise.kernel.lifecycle.instance.WfVertex; +import org.cristalise.kernel.utils.Language; +import org.cristalise.kernel.utils.Logger; + +/** + * @version $Revision: 1.93 $ $Date: 2005/10/05 07:39:36 $ + * @author $Author: abranson $ + */ +public class CompositeActivityDef extends ActivityDef +{ + private final TypeNameAndConstructionInfo[] mVertexTypeNameAndConstructionInfo = + { + new TypeNameAndConstructionInfo(Language.translate("Activity"), "Atomic"), + new TypeNameAndConstructionInfo(Language.translate("Composite"), "Composite"), + new TypeNameAndConstructionInfo(Language.translate("AND Split"), "And"), + new TypeNameAndConstructionInfo(Language.translate("OR Split"), "Or"), + new TypeNameAndConstructionInfo(Language.translate("XOR Split"), "XOr"), + new TypeNameAndConstructionInfo(Language.translate("Join"), "Join"), + new TypeNameAndConstructionInfo(Language.translate("Loop"), "Loop"), + }; + private final TypeNameAndConstructionInfo[] mEdgeTypeNameAndConstructionInfo = + { + new TypeNameAndConstructionInfo(Language.translate("Next Edge"), "Next") + }; + public TypeNameAndConstructionInfo[] getVertexTypeNameAndConstructionInfo() + { + return mVertexTypeNameAndConstructionInfo; + } + public TypeNameAndConstructionInfo[] getEdgeTypeNameAndConstructionInfo() + { + return mEdgeTypeNameAndConstructionInfo; + } + + public CompositeActivityDef() + { + super(); + setChildrenGraphModel(new GraphModel(new WfVertexDefOutlineCreator())); + setIsComposite(true); + } + + /** + * Method addNextDef. + * + * @param origin + * @param terminus + * @return NextDef + */ + public NextDef addNextDef(WfVertexDef origin, WfVertexDef terminus) + { + NextDef returnNxt = new NextDef(origin, terminus); + getChildrenGraphModel().addEdgeAndCreateId(returnNxt, origin, terminus); + return returnNxt; + } + /** + * Method addExistingActivityDef. + * + * @param actDef + * @param point + */ + public ActivitySlotDef addExistingActivityDef(String name, ActivityDef actDef, GraphPoint point) + { + changed = true; + ActivitySlotDef child = new ActivitySlotDef(); + addChild(child, point); + actDef.linkToSlot(child, actDef.getName(), name); + return child; + } + /** + * Method newChild. + * + * @param Name + * @param Type + * @param location + * @return WfVertexDef + */ + public WfVertexDef newChild(String Name, String Type, GraphPoint location) + { + changed = true; + WfVertexDef child; + if (Type.equals("Or")) + { + child = new OrSplitDef(); + addChild(child, location); + Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID()); + } + else if (Type.equals("XOr")) + { + child = new XOrSplitDef(); + addChild(child, location); + Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID()); + } + else if (Type.equals("And")) + { + child = new AndSplitDef(); + addChild(child, location); + Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID()); + } + else if (Type.equals("Loop")) + { + child = new LoopDef(); + addChild(child, location); + Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID()); + } + else if (Type.equals("Atomic")) + { + child = new ActivitySlotDef(); + ActivityDef act = new ActivityDef(); + act.changed = true; + addChild(child, location); + act.linkToSlot((ActivitySlotDef) child, Name, Name); + act.getProperties().put("Description", Name); + Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID()); + } + else if (Type.equals("Join")) + { + child = new JoinDef(); + child.getProperties().put("Type", "Join"); + addChild(child, location); + Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID()); + } + else if (Type.equals("Route")) + { + child = new JoinDef(); + child.getProperties().put("Type", "Route"); + addChild(child, location); + Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID()); + } + else + { + child = new ActivitySlotDef(); + CompositeActivityDef act = new CompositeActivityDef(); + act.changed = true; + addChild(child, location); + act.linkToSlot((ActivitySlotDef) child, Name, Name); + Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID()); + } + return child; + } + /** + * Method instantiateAct. + * + * @return CompositeActivity + */ + @Override + public WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException { + return instantiate(getName()); + } + + @Override + public WfVertex instantiate(String name) throws ObjectNotFoundException, InvalidDataException + { + CompositeActivity cAct = new CompositeActivity(); + configureInstance(cAct); + cAct.setType(getName()); + cAct.setName(name); + GraphableVertex[] vertexDefs = getLayoutableChildren(); + WfVertex[] wfVertices = new WfVertex[vertexDefs.length]; + for (int i = 0; i < vertexDefs.length; i++) + { + WfVertexDef vertDef = (WfVertexDef)vertexDefs[i]; + wfVertices[i] = vertDef.instantiate(); + wfVertices[i].setParent(cAct); + } + Next[] nexts = new Next[getChildrenGraphModel().getEdges().length]; + for (int i = 0; i < getChildrenGraphModel().getEdges().length; i++) + { + NextDef nextDef = (NextDef) getChildrenGraphModel().getEdges()[i]; + nexts[i] = nextDef.instantiate(); + nexts[i].setParent(cAct); + } + cAct.getChildrenGraphModel().setStartVertexId(getChildrenGraphModel().getStartVertexId()); + cAct.getChildrenGraphModel().setEdges(nexts); + cAct.getChildrenGraphModel().setVertices(wfVertices); + cAct.getChildrenGraphModel().setNextId(getChildrenGraphModel().getNextId()); + cAct.getChildrenGraphModel().resetVertexOutlines(); + return cAct; + } + + /** + * Method hasGoodNumberOfActivity. + * + * @return boolean + */ + + public boolean hasGoodNumberOfActivity() + { + int endingAct = 0; + GraphableVertex[] graphableVertices = this.getLayoutableChildren(); + if (graphableVertices != null) + for (GraphableVertex graphableVertice : graphableVertices) { + WfVertexDef vertex = (WfVertexDef) graphableVertice; + if (getChildrenGraphModel().getOutEdges(vertex).length == 0) + endingAct++; + } + if (endingAct > 1) + return false; + return true; + } + + /** + * @see org.cristalise.kernel.graph.model.GraphableVertex#getPath() + */ + @Override + public String getPath() + { + if (getParent() == null) + return getName(); + return super.getPath(); + } + @Override + public void setChildrenGraphModel(GraphModel childrenGraph) { + super.setChildrenGraphModel(childrenGraph); + childrenGraph.setVertexOutlineCreator(new WfVertexDefOutlineCreator()); + } + //deprecated + public String[] getCastorNonLayoutableChildren() { + return new String[0]; + } + + public void setCastorNonLayoutableChildren(String[] dummy) { } + + @Override + public boolean verify() { + boolean err = super.verify(); + GraphableVertex[] vChildren = getChildren(); + for (int i = 0; i < vChildren.length; i++) + { + WfVertexDef wfvChild = (WfVertexDef)vChildren[i]; + if (!(wfvChild.verify())) + { + mErrors.add(wfvChild.getName()+": "+wfvChild.getErrors()); + err = false; + } + } + return err; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/JoinDef.java b/src/main/java/org/cristalise/kernel/lifecycle/JoinDef.java new file mode 100644 index 0000000..a198453 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/JoinDef.java @@ -0,0 +1,88 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle; + +import org.cristalise.kernel.lifecycle.instance.Join; +import org.cristalise.kernel.lifecycle.instance.WfVertex; + +/** + * @version $Revision: 1.18 $ $Date: 2005/09/29 10:18:31 $ + * @author $Author: abranson $ + */ +public class JoinDef extends WfVertexDef +{ + /** + * @see java.lang.Object#Object() + */ + public JoinDef() + { + } + /** + * @see org.cristalise.kernel.lifecycle.WfVertexDef#verify() + */ + @Override + public boolean verify() + { + mErrors.removeAllElements(); + int nbOutEdges = getOutEdges().length; + int nbInEdges = getInEdges().length; + String type = (String) getProperties().get("Type"); + if (nbInEdges < 1) + { + mErrors.add("not enough previous"); + return false; + } + if (type != null && type.equals("Route")) + { + if (nbInEdges > 1) + { + mErrors.add("Bad nb of previous"); + return false; + } + } + if (nbOutEdges > 1) + { + mErrors.add("too many next"); + return false; + } + if (nbOutEdges == 0) + { + if (!((CompositeActivityDef) getParent()).hasGoodNumberOfActivity()) + { + mErrors.add("too many endpoints"); + return false; + } + } + return true; + } + @Override + public boolean isJoin() + { + return true; + } + + @Override + public WfVertex instantiate() { + Join newJoin = new Join(); + configureInstance(newJoin); + return newJoin; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/LoopDef.java b/src/main/java/org/cristalise/kernel/lifecycle/LoopDef.java new file mode 100644 index 0000000..96a6f3f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/LoopDef.java @@ -0,0 +1,98 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle; + +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.graph.traversal.GraphTraversal; +import org.cristalise.kernel.lifecycle.instance.Loop; +import org.cristalise.kernel.lifecycle.instance.WfVertex; + +/** + * @version $Revision: 1.19 $ $Date: 2005/09/29 10:18:31 $ + * @author $Author: abranson $ + */ + +public class LoopDef extends XOrSplitDef +{ + public boolean hasLoop = false; + public int isNext = 0; + + /** + * @see java.lang.Object#Object() + */ + public LoopDef() + { + super(); + } + + /** + * @see org.cristalise.kernel.lifecycle.WfVertexDef#loop() + */ + @Override + public boolean loop() + { + return true; + } + + /** + * @see org.cristalise.kernel.lifecycle.WfVertexDef#verify() + */ + @Override + public boolean verify() + { + if (!super.verify()) return false; + Vertex[] nexts = getOutGraphables(); + Vertex[] anteVertices = + GraphTraversal.getTraversal(this.getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false); + int k = 0; + int l = 0; + Vertex[] brothers = getParent().getChildren(); + for (Vertex brother : brothers) + if (brother instanceof LoopDef) l++; + for (Vertex next : nexts) + for (Vertex anteVertice : anteVertices) + if (next.equals(anteVertice)) + k++; + if (k != 1 && !(l>1)) + { + mErrors.add("bad number of pointing back nexts"); + return false; + } +// if (nexts.length>2) { +// mErrors.add("you must only have 2 nexts"); +// return false; +// } + return true; + } + + @Override + public boolean isLoop() { + return true; + } + + @Override + public WfVertex instantiate() { + Loop newLoop = new Loop(); + configureInstance(newLoop); + return newLoop; + } + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/NextDef.java b/src/main/java/org/cristalise/kernel/lifecycle/NextDef.java new file mode 100644 index 0000000..463e7a4 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/NextDef.java @@ -0,0 +1,115 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle; +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.graph.model.GraphableEdge; +import org.cristalise.kernel.lifecycle.instance.Next; +/** + * @version $Revision: 1.32 $ $Date: 2006/03/03 13:52:21 $ + * @author $Author: abranson $ + */ +public class NextDef extends GraphableEdge +{ + /** + * @see java.lang.Object#Object() + */ + public NextDef() + { + } + /** + * Method verify. + * + * @return boolean + */ + public boolean verify() + { + return true; + } + /** + * Method NextDef. + * + * @param pre + * @param nex + */ + /** create and initialize a link between an Activities */ + public NextDef(WfVertexDef pre, WfVertexDef nex) + { + setParent(pre.getParent()); + if (pre instanceof OrSplitDef || pre instanceof XOrSplitDef) + { + int num = pre.getOutGraphables().length; + try + { + num = Integer.parseInt((String) pre.getProperties().get("LastNum")); + } + catch (Exception e) + { + } + getProperties().put("Alias", String.valueOf(num)); + pre.getProperties().put("LastNum", String.valueOf(num + 1)); + } + } + @Override + public boolean containsPoint(GraphPoint p) + { + GraphPoint originPoint = getOriginPoint(); + GraphPoint terminusPoint = getTerminusPoint(); + GraphPoint midPoint = new GraphPoint(); + if (("Broken +".equals(getProperties().get("Type")))) + { + midPoint.x = (originPoint.x + terminusPoint.x) / 2; + midPoint.y = (originPoint.y + terminusPoint.y) / 2; + } + else if (("Broken -".equals(getProperties().get("Type")))) + { + boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60); + midPoint.x = arrowOnY ? terminusPoint.x : (originPoint.x + terminusPoint.x) / 2; + midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : originPoint.y; + } + else if (("Broken |".equals(getProperties().get("Type")))) + { + boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60); + midPoint.x = arrowOnY ? originPoint.x : (originPoint.x + terminusPoint.x) / 2; + midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : terminusPoint.y; + } + else + { + midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x) / 2; + midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y) / 2; + } + int minX = midPoint.x - 10; + int minY = midPoint.y - 10; + int maxX = midPoint.x + 10; + int maxY = midPoint.y + 10; + return (p.x >= minX) && (p.x <= maxX) && (p.y >= minY) && (p.y <= maxY); + } + + public Next instantiate() { + Next next = new Next(); + next.setID(getID()); + next.setOriginVertexId(getOriginVertexId()); + next.setTerminusVertexId(getTerminusVertexId()); + next.setProperties(getProperties()); + next.setOriginPoint(getOriginPoint()); + next.setTerminusPoint(getTerminusPoint()); + return next; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/OrSplitDef.java b/src/main/java/org/cristalise/kernel/lifecycle/OrSplitDef.java new file mode 100644 index 0000000..c51c5fa --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/OrSplitDef.java @@ -0,0 +1,44 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle; +import org.cristalise.kernel.lifecycle.instance.OrSplit; +import org.cristalise.kernel.lifecycle.instance.WfVertex; +/** + * @version $Revision: 1.13 $ $Date: 2005/12/01 14:23:15 $ + * @author $Author: abranson $ + */ +public class OrSplitDef extends AndSplitDef +{ + /** + * @see java.lang.Object#Object() + */ + public OrSplitDef() + { + super(); + } + + @Override + public WfVertex instantiate() { + OrSplit newSplit = new OrSplit(); + configureInstance(newSplit); + return newSplit; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/WfCastorHashMap.java b/src/main/java/org/cristalise/kernel/lifecycle/WfCastorHashMap.java new file mode 100644 index 0000000..e30e9c3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/WfCastorHashMap.java @@ -0,0 +1,48 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle; +import org.cristalise.kernel.utils.CastorHashMap; +/** + * @version $Revision: 1.29 $ $Date: 2005/05/20 13:07:13 $ + * @author $Author: abranson $ + */ +public class WfCastorHashMap extends CastorHashMap +{ + /** + * @see java.lang.Object#Object() + */ + public WfCastorHashMap() + { + put("Show time", true); + put("Breakpoint", false); + put("Description", ""); + put("Agent Role", ""); + put("Agent Name", ""); + put("SchemaType", ""); + put("SchemaVersion", ""); + put("ScriptName", ""); + put("ScriptVersion", ""); + put("StateMachineName", "Default"); + put("StateMachineVersion", 0); + put("Viewpoint", ""); + put("OutcomeInit", ""); + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDef.java b/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDef.java new file mode 100644 index 0000000..939423a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDef.java @@ -0,0 +1,112 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle; + +import java.util.Vector; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.graph.model.GraphableVertex; +import org.cristalise.kernel.lifecycle.instance.WfVertex; +import org.cristalise.kernel.utils.KeyValuePair; + + +/** + * @version $Revision: 1.22 $ $Date: 2005/11/15 15:56:38 $ + * @author $Author: abranson $ + */ +public abstract class WfVertexDef extends GraphableVertex +{ + public Vector mErrors; + + protected boolean loopTested; + + /** + * @see java.lang.Object#Object() + */ + /** @label wf */ + public WfVertexDef() + { + mErrors = new Vector(0, 1); + setIsLayoutable(true); + } + + public abstract WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException; + + public void configureInstance(WfVertex newVertex) { + KeyValuePair[] k = getProperties().getKeyValuePairs(); + for (KeyValuePair element : k) + newVertex.getProperties().put(element.getKey(), element.getValue(), element.isAbstract()); + newVertex.setID(getID()); + if (getIsLayoutable()) { + newVertex.setInEdgeIds(getInEdgeIds()); + newVertex.setOutEdgeIds(getOutEdgeIds()); + newVertex.setCentrePoint(getCentrePoint()); + newVertex.setOutlinePoints(getOutlinePoints()); + } + } + + /** + * Method verify. + * + * @return boolean + */ + public abstract boolean verify(); + + /** + * Method getErrors. + * + * @return String + */ + public String getErrors() + { + if (mErrors.size() == 0) + return "No error"; + else if (mErrors.size() == 1) + return mErrors.elementAt(0); + else { + StringBuffer errorBuffer = new StringBuffer(); + for (String error : mErrors) { + if (errorBuffer.length() > 0) errorBuffer.append("\n"); + errorBuffer.append(error); + } + return errorBuffer.toString(); + } + } + + /** + * Method loop. + * + * @return boolean + */ + public boolean loop() + { + boolean loop2 = false; + if (!loopTested) + { + loopTested = true; + if (getOutGraphables().length != 0) + loop2 = ((WfVertexDef) getOutGraphables()[0]).loop(); + } + loopTested = false; + return loop2; + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDefOutlineCreator.java b/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDefOutlineCreator.java new file mode 100644 index 0000000..1bb8e2e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDefOutlineCreator.java @@ -0,0 +1,70 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle; + +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.graph.model.VertexOutlineCreator; + +public class WfVertexDefOutlineCreator implements VertexOutlineCreator +{ + private static final int mActivityWidth = 130; + private static final int mActivityHeight = 60; + private static final int mSplitJoinWidth = 60; + private static final int mSplitJoinHeight = 25; + + @Override + public void setOutline(Vertex vertex) + { + GraphPoint centrePoint = vertex.getCentrePoint(); + GraphPoint[] outlinePoints = new GraphPoint[ 4 ]; + int vertexWidth = 0; + int vertexHeight = 0; + + + if ( vertex instanceof ActivitySlotDef ) + { + vertexWidth = mActivityWidth; + vertexHeight = mActivityHeight; + } + else + { + vertexWidth = mSplitJoinWidth; + vertexHeight = mSplitJoinHeight; + } + + outlinePoints[ 0 ] = new GraphPoint(); + outlinePoints[ 0 ].x = centrePoint.x - vertexWidth / 2; + outlinePoints[ 0 ].y = centrePoint.y - vertexHeight / 2; + outlinePoints[ 1 ] = new GraphPoint(); + outlinePoints[ 1 ].x = centrePoint.x + vertexWidth / 2; + outlinePoints[ 1 ].y = centrePoint.y - vertexHeight / 2; + outlinePoints[ 2 ] = new GraphPoint(); + outlinePoints[ 2 ].x = centrePoint.x + vertexWidth / 2; + outlinePoints[ 2 ].y = centrePoint.y + vertexHeight / 2; + outlinePoints[ 3 ] = new GraphPoint(); + outlinePoints[ 3 ].x = centrePoint.x - vertexWidth / 2; + outlinePoints[ 3 ].y = centrePoint.y + vertexHeight / 2; + + vertex.setOutlinePoints( outlinePoints ); + } +} + diff --git a/src/main/java/org/cristalise/kernel/lifecycle/XOrSplitDef.java b/src/main/java/org/cristalise/kernel/lifecycle/XOrSplitDef.java new file mode 100644 index 0000000..7754c52 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/XOrSplitDef.java @@ -0,0 +1,48 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle; + +import org.cristalise.kernel.lifecycle.instance.WfVertex; +import org.cristalise.kernel.lifecycle.instance.XOrSplit; + + +/** + * @version $Revision: 1.14 $ $Date: 2005/09/29 10:18:31 $ + * @author $Author: abranson $ + */ + +public class XOrSplitDef extends AndSplitDef +{ + /** + * @see java.lang.Object#Object() + */ + public XOrSplitDef() + { + super(); + } + + @Override + public WfVertex instantiate() { + XOrSplit newSplit = new XOrSplit(); + configureInstance(newSplit); + return newSplit; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Activity.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Activity.java new file mode 100644 index 0000000..f04a7a9 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Activity.java @@ -0,0 +1,573 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; +import java.util.Vector; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.GTimeStamp; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.agent.Job; +import org.cristalise.kernel.events.Event; +import org.cristalise.kernel.events.History; +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.lifecycle.WfCastorHashMap; +import org.cristalise.kernel.lifecycle.instance.stateMachine.State; +import org.cristalise.kernel.lifecycle.instance.stateMachine.StateMachine; +import org.cristalise.kernel.lifecycle.instance.stateMachine.Transition; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidAgentPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.Path; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.Schema; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.DateUtility; +import org.cristalise.kernel.utils.LocalObjectLoader; +import org.cristalise.kernel.utils.Logger; + +/** + * @version $Revision: 1.222 $ $Date: 2005/10/05 07:39:37 $ + * @author $Author: abranson $ + */ +public class Activity extends WfVertex +{ + /** + * vector of errors (Strings) that is constructed each time verify() is launched + */ + protected Vector mErrors; + /** @associates a State machine engine */ + private StateMachine machine; + protected int state = -1; + /** true is available to be executed */ + public boolean active = false; + /** used in verify() */ + private boolean loopTested; + private GTimeStamp mStateDate; + private String mType; + + public Activity() + { + super(); + setProperties(new WfCastorHashMap()); + getProperties().put("StateMachineName", getDefaultSMName()); + mErrors = new Vector(0, 1); + mStateDate = new GTimeStamp(); + DateUtility.setToNow(mStateDate); + } + + protected String getDefaultSMName() { + return "Default"; + } + + /** add the activity which id is idNext as next of the current one */ + void addNext(String idNext) + { + new Next(this, (WfVertex) getParent().search(idNext)); + } + /** + * adds a New link between the current Activity and the WfVertex passed in param + */ + @Override + public Next addNext(WfVertex vertex) + { + return new Next(this, vertex); + } + + public StateMachine getStateMachine() throws InvalidDataException { + if (machine == null) { + String name = (String)getProperties().get("StateMachineName"); + int version = getVersionNumberProperty("StateMachineVersion"); + try { + machine = LocalObjectLoader.getStateMachine(name, version); + } catch (ObjectNotFoundException ex) { + if (name.equals(getDefaultSMName()) && version == 0) { // default state machine not imported yet. Fake it. + try { + String marshalledSM = Gateway.getResource().getTextResource(null, "boot/SM/"+getDefaultSMName()+".xml"); + StateMachine bootstrap = (StateMachine)Gateway.getMarshaller().unmarshall(marshalledSM); + bootstrap.validate(); + machine = bootstrap; + return bootstrap; + } catch (Exception ex2) { + Logger.error(ex2); + throw new InvalidDataException("Could not bootstrap default state machine from resources."); + } + } + Logger.error(ex); + throw new InvalidDataException("Error loading state machine '"+name+"' v"+version); + } + } + return machine; + } + + /** return the current State of the State machine (Used in Serialisation) */ + public int getState() throws InvalidDataException + { + if (state == -1) + state = getStateMachine().getInitialStateCode(); + return state; + } + public String getStateName() throws InvalidDataException + { + return getStateMachine().getState(getState()).getName(); + } + + /** Sets a new State */ + public void setState(int state) + { + this.state = state; + } + + public boolean isFinished() throws InvalidDataException { + return getStateMachine().getState(getState()).isFinished(); + } + + + /** cf Item request + * @throws ObjectNotFoundException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws ObjectCannotBeUpdated + * @throws CannotManageException + * @throws InvalidCollectionModification */ + public String request(AgentPath agent, ItemPath itemPath, int transitionID, String requestData) throws AccessRightsException, InvalidTransitionException, InvalidDataException, ObjectNotFoundException, PersistencyException, ObjectAlreadyExistsException, ObjectCannotBeUpdated, CannotManageException, InvalidCollectionModification + { + + // Find requested transition + Transition transition = getStateMachine().getTransition(transitionID); + + // Check if the transition is possible + String usedRole = transition.getPerformingRole(this, agent); + + // Verify outcome + Schema schema = null; + String viewName = null; + boolean storeOutcome = false; + if (transition.hasOutcome(getProperties())) { + schema = transition.getSchema(getProperties()); + viewName = (String)getProperties().get("Viewpoint"); + if (requestData != null && requestData.length()>0) + storeOutcome = true; + else if (transition.getOutcome().isRequired()) + throw new InvalidDataException("Transition requires outcome data, but none was given"); + } + + // Get new state + State newState = getStateMachine().traverse(this, transition, agent); + + // Run extra logic in predefined steps here + String outcome = runActivityLogic(agent, itemPath, transitionID, requestData); + + // set new state and reservation + setState(newState.getId()); + getProperties().put("Agent Name", transition.getReservation(this, agent)); + + // store new event + Event newEvent = null; + try { + History hist = getWf().getHistory(); + if (storeOutcome) + newEvent = hist.addEvent(agent, usedRole, getName(), getPath(), getType(), schema.docType, schema.docVersion, + getStateMachine().getName(), getStateMachine().getVersion(), transition, viewName); + else + newEvent = hist.addEvent(agent, usedRole, getName(), getPath(), getType(), + getStateMachine().getName(), getStateMachine().getVersion(), transition); + + Logger.msg(7, "Activity::auditEvent() - Event:" + newEvent.getName() + " was added to the AuditTrail"); + + if (storeOutcome) { + Outcome newOutcome = new Outcome(newEvent.getID(), outcome, schema.docType, schema.docVersion); + Gateway.getStorage().put(itemPath, newOutcome, getWf()); + + // update specific view if defined + if (viewName != null && !viewName.equals("")) { + Viewpoint currentView = new Viewpoint(itemPath, schema.docType, viewName, schema.docVersion, newEvent.getID()); + Gateway.getStorage().put(itemPath, currentView, getWf()); + } + // update last view + Viewpoint currentView = new Viewpoint(itemPath, schema.docType, "last", schema.docVersion, newEvent.getID()); + Gateway.getStorage().put(itemPath, currentView, getWf()); + } + Gateway.getStorage().commit(getWf()); + } catch (PersistencyException ex) { + Logger.error(ex); + Gateway.getStorage().abort(getWf()); + throw ex; + } + + if (newState.isFinished()) { + if (!getProperties().get("Breakpoint").equals(Boolean.TRUE)) + runNext(agent, itemPath); + } + + DateUtility.setToNow(mStateDate); + + //refresh all the job lists + String agentRole = getCurrentAgentRole(); + if (agentRole != null && agentRole.length()>0) { + try { + RolePath myRole = Gateway.getLookup().getRolePath(agentRole); + pushJobsToAgents(itemPath, myRole); + } catch (ObjectNotFoundException ex) { // non-existent role + Logger.msg(7, "Activity.pushJobsToAgents() - Activity role '"+agentRole+" not found."); + } + } + + + return outcome; + } + + protected String runActivityLogic(AgentPath agent, ItemPath itemPath, + int transitionID, String requestData) throws + InvalidDataException, + InvalidCollectionModification, + ObjectAlreadyExistsException, + ObjectCannotBeUpdated, + ObjectNotFoundException, + PersistencyException, + CannotManageException + { + // Overriden in predefined steps + return requestData; + } + + @Override + public boolean verify() + { + mErrors.removeAllElements(); + int nbInEdgres = getInEdges().length; + int nbOutEdges = getOutEdges().length; + if (nbInEdgres == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId()) + { + mErrors.add("Unreachable"); + return false; + } + else if (nbInEdgres > 1) + { + mErrors.add("Bad nb of previous"); + return false; + } + else if (nbOutEdges > 1) + { + mErrors.add("too many next"); + return false; + } + else if (nbOutEdges == 0) + { + if (!((CompositeActivity) getParent()).hasGoodNumberOfActivity()) + { + mErrors.add("too many endpoints"); + return false; + } + } +// else +// { +// Vertex[] outV = getOutGraphables(); +// Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false); +// boolean errInLoop = false; +// for (int i = 0; i < outV.length; i++) +// { +// for (int j = 0; j < anteVertices.length; j++) +// if (!loop() && outV[i].getID() == anteVertices[j].getID()) +// errInLoop = true; +// } +// if (errInLoop) +// { +// mErrors.add("Error In Loop"); +// return false; +// } +// } + return true; + } + /** Used in verify() */ + @Override + public boolean loop() + { + boolean loop2 = false; + if (!loopTested) + { + loopTested = true; + if (getOutGraphables().length != 0) + loop2 = ((WfVertex) getOutGraphables()[0]).loop(); + } + loopTested = false; + return loop2; + } + /** sets the next activity available if possible + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws ObjectCannotBeUpdated */ + @Override + public void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException + { + setActive(false); + try + { + Vertex[] outVertices = getOutGraphables(); + Vertex[] outVertices2 = getOutGraphables(); + boolean hasNoNext = false; + boolean out = false; + while (!out) + if (outVertices2.length > 0) + { + if (outVertices2[0] instanceof Join) + outVertices2 = ((WfVertex) outVertices2[0]).getOutGraphables(); + else + out = true; + } + else + { + hasNoNext = true; + out = true; + } + Logger.debug(8, Arrays.toString(outVertices) + " " + Arrays.toString(outVertices2)); + if (!hasNoNext) + ((WfVertex) outVertices[0]).run(agent, itemPath); + else + { + if (getParent() != null && getParent().getName().equals("domain")) // workflow + // finished + setActive(true); + else + { + CompositeActivity parent = (CompositeActivity) getParent(); + if (parent != null) + parent.runNext(agent, itemPath); + } + } + } + catch (InvalidDataException s) + { + setActive(true); + throw s; + } + } + /** @return the only Next of the Activity */ + public Next getNext() + { + if (getOutEdges().length > 0) + return (Next) getOutEdges()[0]; + else + return null; + } + /** reinitialises the Activity and propagate (for Loop) + * @throws InvalidDataException + * @throws ObjectNotFoundException */ + @Override + public void reinit(int idLoop) throws InvalidDataException + { + Vertex[] outVertices = getOutGraphables(); + setState(getStateMachine().getInitialState().getId()); + if (outVertices.length > 0) + { + WfVertex nextAct = (WfVertex) outVertices[0]; + nextAct.reinit(idLoop); + } + } + /** return the String that identifies the errors found in th activity */ + @Override + public String getErrors() + { + if (mErrors.size() == 0) + return "No error"; + return mErrors.elementAt(0); + } + /** + * called by precedent Activity runNext() for setting the activity able to be executed + * @throws InvalidDataException + * @throws ObjectAlreadyExistsException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws ObjectNotFoundException + * @throws PersistencyException + * @throws ObjectCannotBeUpdated + */ + @Override + public void run(AgentPath agent, ItemPath itemPath) throws InvalidDataException + { + Logger.debug(8, getPath() + " run " + getState()); + + if (!getActive()) setActive(true); + boolean finished = getStateMachine().getState(getState()).isFinished(); + if (finished) + { + runNext(agent, itemPath); + } + else + { + DateUtility.setToNow(mStateDate); + pushJobsToAgents(itemPath); + } + } + /** + * sets the activity available to be executed on start of Workflow or composite activity (when it is the first one of the (sub)process + * @throws InvalidDataException + * @throws ObjectAlreadyExistsException + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws PersistencyException + * @throws ObjectCannotBeUpdated + */ + @Override + public void runFirst(AgentPath agent, ItemPath itemPath) throws InvalidDataException + { + Logger.debug(8, getPath() + " runfirst"); + run(agent, itemPath); + } + /** @return the current ability to be executed */ + public boolean getActive() + { + return active; + } + /** sets the ability to be executed */ + public void setActive(boolean acti) + { + active = acti; + } + /** @return the Description field of properties */ + public String getDescription() + { + if (getProperties().containsKey("Description")) + return (String) (getProperties().get("Description")); + return "No description"; + } + public String getCurrentAgentName() + { + return (String) getProperties().get("Agent Name"); + } + public String getCurrentAgentRole() + { + return (String) getProperties().get("Agent Role"); + } + + /** + * returns the lists of jobs for the activity and children (cf org.cristalise.kernel.entity.Job) + * @throws InvalidDataException + * @throws ObjectNotFoundException + * @throws InvalidAgentPathException + */ + public ArrayList calculateJobs(AgentPath agent, ItemPath itemPath, boolean recurse) throws InvalidAgentPathException, ObjectNotFoundException, InvalidDataException + { + return calculateJobsBase(agent, itemPath, false); + } // + public ArrayList calculateAllJobs(AgentPath agent, ItemPath itemPath, boolean recurse) throws InvalidAgentPathException, ObjectNotFoundException, InvalidDataException + { + return calculateJobsBase(agent, itemPath, true); + } + private ArrayList calculateJobsBase(AgentPath agent, ItemPath itemPath, boolean includeInactive) throws ObjectNotFoundException, InvalidDataException, InvalidAgentPathException + { + Logger.msg(7, "calculateJobs - " + getPath()); + ArrayList jobs = new ArrayList(); + Map transitions; + if ((includeInactive || getActive()) && !getName().equals("domain")) { + transitions = getStateMachine().getPossibleTransitions(this, agent); + Logger.msg(7, "Activity.calculateJobs() - Got " + transitions.size() + " transitions."); + for (Transition transition : transitions.keySet()) { + Logger.msg(7, "Creating Job object for transition " + transition); + jobs.add(new Job(this, itemPath, transition, agent, transitions.get(transition))); + } + } + return jobs; + } + + + public void pushJobsToAgents(ItemPath itemPath) { + String agentRole = getCurrentAgentRole(); + if (agentRole != null && agentRole.length()>0) { + try { + RolePath myRole = Gateway.getLookup().getRolePath(agentRole); + pushJobsToAgents(itemPath, myRole); + } catch (ObjectNotFoundException ex) { // non-existent role + Logger.msg(7, "Activity.pushJobsToAgents() - Activity role '"+agentRole+" not found."); + } + } + } + + public void pushJobsToAgents(ItemPath itemPath, RolePath role) + { + if (role.hasJobList()) + new JobPusher(this, itemPath, role).start(); + Iterator childRoles = role.getChildren(); + while (childRoles.hasNext()) { + RolePath childRole = (RolePath)childRoles.next(); + pushJobsToAgents(itemPath, childRole); + } + } + + /** + * Returns the startDate. + * + * @return GTimeStamp + */ + public GTimeStamp getStateDate() + { + return mStateDate; + } + public void setStateDate(GTimeStamp startDate) + { + mStateDate = startDate; + } + + @Deprecated + public void setActiveDate(GTimeStamp date) + { } + @Deprecated + public void setStartDate(GTimeStamp date) + { + setStateDate(date); + } + + /** + * Returns the type. + * + * @return String + */ + public String getType() + { + return mType; + } /** + * Sets the type. + * + * @param type + * The type to set + */ + public void setType(String type) + { + mType = type; + } + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/AdvancementCalculator.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/AdvancementCalculator.java new file mode 100644 index 0000000..f040181 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/AdvancementCalculator.java @@ -0,0 +1,243 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +/* Created on 11 mars 2004 */ +package org.cristalise.kernel.lifecycle.instance; +import java.util.Hashtable; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.graph.model.Vertex; + +//import org.cristalise.kernel.utils.Logger; +/** @author XSeb74 */ +public class AdvancementCalculator +{ + private CompositeActivity activity; + private Hashtable isMarked; + private Hashtable HasNextMarked; + public Hashtable hasprevActive; + private long mCurrentNbActExp = 0; + private long mMaximuNbActexp = 0; + private long mNbActpassed = 0; + private long mNbActpassedWithCurrent = 0; + private long mNbActLeftWithCurrent = 0; + private long mNbActLeftWithoutCurrent = 0; + private boolean mIsbranchActive = false; + private boolean mIsbranchFinished = true; + private boolean mHasPrevActive = false; + public AdvancementCalculator() + { + isMarked = new Hashtable(); + HasNextMarked = new Hashtable(); + hasprevActive = new Hashtable(); + } + public void calculate(CompositeActivity act) throws InvalidDataException + { +// Logger.debug(0, act.getName()+" >>>>>>>>>"); + if (act instanceof Workflow) + { + calculate((CompositeActivity) act.search("workflow/domain")); + return; + } + activity = act; + Vertex v = activity.getChildGraphModel().getStartVertex(); + check(v, this); + isMarked = new Hashtable(); + calc(v, this); +// Logger.debug(0, act.getName()+" <<<<<<<<<"); + } + private void check(Vertex v, AdvancementCalculator current) + { + current.isMarked.put(v, ""); + Vertex[] nexts = current.activity.getChildGraphModel().getOutVertices(v); + for (Vertex next : nexts) + if (current.isMarked.get(next) != null) + current.HasNextMarked.put(v, next); + else + check(next, current); + int j=0; + for (Vertex next : nexts) + if (current.HasNextMarked.get(next) != null) + j++; + if (j != 0 && j==nexts.length) current.HasNextMarked.put(v, nexts[0]); + } + private void calc(Vertex v, AdvancementCalculator current) throws InvalidDataException + { + if (current.isMarked.get(v) != null && !(v instanceof Join)) + return; + if (v instanceof Activity) + { + current.isMarked.put(v, current); + Activity act = (Activity) v; + if (v instanceof CompositeActivity) + { + CompositeActivity cact = (CompositeActivity) v; + AdvancementCalculator adv = new AdvancementCalculator(); + adv.isMarked = current.isMarked; + adv.HasNextMarked = current.HasNextMarked; + adv.calculate(cact); + current.mCurrentNbActExp += adv.mCurrentNbActExp; + current.mMaximuNbActexp += adv.mMaximuNbActexp; + current.mNbActpassed += adv.mNbActpassed; + current.mNbActpassedWithCurrent += adv.mNbActpassedWithCurrent; + current.mIsbranchActive = current.mIsbranchActive || adv.mIsbranchActive || act.getActive(); + current.mNbActLeftWithCurrent += adv.mNbActLeftWithCurrent; + current.mNbActLeftWithoutCurrent += adv.mNbActLeftWithoutCurrent; + current.mHasPrevActive |= adv.mHasPrevActive || act.getActive() || adv.hasprevActive.size()!=0; + } + else + { + current.mCurrentNbActExp += 1; + current.mMaximuNbActexp += 1; + if (act.isFinished()) + { + current.mNbActpassed += 1; + current.mNbActpassedWithCurrent += 1; + } + else if (act.getActive()) + { + current.mIsbranchActive = true; + current.mIsbranchFinished = false; + current.mHasPrevActive = true; + current.mNbActpassedWithCurrent += 1; + current.mNbActLeftWithCurrent += 1; + } + else + { + current.mIsbranchFinished = false; + current.mNbActLeftWithCurrent += 1; + current.mNbActLeftWithoutCurrent += 1; + } + } + } + Vertex[] nexts = current.activity.getChildGraphModel().getOutVertices(v); + if (v instanceof Split) + { + current.isMarked.put(v, current); + AdvancementCalculator[] advs = new AdvancementCalculator[nexts.length]; + for (int i = 0; i < nexts.length; i++) + { + advs[i] = new AdvancementCalculator(); + advs[i].mHasPrevActive = current.mHasPrevActive; + advs[i].isMarked = current.isMarked; + advs[i].HasNextMarked = current.HasNextMarked; + advs[i].activity = current.activity; + if ((v instanceof Loop) && (current.HasNextMarked.get(nexts[i]) != null)) +// Logger.debug(0, v.getID() + " " + nexts[i].getID() + " HasNextMarked") + ; + else + calc(nexts[i], advs[i]); + } + long maximuNbActexp = 0; + long currentNbActExp = 0; + long NbActpassed = 0; + long NbActpassedWithCurrent = 0; + long NbActLeftWithCurrent = 0; + long NbActLeftWithoutCurrent = 0; + boolean hasNobranchFinished = true; + boolean hasNoBranchActive = true; + for (AdvancementCalculator adv : advs) { + if (adv.mIsbranchActive) + hasNoBranchActive = false; + if (adv.mIsbranchFinished) + hasNobranchFinished = false; + } + for (AdvancementCalculator adv : advs) { + + if (maximuNbActexp < adv.mMaximuNbActexp) + maximuNbActexp = adv.mMaximuNbActexp; + if (adv.mIsbranchActive || adv.mIsbranchFinished || (hasNoBranchActive && hasNobranchFinished)) + { + if (NbActpassed < adv.mNbActpassed) + NbActpassed = adv.mNbActpassed; + if (NbActpassedWithCurrent < adv.mNbActpassedWithCurrent) + NbActpassedWithCurrent = adv.mNbActpassedWithCurrent; + if (NbActLeftWithCurrent < adv.mNbActLeftWithCurrent) + NbActLeftWithCurrent = adv.mNbActLeftWithCurrent; + if (NbActLeftWithoutCurrent < adv.mNbActLeftWithoutCurrent) + NbActLeftWithoutCurrent += adv.mNbActLeftWithoutCurrent; + if (currentNbActExp < adv.mCurrentNbActExp) + currentNbActExp = adv.mCurrentNbActExp; + } + } + current.mCurrentNbActExp += currentNbActExp; + current.mNbActpassedWithCurrent += NbActpassedWithCurrent; + current.mMaximuNbActexp += maximuNbActexp; + current.mNbActpassed += NbActpassed; + current.mIsbranchActive = current.mIsbranchActive || !hasNoBranchActive; + current.mNbActLeftWithCurrent += NbActLeftWithCurrent; + current.mNbActLeftWithoutCurrent += NbActLeftWithoutCurrent; + return; + } + if (v instanceof Join) + { + AdvancementCalculator adv; + if (current.isMarked.get(v) == null) + { + adv = new AdvancementCalculator(); + adv.isMarked = current.isMarked; + adv.HasNextMarked = current.HasNextMarked; + adv.activity = current.activity; + adv.mHasPrevActive = current.mHasPrevActive; + current.isMarked.put(v, adv); + if (nexts.length == 1) + calc(nexts[0], adv); + } + else + adv = (AdvancementCalculator) current.isMarked.get(v); + current.mCurrentNbActExp += adv.mCurrentNbActExp; + current.mMaximuNbActexp += adv.mMaximuNbActexp; + current.mNbActpassed += adv.mNbActpassed; + current.mNbActpassedWithCurrent += adv.mNbActpassedWithCurrent; + current.mIsbranchActive = current.mIsbranchActive || (current.mMaximuNbActexp == 0 && adv.mIsbranchActive); + if (current.mHasPrevActive) + hasprevActive.put(String.valueOf(v.getID()), v); + current.mNbActLeftWithCurrent += adv.mNbActLeftWithCurrent; + current.mNbActLeftWithoutCurrent += adv.mNbActLeftWithoutCurrent; + return; + } + if (nexts.length != 0) + calc(nexts[0], current); + } + public long getLongestWayInAct() + { + return mMaximuNbActexp; + } + public long getCurrentLongestWayInAct() + { + return mCurrentNbActExp; + } + public long getNbActLeftWithActive() + { + return mNbActLeftWithCurrent; + } + public long getNbActLeftWithoutActive() + { + return mNbActLeftWithoutCurrent; + } + public long getNbActPassedWithoutActive() + { + return mNbActpassed; + } + public long getNbActPassedWithActive() + { + return mNbActpassedWithCurrent; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/AndSplit.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/AndSplit.java new file mode 100644 index 0000000..98e9afb --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/AndSplit.java @@ -0,0 +1,49 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; + +/** + * @version $Revision: 1.16 $ $Date: 2005/05/10 15:14:54 $ + * @author $Author: abranson $ + */ +public class AndSplit extends Split +{ + /** + * @see java.lang.Object#Object() + */ + public AndSplit() + { + super(); + } + @Override + public void runNext(AgentPath agent, ItemPath item) throws InvalidDataException + { + AdvancementCalculator adv = new AdvancementCalculator(); + adv.calculate((CompositeActivity) getParent()); + Vertex[] outVertices = getOutGraphables(); + for (Vertex outVertice : outVertices) + ((WfVertex) outVertice).run(agent, item); + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/CompositeActivity.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/CompositeActivity.java new file mode 100644 index 0000000..1bdfbe8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/CompositeActivity.java @@ -0,0 +1,469 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; + +import java.util.ArrayList; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.agent.Job; +import org.cristalise.kernel.graph.model.GraphModel; +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.graph.model.GraphableVertex; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidAgentPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.utils.Logger; + + +/** + * @version $Revision: 1.86 $ $Date: 2005/10/05 07:39:37 $ + * @author $Author: abranson $ + */ +public class CompositeActivity extends Activity +{ + + + /* + * -------------------------------------------- + * ----------------CONSTRUCTOR----------------- + * -------------------------------------------- + */ + public CompositeActivity() + { + super(); + setChildrenGraphModel(new GraphModel(new WfVertexOutlineCreator())); + setIsComposite(true); + } + + // State machine + public static final int START = 0; + public static final int COMPLETE = 1; + @Override + protected String getDefaultSMName() { + return "CompositeActivity"; + } + + @Override + public void setChildrenGraphModel(GraphModel childrenGraph) { + super.setChildrenGraphModel(childrenGraph); + childrenGraph.setVertexOutlineCreator(new WfVertexOutlineCreator()); + } + /** + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#verify() + */ + /* + * -------------------------------------------- --------------Other + * Functions--------------- -------------------------------------------- + */ + /** launch the verification of the subprocess() */ + @Override + public boolean verify() + { + boolean err = super.verify(); + GraphableVertex[] vChildren = getChildren(); + for (int i = 0; i < vChildren.length; i++) + { + if (!((WfVertex) vChildren[i]).verify()) + { + mErrors.add("error in children"); + return false; + } + } + return err; + } + + /** + * Method initChild. + * + * @param act + * @param first + * @param point + */ + /** + * Create an initialize a Activity attached to the current activity + * + * @param first : + * if true, the activity Waiting will be one of the first + * launched by the parent activity + */ + public void initChild(Activity act, boolean first, GraphPoint point) + { + this.addChild(act, new GraphPoint(point.x, point.y)); + if (first) + { + getChildrenGraphModel().setStartVertexId(act.getID()); + Logger.msg(5, "org.cristalise.kernel.lifecycle.CompositeActivity :: " + getID() + " is first"); + } + } + + /** + * Method newChild. + * + * @param Name + * @param Type + * @param point + * @return WfVertex + */ + public WfVertex newExistingChild(Activity child, String Name, GraphPoint point) + { + child.setName(Name); + addChild(child, new GraphPoint(point.x, point.y)); + return child; + } + + /** + * Method newChild. + * + * @param Name + * @param Type + * @param point + * @return WfVertex + */ + public WfVertex newChild(String Name, String Type, GraphPoint point) + { + WfVertex v = newChild(Type, point); + v.setName(Name); + return v; + } + + /** + * Method newChild. + * + * @param vertexTypeId + * @param point + * @return WfVertex + */ + public WfVertex newChild(String vertexTypeId, GraphPoint point) + { + WfVertex wfVertex = null; + if (vertexTypeId.equals("Atomic")) + { + wfVertex = newAtomChild("False id", false, point); + } else if (vertexTypeId.equals("Composite")) + { + wfVertex = newCompChild("False id", false, point); + } else if (vertexTypeId.endsWith("Split")) + { + if (vertexTypeId.startsWith("Or")) + { + wfVertex = newSplitChild("Or", point); + } else if (vertexTypeId.startsWith("XOr")) + { + wfVertex = newSplitChild("XOr", point); + } else if (vertexTypeId.startsWith("Loop")) + { + wfVertex = newSplitChild("Loop", point); + } else + { + wfVertex = newSplitChild("And", point); + } + } else if (vertexTypeId.equals("Join")) + { + wfVertex = newJoinChild(point); + } else if (vertexTypeId.equals("Route")) + { + wfVertex = newRouteChild(point); + } + return wfVertex; + } + + /** + * Method newCompChild. + * + * @param id + * @param first + * @param point + * @return CompositeActivity Create an initialize a composite Activity + * attached to the current activity + */ + public CompositeActivity newCompChild(String id, boolean first, GraphPoint point) + { + CompositeActivity act = new CompositeActivity(); + initChild(act, first, point); + act.setName(id); + return act; + } + + /** + * Method newAtomChild. + * + * @param id + * @param first + * @param point + * @return Activity Create an initialize an Atomic Activity attached to the + * current activity + * + */ + public Activity newAtomChild(String id, boolean first, GraphPoint point) + { + Activity act = new Activity(); + initChild(act, first, point); + act.setName(id); + return act; + } + + /** + * Method newSplitChild. + * + * @param Type + * @param point + * @return Split + */ + public Split newSplitChild(String Type, GraphPoint point) + { + Split split; + if (Type.equals("Or")) + { + split = new OrSplit(); + } else if (Type.equals("XOr")) + { + split = new XOrSplit(); + } else if (Type.equals("Loop")) + { + split = new Loop(); + } else + { + split = new AndSplit(); + } + addChild(split, new GraphPoint(point.x, point.y)); + return split; + } + + /** + * Method newJoinChild. + * + * @param point + * @return Join + */ + public Join newJoinChild(GraphPoint point) + { + Join join = new Join(); + join.getProperties().put("Type", "Join"); + addChild(join, new GraphPoint(point.x, point.y)); + return join; + } + + public Join newRouteChild(GraphPoint point) + { + Join join = new Join(); + join.getProperties().put("Type", "Route"); + addChild(join, new GraphPoint(point.x, point.y)); + return join; + } + + /** + * Method search. + * + * @param ids + * @return WfVertex + */ + WfVertex search(int ids) + { + for (int i = 0; i < getChildren().length; i++) + { + WfVertex ver = (WfVertex) getChildren()[i]; + if (ver instanceof Split) + { + if (ver.getID() == ids) + { + return ver; + } + } + if (ver instanceof Join) + { + if (ver.getID() == ids) + { + return ver; + } + } + } + return null; + } + + /** + * @throws InvalidDataException + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws ObjectCannotBeUpdated + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#run() + */ + @Override + public void run(AgentPath agent, ItemPath itemPath) throws InvalidDataException + { + super.run(agent, itemPath); + if (getChildrenGraphModel().getStartVertex() != null && !getStateMachine().getState(state).isFinished()) + { + WfVertex first = (WfVertex) getChildrenGraphModel().getStartVertex(); + first.run(agent, itemPath); + } + } + + @Override + public void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException + { + if (!getStateMachine().getState(state).isFinished()) + try { + request(agent, itemPath, CompositeActivity.COMPLETE, null); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + Logger.error(e); // current agent couldn't complete the composite, so leave it + } + super.runNext(agent, itemPath); + } + + + /** + * @throws InvalidDataException + * @throws ObjectNotFoundException + * @throws InvalidAgentPathException + * @see org.cristalise.kernel.lifecycle.instance.Activity#calculateJobs() + */ + @Override + public ArrayList calculateJobs(AgentPath agent, ItemPath itemPath, boolean recurse) throws InvalidAgentPathException, ObjectNotFoundException, InvalidDataException + { + ArrayList jobs = new ArrayList(); + boolean childActive = false; + if (recurse) + for (int i = 0; i < getChildren().length; i++) + if (getChildren()[i] instanceof Activity) + { + Activity child = (Activity) getChildren()[i]; + jobs.addAll(child.calculateJobs(agent, itemPath, recurse)); + childActive |= child.active; + } + if (!childActive) + jobs.addAll(super.calculateJobs(agent, itemPath, recurse)); + return jobs; + } + + @Override + public ArrayList calculateAllJobs(AgentPath agent, ItemPath itemPath, boolean recurse) throws InvalidAgentPathException, ObjectNotFoundException, InvalidDataException + { + ArrayList jobs = new ArrayList(); + if (recurse) + for (int i = 0; i < getChildren().length; i++) + if (getChildren()[i] instanceof Activity) + { + Activity child = (Activity) getChildren()[i]; + jobs.addAll(child.calculateAllJobs(agent, itemPath, recurse)); + } + jobs.addAll(super.calculateAllJobs(agent, itemPath, recurse)); + return jobs; + } + + /** + * Method addNext. + * + * @param origin + * @param terminus + * @return Next + */ + public Next addNext(WfVertex origin, WfVertex terminus) + { + return new Next(origin, terminus); + } + + /** + * Method addNext. + * + * @param originID + * @param terminusID + * @return Next + */ + public Next addNext(int originID, int terminusID) + { + Next n = new Next(); + n.setParent(this); + getChildrenGraphModel().addEdgeAndCreateId(n, originID, terminusID); + return n; + } + + /** + * Method hasGoodNumberOfActivity. + * + * @return boolean + */ + public boolean hasGoodNumberOfActivity() + { + int endingAct = 0; + for (int i = 0; i < getChildren().length; i++) + { + WfVertex vertex = (WfVertex) getChildren()[i]; + if (getChildrenGraphModel().getOutEdges(vertex).length == 0) + endingAct++; + } + if (endingAct > 1) + return false; + return true; + } + + /** + * @see org.cristalise.kernel.lifecycle.instance.Activity#getType() + */ + @Override + public String getType() + { + return super.getType(); + } + + /** + * @throws InvalidDataException + * + */ + @Override + public void reinit(int idLoop) throws InvalidDataException + { + super.reinit(idLoop); + if (getChildrenGraphModel().getStartVertex() != null && !getStateMachine().getState(state).isFinished()) + ((WfVertex) getChildrenGraphModel().getStartVertex()).reinit(idLoop); + } + + @Override + public String request(AgentPath agent, ItemPath itemPath, int transitionID, String requestData) throws AccessRightsException, InvalidTransitionException, InvalidDataException, ObjectNotFoundException, PersistencyException, ObjectAlreadyExistsException, ObjectCannotBeUpdated, CannotManageException, InvalidCollectionModification + { + if (getChildrenGraphModel().getStartVertex() != null && !getStateMachine().getState(state).isFinished() && transitionID == CompositeActivity.START) + ((WfVertex) getChildrenGraphModel().getStartVertex()).run(agent, itemPath); + + return super.request(agent, itemPath, transitionID, requestData); + } + + public void refreshJobs(ItemPath itemPath) + { + GraphableVertex[] children = getChildren(); + for (GraphableVertex element : children) + if (element instanceof CompositeActivity) + ((CompositeActivity) element).refreshJobs(itemPath); + else if (element instanceof Activity) + ((Activity) element).pushJobsToAgents(itemPath); + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/JobPusher.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/JobPusher.java new file mode 100644 index 0000000..9aeca42 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/JobPusher.java @@ -0,0 +1,81 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; + +import java.util.Iterator; + +import org.cristalise.kernel.entity.Agent; +import org.cristalise.kernel.entity.AgentHelper; +import org.cristalise.kernel.entity.agent.JobArrayList; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.Path; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +final class JobPusher extends Thread { + private final Activity activity; + private final RolePath myRole; + private final ItemPath itemPath; + + JobPusher(Activity activity, ItemPath itemPath, RolePath role) { + this.activity = activity; + this.itemPath = itemPath; + this.myRole = role; + } + + @Override + public void run() + { + Thread.currentThread().setName("Agent job pusher for "+itemPath+":"+activity.getName()+" to role "+myRole); + for (Iterator e = myRole.getChildren(); e.hasNext();) + { + AgentPath nextAgent = (AgentPath)e.next(); + Logger.msg(7, "Activity.pushJobsToAgents() - Calculating jobs for " + nextAgent); + try + { + // get joblist for user + JobArrayList jobList = new JobArrayList(this.activity.calculateJobs(nextAgent, itemPath, false)); + Logger.msg(7, "Activity.pushJobsToAgents() - User will receive " + jobList.list.size() + " jobs"); + String stringJobs = Gateway.getMarshaller().marshall(jobList); + // push it to the agent + org.omg.CORBA.Object agentIOR = nextAgent.getIOR(); + Agent thisAgent = AgentHelper.narrow(agentIOR); + Logger.msg(7, "Calling agent "+thisAgent.getSystemKey()+" from "+activity.getPath()); + thisAgent.refreshJobList(itemPath.getSystemKey(), activity.getPath(), stringJobs); + } + catch (Exception ex) + { + Logger.error( + "Agent " + + nextAgent + + " of role " + + myRole + + " could not be found to be informed of a change in " + + itemPath); + Logger.error(ex); + } + } + + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Join.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Join.java new file mode 100644 index 0000000..2d1f05c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Join.java @@ -0,0 +1,233 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; +import java.util.Vector; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.graph.traversal.GraphTraversal; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; + +/** + * @version $Revision: 1.52 $ $Date: 2005/05/10 15:14:54 $ + * @author $Author: abranson $ + */ +public class Join extends WfVertex +{ + public Vector mErrors; + /** + * @see java.lang.Object#Object() + */ + public Join() + { + super(); + mErrors = new Vector(0, 1); + } + private boolean loopTested; + public int counter = 0; + + /** + * @throws InvalidDataException + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws ObjectCannotBeUpdated + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#runNext() + */ + @Override + public void runNext(AgentPath agent, ItemPath item) throws InvalidDataException + { + AdvancementCalculator adv = new AdvancementCalculator(); + adv.calculate((CompositeActivity) getParent()); + if (adv.hasprevActive.get(String.valueOf(getID())) == null) + { + Vertex[] outVertices = getOutGraphables(); + if (outVertices.length > 0) + { + WfVertex nextAct = (WfVertex) outVertices[0]; + nextAct.run(agent, item); + } + else + super.runNext(agent, item); + } + } + /** + * Method addNext. + * + * @param idNext + */ + public void addNext(String idNext) + { + new Next(this, (WfVertex) getParent().search(idNext)); + } + /** + * @throws InvalidDataException + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#reinit(int) + */ + @Override + public void reinit(int idLoop) throws InvalidDataException + { + Vertex[] outVertices = getOutGraphables(); + if (outVertices.length == 1) + { + WfVertex nextAct = (WfVertex) outVertices[0]; + nextAct.reinit(idLoop); + } + } + + @Override + public boolean verify() + { + mErrors.removeAllElements(); + int nbOutEdges = getOutEdges().length; + int nbInEdges = getInEdges().length; + String type = (String) getProperties().get("Type"); + if (nbInEdges < 1) + { + mErrors.add("not enough previous"); + return false; + } + if (type != null && type.equals("Route")) + { + if (nbInEdges > 1) + { + mErrors.add("Bad nb of previous"); + return false; + } + } + if (nbOutEdges > 1) + { + mErrors.add("too many next"); + return false; + } + if (nbOutEdges == 0) + { + if (!((CompositeActivity) getParent()).hasGoodNumberOfActivity()) + { + mErrors.add("too many endpoints"); + return false; + } + } + Vertex[] outV = getOutGraphables(); + Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false); + boolean loop = false; + boolean errInLoop = false; + for (int i = 0; i < outV.length; i++) + { + for (int j = 0; j < anteVertices.length; j++) + if (!loop && outV[i].getID() == anteVertices[j].getID()) + { + if (outV[i] instanceof Loop) + { + loop = true; + j = anteVertices.length; + i = outV.length; + } + else + { + errInLoop = true; + } + } + } + if (errInLoop && loop) + { + mErrors.add("Problem in Loop"); + return false; + } + return true; + } + /** + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#getErrors() + */ + @Override + public String getErrors() + { + if (mErrors.size() == 0) + return "No error"; + else + return mErrors.elementAt(0); + } + /** + * @throws InvalidDataException + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws ObjectCannotBeUpdated + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#run() + */ + @Override + public void run(AgentPath agent, ItemPath item) throws InvalidDataException + { + runNext(agent, item); + } + /** + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#addNext(org.cristalise.kernel.lifecycle.instance.WfVertex) + */ + @Override + public Next addNext(WfVertex vertex) + { + return new Next(this, vertex); + } + /** + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#loop() + */ + @Override + public boolean loop() + { + boolean loop2 = false; + if (!loopTested) + { + loopTested = true; + if (getOutGraphables().length != 0) + loop2 = ((WfVertex) getOutGraphables()[0]).loop(); + } + else + loop2 = true; + loopTested = false; + return loop2; + } + @Override + public void runFirst(AgentPath agent, ItemPath item) throws InvalidDataException + { + runNext(agent, item); + } + /* + * (non-Javadoc) + * + * @see org.cristalise.kernel.graph.model.Vertex#isJoin() + */ + @Override + public boolean isJoin() + { + return true; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Loop.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Loop.java new file mode 100644 index 0000000..d6a660e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Loop.java @@ -0,0 +1,130 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.graph.traversal.GraphTraversal; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.utils.Logger; + +/** + * @version $Revision: 1.35 $ $Date: 2005/05/10 15:14:54 $ + * @author $Author: abranson $ + */ +public class Loop extends XOrSplit +{ + /** + * @see java.lang.Object#Object() + */ + public Loop() + { + super(); + } + /** + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#loop() + */ + @Override + public boolean loop() + { + return true; + } + @Override + public void followNext(Next activeNext, AgentPath agent, ItemPath itemPath) throws InvalidDataException + { + WfVertex v = activeNext.getTerminusVertex(); + if (!isInPrev(v)) + v.run(agent, itemPath); + else + { + v.reinit(getID()); + v.run(agent, itemPath); + } + } + /** + * @throws InvalidDataException + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#reinit(int) + */ + @Override + public void reinit(int idLoop) throws InvalidDataException + { + Logger.msg(8, "Loop.reinit"); + if (idLoop == getID()) + return; + else + { + Vertex[] outVertices = getOutGraphables(); + for (int j = 0; j < outVertices.length; j++) + { + if (!isInPrev(outVertices[j])) + ((WfVertex) outVertices[j]).reinit(idLoop); + } + } + } + /** + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#verify() + */ + @Override + public boolean verify() + { + boolean err = super.verify(); + Vertex[] nexts = getOutGraphables(); + Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false); + int k = 0; + int l = 0; + Vertex[] brothers = getParent().getChildren(); + for (Vertex brother : brothers) + if (brother instanceof Loop) + l++; + for (Vertex next : nexts) { + for (Vertex anteVertice : anteVertices) + if (next.getID() == anteVertice.getID()) + k++; + } + if (k != 1 && !(l > 1)) + { + mErrors.add("bad number of pointing back nexts"); + return false; + } + // if (nexts.length>2) { + // mErrors.add("you must only have 2 nexts"); + // return false; + // } + return err; + } + private boolean isInPrev(Vertex vertex) + { + int id = vertex.getID(); + Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false); + for (Vertex anteVertice : anteVertices) { + if (anteVertice.getID() == id) + { + return true; + } + } + return false; + } + @Override + public boolean isLoop() + { + return true; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Next.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Next.java new file mode 100644 index 0000000..e0df1e6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Next.java @@ -0,0 +1,103 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; + +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.graph.model.GraphableEdge; + +/** + * @version $Revision: 1.58 $ $Date: 2005/05/10 15:14:54 $ + * @author $Author: abranson $ + */ +/** this class represents the link between 2 successive activities */ +public class Next extends GraphableEdge +{ + /** + * @see java.lang.Object#Object() + */ + public Next() + { + super(); + } + + /** + * Method Next. + * @param pre + * @param nex + */ + /** create and initialize a link between an Activities */ + public Next(WfVertex pre, WfVertex nex) + { + super(pre, nex); + getProperties().put("Alias",""); + getProperties().put("Type","Straight"); + } + + /** + * Method verify. + * @return boolean + */ + public boolean verify() + { + return true; + } + public WfVertex getTerminusVertex() + { + return (WfVertex)((CompositeActivity)getParent()).getWf().search(getParent().getPath()+"/"+this.getTerminusVertexId()); + } + @Override + public boolean containsPoint(GraphPoint p) + { + GraphPoint originPoint = getOriginPoint(); + GraphPoint terminusPoint = getTerminusPoint(); + GraphPoint midPoint = new GraphPoint(); + + if (("Broken +".equals(getProperties().get("Type")))) + { + midPoint.x = (originPoint.x + terminusPoint.x) / 2; + midPoint.y = (originPoint.y + terminusPoint.y) / 2; + } + else if (("Broken -".equals(getProperties().get("Type")))) + { + boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60); + midPoint.x = arrowOnY ? terminusPoint.x : (originPoint.x + terminusPoint.x) / 2; + midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : originPoint.y; + } + else if (("Broken |".equals(getProperties().get("Type")))) + { + boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60); + midPoint.x = arrowOnY ? originPoint.x : (originPoint.x + terminusPoint.x) / 2; + midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : terminusPoint.y; + } + else + { + midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x) / 2; + midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y) / 2; + } + + int minX = midPoint.x - 10; + int minY = midPoint.y - 10; + int maxX = midPoint.x + 10; + int maxY = midPoint.y + 10; + + return (p.x >= minX) && (p.x <= maxX) && (p.y >= minY) && (p.y <= maxY); + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/OrSplit.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/OrSplit.java new file mode 100644 index 0000000..12c7f46 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/OrSplit.java @@ -0,0 +1,90 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; +import java.util.StringTokenizer; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.graph.model.DirectedEdge; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.scripting.ScriptingEngineException; +import org.cristalise.kernel.utils.Logger; + +/** + * @version $Revision: 1.22 $ $Date: 2005/05/10 15:14:54 $ + * @author $Author: abranson $ + */ +public class OrSplit extends Split +{ + /** + * @see java.lang.Object#Object() + */ + public OrSplit() + { + super(); + } + @Override + public void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException + { + String nexts; + String scriptName = (String) getProperties().get("RoutingScriptName"); + Integer scriptVersion = getVersionNumberProperty("RoutingScriptVersion"); + try { + nexts = this.evaluateScript(scriptName, scriptVersion, itemPath).toString(); + } catch (ScriptingEngineException e) { + Logger.error(e); + throw new InvalidDataException("Error running routing script "+scriptName+" v"+scriptVersion); + } + StringTokenizer tok = new StringTokenizer(nexts, ","); + Logger.msg(7, tok.countTokens() + " nexts to activate:" + nexts); + int active = 0; + try + { + DirectedEdge[] outEdges = getOutEdges(); + AdvancementCalculator adv = new AdvancementCalculator(); + adv.calculate((CompositeActivity)getParent()); + while (tok.hasMoreTokens()) + { + String thisNext = tok.nextToken(); + Logger.msg(7, "Finding next " + thisNext); + for (DirectedEdge outEdge : outEdges) { + Next nextEdge = (Next) outEdge; + if (thisNext != null && thisNext.equals(nextEdge.getProperties().get("Alias"))) + { + WfVertex term = nextEdge.getTerminusVertex(); + term.run(agent, itemPath); + Logger.msg(7, "Running " + nextEdge.getProperties().get("Alias")); + active++; + } + } + } + // if no active nexts throw exception + } + catch (Exception e) + { + Logger.error(e); + } + if (active == 0) + throw new InvalidDataException("No nexts were activated!"); + } + + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Split.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Split.java new file mode 100644 index 0000000..ac3afbd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Split.java @@ -0,0 +1,239 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; + +import java.util.Vector; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.graph.traversal.GraphTraversal; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; + + +/** + * @version $Revision: 1.47 $ $Date: 2006/05/29 13:17:45 $ + * @author $Author: abranson $ + */ +public abstract class Split extends WfVertex +{ + public Vector mErrors; + + /** + * @see java.lang.Object#Object() + */ + public Split() + { + mErrors = new Vector(0, 1); + getProperties().put("RoutingScriptName", ""); + getProperties().put("RoutingScriptVersion", ""); + } + + private boolean loopTested; + + /** + * @throws InvalidDataException + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws ObjectCannotBeUpdated + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#runNext() + */ + @Override + public abstract void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException; + + /** + * Method addNext. + * + * @param idNext + */ + void addNext(String idNext) + { + new Next(this, (WfVertex) getParent().search(idNext)); + } + + /** + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#addNext(org.cristalise.kernel.lifecycle.instance.WfVertex) + */ + @Override + public Next addNext(WfVertex vertex) + { + Next nxt = new Next(this, vertex); + int num = getOutGraphables().length; + try + { + num = Integer.parseInt((String) getProperties().get("LastNum")); + } catch (Exception e) + { + } + nxt.getProperties().put("Alias", String.valueOf(num)); + getProperties().put("LastNum", String.valueOf(num + 1)); + return nxt; + } + + @Override + public void reinit(int idLoop) throws InvalidDataException + { + Vertex[] outVertices = getOutGraphables(); + for (Vertex outVertice : outVertices) + ((WfVertex) outVertice).reinit(idLoop); + } + + /** + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#verify() + */ + @Override + public boolean verify() + { + mErrors.removeAllElements(); + int nbInEdgres = getParent().getChildrenGraphModel().getInEdges(this).length; + if (nbInEdgres == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId()) + { + mErrors.add("not enough previous"); + return false; + } + if (nbInEdgres > 1) + { + mErrors.add("Bad nb of previous"); + return false; + } + if (getOutEdges().length <= 1 && !(this instanceof Loop)) + { + mErrors.add("not enough next"); + return false; + } + if (!(this instanceof Loop)) + { + Vertex[] outV = getOutGraphables(); + Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false); + boolean loop = false; + boolean errInLoop = true; + for (int i = 0; i < outV.length; i++) + { + for (int j = 0; j < anteVertices.length; j++) + if (!loop && outV[i].getID() == anteVertices[j].getID()) + { + if (outV[i] instanceof Loop) + { + loop = true; + j = anteVertices.length; + i = outV.length; + } else + { + errInLoop = false; + } + } + } + if (errInLoop && loop) + { + mErrors.add("Problem in Loop"); + return false; + } + } + return true; + } + + /** + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#getErrors() + */ + @Override + public String getErrors() + { + if (mErrors.size() == 0) + return "No error"; + else + return mErrors.elementAt(0); + } + + /** + * @throws InvalidDataException + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws ObjectCannotBeUpdated + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#run() + */ + @Override + public void run(AgentPath agent, ItemPath itemPath) throws InvalidDataException + { + runNext(agent, itemPath); + } + + /** + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#loop() + */ + @Override + public boolean loop() + { + boolean loop2 = false; + if (!loopTested) + { + loopTested = true; + if (getOutGraphables().length != 0) + { + Vertex[] outVertices = getOutGraphables(); + for (int i = 0; i < outVertices.length; i++) + { + WfVertex tmp = (WfVertex) getOutGraphables()[i]; + loop2 = loop2 || tmp.loop(); + } + } + } + loopTested = false; + return loop2; + } + + public String[] nextNames() + { + Vertex[] vs = getOutGraphables(); + String[] result = new String[vs.length]; + for (int i = 0; i < vs.length; i++) + result[i] = vs[i].getName(); + return result; + } + + protected boolean isInTable(String test, String[] list) + { + if (test == null) + return false; + for (String element : list) + if (test.equals(element)) + return true; + return false; + } + + @Override + public void runFirst(AgentPath agent, ItemPath itemPath) throws InvalidDataException + { + runNext(agent, itemPath); + } + +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertex.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertex.java new file mode 100644 index 0000000..d241aca --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertex.java @@ -0,0 +1,223 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; + + + +import java.util.HashMap; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.graph.model.GraphableVertex; +import org.cristalise.kernel.lifecycle.routingHelpers.ViewpointDataHelper; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.scripting.Script; +import org.cristalise.kernel.scripting.ScriptingEngineException; +import org.cristalise.kernel.utils.KeyValuePair; +import org.cristalise.kernel.utils.Logger; + + +/** + * @version $Revision: 1.38 $ $Date: 2005/09/07 13:46:31 $ + * @author $Author: abranson $ + */ +public abstract class WfVertex extends GraphableVertex +{ + /**sets the activity available to be executed on start of Workflow or composite activity (when it is the first one of the + * (sub)process + * @throws InvalidDataException + * @throws ObjectAlreadyExistsException + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws PersistencyException + * @throws ObjectCannotBeUpdated */ + public abstract void runFirst(AgentPath agent, ItemPath itemPath) throws InvalidDataException; + + /** + * @see java.lang.Object#Object() + */ + public WfVertex() + { + super(); + setIsLayoutable(true); + setIsComposite(false); + } + + /** + * Method runNext. + * @throws InvalidDataException + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws ObjectCannotBeUpdated + */ + public void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException + { + try + { + ((CompositeActivity)getParent()).request(agent, itemPath, CompositeActivity.COMPLETE, null); + } + catch (Exception e) + { + //Logger.error(e); + } + + } + + /** + * Method reinit. + * @param idLoop + * @throws InvalidDataException + * @throws ObjectNotFoundException + */ + public abstract void reinit( int idLoop ) throws InvalidDataException; + + /** + * Method verify. + * @return boolean + */ + public abstract boolean verify(); + + /** + * Method getErrors. + * @return String + */ + public abstract String getErrors(); + + /** + * Method run. + * @throws InvalidDataException + * @throws ObjectAlreadyExistsException + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws PersistencyException + * @throws ObjectCannotBeUpdated + */ + public abstract void run(AgentPath agent, ItemPath itemPath) throws InvalidDataException; + + /** + * Method loop. + * @return boolean + */ + public abstract boolean loop(); + + /** + * Method addNext. + * @param vertex + */ + public abstract Next addNext(WfVertex vertex); + + protected Object evaluateScript(String scriptName, Integer scriptVersion, ItemPath itemPath) throws ScriptingEngineException + { + + try + { + Script script = getScript(scriptName, scriptVersion); + + KeyValuePair[] k = getProperties().getKeyValuePairs(); + HashMap requiredInput = script.getAllInputParams(); + for (KeyValuePair element : k) { + if (requiredInput.containsKey(element.getKey())) + { + String value = element.getStringValue(); + Object inputParam = value; + + if (value.startsWith("viewpoint//")) + { + value = value.substring(11); + if (value.startsWith(".")) + value = itemPath.getUUID() + value.substring(1); + try { + inputParam = ViewpointDataHelper.get(value)[0]; + } catch (ArrayIndexOutOfBoundsException ex) { + throw new InvalidDataException("Could not retrieve data from viewpoint: "+value); + } + } + if (value.startsWith("property//")) + { + value = value.substring(10); + try { + inputParam = Gateway.getStorage().get(itemPath, ClusterStorage.PROPERTY+"/"+value, null); + } catch (ObjectNotFoundException ex) { + inputParam = null; + } + } + Logger.msg(5, "Split.evaluateScript() - Setting param " + element.getKey() + " to " + inputParam); + script.setInputParamValue(element.getKey(), inputParam); + } + } + + //TODO: is this right? + if (requiredInput.containsKey("item")) { + script.setInputParamValue("item", Gateway.getProxyManager().getProxy(itemPath)); + } + if (requiredInput.containsKey("agent")) { + AgentPath systemAgent = Gateway.getLookup().getAgentPath("system"); + script.setInputParamValue("agent", Gateway.getProxyManager().getProxy(systemAgent)); + } + Object retVal = script.execute(); + Logger.msg(2, "Split.evaluateScript() - Script returned "+retVal); + if (retVal == null) retVal = ""; + return retVal; + } + catch (Exception e) + { + Logger.msg(1, "Split.evaluateScript() - Error: Script " + scriptName); + Logger.error(e); + throw new ScriptingEngineException(); + } + } + + private static Script getScript(String name, Integer version) throws ScriptingEngineException + { + if (name == null || name.length() == 0) + throw new ScriptingEngineException("Script name is empty"); + Script script; + if (version!=null) { + script = new Script(name, version); + } + else { // empty version: try expression + int split = name.indexOf(":"); + script = new Script(name.substring(0, split), name.substring(split + 1)); + } + + return script; + } + + + public Workflow getWf() + { + return ((CompositeActivity)getParent()).getWf(); + } +} + diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertexOutlineCreator.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertexOutlineCreator.java new file mode 100644 index 0000000..286ba64 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertexOutlineCreator.java @@ -0,0 +1,69 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; + +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.graph.model.Vertex; +import org.cristalise.kernel.graph.model.VertexOutlineCreator; + +public class WfVertexOutlineCreator implements VertexOutlineCreator +{ + private static final int mActivityWidth = 130; + private static final int mActivityHeight = 60; + private static final int mSplitJoinWidth = 60; + private static final int mSplitJoinHeight = 25; + + @Override + public void setOutline(Vertex vertex) + { + GraphPoint centrePoint = vertex.getCentrePoint(); + GraphPoint[] outlinePoints = new GraphPoint[ 4 ]; + int vertexWidth = 0; + int vertexHeight = 0; + + if(vertex instanceof Activity) + { + vertexWidth = mActivityWidth; + vertexHeight = mActivityHeight; + } + else + { + vertexWidth = mSplitJoinWidth; + vertexHeight = mSplitJoinHeight; + } + + outlinePoints[ 0 ] = new GraphPoint(); + outlinePoints[ 0 ].x = centrePoint.x - vertexWidth / 2; + outlinePoints[ 0 ].y = centrePoint.y - vertexHeight / 2; + outlinePoints[ 1 ] = new GraphPoint(); + outlinePoints[ 1 ].x = centrePoint.x + vertexWidth / 2; + outlinePoints[ 1 ].y = centrePoint.y - vertexHeight / 2; + outlinePoints[ 2 ] = new GraphPoint(); + outlinePoints[ 2 ].x = centrePoint.x + vertexWidth / 2; + outlinePoints[ 2 ].y = centrePoint.y + vertexHeight / 2; + outlinePoints[ 3 ] = new GraphPoint(); + outlinePoints[ 3 ].x = centrePoint.x - vertexWidth / 2; + outlinePoints[ 3 ].y = centrePoint.y + vertexHeight / 2; + + vertex.setOutlinePoints( outlinePoints ); + } +} + diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Workflow.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Workflow.java new file mode 100644 index 0000000..c2f632a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Workflow.java @@ -0,0 +1,266 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; +import java.util.ArrayList; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.agent.Job; +import org.cristalise.kernel.events.History; +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.graph.model.TypeNameAndConstructionInfo; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidAgentPathException; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.utils.Language; +import org.cristalise.kernel.utils.Logger; + +/** + * @version $Revision: 1.64 $ $Date: 2005/09/30 07:09:48 $ + * @author $Author: abranson $ + */ +public class Workflow extends CompositeActivity implements C2KLocalObject +{ + public History history; + private ItemPath itemPath = null; + + /** TypeNameAndConstructionInfo[] variables added by Steve */ + private final TypeNameAndConstructionInfo[] mVertexTypeNameAndConstructionInfo = + { + new TypeNameAndConstructionInfo(Language.translate("AND Split"), "AndSplit"), + new TypeNameAndConstructionInfo(Language.translate("OR Split"), "OrSplit"), + new TypeNameAndConstructionInfo(Language.translate("XOR Split"), "XOrSplit"), + new TypeNameAndConstructionInfo(Language.translate("Join"), "Join"), + new TypeNameAndConstructionInfo(Language.translate("Loop"), "LoopSplit"), + new TypeNameAndConstructionInfo(Language.translate("Activity"), "Atomic"), + new TypeNameAndConstructionInfo(Language.translate("Composite"), "Composite") + }; + private final TypeNameAndConstructionInfo[] mEdgeTypeNameAndConstructionInfo = + { + new TypeNameAndConstructionInfo(Language.translate("Next"), "Next") + }; + /** + * @see java.lang.Object#Object() + */ + public Workflow() + { + } + + public Workflow(CompositeActivity domain, PredefinedStepContainer predef) { + this(); + domain.setName("domain"); + initChild(domain, true, new GraphPoint(150, 100)); + addChild(predef, new GraphPoint(300, 100)); + } + + public History getHistory() throws InvalidDataException { + if (history == null) { + if (itemPath == null) + throw new InvalidDataException("Workflow not initialized."); + history = new History(itemPath, this); + } + return history; + } + + /** + * Method getVertexTypeNameAndConstructionInfo. + * + * @return TypeNameAndConstructionInfo[] + */ + /** getVertexTypeNameAndConstructionInfo() added by Steve */ + public TypeNameAndConstructionInfo[] getVertexTypeNameAndConstructionInfo() + { + return mVertexTypeNameAndConstructionInfo; + } + /** + * Method getEdgeTypeNameAndConstructionInfo. + * + * @return TypeNameAndConstructionInfo[] + */ + /** getVertexTypeNameAndConstructionInfo() added by Steve */ + public TypeNameAndConstructionInfo[] getEdgeTypeNameAndConstructionInfo() + { + return mEdgeTypeNameAndConstructionInfo; + } + /** + * Method requestAction. + * + * @param agentInfo + * @param stepPath + * @param transitionID + * @param reguestData + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws InvalidDataException + * @throws PersistencyException + * @throws ObjectCannotBeUpdated + * @throws CannotManageException + * @throws InvalidCollectionModification + */ + //requestData is xmlstring + public String requestAction(AgentPath agent, String stepPath, ItemPath itemPath, int transitionID, String requestData) + throws ObjectNotFoundException, AccessRightsException, InvalidTransitionException, InvalidDataException, ObjectAlreadyExistsException, PersistencyException, ObjectCannotBeUpdated, CannotManageException, InvalidCollectionModification + { + Logger.msg(3, "Action: " + transitionID + " " + stepPath + " by " + agent); + if (search(stepPath) != null) + return ((Activity) search(stepPath)).request(agent, itemPath, transitionID, requestData); + else + throw new ObjectNotFoundException(stepPath + " not found"); + } + + /** + * @see org.cristalise.kernel.graph.model.GraphableVertex#getPath() + */ + @Override + public String getPath() + { + return "workflow"; + } + /** + * @see org.cristalise.kernel.graph.model.Vertex#getName() + */ + @Override + public String getName() + { + return "workflow"; + } + /** + * @see org.cristalise.kernel.lifecycle.instance.Activity#getType() + */ + @Override + public String getType() + { + return "workflow"; + } + /** + * @see org.cristalise.kernel.graph.model.Vertex#setName(java.lang.String) + */ + @Override + public void setName(String name) + { + } + /** + * @see org.cristalise.kernel.lifecycle.instance.WfVertex#verify() + */ + @Override + public boolean verify() + { + for (int i = 0; i < getChildren().length; i++) + { + if (!((WfVertex) getChildren()[i]).verify()) + { + mErrors.add("error in children"); + return false; + } + } + return true; + } + /** + * @see org.cristalise.kernel.lifecycle.instance.Activity#getWf() + */ + @Override + public Workflow getWf() + { + return this; + } + /** + * Method initialise. + * + * @param systemKey + * @throws InvalidDataException + * @throws ObjectNotFoundException + * @throws AccessRightsException + * @throws InvalidTransitionException + * @throws ObjectAlreadyExistsException + * @throws ObjectCannotBeUpdated + */ + public void initialise(ItemPath itemPath, AgentPath agent) throws InvalidDataException + { + setItemPath(itemPath); + runFirst(agent, itemPath); + } + + public ItemPath getItemPath() { + return itemPath; + } + + public void setItemPath(ItemPath itemPath) { + this.itemPath = itemPath; + } + + public void setItemUUID( String uuid ) throws InvalidItemPathException + { + setItemPath(new ItemPath(uuid)); + } + + public String getItemUUID() { + return getItemPath().getUUID().toString(); + } + + /** + * if type = 0 only domain steps will be queried if type = 1 only predefined steps will be queried else both will be queried + * @param agent + * @param itemSysKey + * @param type + * @return + * @throws ObjectNotFoundException + * @throws InvalidDataException + * @throws InvalidAgentPathException + */ + public ArrayList calculateJobs(AgentPath agent, ItemPath itemPath, int type) throws InvalidAgentPathException, ObjectNotFoundException, InvalidDataException + { + ArrayList jobs = new ArrayList(); + if (type != 1) + jobs.addAll(((CompositeActivity) search("workflow/domain")).calculateJobs(agent, itemPath, true)); + if (type != 0) + jobs.addAll(((CompositeActivity) search("workflow/predefined")).calculateJobs(agent, itemPath, true)); + return jobs; + } + /** + * @see org.cristalise.kernel.lifecycle.instance.CompositeActivity#hasGoodNumberOfActivity() + */ + @Override + public boolean hasGoodNumberOfActivity() + { + return true; + } + /** + * @see org.cristalise.kernel.entity.C2KLocalObject#getClusterType() + */ + @Override + public String getClusterType() + { + return ClusterStorage.LIFECYCLE; + } + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/XOrSplit.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/XOrSplit.java new file mode 100644 index 0000000..91719cd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/XOrSplit.java @@ -0,0 +1,84 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance; + +import java.util.ArrayList; +import java.util.StringTokenizer; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.graph.model.DirectedEdge; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.scripting.ScriptingEngineException; +import org.cristalise.kernel.utils.Logger; + + +/** + * @version $Revision: 1.23 $ $Date: 2006/03/03 13:52:21 $ + * @author $Author: abranson $ + */ +public class XOrSplit extends Split +{ + /** + * @see java.lang.Object#Object() + */ + public XOrSplit() + { + super(); + } + + @Override + public void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException + { + ArrayList nextsToFollow = new ArrayList(); + String nexts; + String scriptName = (String) getProperties().get("RoutingScriptName"); + Integer scriptVersion = getVersionNumberProperty("RoutingScriptVersion"); + try { + nexts = this.evaluateScript(scriptName, scriptVersion, itemPath).toString(); + } catch (ScriptingEngineException e) { + Logger.error(e); + throw new InvalidDataException("Error running routing script "+scriptName+" v"+scriptVersion); + } + + StringTokenizer tok = new StringTokenizer(nexts,","); + String[] nextsTab = new String[tok.countTokens()]; + for (int i=0;i 2) + props = (CastorHashMap)Gateway.getMarshaller().unmarshall(params[2]); + + } catch (Exception e) { + throw new InvalidDataException("AddMemberToCollection: Invalid parameters "+Arrays.toString(params)); + } + + // load collection + C2KLocalObject collObj; + collObj = Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null); + if (!(collObj instanceof Dependency)) throw new InvalidDataException("AddMemberToCollection: AddMemberToCollection operates on Dependency collections only."); + dep = (Dependency)collObj; + + // find member and assign entity + if (props == null) + dep.addMember(newChild); + else + dep.addMember(newChild, props, null); + + Gateway.getStorage().put(newChild, dep, null); + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewCollectionDescription.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewCollectionDescription.java new file mode 100644 index 0000000..b230284 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewCollectionDescription.java @@ -0,0 +1,110 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + + +import java.util.Arrays; + +import org.cristalise.kernel.collection.AggregationDescription; +import org.cristalise.kernel.collection.CollectionDescription; +import org.cristalise.kernel.collection.DependencyDescription; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $ + * @version $Revision: 1.8 $ + **************************************************************************/ +public class AddNewCollectionDescription extends PredefinedStep +{ + /************************************************************************** + * Constructor for Castor + **************************************************************************/ + public AddNewCollectionDescription() + { + super(); + } + + + /** + * Generates a new empty collection description. Collection instances should + * be added by an Admin, who can do so using AddC2KObject. + * + * Params: + * 0 - collection name + * 1 - collection type (Aggregation, Dependency) + * @throws PersistencyException + */ + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectAlreadyExistsException, PersistencyException { + + String collName; + String collType; + + // extract parameters + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "AddNewCollectionDescription: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + if (params.length != 2) + throw new InvalidDataException("AddNewCollectionDescription: Invalid parameters "+Arrays.toString(params)); + + collName = params[0]; + collType = params[1]; + + // check if collection already exists + try { + Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null); + throw new ObjectAlreadyExistsException("Collection '"+collName+"' already exists"); + } catch (ObjectNotFoundException ex) { + // collection doesn't exist + } catch (PersistencyException ex) { + Logger.error(ex); + throw new PersistencyException("AddNewCollectionDescription: Error checking for collection '"+collName+"': "+ex.getMessage()); + } + + + CollectionDescription newCollDesc; + + if (collType.equals("Aggregation")) + newCollDesc = new AggregationDescription(collName); + if (collType.equals("Dependency")) + newCollDesc = new DependencyDescription(collName); + else + throw new InvalidDataException("AddNewCollectionDescription: Invalid collection type specified: '"+collType+"'. Must be Aggregation or Dependency."); + + // store it + try { + Gateway.getStorage().put(item, newCollDesc, null); + } catch (PersistencyException e) { + throw new PersistencyException("AddNewCollectionDescription: Error saving new collection '"+collName+"': "+e.getMessage()); + } + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewSlot.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewSlot.java new file mode 100644 index 0000000..f3acdf3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewSlot.java @@ -0,0 +1,128 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + + +import java.util.Arrays; + +import org.cristalise.kernel.collection.Aggregation; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.PropertyDescription; +import org.cristalise.kernel.property.PropertyDescriptionList; +import org.cristalise.kernel.property.PropertyUtility; +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $ + * @version $Revision: 1.8 $ + **************************************************************************/ +public class AddNewSlot extends PredefinedStep +{ + /************************************************************************** + * Constructor for Castor + **************************************************************************/ + public AddNewSlot() + { + super(); + } + + + /** + * Creates a new slot in the given aggregation, that holds instances of the given item description + * + * Params: + *
    1. Collection name
    2. + *
    3. Item Description key (optional)
    4. + *
    5. Item Description version (optional)
    6. + *
    + * + * @throws InvalidDataException Then the parameters were incorrect + * @throws PersistencyException There was a problem loading or saving the collection from persistency + * @throws ObjectNotFoundException A required object, such as the collection or a PropertyDescription outcome, wasn't found + */ + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, PersistencyException, ObjectNotFoundException { + + String collName; + ItemPath descKey = null; + String descVer = "last"; + Aggregation agg; + + // extract parameters + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "AddNewSlot: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + + // resolve desc item path and version + try { + collName = params[0]; + if (params.length > 1 && params[1].length() > 0) descKey = new ItemPath(params[1]); + if (params.length > 2 && params[2].length() > 0) descVer = params[2]; + } catch (Exception e) { + throw new InvalidDataException("AddNewSlot: Invalid parameters "+Arrays.toString(params)); + } + + // load collection + C2KLocalObject collObj; + try { + collObj = Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null); + } catch (PersistencyException ex) { + Logger.error(ex); + throw new PersistencyException("AddNewSlot: Error loading collection '\"+collName+\"': "+ex.getMessage()); + } + if (!(collObj instanceof Aggregation)) throw new InvalidDataException("AddNewSlot: AddNewSlot operates on Aggregation collections only."); + agg = (Aggregation)collObj; + + // get props + CastorHashMap props = new CastorHashMap(); + StringBuffer classProps = new StringBuffer(); + if (descKey != null) { + PropertyDescriptionList propList; + propList = PropertyUtility.getPropertyDescriptionOutcome(descKey, descVer); + for (PropertyDescription pd : propList.list) { + props.put(pd.getName(), pd.getDefaultValue()); + if (pd.getIsClassIdentifier()) + classProps.append((classProps.length()>0?",":"")).append(pd.getName()); + } + } + + agg.addSlot(props, classProps.toString()); + + try { + Gateway.getStorage().put(item, agg, null); + } catch (PersistencyException e) { + Logger.error(e); + throw new PersistencyException("AddNewSlot: Error saving collection '"+collName+"': "+e.getMessage()); + } + + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AssignItemToSlot.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AssignItemToSlot.java new file mode 100644 index 0000000..c242500 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AssignItemToSlot.java @@ -0,0 +1,121 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + + +import java.util.Arrays; + +import org.cristalise.kernel.collection.Aggregation; +import org.cristalise.kernel.collection.AggregationMember; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $ + * @version $Revision: 1.8 $ + **************************************************************************/ +public class AssignItemToSlot extends PredefinedStep +{ + /************************************************************************** + * Constructor for Castor + **************************************************************************/ + public AssignItemToSlot() + { + super(); + } + + + /** + * Params: + * 0 - collection name + * 1 - slot number + * 2 - target entity key + * @throws ObjectNotFoundException + * @throws PersistencyException + * @throws ObjectCannotBeUpdated + * @throws InvalidCollectionModification + */ + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, PersistencyException, ObjectCannotBeUpdated, InvalidCollectionModification { + + String collName; + int slotNo; + ItemPath childItem; + Aggregation agg; + + // extract parameters + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "AssignItemToSlot: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + + try { + collName = params[0]; + slotNo = Integer.parseInt(params[1]); + childItem = new ItemPath(params[2]); + } catch (Exception e) { + throw new InvalidDataException("AssignItemToSlot: Invalid parameters "+Arrays.toString(params)); + } + + // load collection + C2KLocalObject collObj; + try { + collObj = Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null); + } catch (PersistencyException ex) { + Logger.error(ex); + throw new PersistencyException("AssignItemToSlot: Error loading collection '\"+collName+\"': "+ex.getMessage()); + } + if (!(collObj instanceof Aggregation)) throw new InvalidDataException("AssignItemToSlot: AssignItemToSlot operates on Aggregation collections only."); + agg = (Aggregation)collObj; + + // find member and assign entity + boolean stored = false; + for (AggregationMember member : agg.getMembers().list) { + if (member.getID() == slotNo) { + if (member.getItemPath() != null) + throw new ObjectCannotBeUpdated("AssignItemToSlot: Member slot "+slotNo+" not empty"); + member.assignItem(childItem); + stored = true; + break; + } + } + if (!stored) { + throw new ObjectNotFoundException("AssignItemToSlot: Member slot "+slotNo+" not found."); + } + + try { + Gateway.getStorage().put(item, agg, null); + } catch (PersistencyException e) { + throw new PersistencyException("AssignItemToSlot: Error saving collection '"+collName+"': "+e.getMessage()); + } + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ClearSlot.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ClearSlot.java new file mode 100644 index 0000000..bd0fa19 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ClearSlot.java @@ -0,0 +1,114 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + + +import java.util.Arrays; + +import org.cristalise.kernel.collection.Aggregation; +import org.cristalise.kernel.collection.AggregationMember; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $ + * @version $Revision: 1.8 $ + **************************************************************************/ +public class ClearSlot extends PredefinedStep +{ + /************************************************************************** + * Constructor for Castor + **************************************************************************/ + public ClearSlot() + { + super(); + } + + + /** + * Params: + * 0 - collection name + * 1 - slot number + * @throws ObjectNotFoundException + * @throws PersistencyException + * @throws ObjectCannotBeUpdated + */ + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, PersistencyException, ObjectCannotBeUpdated { + + String collName; + int slotNo; + Aggregation agg; + + // extract parameters + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "ClearSlot: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + + try { + collName = params[0]; + slotNo = Integer.parseInt(params[1]); + } catch (Exception e) { + throw new InvalidDataException("ClearSlot: Invalid parameters "+Arrays.toString(params)); + } + + // load collection + try { + agg = (Aggregation)Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null); + } catch (PersistencyException ex) { + Logger.error(ex); + throw new PersistencyException("ClearSlot: Error loading collection '"+collName+"': "+ex.getMessage()); + } + + // find member and clear + boolean stored = false; + for (AggregationMember member : agg.getMembers().list) { + if (member.getID() == slotNo) { + if (member.getItemPath() != null) + throw new ObjectCannotBeUpdated("ClearSlot: Member slot "+slotNo+" already empty"); + member.clearItem(); + stored = true; + break; + } + } + if (!stored) { + throw new ObjectNotFoundException("ClearSlot: Member slot "+slotNo+" not found."); + } + + + try { + Gateway.getStorage().put(item, agg, null); + } catch (PersistencyException e) { + Logger.error(e); + throw new PersistencyException("ClearSlot: Error storing collection"); + } + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/CreateNewCollectionVersion.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/CreateNewCollectionVersion.java new file mode 100644 index 0000000..a598044 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/CreateNewCollectionVersion.java @@ -0,0 +1,103 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + + +import java.util.Arrays; + +import org.cristalise.kernel.collection.Collection; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $ + * @version $Revision: 1.8 $ + **************************************************************************/ +public class CreateNewCollectionVersion extends PredefinedStep +{ + /************************************************************************** + * Constructor for Castor + **************************************************************************/ + public CreateNewCollectionVersion() + { + super(); + } + + + /** + * Generates a new snapshot of a collection from its current state. The + * new version is given the next available number, starting at 0. + * + * Params: + * 0 - Collection name + * @throws InvalidDataException + * @throws PersistencyException + * + * @throws ObjectNotFoundException when there is no collection present with + * that name + */ + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, PersistencyException, ObjectNotFoundException + { + String collName; + + // extract parameters + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "CreateNewCollectionVersion: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + if (params.length != 1) + throw new InvalidDataException("CreateNewCollectionVersion: Invalid parameters "+Arrays.toString(params)); + + collName = params[0]; + Collection coll = (Collection)Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null); + + // find last numbered version + int lastVer = -1; + String[] versions = Gateway.getStorage().getClusterContents(item, ClusterStorage.COLLECTION+"/"+collName); + for (String thisVerStr : versions) { + try { + int thisVer = Integer.parseInt(thisVerStr); + if (thisVer > lastVer) lastVer = thisVer; + } catch (NumberFormatException ex) { } // ignore non-integer versions + } + + // Remove it from the cache before we change it + Gateway.getStorage().clearCache(item, ClusterStorage.COLLECTION+"/"+collName+"/last"); + // Set the version + coll.setVersion(lastVer+1); + + // store it + try { + Gateway.getStorage().put(item, coll, null); + } catch (PersistencyException e) { + throw new PersistencyException("CreateNewCollectionVersion: Error saving new collection '"+collName+"': "+e.getMessage()); + } + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/Import.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/Import.java new file mode 100644 index 0000000..26e015d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/Import.java @@ -0,0 +1,106 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + +import java.util.Arrays; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.events.Event; +import org.cristalise.kernel.events.History; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.TransactionManager; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * $Revision: 1.21 $ + * $Date: 2005/06/02 12:17:22 $ + * + * Params: Schemaname_version:Viewpoint (optional), Outcome, Timestamp (optional + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ +public class Import extends PredefinedStep +{ + public Import() + { + super(); + } + + //requestdata is xmlstring + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, PersistencyException { + + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "Import: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + + int split1 = params[0].indexOf('_'); + int split2 = params[0].indexOf(':'); + + if (split1 == -1) + throw new InvalidDataException("Import: Invalid parameters "+Arrays.toString(params)); + + requestData = params[1]; + + String schemaName = params[0].substring(0, split1); + String viewpoint = null; + int schemaVersion; + if (split2 > -1) { + schemaVersion = Integer.parseInt(params[0].substring(split1+1, split2)); + viewpoint = params[0].substring(split2+1); + } + else + schemaVersion = Integer.parseInt(params[0].substring(split1+1)); + + String timestamp; + if (params.length == 3) + timestamp = params[2]; + else + timestamp = Event.timeToString(Event.getGMT()); + + // write event, outcome and viewpoints to storage + + TransactionManager storage = Gateway.getStorage(); + Object locker = getWf(); + History hist = getWf().getHistory(); + Event event = hist.addEvent(agent, getCurrentAgentRole(), getName(), getPath(), getType(), schemaName, schemaVersion, getStateMachine().getName(), getStateMachine().getVersion(), getStateMachine().getTransition(transitionID), viewpoint, timestamp); + + try { + storage.put(item, new Outcome(event.getID(), requestData, schemaName, schemaVersion), locker); + storage.put(item, new Viewpoint(item, schemaName, viewpoint, schemaVersion, event.getID()), locker); + if (!"last".equals(viewpoint)) + storage.put(item, new Viewpoint(item, schemaName, "last", schemaVersion, event.getID()), locker); + } catch (PersistencyException e) { + storage.abort(locker); + throw e; + } + storage.commit(locker); + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStep.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStep.java new file mode 100644 index 0000000..c8a293e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStep.java @@ -0,0 +1,191 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.cristalise.kernel.lifecycle.instance.Activity; +import org.cristalise.kernel.lifecycle.instance.predefined.agent.AgentPredefinedStepContainer; +import org.cristalise.kernel.lifecycle.instance.predefined.item.ItemPredefinedStepContainer; +import org.cristalise.kernel.lifecycle.instance.predefined.server.ServerPredefinedStepContainer; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.utils.Logger; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.xml.sax.InputSource; + +/*********************************************************************************************************************************************************************************************************************************************************************************************************** + * @author $Author: sgaspard $ $Date: 2004/09/21 10:32:17 $ + * @version $Revision: 1.14 $ + **********************************************************************************************************************************************************************************************************************************************************************************************************/ +public abstract class PredefinedStep extends Activity +{ + /******************************************************************************************************************************************************************************************************************************************************************************************************* + * predefined Steps are always Active, and have only one transition subclasses could override this method (if necessary) + ******************************************************************************************************************************************************************************************************************************************************************************************************/ + + private boolean isPredefined = false; + public static final int DONE = 0; + public static final int AVAILABLE = 0; + + public PredefinedStep() { + super(); + getProperties().put("SchemaType", "PredefinedStepOutcome"); + getProperties().put("SchemaVersion", "0"); + } + + @Override + public boolean getActive() + { + if (isPredefined) + return true; + else + return super.getActive(); + } + + + + @Override + protected String getDefaultSMName() { + return "PredefinedStep"; + } + + @Override + public String getErrors() + { + if (isPredefined) + return getName(); + else + return super.getErrors(); + } + @Override + public boolean verify() + { + if (isPredefined) + return true; + else + return super.verify(); + } + /** + * Returns the isPredefined. + * + * @return boolean + */ + public boolean getIsPredefined() + { + return isPredefined; + } + /** + * Sets the isPredefined. + * + * @param isPredefined + * The isPredefined to set + */ + public void setIsPredefined(boolean isPredefined) + { + this.isPredefined = isPredefined; + } + @Override + public String getType() + { + return getName(); + } + + static public String getPredefStepSchemaName(String stepName) { + PredefinedStepContainer[] allSteps = { new ItemPredefinedStepContainer(), new AgentPredefinedStepContainer(), new ServerPredefinedStepContainer() }; + for (PredefinedStepContainer thisContainer : allSteps) { + String stepPath = thisContainer.getName()+"/"+stepName; + Activity step = (Activity)thisContainer.search(stepPath); + if (step != null) { + return (String)step.getProperties().get("SchemaType"); + } + } + return "PredefinedStepOutcome"; // default to standard if not found - server may be a newer version + } + + // generic bundling of parameters + static public String bundleData(String[] data) + { + try + { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document dom = builder.newDocument(); + Element root = dom.createElement("PredefinedStepOutcome"); + dom.appendChild(root); + for (String element : data) { + Element param = dom.createElement("param"); + Text t = dom.createTextNode(element); + param.appendChild(t); + root.appendChild(param); + } + + return Outcome.serialize(dom, false); + + } + catch (Exception e) + { + Logger.error(e); + StringBuffer xmlData = new StringBuffer().append(""); + for (String element : data) + xmlData.append(""); + xmlData.append(""); + return xmlData.toString(); + } + } + + // generic bundling of single parameter + static public String bundleData(String data) + { + return bundleData(new String[]{ data }); + } + + public static String[] getDataList(String xmlData) + { + try + { + Document scriptDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(xmlData))); + NodeList nodeList = scriptDoc.getElementsByTagName("param"); + String[] result = new String[nodeList.getLength()]; + for (int i = 0; i < nodeList.getLength(); i++) + { + Node n = nodeList.item(i).getFirstChild(); + if (n instanceof CDATASection) + result[i] = ((CDATASection) n).getData(); + else if (n instanceof Text) + result[i] = ((Text) n).getData(); + } + return result; + } + catch (Exception ex) + { + Logger.error("Exception::PredefinedStep::getDataList()"); + Logger.error(ex); + } + return null; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStepContainer.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStepContainer.java new file mode 100644 index 0000000..74a86db --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStepContainer.java @@ -0,0 +1,79 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.lifecycle.instance.CompositeActivity; +public abstract class PredefinedStepContainer extends CompositeActivity +{ + protected int num = 0; + + public PredefinedStepContainer() + { + super(); + setName("predefined"); + getProperties().put("Description", "Contains all predefined Steps"); + createChildren(); + } + public void createChildren() + { + predInit("AddDomainPath", "Adds a new path to this entity in the LDAP domain tree", new AddDomainPath()); + predInit("RemoveDomainPath", "Removes an existing path to this Entity from the LDAP domain tree", new RemoveDomainPath()); + predInit("ReplaceDomainWorkflow", "Replaces the domain CA with the supplied one. Used by the GUI to save new Wf layout", new ReplaceDomainWorkflow()); + predInit("AddC2KObject", "Adds or overwrites a C2Kernel object for this Item", new AddC2KObject()); + predInit("RemoveC2KObject", "Removes the named C2Kernel object from this Item.", new RemoveC2KObject()); + predInit("WriteProperty", "Writes a property to the Item", new WriteProperty()); + predInit("WriteViewpoint", "Writes a viewpoint to the Item", new WriteViewpoint()); + predInit("AddNewCollectionDescription", "Creates a new collection description in this Item", new AddNewCollectionDescription()); + predInit("CreateNewCollectionVersion", "Creates a new numbered collection version in this Item from the current one.", new CreateNewCollectionVersion()); + predInit("AddNewSlot", "Creates a new slot in the given aggregation, that holds instances of the item description of the given key", new AddNewSlot()); + predInit("AssignItemToSlot", "Assigns the referenced entity to a pre-existing slot in an aggregation", new AssignItemToSlot()); + predInit("ClearSlot", "Clears an aggregation member slot, given a slot no or entity key", new ClearSlot()); + predInit("RemoveSlotFromCollection", "Removed the given slot from the aggregation", new RemoveSlotFromCollection()); + predInit("AddMemberToCollection", "Creates a new member slot for the given item in a dependency, and assigns the item", new AddMemberToCollection()); + predInit("Import", "Imports an outcome into the Item, with a given schema and viewpoint", new Import()); + + } + + public void predInit(String alias, String Description, PredefinedStep act) + { + act.setName(alias); + act.setType(alias); + act.getProperties().put("Description", Description); + act.setCentrePoint(new GraphPoint()); + act.setIsPredefined(true); + addChild(act, new GraphPoint(100, 75 * ++num)); + } + @Override + public boolean verify() + { + return true; + } + @Override + public String getErrors() + { + return "predefined"; + } + @Override + public boolean getActive() + { + return true; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveC2KObject.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveC2KObject.java new file mode 100644 index 0000000..2f86274 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveC2KObject.java @@ -0,0 +1,70 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + + + +import java.util.Arrays; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2005/11/15 15:56:38 $ + * @version $Revision: 1.28 $ + **************************************************************************/ +public class RemoveC2KObject extends PredefinedStep +{ + public RemoveC2KObject() + { + super(); + getProperties().put("Agent Role", "Admin"); + } + + //requestdata is xmlstring + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, PersistencyException { + + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "RemoveC2KObject: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + if (params.length != 1) + throw new InvalidDataException("RemoveC2KObject: Invalid parameters "+Arrays.toString(params)); + String path = params[0]; + + try + { + Gateway.getStorage().remove( item, path, null ); + } + catch( PersistencyException ex ) + { + throw new PersistencyException("RemoveC2KObject: Error removing object '"+path+"': "+ex.getMessage()); + } + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveDomainPath.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveDomainPath.java new file mode 100644 index 0000000..0dc24bb --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveDomainPath.java @@ -0,0 +1,73 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + + + + +import java.util.Arrays; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.LookupManager; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +public class RemoveDomainPath extends PredefinedStep +{ + public RemoveDomainPath() + { + super(); + } + + //requestdata is xmlstring + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException { + + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "RemoveDomainPath: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + if (params.length != 1) throw new InvalidDataException("RemoveDomainPath: Invalid parameters "+Arrays.toString(params)); + + DomainPath domainPath = new DomainPath(params[0]); + if (!domainPath.exists()) + throw new ObjectNotFoundException("RemoveDomainPath: Domain path "+domainPath.toString()+" does not exist."); + + if (domainPath.getType()!=DomainPath.ENTITY) + + try { + if (!domainPath.getItemPath().equals(item)) + throw new InvalidDataException("RemoveDomainPath: Domain path "+domainPath.toString()+" is not an alias of the current Item "+item); + } catch (ObjectNotFoundException ex) { + throw new InvalidDataException("RemoveDomainPath: Domain path "+domainPath.toString()+" is a context."); + } + + LookupManager lookupManager = Gateway.getLookupManager(); + lookupManager.delete(domainPath); + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveSlotFromCollection.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveSlotFromCollection.java new file mode 100644 index 0000000..6522384 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveSlotFromCollection.java @@ -0,0 +1,131 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + + +import java.util.Arrays; + +import org.cristalise.kernel.collection.Collection; +import org.cristalise.kernel.collection.CollectionMember; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $ + * @version $Revision: 1.8 $ + **************************************************************************/ +public class RemoveSlotFromCollection extends PredefinedStep +{ + /************************************************************************** + * Constructor for Castor + **************************************************************************/ + public RemoveSlotFromCollection() + { + super(); + } + + + /** + * Params: + * 0 - collection name + * 1 - slot number OR if null: + * 2 - target entity key + * @throws ObjectNotFoundException + * @throws PersistencyException + */ + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, PersistencyException { + + String collName; + int slotNo = -1; + ItemPath currentChild = null; + Collection coll; + + // extract parameters + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "RemoveSlotFromCollection: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + + try { + collName = params[0]; + if (params.length>1 && params[1].length()>0) slotNo = Integer.parseInt(params[1]); + if (params.length>2 && params[2].length()>0) currentChild = new ItemPath(params[2]); + } catch (Exception e) { + throw new InvalidDataException("RemoveSlotFromCollection: Invalid parameters "+Arrays.toString(params)); + } + + if (slotNo == -1 && currentChild == null) + throw new InvalidDataException("RemoveSlotFromCollection: Must give either slot number or entity key"); + + // load collection + try { + coll = (Collection)Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null); + } catch (PersistencyException ex) { + Logger.error(ex); + throw new PersistencyException("RemoveSlotFromCollection: Error loading collection '\"+collName+\"': "+ex.getMessage()); + } + + // check the slot is there if it's given by id + CollectionMember slot = null; + if (slotNo > -1) { + slot = coll.getMember(slotNo); + } + + // if both parameters are supplied, check the given item is actually in that slot + if (slot != null && currentChild != null && !slot.getItemPath().equals(currentChild)) { + throw new ObjectNotFoundException("RemoveSlotFromCollection: Item "+currentChild+" was not in slot "+slotNo); + } + + if (slotNo == -1) { // find slot from entity key + for (CollectionMember member : coll.getMembers().list) { + if (member.getItemPath().equals(currentChild)) { + slotNo = member.getID(); + break; + } + } + } + if (slotNo == -1) { + throw new ObjectNotFoundException("Could not find "+currentChild+" in collection "+coll.getName()); + } + + // Remove the slot + coll.removeMember(slotNo); + + // Store the collection + try { + Gateway.getStorage().put(item, coll, null); + } catch (PersistencyException e) { + Logger.error(e); + throw new PersistencyException("Error storing collection"); + } + + return requestData; + + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java new file mode 100644 index 0000000..5ec7510 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java @@ -0,0 +1,77 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + +//Java +import java.util.Arrays; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.lifecycle.instance.CompositeActivity; +import org.cristalise.kernel.lifecycle.instance.Workflow; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +public class ReplaceDomainWorkflow extends PredefinedStep +{ + public ReplaceDomainWorkflow() + { + super(); + getProperties().put("Agent Role", "Admin"); + } + + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, PersistencyException { + + Workflow lifeCycle = getWf(); + + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "AddC2KObject: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + if (params.length != 1) throw new InvalidDataException("AddC2KObject: Invalid parameters "+Arrays.toString(params)); + + lifeCycle.getChildGraphModel().removeVertex(lifeCycle.search("workflow/domain")); + CompositeActivity domain; + try { + domain = (CompositeActivity) Gateway.getMarshaller().unmarshall(params[0]); + } catch (Exception e) { + Logger.error(e); + throw new InvalidDataException("ReplaceDomainWorkflow: Could not unmarshall new workflow: "+e.getMessage()); + } + domain.setName("domain"); + lifeCycle.initChild(domain, true, new GraphPoint(150, 100)); + // if new workflow, activate it, otherwise refresh the jobs + if (!domain.active) lifeCycle.run(agent, item); + else lifeCycle.refreshJobs(item); + + // store new wf + try { + Gateway.getStorage().put(item, lifeCycle, null); + } catch (PersistencyException e) { + throw new PersistencyException("ReplaceDomainWorkflow: Could not write new workflow to storage: "+e.getMessage()); + } + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteProperty.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteProperty.java new file mode 100644 index 0000000..c73bec8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteProperty.java @@ -0,0 +1,80 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + +import java.util.Arrays; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $ + * @version $Revision: 1.3 $ + **************************************************************************/ +public class WriteProperty extends PredefinedStep +{ + /************************************************************************** + * Constructor for Castror + **************************************************************************/ + public WriteProperty() + { + super(); + } + + //requestdata is xmlstring + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectCannotBeUpdated, ObjectNotFoundException, PersistencyException { + + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "WriteProperty: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + + if (params.length != 2) + throw new InvalidDataException("WriteProperty: invalid parameters "+Arrays.toString(params)); + + String name = params[0]; + String newValue = params[1]; + + Property prop; + + try { + prop = (Property)Gateway.getStorage().get(item, ClusterStorage.PROPERTY+"/"+name, null); + if (!prop.isMutable() && !newValue.equals(prop.getValue())) + throw new ObjectCannotBeUpdated("WriteProperty: Property '"+name+"' is not mutable."); + prop.setValue(newValue); + Gateway.getStorage().put(item, prop, null); + } catch (ObjectNotFoundException e) { + throw new ObjectNotFoundException("WriteProperty: Property '"+name+"' not found."); + } + + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteViewpoint.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteViewpoint.java new file mode 100644 index 0000000..d617b99 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteViewpoint.java @@ -0,0 +1,88 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined; + +import java.util.Arrays; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.events.Event; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +public class WriteViewpoint extends PredefinedStep { + + public WriteViewpoint() { + super(); + } + + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, PersistencyException { + + String schemaName; + String viewName; + int evId; + + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "WriteViewpoint: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + + // outcometype, name and evId. Event and Outcome should be checked so schema version should be discovered. + if (params.length != 3) + throw new InvalidDataException("WriteViewpoint: Invalid parameters "+Arrays.toString(params)); + + schemaName = params[0]; + viewName = params[1]; + + try { + evId = Integer.parseInt(params[2]); + } catch (NumberFormatException ex) { + throw new InvalidDataException("WriteViewpoint: Parameter 3 (EventId) must be an integer"); + } + + // Find event + + Event ev; + try { + ev = (Event)Gateway.getStorage().get(item, ClusterStorage.HISTORY+"/"+evId, null); + } catch (PersistencyException e) { + Logger.error(e); + throw new PersistencyException("WriteViewpoint: Could not load event "+evId); + } + + // Write new viewpoint + Viewpoint newView = new Viewpoint(item, schemaName, viewName, ev.getSchemaVersion(), evId); + try { + Gateway.getStorage().put(item, newView, null); + } catch (PersistencyException e) { + Logger.error(e); + throw new PersistencyException("WriteViewpoint: Could not store new viewpoint"); + } + return requestData; + } + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/AgentPredefinedStepContainer.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/AgentPredefinedStepContainer.java new file mode 100644 index 0000000..6ff3164 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/AgentPredefinedStepContainer.java @@ -0,0 +1,47 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.agent; + +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer; + + +/************************************************************************** + * + * $Revision: 1.2 $ + * $Date: 2005/06/02 10:19:33 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public class AgentPredefinedStepContainer extends PredefinedStepContainer { + + + @Override + public void createChildren() + { + super.createChildren(); + predInit("CreateAgentFromDescription", "Create a new item using this item as its description", new CreateAgentFromDescription()); + predInit("RemoveAgent", "Deletes the Agent", new RemoveAgent()); + predInit("SetAgentPassword", "Changes the Agent's password", new SetAgentPassword()); + predInit("SetAgentRoles", "Sets the roles of the Agent", new SetAgentRoles()); + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/CreateAgentFromDescription.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/CreateAgentFromDescription.java new file mode 100644 index 0000000..335fe2d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/CreateAgentFromDescription.java @@ -0,0 +1,137 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.agent; + +import java.util.Arrays; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.CorbaServer; +import org.cristalise.kernel.entity.agent.ActiveEntity; +import org.cristalise.kernel.lifecycle.instance.predefined.item.CreateItemFromDescription; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2005/10/13 08:13:58 $ + * @version $Revision: 1.47 $ + **************************************************************************/ +public class CreateAgentFromDescription extends CreateItemFromDescription +{ + public CreateAgentFromDescription() + { + super(); + } + + /** + * Params: + *
    1. New Agent name
    2. + *
    3. Description version to use
    4. + *
    5. Comma-delimited Role names to assign to the agent. Must already exist.
    6. + *
    7. Initial properties to set in the new Agent
    8. + *
    + * @throws ObjectNotFoundException + * @throws InvalidDataException The input parameters were incorrect + * @throws ObjectAlreadyExistsException The Agent already exists + * @throws CannotManageException The Agent could not be created + * @throws ObjectCannotBeUpdated The addition of the new entries into the LookupManager failed + * @see org.cristalise.kernel.lifecycle.instance.predefined.item.CreateItemFromDescription#runActivityLogic(org.cristalise.kernel.lookup.AgentPath, int, int, java.lang.String) + */ + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws ObjectNotFoundException, InvalidDataException, ObjectAlreadyExistsException, CannotManageException, ObjectCannotBeUpdated { + + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "CreateAgentFromDescription: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + if (params.length < 3 || params.length > 4) + throw new InvalidDataException("CreateAgentFromDescription: Invalid parameters "+Arrays.toString(params)); + + String newName = params[0]; + String descVer = params[1]; + String roles = params[2]; + PropertyArrayList initProps = + params.length > 3 ? getInitProperties(params[3]):new PropertyArrayList(); + + Logger.msg(1, "CreateAgentFromDescription::request() - Starting."); + + // check if given roles exist + String[] roleArr = roles.split(","); + for(int i=0; i requestedRoles = new ArrayList(); + for (int i=0; i rolesToRemove = new ArrayList(); + for (RolePath existingRole : currentRoles) { // + if (requestedRoles.contains(existingRole)) // if we have it, and it's requested, then it will be kept + requestedRoles.remove(existingRole); // so remove it from request - this will be left with roles to be added + else + rolesToRemove.add(existingRole); // else this role will be removed + } + + // remove roles not in new list + for (RolePath roleToRemove : rolesToRemove) + try { + Gateway.getLookupManager().removeRole(targetAgent, roleToRemove); + } catch (Exception e) { + Logger.error(e); + throw new InvalidDataException("Error removing role "+roleToRemove.getName()); + } + + // add requested roles we don't already have + for (RolePath roleToAdd : requestedRoles) + try { + Gateway.getLookupManager().addRole(targetAgent, roleToAdd); + } catch (Exception e) { + Logger.error(e); + throw new InvalidDataException("Error adding role "+roleToAdd.getName()); + } + + return requestData; + } + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/CreateItemFromDescription.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/CreateItemFromDescription.java new file mode 100644 index 0000000..53e545e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/CreateItemFromDescription.java @@ -0,0 +1,195 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.item; + +import org.cristalise.kernel.collection.Collection; +import org.cristalise.kernel.collection.CollectionArrayList; +import org.cristalise.kernel.collection.CollectionDescription; +import org.cristalise.kernel.collection.CollectionMember; +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.CorbaServer; +import org.cristalise.kernel.entity.TraceableEntity; +import org.cristalise.kernel.lifecycle.CompositeActivityDef; +import org.cristalise.kernel.lifecycle.instance.CompositeActivity; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.property.PropertyDescriptionList; +import org.cristalise.kernel.property.PropertyUtility; +import org.cristalise.kernel.utils.LocalObjectLoader; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2005/10/13 08:13:58 $ + * @version $Revision: 1.47 $ + **************************************************************************/ +public class CreateItemFromDescription extends PredefinedStep +{ + public CreateItemFromDescription() + { + super(); + } + + //requestdata is xmlstring + @Override + protected String runActivityLogic(AgentPath agent, ItemPath itemPath, + int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, ObjectAlreadyExistsException, CannotManageException, ObjectCannotBeUpdated, PersistencyException { + + String[] input = getDataList(requestData); + String newName = input[0]; + String domPath = input[1]; + String descVer = input.length > 2 ? input[2]:"last"; + PropertyArrayList initProps = + input.length > 3?getInitProperties(input[3]):new PropertyArrayList(); + + Logger.msg(1, "CreateItemFromDescription - Starting."); + + // check if the path is already taken + DomainPath context = new DomainPath(new DomainPath(domPath), newName); + //Logger.debug(8,"context "+context.getItemPath()+" "+context.getPath()+" "+context.getString()); + if (context.exists()) + throw new ObjectAlreadyExistsException("The path " +context+ " exists already."); + + // get init objects + + /* ITEM CREATION */ + + // generate new entity key + Logger.msg(6, "CreateItemFromDescription - Requesting new item path"); + ItemPath newItemPath = new ItemPath(); + + // resolve the item factory + Logger.msg(6, "CreateItemFromDescription - Resolving item factory"); + + // create the Item object + Logger.msg(3, "CreateItemFromDescription - Creating Item"); + CorbaServer factory = Gateway.getCorbaServer(); + if (factory == null) throw new CannotManageException("This process cannot create new Items"); + TraceableEntity newItem = factory.createItem(newItemPath); + Gateway.getLookupManager().add(newItemPath); + + + // initialise it with its properties and workflow + + Logger.msg(3, "CreateItemFromDescription - Initializing Item"); + + try { + newItem.initialise( + agent.getSystemKey(), + Gateway.getMarshaller().marshall(getNewProperties(itemPath, descVer, initProps, newName, agent)), + Gateway.getMarshaller().marshall(getNewWorkflow(itemPath, descVer)), + Gateway.getMarshaller().marshall(getNewCollections(itemPath, descVer)) + ); + } catch (PersistencyException e) { + throw e; + } catch (Exception e) { + throw new InvalidDataException("CreateAgentFromDescription: Problem initializing new Agent. See log: "+e.getMessage()); + } + // add its domain path + Logger.msg(3, "CreateItemFromDescription - Creating "+context); + context.setItemPath(newItemPath); + Gateway.getLookupManager().add(context); + return requestData; + } + + protected PropertyArrayList getInitProperties(String input) throws InvalidDataException { + try { + return (PropertyArrayList)Gateway.getMarshaller().unmarshall(input); + } catch (Exception e) { + Logger.error(e); + throw new InvalidDataException("Initial property parameter was not a marshalled PropertyArrayList: "+input); + } + } + + protected PropertyArrayList getNewProperties(ItemPath itemPath, String descVer, PropertyArrayList initProps, String newName, AgentPath agent) throws ObjectNotFoundException, InvalidDataException { + // copy properties -- intend to create from propdesc + PropertyDescriptionList pdList = PropertyUtility.getPropertyDescriptionOutcome(itemPath, descVer); + PropertyArrayList props = pdList.instantiate(initProps); + // set Name prop or create if not present + boolean foundName = false; + for (Property prop : props.list) { + if (prop.getName().equals("Name")) { + foundName = true; + prop.setValue(newName); + } + } + if (!foundName) props.list.add(new Property("Name", newName, true)); + props.list.add( new Property("Creator", agent.getAgentName(), false)); + return props; + } + + protected CompositeActivity getNewWorkflow(ItemPath itemPath, String descVer) throws ObjectNotFoundException, InvalidDataException, PersistencyException { + // find the workflow def for the given description version + + String wfDefName = null; Integer wfDefVer = null; + + Collection thisCol = (Collection)Gateway.getStorage().get(itemPath, ClusterStorage.COLLECTION+"/workflow/"+descVer, null); + CollectionMember wfMember = thisCol.getMembers().list.get(0); + wfDefName = wfMember.resolveItem().getName(); + Object wfVerObj = wfMember.getProperties().get("Version"); + try { + wfDefVer = Integer.parseInt(wfVerObj.toString()); + } catch (NumberFormatException ex) { + throw new InvalidDataException("Invalid workflow version number: "+wfVerObj.toString()); + } + + // load workflow def + if (wfDefName == null) + throw new InvalidDataException("No workflow given or defined"); + if (wfDefVer == null) + throw new InvalidDataException("No workflow def version given"); + + try { + CompositeActivityDef wfDef = (CompositeActivityDef)LocalObjectLoader.getActDef(wfDefName, wfDefVer); + return (CompositeActivity)wfDef.instantiate(); + } catch (ObjectNotFoundException ex) { + throw new InvalidDataException("Workflow def '"+wfDefName+"'v"+wfDefVer+" not found"); + } catch (ClassCastException ex) { + throw new InvalidDataException("Activity def '"+wfDefName+"' was not Composite"); + } + } + + protected CollectionArrayList getNewCollections(ItemPath itemPath, String descVer) throws ObjectNotFoundException, PersistencyException { + // loop through collections, collecting instantiated descriptions and finding the default workflow def + CollectionArrayList colls = new CollectionArrayList(); + String[] collNames = Gateway.getStorage().getClusterContents(itemPath, ClusterStorage.COLLECTION); + for (String collName : collNames) { + Collection thisCol = (Collection)Gateway.getStorage().get(itemPath, ClusterStorage.COLLECTION+"/"+collName+"/"+descVer, null); + if (thisCol instanceof CollectionDescription) { + CollectionDescription thisDesc = (CollectionDescription)thisCol; + colls.put(thisDesc.newInstance()); + } + } + return colls; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/Erase.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/Erase.java new file mode 100644 index 0000000..50a1bfd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/Erase.java @@ -0,0 +1,80 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.item; + + + +import java.util.Iterator; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.Path; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2005/11/15 15:56:38 $ + * @version $Revision: 1.10 $ + **************************************************************************/ +public class Erase extends PredefinedStep +{ + public Erase() + { + super(); + getProperties().put("Agent Role", "Admin"); + } + + //requestdata is xmlstring + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException, PersistencyException { + + Logger.msg(1, "Erase::request() - Starting."); + + Iterator domPaths = Gateway.getLookup().searchAliases(item); + while (domPaths.hasNext()) { + DomainPath path = (DomainPath)domPaths.next(); + // delete them + if (path.getItemPath().equals(item)) + Gateway.getLookupManager().delete(path); + } + + //clear out all storages + Gateway.getStorage().removeCluster(item, "", null); + + //remove entity path + Gateway.getLookupManager().delete(item); + + Logger.msg(1, "Erase::request() - DONE."); + return requestData; + } + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/ItemPredefinedStepContainer.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/ItemPredefinedStepContainer.java new file mode 100644 index 0000000..46a6feb --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/ItemPredefinedStepContainer.java @@ -0,0 +1,45 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.item; + +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer; + + +/************************************************************************** + * + * $Revision: 1.2 $ + * $Date: 2005/06/02 10:19:33 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public class ItemPredefinedStepContainer extends PredefinedStepContainer { + + + @Override + public void createChildren() + { + super.createChildren(); + predInit("CreateItemFromDescription", "Create a new item using this item as its description", new CreateItemFromDescription()); + predInit("Erase", "Deletes all objects and domain paths for this item.", new Erase()); + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/AddDomainContext.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/AddDomainContext.java new file mode 100644 index 0000000..b225978 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/AddDomainContext.java @@ -0,0 +1,67 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.server; + +import java.util.Arrays; +import java.util.Stack; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +public class AddDomainContext extends PredefinedStep { + + public AddDomainContext() { + super(); + } + + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectCannotBeUpdated, ObjectAlreadyExistsException, CannotManageException { + + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "AddDomainContext: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + if (params.length != 1) throw new InvalidDataException("AddDomainContext: Invalid parameters "+Arrays.toString(params)); + + DomainPath pathToAdd = new DomainPath(params); + if (pathToAdd.exists()) + throw new ObjectAlreadyExistsException("Context "+pathToAdd+" already exists"); + // collect parent paths if they don't exist + Stack pathsToAdd = new Stack(); + while(pathToAdd!= null && !pathToAdd.exists()) { + pathsToAdd.push(pathToAdd); + pathToAdd = pathToAdd.getParent(); + } + while(!pathsToAdd.empty()) { + pathToAdd = pathsToAdd.pop(); + Gateway.getLookupManager().add(pathToAdd); + } + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewAgent.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewAgent.java new file mode 100644 index 0000000..65e56b5 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewAgent.java @@ -0,0 +1,68 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.server; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.imports.ImportAgent; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +public class CreateNewAgent extends PredefinedStep +{ + public CreateNewAgent() + { + super(); + getProperties().put("SchemaType", "Agent"); + } + + //requestdata is xmlstring + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException, ObjectAlreadyExistsException { + + String redactedRequestData; + + ImportAgent newAgent; + try { + newAgent = (ImportAgent)Gateway.getMarshaller().unmarshall(requestData); + } catch (Exception e1) { + Logger.error(e1); + throw new InvalidDataException("CreateNewAgent: Couldn't unmarshall new Agent: "+requestData); + } + newAgent.create(agent, true); + newAgent.setPassword("REDACTED"); + try { + redactedRequestData = Gateway.getMarshaller().marshall(newAgent); + } catch (Exception e) { + Logger.error(e); + throw new InvalidDataException("CreateNewAgent: Couldn't marshall new Agent for outcome: "+newAgent); + } + return redactedRequestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewItem.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewItem.java new file mode 100644 index 0000000..acd1fd1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewItem.java @@ -0,0 +1,63 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.server; + + + + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.imports.ImportItem; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +public class CreateNewItem extends PredefinedStep +{ + public CreateNewItem() + { + super(); + getProperties().put("SchemaType", "Item"); + } + + //requestdata is xmlstring + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectCannotBeUpdated, ObjectNotFoundException, CannotManageException, ObjectAlreadyExistsException, InvalidCollectionModification { + + ImportItem newItem; + try { + newItem = (ImportItem)Gateway.getMarshaller().unmarshall(requestData); + } catch (Exception e) { + Logger.error(e); + throw new InvalidDataException("CreateNewAgent: Couldn't unmarshall new Agent: "+requestData); + } + newItem.create(agent, false); + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewRole.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewRole.java new file mode 100644 index 0000000..3771a7e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewRole.java @@ -0,0 +1,60 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.server; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.imports.ImportRole; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +public class CreateNewRole extends PredefinedStep +{ + public CreateNewRole() + { + super(); + getProperties().put("SchemaType", "Role"); + } + + //requestdata is xmlstring + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectAlreadyExistsException, ObjectCannotBeUpdated, CannotManageException, ObjectNotFoundException { + + + ImportRole newRole; + try { + newRole = (ImportRole)Gateway.getMarshaller().unmarshall(requestData); + } catch (Exception e) { + Logger.error(e); + throw new InvalidDataException("CreateNewAgent: Couldn't unmarshall new Agent: "+requestData); + } + newRole.create(agent, true); + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveDomainContext.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveDomainContext.java new file mode 100644 index 0000000..bc1ed5c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveDomainContext.java @@ -0,0 +1,65 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.server; + +import java.util.Arrays; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +public class RemoveDomainContext extends PredefinedStep { + public RemoveDomainContext() { + super(); + } + + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException { + + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "RemoveDomainContext: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + if (params.length != 1) throw new InvalidDataException("RemoveDomainContext: Invalid parameters "+Arrays.toString(params)); + + DomainPath pathToDelete = new DomainPath(params[0]); + if (!pathToDelete.exists()) + throw new ObjectNotFoundException("Context "+pathToDelete+" does not exist"); + + try { + pathToDelete.getItemPath(); + throw new InvalidDataException("Path "+pathToDelete+" is an Entity. Use its own Erase step instead, or RemoveAgent."); + } catch (ObjectNotFoundException ex) { } + + if (Gateway.getLookup().getChildren(pathToDelete).hasNext()) + throw new ObjectCannotBeUpdated("Context "+pathToDelete+" is not empty. Cannot delete."); + + Gateway.getLookupManager().delete(pathToDelete); + return requestData; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveRole.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveRole.java new file mode 100644 index 0000000..6136cac --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveRole.java @@ -0,0 +1,68 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.server; + +import java.util.Arrays; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.LookupManager; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +public class RemoveRole extends PredefinedStep +{ + public RemoveRole() + { + super(); + } + + //requestdata is xmlstring + @Override + protected String runActivityLogic(AgentPath agent, ItemPath item, + int transitionID, String requestData) throws InvalidDataException, CannotManageException, ObjectNotFoundException, ObjectCannotBeUpdated { + + String[] params = getDataList(requestData); + if (Logger.doLog(3)) Logger.msg(3, "RemoveRole: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params)); + if (params.length != 1) throw new InvalidDataException("RemoveRole: Invalid parameters "+Arrays.toString(params)); + + LookupManager lookup = Gateway.getLookupManager(); + + RolePath thisRole; AgentPath[] agents; + thisRole = lookup.getRolePath(params[0]); + agents = Gateway.getLookup().getAgents(thisRole); + + if (agents.length > 0) + throw new ObjectCannotBeUpdated("Cannot remove role. "+agents.length+" agents still hold it."); + + lookup.delete(thisRole); + + return requestData; + + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/ServerPredefinedStepContainer.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/ServerPredefinedStepContainer.java new file mode 100644 index 0000000..0fdc34c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/ServerPredefinedStepContainer.java @@ -0,0 +1,62 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.predefined.server; + +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer; + +/************************************************************************** + * + * $Revision: 1.2 $ + * $Date: 2005/06/02 10:19:33 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public class ServerPredefinedStepContainer extends PredefinedStepContainer { + + + @Override + public void createChildren() + { + super.createChildren(); + serverPredInit("CreateNewItem", "Creates a new Item in this Server without description.", new CreateNewItem()); + serverPredInit("CreateNewAgent", "Creates a new Agent in this Server without description.", new CreateNewAgent()); + serverPredInit("CreateNewRole", "Creates a new Role in this Server.", new CreateNewRole()); + serverPredInit("RemoveRole", "Removes a Role from this Server.", new RemoveRole()); + serverPredInit("RemoveDomainContext", "Deletes an existing context in the domain tree, but only if empty", new RemoveDomainContext()); + serverPredInit("AddDomainContext", "Creates an empty domain context in the tree", new AddDomainContext()); + } + + public void serverPredInit(String alias, String Description, PredefinedStep act) + { + act.setName(alias); + act.setType(alias); + act.getProperties().put("Description", Description); + act.getProperties().put("Agent Role", "Admin"); + act.setCentrePoint(new GraphPoint()); + act.setIsPredefined(true); + addChild(act, new GraphPoint(100, 75 * ++num)); + } + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/State.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/State.java new file mode 100644 index 0000000..d78bb4e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/State.java @@ -0,0 +1,101 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.stateMachine; + +import java.util.HashMap; +import java.util.Set; + +public class State { + + int id; + String name; + boolean finished = false; // If true, this state deactivates the current activity and the lifecycle proceeds + + HashMap possibleTransitions; + + public State() { + possibleTransitions = new HashMap(); + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return id+": "+name; + } + + public void setName(String name) { + this.name = name; + } + + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public boolean isFinished() { + return finished; + } + + public void setFinished(boolean finished) { + this.finished = finished; + } + + public HashMap getPossibleTransitions() { + return possibleTransitions; + } + + protected void addPossibleTransition(Transition possibleTransition) { + possibleTransitions.put(possibleTransition.getId(), possibleTransition); + } + + public Set getPossibleTransitionIds() { + return possibleTransitions.keySet(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + State other = (State) obj; + if (id != other.id) + return false; + return true; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/StateMachine.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/StateMachine.java new file mode 100644 index 0000000..975dee1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/StateMachine.java @@ -0,0 +1,178 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.stateMachine; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lifecycle.instance.Activity; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.utils.DescriptionObject; +import org.cristalise.kernel.utils.Logger; + + +public class StateMachine implements DescriptionObject +{ + public String name; + public int version; + + private ArrayList states; + private ArrayList transitions; + private final HashMap stateCodes; + private final HashMap transitionCodes; + + State initialState; + int initialStateCode; + boolean isCoherent = false; + + public StateMachine() { + states = new ArrayList(); + transitions = new ArrayList(); + stateCodes = new HashMap(); + transitionCodes = new HashMap(); + } + + public void setStates(ArrayList newStates) { + this.states = newStates; + validate(); + } + + public void setTransitions(ArrayList newTransitions) { + this.transitions = newTransitions; + validate(); + } + + public void validate() { + stateCodes.clear(); + transitionCodes.clear(); + isCoherent = true; + + for (State state : states) { + Logger.debug(6, "State "+state.id+": "+state.name); + stateCodes.put(state.getId(), state); + } + + if (stateCodes.containsKey(initialStateCode)) + initialState = stateCodes.get(initialStateCode); + else + isCoherent = false; + + for (Transition trans : transitions) { + Logger.debug(6, "Transition "+trans.id+": "+trans.name); + transitionCodes.put(trans.getId(), trans); + isCoherent = isCoherent && trans.resolveStates(stateCodes); + } + + } + + public ArrayList getStates() { + return states; + } + + public ArrayList getTransitions() { + return transitions; + } + + public State getInitialState() { + return initialState; + } + + public void setInitialState(State initialState) { + this.initialState = initialState; + initialStateCode = initialState.getId(); + } + + public int getInitialStateCode() { + return initialStateCode; + } + + public void setInitialStateCode(int initialStateCode) { + this.initialStateCode = initialStateCode; + initialState = stateCodes.get(initialStateCode); + if (initialState == null) isCoherent = false; + } + + @Override + public String getName() { + return name; + } + + @Override + public int getVersion() { + return version; + } + + @Override + public void setName(String name) { + this.name = name; + } + + @Override + public void setVersion(int version) { + this.version = version; + } + + public Transition getTransition(int transitionID) { + return transitionCodes.get(transitionID); + } + + public State getState(int stateID) { + return stateCodes.get(stateID); + } + + public Map getPossibleTransitions(Activity act, AgentPath agent) throws ObjectNotFoundException, InvalidDataException { + HashMap returnList = new HashMap(); + State currentState = getState(act.getState()); + for (Integer transCode : currentState.getPossibleTransitionIds()) { + Transition possTrans = currentState.getPossibleTransitions().get(transCode); + try { + String role = possTrans.getPerformingRole(act, agent); + returnList.put(possTrans, role); + } catch (AccessRightsException ex) { + if (Logger.doLog(5)) + Logger.msg(5, "Transition '"+possTrans+"' not possible for "+agent.getAgentName()+": "+ex.getMessage()); + } + } + return returnList; + } + + public State traverse(Activity act, Transition transition, AgentPath agent) throws InvalidTransitionException, AccessRightsException, ObjectNotFoundException, InvalidDataException { + State currentState = getState(act.getState()); + if (transition.originState.equals(currentState)) { + transition.getPerformingRole(act, agent); + return transition.targetState; + } + else + throw new InvalidTransitionException("Transition '"+transition.getName()+"' not valid from state '"+currentState.getName()); + + } + + public boolean isCoherent() { + return isCoherent; + } + + +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/Transition.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/Transition.java new file mode 100644 index 0000000..845b489 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/Transition.java @@ -0,0 +1,345 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.stateMachine; + +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lifecycle.instance.Activity; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.persistency.outcome.Schema; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.LocalObjectLoader; +import org.cristalise.kernel.utils.Logger; + + +public class Transition { + + int id; + String name; + + int originStateId; + int targetStateId; + State originState; + State targetState; + String reservation; + + String enabledProp; // Boolean property that permits this transition e.g. 'Skippable' + + // activation properties + boolean requiresActive = true; // Whether the activity must be active for this transition to be available + boolean finishing; // whether the target state is a finishing state; + + // permissions + String roleOverride; + + TransitionOutcome outcome; + TransitionScript script; + + public Transition() { + } + + + public Transition(int id, String name, int originStateId, int targetStateId) { + super(); + this.id = id; + this.name = name; + this.originStateId = originStateId; + this.targetStateId = targetStateId; + } + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public State getOriginState() { + return originState; + } + + public void setOriginState(State originState) { + this.originState = originState; + } + + public State getTargetState() { + return targetState; + } + + public void setTargetState(State targetState) { + this.targetState = targetState; + finishing = targetState.finished; + } + + public String getEnabledProp() { + return enabledProp; + } + + public void setEnabledProp(String enabledProp) { + this.enabledProp = enabledProp; + } + + public boolean isRequiresActive() { + return requiresActive; + } + + public boolean isFinishing() { + return finishing; + } + + public void setRequiresActive(boolean requiresActive) { + this.requiresActive = requiresActive; + } + + public String getRoleOverride() { + return roleOverride; + } + + public void setRoleOverride(String roleOverride) { + this.roleOverride = roleOverride; + } + + public TransitionOutcome getOutcome() { + return outcome; + } + + public void setOutcome(TransitionOutcome outcome) { + this.outcome = outcome; + } + + public TransitionScript getScript() { + return script; + } + + public void setScript(TransitionScript script) { + this.script = script; + } + + public String getReservation() { + return reservation; + } + + public void setReservation(String reservation) { + this.reservation = reservation; + } + + protected boolean resolveStates(HashMap states) { + boolean allFound = true; + if (states.keySet().contains(originStateId)) { + originState = states.get(originStateId); + originState.addPossibleTransition(this); + } + else + allFound = false; + if (states.keySet().contains(targetStateId)) + targetState = states.get(targetStateId); + else + allFound = false; + return allFound; + } + + public int getOriginStateId() { + return originStateId; + } + + public void setOriginStateId(int originStateId) { + this.originStateId = originStateId; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getTargetStateId() { + return targetStateId; + } + + public void setTargetStateId(int targetStateId) { + this.targetStateId = targetStateId; + } + + public String getPerformingRole(Activity act, AgentPath agent) throws ObjectNotFoundException, AccessRightsException { + + // check available + if (!isEnabled(act.getProperties())) + throw new AccessRightsException("Transition '"+name+"' is disabled by the '"+enabledProp+"' property."); + + // check active + if (isRequiresActive() && !act.getActive()) + throw new AccessRightsException("Activity must be active to perform this transition"); + + RolePath role = null; + String overridingRole = resolveValue(roleOverride, act.getProperties()); + boolean override = overridingRole != null; + boolean isOwner = false, isOwned = true; + + // Check agent name + String agentName = act.getCurrentAgentName(); + if (agentName != null && agentName.length() >0) { + if (agent.getAgentName().equals(agentName)) + isOwner = true; + } + else isOwned = false; + + // determine transition role + if (override) { + role = Gateway.getLookup().getRolePath(overridingRole); + } + else { + String actRole = act.getCurrentAgentRole(); + if (actRole != null && actRole.length() > 0) + role = Gateway.getLookup().getRolePath(actRole); + } + + // Decide the access + if (isOwned && !override && !isOwner) + throw new AccessRightsException("Agent '"+agent.getAgentName() + +"' cannot perform this transition because the activity '"+act.getName()+"' is currently owned by "+agentName); + + if (role != null) { + if (agent.hasRole(role)) + return role.getName(); + else if (agent.hasRole("Admin")) + return "Admin"; + else + throw new AccessRightsException("Agent '"+agent.getAgentName() + +"' does not hold a suitable role '"+role.getName()+"' for the activity "+act.getName()); + } + else + return null; + } + + public String getReservation(Activity act, AgentPath agent) { + if (reservation == null || reservation.length() == 0) + reservation = targetState.finished?"clear":"set"; + + String reservedAgent = act.getCurrentAgentName(); + if (reservation.equals("set")) + reservedAgent = agent.getAgentName(); + else if (reservation.equals("clear")) + reservedAgent = ""; + return reservedAgent; + + } + + private static String resolveValue(String key, CastorHashMap props) { + if (key==null) return null; + String result = key; + Pattern propField = Pattern.compile("\\$\\{(.+?)\\}"); + Matcher propMatcher = propField.matcher(result); + while (propMatcher.find()) { + String propName = propMatcher.group(1); + Object propValue = props.get(propName); + Logger.msg(8, "Replacing Property "+propName+" as "+propValue); + String propValString = propValue==null?"":propValue.toString(); + result = result.replace("${"+propName+"}", propValString); + } + return result; + } + + public boolean isEnabled(CastorHashMap props) { + if (enabledProp == null) + return true; + return (Boolean)props.get(enabledProp); + } + + public boolean hasOutcome(CastorHashMap actProps) { + if (outcome == null || actProps == null) return false; + String outcomeName = resolveValue(outcome.schemaName, actProps); + if (outcomeName == null || outcomeName.length() == 0) + return false; + String outcomeVersion = resolveValue(outcome.schemaVersion, actProps); + if (outcomeVersion == null || outcomeVersion.length() == 0) + return false; + return true; + } + + public Schema getSchema(CastorHashMap actProps) throws InvalidDataException, ObjectNotFoundException { + if (hasOutcome(actProps)) + try { + return LocalObjectLoader.getSchema(resolveValue(outcome.schemaName, actProps), + Integer.parseInt(resolveValue(outcome.schemaVersion, actProps))); + } catch (NumberFormatException ex) { + throw new InvalidDataException("Bad schema version number: "+outcome.schemaVersion+" ("+resolveValue(outcome.schemaVersion, actProps)+")"); + } + else + return null; + } + + public String getScriptName(CastorHashMap actProps) { + return resolveValue(script.scriptName, actProps); + } + + public int getScriptVersion(CastorHashMap actProps) throws InvalidDataException { + try { + return Integer.parseInt(resolveValue(script.scriptVersion, actProps)); + } catch (NumberFormatException ex) { + throw new InvalidDataException("Bad Script version number: "+script.scriptVersion+" ("+resolveValue(script.scriptVersion, actProps)+")"); + } + } + + public boolean hasScript(CastorHashMap actProps) { + if (script == null || actProps == null) return false; + String scriptName = getScriptName(actProps); + if (scriptName == null || scriptName.length() == 0) + return false; + String scriptVersion = resolveValue(script.scriptVersion, actProps); + if (scriptVersion == null || scriptVersion.length() == 0) + return false; + return true; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + return result; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Transition other = (Transition) obj; + if (id != other.id) + return false; + return true; + } +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionOutcome.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionOutcome.java new file mode 100644 index 0000000..7575359 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionOutcome.java @@ -0,0 +1,57 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.stateMachine; + + +public class TransitionOutcome extends TransitionResource { + + // schema properties + String schemaName, schemaVersion; // Name & version of the schema of the data required for this transition. + boolean required = true; // If true, then the data must be supplied to perform the transition, otherwise it is optional + + public TransitionOutcome() { + } + + public String getSchemaName() { + return schemaName; + } + + public void setSchemaName(String schemaName) { + this.schemaName = schemaName; + } + + public String getSchemaVersion() { + return schemaVersion; + } + + public void setSchemaVersion(String schemaVersion) { + this.schemaVersion = schemaVersion; + } + + public boolean isRequired() { + return required; + } + + public void setRequired(boolean required) { + this.required = required; + } + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionResource.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionResource.java new file mode 100644 index 0000000..e220447 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionResource.java @@ -0,0 +1,29 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.stateMachine; + +public class TransitionResource { + + public TransitionResource() { + // TODO Auto-generated constructor stub + } + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionScript.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionScript.java new file mode 100644 index 0000000..a41ec2c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionScript.java @@ -0,0 +1,48 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.instance.stateMachine; + + +public class TransitionScript extends TransitionResource { + + // script properties + String scriptName, scriptVersion; // Name & version of the script to be run by the agent during this transition + + public TransitionScript() { + } + + public String getScriptName() { + return scriptName; + } + + public void setScriptName(String scriptName) { + this.scriptName = scriptName; + } + + public String getScriptVersion() { + return scriptVersion; + } + + public void setScriptVersion(String scriptVersion) { + this.scriptVersion = scriptVersion; + } + +} diff --git a/src/main/java/org/cristalise/kernel/lifecycle/package-info.java b/src/main/java/org/cristalise/kernel/lifecycle/package-info.java new file mode 100644 index 0000000..af6300b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/package-info.java @@ -0,0 +1,30 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +/** + * The implementation of the Item lifecycle, as composite workflows. + * + *

    This package contains the activity description implementations. The + * workflow instance is in the {@link org.cristalise.kernel.lifecycle.instance} + * subpackage, which also contains the predefined steps. + * + */ + +package org.cristalise.kernel.lifecycle; \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/routingHelpers/ViewpointDataHelper.java b/src/main/java/org/cristalise/kernel/lifecycle/routingHelpers/ViewpointDataHelper.java new file mode 100644 index 0000000..49bebf4 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/routingHelpers/ViewpointDataHelper.java @@ -0,0 +1,86 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lifecycle.routingHelpers; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.XmlElementParser; + + +public class ViewpointDataHelper +{ + static Object[] errArr = { "" }; + /** + * Method get. + * @param value + * @return String[] + * @throws Exception + */ + /**@param value : /UUID (or . if current) /SchemaName/Viewname/Path:XPathInOutcome */ + public static Object [] get(String value) throws Exception + { + //Syntax of search : /: + String entityPath; + String viewpoint; + String xpath; + Object[] retArr; + + // find syskey, viewname, xpath + int firstSlash = value.indexOf("/"); + if (firstSlash > 0) { + entityPath = value.substring(0, firstSlash); + int startXPath = value.indexOf(":"); + if (startXPath==-1) { + viewpoint = value.substring(firstSlash + 1); + xpath = null; + } else { + viewpoint = value.substring(firstSlash + 1, startXPath); + xpath = value.substring(startXPath+1); + } + } + else return errArr; + + // find entity + ItemPath sourcePath = new ItemPath(entityPath); + + try { + // load viewpoint + ItemProxy dataSource = Gateway.getProxyManager().getProxy(sourcePath); + Viewpoint view = (Viewpoint)dataSource.getObject(ClusterStorage.VIEWPOINT + "/" + viewpoint); + Outcome outcome = view.getOutcome(); + if (xpath == null) { + retArr = new Object[1]; + retArr[0] = outcome; + } + else + retArr = XmlElementParser.parse(outcome.getData(), xpath); + return retArr; + + } catch (ObjectNotFoundException e) { + return errArr; + } + } +} diff --git a/src/main/java/org/cristalise/kernel/lookup/AgentPath.java b/src/main/java/org/cristalise/kernel/lookup/AgentPath.java new file mode 100644 index 0000000..cab9068 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/AgentPath.java @@ -0,0 +1,159 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lookup; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.UUID; + +import org.apache.xerces.impl.dv.util.Base64; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.process.Gateway; + + + +/** +* Extends Path to enforce SystemKey structure and support int form +* +* @version $Revision: 1.12 $ $Date: 2005/10/13 08:15:00 $ +* @author $Author: abranson $ +**/ +public class AgentPath extends ItemPath +{ + + private String mAgentName=null; + private String mPassword=null; + + public AgentPath(SystemKey syskey) throws InvalidAgentPathException, InvalidItemPathException { + super(syskey); + try { + findAgentName(); + } catch (ObjectNotFoundException e) { + throw new InvalidAgentPathException(); + } + } + protected AgentPath(UUID uuid) throws InvalidAgentPathException, InvalidItemPathException { + super(uuid); + try { + findAgentName(); + } catch (ObjectNotFoundException e) { + throw new InvalidAgentPathException(); + } + } + + public AgentPath(ItemPath itemPath) throws InvalidAgentPathException { + super(itemPath.mUUID); + try { + findAgentName(); + } catch (ObjectNotFoundException e) { + throw new InvalidAgentPathException(); + } + } + + public AgentPath(ItemPath itemPath, String agentName) { + super(itemPath.mUUID); + mAgentName = agentName; + } + + public AgentPath(String path) throws InvalidItemPathException { + super(path); + try { + findAgentName(); + } catch (ObjectNotFoundException e) { + throw new InvalidAgentPathException(); + } + } + + public void setAgentName(String agentID) + { + mAgentName = agentID; + } + + public String getAgentName() + { + if (mAgentName==null) + try { + findAgentName(); + } catch (ObjectNotFoundException e) { + return null; + } + return mAgentName; + } + + private void findAgentName() throws ObjectNotFoundException { + mAgentName = Gateway.getLookup().getAgentName(this); + } + + public RolePath[] getRoles() + { + return Gateway.getLookup().getRoles(this); + } + + public boolean hasRole(RolePath role) { + return Gateway.getLookup().hasRole(this, role); + } + + public boolean hasRole(String role) { + try { + return hasRole(Gateway.getLookup().getRolePath(role)); + } catch (ObjectNotFoundException ex) { + return false; + } + } + + public void setPassword(String passwd) + { + mPassword = passwd; + } + + public String getPassword() + { + return mPassword; + } + + @Override + public String dump() { + return super.dump()+ + "\n agentID="+ + mAgentName; + } + + public static String generateUserPassword(String pass, String algo) throws NoSuchAlgorithmException { + MessageDigest sha = MessageDigest.getInstance(algo); + sha.reset(); + sha.update(pass.getBytes()); + byte hash[] = sha.digest(); + StringBuffer digest = new StringBuffer("{").append(algo).append("}"); + digest.append(Base64.encode(hash)); + return digest.toString(); + } + + public static AgentPath fromUUIDString(String uuid) throws InvalidAgentPathException { + try { + return new AgentPath(new ItemPath(uuid)); + } catch (InvalidItemPathException ex) { + throw new InvalidAgentPathException(ex.getMessage()); + } + } + +} + diff --git a/src/main/java/org/cristalise/kernel/lookup/DomainPath.java b/src/main/java/org/cristalise/kernel/lookup/DomainPath.java new file mode 100644 index 0000000..a054da6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/DomainPath.java @@ -0,0 +1,136 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lookup; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.process.Gateway; + + + +/** +* @version $Revision: 1.22 $ $Date: 2005/10/13 08:15:00 $ +* @author $Author: abranson $ +**/ +public class DomainPath extends Path +{ + private ItemPath target = null; + protected static String mTypeRoot; + +/* Very simple extension to Path. Only copies constructors and defines root */ + + public DomainPath() + { + super(Path.UNKNOWN); + } + + public DomainPath(short type) + { + super(); + mType = type; + } + + public DomainPath(String[] path) + { + super(path, Path.UNKNOWN); + } + + public DomainPath(String path) + { + super(path, Path.UNKNOWN); + } + + public DomainPath(String path, ItemPath entity) + { + super(path, Path.UNKNOWN); + setItemPath(entity); + } + + public DomainPath(DomainPath parent, String child) { + super(parent, child); + } + + /* the root of domain paths is /domain + * clearly + */ + @Override + public String getRoot() { + return "domain"; + } + + public DomainPath getParent() { + if (mPath.length == 0) + return null; + + String[] parentPath = new String[mPath.length-1]; + System.arraycopy(mPath, 0, parentPath, 0, parentPath.length); + return new DomainPath(parentPath); + } + + public void setItemPath(ItemPath newTarget) { + if (newTarget == null) { // clear + target = null; + mType = Path.CONTEXT; + return; + } + + target = newTarget; + mType = Path.ENTITY; + } + + @Override + public ItemPath getItemPath() throws ObjectNotFoundException { + if (mType == UNKNOWN) { // must decide + checkType(); + } + + if (target == null) + throw new ObjectNotFoundException("Path "+toString()+" does not resolve to an Item"); + return target; + } + + @Override + public short getType() { + if (mType == UNKNOWN) { // must decide + checkType(); + } + return mType; + } + + protected void checkType() { + try { + setItemPath(Gateway.getLookup().resolvePath(this)); + } catch (InvalidItemPathException ex) { + mType = CONTEXT; + } catch (ObjectNotFoundException ex) { + mType = CONTEXT; + } + + } + + /** + * Retrieves the domkey of the path + * @return the last path component; + */ + public String getName() { + return mPath[mPath.length-1]; + } +} + diff --git a/src/main/java/org/cristalise/kernel/lookup/InvalidAgentPathException.java b/src/main/java/org/cristalise/kernel/lookup/InvalidAgentPathException.java new file mode 100644 index 0000000..60ac840 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/InvalidAgentPathException.java @@ -0,0 +1,33 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lookup; + +public class InvalidAgentPathException extends InvalidItemPathException { + + public InvalidAgentPathException() { + super(); + } + + public InvalidAgentPathException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/org/cristalise/kernel/lookup/InvalidItemPathException.java b/src/main/java/org/cristalise/kernel/lookup/InvalidItemPathException.java new file mode 100644 index 0000000..b6817af --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/InvalidItemPathException.java @@ -0,0 +1,33 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lookup; + +public class InvalidItemPathException extends InvalidPathException { + + public InvalidItemPathException() { + super(); + } + + public InvalidItemPathException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/org/cristalise/kernel/lookup/InvalidPathException.java b/src/main/java/org/cristalise/kernel/lookup/InvalidPathException.java new file mode 100644 index 0000000..9e75c11 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/InvalidPathException.java @@ -0,0 +1,33 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lookup; + +public class InvalidPathException extends Exception { + + public InvalidPathException() { + super(); + } + + public InvalidPathException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/org/cristalise/kernel/lookup/ItemPath.java b/src/main/java/org/cristalise/kernel/lookup/ItemPath.java new file mode 100644 index 0000000..9df4a0a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/ItemPath.java @@ -0,0 +1,120 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lookup; + +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.UUID; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.SystemKey; + + + +/** +* Extends Path to enforce SystemKey structure and support int form +* +* @version $Revision: 1.14 $ $Date: 2006/03/03 13:52:21 $ +* @author $Author: abranson $ +**/ +public class ItemPath extends Path +{ + + public ItemPath() { + setSysKey(UUID.randomUUID()); + } + + protected ItemPath(UUID uuid) { + setSysKey(uuid); + } + + public ItemPath(SystemKey syskey) { + setSysKey(syskey); + } + + /* + */ + public ItemPath(String[] path) throws InvalidItemPathException + { + super(path, Path.CONTEXT); + getSysKeyFromPath(); + } + + /* + */ + public ItemPath(String path) throws InvalidItemPathException + { + super(path, Path.CONTEXT); + if (path == null) throw new InvalidItemPathException("Path cannot be null"); + getSysKeyFromPath(); + } + + private void getSysKeyFromPath() throws InvalidItemPathException { + if (mPath.length == 1) { + try { + setSysKey(UUID.fromString(mPath[0])); + mType = Path.ENTITY; + } catch (IllegalArgumentException ex) { + throw new InvalidItemPathException(mPath[0]+" is not a valid UUID"); + } + } + else + throw new InvalidItemPathException("Not a valid item path: "+Arrays.toString(mPath)); + } + + // EntityPaths root in /entity + @Override + public String getRoot() { + return "entity"; + } + + @Override + public ItemPath getItemPath() throws ObjectNotFoundException { + return this; + } + + public byte[] getOID() { + if (mType == Path.CONTEXT) return null; + ByteBuffer bb = ByteBuffer.wrap(new byte[16]); + bb.putLong(mSysKey.msb); + bb.putLong(mSysKey.lsb); + return bb.array(); + } + + protected void setSysKey(UUID uuid) { + mUUID = uuid; + mSysKey = new SystemKey(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); + setPathFromUUID(mUUID.toString()); + } + + protected void setSysKey(SystemKey sysKey) { + mSysKey = sysKey; + mUUID = new UUID(sysKey.msb, sysKey.lsb); + setPathFromUUID(mUUID.toString()); + } + + private void setPathFromUUID(String uuid) { + mPath = new String[1]; + mPath[0] = uuid; + mType = Path.ENTITY; + } +} + diff --git a/src/main/java/org/cristalise/kernel/lookup/Lookup.java b/src/main/java/org/cristalise/kernel/lookup/Lookup.java new file mode 100644 index 0000000..eb54775 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/Lookup.java @@ -0,0 +1,175 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lookup; + +import java.util.Iterator; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.process.auth.Authenticator; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyDescriptionList; + + +/** + * @author abranson + * + */ +public interface Lookup { + + /** + * Connect to the directory using the credentials supplied in the Authenticator. + * + * @param user The connected Authenticator. The Lookup implementation may use the AuthObject in this to communicate with the database. + */ + public void open(Authenticator user); + + /** + * Shutdown the lookup + */ + public void close(); + + // Path resolution + /** + * Fetch the correct subclass class of ItemPath for a particular Item, derived from its lookup entry. + * This is used by the CORBA Server to make sure the correct Item subclass is used. + * + * @param sysKey The system key of the Item + * @return an ItemPath or AgentPath + * @throws InvalidItemPathException When the system key is invalid/out-of-range + * @throws ObjectNotFoundException When the Item does not exist in the directory. + */ + public ItemPath getItemPath(String sysKey) throws InvalidItemPathException, ObjectNotFoundException; + + /** + * Find the ItemPath for which a DomainPath is an alias. + * + * @param domainPath The path to resolve + * @return The ItemPath it points to (should be an AgentPath if the path references an Agent) + * @throws InvalidItemPathException + * @throws ObjectNotFoundException + */ + public ItemPath resolvePath(DomainPath domainPath) throws InvalidItemPathException, ObjectNotFoundException; + + /** + * Resolve a path to a CORBA Object Item or Agent + * + * @param path The path to be resolved + * @return The CORBA Object + * @throws ObjectNotFoundException When the Path doesn't exist, or doesn't have an IOR associated with it + */ + public org.omg.CORBA.Object resolve(Path path) throws ObjectNotFoundException; + + // Path finding and searching + + /** + * Checks if a particular Path exists in the directory + * @param path The path to check + * @return boolean true if the path exists, false if it doesn't + */ + public boolean exists(Path path); + + /** + * List the next-level-deep children of a Path + * + * @param path The parent Path + * @return An Iterator of child Paths + */ + public Iterator getChildren(Path path); + + /** + * Find a path with a particular name (last component) + * + * @param start Search root + * @param name The name to search for + * @return An Iterator of matching Paths. Should be an empty Iterator if there are no matches. + */ + public Iterator search(Path start, String name); + + /** + * Search for Items in the specified path with the given property name and value + * @param start Search root + * @param propname Property name + * @param propvalue The property value to search for + * @return An Iterator of matching Paths + */ + public Iterator search(Path start, Property... props); + + /** + * Search for Items of a particular type, based on its PropertyDescription outcome + * @param start Search root + * @param props Properties unmarshalled from an ItemDescription's property description outcome. + * @return An Iterator of matching Paths + */ + public Iterator search(Path start, PropertyDescriptionList props); + + /** + * Find all DomainPaths that are aliases for a particular Item or Agent + * @param itemPath The ItemPath + * @return An Iterator of DomainPaths that are aliases for that Item + */ + public Iterator searchAliases(ItemPath itemPath); + + // Role and agent management + + /** + * @param agentName + * @return + * @throws ObjectNotFoundException + */ + public AgentPath getAgentPath(String agentName) throws ObjectNotFoundException; + + /** + * @param roleName + * @return + * @throws ObjectNotFoundException + */ + public RolePath getRolePath(String roleName) throws ObjectNotFoundException; + + /** + * @param rolePath + * @return + * @throws ObjectNotFoundException + */ + public AgentPath[] getAgents(RolePath rolePath) throws ObjectNotFoundException; + + /** + * @param agentPath + * @return + */ + public RolePath[] getRoles(AgentPath agentPath); + + /** + * Returns all of the Agents in this centre who hold this role (including sub-roles) + * + * @param agentPath + * @param role + * @return + */ + public boolean hasRole(AgentPath agentPath, RolePath role); + + /** + * @param agentPath + * @return + * @throws ObjectNotFoundException + */ + public String getAgentName(AgentPath agentPath) throws ObjectNotFoundException; + +} diff --git a/src/main/java/org/cristalise/kernel/lookup/LookupManager.java b/src/main/java/org/cristalise/kernel/lookup/LookupManager.java new file mode 100644 index 0000000..0ce04c3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/LookupManager.java @@ -0,0 +1,124 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lookup; + +import java.security.NoSuchAlgorithmException; + +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; + + +/** + * The LookupManager interface contains all of the directory modifying methods + * of the Lookup. This allows read-only Lookup implementations. Server processes + * will attempt to cast their Lookups into LookupManagers, and fail to start up + * if this is not possible. + * + */ +public interface LookupManager extends Lookup { + + /** + * Called when a server starts up. The Lookup implementation should ensure + * that the initial structure of its directory is valid, and create it on + * first boot. + * + * @throws ObjectNotFoundException When initialization data is not found + */ + public void initializeDirectory() throws ObjectNotFoundException; + + // Path management + + /** + * Register a new a Path in the directory. + * + * @param newPath The path to add + * @throws ObjectCannotBeUpdated When there is an error writing to the + * directory + * @throws ObjectAlreadyExistsException When the Path has already been registered + */ + public void add(Path newPath) throws ObjectCannotBeUpdated, ObjectAlreadyExistsException; + + /** + * Remove a Path from the directory. + * + * @param path The path to remove + * @throws ObjectCannotBeUpdated When an error occurs writing to the directory + */ + public void delete(Path path) throws ObjectCannotBeUpdated; + + // Role and agent management + + /** + * Creates a new Role. Called by the server predefined step 'CreateNewRole' + * + * @param role The new role path + * @return + * @throws ObjectAlreadyExistsException + * @throws ObjectCannotBeUpdated + */ + public RolePath createRole(RolePath role) throws ObjectAlreadyExistsException, ObjectCannotBeUpdated; + + /** + * Adds the given Agent to the given Role, if they both exist. + * + * @param agent + * @param rolePath + * @throws ObjectCannotBeUpdated + * @throws ObjectNotFoundException + */ + public void addRole(AgentPath agent, RolePath rolePath) throws ObjectCannotBeUpdated, ObjectNotFoundException; + + /** + * Remove the given Agent from the given Role. Does not delete the Role. + * + * @param agent + * @param role + * @throws ObjectCannotBeUpdated + * @throws ObjectNotFoundException + */ + public void removeRole(AgentPath agent, RolePath role) throws ObjectCannotBeUpdated, ObjectNotFoundException; + + /** + * Set an Agent's password + * + * @param agent The Agent + * @param newPassword The Agent's new password + * @throws ObjectNotFoundException + * @throws ObjectCannotBeUpdated + * @throws NoSuchAlgorithmException + */ + public void setAgentPassword(AgentPath agent, String newPassword) throws ObjectNotFoundException, ObjectCannotBeUpdated, NoSuchAlgorithmException; + + /** + * Set the flag specifying whether Activities holding this Role should push + * Jobs its Agents. + * + * @param role The role to modify + * @param hasJobList boolean flag + * + * @throws ObjectNotFoundException When the Role doesn't exist + * @throws ObjectCannotBeUpdated + */ + public void setHasJobList(RolePath role, boolean hasJobList) throws ObjectNotFoundException, ObjectCannotBeUpdated; + + +} diff --git a/src/main/java/org/cristalise/kernel/lookup/Path.java b/src/main/java/org/cristalise/kernel/lookup/Path.java new file mode 100644 index 0000000..77bca9b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/Path.java @@ -0,0 +1,243 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lookup; + +import java.util.ArrayList; +import java.util.StringTokenizer; +import java.util.UUID; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.process.Gateway; + + + +/** +* +**/ +public abstract class Path +{ + public static final String delim = "/"; + + // types + public static final short UNKNOWN = 0; + public static final short CONTEXT = 1; + public static final short ENTITY = 2; + + protected String[] mPath = new String[0]; + + // slash delimited path + protected String mStringPath = null; + // entity or context + protected short mType = CONTEXT; + + // item UUID (only valid for ItemPaths and DomainPaths that are aliases for Items) + protected UUID mUUID; + protected SystemKey mSysKey; + + // ior is stored in here when it is resolved + protected org.omg.CORBA.Object mIOR = null; + + public Path() { + } + + /* + * Creates an empty path + */ + public Path(short type) + { + mType = type; + } + + /* + * Creates a path with an arraylist of the path (big endian) + */ + public Path(String[] path, short type) { + setPath(path); + mType = type; + } + + /* + * Creates a path from a slash separated string (big endian) + */ + public Path(String path, short type) { + setPath(path); + mType = type; + } + + /* + * Create a path by appending a child string to an existing path + */ + public Path(Path parent, String child, short type) { + String[] oldPath = parent.getPath(); + mPath = new String[oldPath.length+1]; + for (int i=0; i newPath = new ArrayList(); + if (path != null) { + StringTokenizer tok = new StringTokenizer(path, delim); + if (tok.hasMoreTokens()) { + String first = tok.nextToken(); + if (!first.equals(getRoot())) + newPath.add(first); + while (tok.hasMoreTokens()) + newPath.add(tok.nextToken()); + } + } + + mPath = (newPath.toArray(mPath)); + mStringPath = null; + mUUID = null; + mSysKey = null; + } + + // lookup sets the IOR + public void setIOR(org.omg.CORBA.Object IOR) { + mIOR = IOR; + if (IOR == null) mType = Path.CONTEXT; + else mType = Path.ENTITY; + } + + /* clone another path object + */ + public void setPath(Path path) + { + mStringPath = null; + mPath = (path.getPath().clone()); + mUUID = null; + mSysKey = null; + } + + /*************************************************************************/ + + + /* + * Getter Methods + */ + + // root is defined as 'domain', 'entity' or 'system' in subclasses + public abstract String getRoot(); + + public String[] getPath() + { + return mPath; + } + + public String getString() + { + if (mStringPath == null) { + StringBuffer stringPathBuffer = new StringBuffer("/").append(getRoot()); + for (String element : mPath) + stringPathBuffer.append(delim).append(element); + mStringPath = stringPathBuffer.toString(); + } + return mStringPath; + } + + public boolean exists() { + return Gateway.getLookup().exists(this); + } + + /** Queries the lookup for the IOR + */ + + public org.omg.CORBA.Object getIOR() { + org.omg.CORBA.Object newIOR = null; + if (mIOR==null) { // if not cached try to resolve + Lookup myLookup = Gateway.getLookup(); + try { + newIOR = myLookup.resolve(this); + } catch (ObjectNotFoundException ex) { + } + setIOR(newIOR); + } + return mIOR; + } + + @Override + public String toString() { + return getString(); + } + + public short getType() { + return mType; + } + + public SystemKey getSystemKey() { + return mSysKey; + } + + public UUID getUUID() { + return mUUID; + } + + public abstract ItemPath getItemPath() throws ObjectNotFoundException; + + @Override + public boolean equals( Object path ) + { + if (path == null) return false; + return toString().equals(path.toString()); + } + + @Override + public int hashCode() { + return toString().hashCode(); + } + + public String dump() { + StringBuffer comp = new StringBuffer("Components: { "); + for (String element : mPath) + comp.append("'").append(element).append("' "); + return "Path - dump(): "+comp.toString()+"}\n string="+toString()+"\n uuid="+getUUID()+"\n type="+mType; + } +} + diff --git a/src/main/java/org/cristalise/kernel/lookup/RolePath.java b/src/main/java/org/cristalise/kernel/lookup/RolePath.java new file mode 100644 index 0000000..61f444c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/RolePath.java @@ -0,0 +1,116 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.lookup; + +import java.util.Iterator; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.process.Gateway; + + + + +/** +* @version $Revision: 1.7 $ $Date: 2005/04/26 06:48:12 $ +* @author $Author: abranson $ +**/ +public class RolePath extends DomainPath +{ + /** + * + */ + + private boolean hasJobList = false; + + public RolePath() { + super("agent"); + } + + @Override + public RolePath getParent() { + try { + if (mPath.length > 2) + return Gateway.getLookup().getRolePath(mPath[mPath.length-2]); + } catch (ObjectNotFoundException ex) { } + return null; + } + + public RolePath(RolePath parent, String roleName) { + super(parent, roleName); + } + + public RolePath(String[] path, boolean jobList) { + super(path); + hasJobList = jobList; + } + + public RolePath(RolePath parent, String roleName, boolean jobList) { + this(parent, roleName); + hasJobList = jobList; + } + + /** + * @return Returns the hasJobList. + */ + public boolean hasJobList() { + return hasJobList; + } + /** + * @param hasJobList The hasJobList to set. + * @throws ObjectCannotBeUpdated + * @throws ObjectNotFoundException + * @throws CannotManageException + */ + public void setHasJobList(boolean hasJobList) throws ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException { + this.hasJobList = hasJobList; + } + + + @Override + protected void checkType() { + mType = CONTEXT; + } + + public Iterator getChildren() { + return Gateway.getLookup().getChildren(this); + } + + @Override + public String dump() { + StringBuffer comp = new StringBuffer("Components: { "); + for (String element : mPath) + comp.append("'").append(element).append("' "); + + return "Path - dump(): "+ + comp.toString()+ + "}\n string="+ + toString()+ + "\n type="+ + mType+ + "\n name="+ + getName()+ + "\n "; + } + +} + diff --git a/src/main/java/org/cristalise/kernel/persistency/ClusterStorage.java b/src/main/java/org/cristalise/kernel/persistency/ClusterStorage.java new file mode 100644 index 0000000..ca43e67 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/ClusterStorage.java @@ -0,0 +1,296 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.persistency; + +import org.cristalise.kernel.collection.Collection; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.auth.Authenticator; +import org.cristalise.kernel.utils.Logger; + + +/** + *

    Interface for persistency managers of entities. It allows different kernel + * objects to be stored in different backend. For instance, Properties may be + * stored in LDAP, while Events, Outcomes and Viewpoints could be stored in a + * relational database. The kernel does and needs no analytical querying of the + * ClusterStorages, only simple gets and puts. This may be implemented on top + * of the storage implementation separately. + * + *

    Each item is indexed by its {@link ItemPath}, which is may be constructed from its + * UUID, equivalent {@link SystemKey} object, or + * + *

    Each first-level path under the Item is defined as a Cluster. Different + * Clusters may be stored in different places. Each ClusterStorage must support + * {@link #get(ItemPath, String)} and + * {@link #getClusterContents(ItemPath, String)} for clusters they return + * {@link #READ} and {@link #READWRITE} from queryClusterSupport and + * {@link #put(ItemPath, C2KLocalObject)} and {@link #delete(ItemPath, String)} + * for clusters they return {@link #WRITE} and {@link #READWRITE} from + * {@link #getClusterContents(ItemPath, String)}. Operations that have not been + * declared as not supported should throw a PersistencyException. If a + * cluster does not exist, get should return null, and delete should return with + * no action. + */ +public abstract class ClusterStorage { + + /** + * Constant to return from {@link #queryClusterSupport(String)} for Cluster + * types this storage does not support. + */ + public static final short NONE = 0; + /** + * Constant to return from {@link #queryClusterSupport(String)} for Cluster + * types this storage can read from a database but not write. An example + * would be pre-existing data in a database that is mapped to Items in some + * way. + */ + public static final short READ = 1; + /** + * Constant to return from {@link #queryClusterSupport(String)} for Cluster + * types this storage can write to a database but not read. An example would + * be a realtime database export of data, which is transformed in an + * unrecoverable way for use in other systems. + */ + public static final short WRITE = 2; + /** + * Constant to return from {@link #queryClusterSupport(String)} for data + * stores that CRISTAL may use for both reading and writing for the given + * Cluster type. + */ + public static final short READWRITE = 3; + + // Cluster types + /** + * The defined path of the root of the CRISTAL Kernel object cluster tree. A + * zero-length string. + */ + public static final String ROOT = ""; + /** + * The root of the Property object cluster. All Property paths start with + * this. Defined as "Property". Properties are stored underneath according + * to their name e.g. "Property/Name" + */ + public static final String PROPERTY = "Property"; + /** + * The root of the Collection object cluster. All Collection paths start + * with this. Defined as "Collection". Collections are stored underneath by + * name e.g. "Collection/Composition" + */ + public static final String COLLECTION = "Collection"; + /** + * The cluster which holds the Item workflow. Defined as "LifeCycle". Holds + * the workflow inside, which is named "workflow", hence + * "LifeCycle/workflow". + * + * @see org.cristalise.kernel.lifecycle.instance.Workflow + */ + public static final String LIFECYCLE = "LifeCycle"; + /** + * This cluster holds all outcomes of this Item. The path to each outcome is + * "Outcome/Schema Name/Schema Version/Event ID" + */ + public static final String OUTCOME = "Outcome"; + /** + * This is the cluster that contains all event for this Item. This cluster + * may be instantiated in a client as a History, which is a RemoteMap. + * Events are stored with their ID: "/AuditTrail/Event ID" + */ + public static final String HISTORY = "AuditTrail"; + /** + * This cluster contains all viewpoints. Its name is defined as "ViewPoint". + * The paths of viewpoint objects stored here follow this pattern: + * "ViewPoint/Schema Name/Viewpoint Name" + */ + public static final String VIEWPOINT = "ViewPoint"; + /** + * Agents store their persistent jobs in this cluster that have been pushed + * to them by activities configured to do so. The name is defined as "Job" + * and each new job received is assigned an integer ID one more than the + * highest already present. + */ + public static final String JOB = "Job"; + + /** + * An array of all currently supported cluster types, for iterative + * purposes. + */ + public static final String[] allClusterTypes = { PROPERTY, COLLECTION, + LIFECYCLE, OUTCOME, HISTORY, VIEWPOINT, JOB }; + + /** + * Connects to the storage. It must be possible to retrieve CRISTAL local + * objects after this method returns. + * + * @param auth + * The Authenticator instance that the user or server logged in + * with. + * @throws PersistencyException + * If storage initialization failed + */ + public abstract void open(Authenticator auth) + throws PersistencyException; + + /** + * Shuts down the storage. Data must be completely written to disk before + * this method returns, so the process can exit. No further gets or puts + * should follow. + * + * @throws PersistencyException + * If closing failed + */ + public abstract void close() throws PersistencyException; + + /** + * Declares whether or not this ClusterStorage can read or write a + * particular CRISTAL local object type. + * + * @param clusterType + * The Cluster type requested. Must be one of the Cluster type + * constants from this class. + * @return A ClusterStorage constant: NONE, READ, WRITE, or READWRITE + */ + public abstract short queryClusterSupport(String clusterType); + + /** + * @return A full name of this storage for logging + */ + public abstract String getName(); + + /** + * @return A short code for this storage for reference + */ + public abstract String getId(); + + /** + * Utility method to find the cluster for a particular Local Object (the + * first part of its path) + * + * @param Local + * object path + * @return The cluster to which it belongs + */ + protected static String getClusterType(String path) { + try { + if (path == null || path.length() == 0) + return ClusterStorage.ROOT; + int start = path.charAt(0) == '/' ? 1 : 0; + int end = path.indexOf('/', start + 1); + if (end == -1) + end = path.length(); + return path.substring(start, end); + } catch (Exception ex) { + Logger.error(ex); + return ClusterStorage.ROOT; + } + } + + /** + * Gives the path for a local object. Varies by Cluster. + * + * @param C2KLocalObject + * @return Its path + */ + public static String getPath(C2KLocalObject obj) { + String root = obj.getClusterType(); + if (root == null) + return null; // no storage allowed + if (obj instanceof Outcome) { + Outcome oc = (Outcome) obj; + return root + "/" + oc.getSchemaType() + "/" + + oc.getSchemaVersion() + "/" + oc.getName(); + } else if (obj instanceof Viewpoint) { + Viewpoint vp = (Viewpoint) obj; + return root + "/" + vp.getSchemaName() + "/" + vp.getName(); + } else if (obj instanceof Collection) { + Collection coll = (Collection) obj; + return root + "/" + coll.getName() + "/" +coll.getVersionName(); + } + return root + "/" + obj.getName(); + } + + /* object manipulation */ + + // retrieve object by path + /** + * Fetches a CRISTAL local object from storage + * + * @param itemPath + * The ItemPath of the containing Item + * @param path + * The path of the local object + * @return The C2KLocalObject, or null if the object was not found + * @throws PersistencyException + * when retrieval failed + */ + public abstract C2KLocalObject get(ItemPath itemPath, String path) + throws PersistencyException; + + /** + * Stores a CRISTAL local object. The path is automatically generated. + * + * @param itemPath + * The Item that the object will be stored under + * @param obj + * The C2KLocalObject to store + * @throws PersistencyException + * When storage fails + */ + public abstract void put(ItemPath itemPath, C2KLocalObject obj) + throws PersistencyException; + + /** + * Remove a CRISTAL local object from storage. This should be used sparingly + * and responsibly, as it violated traceability. Objects removed in this way + * are not expected to be recoverable. + * + * @param itemPath + * The containing Item + * @param path + * The path of the object to be removed + * @throws PersistencyException + * When deletion fails or is not allowed + */ + public abstract void delete(ItemPath itemPath, String path) + throws PersistencyException; + + // directory listing + /** + * Queries the local path below the given root and returns the possible next + * elements. + * + * @param itemPath + * The Item to query + * @param path + * The path within that Item to query. May be ClusterStorage.ROOT + * (empty String) + * @return A String array of the possible next path elements + * @throws PersistencyException + * When an error occurred during the query + */ + public abstract String[] getClusterContents(ItemPath itemPath, String path) + throws PersistencyException; + +} diff --git a/src/main/java/org/cristalise/kernel/persistency/ClusterStorageManager.java b/src/main/java/org/cristalise/kernel/persistency/ClusterStorageManager.java new file mode 100644 index 0000000..46485b6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/ClusterStorageManager.java @@ -0,0 +1,413 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.persistency; + +import java.util.ArrayList; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.StringTokenizer; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.agent.JobList; +import org.cristalise.kernel.entity.proxy.ProxyMessage; +import org.cristalise.kernel.events.History; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.process.auth.Authenticator; +import org.cristalise.kernel.utils.Logger; +import org.cristalise.kernel.utils.SoftCache; +import org.cristalise.kernel.utils.WeakCache; + + +/** + * instantiates ClusterStorages listed in properties file All read/write requests to storage pass through this object, which + * can query the capabilities of each declared storage, and channel requests accordingly. Transaction based. + * + * * @version $Revision: 1.62 $ $Date: 2006/02/01 13:27:46 $ + * @author $Author: abranson $ + */ +public class ClusterStorageManager { + HashMap allStores = new HashMap(); + String[] clusterPriority = new String[0]; + HashMap> clusterWriters = new HashMap>(); + HashMap> clusterReaders = new HashMap>(); + // we don't need a soft cache for the top level cache - the proxies and entities clear that when reaped + HashMap> memoryCache = new HashMap>(); + + /** + * Initialises all ClusterStorage handlers listed by class name in the property "ClusterStorages" + * This property is usually process specific, and so should be in the server/client.conf and not the connect file. + */ + public ClusterStorageManager(Authenticator auth) throws PersistencyException { + Object clusterStorageProp = Gateway.getProperties().getObject("ClusterStorage"); + if (clusterStorageProp == null || clusterStorageProp.equals("")) { + throw new PersistencyException("ClusterStorageManager.init() - no ClusterStorages defined. No persistency!"); + } + + ArrayList rootStores; + if (clusterStorageProp instanceof String) + rootStores = instantiateStores((String)clusterStorageProp); + else if (clusterStorageProp instanceof ArrayList) { + ArrayList propStores = (ArrayList)clusterStorageProp; + rootStores = new ArrayList(); + clusterPriority = new String[propStores.size()]; + for (Object thisStore : propStores) { + if (thisStore instanceof ClusterStorage) + rootStores.add((ClusterStorage)thisStore); + else + throw new PersistencyException("Supplied ClusterStorage "+thisStore.toString()+" was not an instance of ClusterStorage"); + } + } + else { + throw new PersistencyException("Unknown class of ClusterStorage property: "+clusterStorageProp.getClass().getName()); + } + + int clusterNo = 0; + for (ClusterStorage newStorage : rootStores) { + try { + newStorage.open(auth); + } catch (PersistencyException ex) { + Logger.error(ex); + throw new PersistencyException("ClusterStorageManager.init() - Error initialising storage handler " + newStorage.getClass().getName() + + ": " + ex.getMessage()); + } + Logger.msg(5, "ClusterStorageManager.init() - Cluster storage " + newStorage.getClass().getName() + + " initialised successfully."); + allStores.put(newStorage.getId(), newStorage); + clusterPriority[clusterNo++] = newStorage.getId(); + } + clusterReaders.put(ClusterStorage.ROOT, rootStores); // all storages are queried for clusters at the root level + + } + + public ArrayList instantiateStores(String allClusters) throws PersistencyException { + ArrayList rootStores = new ArrayList(); + StringTokenizer tok = new StringTokenizer(allClusters, ","); + clusterPriority = new String[tok.countTokens()]; + + while (tok.hasMoreTokens()) { + ClusterStorage newStorage = null; + String newStorageClass = tok.nextToken(); + try { + try { + newStorage = (ClusterStorage)(Class.forName(newStorageClass).newInstance()); + } catch (ClassNotFoundException ex2) { + newStorage = (ClusterStorage)(Class.forName("org.cristalise.storage."+newStorageClass).newInstance()); + } + } catch (ClassNotFoundException ex) { + throw new PersistencyException("ClusterStorageManager.init() - The cluster storage handler class " + newStorageClass + + " could not be found."); + } catch (InstantiationException ex) { + throw new PersistencyException("ClusterStorageManager.init() - The cluster storage handler class " + newStorageClass + + " could not be instantiated."); + } catch (IllegalAccessException ex) { + throw new PersistencyException("ClusterStorageManager.init() - The cluster storage handler class " + newStorageClass + + " was not allowed to be instantiated."); + } + rootStores.add(newStorage); + } + return rootStores; + } + + public void close() { + for (ClusterStorage thisStorage : allStores.values()) { + try { + thisStorage.close(); + } catch (PersistencyException ex) { + Logger.error(ex); + } + } + } + + /** + * Returns the loaded storage that declare that they can handle writing or reading the specified cluster name (e.g. + * Collection, Property) Must specify if the request is a read or a write. + */ + private ArrayList findStorages(String clusterType, boolean forWrite) { + + // choose the right cache for readers or writers + HashMap> cache; + if (forWrite) + cache = clusterWriters; + else + cache = clusterReaders; + + // check to see if we've been asked to do this before + if (cache.containsKey(clusterType)) + return cache.get(clusterType); + + // not done yet, we'll have to query them all + Logger.msg(7, "ClusterStorageManager.findStorages() - finding storage for "+clusterType+" forWrite:"+forWrite); + ArrayList useableStorages = new ArrayList(); + for (String element : clusterPriority) { + ClusterStorage thisStorage = allStores.get(element); + short requiredSupport = forWrite ? ClusterStorage.WRITE : ClusterStorage.READ; + if ((thisStorage.queryClusterSupport(clusterType) & requiredSupport) == requiredSupport) { + Logger.msg(7, "ClusterStorageManager.findStorages() - Got "+thisStorage.getName()); + useableStorages.add(thisStorage); + } + } + cache.put(clusterType, useableStorages); + return useableStorages; + } + + /** + * Retrieves the ids of the next level of a cluster + * Does not look in any currently open transactions. + */ + public String[] getClusterContents(ItemPath itemPath, String path) throws PersistencyException { + + ArrayList contents = new ArrayList(); + // get all readers + Logger.msg(8, "ClusterStorageManager.getClusterContents() - Finding contents of "+path); + ArrayList readers = findStorages(ClusterStorage.getClusterType(path), false); + // try each in turn until we get a result + for (ClusterStorage thisReader : readers) { + try { + String[] thisArr = thisReader.getClusterContents(itemPath, path); + if (thisArr != null) { + for (int j = 0; j < thisArr.length; j++) + if (!contents.contains(thisArr[j])) { + Logger.msg(9, "ClusterStorageManager.getClusterContents() - "+thisReader.getName()+" reports "+thisArr[j]); + contents.add(thisArr[j]); + } + } + } catch (PersistencyException e) { + Logger.msg(5, "ClusterStorageManager.getClusterContents() - reader " + thisReader.getName() + + " could not retrieve contents of " + itemPath + "/" + path + ": " + e.getMessage()); + } + } + + String[] retArr = new String[0]; + retArr = contents.toArray(retArr); + return retArr; + } + + /** Internal get method. Retrieves clusters from ClusterStorages & maintains the memory cache */ + public C2KLocalObject get(ItemPath itemPath, String path) throws PersistencyException, ObjectNotFoundException { + C2KLocalObject result = null; + // check cache first + Map sysKeyMemCache = null; + sysKeyMemCache = memoryCache.get(itemPath); + if (sysKeyMemCache != null) { + synchronized(sysKeyMemCache) { + C2KLocalObject obj = sysKeyMemCache.get(path); + if (obj != null) { + Logger.msg(7, "ClusterStorageManager.get() - found "+itemPath+"/"+path+" in memcache"); + return obj; + } + } + } + + // special case - loading viewpoint contents + if (path.startsWith(ClusterStorage.VIEWPOINT) && + path.endsWith("/data")) { + StringTokenizer tok = new StringTokenizer(path,"/"); + if (tok.countTokens() == 4) { // to not catch viewpoints called 'data' + Outcome data = null; + Viewpoint view = (Viewpoint)get(itemPath, path.substring(0, path.lastIndexOf("/"))); + if (view != null) + data = view.getOutcome(); + return data; + } + } + + // deal out top level remote maps + if (path.indexOf('/') == -1) { + if (path.equals(ClusterStorage.HISTORY)) + result = new History(itemPath, null); + if (path.equals(ClusterStorage.JOB)) + result = new JobList(itemPath, null); + if (result!=null) { + synchronized(sysKeyMemCache) { + sysKeyMemCache.put(path, result); + } + return result; + } + + } + + // else try each reader in turn until we find it + ArrayList readers = findStorages(ClusterStorage.getClusterType(path), false); + for (ClusterStorage thisReader : readers) { + try { + result = thisReader.get(itemPath, path); + Logger.msg(7, "ClusterStorageManager.get() - reading "+path+" from "+thisReader.getName() + " for item " + itemPath); + if (result != null) { // got it! + // store it in the cache + if (sysKeyMemCache == null) { // create cache if needed + boolean useWeak = Gateway.getProperties().getBoolean("Storage.useWeakCache", false); + Logger.msg(7,"ClusterStorageManager.put() - Creating "+(useWeak?"Weak":"Strong")+" cache for item "+itemPath); + sysKeyMemCache = useWeak?new WeakCache():new SoftCache(0); + synchronized (memoryCache) { + memoryCache.put(itemPath, sysKeyMemCache); + } + } + synchronized(sysKeyMemCache) { + sysKeyMemCache.put(path, result); + } + // then return it + return result; + } + } catch (PersistencyException e) { + Logger.msg(7, "ClusterStorageManager.get() - reader " + thisReader.getName() + " could not retrieve " + itemPath + + "/" + path + ": " + e.getMessage()); + } + } + throw new ObjectNotFoundException("ClusterStorageManager.get() - Path " + path + " not found in " + itemPath); + } + + /** Internal put method. Creates or overwrites a cluster in all writers. Used when committing transactions. */ + public void put(ItemPath itemPath, C2KLocalObject obj) throws PersistencyException { + String path = ClusterStorage.getPath(obj); + ArrayList writers = findStorages(ClusterStorage.getClusterType(path), true); + for (ClusterStorage thisWriter : writers) { + try { + Logger.msg(7, "ClusterStorageManager.put() - writing "+path+" to "+thisWriter.getName()); + thisWriter.put(itemPath, obj); + } catch (PersistencyException e) { + Logger.error("ClusterStorageManager.put() - writer " + thisWriter.getName() + " could not store " + + itemPath + "/" + path + ": " + e.getMessage()); + throw e; + } + } + // put in mem cache if that worked + Map sysKeyMemCache; + if (memoryCache.containsKey(itemPath)) + sysKeyMemCache = memoryCache.get(itemPath); + else { + boolean useWeak = Gateway.getProperties().getBoolean("Storage.useWeakCache", false); + Logger.msg(7,"ClusterStorageManager.put() - Creating "+(useWeak?"Weak":"Strong")+" cache for entity "+itemPath); + sysKeyMemCache = useWeak?new WeakCache():new SoftCache(0); + synchronized (memoryCache) { + memoryCache.put(itemPath, sysKeyMemCache); + } + } + + synchronized(sysKeyMemCache) { + sysKeyMemCache.put(path, obj); + } + + if (Logger.doLog(9)) dumpCacheContents(9); + + // transmit proxy event + Gateway.getProxyServer().sendProxyEvent( new ProxyMessage(itemPath, path, ProxyMessage.ADDED)); + } + + /** Deletes a cluster from all writers */ + public void remove(ItemPath itemPath, String path) throws PersistencyException { + ArrayList writers = findStorages(ClusterStorage.getClusterType(path), true); + for (ClusterStorage thisWriter : writers) { + try { + Logger.msg(7, "ClusterStorageManager.delete() - removing "+path+" from "+thisWriter.getName()); + thisWriter.delete(itemPath, path); + } catch (PersistencyException e) { + Logger.error("ClusterStorageManager.delete() - writer " + thisWriter.getName() + " could not delete " + itemPath + + "/" + path + ": " + e.getMessage()); + throw e; + } + } + + if (memoryCache.containsKey(itemPath)) { + Map itemMemCache = memoryCache.get(itemPath); + synchronized (itemMemCache) { + itemMemCache.remove(path); + } + } + + + // transmit proxy event + Gateway.getProxyServer().sendProxyEvent( new ProxyMessage(itemPath, path, ProxyMessage.DELETED)); + } + + public void clearCache(ItemPath itemPath, String path) { + Logger.msg(7, "CSM.clearCache() - removing "+itemPath+"/"+path); + + if (memoryCache.containsKey(itemPath)) { + Map sysKeyMemCache = memoryCache.get(itemPath); + synchronized(sysKeyMemCache) { + for (Iterator iter = sysKeyMemCache.keySet().iterator(); iter.hasNext();) { + String thisPath = iter.next(); + if (thisPath.startsWith(path)) { + Logger.msg(7, "CSM.clearCache() - removing "+itemPath+"/"+thisPath); + iter.remove(); + } + } + } + } + } + + public void clearCache(ItemPath itemPath) { + + Logger.msg(5, "CSM.clearCache() - removing entire cache of "+itemPath); + + if (memoryCache.containsKey(itemPath)) { + synchronized (memoryCache) { + if (Logger.doLog(6)) { + Map sysKeyMemCache = memoryCache.get(itemPath); + int size = sysKeyMemCache.size(); + Logger.msg(6, "CSM.clearCache() - "+size+" objects to remove."); + } + memoryCache.remove(itemPath); + } + } + else + Logger.msg(6, "CSM.clearCache() - No objects cached"); + } + + public void clearCache() { + synchronized (memoryCache) { + memoryCache.clear(); + } + Logger.msg(5, "CSM.clearCache() - cleared entire cache, "+memoryCache.size()+" entities."); + } + + public void dumpCacheContents(int logLevel) { + if (!Logger.doLog(logLevel)) return; + synchronized(memoryCache) { + for (ItemPath itemPath : memoryCache.keySet()) { + Logger.msg(logLevel, "Cached Objects of Entity "+itemPath); + Map sysKeyMemCache = memoryCache.get(itemPath); + try { + synchronized(sysKeyMemCache) { + for (Object name : sysKeyMemCache.keySet()) { + String path = (String) name; + try { + Logger.msg(logLevel, " Path "+path+": "+sysKeyMemCache.get(path).getClass().getName()); + } catch (NullPointerException e) { + Logger.msg(logLevel, " Path "+path+": reaped"); + } + } + } + } catch (ConcurrentModificationException ex) { + Logger.msg(logLevel, "Cache modified - aborting"); + } + } + Logger.msg(logLevel, "Total number of cached entities: "+memoryCache.size()); + } + } +} diff --git a/src/main/java/org/cristalise/kernel/persistency/RemoteMap.java b/src/main/java/org/cristalise/kernel/persistency/RemoteMap.java new file mode 100644 index 0000000..deb8f0b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/RemoteMap.java @@ -0,0 +1,398 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.persistency; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.Set; +import java.util.TreeMap; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.entity.proxy.MemberSubscription; +import org.cristalise.kernel.entity.proxy.ProxyObserver; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +/** + * Maps a storage cluster onto a java.util.Map + * + * @author Andrew Branson + * $Revision: 1.22 $ + * $Date: 2006/03/03 13:52:21 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + */ +public class RemoteMap extends TreeMap implements C2KLocalObject { + + private int mID=-1; + private String mName; + protected ItemPath mItemPath; + private String mPath = ""; + Object keyLock = null; + TransactionManager storage; + ProxyObserver listener; + Comparator comp; + ItemProxy source; + Object mLocker; // if this remote map will participate in a transaction + + public RemoteMap(ItemPath itemPath, String path, Object locker) { + + super(new Comparator() { + @Override + public int compare(String o1, String o2) { + Integer i1 = null, i2 = null; + try { + i1 = Integer.valueOf(o1); + i2 = Integer.valueOf(o2); + return i1.compareTo(i2); + } catch (NumberFormatException ex) { } + return o1.compareTo(o2); + } + }); + + mItemPath = itemPath; + mLocker = locker; + + // split the path into path/name + int lastSlash = path.lastIndexOf("/"); + mName = path.substring(lastSlash+1); + if (lastSlash>0) mPath = path.substring(0,lastSlash); + + // see if the name is also a suitable id + try { + mID = Integer.parseInt(mName); + } catch (NumberFormatException e) {} + storage = Gateway.getStorage(); + + listener = new ProxyObserver() { + @Override + public void add(V obj) { + synchronized (this) { + putLocal(obj.getName(), obj); + } + } + + @Override + public void remove(String id) { + synchronized (this) { + removeLocal(id); + } + } + + @Override + public void control(String control, String msg) { } + }; + + try { + source = Gateway.getProxyManager().getProxy(mItemPath); + source.subscribe(new MemberSubscription(listener, path, false)); + } catch (Exception ex) { + Logger.error("Error subscribing to remote map. Changes will not be received"); + Logger.error(ex); + } + } + + protected void loadKeys() { + if (keyLock != null) return; + clear(); + keyLock = new Object(); + synchronized(this) { + String[] keys; + try { + keys = storage.getClusterContents(mItemPath, mPath+mName); + for (String key : keys) super.put(key, null); + } catch (PersistencyException e) { + Logger.error(e); + } + + } + } + + public synchronized int getLastId() { + loadKeys(); + if (size() == 0) return -1; + try { + return Integer.parseInt(lastKey()); + } catch (NumberFormatException ex) { + return -1; + } + } + + + // c2kLocalObject methods + public void setID(int id) { mID = id; } + + public int getID() { return mID; } + + @Override + public void setName(String name) { mName = name; } + + @Override + public String getName() { return mName; } + + /** + * Cannot be stored + */ + @Override + public String getClusterType() { + return null; + } + /** + * @see java.util.Map#clear() + */ + @Override + public synchronized void clear() { + synchronized (this) { + super.clear(); + } + keyLock = null; + } + + + + /** + * @see java.util.Map#containsKey(Object) + */ + @Override + public synchronized boolean containsKey(Object key) { + if (keyLock == null) loadKeys(); + return super.containsKey(key); + } + + /** + * This must retrieve all the values until a match is made. + * Very expensive, but if you must, you must. + * @see java.util.Map#containsValue(Object) + */ + @Override + public synchronized boolean containsValue(Object value) { + loadKeys(); + synchronized(this) { + for (String key: keySet()) { + if (get(key).equals(value)) return true; + } + } + return false; + } + + + /** + * @see java.util.Map#get(Object) + */ + @Override + public synchronized V get(Object objKey) { + loadKeys(); + String key; + if (objKey instanceof Integer) + key = ((Integer)objKey).toString(); + else if (objKey instanceof String) + key = (String)objKey; + else + return null; + + synchronized(this) { + try { + V value = super.get(key); + if (value == null) { + value = (V)storage.get(mItemPath, mPath+mName+"/"+key, mLocker); + super.put(key, value); + } + return value; + } catch (PersistencyException e) { + Logger.error(e); + } catch (ObjectNotFoundException e) { + Logger.error(e); + } + } + return null; + } + + /** + * @see java.util.Map#isEmpty() + */ + @Override + public synchronized boolean isEmpty() { + loadKeys(); + return super.isEmpty(); + } + + /** + * @see java.util.Map#keySet() + */ + @Override + public synchronized Set keySet() { + loadKeys(); + return super.keySet(); + } + + /** + * Inserts the given object into the storage + * the key is ignored - it can be fetched from the value. + * @see java.util.Map#put(Object, Object) + */ + @Override + public synchronized V put(String key, V value) { + try { + synchronized(this) { + storage.put(mItemPath, value, mLocker); + return putLocal(key, value); + } + } catch (PersistencyException e) { + Logger.error(e); + return null; + } + } + + protected synchronized V putLocal(String key, V value) { + return super.put(key, value); + } + + /** + * @see java.util.Map#remove(Object) + */ + @Override + public synchronized V remove(Object key) { + loadKeys(); + if (containsKey(key)) try { + synchronized(keyLock) { + storage.remove(mItemPath, mPath+mName+"/"+key, mLocker); + return super.remove(key); + } + } catch (PersistencyException e) { + Logger.error(e); + } + return null; + } + + protected synchronized V removeLocal(Object key) { + return super.remove(key); + } + + /** + * @see java.util.Map#size() + */ + @Override + public synchronized int size() { + loadKeys(); + return super.size(); + } + + /** + * @see java.util.Map#values() + */ + @Override + public synchronized Collection values() { + return new RemoteSet(this); + } + + /** + * Basic implementation of Set and Collection to bridge to the Iterator + * Disallows all writes. + */ + + private class RemoteSet extends AbstractSet { + RemoteMap mParent; + + public RemoteSet(RemoteMap parent) { + mParent = parent; + } + + // no modifications allowed + @Override + public boolean add(E o) { + throw new UnsupportedOperationException(); + } + @Override + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public Iterator iterator() { + return new RemoteIterator(mParent); + } + + @Override + public int size() { + return mParent.size(); + } + + } + /** + * Iterator view on RemoteMap data. Doesn't preload anything. + * REVISIT: Will go strange if the RemoteMap is modified. Detect this and throw ConcurrentMod ex + */ + private class RemoteIterator implements Iterator { + RemoteMap mParent; + Iterator iter; + String currentKey; + + public RemoteIterator(RemoteMap parent) { + mParent = parent; + iter = mParent.keySet().iterator(); + } + + @Override + public boolean hasNext() { + return iter.hasNext(); + } + + @Override + public C next() { + currentKey = iter.next(); + return mParent.get(currentKey); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + } + + + + +} diff --git a/src/main/java/org/cristalise/kernel/persistency/TransactionManager.java b/src/main/java/org/cristalise/kernel/persistency/TransactionManager.java new file mode 100644 index 0000000..7712da6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/TransactionManager.java @@ -0,0 +1,353 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.persistency; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.agent.JobList; +import org.cristalise.kernel.events.History; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.auth.Authenticator; +import org.cristalise.kernel.utils.Logger; + + +public class TransactionManager { + + HashMap locks; + HashMap> pendingTransactions; + ClusterStorageManager storage; + + public TransactionManager(Authenticator auth) throws PersistencyException { + storage = new ClusterStorageManager(auth); + locks = new HashMap(); + pendingTransactions = new HashMap>(); + } + + public boolean hasPendingTransactions() + { + return pendingTransactions.size() > 0; + } + + public ClusterStorageManager getDb() { + return storage; + } + + public void close() { + if (pendingTransactions.size() != 0) { + Logger.error("There were pending transactions on shutdown. All changes were lost."); + dumpPendingTransactions(0); + } + Logger.msg("Transaction Manager: Closing storages"); + storage.close(); + } + + public String[] getClusterContents(ItemPath itemPath, String path) throws PersistencyException { + if (path.startsWith("/") && path.length() > 1) path = path.substring(1); + return storage.getClusterContents(itemPath, path); + } + + /** + * Public get method. Required a 'locker' object for a transaction key. + * Checks the transaction table first to see if the caller has uncommitted changes + */ + public C2KLocalObject get(ItemPath itemPath, String path, Object locker) + throws PersistencyException, + ObjectNotFoundException { + if (path.startsWith("/") && path.length() > 1) path = path.substring(1); + + // deal out top level remote maps, if transactions aren't needed + if (path.indexOf('/') == -1) { + if (path.equals(ClusterStorage.HISTORY) && locker != null) + return new History(itemPath, locker); + if (path.equals(ClusterStorage.JOB) && locker != null) + return new JobList(itemPath, locker); + } + + // check to see if the locker has been modifying this cluster + if (locks.containsKey(itemPath) && locks.get(itemPath).equals(locker)) { + ArrayList lockerTransaction = pendingTransactions.get(locker); + for (TransactionEntry thisEntry : lockerTransaction) { + if (itemPath.equals(thisEntry.itemPath) && path.equals(thisEntry.path)) { + if (thisEntry.obj == null) + throw new PersistencyException("ClusterStorageManager.get() - Cluster " + path + " has been deleted in " + itemPath + + " but not yet committed"); + return thisEntry.obj; + } + } + } + return storage.get(itemPath, path); + } + + /** + * Public put method. Manages the transaction table keyed by the object 'locker'. + * If this object is null, transaction support is bypassed (so long as no lock exists on that object). + */ + public void put(ItemPath itemPath, C2KLocalObject obj, Object locker) throws PersistencyException { + Object tempLocker = null; + ArrayList lockerTransaction; + + synchronized(locks) { + // look to see if this object is already locked + if (locks.containsKey(itemPath)) { + // if it's this locker, get the transaction list + Object thisLocker = locks.get(itemPath); + if (thisLocker.equals(locker)) // retrieve the transaction list + lockerTransaction = pendingTransactions.get(locker); + else // locked by someone else + throw new PersistencyException("ClusterStorageManager.get() - Access denied: Object " + itemPath + + " has been locked for writing by " + thisLocker); + } + else { // no locks for this item + if (locker == null) { // lock the item until the non-transactional put is complete :/ + tempLocker = new Object(); + locks.put(itemPath, tempLocker); + lockerTransaction = null; + } + else { // initialise the transaction + locks.put(itemPath, locker); + lockerTransaction = new ArrayList(); + pendingTransactions.put(locker, lockerTransaction); + } + } + } + + if (tempLocker != null) { // non-locking put/delete + storage.put(itemPath, obj); + locks.remove(itemPath); + return; + } + + // create the new entry in the transaction table + TransactionEntry newEntry = new TransactionEntry(itemPath, obj); + /* equals() in TransactionEntry only compares sysKey and path, so we can use + * contains() in ArrayList to looks for preexisting entries for this cluster + * and overwrite them. + */ + if (lockerTransaction.contains(newEntry)) + lockerTransaction.remove(newEntry); + lockerTransaction.add(newEntry); + } + + /** Public delete method. Uses the put method, with null as the object value. + */ + public void remove(ItemPath itemPath, String path, Object locker) throws PersistencyException { + ArrayList lockerTransaction; + Object tempLocker = null; + synchronized(locks) { + // look to see if this object is already locked + if (locks.containsKey(itemPath)) { + // if it's this locker, get the transaction list + Object thisLocker = locks.get(itemPath); + if (thisLocker.equals(locker)) // retrieve the transaction list + lockerTransaction = pendingTransactions.get(locker); + else // locked by someone else + throw new PersistencyException("ClusterStorageManager.get() - Access denied: Object " + itemPath + + " has been locked for writing by " + thisLocker); + } + else { // either we are the locker, or there is no locker + if (locker == null) { // non-locking put/delete + tempLocker = new Object(); + locks.put(itemPath, tempLocker); + lockerTransaction = null; + } + else {// initialise the transaction + locks.put(itemPath, locker); + lockerTransaction = new ArrayList(); + pendingTransactions.put(locker, lockerTransaction); + } + } + } + + if (tempLocker != null) { + storage.remove(itemPath, path); + locks.remove(itemPath); + return; + } + + // create the new entry in the transaction table + TransactionEntry newEntry = new TransactionEntry(itemPath, path); + /* equals() in TransactionEntry only compares sysKey and path, so we can use + * contains() in ArrayList to looks for preexisting entries for this cluster + * and overwrite them. + */ + if (lockerTransaction.contains(newEntry)) + lockerTransaction.remove(newEntry); + lockerTransaction.add(newEntry); + + } + + /** + * Removes all child objects from the given path + * + * @param sysKey - entity to delete from + * @param path - root path to delete + * @param locker - locking object + * + * @throws PersistencyException - when deleting fails + */ + public void removeCluster(ItemPath itemPath, String path, Object locker) throws PersistencyException { + + String[] children = getClusterContents(itemPath, path); + for (String element : children) + removeCluster(itemPath, path+(path.length()>0?"/":"")+element, locker); + if (children.length==0 && path.indexOf("/") > -1) + remove(itemPath, path, locker); + + } + /** + * Writes all pending changes to the backends. + */ + public void commit(Object locker) { + synchronized(locks) { + ArrayList lockerTransactions = pendingTransactions.get(locker); + HashMap exceptions = new HashMap(); + // quit if no transactions are present; + if (lockerTransactions == null) return; + for (TransactionEntry thisEntry : lockerTransactions) { + try { + if (thisEntry.obj == null) + storage.remove(thisEntry.itemPath, thisEntry.path); + else + storage.put(thisEntry.itemPath, thisEntry.obj); + locks.remove(thisEntry.itemPath); + } catch (Exception e) { + exceptions.put(thisEntry, e); + } + } + pendingTransactions.remove(locker); + if (exceptions.size() > 0) { // oh dear + Logger.error("TransactionManager.commit() - Problems during transaction commit of locker "+locker.toString()+". Database may be in an inconsistent state."); + for (TransactionEntry entry : exceptions.keySet()) { + Exception ex = exceptions.get(entry); + Logger.msg(entry.toString()); + Logger.error(ex); + } + dumpPendingTransactions(0); + Logger.die("Database failure"); + } + + } + } + + /** + * Rolls back all changes sent in the name of 'locker' and unlocks the sysKeys + */ + public void abort(Object locker) { + synchronized(locks) { + if (locks.containsValue(locker)) { + for (ItemPath thisPath : locks.keySet()) { + if (locks.get(thisPath).equals(locker)) + locks.remove(thisPath); + } + } + pendingTransactions.remove(locker); + } + } + + public void clearCache(ItemPath itemPath, String path) { + if (itemPath == null) + storage.clearCache(); + else if (path == null) + storage.clearCache(itemPath); + else + storage.clearCache(itemPath, path); + + } + + public void dumpPendingTransactions(int logLevel) { + Logger.msg(logLevel, "================"); + Logger.msg(logLevel, "Transaction dump"); + Logger.msg(logLevel, "Locked Items:"); + if (locks.size() == 0) + Logger.msg(logLevel, " None"); + else + for (ItemPath thisPath : locks.keySet()) { + Object locker = locks.get(thisPath); + Logger.msg(logLevel, " "+thisPath+" locked by "+locker); + } + + Logger.msg(logLevel, "Open transactions:"); + if (pendingTransactions.size() == 0) + Logger.msg(logLevel, " None"); + else + for (Object thisLocker : pendingTransactions.keySet()) { + Logger.msg(logLevel, " Transaction owner:"+thisLocker); + ArrayList entries = pendingTransactions.get(thisLocker); + for (TransactionEntry thisEntry : entries) { + Logger.msg(logLevel, " "+thisEntry.toString()); + } + } + } + + /** Used in the transaction table to store details of a put until commit + */ + static class TransactionEntry { + public ItemPath itemPath; + public String path; + public C2KLocalObject obj; + public TransactionEntry(ItemPath itemPath, C2KLocalObject obj) { + this.itemPath = itemPath; + this.path = ClusterStorage.getPath(obj); + this.obj = obj; + } + + public TransactionEntry(ItemPath itemPath, String path) { + this.itemPath = itemPath; + this.path = path; + this.obj = null; + } + + @Override + public String toString() { + StringBuffer report = new StringBuffer(); + if (obj == null) + report.append("Delete"); + else + report.append("Put "+obj.getClass().getName()); + report.append(" at ").append(path).append(" in ").append(itemPath); + return report.toString(); + + } + /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return itemPath.hashCode()*path.hashCode(); + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object other) { + if (other instanceof TransactionEntry) + return hashCode() == ((TransactionEntry)other).hashCode(); + return false; + } + + } + +} diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/Outcome.java b/src/main/java/org/cristalise/kernel/persistency/outcome/Outcome.java new file mode 100644 index 0000000..95f3e6b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/Outcome.java @@ -0,0 +1,290 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.persistency.outcome; +import java.io.StringReader; +import java.util.StringTokenizer; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.utils.LocalObjectLoader; +import org.cristalise.kernel.utils.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.w3c.dom.bootstrap.DOMImplementationRegistry; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSSerializer; +import org.xml.sax.InputSource; + + +public class Outcome implements C2KLocalObject { + Integer mID; + String mData; + String mSchemaType; + int mSchemaVersion; + Document dom; + static DocumentBuilder parser; + static DOMImplementationLS impl; + static XPath xpath; + + static { + // Set up parser + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setValidating(false); + dbf.setNamespaceAware(false); + try { + parser = dbf.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + Logger.error(e); + Logger.die("Cannot function without XML parser"); + } + + // Set up serialiser + try { + DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance(); + impl = (DOMImplementationLS)registry.getDOMImplementation("LS"); + } catch (Exception e) { + Logger.error(e); + Logger.die("Cannot function without XML serialiser"); + } + + XPathFactory xPathFactory = XPathFactory.newInstance(); + xpath = xPathFactory.newXPath(); + } + + //id is the eventID + public Outcome(int id, String data, String schemaType, int schemaVersion) { + mID = id; + mData = data; + mSchemaType = schemaType; + mSchemaVersion = schemaVersion; + } + + public Outcome(String path, String data) throws PersistencyException { + // derive all the meta data from the path + StringTokenizer tok = new StringTokenizer(path,"/"); + if (tok.countTokens() != 3 && !(tok.nextToken().equals(ClusterStorage.OUTCOME))) + throw new PersistencyException("Outcome() - Outcome path must have three components: "+path); + mSchemaType = tok.nextToken(); + String verstring = tok.nextToken(); + String objId = tok.nextToken(); + try { + mSchemaVersion = Integer.parseInt(verstring); + } catch (NumberFormatException ex) { + throw new PersistencyException("Outcome() - Outcome version was an invalid number: "+verstring); + } + try { + mID = Integer.valueOf(objId); + } catch (NumberFormatException ex) { + mID = null; + } + mData = data; + } + + public void setID(Integer ID) { + mID = ID; + } + + public Integer getID() { + return mID; + } + + @Override + public void setName(String name) { + try { + mID = Integer.valueOf(name); + } catch (NumberFormatException e) { + Logger.error("Invalid id set on Outcome:"+name); + } + } + + @Override + public String getName() { + return mID.toString(); + } + + public void setData(String data) { + mData = data; + dom = null; + } + + public void setData(Document data) { + dom = data; + mData = null; + } + + public String getFieldByXPath(String xpath) throws XPathExpressionException, InvalidDataException { + Node field = getNodeByXPath(xpath); + if (field == null) + throw new InvalidDataException(xpath); + + else if (field.getNodeType()==Node.TEXT_NODE || field.getNodeType()==Node.CDATA_SECTION_NODE) + return field.getNodeValue(); + + else if (field.getNodeType()==Node.ELEMENT_NODE) { + NodeList fieldChildren = field.getChildNodes(); + if (fieldChildren.getLength() == 0) + throw new InvalidDataException("No child node for element"); + + else if (fieldChildren.getLength() == 1) { + Node child = fieldChildren.item(0); + if (child.getNodeType()==Node.TEXT_NODE || child.getNodeType()==Node.CDATA_SECTION_NODE) + return child.getNodeValue(); + else + throw new InvalidDataException("Can't get data from child node of type "+child.getNodeName()); + } + else + throw new InvalidDataException("Element "+xpath+" has too many children"); + } + else if (field.getNodeType()==Node.ATTRIBUTE_NODE) + return field.getNodeValue(); + else + throw new InvalidDataException("Don't know what to do with node "+field.getNodeName()); + } + + public void setFieldByXPath(String xpath, String data) throws XPathExpressionException, InvalidDataException { + Node field = getNodeByXPath(xpath); + if (field == null) + throw new InvalidDataException(xpath); + + else if (field.getNodeType()==Node.ELEMENT_NODE) { + NodeList fieldChildren = field.getChildNodes(); + if (fieldChildren.getLength() == 0) { + field.appendChild(dom.createTextNode(data)); + } + else if (fieldChildren.getLength() == 1) { + Node child = fieldChildren.item(0); + switch (child.getNodeType()) { + case Node.TEXT_NODE: + case Node.CDATA_SECTION_NODE: + child.setNodeValue(data); + break; + default: + throw new InvalidDataException("Can't set child node of type "+child.getNodeName()); + } + } + else + throw new InvalidDataException("Element "+xpath+" has too many children"); + } + else if (field.getNodeType()==Node.ATTRIBUTE_NODE) + field.setNodeValue(data); + else + throw new InvalidDataException("Don't know what to do with node "+field.getNodeName()); + } + + + public String getData() { + if (mData == null && dom != null) { + mData = serialize(dom, false); + } + return mData; + } + + public Schema getSchema() throws ObjectNotFoundException { + return LocalObjectLoader.getSchema(mSchemaType, mSchemaVersion); + } + + public void setSchemaType(String schemaType) { + mSchemaType = schemaType; + } + + public String getSchemaType() { + return mSchemaType; + } + + public int getSchemaVersion() { + return mSchemaVersion; + } + + public void setSchemaVersion(int schVer) { + mSchemaVersion = schVer; + } + + @Override + public String getClusterType() { + return ClusterStorage.OUTCOME; + } + + // special script API methods + + /** + * Parses the outcome into a DOM tree + * @return a DOM Document + */ + public Document getDOM() { + if (dom == null) + try { + synchronized (parser) { + if (mData!=null) + dom = parser.parse(new InputSource(new StringReader(mData))); + else + dom = parser.newDocument(); + } + } catch (Exception e) { + Logger.error(e); + return null; + } + return dom; + } + + public String getField(String name) { + NodeList elements = getDOM().getDocumentElement().getElementsByTagName(name); + if (elements.getLength() == 1 && elements.item(0).hasChildNodes() && elements.item(0).getFirstChild() instanceof Text) + return ((Text)elements.item(0).getFirstChild()).getData(); + else + return null; + } + + public NodeList getNodesByXPath(String xpathExpr) throws XPathExpressionException { + + XPathExpression expr = xpath.compile(xpathExpr); + return (NodeList)expr.evaluate(getDOM(), XPathConstants.NODESET); + + } + + public Node getNodeByXPath(String xpathExpr) throws XPathExpressionException { + + XPathExpression expr = xpath.compile(xpathExpr); + return (Node)expr.evaluate(getDOM(), XPathConstants.NODE); + + } + + static public String serialize(Document doc, boolean prettyPrint) + { + LSSerializer writer = impl.createLSSerializer(); + writer.getDomConfig().setParameter("format-pretty-print", prettyPrint); + writer.getDomConfig().setParameter("xml-declaration", false); + return writer.writeToString(doc); + } +} diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeInitiator.java b/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeInitiator.java new file mode 100644 index 0000000..0a22fd0 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeInitiator.java @@ -0,0 +1,31 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.persistency.outcome; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.entity.agent.Job; + + +public interface OutcomeInitiator { + + public String initOutcome(Job job) throws InvalidDataException; + +} diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeValidator.java b/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeValidator.java new file mode 100644 index 0000000..fed0c8c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeValidator.java @@ -0,0 +1,207 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.persistency.outcome; + +import java.io.IOException; +import java.io.StringReader; + +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.parsers.IntegratedParserConfiguration; +import org.apache.xerces.parsers.XMLGrammarPreparser; +import org.apache.xerces.util.SymbolTable; +import org.apache.xerces.util.XMLGrammarPoolImpl; +import org.apache.xerces.xni.XNIException; +import org.apache.xerces.xni.grammars.XMLGrammarDescription; +import org.apache.xerces.xni.parser.XMLErrorHandler; +import org.apache.xerces.xni.parser.XMLInputSource; +import org.apache.xerces.xni.parser.XMLParseException; +import org.apache.xerces.xni.parser.XMLParserConfiguration; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.utils.Logger; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + + +/************************************************************************** + * + * $Revision: 1.24 $ + * $Date: 2005/06/09 13:50:10 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + + +public class OutcomeValidator implements ErrorHandler, XMLErrorHandler { + + protected static final String NAMESPACES_FEATURE_ID = "http://xml.org/sax/features/namespaces"; + /** Validation feature id (http://xml.org/sax/features/validation). */ + protected static final String VALIDATION_FEATURE_ID = "http://xml.org/sax/features/validation"; + /** Schema validation feature id (http://apache.org/xml/features/validation/schema). */ + protected static final String SCHEMA_VALIDATION_FEATURE_ID = "http://apache.org/xml/features/validation/schema"; + /** Schema full checking feature id (http://apache.org/xml/features/validation/schema-full-checking). */ + protected static final String SCHEMA_FULL_CHECKING_FEATURE_ID = "http://apache.org/xml/features/validation/schema-full-checking"; + public static final String GRAMMAR_POOL = "http://apache.org/xml/properties/internal/grammar-pool"; + + static SchemaValidator schemaValid = new SchemaValidator(); + + Schema schema; + protected StringBuffer errors = null; + XMLGrammarPoolImpl schemaGrammarPool = new XMLGrammarPoolImpl(1); + SymbolTable sym = new SymbolTable(); + + public static OutcomeValidator getValidator(Schema schema) throws InvalidDataException { + + if (schema.docType.equals("Schema") && + schema.docVersion==0) + return schemaValid; + + return new OutcomeValidator(schema); + } + + protected OutcomeValidator() { + errors = new StringBuffer(); + } + + public OutcomeValidator(Schema schema) throws InvalidDataException { + this.schema = schema; + + if (schema.docType.equals("Schema")) + throw new InvalidDataException("Use SchemaValidator to validate schema"); + + errors = new StringBuffer(); + Logger.msg(5, "Parsing "+schema.docType+" version "+schema.docVersion+". "+schema.schema.length()+" chars"); + + XMLGrammarPreparser preparser = new XMLGrammarPreparser(sym); + preparser.registerPreparser(XMLGrammarDescription.XML_SCHEMA, null); + preparser.setProperty(GRAMMAR_POOL, schemaGrammarPool); + + preparser.setFeature(NAMESPACES_FEATURE_ID, true); + preparser.setFeature(VALIDATION_FEATURE_ID, true); + preparser.setFeature(SCHEMA_VALIDATION_FEATURE_ID, true); + preparser.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, true); + preparser.setErrorHandler(this); + try { + preparser.preparseGrammar(XMLGrammarDescription.XML_SCHEMA, new XMLInputSource(null, null, null, new StringReader(schema.schema), null)); + } catch (IOException ex) { + throw new InvalidDataException("Error parsing schema: "+ex.getMessage()); + } + + if (errors.length() > 0) { + throw new InvalidDataException("Schema error: \n"+errors.toString()); + } + + } + + public synchronized String validate(Outcome outcome) { + if (outcome == null) return "Outcome object was null"; + Logger.msg(5, "Validating outcome no "+outcome.getID()+" as "+schema.docType+" v"+schema.docVersion); + if (outcome.getSchemaType().equals(schema.docType) + && outcome.getSchemaVersion() == schema.docVersion) { + return validate(outcome.getData()); + } + else + return "Outcome type and version did not match schema "+schema.docType; + } + + public synchronized String validate(String outcome) { + if (outcome == null) return "Outcome String was null"; + errors = new StringBuffer(); + try { + XMLParserConfiguration parserConfiguration = new IntegratedParserConfiguration(sym, schemaGrammarPool); + parserConfiguration.setFeature(NAMESPACES_FEATURE_ID, true); + parserConfiguration.setFeature(VALIDATION_FEATURE_ID, true); + // now we can still do schema features just in case, + // so long as it's our configuraiton...... + parserConfiguration.setFeature(SCHEMA_VALIDATION_FEATURE_ID, true); + parserConfiguration.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, true); + DOMParser parser = new DOMParser(parserConfiguration); + parser.setErrorHandler(this); + + parser.parse(new XMLInputSource(null, null, null, new StringReader(outcome), null)); + } catch (Exception e) { + return e.getMessage(); + } + return errors.toString(); + } + + private void appendError(String level, Exception ex) { + errors.append(level); + String message = ex.getMessage(); + if (message == null || message.length()==0) + message = ex.getClass().getName(); + errors.append(message); + errors.append("\n"); + } + + /** + * ErrorHandler for instances + */ + @Override + public void error(SAXParseException ex) throws SAXException { + appendError("ERROR: ", ex); + } + + /** + * + */ + @Override + public void fatalError(SAXParseException ex) throws SAXException { + appendError("FATAL: ", ex); + } + + /** + * + */ + @Override + public void warning(SAXParseException ex) throws SAXException { + appendError("WARNING: ", ex); + } + + /** + * XMLErrorHandler for schema + */ + @Override + public void error(String domain, String key, XMLParseException ex) + throws XNIException { + appendError("ERROR: ", ex); + } + + /** + * + */ + @Override + public void fatalError(String domain, String key, XMLParseException ex) + throws XNIException { + appendError("FATAL: ", ex); + } + + /** + * + */ + @Override + public void warning(String domain, String key, XMLParseException ex) + throws XNIException { + appendError("WARNING: ", ex); + } + +} diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/Schema.java b/src/main/java/org/cristalise/kernel/persistency/outcome/Schema.java new file mode 100644 index 0000000..4ae6ef3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/Schema.java @@ -0,0 +1,73 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.persistency.outcome; + +import java.io.IOException; +import java.io.StringReader; + +import org.exolab.castor.xml.schema.reader.SchemaReader; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; + +/** + * @author Andrew Branson + * + * $Revision: 1.3 $ + * $Date: 2006/09/14 14:13:26 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + */ + +public class Schema { + public String docType; + public int docVersion; + public String schema; + public org.exolab.castor.xml.schema.Schema som; + + /** + * @param docType + * @param docVersion + * @param schema + */ + public Schema(String docType, int docVersion, String schema) { + super(); + this.docType = docType; + this.docVersion = docVersion; + this.schema = schema; + } + + public Schema(String schema) { + this.schema = schema; + } + + public org.exolab.castor.xml.schema.Schema parse(ErrorHandler errorHandler) throws IOException { + InputSource schemaSource = new InputSource(new StringReader(schema)); + SchemaReader mySchemaReader = new SchemaReader(schemaSource); + if (errorHandler!= null) { + mySchemaReader.setErrorHandler(errorHandler); + mySchemaReader.setValidation(true); + } + som = mySchemaReader.read(); + return som; + } + +} diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/SchemaValidator.java b/src/main/java/org/cristalise/kernel/persistency/outcome/SchemaValidator.java new file mode 100644 index 0000000..b9684d2 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/SchemaValidator.java @@ -0,0 +1,55 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.persistency.outcome; + +import java.io.IOException; + + +/************************************************************************** + * + * $Revision: 1.2 $ + * $Date: 2005/04/26 06:48:13 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + + + +public class SchemaValidator extends OutcomeValidator { + + public SchemaValidator() { + + } + + @Override + public synchronized String validate(String outcome) { + errors = new StringBuffer(); + Schema schema = new Schema(outcome); + try { + schema.parse(this); + } catch (IOException e) { + errors.append(e.getMessage()); + } + return errors.toString(); + } + +} diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/Viewpoint.java b/src/main/java/org/cristalise/kernel/persistency/outcome/Viewpoint.java new file mode 100644 index 0000000..630975a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/Viewpoint.java @@ -0,0 +1,191 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.persistency.outcome; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.events.Event; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; + + +/** + * @author Andrew Branson + * + * $Revision: 1.10 $ + * $Date: 2005/10/05 07:39:36 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + */ + +public class Viewpoint implements C2KLocalObject { + + // db fields + ItemPath itemPath; + String schemaName; + String name; + int schemaVersion; + int eventId; + public static final int NONE = -1; + + public Viewpoint() { + eventId = NONE; + itemPath = null; + schemaVersion = NONE; + schemaName = null; + name = null; + } + + public Viewpoint(ItemPath itemPath, String schemaName, String name, int schemaVersion, int eventId) { + this.itemPath = itemPath; + this.schemaName = schemaName; + this.name = name; + this.schemaVersion = schemaVersion; + this.eventId = eventId; + } + + public Outcome getOutcome() throws ObjectNotFoundException, PersistencyException { + if (eventId == NONE) throw new ObjectNotFoundException("No last eventId defined"); + Outcome retVal = (Outcome)Gateway.getStorage().get(itemPath, ClusterStorage.OUTCOME+"/"+schemaName+"/"+schemaVersion+"/"+eventId, null); + return retVal; + } + + @Override + public String getClusterType() { + return ClusterStorage.VIEWPOINT; + } + + + /** + * Returns the eventId. + * @return int + */ + public int getEventId() { + return eventId; + } + + /** + * Returns the name. + * @return String + */ + @Override + public String getName() { + return name; + } + + /** + * Returns the schemaName. + * @return String + */ + public String getSchemaName() { + return schemaName; + } + + /** + * Returns the schemaVersion. + * @return int + */ + public int getSchemaVersion() { + return schemaVersion; + } + + /** + * Returns the sysKey. + * @return int + */ + public ItemPath getItemPath() { + return itemPath; + } + + /** + * Sets the eventId. + * @param eventId The eventId to set + */ + public void setEventId(int eventId) { + this.eventId = eventId; + } + + /** + * Sets the name. + * @param name The name to set + */ + @Override + public void setName(String name) { + this.name = name; + } + + /** + * Sets the schemaName. + * @param schemaName The schemaName to set + */ + public void setSchemaName(String schemaName) { + this.schemaName = schemaName; + } + + /** + * Sets the schemaVersion. + * @param schemaVersion The schemaVersion to set + */ + public void setSchemaVersion(int schemaVersion) { + this.schemaVersion = schemaVersion; + } + + /** + * Sets the sysKey. + * @param sysKey The sysKey to set + */ + public void setItemPath(ItemPath itemPath) { + this.itemPath = itemPath; + } + + public void setItemUUID( String uuid ) throws InvalidItemPathException + { + setItemPath(new ItemPath(uuid)); + } + + public String getItemUUID() { + return getItemPath().getUUID().toString(); + } + + /** + * Method getEvent. + * @return GDataRecord + */ + public Event getEvent() + throws InvalidDataException, PersistencyException, ObjectNotFoundException + { + if (eventId == NONE) + throw new InvalidDataException("No last eventId defined"); + + return (Event)Gateway.getStorage().get(itemPath, ClusterStorage.HISTORY+"/"+eventId, null); + } + + @Override + public String toString() { + return name; + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/AbstractMain.java b/src/main/java/org/cristalise/kernel/process/AbstractMain.java new file mode 100644 index 0000000..5acfbef --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/AbstractMain.java @@ -0,0 +1,178 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.util.Enumeration; +import java.util.Properties; + +import org.cristalise.kernel.process.resource.BadArgumentsException; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2004/10/25 15:27:35 $ + * @version $Revision: 1.67 $ + **************************************************************************/ +abstract public class AbstractMain +{ + public static boolean isServer = false; + private static ShutdownHandler shutdownHandler; + + public static String MAIN_ARG_NONEWLOGSTREAM = "noNewLogStream"; + public static String MAIN_ARG_CONFIG = "config"; + public static String MAIN_ARG_LOGLEVEL = "logLevel"; + public static String MAIN_ARG_LOGFILE = "logFile"; + public static String MAIN_ARG_CONNECT = "connect"; + + + + /************************************************************************** + * reading and setting input paramaters + ************************************************************************** + * + * Known arguments : + *

      + *
    • logLevel: the log level 0-9 (+10 to have time, +20 to have only one level)
    • + *
    • logFile: the full path of the target log file. if none, the Logstream is the stdOut
    • + *
    • noNewLogStream: if present no new Logstream is added to the logger ( + * considers that the Logger is already configured)
    • + * + *
    • config
    • + *
    • connect
    • + *
    • LocalCentre
    • + *
    + * + * + * @param args + * @return + * @throws BadArgumentsException + */ + public static Properties readC2KArgs( String[] args ) throws BadArgumentsException { + Properties c2kProps; + Properties argProps = new Properties(); + int logLevel = 0; + PrintStream logStream = System.out; + + int i = 0; + while( i < args.length ) { + if (args[i].startsWith("-") && args[i].length()>1) { + String key = args[i].substring(1); + if (argProps.containsKey(key)) + throw new BadArgumentsException("Argument "+args[i]+" given twice"); + String value = ""; + if (!args[i+1].startsWith("-")) + value = args[++i]; + argProps.put(key, value); + i++; + } + else + throw new BadArgumentsException("Bad argument: "+args[i]); + + } + + if (argProps.containsKey("logFile")) + try { + logStream = new PrintStream(new FileOutputStream(argProps.getProperty("logFile"), true)); + } catch (FileNotFoundException e) { + e.printStackTrace(); + throw new BadArgumentsException("Logfile "+argProps.getProperty("logFile")+" cannot be created"); + } + + + // if the optional arg "noNewLogStream" isn't present => add a + // new LogStream + boolean wMustAddNewLogStream = !argProps.contains(MAIN_ARG_NONEWLOGSTREAM); + if (wMustAddNewLogStream) { + + // Set up log stream + if (argProps.containsKey("logLevel")) + logLevel = Integer.parseInt(argProps.getProperty("logLevel")); + + Logger.addLogStream(logStream, logLevel); + } + if (wMustAddNewLogStream) Logger.msg( + String.format("New logStream added at logLevel %d: %s", logLevel, logStream.getClass().getName())); + + + // Dump params if log high enough + + if (Logger.doLog(3)) for (Enumeration e = argProps.propertyNames(); e.hasMoreElements();) { + String next = (String)e.nextElement(); + System.out.println("AbstractMain: Param "+next+": "+argProps.getProperty(next)); + } + + String configPath = argProps.getProperty("config"); + if (configPath == null) + throw new BadArgumentsException("Config file not specified"); + + if (!new File(configPath).exists()) + throw new BadArgumentsException("Config file "+configPath+" not found"); + else + Logger.msg(0, "Config file: "+configPath); + + // Load config & connect files into c2kprops + c2kProps = FileStringUtility.loadConfigFile(argProps.getProperty("config") ); + c2kProps.putAll(argProps); // args overlap config + + String connectFile = c2kProps.getProperty("connect"); + if (connectFile == null) + throw new BadArgumentsException("Connect file not specified"); + + if (!new File(connectFile).exists()) + throw new BadArgumentsException("Connect file "+connectFile+" not found"); + else + Logger.msg(0, "Connect file: "+connectFile); + + FileStringUtility.appendConfigFile( c2kProps, connectFile); + + if (!c2kProps.containsKey("LocalCentre")) { + String connectFileName = new File(connectFile).getName(); + String centreId = connectFileName.substring(0, connectFileName.lastIndexOf(".clc")); + c2kProps.setProperty("LocalCentre", centreId); + } + + c2kProps.putAll(argProps); // args override connect file too + Logger.msg(7, "AbstractMain::standardSetUp() - readC2KArgs() DONE."); + + return c2kProps; + } + + public static void setShutdownHandler(ShutdownHandler handler) { + shutdownHandler = handler; + } + + public static void shutdown(int errCode) { + if (shutdownHandler!= null) + shutdownHandler.shutdown(errCode, isServer); + else + try { + Gateway.close(); + } catch (Exception ex) { + Logger.error(ex); + } + } +} diff --git a/src/main/java/org/cristalise/kernel/process/Bootstrap.java b/src/main/java/org/cristalise/kernel/process/Bootstrap.java new file mode 100644 index 0000000..8934cd8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/Bootstrap.java @@ -0,0 +1,394 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +import java.net.InetAddress; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.UUID; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.events.Event; +import org.cristalise.kernel.events.History; +import org.cristalise.kernel.lifecycle.CompositeActivityDef; +import org.cristalise.kernel.lifecycle.instance.CompositeActivity; +import org.cristalise.kernel.lifecycle.instance.Workflow; +import org.cristalise.kernel.lifecycle.instance.predefined.server.ServerPredefinedStepContainer; +import org.cristalise.kernel.lifecycle.instance.stateMachine.Transition; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.LookupManager; +import org.cristalise.kernel.lookup.Path; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.OutcomeValidator; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.resource.DefaultResourceImportHandler; +import org.cristalise.kernel.process.resource.ResourceImportHandler; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.property.PropertyDescription; +import org.cristalise.kernel.property.PropertyDescriptionList; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.LocalObjectLoader; +import org.cristalise.kernel.utils.Logger; +import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.XMLUnit; + + +/** + * @version $Revision: 1.25 $ $Date: 2006/01/10 09:48:32 $ + * @author $Author: abranson $ + */ + +public class Bootstrap +{ + static DomainPath thisServerPath; + static HashMap resHandlerCache = new HashMap(); + static HashMap systemAgents = new HashMap(); + + /** + * Run everything without timing-out the service wrapper + */ + public static void run() throws Exception { + // check for system agents + checkAdminAgents(); + + // create the server's mother item + createServerItem(); + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.currentThread().setName("Bootstrapper"); + + ClassLoader wClassLoader = Bootstrap.class.getClassLoader(); + Logger.msg(String.format("Bootstrap.run() setContextClassLoader=[%s]",wClassLoader)); + Thread.currentThread().setContextClassLoader(wClassLoader); + + // make sure all of the boot items are up-to-date + Logger.msg("Bootstrap.run() - Verifying kernel boot data items"); + verifyBootDataItems(); + + // verify the server item's wf + Logger.msg("Bootstrap.run() - Initialising Server Item Workflow"); + initServerItemWf(); + + Gateway.getModuleManager().setUser(systemAgents.get("system")); + Gateway.getModuleManager().registerModules(); + + Logger.msg("Bootstrap.run() - Bootstrapping complete"); + } catch (Throwable e) { + Logger.error(e); + Logger.die("Exception performing bootstrap. Check that everything is OK."); + } + } + }).start(); + } + + /************************************************************************** + * Checks all kernel descriptions, stored in resources + **************************************************************************/ + public static void verifyBootDataItems() throws Exception { + String bootItems; + Logger.msg(1, "Verifying kernel boot items"); + bootItems = FileStringUtility.url2String(Gateway.getResource().getKernelResourceURL("boot/allbootitems.txt")); + verifyBootDataItems(bootItems, null, true); + Logger.msg(1, "Boot data items complete"); + } + + private static void verifyBootDataItems(String bootList, String ns, boolean reset) throws InvalidItemPathException { + StringTokenizer str = new StringTokenizer(bootList, "\n\r"); + while (str.hasMoreTokens()) { + String thisItem = str.nextToken(); + ItemPath itemPath = null; + String[] itemParts = thisItem.split("/"); + if (itemParts.length == 3) { // includes UUID + itemPath = new ItemPath(itemParts[2]); + } + String itemType = itemParts[0]; + String itemName = itemParts[1]; + try { + String location = "boot/"+thisItem+(itemType.equals("OD")?".xsd":".xml"); + verifyResource(ns, itemName, 0, itemType, itemPath, location, reset); + } catch (Exception e) { + Logger.error(e); + Logger.die("Error importing bootstrap items. Unsafe to continue."); + } + } + } + + public static DomainPath verifyResource(String ns, String itemName, int version, String itemType, ItemPath itemPath, String dataLocation, boolean reset) throws Exception { + LookupManager lookupManager = Gateway.getLookupManager(); + ResourceImportHandler typeImpHandler = getHandler(itemType); + Logger.msg(1, "Bootstrap.verifyResource() - Verifying version "+version+" of "+typeImpHandler.getName()+" "+itemName); + + // Find or create Item for Resource + DomainPath modDomPath = typeImpHandler.getPath(itemName, ns); + ItemProxy thisProxy; + Iterator en = Gateway.getLookup().search(typeImpHandler.getTypeRoot(), itemName); + if (!en.hasNext()) { + if (itemPath == null) itemPath = new ItemPath(); + Logger.msg("Bootstrap.verifyResource() - "+typeImpHandler.getName()+" "+itemName+" not found. Creating new."); + thisProxy = createResourceItem(typeImpHandler, itemName, ns, itemPath); + } + else { + DomainPath path = (DomainPath)en.next(); + thisProxy = Gateway.getProxyManager().getProxy(path); + if (itemPath != null && !path.getItemPath().equals(itemPath)) { + Logger.warning("Resource "+itemType+"/"+itemName+" should have path "+itemPath+" but was found with path "+path.getItemPath()); + itemPath = path.getItemPath(); + } + if (itemPath == null) itemPath = path.getItemPath(); + // Verify module property and location + + String moduleName = (ns==null?"kernel":ns); + String itemModule; + try{ + itemModule = thisProxy.getProperty("Module"); + if (!itemModule.equals("") && !itemModule.equals("null") && !moduleName.equals(itemModule)) { + Logger.error("Bootstrap.verifyResource() - Module clash! Resource '"+itemName+"' included in module "+moduleName+" but is assigned to '"+itemModule+"'. Not overwriting."); + return path; + } + } catch (ObjectNotFoundException ex) { + itemModule = ""; + } + + if (!moduleName.equals(itemModule)) { // write module property + Gateway.getStorage().put(itemPath, new Property("Module", moduleName, false), thisProxy); + } + + if (!modDomPath.equals(path)) { // move item to module subtree + Logger.msg("Module item "+itemName+" found with path "+path.toString()+". Moving to "+modDomPath.toString()); + modDomPath.setItemPath(itemPath); + if (!modDomPath.exists()) + lookupManager.add(modDomPath); + lookupManager.delete(path); + } + } + + // Verify/Import Outcomes, creating events and views as necessary + Set impList = typeImpHandler.getResourceOutcomes(itemName, ns, dataLocation, version); + for (Outcome newOutcome : impList) { + try { + Viewpoint currentData = (Viewpoint)thisProxy.getObject(ClusterStorage.VIEWPOINT+"/"+newOutcome.getSchemaType()+"/"+version); + Outcome oldData = currentData.getOutcome(); + XMLUnit.setIgnoreWhitespace(true); + XMLUnit.setIgnoreComments(true); + Diff xmlDiff = new Diff(newOutcome.getDOM(), oldData.getDOM()); + if (xmlDiff.identical()) { + Logger.msg(5, "Bootstrap.verifyResource() - Data identical, no update required"); + continue; + } + else { + Logger.msg("Difference found in "+itemName+": "+xmlDiff.toString()); + if (!reset && !currentData.getEvent().getStepPath().equals("Bootstrap")) { + Logger.msg("Version "+version+" was not set by Bootstrap, and reset not requested. Not overwriting."); + continue; + } + } + + } catch (ObjectNotFoundException ex) { + Logger.msg("Bootstrap.verifyResource() - Item "+itemName+" exists but version "+version+" not found! Attempting to insert new."); + } + + // data was missing or doesn't match + // validate it (but not for kernel objects because we need those to validate the rest) + if (ns!= null) { + OutcomeValidator validator = OutcomeValidator.getValidator(LocalObjectLoader.getSchema(newOutcome.getSchemaType(), newOutcome.getSchemaVersion())); + String error = validator.validate(newOutcome.getData()); + if (error.length() > 0) { + Logger.error("Outcome not valid: \n " + error); + throw new InvalidDataException(error); + } + } + + // store + Logger.msg("Bootstrap.verifyResource() - Writing new "+newOutcome.getSchemaType()+" v"+version+" to "+typeImpHandler.getName()+" "+itemName); + History hist = new History(itemPath, thisProxy); + Transition predefDone = new Transition(0, "Done", 0, 0); + Event newEvent = hist.addEvent(systemAgents.get("system").getPath(), "Admin", "Bootstrap", "Bootstrap", "Bootstrap", newOutcome.getSchemaType(), 0, "PredefinedStep", 0, predefDone, String.valueOf(version)); + newOutcome.setID(newEvent.getID()); + Viewpoint newLastView = new Viewpoint(itemPath, newOutcome.getSchemaType(), "last", 0, newEvent.getID()); + Viewpoint newNumberView = new Viewpoint(itemPath, newOutcome.getSchemaType(), String.valueOf(version), 0, newEvent.getID()); + Gateway.getStorage().put(itemPath, newOutcome, thisProxy); + Gateway.getStorage().put(itemPath, newLastView, thisProxy); + Gateway.getStorage().put(itemPath, newNumberView, thisProxy); + } + Gateway.getStorage().commit(thisProxy); + return modDomPath; + } + + private static ResourceImportHandler getHandler(String resType) throws Exception { + if (resHandlerCache.containsKey(resType)) + return resHandlerCache.get(resType); + ResourceImportHandler handler = null; + if (Gateway.getProperties().containsKey("ResourceImportHandler."+resType)) { + try { + handler = (ResourceImportHandler) Gateway.getProperties().getInstance("ResourceImportHandler."+resType); + } catch (Exception ex) { + Logger.error(ex); + Logger.error("Exception loading ResourceHandler for "+resType+". Using default."); + } + } + + if (handler == null) + handler = new DefaultResourceImportHandler(resType); + + resHandlerCache.put(resType, handler); + return handler; + } + + /** + * @param itemType + * @param itemName + * @param data + */ + private static ItemProxy createResourceItem(ResourceImportHandler impHandler, String itemName, String ns, ItemPath itemPath) throws Exception { + // create props + PropertyDescriptionList pdList = impHandler.getPropDesc(); + PropertyArrayList props = new PropertyArrayList(); + LookupManager lookupManager = Gateway.getLookupManager(); + + for (int i = 0; i < pdList.list.size(); i++) { + PropertyDescription pd = pdList.list.get(i); + String propName = pd.getName(); + String propVal = propName.equals("Name")?itemName:pd.getDefaultValue(); + props.list.add(new Property(propName, propVal, pd.getIsMutable())); + } + + CompositeActivity ca = new CompositeActivity(); + if (ns!=null && Gateway.getProperties().getBoolean("Module.debug", false)) + try { + ca = (CompositeActivity) ((CompositeActivityDef)LocalObjectLoader.getActDef(impHandler.getWorkflowName(), 0)).instantiate(); + } catch (ObjectNotFoundException ex) { + Logger.error("Module resource workflow "+impHandler.getWorkflowName()+" not found. Using empty."); + } + + + Gateway.getCorbaServer().createItem(itemPath); + lookupManager.add(itemPath); + DomainPath newDomPath = impHandler.getPath(itemName, ns); + newDomPath.setItemPath(itemPath); + lookupManager.add(newDomPath); + ItemProxy newItemProxy = Gateway.getProxyManager().getProxy(itemPath); + newItemProxy.initialise( systemAgents.get("system").getPath(), props, ca, null); + return newItemProxy; + } + + /************************************************************************** + * Checks for the existence of the admin users so you can use Cristal + **************************************************************************/ + private static void checkAgent(String name, String pass, RolePath rolePath, String uuid) throws Exception { + Logger.msg(1, "Bootstrap.checkAgent() - Checking for existence of '"+name+"' user."); + LookupManager lookup = Gateway.getLookupManager(); + + try { + systemAgents.put(name, Gateway.getProxyManager().getAgentProxy(lookup.getAgentPath(name))); + Logger.msg(3, "Bootstrap.checkAgent() - User '"+name+"' found."); + return; + } catch (ObjectNotFoundException ex) { } + + Logger.msg("Bootstrap.checkAgent() - User '"+name+"' not found. Creating."); + + try { + AgentPath agentPath = new AgentPath(new ItemPath(uuid), name); + agentPath.setPassword(pass); + Gateway.getCorbaServer().createAgent(agentPath); + lookup.add(agentPath); + + // assign admin role + Logger.msg("Bootstrap.checkAgent() - Assigning role '"+rolePath.getName()+"'"); + Gateway.getLookupManager().addRole(agentPath, rolePath); + Gateway.getStorage().put(agentPath, new Property("Name", name, true), null); + Gateway.getStorage().put(agentPath, new Property("Type", "Agent", false), null); + systemAgents.put(name, Gateway.getProxyManager().getAgentProxy(agentPath)); + } catch (Exception ex) { + Logger.error("Unable to create "+name+" user."); + throw ex; + } + } + + /** + * + */ + public static void checkAdminAgents() throws Exception { + + // check for administrative user & admin role + String adminPassword = Gateway.getProperties().getString("AdminPassword", "admin12345"); + RolePath rootRole = new RolePath(); + if (!rootRole.exists()) Gateway.getLookupManager().createRole(rootRole); + RolePath adminRole = new RolePath(rootRole, "Admin", false); + if (!adminRole.exists()) Gateway.getLookupManager().createRole(adminRole); + + // check for import user + checkAgent("system", adminPassword, adminRole, new UUID(0, 0).toString()); + + checkAgent("admin", adminPassword, adminRole, new UUID(0, 1).toString()); + + // check for local usercode user & role + RolePath usercodeRole = new RolePath(rootRole, "UserCode", true); + if (!usercodeRole.exists()) Gateway.getLookupManager().createRole(usercodeRole); + checkAgent(InetAddress.getLocalHost().getHostName(), "uc", usercodeRole, UUID.randomUUID().toString()); + } + + public static void createServerItem() throws Exception { + LookupManager lookupManager = Gateway.getLookupManager(); + String serverName = Gateway.getProperties().getString("ItemServer.name", InetAddress.getLocalHost().getHostName()); + thisServerPath = new DomainPath("/servers/"+serverName); + ItemPath serverEntity; + try { + serverEntity = thisServerPath.getItemPath(); + } catch (ObjectNotFoundException ex) { + Logger.msg("Creating server item "+thisServerPath); + serverEntity = new ItemPath(); + Gateway.getCorbaServer().createItem(serverEntity); + lookupManager.add(serverEntity); + thisServerPath.setItemPath(serverEntity); + lookupManager.add(thisServerPath); + } + Gateway.getStorage().put(serverEntity, new Property("Name", serverName, false), null); + Gateway.getStorage().put(serverEntity, new Property("Type", "Server", false), null); + Gateway.getStorage().put(serverEntity, new Property("KernelVersion", Gateway.getKernelVersion(), true), null); + int proxyPort = Gateway.getProperties().getInt("ItemServer.Proxy.port", 1553); + Gateway.getStorage().put(serverEntity, + new Property("ProxyPort", String.valueOf(proxyPort), false), null); + Gateway.getStorage().put(serverEntity, + new Property("ConsolePort", String.valueOf(Logger.getConsolePort()), true), null); + Gateway.getProxyManager().connectToProxyServer(serverName, proxyPort); + + } + + public static void initServerItemWf() throws Exception { + CompositeActivityDef serverWfCa = (CompositeActivityDef)LocalObjectLoader.getActDef("ServerItemWorkflow", 0); + Workflow wf = new Workflow((CompositeActivity)serverWfCa.instantiate(), new ServerPredefinedStepContainer()); + wf.initialise(thisServerPath.getItemPath(), systemAgents.get("system").getPath()); + Gateway.getStorage().put(thisServerPath.getItemPath(), wf, null); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/ClientShell.java b/src/main/java/org/cristalise/kernel/process/ClientShell.java new file mode 100644 index 0000000..0a9ad83 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/ClientShell.java @@ -0,0 +1,71 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +import java.util.Scanner; + +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.process.auth.ProxyLogin; +import org.cristalise.kernel.scripting.Script; +import org.cristalise.kernel.scripting.ScriptParsingException; + + +public class ClientShell extends StandardClient { + + AgentProxy user; + Script console; + + public ClientShell(AgentProxy user) throws Exception { + this.user = user; + console = new Script("javascript", user, System.out); + } + + public void run() { + Scanner scan = new Scanner(System.in); + System.out.print("> "); + while (scan.hasNextLine()) { + String command = scan.nextLine(); + try { + console.setScript(command); + Object response = console.execute(); + if (response == null) + System.out.println("Ok"); + else + System.out.println(response); + } catch (ScriptParsingException e) { + System.err.println("Syntax error: "+e.getMessage()); + } catch (Throwable ex) { + ex.printStackTrace(); + } + System.out.print("> "); + } + shutdown(0); + } + + public static void main(String[] args) throws Exception { + Gateway.init(readC2KArgs(args)); + ProxyLogin auth = (ProxyLogin)Gateway.getProperties().getInstance("cli.auth"); + AgentProxy user = auth.authenticate(Gateway.getProperties().getProperty("Name")); + ClientShell shell = new ClientShell(user); + shell.run(); + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/Gateway.java b/src/main/java/org/cristalise/kernel/process/Gateway.java new file mode 100644 index 0000000..c7936c3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/Gateway.java @@ -0,0 +1,426 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +/** + * @version $Revision: 1.17 $ $Date: 2005/10/12 12:51:54 $ + * @author $Author: abranson $ + */ + +import java.net.MalformedURLException; +import java.util.Enumeration; +import java.util.Properties; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.CorbaServer; +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.entity.proxy.ProxyManager; +import org.cristalise.kernel.entity.proxy.ProxyServer; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.Lookup; +import org.cristalise.kernel.lookup.LookupManager; +import org.cristalise.kernel.persistency.TransactionManager; +import org.cristalise.kernel.process.auth.Authenticator; +import org.cristalise.kernel.process.module.ModuleManager; +import org.cristalise.kernel.process.resource.Resource; +import org.cristalise.kernel.process.resource.ResourceLoader; +import org.cristalise.kernel.utils.CastorXMLUtility; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Language; +import org.cristalise.kernel.utils.Logger; +import org.cristalise.kernel.utils.ObjectProperties; + + + +/************************************************************************** + * The Gateway is the central object of a CRISTAL process. It initializes, + * maintains and shuts down every other subsystem in both the client and the + * server. + * + * Child objects: + *
      + *
    • Lookup - Provides access to the CRISTAL directory. Find or + * search for Items or Agents. + *
    • EntityProxyManager - Gives a local proxy object for Entities found + * in LDAP. Execute activities in Items, query or subscribe to Entity data. + *
    • TransactionManager - Access to the configured CRISTAL databases + *
    • CorbaServer - Manages the memory pool of active Entities + *
    • mORB - the Orbacus CORBA ORB + *
    + * + * @author $Author: abranson $ $Date: 2005/10/12 12:51:54 $ + * @version $Revision: 1.17 $ + **************************************************************************/ + +public class Gateway +{ + static private ObjectProperties mC2KProps = new ObjectProperties(); + static private ModuleManager mModules; + static private org.omg.CORBA.ORB mORB; + static private boolean orbDestroyed = false; + static private Lookup mLookup; + static private LookupManager mLookupManager = null; + static private TransactionManager mStorage; + static private ProxyManager mProxyManager; + static private ProxyServer mProxyServer; + static private CorbaServer mCorbaServer; + static private CastorXMLUtility mMarshaller; + static private ResourceLoader mResource; + + + + private Gateway() { } + + /** + * Initialises the Gateway and all of the client objects it holds, with + * the exception of the Lookup, which is initialised during connect() + * + * @param props - java.util.Properties containing all application properties. + * If null, the java system properties are used + * @throws InvalidDataException - invalid properties caused a failure in initialisation + */ + static public void init(Properties props) throws InvalidDataException { + init(props, null); + } + + /** + * Initialises the Gateway and all of the client objects it holds, with + * the exception of the Lookup, which is initialised during connect() + * + * @param props - java.util.Properties containing all application properties. + * If null, the java system properties are used + * @param res - ResourceLoader for the kernel to use to resolve all class resource requests + * such as for bootstrap descriptions and version information + * @throws InvalidDataException - invalid properties caused a failure in initialisation + */ + static public void init(Properties props, ResourceLoader res) throws InvalidDataException { + + // Init properties & resources + mC2KProps.clear(); + + orbDestroyed = false; + mResource = res; + if (mResource == null) mResource = new Resource(); + + // report version info + Logger.msg("Kernel version: "+getKernelVersion()); + + // load kernel mapfiles giving the resourse loader and the properties of + // the application to be able to configure castor + try { + mMarshaller = new CastorXMLUtility(mResource, props, mResource.getKernelResourceURL("mapFiles/")); + } catch (MalformedURLException e1) { + throw new InvalidDataException("Invalid Resource Location"); + } + + + // init module manager + try { + mModules = new ModuleManager(mResource.getModuleDefURLs(), AbstractMain.isServer); + } catch (Exception e) { + Logger.error(e); + throw new InvalidDataException("Could not load module definitions."); + } + + // merge in module props + Properties moduleProperties = mModules.getAllModuleProperties(); + for (Enumeration e = moduleProperties.propertyNames(); e.hasMoreElements();) { + String propName = (String)e.nextElement(); + mC2KProps.put(propName, moduleProperties.get(propName)); + } + + // Overwrite with argument props + if (props != null) mC2KProps.putAll(props); + + // dump properties + dumpC2KProps(7); + + //Initialise language file + String languageFile = getProperties().getString("language.file"); + if (languageFile != null && languageFile.length() > 0) { + Language.isTranlated=true; + Language.mTableOfTranslation = FileStringUtility.loadLanguageFile(languageFile); + } + } + + /** + * Makes this process capable of creating and managing server entities. Runs the + * bootstrap to create the root LDAP contexts, initialises the CORBA server and + * time-out manager. + * + * @throws InvalidDataException - error initialising + */ + static public void startServer(Authenticator auth) throws InvalidDataException, CannotManageException { + try { + // check top level directory contexts + if (mLookup instanceof LookupManager) { + mLookupManager = (LookupManager)mLookup; + mLookupManager.initializeDirectory(); + } + else { + throw new CannotManageException("Lookup implementation is not a LookupManager. Cannot write to directory"); + } + + // start entity proxy server + mProxyServer = new ProxyServer(mC2KProps.getProperty("ItemServer.name")); + + // Init ORB - set various config + String serverName = mC2KProps.getProperty("ItemServer.name"); + if (serverName != null) + mC2KProps.put("com.sun.CORBA.ORBServerHost", serverName); + String serverPort = mC2KProps.getProperty("ItemServer.iiop", "1500"); + mC2KProps.put("com.sun.CORBA.ORBServerPort", serverPort); + //TODO: externalize this (or replace corba completely) + mC2KProps.put("com.sun.CORBA.POA.ORBServerId", "1"); + mC2KProps.put("com.sun.CORBA.POA.ORBPersistentServerPort", serverPort); + mC2KProps.put("com.sun.CORBA.codeset.charsets", "0x05010001, 0x00010109"); // need to force UTF-8 in the Sun ORB + mC2KProps.put("com.sun.CORBA.codeset.wcharsets", "0x00010109, 0x05010001"); + //Standard initialisation of the ORB + orbDestroyed = false; + mORB = org.omg.CORBA.ORB.init(new String[0], mC2KProps); + + Logger.msg("Gateway.init() - ORB initialised. ORB is " + mORB.getClass().getName() ); + + // start corba server components + mCorbaServer = new CorbaServer(); + + // start checking bootstrap & module items + Bootstrap.run(); + System.out.println("Server '"+serverName+"' initialised."); + } catch (Exception ex) { + Logger.error(ex); + Logger.die("Exception starting server components. Shutting down."); + } + + } + + public static ModuleManager getModuleManager() { + return mModules; + } + + /** + * Connects to the LDAP server in an administrative context - using the admin username and + * password given in the LDAP.user and LDAP.password props of the kernel properties. + * + * @throws InvalidDataException - bad params + * @throws PersistencyException - error starting storages + */ + static public Authenticator connect() + throws InvalidDataException, + PersistencyException + { + try { + Authenticator auth = (Authenticator)mC2KProps.getInstance("Authenticator"); + auth.authenticate("System"); + + mLookup = (Lookup)mC2KProps.getInstance("Lookup"); + mLookup.open(auth); + + mStorage = new TransactionManager(auth); + mProxyManager = new ProxyManager(); + + return auth; + } catch (Exception ex) { + Logger.error(ex); + throw new InvalidDataException("Cannot connect server process. Please check config."); + } + + + } + + /** + * Logs in with the given username and password, and initialises the lookup, storage and proxy manager. + * + * @param agentName - username + * @param agentPassword - password + * @return an AgentProxy on the requested user + * @throws InvalidDataException + * @throws PersistencyException + * @throws ClassNotFoundException + * @throws IllegalAccessException + * @throws InstantiationException + */ + static public AgentProxy connect(String agentName, String agentPassword, String resource) + throws InvalidDataException, ObjectNotFoundException, PersistencyException, InstantiationException, IllegalAccessException, ClassNotFoundException + { + Authenticator auth = (Authenticator)mC2KProps.getInstance("Authenticator"); + if (!auth.authenticate(agentName, agentPassword, resource)) + throw new InvalidDataException("Login failed"); + + mLookup = (Lookup)mC2KProps.getInstance("Lookup"); + mLookup.open(auth); + + mStorage = new TransactionManager(auth); + mProxyManager = new ProxyManager(); + + // find agent proxy + AgentPath agentPath = mLookup.getAgentPath(agentName); + AgentProxy userProxy = (AgentProxy) mProxyManager.getProxy(agentPath); + userProxy.setAuthObj(auth); + + // Run module startup scripts. Server does this during bootstrap + mModules.setUser(userProxy); + mModules.runScripts("startup"); + + return userProxy; + } + + static public AgentProxy connect(String agentName, String agentPassword) + throws InvalidDataException, ObjectNotFoundException, PersistencyException, InstantiationException, IllegalAccessException, ClassNotFoundException + { + return connect(agentName, agentPassword, null); + } + + /** + * Shuts down all kernel api objects + */ + public static void close() + { + // run shutdown module scripts + if (mModules != null) + mModules.runScripts("shutdown"); + + // shut down servers if running + if (mCorbaServer != null) + mCorbaServer.close(); + mCorbaServer = null; + + // disconnect from storages + if (mStorage != null) + mStorage.close(); + mStorage = null; + + // disconnect from ldap + if (mLookup != null) + mLookup.close(); + mLookup = null; + mLookupManager = null; + + // shut down proxy manager & server + if (mProxyManager != null) + mProxyManager.shutdown(); + if (mProxyServer != null) + mProxyServer.shutdownServer(); + mProxyManager = null; + mProxyServer = null; + + // close log consoles + Logger.closeConsole(); + + // finally, destroy the ORB + if (!orbDestroyed) { + getORB().destroy(); + orbDestroyed = true; + mORB = null; + } + + // clean up remaining objects + mModules = null; + mResource = null; + mMarshaller = null; + mC2KProps.clear(); + } + + static public org.omg.CORBA.ORB getORB() + { + if (orbDestroyed) throw new RuntimeException("Gateway has been closed. ORB is destroyed. "); + + if (mORB == null) { + mC2KProps.put("com.sun.CORBA.codeset.charsets", "0x05010001, 0x00010109"); // need to force UTF-8 in the Sun ORB + mC2KProps.put("com.sun.CORBA.codeset.wcharsets", "0x00010109, 0x05010001"); + mORB = org.omg.CORBA.ORB.init(new String[0], mC2KProps); + } + return mORB; + } + + static public Lookup getLookup() + { + return mLookup; + } + + static public LookupManager getLookupManager() throws CannotManageException + { + if (mLookupManager == null) + throw new CannotManageException("No Lookup Manager created. Not a server process."); + else + return mLookupManager; + } + + static public CorbaServer getCorbaServer() + { + return mCorbaServer; + } + + static public TransactionManager getStorage() + { + return mStorage; + } + + static public CastorXMLUtility getMarshaller() + { + return mMarshaller; + } + + static public ResourceLoader getResource() + { + return mResource; + } + + static public ProxyManager getProxyManager() + { + return mProxyManager; + } + + + public static ProxyServer getProxyServer() { + return mProxyServer; + } + + static public String getCentreId() { + return getProperties().getString("LocalCentre"); + } + + static public Enumeration propertyNames() { + return mC2KProps.propertyNames(); + } + + static public void dumpC2KProps(int logLevel) { + if (!Logger.doLog(logLevel)) return; + mC2KProps.dumpProps(logLevel); + } + + static public ObjectProperties getProperties() { + return mC2KProps; + } + + static public String getKernelVersion() { + try { + return mResource.getTextResource(null, "textFiles/version.txt"); + } catch (Exception ex) { + return "No version info found"; + } + + } +} + diff --git a/src/main/java/org/cristalise/kernel/process/ShutdownHandler.java b/src/main/java/org/cristalise/kernel/process/ShutdownHandler.java new file mode 100644 index 0000000..f34800d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/ShutdownHandler.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +public interface ShutdownHandler { + + public void shutdown(int errCode, boolean isServer); +} diff --git a/src/main/java/org/cristalise/kernel/process/StandardClient.java b/src/main/java/org/cristalise/kernel/process/StandardClient.java new file mode 100644 index 0000000..c97fed0 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/StandardClient.java @@ -0,0 +1,31 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + + +abstract public class StandardClient extends AbstractMain +{ + + static public void main(String[] args) throws Exception { + Gateway.init(readC2KArgs(args)); + //AgentProxy user = Gateway.connect("username", "password"); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/StandardServer.java b/src/main/java/org/cristalise/kernel/process/StandardServer.java new file mode 100644 index 0000000..9d31b8e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/StandardServer.java @@ -0,0 +1,67 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +import org.cristalise.kernel.process.auth.Authenticator; +import org.cristalise.kernel.utils.Logger; + +/************************************************************************** + * Base class for all servers i.e. c2k processes that serve Entities + * + * @author $Author: abranson $ $Date: 2005/04/28 13:49:43 $ + * @version $Revision: 1.47 $ + **************************************************************************/ +public class StandardServer extends AbstractMain +{ + protected static StandardServer server; + + /************************************************************************** + * void StandardInitalisation( String[] ) + * + * Set-up calls to ORB, POA and Factorys, both optional and required. + **************************************************************************/ + protected static void standardInitialisation( String[] args ) + throws Exception + { + isServer = true; + + // read args and init Gateway + Gateway.init(readC2KArgs(args)); + + // connect to LDAP as root + Authenticator auth = Gateway.connect(); + + //start console + Logger.initConsole("ItemServer"); + + //initialize the server objects + Gateway.startServer(auth); + + Logger.msg(5, "StandardServer::standardInitialisation - complete."); + + } + + public static void main(String[] args) throws Exception + { + //initialise everything + standardInitialisation( args ); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/UserCodeProcess.java b/src/main/java/org/cristalise/kernel/process/UserCodeProcess.java new file mode 100644 index 0000000..ff63baf --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/UserCodeProcess.java @@ -0,0 +1,276 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.HashMap; + +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.agent.Job; +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.entity.proxy.MemberSubscription; +import org.cristalise.kernel.entity.proxy.ProxyObserver; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.scripting.ErrorInfo; +import org.cristalise.kernel.scripting.ScriptErrorException; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * $Revision: 1.31 $ + * $Date: 2004/10/21 08:02:19 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ +public class UserCodeProcess extends StandardClient implements ProxyObserver, Runnable { + + // Default state machine transitions + private static final int START = 1; + private static final int COMPLETE = 2; + private static final int SUSPEND = 3; + private static final int RESUME = 4; + + protected AgentProxy agent; + static boolean active = true; + ArrayList ignoredPaths = new ArrayList(); + HashMap errors = new HashMap(); + final HashMap jobs = new HashMap(); + + public UserCodeProcess(String agentName, String agentPass, String resource) { + // login - try for a while in case server hasn't imported our user yet + for (int i=1;i<6;i++) { + try { + Logger.msg("Login attempt "+i+" of 5"); + agent = Gateway.connect(agentName, agentPass, resource); + break; + } catch (Exception ex) { + Logger.error("Could not log in."); + Logger.error(ex); + try { + Thread.sleep(5000); + } catch (InterruptedException ex2) { } + } + } + System.out.println(getDesc()+" initialised for " + agentName); + } + + @Override + public void run() { + Thread.currentThread().setName("Usercode Process"); + // subscribe to job list + agent.subscribe(new MemberSubscription(this, ClusterStorage.JOB, true)); + while (active) { + Job thisJob = null; + synchronized (jobs) { + if (jobs.size() > 0) { + thisJob = getJob(jobs, COMPLETE); + if (thisJob == null) + thisJob = getJob(jobs, START); + if (thisJob == null) + thisJob = getJob(jobs, SUSPEND); + if (thisJob == null) + thisJob = getJob(jobs, RESUME); + + if (thisJob == null) { + Logger.error("No supported jobs, but joblist is not empty! Discarding remaining jobs"); + jobs.clear(); + } + else + jobs.remove(ClusterStorage.getPath(thisJob)); + } + } + + if (thisJob != null) { + String jobKey = thisJob.getItemPath()+":"+thisJob.getStepPath(); + int transitionId = thisJob.getTransition().getId(); + try { + if (transitionId==START) { + Logger.msg(5, "Testing start conditions"); + boolean start = assessStartConditions(thisJob); + if (start) { + Logger.msg(5, "Attempting to start"); + agent.execute(thisJob); + } + else { + Logger.msg(5, "Start conditions failed "+thisJob.getStepName()+" in "+thisJob.getItemPath()); + } + } + else if (transitionId==COMPLETE) { + Logger.msg(5, "Executing logic"); + runUCLogic(thisJob); + if (ignoredPaths.contains(jobKey)) + ignoredPaths.remove(jobKey); + } + else if (transitionId==SUSPEND) { + if (ignoredPaths.contains(jobKey)) { + if (errors.containsKey(jobKey)) { + thisJob.setOutcome(Gateway.getMarshaller().marshall(errors.get(jobKey))); + errors.remove(jobKey); + } + agent.execute(thisJob); + } + } + else if (transitionId==RESUME) { + if (!ignoredPaths.contains(jobKey)) + agent.execute(thisJob); + } + } catch (ScriptErrorException ex) { + errors.put(jobKey, ex.getErrors()); + ignoredPaths.add(jobKey); + } catch (InvalidTransitionException ex) { + // must have already been done by someone else - ignore + } catch (Throwable ex) { + Logger.error("Error executing "+thisJob.getTransition().getName()+" job:"); + Logger.error(ex); + ErrorInfo ei = new ErrorInfo(); + ei.setFatal(); + ei.addError(ex.getClass().getSimpleName()); + ei.addError(ex.getMessage()); + errors.put(jobKey, ei); + ignoredPaths.add(jobKey); + } + } + try { + synchronized (jobs) { + if (jobs.size() == 0) { + Logger.msg("Sleeping"); + while (active && jobs.size() == 0) + jobs.wait(2000); + } + } + } catch (InterruptedException ex) { } + } + + // shut down + try + { + Gateway.close(); + } + catch( Exception ex ) + { + Logger.error(ex); + } + } + + private static Job getJob(HashMap jobs, int transition) { + for (C2KLocalObject c2kLocalObject : jobs.values()) { + Job thisJob = (Job)c2kLocalObject; + if (thisJob.getTransition().getId() == transition) { + Logger.msg(1,"================================================================="); + Logger.msg(1, "Got "+thisJob.getTransition().getName()+" job for "+thisJob.getStepName()+" in "+thisJob.getItemPath()); + return thisJob; + } + } + return null; + } + + public boolean assessStartConditions(Job job) { + // default implementation - has no start conditions. + return true; + } + + public void runUCLogic(Job job) throws Exception { + // default implementation - the agent will execute any scripts defined when we execute + agent.execute(job); + } + + + /** + * Receives job from the AgentProxy. Reactivates thread if sleeping. + */ + @Override + public void add(Job contents) { + synchronized(jobs) { + Logger.msg(7, "Adding "+ClusterStorage.getPath(contents)); + jobs.put(ClusterStorage.getPath(contents), contents); + jobs.notify(); + } + + } + + @Override + public void control(String control, String msg) { + if (MemberSubscription.ERROR.equals(control)) + Logger.error("Error in job subscription: "+msg); + } + + /** + * Removes job removal notification from the AgentProxy. + */ + @Override + public void remove(String id) { + synchronized(jobs) { + Logger.msg(7, "Deleting "+id); + jobs.remove(id); + } + } + + public static UserCodeProcess getInstance() throws UnknownHostException { + return new UserCodeProcess(InetAddress.getLocalHost().getHostName(), "uc", Gateway.getProperties().getString("AuthResource", "Cristal")); + } + + static public void main(String[] args) + { + int status = 0; + + try + { + Gateway.init(readC2KArgs(args)); + UserCodeProcess proc = getInstance(); + new Thread(proc).start(); + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + shutdown(); + } + })); + } + catch( Exception ex ) + { + Logger.error(ex); + + try + { + Gateway.close(); + } + catch(Exception ex1) + { + Logger.error(ex1); + } + status = 1; + System.exit(status); + } + } + + public String getDesc() { + return("Usercode Process"); + } + + public static void shutdown() { + active = false; + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/auth/Authenticator.java b/src/main/java/org/cristalise/kernel/process/auth/Authenticator.java new file mode 100644 index 0000000..2d92d4d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/auth/Authenticator.java @@ -0,0 +1,93 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.auth; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; + +/** + * This interface is used by the kernel to store an authenticated connection + * and/or token that will be used by kernel components. The CRISTAL property + * 'Authenticator' is used to specify the implementation used. It is + * instantiated by the connect() methods of the Gateway, and will be found in + * the AgentProxy returned by connect(). Lookup and ClusterStorage instances are + * initialized with this Authenticator, which is expected to maintain the same + * user's connection through the process lifetime, reconnecting if the + * connection is lost. + * + * @since 3.0 + * + */ +public interface Authenticator { + + /** + * Authenticates a CRISTAL agent. If this method returns true, then the + * connect method will create and return an AgentProxy for the given + * username using the Lookup and ProxyManager. + * + * @param agentName + * The username of the Agent to be authenticated. This must be + * already present as an Agent in the CRISTAL directory. + * @param password + * The Agent's password + * @param resource + * The authentication resource/domain/realm of the agent. + * Included so that domains may include CRISTAL users from + * different realms. This parameter is passed into the connect() + * method if required. May be null. + * @return a boolean indicating if the authentication was successful. If so, + * then the Gateway will generate an AgentProxy for the given user. + * @throws ObjectNotFoundException + * When the Agent doesn't exist + * @throws InvalidDataException + * When authentication fails for another reason + */ + public boolean authenticate(String agentName, String password, + String resource) throws InvalidDataException, + ObjectNotFoundException; + + /** + * Authenticates a superuser connection for the server. It must be able to + * act on behalf of any other Agent, as the server needs to do this. + * Credentials may be in the CRISTAL properties, or some other mechanism. + * + * @param resource + * @return + * @throws InvalidDataException + * @throws ObjectNotFoundException + */ + public boolean authenticate(String resource) throws InvalidDataException, + ObjectNotFoundException; + + /** + * Lookup and storage implementations that need to use user or superuser + * authentication can retrieve it using this method. This will be highly + * implementation specific. + * + * @return the connection/token created during authentication + */ + public Object getAuthObject(); + + /** + * Close or expire the connection as the CRISTAL process shuts down. + */ + public void disconnect(); +} diff --git a/src/main/java/org/cristalise/kernel/process/auth/ConsoleAuth.java b/src/main/java/org/cristalise/kernel/process/auth/ConsoleAuth.java new file mode 100644 index 0000000..319c792 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/auth/ConsoleAuth.java @@ -0,0 +1,65 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.auth; + +import java.util.Properties; +import java.util.Scanner; + +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.process.Gateway; + + +public class ConsoleAuth implements ProxyLogin { + + public ConsoleAuth() { + } + + @Override + public void initialize(Properties props) throws Exception { + + } + @Override + public AgentProxy authenticate(String resource) throws Exception { + AgentProxy user = null; + if (resource!=null) System.out.println("Please log in"+(resource.length()>0?"to "+resource:"")); + Scanner scan = new Scanner(System.in); + int loginAttempts = 0; + while (user == null && loginAttempts++ < 3) { + System.out.print("User:"); + String username = scan.nextLine(); + System.out.print("Password:"); + String pass = scan.nextLine(); + try { + user = Gateway.connect(username, pass, resource); + } catch (Exception ex) { + System.err.println(ex.getMessage()); + } + } + + if (user == null) { + System.err.println("Bye"); + System.exit(0); + } + return user; + + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/auth/ProxyLogin.java b/src/main/java/org/cristalise/kernel/process/auth/ProxyLogin.java new file mode 100644 index 0000000..9305d50 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/auth/ProxyLogin.java @@ -0,0 +1,42 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.auth; + +import java.util.Properties; + +import org.cristalise.kernel.entity.proxy.AgentProxy; + + +/** + * This interface is used by client processes to implement alternative login + * mechanisms aside from the standard username and password. Implementations may + * synchronize Agents with an external user library, such as Active Directory. + * Implementations are expected to set up the Gateway process and its + * authenticated components itself. + * + */ +public interface ProxyLogin { + + public void initialize(Properties props) throws Exception; + + public AgentProxy authenticate(String resource) throws Exception; + +} diff --git a/src/main/java/org/cristalise/kernel/process/module/Module.java b/src/main/java/org/cristalise/kernel/process/module/Module.java new file mode 100644 index 0000000..840614b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/Module.java @@ -0,0 +1,224 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import java.util.ArrayList; +import java.util.Properties; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.imports.ImportAgent; +import org.cristalise.kernel.entity.imports.ImportDependency; +import org.cristalise.kernel.entity.imports.ImportDependencyMember; +import org.cristalise.kernel.entity.imports.ImportItem; +import org.cristalise.kernel.entity.imports.ImportOutcome; +import org.cristalise.kernel.entity.imports.ImportRole; +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.scripting.ErrorInfo; +import org.cristalise.kernel.scripting.ScriptingEngineException; +import org.cristalise.kernel.utils.Logger; + + +public class Module extends ImportItem { + + private ModuleInfo info; + private String resURL; + private ModuleImports imports = new ModuleImports(); + private ArrayList config = new ArrayList(); + private ArrayList scripts = new ArrayList(); + + public Module() { + super(); + // Module properties + properties.add(new Property("Type", "Module", false)); + setInitialPath("/desc/modules/"); + setWorkflow("NoWorkflow"); + setWorkflowVer(0); + imports.list.add(this); + } + + public void runScript(String event, AgentProxy user, boolean isServer) throws ScriptingEngineException { + for (ModuleScript script : scripts) { + if (script.shouldRun(event, isServer)) { + Logger.msg("Running "+script.event+" "+script.target+" script from "+name); + Object result = script.getScript(ns, user).execute(); + if (result instanceof ErrorInfo) { + ErrorInfo error = (ErrorInfo) result; + Logger.error(error.toString()); + if (error.getFatal()) + throw new ScriptingEngineException("Fatal Script Error"); + } + else if (result != null) + Logger.msg(result.toString()); + } + } + } + + public void setModuleXML(String moduleXML) { + ImportOutcome moduleOutcome = new ImportOutcome("Module", 0, "last", null); + moduleOutcome.data = moduleXML; + outcomes.add(moduleOutcome); + } + + @Override + public void setNamespace(String ns) { + super.setNamespace(ns); + replaceProp(new Property("Namespace", ns, false)); + } + + @Override + public void setName(String name) { + super.setName(name); + replaceProp(new Property("Name", name, false)); + } + + private void replaceProp(Property newProp) { + for (Property prop : properties) { + if (prop.getName().equals("Namespace")) { + prop.setMutable(newProp.isMutable()); + prop.setValue(newProp.getValue()); + return; + } + } + properties.add(newProp); + } + public void importAll(ItemProxy serverEntity, AgentProxy systemAgent, String moduleXML, boolean reset) throws Exception { + setModuleXML(moduleXML); + + for (ModuleResource thisRes : imports.getResources()) { + try { + thisRes.setNamespace(ns); + thisRes.create(systemAgent.getPath(), reset); + } catch (Exception ex) { + Logger.error(ex); + Logger.die("Error importing module resources. Unsafe to continue."); + } + } + + for (ImportRole thisRole : imports.getRoles()) { + RolePath rolePath; + try { + String roleName = thisRole.name; + if (roleName.indexOf('/') > -1) roleName = roleName.substring(roleName.indexOf('/')+1); + rolePath = Gateway.getLookup().getRolePath(roleName); + if (rolePath.hasJobList() != thisRole.hasJobList()) { + Logger.msg("Module.importAll() - Role '"+thisRole.name+"' has incorrect joblist settings. Correcting."); + rolePath.setHasJobList(thisRole.hasJobList()); + Gateway.getLookupManager().createRole(rolePath); + } + } catch (ObjectNotFoundException ex) { + Logger.msg("Module.importAll() - Role '"+thisRole.name+"' not found. Creating."); + thisRole.create(systemAgent.getPath(), reset); + } + } + + for (ImportAgent thisAgent : imports.getAgents()) { + try { + Gateway.getLookup().getAgentPath(thisAgent.name); + Logger.msg(3, "Module.importAll() - User '"+thisAgent.name+"' found."); + continue; + } catch (ObjectNotFoundException ex) { } + Logger.msg("Module.importAll() - User '"+thisAgent.name+"' not found. Creating."); + thisAgent.create(systemAgent.getPath(), reset); + } + + for (ImportItem thisItem : imports.getItems()) { + thisItem.setNamespace(ns); + thisItem.create(systemAgent.getPath(), reset); + } + + } + + public Properties getProperties(boolean isServer) { + Properties props = new Properties(); + for (ModuleConfig thisProp : config) { + if (thisProp.include(isServer)) + props.put(thisProp.name, thisProp.value); + } + return props; + } + + public ArrayList getScripts() { + return scripts; + } + + public void setResURL(String resURL) { + this.resURL = resURL; + } + public String getDesc() { + return info.desc; + } + public String getVersion() { + return info.version; + } + public String getResURL() { + return resURL; + } + public ArrayList getDependencies() { + return info.dependency; + } + public boolean hasDependency(String dep) { + return info.dependency.contains(dep); + } + + public ModuleInfo getInfo() { + return info; + } + + public void setInfo(ModuleInfo info) { + this.info = info; + replaceProp(new Property("Version", info.version, true)); + } + + public ModuleImports getImports() { + return imports; + } + + public void setImports(ModuleImports imp) { + // Add dependency for all children + imports = imp; + ImportDependency children = new ImportDependency("Contents"); + for (ModuleImport thisImport : imports.list) { + DomainPath path = thisImport.domainPath; + if (path != null) + children.dependencyMemberList.add(new ImportDependencyMember(path.toString())); + } + dependencyList.add(children); + } + + public void setConfig(ArrayList config) { + this.config = config; + } + + public void setScripts(ArrayList scripts) { + this.scripts = scripts; + } + + public ArrayList getConfig() { + return config; + } + + +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleConfig.java b/src/main/java/org/cristalise/kernel/process/module/ModuleConfig.java new file mode 100644 index 0000000..1165e31 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleConfig.java @@ -0,0 +1,42 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +public class ModuleConfig { + + public String name; + public String value; + public String target; + + public ModuleConfig() { + } + + public ModuleConfig(String name, String value, String target) { + super(); + this.name = name; + this.value = value; + this.target = target; + } + + public boolean include(boolean isServer) { + return (target == null || target.length() == 0 || isServer == target.equals("server")); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleException.java b/src/main/java/org/cristalise/kernel/process/module/ModuleException.java new file mode 100644 index 0000000..e09107e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleException.java @@ -0,0 +1,29 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +public class ModuleException extends Exception { + + public ModuleException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleImport.java b/src/main/java/org/cristalise/kernel/process/module/ModuleImport.java new file mode 100644 index 0000000..22faa5a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleImport.java @@ -0,0 +1,87 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; + + +public abstract class ModuleImport { + + protected String ns; + protected String name; + protected DomainPath domainPath; + protected ItemPath itemPath; + + public ModuleImport() { + } + + public abstract void create(AgentPath agentPath, boolean reset) throws ObjectNotFoundException, + ObjectCannotBeUpdated, CannotManageException, ObjectAlreadyExistsException, InvalidCollectionModification; + + public void setID( String uuid ) throws InvalidItemPathException + { + if (uuid != null && uuid.length() > 0) itemPath = new ItemPath(uuid); + } + + public String getID() { + return itemPath==null?null:itemPath.getUUID().toString(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void setNamespace(String ns) { + this.ns = ns; + } + + public String getNamespace() { + return ns; + } + + public DomainPath getDomainPath() { + return domainPath; + } + + public void setDomainPath(DomainPath domainPath) { + this.domainPath = domainPath; + } + + public ItemPath getItemPath() { + return itemPath; + } + + public void setItemPath(ItemPath itemPath) { + this.itemPath = itemPath; + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleImports.java b/src/main/java/org/cristalise/kernel/process/module/ModuleImports.java new file mode 100644 index 0000000..53c7e9d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleImports.java @@ -0,0 +1,78 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import java.util.ArrayList; + +import org.cristalise.kernel.entity.imports.ImportAgent; +import org.cristalise.kernel.entity.imports.ImportItem; +import org.cristalise.kernel.entity.imports.ImportRole; +import org.cristalise.kernel.utils.CastorArrayList; + + +public class ModuleImports extends CastorArrayList { + + public ModuleImports() + { + super(); + } + + public ModuleImports(ArrayList aList) + { + super(aList); + } + + public ArrayList getResources() { + ArrayList subset = new ArrayList(); + for (ModuleImport imp : list) { + if (imp instanceof ModuleResource) + subset.add((ModuleResource)imp); + } + return subset; + } + + public ArrayList getItems() { + ArrayList subset = new ArrayList(); + for (ModuleImport imp : list) { + if (imp instanceof ImportItem) + subset.add((ImportItem)imp); + } + return subset; + } + + public ArrayList getAgents() { + ArrayList subset = new ArrayList(); + for (ModuleImport imp : list) { + if (imp instanceof ImportAgent) + subset.add((ImportAgent)imp); + } + return subset; + } + + public ArrayList getRoles() { + ArrayList subset = new ArrayList(); + for (ModuleImport imp : list) { + if (imp instanceof ImportRole) + subset.add((ImportRole)imp); + } + return subset; + } +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleInfo.java b/src/main/java/org/cristalise/kernel/process/module/ModuleInfo.java new file mode 100644 index 0000000..8f482fc --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleInfo.java @@ -0,0 +1,34 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import java.util.ArrayList; + +public class ModuleInfo { + + public String desc; + public String version; + public ArrayList dependency = new ArrayList(); + + public ModuleInfo() { + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleManager.java b/src/main/java/org/cristalise/kernel/process/module/ModuleManager.java new file mode 100644 index 0000000..d95abe6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleManager.java @@ -0,0 +1,211 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Properties; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.persistency.outcome.OutcomeValidator; +import org.cristalise.kernel.persistency.outcome.Schema; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.scripting.ScriptingEngineException; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Logger; + + +public class ModuleManager { + ArrayList modules = new ArrayList(); + HashMap modulesXML = new HashMap(); + Properties props = new Properties(); + AgentProxy user; + boolean isServer; + OutcomeValidator moduleValidator; + + public ModuleManager(Enumeration moduleEnum, boolean isServer) throws ModuleException { + this.isServer = isServer; + try { + Schema moduleSchema = new Schema("Module", 0, + FileStringUtility.url2String(Gateway.getResource().getKernelResourceURL("boot/OD/Module.xsd"))); + moduleValidator = new OutcomeValidator(moduleSchema); + } catch (InvalidDataException ex) { + Logger.error(ex); + throw new ModuleException("Module Schema is not valid"); + } catch (IOException ex) { + throw new ModuleException("Could not load Module Schema from kernel resources"); + } + ArrayList loadedModules = new ArrayList(); + ArrayList moduleNs = new ArrayList(); + while(moduleEnum.hasMoreElements()) { + URL newModuleURL = moduleEnum.nextElement(); + try { + String moduleXML = FileStringUtility.url2String(newModuleURL); + String errors = moduleValidator.validate(moduleXML); + if (errors.length() > 0) + throw new ModuleException("Module XML found at "+newModuleURL+" was not valid: "+errors); + Module newModule = (Module)Gateway.getMarshaller().unmarshall(moduleXML); + if (newModule.getResURL() != null && newModule.getResURL().length()>0) Gateway.getResource().addModuleBaseURL(newModule.getNamespace(), newModule.getResURL()); + modules.add(newModule); + modulesXML.put(newModule.getNamespace(), moduleXML); + if (loadedModules.contains(newModule.getName())) throw new ModuleException("Module name clash: "+newModule.getName()); + if (moduleNs.contains(newModule.getNamespace())) throw new ModuleException("Module namespace clash: "+newModule.getNamespace()); + Logger.debug(4, "Module found: "+newModule.getNamespace()+" - "+newModule.getName()); + loadedModules.add(newModule.getName()); moduleNs.add(newModule.getNamespace()); + } catch (ModuleException e) { + Logger.error("Could not load module description from "+newModuleURL); + throw e; + } catch (Exception e) { + Logger.error(e); + throw new ModuleException("Could not load module.xml from "+newModuleURL); + } + } + + Logger.debug(5, "Checking dependencies"); + boolean allDepsPresent = true; + + ArrayList prevModules = new ArrayList(); + for (int i=0; i deps = thisMod.getDependencies(); + depClean = true; + for (String dep : deps) { + Logger.msg(6, thisMod.getName()+" depends on "+dep); + if (!loadedModules.contains(dep)) { + Logger.error("UNMET MODULE DEPENDENCY: "+thisMod.getName()+" requires "+dep); + allDepsPresent = false; + } + else if (!prevModules.contains(dep)) { + Logger.msg(1, "ModuleManager: Shuffling "+thisMod.getName()+" to the end to fulfil dependency on "+dep); + modules.remove(i); + modules.add(thisMod); + thisMod = modules.get(i); + skipped++; + depClean = false; + break; + } + } + if (skipped > modules.size()-i) { + StringBuffer badMod = new StringBuffer(); + for (Module mod : modules.subList(i, modules.size())) { + badMod.append(mod.getName()).append(" "); + } + Logger.die("Circular module dependencies involving: "+badMod); + } + } + // Current module is 'next', this is the correct order to load the properties + Properties modProp = thisMod.getProperties(isServer); + for (Enumeration e = modProp.propertyNames(); e.hasMoreElements();) { + String propName = (String)e.nextElement(); + props.put(propName, modProp.get(propName)); + } + prevModules.add(thisMod.getName()); + } + if (!allDepsPresent) Logger.die("Unmet module dependencies. Cannot continue"); + } + + public void setUser(AgentProxy user) { + this.user = user; + } + + public String getModuleVersions() { + StringBuffer ver = new StringBuffer(); + for (Module thisMod : modules) { + if (ver.length()>0) ver.append("; "); + ver.append(thisMod.getName()+" ("+thisMod.getVersion()+")"); + } + return ver.toString(); + } + + + public Properties getAllModuleProperties() { + return props; + } + + public void runScripts(String event) { + for (Module thisMod : modules) { + try { + thisMod.runScript(event, user, isServer); + } catch (ScriptingEngineException e) { + Logger.error(e); + Logger.die(e.getMessage()); + } + } + } + + public void registerModules() throws ModuleException { + ItemProxy serverEntity; + try { + serverEntity = Gateway.getProxyManager().getProxy(new DomainPath("/servers/"+Gateway.getProperties().getString("ItemServer.name"))); + } catch (ObjectNotFoundException e) { + throw new ModuleException("Cannot find local server name."); + } + Logger.debug(3, "Registering modules"); + + boolean reset = Gateway.getProperties().getBoolean("Module.reset", false); + + for (Module thisMod : modules) { + + Logger.msg("Registering module "+thisMod.getName()); + try { + String thisResetKey = "Module."+thisMod.getNamespace()+".reset"; + boolean thisReset = reset; + if (Gateway.getProperties().containsKey(thisResetKey)) + thisReset = Gateway.getProperties().getBoolean(thisResetKey); + thisMod.importAll(serverEntity, user, modulesXML.get(thisMod.getNamespace()), thisReset); + } catch (Exception e) { + Logger.error(e); + throw new ModuleException("Error importing items for module "+thisMod.getName()); + } + Logger.msg("Module "+thisMod.getName()+" registered"); + + try { + thisMod.runScript("startup", user, true); + } catch (ScriptingEngineException e) { + Logger.error(e); + throw new ModuleException("Error in startup script for module "+thisMod.getName()); + } + + } + } + + public void dumpModules() { + for (Module thisMod : modules) { + try { + FileStringUtility.string2File(thisMod.getName()+".xml", Gateway.getMarshaller().marshall(thisMod)); + } catch (Exception e) { + Logger.error(e); + } + } + + } +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleResource.java b/src/main/java/org/cristalise/kernel/process/module/ModuleResource.java new file mode 100644 index 0000000..74b5673 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleResource.java @@ -0,0 +1,80 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.process.Bootstrap; +import org.cristalise.kernel.utils.Logger; + + +public class ModuleResource extends ModuleImport { + + public int version; + public String resourceType; + public String resourceLocation; + + public ModuleResource() { + // if not given, version defaults to 0 + version = 0; + } + + @Override + public void create(AgentPath agentPath, boolean reset) + throws ObjectNotFoundException, ObjectCannotBeUpdated, + CannotManageException, ObjectAlreadyExistsException { + try { + domainPath = Bootstrap.verifyResource(ns, name, version, resourceType, itemPath, resourceLocation, reset); + } catch (Exception e) { + Logger.error(e); + throw new CannotManageException("Exception verifying module resource "+ns+"/"+name); + } + } + + public int getVersion() { + return version; + } + + public void setVersion(int version) { + this.version = version; + } + + public String getResourceType() { + return resourceType; + } + + public void setResourceType(String resourceType) { + this.resourceType = resourceType; + } + + public String getResourceLocation() { + return resourceLocation; + } + + public void setResourceLocation(String resourceLocation) { + this.resourceLocation = resourceLocation; + } + + +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleScript.java b/src/main/java/org/cristalise/kernel/process/module/ModuleScript.java new file mode 100644 index 0000000..4e81864 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleScript.java @@ -0,0 +1,53 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.scripting.Script; +import org.cristalise.kernel.scripting.ScriptingEngineException; + +public class ModuleScript { + + + public String target; + public String event; + public String lang; + public String script; + public ModuleScript() { + } + + public ModuleScript(String target, String event, String lang, String script) { + super(); + this.target = target; + this.event = event; + this.lang = lang; + this.script = script; + } + + public Script getScript(String ns, AgentProxy user) throws ScriptingEngineException { + return new Script(lang, ns+" "+target+" "+event, script, user); + } + + public boolean shouldRun(String event, boolean isServer) { + return ((this.target == null || this.target.length() == 0 || isServer == target.equals("server")) && + (this.event == null || this.event.length() == 0 || event.equals(this.event))); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/resource/BadArgumentsException.java b/src/main/java/org/cristalise/kernel/process/resource/BadArgumentsException.java new file mode 100644 index 0000000..d8d7dc9 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/BadArgumentsException.java @@ -0,0 +1,37 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.resource; + +public class BadArgumentsException extends Exception { + + public BadArgumentsException() { + super(); + } + + public BadArgumentsException(String message) { + super(message); + } + + public BadArgumentsException(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/resource/DefaultResourceImportHandler.java b/src/main/java/org/cristalise/kernel/process/resource/DefaultResourceImportHandler.java new file mode 100644 index 0000000..dbd2d44 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/DefaultResourceImportHandler.java @@ -0,0 +1,106 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.resource; + +import java.util.HashSet; +import java.util.Set; + +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.PropertyDescriptionList; + + +public class DefaultResourceImportHandler implements ResourceImportHandler { + + String schemaName; + String typeRoot; + DomainPath typeRootPath; + String wfDef; + PropertyDescriptionList props; + + public DefaultResourceImportHandler(String resType) throws Exception { + if (resType.equals("CA")) { + wfDef = "ManageCompositeActDef"; + schemaName = "CompositeActivityDef"; + typeRoot = "/desc/ActivityDesc"; + } + else if (resType.equals("EA")) { + wfDef = "ManageElementaryActDef"; + schemaName = "ElementaryActivityDef"; + typeRoot = "/desc/ActivityDesc"; + } + else if (resType.equals("OD")) { + wfDef = "ManageSchema"; + schemaName = "Schema"; + typeRoot = "/desc/OutcomeDesc"; + } + else if (resType.equals("SC")) { + wfDef = "ManageScript"; + schemaName = "Script"; + typeRoot = "/desc/Script"; + } + else if (resType.equals("SM")) { + wfDef = "ManageStateMachine"; + schemaName = "StateMachine"; + typeRoot = "/desc/StateMachine"; + } + else throw new Exception("Unknown bootstrap item type: "+resType); + typeRootPath = new DomainPath(typeRoot); + props = (PropertyDescriptionList)Gateway.getMarshaller().unmarshall(Gateway.getResource().getTextResource(null, "boot/property/"+resType+"Prop.xml")); + } + + @Override + public DomainPath getTypeRoot() { + return typeRootPath; + } + + @Override + public String getName() { + return schemaName; + } + + @Override + public DomainPath getPath(String name, String ns) throws Exception { + return new DomainPath(typeRoot+"/system/"+(ns==null?"kernel":ns)+'/'+name); + } + + @Override + public Set getResourceOutcomes(String name, String ns, String location, int version) throws Exception { + HashSet retArr = new HashSet(); + String data = Gateway.getResource().getTextResource(ns, location); + if (data == null) + throw new Exception("No data found for "+schemaName+" "+name); + Outcome resOutcome = new Outcome(0, data, schemaName, 0); + retArr.add(resOutcome); + return retArr; + } + + @Override + public PropertyDescriptionList getPropDesc() throws Exception { + return props; + } + + @Override + public String getWorkflowName() throws Exception { + return wfDef; + } +} diff --git a/src/main/java/org/cristalise/kernel/process/resource/Resource.java b/src/main/java/org/cristalise/kernel/process/resource/Resource.java new file mode 100644 index 0000000..25b1ee8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/Resource.java @@ -0,0 +1,196 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.resource; + +//Java +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2005/10/05 07:39:36 $ + * @version $Revision: 1.71 $ + **************************************************************************/ +public class Resource implements ResourceLoader { + + private final Hashtable txtCache = new Hashtable(); + private final URL baseURL; + private final HashMap moduleBaseURLs = new HashMap(); + private final HashMap allBaseURLs = new HashMap(); + + public Resource() throws InvalidDataException { + baseURL = getURLorResURL("org/cristalise/kernel/utils/resources/"); + allBaseURLs.put(null, baseURL); + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getKernelBaseURL() + */ + @Override + public URL getKernelBaseURL() { + return baseURL; + } + + @Override + public ClassLoader getClassLoader(String className) { + return Resource.class.getClassLoader(); + } + + @Override + public Class getClassForName(String name) throws ClassNotFoundException { + return Class.forName(name); + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getKernelResourceURL(java.lang.String) + */ + @Override + public URL getKernelResourceURL(String resName) throws MalformedURLException { + return new URL(baseURL, resName); + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#addModuleBaseURL(java.lang.String, java.net.URL) + */ + @Override + public void addModuleBaseURL(String ns, URL newBaseURL) { + moduleBaseURLs.put(ns, newBaseURL); + allBaseURLs.put(ns, newBaseURL); + Logger.msg("Adding resource URL for "+ns+": "+newBaseURL.toString()); + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#addModuleBaseURL(java.lang.String, java.lang.String) + */ + @Override + public void addModuleBaseURL(String ns, String newBaseURL) throws InvalidDataException { + addModuleBaseURL(ns, getURLorResURL(newBaseURL)); + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getModuleBaseURLs() + */ + @Override + public HashMap getModuleBaseURLs() { + return moduleBaseURLs; + } + + private HashMap getAllBaseURLs() { + return allBaseURLs; + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getModuleResourceURL(java.lang.String, java.lang.String) + */ + @Override + public URL getModuleResourceURL(String ns, String resName) throws MalformedURLException { + return new URL(moduleBaseURLs.get(ns), resName); + } + + static private URL getURLorResURL(String newURL) throws InvalidDataException { + URL result; + try { + result = new URL(newURL); + } catch (java.net.MalformedURLException ex) { + //it is assumed that a 'wrong' URL denotes a directory + //of files resolvable from the CLASSPATH + result = Resource.class.getClassLoader().getResource(newURL); + } + if (result == null) { + Logger.error("URL "+newURL+" could not be found"); + throw new InvalidDataException(); + } + return result; + } + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#findTextResource(java.lang.String) + */ + + @Override + public String findTextResource(String resName) { + for (String ns : getAllBaseURLs().keySet()) { + try { + return getTextResource(ns, resName); + } catch (ObjectNotFoundException ex) { } + } + Logger.warning("Text resource '"+resName+"' not found."); + return null; + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getAllTextResources(java.lang.String) + */ + @Override + public HashMap getAllTextResources(String resName) { + HashMap results = new HashMap(); + for (String ns : getAllBaseURLs().keySet()) { + try { + results.put(ns, getTextResource(ns, resName)); + } catch (ObjectNotFoundException ex) { } + } + return results; + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getTextResource(java.lang.String, java.lang.String) + */ + @Override + public String getTextResource(String ns, String resName) throws ObjectNotFoundException + // throws IOException + { + Logger.msg(8, "Resource::getTextResource() - Getting resource from "+ns+": " + resName); + + if (txtCache.containsKey(ns+'/'+resName)) { + return txtCache.get(ns+'/'+resName); + } + + try { + + String newRes = null; + URL loc; + + if (ns == null) // kernel + loc = getKernelResourceURL(resName); + else + loc = getModuleResourceURL(ns, resName); + Logger.msg(5, "Loading resource: "+loc.toString()); + newRes = FileStringUtility.url2String(loc); + txtCache.put(ns+'/'+resName, newRes); + return newRes; + } catch (Exception e) { + throw new ObjectNotFoundException(e.getMessage()); + } + } + + @Override + public Enumeration getModuleDefURLs() throws Exception { + return ClassLoader.getSystemResources("META-INF/cristal/module.xml"); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/resource/ResourceImportHandler.java b/src/main/java/org/cristalise/kernel/process/resource/ResourceImportHandler.java new file mode 100644 index 0000000..9d37e31 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/ResourceImportHandler.java @@ -0,0 +1,68 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.resource; + +import java.util.Set; + +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.property.PropertyDescriptionList; + + +public interface ResourceImportHandler { + + + /** Returns the DomainPath for a specific resource + * @param ns - module namespace + * @param name - resource name + * @return + */ + public DomainPath getPath(String name, String ns) throws Exception; + + /** Generates the outcomes that the resource should contain. + * @param res - the module resource definition + * @return a set of outcomes to be synced with the resource item. + * @throws Exception - if the supplied resources are not valid + */ + public Set getResourceOutcomes(String name, String ns, String location, int version) throws Exception; + + /** Gives the CompActDef name to instantiate to provide the workflow for this type of resource. + * Should be found in the CA typeroot (/desc/ActivityDesc/) + * @return String workflow name + * @throws Exception + */ + public String getWorkflowName() throws Exception; + + /** Should return all of the Properties the resource Item + * will have on creation. The Property 'Name' will be created and populated automatically, even if not declared. + * @return a PropertyDescriptionList - an arraylist of PropertyDescriptions + * @throws Exception + */ + public PropertyDescriptionList getPropDesc() throws Exception; + + /** The directory context to search for existing resources. The name of the resource must be unique below this point. + * @return Root path + */ + public DomainPath getTypeRoot(); + + public String getName(); + +} diff --git a/src/main/java/org/cristalise/kernel/process/resource/ResourceLoader.java b/src/main/java/org/cristalise/kernel/process/resource/ResourceLoader.java new file mode 100644 index 0000000..4ef0e9d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/ResourceLoader.java @@ -0,0 +1,67 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.resource; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; + + +public interface ResourceLoader { + + public URL getKernelBaseURL(); + + public URL getKernelResourceURL(String resName) + throws MalformedURLException; + + public void addModuleBaseURL(String ns, URL newBaseURL); + + public void addModuleBaseURL(String ns, String newBaseURL) + throws InvalidDataException; + + public HashMap getModuleBaseURLs(); + + public URL getModuleResourceURL(String ns, String resName) + throws MalformedURLException; + + /************************************************************************** + * Gets any text resource files + **************************************************************************/ + + public String findTextResource(String resName); + + public HashMap getAllTextResources(String resName); + + public String getTextResource(String ns, String resName) + throws ObjectNotFoundException; + + public Class getClassForName(String name) + throws ClassNotFoundException; + + public ClassLoader getClassLoader(String className); + + public Enumeration getModuleDefURLs() throws Exception; + +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/property/Property.java b/src/main/java/org/cristalise/kernel/property/Property.java new file mode 100644 index 0000000..920574c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/property/Property.java @@ -0,0 +1,112 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.property; + +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.persistency.ClusterStorage; + + +public class Property implements C2KLocalObject +{ + private String mName; + private String mValue; + private boolean mMutable = true; + + + /************************************************************************** + * + **************************************************************************/ + public Property() + { + } + + + /************************************************************************** + * + **************************************************************************/ + public Property( String name, String value, boolean mutable ) + { + setName( name ); + setValue( value ); + setMutable( mutable ); + } + + public Property( String name, String value) + { + setName( name ); + setValue( value ); + } + + /************************************************************************** + * + **************************************************************************/ + @Override + public void setName(String name) + { + mName = name; + } + + + public boolean isMutable() { + return mMutable; + } + + + public void setMutable(boolean mMutable) { + this.mMutable = mMutable; + } + + +/************************************************************************** + * + **************************************************************************/ + @Override + public String getName() + { + return mName; + } + + + /************************************************************************** + * + **************************************************************************/ + public void setValue( String value ) + { + mValue = value; + } + + + /************************************************************************** + * + **************************************************************************/ + public String getValue() + { + return mValue; + } + /** + * @see org.cristalise.kernel.entity.C2KLocalObject#getClusterType() + */ + @Override + public String getClusterType() { + return ClusterStorage.PROPERTY; + } + +} diff --git a/src/main/java/org/cristalise/kernel/property/PropertyArrayList.java b/src/main/java/org/cristalise/kernel/property/PropertyArrayList.java new file mode 100644 index 0000000..3e981a0 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/property/PropertyArrayList.java @@ -0,0 +1,54 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.property; + +import java.util.ArrayList; + +import org.cristalise.kernel.utils.CastorArrayList; + + +public class PropertyArrayList extends CastorArrayList +{ + public PropertyArrayList() + { + super(); + } + + public PropertyArrayList(ArrayList aList) + { + super(); + // put all properties in order, so later ones with the same name overwrite earlier ones + for (Property property : aList) { + put(property); + } + } + + /** Overwrite */ + public void put(Property p) { + for (Property thisProp : list) { + if (thisProp.getName().equals(p.getName())) { + list.remove(thisProp); + break; + } + } + list.add(p); + } +} diff --git a/src/main/java/org/cristalise/kernel/property/PropertyDescription.java b/src/main/java/org/cristalise/kernel/property/PropertyDescription.java new file mode 100644 index 0000000..29b10b1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/property/PropertyDescription.java @@ -0,0 +1,88 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.property; + +public class PropertyDescription +{ + private String mName=null; + private String mDefaultValue=null; + private boolean mIsClassIdentifier=false; + private boolean mIsMutable=false; + + + public PropertyDescription() + { + } + + public PropertyDescription(String name, String defaultValue, boolean isClassIdentifier, boolean isMutable ) + { + setName(name); + setDefaultValue(defaultValue); + setIsClassIdentifier(isClassIdentifier); + setIsMutable(isMutable); + } + + public void setName(String name) + { + mName = name; + } + + public void setIsClassIdentifier(boolean classId) + { + mIsClassIdentifier = classId; + } + + public void setDefaultValue(String defaultValue) + { + mDefaultValue = defaultValue; + } + + public void setIsMutable(boolean mutable) + { + mIsMutable = mutable; + } + + public String getName() + { + return mName; + } + + public boolean getIsClassIdentifier() + { + return mIsClassIdentifier; + } + + public String getDefaultValue() + { + return mDefaultValue; + } + + public boolean getIsMutable() + { + return mIsMutable; + } + + public Property getProperty() + { + return new Property(mName, mDefaultValue, mIsMutable); + } + +} diff --git a/src/main/java/org/cristalise/kernel/property/PropertyDescriptionList.java b/src/main/java/org/cristalise/kernel/property/PropertyDescriptionList.java new file mode 100644 index 0000000..98df773 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/property/PropertyDescriptionList.java @@ -0,0 +1,94 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.property; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.utils.CastorArrayList; + + +public class PropertyDescriptionList extends CastorArrayList +{ + public PropertyDescriptionList() + { + super(); + } + + public PropertyDescriptionList(ArrayList aList) + { + super(aList); + } + + public String getClassProps() { + StringBuffer props = new StringBuffer(); + for (PropertyDescription element : list) { + if (element.getIsClassIdentifier()) { + if (props.length()>0) + props.append(","); + props.append(element.getName()); + } + } + return props.toString(); + } + + public boolean setDefaultValue(String name, String value) { + for (PropertyDescription element : list) { + if (element.getName().equals(name)) { + element.setDefaultValue(value); + return true; + } + } + return false; + } + + public boolean definesProperty(String name) { + for (PropertyDescription element : list) { + if (element.getName().equals(name)) + return true; + } + return false; + } + + public PropertyArrayList instantiate(PropertyArrayList initProps) throws InvalidDataException { + // check that supplied init properties exist in desc list + HashMap validatedInitProps = new HashMap(); + for (Property initProp : initProps.list) { + if (!definesProperty(initProp.getName())) + throw new InvalidDataException("Property "+initProp.getName()+" has not been declared in the property descriptions"); + else + validatedInitProps.put(initProp.getName(), initProp.getValue()); + } + + PropertyArrayList propInst = new PropertyArrayList(); + for (int i = 0; i < list.size(); i++) { + PropertyDescription pd = list.get(i); + String propName = pd.getName(); + String propVal = pd.getDefaultValue(); + if (validatedInitProps.containsKey(propName)) + propVal = validatedInitProps.get(propName); + boolean isMutable = pd.getIsMutable(); + propInst.list.add( new Property(propName, propVal, isMutable)); + } + return propInst; + } +} diff --git a/src/main/java/org/cristalise/kernel/property/PropertyUtility.java b/src/main/java/org/cristalise/kernel/property/PropertyUtility.java new file mode 100644 index 0000000..39d399f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/property/PropertyUtility.java @@ -0,0 +1,96 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.property; + +import java.util.ArrayList; +import java.util.Iterator; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.Logger; + + + +public class PropertyUtility +{ + static public String getValue(ArrayList pdlist, String name) + { + for (PropertyDescription pd : pdlist) { + if ( name.equalsIgnoreCase(pd.getName()) ) + return pd.getDefaultValue(); + } + return null; + } + + static public String getNames(ArrayList pdlist) + { + StringBuffer names = new StringBuffer(); + for (PropertyDescription value : pdlist) + names.append( value.getDefaultValue()).append(" "); + return names.toString(); + } + + static public String getClassIdNames(ArrayList pdlist) + { + StringBuffer names = new StringBuffer(); + + for (Iterator iter = pdlist.iterator(); iter.hasNext();) { + PropertyDescription pd = iter.next(); + if (pd.getIsClassIdentifier()) + names.append(pd.getName()); + if (iter.hasNext()) + names.append(","); + } + return names.toString(); + } + + + static public PropertyDescriptionList getPropertyDescriptionOutcome(ItemPath itemPath, String descVer) throws ObjectNotFoundException + { + try + { + Outcome outc = (Outcome) Gateway.getStorage().get(itemPath, ClusterStorage.VIEWPOINT+"/PropertyDescription/"+descVer+"/data", null); + return (PropertyDescriptionList)Gateway.getMarshaller().unmarshall(outc.getData()); + } + catch (Exception ex) + { + Logger.error(ex); + throw new ObjectNotFoundException("Could not fetch PropertyDescription from "+itemPath); + } + } + + static public CastorHashMap createProperty(PropertyDescriptionList pdList) + { + CastorHashMap props = new CastorHashMap(); + for (int i=0; i< pdList.list.size();i++) + { + PropertyDescription pd = pdList.list.get(i); + if (pd.getIsClassIdentifier()) + props.put(pd.getName(),pd.getDefaultValue()); + } + return props; + } + +} diff --git a/src/main/java/org/cristalise/kernel/scripting/ErrorInfo.java b/src/main/java/org/cristalise/kernel/scripting/ErrorInfo.java new file mode 100644 index 0000000..3ea4200 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/ErrorInfo.java @@ -0,0 +1,75 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.scripting; + +import java.util.ArrayList; + +/************************************************************************** + * + * $Revision: 1.2 $ + * $Date: 2003/06/06 11:37:45 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ +public class ErrorInfo { + ArrayList msg; + boolean fatal = false; + + public ErrorInfo() { + super(); + msg = new ArrayList(); + } + + public ErrorInfo(String error) { + this(); + msg.add(error); + } + + public void addError(String error) { + msg.add(error); + } + + @Override + public String toString() { + StringBuffer err = new StringBuffer(); + for (String element : msg) { + err.append(element+"\n"); + } + return err.toString(); + } + + public void setErrors(ArrayList msg) { + this.msg = msg; + } + + public ArrayList getErrors() { + return msg; + } + + public void setFatal() { + fatal=true; + } + + public boolean getFatal() { + return fatal; + } +} diff --git a/src/main/java/org/cristalise/kernel/scripting/Parameter.java b/src/main/java/org/cristalise/kernel/scripting/Parameter.java new file mode 100644 index 0000000..6b5e29a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/Parameter.java @@ -0,0 +1,72 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.scripting; + + +/************************************************************************** +* Place holder for the Parameter details to be passed to the script. +**************************************************************************/ +public class Parameter { + + private String name; + private Class type; + private boolean initialised=false; + + public Parameter(String name) { + this.name = name; + } + + public Parameter(String name, Class type) { + this.name = name; + this.type = type; + } + + public void setName(String n) + { + name=n; + } + + public String getName() + { + return name; + } + + public void setType(Class t) + { + type=t; + } + + public Class getType() + { + return type; + } + + public void setInitialised(boolean state) + { + initialised=state; + } + + public boolean getInitialised() + { + return initialised; + } + +} diff --git a/src/main/java/org/cristalise/kernel/scripting/ParameterException.java b/src/main/java/org/cristalise/kernel/scripting/ParameterException.java new file mode 100644 index 0000000..8ecf806 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/ParameterException.java @@ -0,0 +1,40 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.scripting; + +public class ParameterException extends ScriptingEngineException { + + /** + * Creates new ParameterException without detail message. + */ + public ParameterException() { + } + + /** + * Constructs an ParameterException with the specified detail message. + * @param msg the detail message. + */ + public ParameterException(String msg) { + super(msg); + } +} + + diff --git a/src/main/java/org/cristalise/kernel/scripting/Script.java b/src/main/java/org/cristalise/kernel/scripting/Script.java new file mode 100644 index 0000000..9b0d402 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/Script.java @@ -0,0 +1,572 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.scripting; + +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; + +import javax.script.Bindings; +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.script.SimpleScriptContext; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.agent.Job; +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.LocalObjectLoader; +import org.cristalise.kernel.utils.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.xml.sax.InputSource; + + +/************************************************************************** + * + * $Revision: 1.25 $ + * $Date: 2005/10/05 07:39:37 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ +public class Script +{ + String mScript = ""; + CompiledScript mCompScript = null; + String mName; + Integer mVersion; + HashMap mInputParams = new HashMap(); + HashMap mAllInputParams = new HashMap(); + HashMap mOutputParams = new HashMap(); + ArrayList