|
| 1 | +@startuml |
| 2 | +title GDA Baton Management |
| 3 | + |
| 4 | +package Server { |
| 5 | + class Thread |
| 6 | + class JythonServerThread extends Thread { |
| 7 | + authorisationLevel: int |
| 8 | + int getAuthorisationLevel() |
| 9 | + } |
| 10 | + |
| 11 | + interface IBatonManager { |
| 12 | + ClientDetails getClientInformation((myJSFIdentifier) |
| 13 | + boolean requestBaton(uniqueIdentifier) |
| 14 | + void returnBaton((uniqueIdentifier) |
| 15 | + void assignBaton(myJSFIdentifier, indexOfReceiver, indexOfPasser) |
| 16 | + boolean isBatonHeld() |
| 17 | + boolean amIBatonHolder(myJSFIdentifier) |
| 18 | + int effectiveAuthorisationLevelOf(uniqueId) |
| 19 | + void addFacade(uniqueId, info: ClientDetails) |
| 20 | + void removeFacade(uniqueId) |
| 21 | + } |
| 22 | + |
| 23 | + class BatonManager implements IBatonManager { |
| 24 | + useBaton = true |
| 25 | + useRBAC = true |
| 26 | + firstClientTakesBaton = true |
| 27 | + batonHolder: String |
| 28 | + facadeNames: Map<String, ClientInfo> |
| 29 | + leaseHolders: Map<String, Long> |
| 30 | + } |
| 31 | + |
| 32 | + note "Each client has a facade name aka uniqueId aka jsfIdentifier\n\ |
| 33 | +There is a LeaseRefresher that periodically sends a BatonLeaseRenewRequest\n\ |
| 34 | +to all clients, any interaction with the BatonManager extends the lease.\n\n\ |
| 35 | +On first client registration, if firstClientTakesBaton is true then it will\n\ |
| 36 | +assume the baton if it is not the server or an automated client." as batonManagerNote |
| 37 | + |
| 38 | + BatonManager .. batonManagerNote |
| 39 | + |
| 40 | + |
| 41 | + interface IJythonServerNotifier { |
| 42 | + void notifyServer(source, data) |
| 43 | + } |
| 44 | + interface LocalJython |
| 45 | + class JythonServer implements LocalJython { |
| 46 | + batonManager: BatonManager |
| 47 | + } |
| 48 | + |
| 49 | + note "JythonServer registers a client with the BatonManager via forwarding of addFacade()\n\ |
| 50 | +The authorisationLevel is determined by asking the Authoriser" as jythonServerNote |
| 51 | + |
| 52 | + JythonServer .. jythonServerNote |
| 53 | + |
| 54 | + interface Authoriser { |
| 55 | + int getAuthorisationLevel(username) |
| 56 | + int getDefaultPermissions(username) |
| 57 | + isLocalStaff(username) |
| 58 | + } |
| 59 | + |
| 60 | + class FileAuthoriser implements Authoriser |
| 61 | + note "Gets the permissions from user_permissions.xml" as fileAuthoriserNote |
| 62 | + FileAuthoriser .. fileAuthoriserNote |
| 63 | + class LdapAuthoriser extends FileAuthoriser |
| 64 | + class SingleFileAuthoriser implements Authoriser |
| 65 | + note "Authorisation method is determined by gda.gui.AcquisitionGUI.authorisationMethod" as authoriserNote |
| 66 | + |
| 67 | + Authoriser .. authoriserNote |
| 68 | + |
| 69 | + together { |
| 70 | + class UDCBatonHandler { |
| 71 | + runner: IUDCRunner |
| 72 | + } |
| 73 | + interface IUDCRunner |
| 74 | + class GDAUDCRunner implements IUDCRunner |
| 75 | + class HyperionUDCRunner implements IUDCRunner |
| 76 | + } |
| 77 | + |
| 78 | + note "\ |
| 79 | +Creates the UDC Client by calling getUnattendedClientFacade() during configuration.\n\ |
| 80 | +Creates the UDC Runner according to the gda.mx.udc.hyperion.enable property.\ |
| 81 | +" as udcBatonHandlerNote |
| 82 | + UDCBatonHandler .. udcBatonHandlerNote |
| 83 | + |
| 84 | + class Device { |
| 85 | + protectionLevel: int |
| 86 | + } |
| 87 | + class DeviceInterceptor |
| 88 | + note "DeviceInterceptor is an interceptor on specific methods of Device, if the current thread\n\ |
| 89 | +has an authorisationLevel below the protectionLevel of the device, and\n\ |
| 90 | +the call is made from Jython the method call throws AccessDeniedException." as deviceNote |
| 91 | + Device .. deviceNote |
| 92 | + |
| 93 | + |
| 94 | + |
| 95 | + class UDCCompleteEvent |
| 96 | + |
| 97 | +} |
| 98 | + |
| 99 | +package Common { |
| 100 | + together { |
| 101 | + class BatonChanged |
| 102 | + class BatonRequested |
| 103 | + class BatonLeaseRenewRequest |
| 104 | + } |
| 105 | + |
| 106 | + interface Jython { |
| 107 | + boolean amIBatonHolder(myJSFIdentifier) |
| 108 | + int addFacade(jsfIdentifier, hostname, username, fullName, visitId) |
| 109 | + boolean isBatonHeld() |
| 110 | + } |
| 111 | + |
| 112 | + class ClientInfo { |
| 113 | + index: int |
| 114 | + userId: String |
| 115 | + fullName: String |
| 116 | + hostname: String |
| 117 | + authorisationLevel: int |
| 118 | + visitID: String |
| 119 | + |
| 120 | + boolean isServer() |
| 121 | + boolean isAutomatedUser() |
| 122 | + } |
| 123 | + note "isServer and isAutomatedUser are determined by the authorisationLevel" as clientInfoNote |
| 124 | + ClientInfo .. clientInfoNote |
| 125 | + |
| 126 | + class ClientDetails extends ClientInfo { |
| 127 | + hasBaton: boolean |
| 128 | + } |
| 129 | + |
| 130 | + interface IAuthorisationHolder { |
| 131 | + int getAuthorisationLevel() |
| 132 | + int getAuthorisationLevelAtRegistration() |
| 133 | + } |
| 134 | + |
| 135 | + interface IBatonStateProvider { |
| 136 | + boolean amIBatonHolder() |
| 137 | + boolean isBatonHeld() |
| 138 | + void addBatonChangedObserver(observer) |
| 139 | + void deleteBatonChangedObserver(observer) |
| 140 | + } |
| 141 | + note "Access is enforced in the client via calls to amIBatonHolder()" as iBatonStateProviderNote |
| 142 | + |
| 143 | + class JythonServerFacade implements IBatonStateProvider, IAuthorisationHolder { |
| 144 | + commandServer: Jython |
| 145 | + visitID: String |
| 146 | + {static} JythonServerFacade getUnattendedClientFacade() |
| 147 | + } |
| 148 | +} |
| 149 | + |
| 150 | +package Client { |
| 151 | + class ApplicationWorkbenchAdvisor |
| 152 | + note "ApplicationWorkbenchAdvisor receives the BatonLeaseRenewRequest and uses IBatonStateProvider\n\ |
| 153 | +to renew the lease by calling amIBatonHolder()" as applicationWorkbenchAdvisorNote |
| 154 | +} |
| 155 | + |
| 156 | +'Server -up-> Common |
| 157 | +'Common -up[hidden]-> Client |
| 158 | +ApplicationWorkbenchAdvisor ..[norank] applicationWorkbenchAdvisorNote |
| 159 | + |
| 160 | +ApplicationWorkbenchAdvisor --down> IBatonStateProvider |
| 161 | + |
| 162 | +IBatonStateProvider .. iBatonStateProviderNote |
| 163 | +LocalJython -up-|> Jython |
| 164 | +LocalJython --|> IJythonServerNotifier |
| 165 | + |
| 166 | +JythonServerFacade o-> Jython |
| 167 | +JythonServer o->BatonManager |
| 168 | +JythonServer --> Authoriser |
| 169 | + |
| 170 | +JythonServer --> JythonServerThread |
| 171 | + |
| 172 | +BatonChanged --> UDCBatonHandler : handles |
| 173 | +BatonRequested --> UDCBatonHandler : handles |
| 174 | +UDCCompleteEvent --> UDCBatonHandler : handles |
| 175 | + |
| 176 | +UDCBatonHandler -[norank]-> JythonServerFacade |
| 177 | +UDCBatonHandler o-> IUDCRunner |
| 178 | +BatonManager -up-> BatonChanged : fires |
| 179 | +BatonManager -up-> BatonRequested : fires |
| 180 | +BatonManager -up-> BatonLeaseRenewRequest : fires |
| 181 | +GDAUDCRunner -[norank]-> UDCCompleteEvent : fires |
| 182 | +BatonManager *-[norank]-> ClientInfo |
| 183 | + |
| 184 | +UDCCompleteEvent --> GDAUDCRunner : handles |
| 185 | +HyperionUDCRunner --> UDCCompleteEvent : fires |
| 186 | + |
| 187 | +DeviceInterceptor --> Device |
| 188 | +DeviceInterceptor --> JythonServerThread |
| 189 | + |
| 190 | +BatonManager -up-> IJythonServerNotifier |
| 191 | + |
| 192 | +@enduml |
0 commit comments