package Cpanel::Easy::Utils::Tomcat;

# cpanel - Cpanel/Easy/Utils/Tomcat.pm            Copyright(c) 2014 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cpanel license. Unauthorized copying is prohibited

use strict;
use warnings;

use Cpanel::Env                    ();
use Cpanel::Config::userdata       ();
use Cpanel::Config::userdata::Load ();
use Cpanel::SafeRun                ();
use Cpanel::Version::Compare       ();

our $Tomcat55_BaseDir = '/usr/local/jakarta';
my $Tomcat55_NS = 'Cpanel::Easy::ModJk5';
our $Tomcat70_BaseDir = '/usr/local/easy';
my $Tomcat70_NS = 'Cpanel::Easy::Tomcat::7_0';
my $ModJkConfDir;

# Location of the mod_jk source 'conf' directory
sub get_src_modjk_confdir {
    return $ModJkConfDir;
}

# Location of the mod_jk source 'conf' directory
sub set_src_modjk_confdir {
    $ModJkConfDir = shift;
}

sub get_tomcat_confdir {
    my $self = shift;
    my $dir;

    # Checking both profile option and tomcat existence is important in case
    # the user enables both in profile to "force" one to install... but doesn't
    # have it installed (Case 73065).
    if ( -e "$Tomcat55_BaseDir/tomcat" && $self->get_ns_value_from_profile( $Tomcat55_NS, $self->{'working_profile'} ) ) {
        $dir = "$Tomcat55_BaseDir/tomcat/conf";
    }
    else {
        if ( $self->get_ns_value_from_profile( $Tomcat70_NS, $self->{'working_profile'} ) ) {
            $dir = "$Tomcat70_BaseDir/etc/easy-tomcat7";
        }
    }

    return $dir;
}

my %tomcat_files = (
    '/usr/sbin/stoptomcat'                     => "$Tomcat70_BaseDir/sbin/easy-tomcat7-stop",
    '/usr/sbin/starttomcat'                    => "$Tomcat70_BaseDir/sbin/easy-tomcat7-start",
    '/usr/local/cpanel/scripts/gentomcatlist2' => "$Tomcat70_BaseDir/sbin/easy-tomcat7-gentomcatlist2",
    '/usr/local/cpanel/scripts/addservlets2'   => "$Tomcat70_BaseDir/sbin/easy-tomcat7-addservlets2",
    '/usr/local/cpanel/scripts/remservlets'    => "$Tomcat70_BaseDir/sbin/easy-tomcat7-remservlets",
);

sub cleanup_tomcat_support_files {
    my $self = shift;

    my $tomcat_chkservd = '/etc/chkserv.d/tomcat';

    if ( $self->get_ns_value_from_profile( $Tomcat70_NS, $self->{'working_profile'} ) ) {

        # Create symlinks
        my @ln_cmd = ( '/bin/ln', '-s', '-f', '-n' );
        for my $symlink ( keys %tomcat_files ) {
            system @ln_cmd, $tomcat_files{$symlink}, $symlink;
        }

        # Clean up Tomcat 5.5 chkservd entry, if any; set up Tomcat 7 chkservd entry
        if ( -e $tomcat_chkservd ) {
            unlink $tomcat_chkservd or $self->print_alert( q{Could not unlink '[_1]': [_2]}, $tomcat_chkservd, $! );
        }
        Cpanel::FileUtils::safecopy( "$Tomcat70_BaseDir/etc/easy-tomcat7/easy-tomcat7-chkserv", $tomcat_chkservd )
          or return ( 0, q{Failed to copy '[_1]' script to '[_2]'}, "$Tomcat70_BaseDir/etc/easy-tomcat7/easy-tomcat7-chkserv", $tomcat_chkservd );

        $self->restart_chkservd();
    }
    elsif ( $self->get_ns_value_from_profile( $Tomcat55_NS, $self->{'working_profile'} ) ) {

        # Using Tomcat 5.5; no cleanup actions required
    }
    else {

        # remove scripts and symlinks
        for my $script ( keys %tomcat_files ) {
            if ( -e $script || -l $script ) {
                unlink $script or $self->print_alert( q{Could not unlink '[_1]': [_2]}, $script, $! );
            }
        }

        # Clean up chkserv entries, if any
        if ( -e $tomcat_chkservd ) {
            unlink $tomcat_chkservd or $self->print_alert( q{Could not unlink '[_1]': [_2]}, $tomcat_chkservd, $! );
            $self->restart_chkservd();
        }
    }
}

