using concurrent::AtomicBoolusing concurrent::AtomicRefusing afIoc::Registryusing afIoc::RegistryBuilderusing wisp::MemWispSessionStoreusing wisp::WispSessionStoreusing afBedSheet::BedSheetModuleusing afBedSheet::BedSheetMetaDatausing afBedSheet::BedSheetWebModusing afButter::Butterusing afButter::HttpTerminator** Initialises a Bed App without the overhead of starting the 'wisp' web server. ** ** 'BedServer' is a 'const' class so it may be used in multiple threads. Do this to create 'BedClients' in different** threads to make concurrent calls - handy for load testing.** constclass BedServer {privateconststatic Log log := Utils.getLog(BedServer#)privateconst AtomicRef reg := AtomicRef()privateconst AtomicBool started := AtomicBool()privateconst AtomicRef modules := AtomicRef(Type#.emptyList)privateconst AtomicRef moduleDeps := AtomicRef(Pod#.emptyList)privateconst AtomicRef bsMeta := AtomicRef()** The 'afIoc' registry - read only. Registry registry { get { checkHasStarted; return reg.val }private set { reg.val = it}}** Create a instance of 'afBedSheet' with the given afIoc module (usually your web app)new makeWithModule(Type? iocModule := null){ addModulesFromDependencies(BedSheetModule#.pod)if(iocModule != null) addModule(iocModule) bsMeta.val = BedSheetMetaDataImpl(iocModule?.pod, iocModule, [:])}** Create a instance of 'afBedSheet' with afIoc dependencies from the given pod (usually your web app)new makeWithPod(Pod webApp){ addModulesFromDependencies(webApp) addModule(BedSheetModule#) mod := BedSheetWebMod.findModFromPod(webApp) bsMeta.val = BedSheetMetaDataImpl(webApp, mod, [:])}** Add extra (test) modules should you wish to override behaviour in your tests BedServer addModule(Type iocModule){ checkHasNotStarted mods := (Type[]) modules.val modules.val = mods.rw.add(iocModule).toImmutablereturnthis} BedServer addModulesFromDependencies(Pod dependency){ checkHasNotStarted deps := (Pod[]) moduleDeps.val moduleDeps.val = deps.rw.add(dependency).toImmutablereturnthis}** Startup 'afBedSheet' BedServer startup(){ checkHasNotStarted bannerText := "Alien-Factory BedServer v${typeof.pod.version}, IoC v${Registry#.pod.version}" bob := RegistryBuilder()((Pod[]) moduleDeps.val).each |pod| { bob.addModulesFromDependencies(pod)} mods := (Type[]) modules.val bob.addModules(mods) bedSheetMetaData := bsMeta.val registry = bob.build(["bannerText" : bannerText, "bedSheetMetaData" : bedSheetMetaData, "suppressStartupServiceList" : true,"appName" : "BedServer"]).startup started.val = truereturnthis}** Shutdown 'afBedSheet' BedServer shutdown(){if(started.val) registry.shutdown reg.val = null started.val = false modules.val = Type#.emptyListreturnthis}** Creates a pack of 'Butter' whose middleware ends with a BedTerminator which makes requests to the Bed app. BedClient makeClient(){ checkHasStartedreturn BedClient(Butter.churnOut( Butter.defaultStack .exclude {it.typeof == HttpTerminator# } .add(BedTerminator(this)) .insert(0, SizzleMiddleware())))}// ---- Registry Methods ----** Helper method - tap into BedSheet's afIoc registry Obj serviceById(Str serviceId){ checkHasStartedreturn registry.serviceById(serviceId)}** Helper method - tap into BedSheet's afIoc registry Obj dependencyByType(Type dependencyType){ checkHasStartedreturn registry.dependencyByType(dependencyType)}** Helper method - tap into BedSheet's afIoc registry Obj autobuild(Type type, Obj?[] ctorArgs := Obj#.emptyList){ checkHasStartedreturn registry.autobuild(type, ctorArgs)}** Helper method - tap into BedSheet's afIoc registry Obj injectIntoFields(Obj service){ checkHasStartedreturn registry.injectIntoFields(service)}// ---- helper methods ----** as called by BedClients - if no reg then we must have been shutdowninternal Void checkHasNotShutdown(){if(reg.val == null)throw Err("${BedServer#.name} has been shutdown!")}private Void checkHasStarted(){if(!started.val)throw Err("${BedServer#.name} has not yet started!")}private Void checkHasNotStarted(){if(started.val)throw Err("${BedServer#.name} has not already been started!")}}internalconstclass BedSheetMetaDataImpl : BedSheetMetaData {overrideconst Pod? appPodoverrideconst Type? appModuleoverrideconst Int portoverrideconst[Str:Obj] optionsinternalnew make(Pod? appPod, Type? appModule, [Str:Obj] options){this.appPod = appPodthis.appModule = appModulethis.port = 0 // we're not really listening!this.options = options.toImmutable}}