WARegistry


Seaside-RequestHandler

Comment:



Hierarchy:

ProtoObject
Object
WARequestHandler
WAEntryPoint
WARegistry

Summary:

instance variables:

handlersByKey keysByHandler mutex

methods:

instance class
private public as yet unclassified

Detail:

instance variables:

handlersByKey
InitialValue:
a Dictionary()
inferredType:
Dictionary
keysByHandler
InitialValue:
a Dictionary()
inferredType:
Dictionary
mutex
InitialValue:
a Semaphore()
inferredType:
Semaphore

instance methods:

private
clearHandlers

	self mutex critical:
		[handlersByKey _ Dictionary new.
		keysByHandler _ Dictionary new].
handleDefaultRequest: aRequest

	self subclassResponsibility
handleExpiredRequest: aRequest

	| url |
	url _ WAUrl new.
	url addToPath: aRequest url.
	aRequest isGet ifTrue:
		[aRequest fields keysAndValuesDo:
			[:k :v |
			(self isSeasideField: k) ifFalse: [url addParameter: k value: v]]]. 
	
	^ WAResponse
		refreshWithMessage: 'That page has expired.'
		location: url asString
		delay: 3
handleKeyRequest: aRequest

	|key handler|
	key _ [WAExternalID fromString: (aRequest at: self handlerField)] on: Error do: [:e | nil].
	handler _ handlersByKey at: key ifAbsent: [nil].
	^ (handler notNil and: [handler isActive])
		ifTrue: [handler handleRequest: aRequest]
		ifFalse: [self handleExpiredRequest: aRequest]
handlerField

	^ '_s'
initialize

	self clearHandlers.
isSeasideField: aString

	^ aString first  = $_
keyOrNilForHandler: anObject

	^ self mutex critical: [keysByHandler at: anObject ifAbsent: [nil]]
mutex

	^ mutex ifNil: [mutex _ Semaphore forMutualExclusion]
registerRequestHandler: anObject

	|key|
	key _ WAExternalID new: 16.
	self shouldCollectHandlers ifTrue: [self unregisterExpiredHandlers].
	self mutex critical:
		[handlersByKey at: key put: anObject.
		keysByHandler at: anObject put: key].
	^ key
shouldCollectHandlers

	^ 10 atRandom = 1
unregisterExpiredHandlers

	"This method is a little ugly, but using #associationsDo: to build a new
	dictionary is 200 times faster than iterating over them with #removeKey:
	or even using #keysAndValuesRemove:"

	| expired newHandlersByKey newKeysByHandler |
	self mutex critical:
		[expired _ OrderedCollection new.
		newHandlersByKey _ Dictionary new.
		handlersByKey associationsDo:
			[:assoc |
			assoc value isActive
				ifTrue: [newHandlersByKey add: assoc]
				ifFalse: [expired add: assoc value]].
		newKeysByHandler _ Dictionary new.
		keysByHandler associationsDo: [:assoc | assoc key isActive ifTrue: [newKeysByHandler add: assoc]].
		handlersByKey _ newHandlersByKey.
		keysByHandler _ newKeysByHandler].
	
	"Send #unregistered to each in expired"
	expired do: [:ea | [ea unregistered] fork]

public
handleRequest: aRequest

	^ (aRequest fields includesKey: self handlerField)
		ifTrue: [self handleKeyRequest: aRequest]
		ifFalse: [self handleDefaultRequest: aRequest]
urlForRequestHandler: anObject

	|key url |
	key _ (self keyOrNilForHandler: anObject) ifNil: [self registerRequestHandler: anObject].
	url _ self baseUrl.
	url addParameter: self handlerField value: key asString.
	^ url

class methods:

as yet unclassified
clearAllHandlers

	self allSubInstances do: [:ea | ea clearHandlers]
new

	^ super new initialize

^top


- made by Dandelion -