Wie der CosmoShop mit generischen
Hookpoints in Perl-Objekten „umspringt“
How the CosmoShop handles
generic Hook Points in Perl Objects
Product
Development
• new features
• security updates
• most recent third party packages
• adapted frame conditions (EU regulations)
• more modern source code
• state-of-the-art design
Timeline
of
The
Windows
Versions
Reservations
About
Updates
• technical risk: never change a running system
• usability improvements: changed interfaces cause confusion
• new mechanics: changed workflows to get used to
• state-of-the-art design: looks "different"
•incompatible custom changes
Outsource
to
Plugins
• modularity by hooks
• compatibility for many release versions
• reusability for multiple installations
Custom Changes in Plugins
Classic
Manual
Hook
Points
dedicated hook points at the beginning
and end of a function
sub myFunction {
&hook_before_myFunction(@_);
my $result = […]
&hook_after_myFunction($result, @_);
}
BUT:
Can you hook into
a function call
dynamically?
$AUTOLOAD
1st
Try
package MyObject;
our $AUTOLOAD;
sub AUTOLOAD {
return &myFunction() + 2;
}
sub myFunction {
return 1;
}
print &myFunction(); ## result: 1
AUTOLOAD won't
be executed as the
called function
already exists
2nd
Try
package MyObject;
our $AUTOLOAD;
sub AUTOLOAD {
my $function = $AUTOLOAD;
$function =~ s/^(.*)::(.+?)$/$2/sg;
my $hookableFunction = 'hookable_'.$function;
return &$hookableFunction() + 2;
}
sub hookable_myFunction {
return 1;
}
print &myFunction(); ## result: 3
AUTOLOAD is executed
as the current function
doesn't exist!
BUT:
unpleasant prefix
in the function name
Object
to
Hook
package My::Object;
sub myFunction {
my $self = shift;
return $self->myOtherFunction();
}
sub myOtherFunction {
[…]
}
1;
Our
Solution:
Twins
!
dummy object in original namespace actual object in the twin namespace Core
package My::Object;
use base My::HookBase;
1;
package My::Core::Object;
use base My::BaseObject;
sub myFunction {
my $self = shift;
return $self->{hookclass}->myOtherFunction();
}
sub myOtherFunction {
[…]
}
1;
here
comes
the
Hip-Hop
$myObject->myFunction()
My::Core::Object
sub myFunction {
my $self = shift;
return $self->{hookclass}-
>myOtherFunction();
}
sub myOtherFunction {
[…]
}
My::Object
AUTOLOAD Dummy
$Hooks->addCoreHook({
coreObject => 'My::Object',
coreFunction => 'myFunction',
runlevel => 100,
hookFunction => sub {
my $self = shift;
my $hookQueue = shift;
my @param = @_;
## code before: can manipulate @param
my $result = $self->nextHook($hookQueue, @param);
## code afterwards: can manipulate $result
return $result;
}
});
in
the
plugin:
sub addCoreHook {
my $self = shift;
my $param = shift;
my $coreObject = $param->{coreObject};
my $coreFunction = $param->{coreFunction};
push @{$self->{coreHooks}->{$coreObject}->{$coreFunction}}, {
hookFunction => $param->{hookFunction},
runlevel => $param->{runlevel},
};
}
sub getCoreHooks {
my $self = shift;
my $coreObject = shift;
my $coreFunction = shift;
return {
hookFunctions => $self->sortByRunlevel($self->{coreHooks}->{$coreObject}->{$coreFunction}),
coreFunction => $coreFunction,
};
}
in
Hooks.pm
package My::HookBase;
sub new {
my $class = shift;
my $params = shift;
my $self = {};
bless ($self, $class);
my $coreClass = $class;
$coreClass =~ s/^My::/My::Core::/sg;
my $corePath = $coreClass;
$corePath =~ s/::///sg;
require $corePath.'.pm';
$params->{hookclass} = $self;
$self->{corebase} = $coreClass->new($params);
return $self;
}
our $AUTOLOAD;
sub AUTOLOAD {
my $self = shift;
my $function = $AUTOLOAD;
$function =~ s/^(.*)::(.+?)$/$2/sg;
my $package = $1;
return $self->parseHooks($package, $function, @_);
}
in
the
dummy
object:
sub parseHooks {
my $self = shift;
my $package = shift;
my $function = shift;
my @param = @_;
my $hookQueue = $self->getCoreHooks($package, $function);
return $self->nextHook($hookQueue, @param);
}
sub nextHook {
my $self = shift;
my $hookQueue = shift;
my @params = @_;
my $hookFunctions = $hookQueue->{hookFunctions}; ## sorted list of hooks
if (my $thisHook = shift @$hookFunctions) { ## one hook after another
my $hookFunction = $thisHook->{hookFunction};
return &$hookFunction($self, $hookQueue, @param); ## run the hook function
} else {
my $coreFunction = $hookQueue->{coreFunction}; ## function to hook
return $self->{corebase}->$coreFunction(@param); ## run the base function
}
}
in the plugin:
$Hooks->addCoreHook({
coreObject => 'My::Object',
coreFunction => 'myFunction',
runlevel => 100,
hookFunction => sub {
my $self = shift;
my $hookQueue = shift;
my @param = @_;
## code before: can manipulate @param
my $result = $self->nextHook($hookQueue, @param);
## code afterwards: can manipulate $result
return $result;
}
});
in
the
dummy
object:
How do we get the
hook system in existing
software installations?
With patience !
The hook system has already
been implemented in the year
2014
and all current CosmoShop
installations
have it ready to use

