The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/env perl
package # Hide package name from PAUSE
  Alien::ActiveMQ::Install;
use Moose;
use Method::Signatures::Simple;
use MooseX::Types::Moose qw/Str/;
use MooseX::Types::Path::Class;
use Path::Class qw/file dir/;
use File::ShareDir qw/dist_dir/;
use File::Temp qw/tempdir/;
use LWP::Simple qw/get getstore/;
use Archive::Extract;
use File::Copy::Recursive qw/ dircopy /;
use namespace::autoclean;

with 'MooseX::Getopt';

has install_dir => ( isa => 'Path::Class::Dir', is => 'ro', coerce => 1,
    lazy_build => 1,
);

has tarball => ( isa => 'Path::Class::File', is => 'ro', coerce => 1,
    lazy_build => 1
);

method _build_tarball {
    my $tarball = $self->download_uri;
    $tarball =~ s|.+/||;
    file( $self->_temp_dir, $tarball );
}

has version_number => ( isa => Str, is => 'ro', required => 1, lazy_build => 1 );

method _build_version_number {
    return '5.2.0' unless $self->has_download_uri;
    $self->download_uri =~ /activemq-(.+\d)/;
}

has download_uri => ( isa => Str, is => 'ro', lazy_build => 1 );

method _build_download_uri {
    sprintf("http://www.apache.org/dyn/closer.cgi/activemq/apache-activemq/5.2.0/apache-activemq-%s-bin.tar.gz", $self->version_number);
}

method _build_install_dir {
    dir( dist_dir('Alien-ActiveMQ'), $self->version_number );
}

has _temp_dir => (
    isa => 'Path::Class::Dir', coerce => 1, is => 'ro', lazy => 1,
    default => sub { tempdir( XXCLEANUP => 1 ) },
);

# To make it easier to test
method _get ($uri) { get($uri) }
method _getstore ($uri, $file) { getstore($uri, $file) }

method download_tarball {
    my $mirror_list = $self->_get($self->download_uri);
    die("Failed to download " . $self->download_uri . "\n") unless $mirror_list;
    my ($file) = $mirror_list =~ /(http[^"]+\.tar\.gz)/;
    die("Failed to extract mirror from " . $self->download_uri . "\n") unless $file;
    my $res = $self->_getstore($file, $self->tarball . '');
    die("Failed to download " . $self->download_uri . "\n") unless $res == 200;
    $self->tarball;
}

method unpack_tarball ($tarball) {
    local $Archive::Extract::PREFER_BIN = 1;
    my $tar = Archive::Extract->new(archive => $self->tarball.'');
    $tar->extract(to => $self->_temp_dir.'');
}

method _dircopy ($from, $to) { dircopy($from, $to) }

method run {
    my $tarball = $self->has_tarball ? $self->tarball : $self->download_tarball;
    warn("Downloaded tarball to: $tarball\n");
    $self->unpack_tarball($tarball);   
    warn("Unpacked tarball $tarball");
    my $dir = $tarball;
    $dir =~ s/\.tar\.gz$//;
    $dir =~ s/-bin//;
    die("Could not find where tarball unpacked") unless -d $dir;
    warn("From $dir to " . $self->install_dir);
    $self->_dircopy( $dir => $self->install_dir );
    warn("ActiveMQ installed in " . $self->install_dir . "\n");
}

__PACKAGE__->meta->make_immutable;
__PACKAGE__->new_with_options->run unless caller;
1;

__END__