diff options
Diffstat (limited to 'lib/App/Acmeman/Apache/Layout.pm')
-rw-r--r-- | lib/App/Acmeman/Apache/Layout.pm | 186 |
1 files changed, 111 insertions, 75 deletions
diff --git a/lib/App/Acmeman/Apache/Layout.pm b/lib/App/Acmeman/Apache/Layout.pm index 7cc8399..39e40d5 100644 --- a/lib/App/Acmeman/Apache/Layout.pm +++ b/lib/App/Acmeman/Apache/Layout.pm @@ -4,112 +4,148 @@ use strict; use warnings; use Carp; use File::Basename; +use feature 'state'; +use App::Acmeman::Log qw(:all); -require Exporter; -our @ISA = qw(Exporter); - -my %apache_layout_tab = ( - slackware => { - _test => sub { -d '/etc/httpd/extra' }, - _config_file => '/etc/httpd/httpd.conf', - _incdir => '/etc/httpd/extra', - _restart => '/etc/rc.d/rc.httpd restart' - }, - debian => { - _config_file => '/etc/apache2/apache2.conf', - _incdir => sub { - for my $dir ('/etc/apache2/conf-available', - '/etc/apache2/conf.d') { - return $dir if -d $dir; - } - carp 'none of the expected configuration directories found; falling back to /etc/apache2'; - return '/etc/apache2'; - }, - _restart => '/usr/sbin/service apache2 restart', - _post_setup => sub { - my ($filename) = @_; - my $dir = dirname($filename); - my $name = basename($filename); - if ($dir eq '/etc/apache2/conf-available') { - chdir('/etc/apache2/conf-enabled'); - symlink "../conf-available/$name", $name; +sub _find_httpd { + my $httpd; + foreach my $d (split /:/, $ENV{PATH}) { + foreach my $n (glob "$d/apachectl $d/httpd") { + if (-x $n) { + return $n; } } - }, - rh => { - _config_file => '/etc/httpd/conf/httpd.conf', - _incdir => '/etc/httpd/conf.d', - _restart => '/usr/sbin/service httpd restart' - }, - suse => { - _config_file => '/etc/apache2/httpd.conf', - _test => sub { ! -f '/etc/apache2/apache2.conf' }, - _incdir => '/etc/apache2/conf.d', - _restart => '/usr/sbin/service httpd restart' - # or systemctl restart apache2.service } -); +} + +sub modules { + my $class = shift; + my @path = split /::/, $class; + + state $loaders //= + [map { $_->[1] } + sort { $a->[0] <=> $b->[0] } + map { + my ($modname) = $class . '::' . fileparse($_, '.pm'); + eval { + no strict 'refs'; + if (scalar %{ $modname.'::' }) { + die "INCLUDED $modname"; + }; + require $_; + my $prio = ${$modname.'::PRIORITY'} // 0; + [ $prio, $modname ] + }; + } + map { glob File::Spec->catfile($_, '*.pm') } + grep { -d $_ } + map { File::Spec->catfile($_, @path) } @INC]; + @$loaders; +} # new(NAME) # new() sub new { my $class = shift; - my $self = bless { }, $class; - my $name; if (@_ == 0) { - # Autodetect - while (my ($n, $layout) = each %apache_layout_tab) { - if (-f $layout->{_config_file}) { - if (exists($layout->{_test}) && !&{$layout->{_test}}) { - next; - } - $name = $n; - last; + # Autodetect + my $ap = new Apache::Defaults(server => $class->_find_httpd, + on_error => 'return'); + if ($ap->status) { + croak "unable to get Apache defaults: " . $ap->error; + } + + foreach my $mod ($class->modules) { + my $obj; + eval { + $obj = $mod->new($ap); + }; + if ($obj) { + return $obj; } +# print "A $mod: $@\n"; + } + + if ($ap) { + return new App::Acmeman::Apache::Layout::auto($ap); } - croak "unrecognized Apache layout" unless defined $name; - } elsif (@_ == 1) { - $name = shift; + + croak "unrecognized Apache layout"; } - - if (exists($apache_layout_tab{$name})) { - @{$self}{keys %{$apache_layout_tab{$name}}} = - values %{$apache_layout_tab{$name}}; - } else { - croak "undefined Apache layout $name"; + + my ($name, %args) = @_; + if (ref($name) eq '') { + my $mod = "$class::$name"; + my $obj; + eval { + require $mod; + }; + croak "undefined Apache layout $name" if ($@); + return $mod->new; + } + + unless ($name->isa('Apache::Defaults')) { + croak "unrecognized argument"; + } + + my $self = bless { _defaults => $name }, $class; + foreach my $kw (qw(layout_name incdir restart_command)) { + if (defined(my $v = delete $args{$kw})) { + $self->{$kw} = $v; + } } - $self->{_layout_name} = $name; - return $self; -} +} + +sub apache { shift->{_defaults} } sub name { my $self = shift; - return $self->{_layout_name}; + unless ($self->{layout_name}) { + $self->{layout_name} = ref($self); + $self->{layout_name} =~ s/.*:://; + $self->{layout_name} =~ s/\.pm$//; + } + return $self->{layout_name}; } -sub config_file { +sub config_file { shift->apache->server_config } + +sub incdir { my $self = shift; - return $self->{_config_file}; + unless ($self->{incdir}) { + $self->{incdir} = dirname($self->config_file); + } + return $self->{incdir}; } +sub server_command { join(' ', shift->apache->server_command) } + sub restart_command { my $self = shift; - return $self->{_restart}; -} -sub incdir { - my $self = shift; - if (exists($self->{_incdir})) { - if (ref($self->{_incdir}) eq 'CODE') { - return &{$self->{_incdir}}; + unless (exists($self->{restart_command})) { + if ($self->server_command =~ m{/apachectl$}) { + $self->{restart_command} = $self->server_command . ' restart'; } else { - return $self->{_incdir}; + error("no postrenew command defined", prefix => 'warning'); + $self->{restart_command} = undef } } - return dirname($self->{_config_file}); + return $self->{restart_command}; +} + +sub post_setup {} + +package App::Acmeman::Apache::Layout::auto; +use parent 'App::Acmeman::Apache::Layout'; +use App::Acmeman::Log qw(:all); + +sub new { + my ($class, $ap) = @_; + return $class->SUPER::new($ap); } 1; |