Hip-Hop-Hooks_english_v2_16-04-2024.pptx

  • 1.
    Wie der CosmoShopmit generischen Hookpoints in Perl-Objekten „umspringt“ How the CosmoShop handles generic Hook Points in Perl Objects
  • 2.
    Product Development • new features •security updates • most recent third party packages • adapted frame conditions (EU regulations) • more modern source code • state-of-the-art design
  • 3.
  • 4.
    Reservations About Updates • technical risk:never change a running system • usability improvements: changed interfaces cause confusion • new mechanics: changed workflows to get used to • state-of-the-art design: looks "different" •incompatible custom changes
  • 5.
    Outsource to Plugins • modularity byhooks • compatibility for many release versions • reusability for multiple installations Custom Changes in Plugins
  • 6.
    Classic Manual Hook Points dedicated hook pointsat the beginning and end of a function sub myFunction { &hook_before_myFunction(@_); my $result = […] &hook_after_myFunction($result, @_); }
  • 7.
    BUT: Can you hookinto a function call dynamically?
  • 8.
  • 9.
    1st Try package MyObject; our $AUTOLOAD; subAUTOLOAD { return &myFunction() + 2; } sub myFunction { return 1; } print &myFunction(); ## result: 1 AUTOLOAD won't be executed as the called function already exists
  • 10.
    2nd Try package MyObject; our $AUTOLOAD; subAUTOLOAD { my $function = $AUTOLOAD; $function =~ s/^(.*)::(.+?)$/$2/sg; my $hookableFunction = 'hookable_'.$function; return &$hookableFunction() + 2; } sub hookable_myFunction { return 1; } print &myFunction(); ## result: 3 AUTOLOAD is executed as the current function doesn't exist! BUT: unpleasant prefix in the function name
  • 11.
    Object to Hook package My::Object; sub myFunction{ my $self = shift; return $self->myOtherFunction(); } sub myOtherFunction { […] } 1;
  • 12.
    Our Solution: Twins ! dummy object inoriginal namespace actual object in the twin namespace Core package My::Object; use base My::HookBase; 1; package My::Core::Object; use base My::BaseObject; sub myFunction { my $self = shift; return $self->{hookclass}->myOtherFunction(); } sub myOtherFunction { […] } 1;
  • 13.
    here comes the Hip-Hop $myObject->myFunction() My::Core::Object sub myFunction { my$self = shift; return $self->{hookclass}- >myOtherFunction(); } sub myOtherFunction { […] } My::Object AUTOLOAD Dummy
  • 14.
    $Hooks->addCoreHook({ coreObject => 'My::Object', coreFunction=> 'myFunction', runlevel => 100, hookFunction => sub { my $self = shift; my $hookQueue = shift; my @param = @_; ## code before: can manipulate @param my $result = $self->nextHook($hookQueue, @param); ## code afterwards: can manipulate $result return $result; } }); in the plugin:
  • 15.
    sub addCoreHook { my$self = shift; my $param = shift; my $coreObject = $param->{coreObject}; my $coreFunction = $param->{coreFunction}; push @{$self->{coreHooks}->{$coreObject}->{$coreFunction}}, { hookFunction => $param->{hookFunction}, runlevel => $param->{runlevel}, }; } sub getCoreHooks { my $self = shift; my $coreObject = shift; my $coreFunction = shift; return { hookFunctions => $self->sortByRunlevel($self->{coreHooks}->{$coreObject}->{$coreFunction}), coreFunction => $coreFunction, }; } in Hooks.pm
  • 16.
    package My::HookBase; sub new{ my $class = shift; my $params = shift; my $self = {}; bless ($self, $class); my $coreClass = $class; $coreClass =~ s/^My::/My::Core::/sg; my $corePath = $coreClass; $corePath =~ s/::///sg; require $corePath.'.pm'; $params->{hookclass} = $self; $self->{corebase} = $coreClass->new($params); return $self; } our $AUTOLOAD; sub AUTOLOAD { my $self = shift; my $function = $AUTOLOAD; $function =~ s/^(.*)::(.+?)$/$2/sg; my $package = $1; return $self->parseHooks($package, $function, @_); } in the dummy object:
  • 17.
    sub parseHooks { my$self = shift; my $package = shift; my $function = shift; my @param = @_; my $hookQueue = $self->getCoreHooks($package, $function); return $self->nextHook($hookQueue, @param); } sub nextHook { my $self = shift; my $hookQueue = shift; my @params = @_; my $hookFunctions = $hookQueue->{hookFunctions}; ## sorted list of hooks if (my $thisHook = shift @$hookFunctions) { ## one hook after another my $hookFunction = $thisHook->{hookFunction}; return &$hookFunction($self, $hookQueue, @param); ## run the hook function } else { my $coreFunction = $hookQueue->{coreFunction}; ## function to hook return $self->{corebase}->$coreFunction(@param); ## run the base function } } in the plugin: $Hooks->addCoreHook({ coreObject => 'My::Object', coreFunction => 'myFunction', runlevel => 100, hookFunction => sub { my $self = shift; my $hookQueue = shift; my @param = @_; ## code before: can manipulate @param my $result = $self->nextHook($hookQueue, @param); ## code afterwards: can manipulate $result return $result; } }); in the dummy object:
  • 18.
    How do weget the hook system in existing software installations?
  • 19.
    With patience ! Thehook system has already been implemented in the year 2014 and all current CosmoShop installations have it ready to use