/**
  * Validates this package and optionally it's delivered requirements. The set validation
  * mode will toggle between different checks. 
  * 
  * @param	integer		$validationMode
  * @return	boolean
  */
 public function validate($validationMode, $requiredVersion = '')
 {
     if ($validationMode !== PackageValidationManager::VALIDATION_EXCLUSION) {
         try {
             // try to read archive
             $this->archive->openArchive();
             // check if package is installable or suitable for an update
             $this->validateInstructions($requiredVersion, $validationMode);
         } catch (PackageValidationException $e) {
             $this->exception = $e;
             return false;
         }
     }
     $package = $this->archive->getPackageInfo('name');
     if ($validationMode === PackageValidationManager::VALIDATION_RECURSIVE) {
         try {
             PackageValidationManager::getInstance()->addVirtualPackage($package, $this->archive->getPackageInfo('version'));
             // cache excluded packages
             self::$excludedPackages[$package] = array();
             $excludedPackages = $this->archive->getExcludedPackages();
             for ($i = 0, $count = count($excludedPackages); $i < $count; $i++) {
                 if (!isset(self::$excludedPackages[$package][$excludedPackages[$i]['name']])) {
                     self::$excludedPackages[$package][$excludedPackages[$i]['name']] = array();
                 }
                 self::$excludedPackages[$package][$excludedPackages[$i]['name']][] = $excludedPackages[$i]['version'];
             }
             // traverse open requirements
             foreach ($this->archive->getOpenRequirements() as $requirement) {
                 $virtualPackageVersion = PackageValidationManager::getInstance()->getVirtualPackage($requirement['name']);
                 if ($virtualPackageVersion === null || Package::compareVersion($virtualPackageVersion, $requirement['minversion'], '<')) {
                     if (empty($requirement['file'])) {
                         // check if package is known
                         $sql = "SELECT\t*\n\t\t\t\t\t\t\t\tFROM\twcf" . WCF_N . "_package\n\t\t\t\t\t\t\t\tWHERE\tpackage = ?";
                         $statement = WCF::getDB()->prepareStatement($sql);
                         $statement->execute(array($requirement['name']));
                         $package = $statement->fetchObject('wcf\\data\\package\\Package');
                         throw new PackageValidationException(PackageValidationException::MISSING_REQUIREMENT, array('package' => $package, 'packageName' => $requirement['name'], 'packageVersion' => $requirement['minversion']));
                     }
                     $archive = $this->archive->extractTar($requirement['file']);
                     $index = count($this->children);
                     $this->children[$index] = new PackageValidationArchive($archive, $this, $this->depth + 1);
                     if (!$this->children[$index]->validate(PackageValidationManager::VALIDATION_RECURSIVE, $requirement['minversion'])) {
                         return false;
                     }
                     PackageValidationManager::getInstance()->addVirtualPackage($this->children[$index]->getArchive()->getPackageInfo('name'), $this->children[$index]->getArchive()->getPackageInfo('version'));
                 }
             }
         } catch (PackageValidationException $e) {
             $this->exception = $e;
             return false;
         }
     } else {
         if ($validationMode === PackageValidationManager::VALIDATION_EXCLUSION) {
             try {
                 $this->validateExclusion($package);
                 for ($i = 0, $count = count($this->children); $i < $count; $i++) {
                     if (!$this->children[$i]->validate(PackageValidationManager::VALIDATION_EXCLUSION)) {
                         return false;
                     }
                 }
             } catch (PackageValidationException $e) {
                 $this->exception = $e;
                 return false;
             }
         }
     }
     return true;
 }