#!/usr/bin/perl -w
package Apache::Sling;
use 5.008001;
use strict;
use warnings;
use Carp;
use Apache::Sling::Authn;
use Apache::Sling::Authz;
use Apache::Sling::Content;
use Apache::Sling::Group;
use Apache::Sling::JsonQueryServlet;
use Apache::Sling::LDAPSynch;
use Apache::Sling::User;
require Exporter;
use base qw(Exporter);
our @EXPORT_OK = ();
our $VERSION = '0.17';
#{{{sub new
sub new {
my ( $class, $max_allowed_forks ) = @_;
# control the maximum number of forks that can be
# created when testing concurrency:
$max_allowed_forks =
( defined $max_allowed_forks ? $max_allowed_forks : 32 );
my $auth;
my $help;
my $log;
my $man;
my $number_forks = 1;
my $password;
my $url;
my $user;
my $verbose;
my $sling = {
MaxForks => $max_allowed_forks,
Auth => $auth,
Help => $help,
Log => $log,
Man => $man,
Pass => $password,
Threads => $number_forks,
URL => $url,
User => $user,
Verbose => $verbose
};
bless $sling, $class;
return $sling;
}
#}}}
#{{{sub check_forks
sub check_forks {
my ($sling) = @_;
$sling->{'Threads'} = ( $sling->{'Threads'} || 1 );
$sling->{'Threads'} =
( $sling->{'Threads'} =~ /^[0-9]+$/xms ? $sling->{'Threads'} : 1 );
$sling->{'Threads'} =
( $sling->{'Threads'} < $sling->{'MaxForks'} ? $sling->{'Threads'} : 1 );
return 1;
}
#}}}
#{{{sub authz_config
sub authz_config {
my ($sling) = @_;
my $delete;
my $principal;
my $remote_node;
my $view;
# privileges:
my $add_child_nodes;
my $all;
my $life_cycle_manage;
my $lock_manage;
my $modify_acl;
my $modify_props;
my $node_type_manage;
my $read;
my $read_acl;
my $remove_childs;
my $remove_node;
my $retention_manage;
my $version_manage;
my $write;
my %authz_config = (
'auth' => \$sling->{'Auth'},
'help' => \$sling->{'Help'},
'log' => \$sling->{'Log'},
'man' => \$sling->{'Man'},
'pass' => \$sling->{'Pass'},
'threads' => \$sling->{'Threads'},
'url' => \$sling->{'URL'},
'user' => \$sling->{'User'},
'verbose' => \$sling->{'Verbose'},
'addChildNodes' => \$add_child_nodes,
'all' => \$all,
'delete' => \$delete,
'lifecycleManage' => \$life_cycle_manage,
'lockManage' => \$lock_manage,
'modifyACL' => \$modify_acl,
'modifyProps' => \$modify_props,
'nodeTypeManage' => \$node_type_manage,
'principal' => \$principal,
'readACL' => \$read_acl,
'read' => \$read,
'remote' => \$remote_node,
'removeChilds' => \$remove_childs,
'removeNode' => \$remove_node,
'retentionManage' => \$retention_manage,
'versionManage' => \$version_manage,
'view' => \$view,
'write' => \$write
);
return \%authz_config;
}
#}}}
#{{{sub authz_run
sub authz_run {
my ( $sling, $config ) = @_;
if ( !defined $config ) {
croak 'No authz config supplied!';
}
$sling->check_forks;
${ $config->{'remote'} } =
Apache::Sling::URL::strip_leading_slash( ${ $config->{'remote'} } );
my $authn = new Apache::Sling::Authn( \$sling );
my $authz =
new Apache::Sling::Authz( \$authn, $sling->{'Verbose'}, $sling->{'Log'} );
if ( defined ${ $config->{'delete'} } ) {
$authz->delete( ${ $config->{'remote'} }, ${ $config->{'principal'} } );
Apache::Sling::Print::print_result($authz);
}
my @grant_privileges;
my @deny_privileges;
if ( defined ${ $config->{'read'} } ) {
${ $config->{'read'} }
? push @grant_privileges, 'read'
: push @deny_privileges, 'read';
}
if ( defined ${ $config->{'modifyProps'} } ) {
${ $config->{'modifyProps'} }
? push @grant_privileges, 'modifyProperties'
: push @deny_privileges, 'modifyProperties';
}
if ( defined ${ $config->{'addChildNodes'} } ) {
${ $config->{'addChildNodes'} }
? push @grant_privileges, 'addChildNodes'
: push @deny_privileges, 'addChildNodes';
}
if ( defined ${ $config->{'removeNode'} } ) {
${ $config->{'removeNode'} }
? push @grant_privileges, 'removeNode'
: push @deny_privileges, 'removeNode';
}
if ( defined ${ $config->{'removeChilds'} } ) {
${ $config->{'removeChilds'} }
? push @grant_privileges, 'removeChildNodes'
: push @deny_privileges, 'removeChildNodes';
}
if ( defined ${ $config->{'write'} } ) {
${ $config->{'write'} }
? push @grant_privileges, 'write'
: push @deny_privileges, 'write';
}
if ( defined ${ $config->{'readACL'} } ) {
${ $config->{'readACL'} }
? push @grant_privileges, 'readAccessControl'
: push @deny_privileges, 'readAccessControl';
}
if ( defined ${ $config->{'modifyACL'} } ) {
${ $config->{'modifyACL'} }
? push @grant_privileges, 'modifyAccessControl'
: push @deny_privileges, 'modifyAccessControl';
}
# Privileges that may become available in due course:
# if ( defined $lock_manage ) {
# $lock_manage ? push ( @grant_privileges, 'lockManagement' ) : push ( @deny_privileges, 'lockManagement' );
# }
# if ( defined $version_manage ) {
# $version_manage ? push ( @grant_privileges, 'versionManagement' ) : push ( @deny_privileges, 'versionManagement' );
# }
# if ( defined $node_type_manage ) {
# $node_type_manage ? push ( @grant_privileges, 'nodeTypeManagement' ) : push ( @deny_privileges, 'nodeTypeManagement' );
# }
# if ( defined $retention_manage ) {
# $retention_manage ? push ( @grant_privileges, 'retentionManagement' ) : push ( @deny_privileges, 'retentionManagement' );
# }
# if ( defined $life_cycle_manage ) {
# $life_cycle_manage ? push ( @grant_privileges, 'lifecycleManagement' ) : push ( @deny_privileges, 'lifecycleManagement' );
# }
if ( defined ${ $config->{'all'} } ) {
${ $config->{'all'} }
? push @grant_privileges, 'all'
: push @deny_privileges, 'all';
}
if ( @grant_privileges || @deny_privileges ) {
$authz->modify_privileges(
${ $config->{'remote'} }, ${ $config->{'principal'} },
\@grant_privileges, \@deny_privileges
);
Apache::Sling::Print::print_result($authz);
}
if ( defined ${ $config->{'view'} } ) {
$authz->get_acl( ${ $config->{'remote'} } );
Apache::Sling::Print::print_result($authz);
}
return 1;
}
#}}}
#{{{sub content_config
sub content_config {
my ($sling) = @_;
my $add;
my $additions;
my $copy;
my $delete;
my $exists;
my $filename;
my $local;
my $move;
my @property;
my $remote;
my $remote_source;
my $replace;
my $view;
my %content_config = (
'auth' => \$sling->{'Auth'},
'help' => \$sling->{'Help'},
'log' => \$sling->{'Log'},
'man' => \$sling->{'Man'},
'pass' => \$sling->{'Pass'},
'threads' => \$sling->{'Threads'},
'url' => \$sling->{'URL'},
'user' => \$sling->{'User'},
'verbose' => \$sling->{'Verbose'},
'add' => \$add,
'additions' => \$additions,
'copy' => \$copy,
'delete' => \$delete,
'exists' => \$exists,
'filename' => \$filename,
'local' => \$local,
'move' => \$move,
'property' => \@property,
'remote' => \$remote,
'remote-source' => \$remote_source,
'replace' => \$replace,
'view' => \$view
);
return \%content_config;
}
#}}}
#{{{sub content_run
sub content_run {
my ( $sling, $config ) = @_;
if ( !defined $config ) {
croak 'No content config supplied!';
}
$sling->check_forks;
${ $config->{'remote'} } =
Apache::Sling::URL::strip_leading_slash( ${ $config->{'remote'} } );
${ $config->{'remote-source'} } = Apache::Sling::URL::strip_leading_slash(
${ $config->{'remote-source'} } );
if ( defined ${ $config->{'additions'} } ) {
my $message =
"Adding content from file \"" . ${ $config->{'additions'} } . "\":\n";
Apache::Sling::Print::print_with_lock( "$message", $sling->{'Log'} );
my @childs = ();
for my $i ( 0 .. $sling->{'Threads'} ) {
my $pid = fork;
if ($pid) { push @childs, $pid; } # parent
elsif ( $pid == 0 ) { # child
# Create a separate authorization per fork:
my $authn = new Apache::Sling::Authn( \$sling );
my $content =
new Apache::Sling::Content( \$authn, $sling->{'Verbose'},
$sling->{'Log'} );
$content->upload_from_file( ${ $config->{'additions'} },
$i, $sling->{'Threads'} );
exit 0;
}
else {
croak "Could not fork $i!";
}
}
foreach (@childs) { waitpid $_, 0; }
}
else {
my $authn = new Apache::Sling::Authn( \$sling );
my $content =
new Apache::Sling::Content( \$authn, $sling->{'Verbose'},
$sling->{'Log'} );
if ( defined ${ $config->{'local'} }
&& defined ${ $config->{'remote'} } )
{
$content->upload_file(
${ $config->{'local'} },
${ $config->{'remote'} },
${ $config->{'filename'} }
);
}
elsif ( defined ${ $config->{'exists'} } ) {
$content->check_exists( ${ $config->{'remote'} } );
}
elsif ( defined ${ $config->{'add'} } ) {
$content->add( ${ $config->{'remote'} }, $config->{'property'} );
}
elsif ( defined ${ $config->{'copy'} } ) {
$content->copy(
${ $config->{'remote-source'} },
${ $config->{'remote'} },
${ $config->{'replace'} }
);
}
elsif ( defined ${ $config->{'delete'} } ) {
$content->del( ${ $config->{'remote'} } );
}
elsif ( defined ${ $config->{'move'} } ) {
$content->move(
${ $config->{'remote-source'} },
${ $config->{'remote'} },
${ $config->{'replace'} }
);
}
elsif ( defined ${ $config->{'view'} } ) {
$content->view( ${ $config->{'remote'} } );
}
Apache::Sling::Print::print_result($content);
}
return 1;
}
#}}}
#{{{sub group_config
sub group_config {
my ($sling) = @_;
my $additions;
my $add;
my $delete;
my $exists;
my @property;
my $view;
my %group_config = (
'auth' => \$sling->{'Auth'},
'help' => \$sling->{'Help'},
'log' => \$sling->{'Log'},
'man' => \$sling->{'Man'},
'pass' => \$sling->{'Pass'},
'threads' => \$sling->{'Threads'},
'url' => \$sling->{'URL'},
'user' => \$sling->{'User'},
'verbose' => \$sling->{'Verbose'},
'add' => \$add,
'additions' => \$additions,
'delete' => \$delete,
'exists' => \$exists,
'property' => \@property,
'view' => \$view
);
return \%group_config;
}
#}}}
#{{{sub group_run
sub group_run {
my ( $sling, $config ) = @_;
if ( !defined $config ) {
croak 'No group config supplied!';
}
$sling->check_forks;
if ( defined ${ $config->{'additions'} } ) {
my $message =
"Adding groups from file \"" . ${ $config->{'additions'} } . "\":\n";
Apache::Sling::Print::print_with_lock( "$message", $sling->{'Log'} );
my @childs = ();
for my $i ( 0 .. $sling->{'Threads'} ) {
my $pid = fork;
if ($pid) { push @childs, $pid; } # parent
elsif ( $pid == 0 ) { # child
# Create a separate authorization per fork:
my $authn = new Apache::Sling::Authn( \$sling );
my $group =
new Apache::Sling::Group( \$authn, $sling->{'Verbose'},
$sling->{'Log'} );
$group->add_from_file( ${ $config->{'additions'} },
$i, $sling->{'Threads'} );
exit 0;
}
else {
croak "Could not fork $i!";
}
}
foreach (@childs) { waitpid $_, 0; }
}
else {
my $authn = new Apache::Sling::Authn( \$sling );
my $group =
new Apache::Sling::Group( \$authn, $sling->{'Verbose'},
$sling->{'Log'} );
if ( defined ${ $config->{'exists'} } ) {
$group->check_exists( ${ $config->{'exists'} } );
}
elsif ( defined ${ $config->{'add'} } ) {
$group->add( ${ $config->{'add'} }, $config->{'property'} );
}
elsif ( defined ${ $config->{'delete'} } ) {
$group->del( ${ $config->{'delete'} } );
}
elsif ( defined ${ $config->{'view'} } ) {
$group->view( ${ $config->{'view'} } );
}
Apache::Sling::Print::print_result($group);
}
return 1;
}
#}}}
#{{{sub group_member_config
sub group_member_config {
my ($sling) = @_;
my $additions;
my $add;
my $delete;
my $exists;
my $group;
my $view;
my %group_member_config = (
'auth' => \$sling->{'Auth'},
'help' => \$sling->{'Help'},
'log' => \$sling->{'Log'},
'man' => \$sling->{'Man'},
'pass' => \$sling->{'Pass'},
'threads' => \$sling->{'Threads'},
'url' => \$sling->{'URL'},
'user' => \$sling->{'User'},
'verbose' => \$sling->{'Verbose'},
'add' => \$add,
'additions' => \$additions,
'delete' => \$delete,
'exists' => \$exists,
'group' => \$group,
'view' => \$view
);
return \%group_member_config;
}
#}}}
#{{{sub group_member_run
sub group_member_run {
my ( $sling, $config ) = @_;
if ( !defined $config ) {
croak 'No group_member config supplied!';
}
$sling->check_forks;
if ( defined ${ $config->{'additions'} } ) {
my $message =
"Adding groups from file \"" . ${ $config->{'additions'} } . "\":\n";
Apache::Sling::Print::print_with_lock( "$message", $sling->{'Log'} );
my @childs = ();
for my $i ( 0 .. $sling->{'Threads'} ) {
my $pid = fork;
if ($pid) { push @childs, $pid; } # parent
elsif ( $pid == 0 ) { # child
# Create a separate authorization per fork:
my $authn = new Apache::Sling::Authn( \$sling );
my $group =
new Apache::Sling::Group( \$authn, $sling->{'Verbose'},
$sling->{'Log'} );
$group->member_add_from_file( ${ $config->{'additions'} },
$i, $sling->{'Threads'} );
exit 0;
}
else {
croak "Could not fork $i!";
}
}
foreach (@childs) { waitpid $_, 0; }
}
else {
my $authn = new Apache::Sling::Authn( \$sling );
my $group =
new Apache::Sling::Group( \$authn, $sling->{'Verbose'},
$sling->{'Log'} );
if ( defined ${ $config->{'exists'} } ) {
$group->member_exists( ${ $config->{'group'} },
${ $config->{'exists'} } );
}
elsif ( defined ${ $config->{'add'} } ) {
$group->member_add( ${ $config->{'group'} },
${ $config->{'add'} } );
}
elsif ( defined ${ $config->{'delete'} } ) {
$group->member_delete( ${ $config->{'group'} },
${ $config->{'delete'} } );
}
elsif ( defined ${ $config->{'view'} } ) {
$group->member_view( ${ $config->{'group'} } );
}
Apache::Sling::Print::print_result($group);
}
return 1;
}
#}}}
#{{{sub json_query_servlet_config
sub json_query_servlet_config {
my ($sling) = @_;
my $all_nodes;
my %json_query_servlet_config = (
'auth' => \$sling->{'Auth'},
'help' => \$sling->{'Help'},
'log' => \$sling->{'Log'},
'man' => \$sling->{'Man'},
'pass' => \$sling->{'Pass'},
'threads' => \$sling->{'Threads'},
'url' => \$sling->{'URL'},
'user' => \$sling->{'User'},
'verbose' => \$sling->{'Verbose'},
'all_nodes' => \$all_nodes
);
return \%json_query_servlet_config;
}
#}}}
#{{{sub json_query_servlet_run
sub json_query_servlet_run {
my ( $sling, $config ) = @_;
if ( !defined $config ) {
croak 'No json query servlet config supplied!';
}
$sling->check_forks;
${ $config->{'remote'} } =
Apache::Sling::URL::strip_leading_slash( ${ $config->{'remote'} } );
${ $config->{'remote-source'} } = Apache::Sling::URL::strip_leading_slash(
${ $config->{'remote-source'} } );
my $authn = new Apache::Sling::Authn( \$sling );
my $json_query_servlet =
new Apache::Sling::JsonQueryServlet( \$authn, $sling->{'Verbose'},
$sling->{'Log'} );
if ( defined ${ $config->{'all_nodes'} } )
{
$json_query_servlet->all_nodes();
}
Apache::Sling::Print::print_result($json_query_servlet);
return 1;
}
#}}}
#{{{sub ldap_synch_config
sub ldap_synch_config {
my ($sling) = @_;
my $attributes;
my $download_user_list;
my $flag_disabled;
my $ldap_attributes;
my $ldap_base;
my $ldap_dn;
my $ldap_filter;
my $ldap_host;
my $ldap_pass;
my $synch_full;
my $synch_full_since;
my $synch_listed;
my $synch_listed_since;
my $upload_user_list;
my %ldap_synch_config = (
'auth' => \$sling->{'Auth'},
'help' => \$sling->{'Help'},
'log' => \$sling->{'Log'},
'man' => \$sling->{'Man'},
'pass' => \$sling->{'Pass'},
'threads' => \$sling->{'Threads'},
'url' => \$sling->{'URL'},
'user' => \$sling->{'User'},
'verbose' => \$sling->{'Verbose'},
'attributes' => $attributes,
'download-user-list' => $download_user_list,
'flag-disabled' => $flag_disabled,
'ldap-attributes' => $ldap_attributes,
'ldap-base' => $ldap_base,
'ldap-dn' => $ldap_dn,
'ldap-filter' => $ldap_filter,
'ldap-host' => $ldap_host,
'ldap-pass' => $ldap_pass,
'synch-full' => $synch_full,
'synch-full-since' => $synch_full_since,
'synch-listed' => $synch_listed,
'synch-listed-since' => $synch_listed_since,
'upload-user-list' => $upload_user_list
);
return \%ldap_synch_config;
}
#}}}
#{{{sub ldap_synch_run
sub ldap_synch_run {
my ( $sling, $config ) = @_;
if ( !defined $config ) {
croak 'No ldap_synch config supplied!';
}
$sling->check_forks;
my $authn = new Apache::Sling::Authn( \$sling );
my $ldap_synch = new Apache::Sling::LDAPSynch(
${ $config->{'ldap-host'} },
${ $config->{'ldap-base'} },
${ $config->{'ldap-filter'} },
${ $config->{'ldap-dn'} },
${ $config->{'ldap-pass'} },
\$authn,
${ $config->{'flag-disabled'} },
$sling->{'Verbose'},
$sling->{'Log'}
);
if ( defined ${ $config->{'download-user-list'} } ) {
$ldap_synch->download_synch_user_list(
${ $config->{'download-user-list'} } );
}
elsif ( defined ${ $config->{'upload-user-list'} } ) {
$ldap_synch->upload_synch_user_list(
${ $config->{'upload-user-list'} } );
}
elsif ( defined ${ $config->{'synch-full'} } ) {
$ldap_synch->synch_full( ${ $config->{'ldap-attributes'} },
${ $config->{'attributes'} } );
}
elsif ( defined ${ $config->{'synch-full-since'} } ) {
$ldap_synch->synch_full_since(
${ $config->{'ldap-attributes'} },
${ $config->{'attributes'} },
${ $config->{'synch-full-since'} }
);
}
elsif ( defined ${ $config->{'synch-listed'} } ) {
$ldap_synch->synch_listed( ${ $config->{'ldap-attributes'} },
${ $config->{'attributes'} } );
}
elsif ( defined ${ $config->{'synch-listed-since'} } ) {
$ldap_synch->synch_listed_since(
${ $config->{'ldap-attributes'} },
${ $config->{'attributes'} },
${ $config->{'synch-listed-since'} }
);
}
Apache::Sling::Print::print_result($ldap_synch);
return 1;
}
#}}}
#{{{sub user_config
sub user_config {
my ($sling) = @_;
my $password;
my $additions;
my $add;
my $change_password;
my $delete;
my $email;
my $exists;
my $first_name;
my $last_name;
my $me;
my $new_password;
my @property;
my $sites;
my $update;
my $view;
my %user_config = (
'auth' => \$sling->{'Auth'},
'help' => \$sling->{'Help'},
'log' => \$sling->{'Log'},
'man' => \$sling->{'Man'},
'pass' => \$sling->{'Pass'},
'threads' => \$sling->{'Threads'},
'url' => \$sling->{'URL'},
'user' => \$sling->{'User'},
'verbose' => \$sling->{'Verbose'},
'add' => \$add,
'additions' => \$additions,
'change-password' => \$change_password,
'delete' => \$delete,
'email' => \$email,
'exists' => \$exists,
'first-name' => \$first_name,
'last-name' => \$last_name,
'me' => \$me,
'new-password' => \$new_password,
'password' => \$password,
'property' => \@property,
'sites' => \$sites,
'update' => \$update,
'view' => \$view
);
return \%user_config;
}
#}}}
#{{{sub user_run
sub user_run {
my ( $sling, $config ) = @_;
if ( !defined $config ) {
croak 'No user config supplied!';
}
$sling->check_forks;
# Handle the three special case commonly used properties:
if ( defined ${ $config->{'email'} } ) {
push @{ $config->{'property'} }, "email=" . ${ $config->{'email'} };
}
if ( defined ${ $config->{'first-name'} } ) {
push @{ $config->{'property'} },
"firstName=" . ${ $config->{'first-name'} };
}
if ( defined ${ $config->{'last-name'} } ) {
push @{ $config->{'property'} },
"lastName=" . ${ $config->{'last-name'} };
}
if ( defined ${ $config->{'additions'} } ) {
my $message =
"Adding users from file \"" . ${ $config->{'additions'} } . "\":\n";
Apache::Sling::Print::print_with_lock( "$message", $sling->{'Log'} );
my @childs = ();
for my $i ( 0 .. $sling->{'Threads'} ) {
my $pid = fork;
if ($pid) { push @childs, $pid; } # parent
elsif ( $pid == 0 ) { # child
# Create a separate authorization per fork:
my $authn = new Apache::Sling::Authn( \$sling );
my $user =
new Apache::Sling::User( \$authn, $sling->{'Verbose'},
$sling->{'Log'} );
$user->add_from_file( ${ $config->{'additions'} },
$i, $sling->{'Threads'} );
exit 0;
}
else {
croak "Could not fork $i!";
}
}
foreach (@childs) { waitpid $_, 0; }
}
else {
my $authn = new Apache::Sling::Authn( \$sling );
my $user =
new Apache::Sling::User( \$authn, $sling->{'Verbose'},
$sling->{'Log'} );
if ( defined ${ $config->{'exists'} } ) {
$user->check_exists( ${ $config->{'exists'} } );
}
elsif ( defined ${ $config->{'me'} } ) {
$user->me();
}
elsif ( defined ${ $config->{'sites'} } ) {
$user->sites();
}
elsif ( defined ${ $config->{'add'} } ) {
$user->add(
${ $config->{'add'} },
${ $config->{'password'} },
$config->{'property'}
);
}
elsif ( defined ${ $config->{'update'} } ) {
$user->update( ${ $config->{'update'} }, $config->{'property'} );
}
elsif ( defined ${ $config->{'change-password'} } ) {
$user->change_password(
${ $config->{'change-password'} },
${ $config->{'password'} },
${ $config->{'new-password'} },
${ $config->{'new-password'} }
);
}
elsif ( defined ${ $config->{'delete'} } ) {
$user->del( ${ $config->{'delete'} } );
}
elsif ( defined ${ $config->{'view'} } ) {
$user->view( ${ $config->{'view'} } );
}
Apache::Sling::Print::print_result($user);
}
return 1;
}
#}}}
1;
__END__
=head1 NAME
Apache::Sling - Perl library for interacting with the apache sling web framework
=head1 ABSTRACT
Top level Entry point to the Apache Sling libraries. Provides a layer of
abstraction for configuring and running the various Sling operations.
=head1 METHODS
=head2 new
Create, set up, and return a Sling object.
=head2 check_forks
Check number of forks to create complies with maximum number of forks
allowed.
=head2 authz_config
Fetch hash of authz configuration.
=head2 authz_run
Run authz related actions.
=head2 content_config
Fetch hash of content configuration.
=head2 content_run
Run content related actions.
=head2 group_config
Fetch hash of group configuration.
=head2 group_run
Run group related actions.
=head2 group_member_config
Fetch hash of group membership configuration.
=head2 group_member_run
Run group membership related actions.
=head2 ldap_synch_config
Fetch hash of ldap synchronization configuration.
=head2 ldap_synch_run
Run ldap synchronization related actions.
=head2 user_config
Fetch hash of user configuration.
=head2 user_run
Run user related actions.
=head1 USAGE
use Apache::Sling;
=head1 DESCRIPTION
The Apache::Sling perl library is designed to provide a perl based interface on
to the Apache sling web framework.
=head1 REQUIRED ARGUMENTS
None required.
=head1 OPTIONS
n/a
=head1 DIAGNOSTICS
n/a
=head1 EXIT STATUS
1 on success.
=head1 CONFIGURATION
None required.
=head1 DEPENDENCIES
=head1 INCOMPATIBILITIES
None known.
=head1 BUGS AND LIMITATIONS
None known.
=head1 AUTHOR
Daniel David Parry <perl@ddp.me.uk>
=head1 LICENSE AND COPYRIGHT
LICENSE: http://dev.perl.org/licenses/artistic.html
COPYRIGHT: (c) 2011 Daniel David Parry <perl@ddp.me.uk>