skeleton.pl


#!/usr/bin/perl
# ---------------------------------------------------------------------------------------------
#
# skeleton.pl --- Skeleton API Example for v 0.20.0 API Access to POPFile
#                 API from commandline programs
#
# This program compiled by Scott W Leighton (helphand@pacbell.net)
# from POPFile sources as an example for use in creating POPFile
# commandline programs using the POPFile API. In compiling this
# example, sections of POPFile code were copied, verbatim, from
# the code base of the POPFile project, and are not the original
# work of the compiler.
#
# POPFile and it's components, are Copyrighted by John Graham-Cumming.
# The compiler hereby contributes this compilation of POPFile code
# to the Popfile project under the terms of the Popfile License
# Agreement.    /Scott W Leighton/  June 23, 2003
#
# Revised June 22, 2003 - Initial Release
#         June 23, 2003 - Merged v 0.19.0 version
#         June 24, 2003 - Added use locale
#
# POPFile
# Copyright (c) 2001-2003 John Graham-Cumming
#
# ---------------------------------------------------------------------------------------------

use strict;
use locale;


# The POPFile classes are stored by reference in the %components hash, the top level key is
# the type of the component (see load_modules) and then the name of the component derived from
# calls to each loadable modules name() method and which points to the actual module

    my %components;


# ---------------------------------------------------------------------------------------------
#
# load_modules
#
# Called to load specific POPFile loadable modules (implemented as .pm files with special
# comment on first line) in a specific subdirectory
#
# $directory          The directory to search for loadable modules
# $type               The 'type' of module being loaded (e.g. proxy, core, ui) which is used
#                     below when fixing up references between modules (e.g. proxy modules all
#                     need access to the classifier module)
# $module             The specific module name to be loaded.
#
# ---------------------------------------------------------------------------------------------

sub load_modules {

     my ( $directory, $type, $module ) = @_;

     $module = $directory . '/' . $module;

     if ( open MODULE, "<$module" ) {
           my $first = <MODULE>;
           close MODULE;

           if ( $first =~ /^# POPFILE LOADABLE MODULE/ ) {
                require $module;

                $module =~ s/\//::/;
                $module =~ s/\.pm//;

                my $mod = new $module;
                my $name = $mod->name();

                $components{$type}{$name} = $mod;

           }
     }

}

    #
    # Main
    #

    #
    # Load the modules we'll be using
    #

    load_modules( 'POPFile',      'core',       'Configuration.pm' );
    load_modules( 'POPFile',      'core',       'Logger.pm' );
    load_modules( 'POPFile',      'core',       'MQ.pm' );
    load_modules( 'Classifier',   'classifier', 'Bayes.pm' );

#
# Perform a version check by looking for the POPFile::Module that
# was introduced in v 0.19.0. If you require features of v 0.20.0
# then change the second test to
#          $components{core}{config}->can ( 'mq' )
# since the message queue module was introduced in v 0.20.0
#

if ($components{core}{config}->isa ('POPFile::Module') && $components{core}{config}->can ( 'parameter' ) ) {

    # link each of the objects with the configuration object, 
    # the logger (except the logger itself) and, if we are on v 0.20.0
    # to the mq. 

    foreach my $type (keys %components) {
        foreach my $name (keys %{$components{$type}}) {
            $components{$type}{$name}->configuration($components{core}{config});
            $components{$type}{$name}->logger($components{core}{logger}) if ( $name ne 'logger' );
            $components{$type}{$name}->mq($components{core}{mq}) if ( $components{$type}{$name}->can ( 'mq' ) );
        }
    }


    #
    # Tell each module to initialize itself
    #

    foreach my $type (keys %components) {
        foreach my $name (keys %{$components{$type}}) {
            if ($components{$type}{$name}->initialize() == 0 ) {
                die "Failed to start while initializing the $name module\n";
            }
        }
    }


    # Ensure that a temp subdirectory exists to hold any error log
    # that logger might generate so we don't interfere with a
    # running POPFile.

    mkdir ( 'temp' );

    # Set default commandline options, if your program has any
    # commandline options, establish the default values here.
    # Those defaults will be replaced later if the user runs
    # with the commandline option set.

    $components{core}{config}->parameter('myprog_myoption','default value');

    # Load in the Popfile configuration parameters, any configured
    # ones will override the initialized default values
    # NOTE: We are intentially NOT saving this configuration
    # back to disk since the parameters we are allowing
    # for this program are NOT legal Popfile parameters.

    $components{core}{config}->load_configuration();

    # Now grab any commandline parameters, they will override
    # the defaults and those in popfile.cfg. As a byproduct,
    # if the user overrides our program's options this will
    # pick it up for us.
    
    $components{core}{config}->parse_command_line();

    # Now override the logdir and piddir so we don't mess with
    # the production ones, we are intentionally doing this
    # AFTER the command line options are loaded so we are
    # guaranteed that they weren't changed by the user.

    $components{core}{config}->parameter('logger_logdir','temp/');
    $components{core}{config}->parameter('config_piddir','temp/');

    # force logger to recognize the new logdir before we startup
    # the modules. That way we will not inadvertently log to the
    # production POPFile log. 

    $components{core}{logger}->service();

    # now that the configuration is established, tell each module
    # to start

    foreach my $type (keys %components) {
        foreach my $name (keys %{$components{$type}}) {
            if ($components{$type}{$name}->start() == 0 ) {
                die "Failed to start while starting the $name module\n";
            }
        }
    }


    #
    #  Your Program Logic goes here.....
    #


The code below is our example code


# obtain the buckets from the classifier my @buckets = $components{classifier}{bayes}->get_buckets(); # iterate thru the buckets we found, for each bucket, obtain # the color, unique count, and word count from the classifier # and print the results to the screen. foreach my $bucket (@buckets) { print "Bucket $bucket is colored ", $components{classifier}{bayes}->get_bucket_color($bucket), " and has ", $components{classifier}{bayes}->get_bucket_unique_count($bucket), " unique words and ", $components{classifier}{bayes}->get_bucket_word_count($bucket), " for a word count\n"; }

The code above is our example code


# # All Done # # # Cleanup - Get rid of the popfile.pid file created by the configuration # module. # unlink($components{core}{config}->parameter('config_piddir') . 'popfile.pid'); exit(0); } else { print "$0 is not compatible with your version of POPFile\n"; exit(1); }