public function main()
 {
     if ($this->_database === null) {
         $coverageDatabase = $this->project->getProperty('coverage.database');
         if (!$coverageDatabase) {
             throw new BuildException('Either include coverage-setup in your build file or set ' . 'the "database" attribute');
         }
         $database = new PhingFile($coverageDatabase);
     } else {
         $database = $this->_database;
     }
     $this->log('Calculating coverage threshold: min. ' . $this->_perProject . '% per project, ' . $this->_perClass . '% per class and ' . $this->_perMethod . '% per method is required');
     $props = new Properties();
     $props->load($database);
     foreach ($props->keys() as $filename) {
         $file = unserialize($props->getProperty($filename));
         // Skip file if excluded from coverage threshold validation
         if ($this->_excludes !== null) {
             if (in_array($file['fullname'], $this->_excludes->getExcludedFiles())) {
                 continue;
             }
         }
         $this->calculateCoverageThreshold($file['fullname'], $file['coverage']);
     }
     if ($this->_projectStatementCount > 0) {
         $coverage = $this->_projectStatementsCovered / $this->_projectStatementCount * 100;
     } else {
         $coverage = 0;
     }
     if ($coverage < $this->_perProject) {
         throw new BuildException('The coverage (' . round($coverage, 2) . '%) for the entire project ' . 'is lower than the specified threshold (' . $this->_perProject . '%)');
     }
     $this->log('Passed coverage threshold. Minimum found coverage values are: ' . round($coverage, 2) . '% per project, ' . round($this->_minClassCoverageFound, 2) . '% per class and ' . round($this->_minMethodCoverageFound, 2) . '% per method');
 }