# Queries cPanel/WHM for a list of domains that have servlet support
# Returns a hashref of user to domain list
sub list_servlet_enabled {
    my $self = shift;
    my %hash;

    my $users = Cpanel::Config::userdata::load_user_list();

    # Look through all accounts for anything that has servlet support enabled
    for my $user (@$users) {
        my $userdata = Cpanel::Config::userdata::Load::load_userdata_main($user);

        # Find which domains in the account have been enabled for a user
        # NOTE: We do not return parked domains because you don't enable
        #       servlet support for parked domains.  You enable it on the
        #       domain it's parked on top of.
        my @doms = ( keys %{ $userdata->{'addon_domains'} }, @{ $userdata->{'sub_domains'} }, $userdata->{'main_domain'} );

        # Got a list of domains, now check if the domain has servlet support enabled
        for my $dom (@doms) {
            next unless $dom;    # sanitization to prevent undef values I've seen on my sandbox

            my $ref = Cpanel::Config::userdata::Load::load_userdata( $user, $dom );

            # Found servlet support enabled for this domain
            if ( defined $ref->{'cp_jkmount.conf'} && $ref->{'cp_jkmount.conf'} ) {
                push @{ $hash{$user} }, $dom;
            }
        }
    }

    return \%hash;
}

# Determines which devices have servlet support enabled, then ensure
# Apache and Tomcat are set up correctly.
#
# For this change to take effect, Tomcat will need to be restarted
# after it's called.  As of this writing, this routine is called
# when EA starts restarting Apache (and now Tomcat), at the end of the
# installation phase.  Therefore, this routines expects that the changes
# it makes will take effect when Tomcat is eventually restarted.
sub mass_install_servlet {
    my $self = shift;

    $self->print_alert("Setting up .jsp support for enabled accounts");

    # get user->domain reference that have servlets enabled
    my $enabled = $self->list_servlet_enabled();

    # NOTE: In hind sight, it might have been better to call addservlets multiple
    # times, but instead of having a flag to simply prevent a Tomcat restart, have
    # a flag to prevent it from calling gentomcatlist.  Why?  gentomcatlist updates
    # all of tomcat regardles of the domain passed to addservlets.  If this had
    # been implemented instead, you could update the Apache conf multiple times, then
    # call gentomcatlist to sync Tomcat once, then reboot once.
    while ( my ( $user, $domains ) = each(%$enabled) ) {
        for my $domain (@$domains) {
            my $servlet = '/usr/local/cpanel/scripts/addservlets';
            Cpanel::SafeRun::saferunnoerror( $servlet, '--no-restart', "--domain=$domain" );
        }
    }

    return ( 1, 'Ok' );
}

sub restart_chkservd {
    my $self = shift;

    local %ENV = %ENV;
    Cpanel::Env::cleanenv( 'http_purge' => 1 );
    $self->run_system_cmd( ['/usr/local/cpanel/scripts/restartsrv_chkservd'] );
}

# We only expose Tomcat 5.5 as an install option if the
# 'tomcat' file exists (presumed to be a symlink) in the old
# /usr/local/jakarta directory
sub tomcat_55_available {
    my $easy = shift;

    return 0 if ( $easy->is_redhat() && $easy->{'getos_releaseversion'} >= 7 );

    if ( !-e "$Tomcat55_BaseDir/tomcat" ) {

        # Tomcat 5.5 is deprecated; don't offer to install it unless it's already in use.
        return 0;
    }
    return 1;
}

# Tomcat 7 only available with cPanel/WHM 11.38 and later, and < CentOS 7
# http://go.cpanel.net/tomcat
sub tomcat_7_available {
    my $easy = shift;
    my $avail;

    if ( $easy->is_redhat() && $easy->{'getos_releaseversion'} >= 7 ) {
        $avail = 0;
    }
    else {
        $avail = Cpanel::Version::Compare::compare( $Cpanel::Version::Tiny::VERSION_BUILD, '>=', '11.37' ) ? 1 : 0;
    }

    return $avail;
}

1;

