/**
  * Implement's module logic for given hook
  *
  * @param \AppserverIo\Psr\HttpMessage\RequestInterface          $request        A request object
  * @param \AppserverIo\Psr\HttpMessage\ResponseInterface         $response       A response object
  * @param \AppserverIo\Server\Interfaces\RequestContextInterface $requestContext A requests context instance
  * @param int                                                    $hook           The current hook to process logic for
  *
  * @return bool
  * @throws \AppserverIo\Server\Exceptions\ModuleException
  */
 public function process(RequestInterface $request, ResponseInterface $response, RequestContextInterface $requestContext, $hook)
 {
     // In php an interface is, by definition, a fixed contract. It is immutable.
     // So we have to declair the right ones afterwards...
     /**
      * @var $request \AppserverIo\Psr\HttpMessage\RequestInterface
      */
     /**
      * @var $response \AppserverIo\Psr\HttpMessage\ResponseInterface
      */
     // if false hook is coming do nothing
     if (ModuleHooks::REQUEST_POST !== $hook) {
         return;
     }
     // We have to throw a ModuleException on failure, so surround the body with a try...catch block
     try {
         // set request context as member property for further usage
         $this->requestContext = $requestContext;
         // Reset the $serverBackreferences array to avoid mixups of different requests
         $this->serverBackreferences = array();
         // Resolve all used backreferences which are NOT linked to the query string.
         // We will resolve query string related backreferences separately as we are not able to cache them
         // as easily as, say, the URI
         // We also have to resolve all the changes rules in front of us made, so build up the backreferences
         // IN the loop.
         // TODO switch to backreference request not prefill as it might be faster
         $this->fillContextBackreferences();
         $this->fillHeaderBackreferences($request);
         $this->fillSslEnvironmentBackreferences();
         // Get the environment variables as the array they are within the config.
         // We have to also collect any volative rules which might be set on request base.
         // We might not even get anything, so prepare our rules accordingly
         $volatileEnvironmentVariables = array();
         if ($requestContext->hasModuleVar(ModuleVars::VOLATILE_ENVIRONMENT_VARIABLES)) {
             $volatileEnvironmentVariables = $requestContext->getModuleVar(ModuleVars::VOLATILE_ENVIRONMENT_VARIABLES);
         }
         // Build up the complete ruleset, volatile rules up front
         $variables = array_merge($volatileEnvironmentVariables, $this->configuredVariables);
         // Only act if we got something
         if (is_array($variables)) {
             // Convert the rules to our internally used objects
             foreach ($variables as $variable) {
                 // Make that condition handling only if there even are conditions
                 if (!empty($variable['condition'])) {
                     // Get the operand
                     $condition = $variable['condition'] . $this->getDefaultOperand();
                     if (strpos($condition, '@') !== false) {
                         // Get the pieces of the condition
                         $conditionPieces = array();
                         preg_match_all('`(.*?)@(\\$[0-9a-zA-Z_\\-]+)`', $condition, $conditionPieces);
                         // Check the condition and continue for the next variable if we do not match
                         if (!isset($this->serverBackreferences[$conditionPieces[2][0]])) {
                             continue;
                         }
                         // Do we have a match? Get the potential backreferences
                         $conditionBackreferences = array();
                         if (preg_match('`' . $conditionPieces[1][0] . '`', $this->serverBackreferences[$conditionPieces[2][0]], $conditionBackreferences) !== 1) {
                             continue;
                         }
                     }
                 }
                 // We have to split up the definition string, if we do not find a equal character we have to fail
                 if (!strpos($variable['definition'], '=')) {
                     throw new ModuleException('Invalid definition ' . $variable['definition'] . 'missing "=".');
                 }
                 // Get the variable name and its value from the definition string
                 $varName = $this->filterVariableName(strstr($variable['definition'], '=', true));
                 $value = substr(strstr($variable['definition'], '='), 1);
                 // We also have to resolve backreferences for the value part of the definition, as people might want
                 // to pass OS environment vars to the server vars
                 if (strpos($value, '$') !== false) {
                     // Get the possible backreference (might as well be something else) and resolve it if needed
                     // TODO tell them if we do not find a backreference to resolve, might be a problem
                     $possibleBackreferences = array();
                     preg_match('`\\$.+?`', $value, $possibleBackreferences);
                     foreach ($possibleBackreferences as $possibleBackreference) {
                         if ($backrefValue = getenv($possibleBackreference)) {
                             // Do we have a backreference which is a server or env var?
                             $value = str_replace($possibleBackreference, $backrefValue, $value);
                         } elseif (isset($conditionBackreferences[(int) substr($possibleBackreference, 1)])) {
                             // We got no backreference from any of the server or env vars, so maybe we got
                             // something from the preg_match
                             $value = str_replace($possibleBackreference, $conditionBackreferences[(int) substr($possibleBackreference, 1)], $value);
                         }
                     }
                 }
                 // If the value is "null" we will unset the variable
                 if ($value === 'null') {
                     // Unset the variable and continue with the next environment variable
                     if ($requestContext->hasEnvVar($varName)) {
                         $requestContext->unsetEnvVar($varName);
                     }
                     continue;
                 }
                 // Take action according to the needed definition
                 $requestContext->setEnvVar($varName, $value);
             }
         }
     } catch (\Exception $e) {
         // Re-throw as a ModuleException
         throw new ModuleException($e);
     }
 }