/**
  * Register Session Component
  * @throws BootstrapException
  */
 protected function registerSession()
 {
     // Container has Session component, must be defined in config.
     if (!property_exists($this->config->app, "sessions")) {
         throw BootstrapException::sessionNode();
     }
     $sessionsConfig = $this->config->app->sessions;
     // Means of storage must be defined
     try {
         // Use Cache?
         if (property_exists($sessionsConfig, "useCache") && $sessionsConfig->useCache === true) {
             if (!$this->cache instanceof Cache) {
                 throw BootstrapException::sessionCache();
             }
             try {
                 $this->cache->poke(false);
                 // Poke cache engine; Don't reconnect
                 $cache = $this->cache;
                 // Ref. cache instance
             } catch (CacheException $e) {
                 trigger_error(sprintf('%s: %s', __METHOD__, $e->getMessage()), E_USER_WARNING);
             }
         }
         /** @var $this Kernel */
         if (isset($cache) && $cache instanceof Cache) {
             $storage = Storage::Cache($cache);
         } elseif (property_exists($sessionsConfig, "storageDb")) {
             $storage = Storage::Database($this->getDb($sessionsConfig->storageDb));
         } elseif (property_exists($sessionsConfig, "storagePath")) {
             $storage = Storage::Disk(new Disk($this->rootPath . self::DS . $sessionsConfig->storagePath));
         } else {
             // No storage configuration was set
             throw BootstrapException::sessionStorage();
         }
         // Retrieve session instance
         $this->session = $this->container->get("Session", $storage);
         // Session configuration
         // Expiry
         if (property_exists($sessionsConfig, "expire")) {
             $this->session->setSessionLife(Time::unitsToSeconds($sessionsConfig->expire));
         }
         // Encryption
         if (property_exists($sessionsConfig, "encrypt")) {
             if ($sessionsConfig->encrypt === true) {
                 if (!isset($this->cipher)) {
                     throw BootstrapException::cipherService();
                 }
                 $this->session->useCipher($this->cipher);
             }
         }
         // Cookie
         $cookie = [false, "30d", "", "", false, true];
         if (property_exists($sessionsConfig, "cookie")) {
             $cookie[0] = true;
             $cookieArgCount = 1;
             foreach (["expire", "path", "domain", "secure", "httpOnly"] as $cookieArg) {
                 if (property_exists($sessionsConfig->cookie, $cookieArg)) {
                     $cookie[$cookieArgCount] = $sessionsConfig->cookie->{$cookieArg};
                 }
                 $cookieArgCount++;
             }
         }
         $cookie[1] = Time::unitsToSeconds($cookie[1]);
         // Life
         $cookie[2] = $cookie[2] ?? "";
         // Path
         $cookie[3] = $cookie[3] ?? "";
         // Domain
         call_user_func_array([$this->session, "setCookie"], $cookie);
         // PBKDF2 Hashing
         // Salt
         if (property_exists($sessionsConfig, "hashSalt")) {
             $this->session->setHashSalt(strval($sessionsConfig->hashSalt));
         }
         // Cost
         if (property_exists($sessionsConfig, "hashCost")) {
             $this->session->setHashCost(intval($sessionsConfig->hashCost));
         }
         // Bootstrap Session
         $this->session->start();
         // If storage is filesystem, save instance in disks repo.
         if ($storage instanceof Disk) {
             $this->disks->push($storage, "sessions");
         }
     } catch (\ComelyException $e) {
         throw new BootstrapException(__METHOD__, $e->getMessage(), $e->getCode());
     }
 }