/**
  * Run the PHP SoapServer
  * 
  * @param string $wsdlFile The WSDL file name or NULL to let PhpWsdl decide (default: NULL)
  * @param string|object|array $class The class name to serve, the classname and class as array or NULL (default: NULL)
  * @param boolean $andExit Exit after running the server? (default: TRUE)
  * @param boolean $forceNoWsdl Force no WSDL usage? (default: FALSE);
  * @return boolean Did the server run?
  */
 public function RunServer($wsdlFile = null, $class = null, $andExit = true, $forceNoWsdl = false)
 {
     self::Debug('Run the server');
     if ($forceNoWsdl) {
         self::Debug('Forced non-WSDL mode');
     }
     if (self::CallHook('BeforeRunServerHook', array('server' => $this, 'wsdlfile' => &$wsdlFile, 'class' => &$class, 'andexit' => &$andExit, 'forcenowsdl' => &$forceNoWsdl))) {
         // WSDL requested?
         if ($this->OutputWsdlOnRequest($andExit)) {
             return false;
         }
         // PHP requested?
         if ($this->OutputPhpOnRequest($andExit)) {
             return false;
         }
         // HTML requested?
         if ($this->OutputHtmlOnRequest($andExit)) {
             return false;
         }
     }
     // Login
     $user = null;
     $password = null;
     if ($this->RequireLogin) {
         if (isset($_SERVER['PHP_AUTH_USER']) || isset($_SERVER['PHP_AUTH_PW'])) {
             $user = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null;
             $password = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null;
         }
         self::Debug('Check login ' . $user . ':' . str_repeat('*', strlen($password)));
         if (!self::CallHook('LoginHook', array('server' => $this, 'user' => &$user, 'password' => &$password))) {
             self::Debug('Login required');
             header('WWW-Authenticate: Basic realm="SOAP webservice login required"');
             header('HTTP/1.0 401 Unauthorized');
             if ($andExit) {
                 self::Debug('Exit script execution');
                 exit;
             }
             return false;
         }
     }
     // Load the proxy
     $useProxy = false;
     if (is_array($class)) {
         self::Debug('Use the proxy for ' . $class[0]);
         self::$ProxyObject = $class[1];
         self::$ProxyServer = $this;
         $class = $class[0];
         $useProxy = true;
     }
     // Ensure a webservice name
     if (is_null($class)) {
         self::Debug('No webservice name yet');
         if (!$this->DetermineConfiguration()) {
             throw new Exception('Invalid configuration');
         }
         if (!is_null($this->Name)) {
             $class = $this->Name;
         }
     } else {
         if (is_string($class)) {
             self::Debug('Using ' . $class . ' as webservice name');
             $this->Name = $class;
         }
     }
     self::Debug('Use class ' . (!is_object($class) ? $class : get_class($class)));
     // Load WSDL
     if (!$forceNoWsdl && (!$useProxy || self::$UseProxyWsdl)) {
         self::Debug('Load WSDL');
         $this->CreateWsdl(false, true);
         if (is_null($wsdlFile)) {
             $wsdlFile = $this->GetCacheFileName();
         }
         if (!is_null($wsdlFile)) {
             if (!file_exists($wsdlFile)) {
                 self::Debug('WSDL file "' . $wsdlFile . '" does not exists');
                 $wsdlFile = null;
             }
         }
     }
     // Load the files, if the webservice handler class doesn't exist
     if (!is_object($class)) {
         if (!class_exists($class) && !$this->IsOnlyGlobal()) {
             self::Debug('Try to load the webservice handler class');
             $i = -1;
             $len = sizeof($this->Files);
             while (++$i < $len) {
                 self::Debug('Load ' . $this->Files[$i]);
                 require_once $this->Files[$i];
             }
             if (!class_exists($class)) {
                 // Try class.webservice.php
                 if (file_exists('class.webservice.php')) {
                     self::Debug('Try to load class.webservice.php');
                     require_once 'class.webservice.php';
                     if (class_exists($class)) {
                         $this->Files[] = 'class.webservice.php';
                     }
                 }
                 if (!class_exists($class)) {
                     if (file_exists(dirname(__FILE__) . '/class.webservice.php')) {
                         self::Debug('Try to load ' . dirname(__FILE__) . '/class.webservice.php');
                         require_once dirname(__FILE__) . '/class.webservice.php';
                         if (class_exists($class)) {
                             $this->Files[] = dirname(__FILE__) . '/class.webservice.php';
                         }
                     }
                 }
                 if (!class_exists($class)) {
                     // A handler class or object is required when using non-global methods!
                     throw new Exception('Webservice handler class not present');
                 }
             }
         }
     }
     // Prepare the SOAP server
     $this->SoapServer = null;
     if (self::CallHook('PrepareServerHook', array('server' => $this, 'soapserver' => &$this->SoapServer, 'wsdlfile' => &$wsdlFile, 'class' => &$class, 'useproxy' => &$useProxy, 'forcenowsdl' => &$forceNoWsdl, 'andexit' => &$andExit, 'user' => &$user, 'password' => &$password))) {
         self::Debug('Prepare the SOAP server');
         // WSDL file
         $wsdlFile = $forceNoWsdl || $useProxy && !self::$UseProxyWsdl ? null : $wsdlFile;
         if (!is_null($wsdlFile)) {
             self::Debug('Using WSDL file ' . $wsdlFile);
         } else {
             self::Debug('No WSDL file');
         }
         // Server options
         $temp = array('actor' => $this->EndPoint, 'uri' => $this->NameSpace);
         $temp = array_merge($this->SoapServerOptions, $temp);
         if (self::$Debugging) {
             self::Debug('Server options: ' . print_r($temp, true));
         }
         // Create the server object
         self::Debug('Creating PHP SoapServer object');
         $this->SoapServer = new SoapServer($wsdlFile, $temp);
         // Set the handler class or object
         if ($useProxy || !is_object($class)) {
             $temp = $useProxy ? 'PhpWsdlProxy' : $class;
             if (!is_null($temp)) {
                 self::Debug('Setting server class ' . $temp);
                 $this->SoapServer->setClass($temp);
             } else {
                 self::Debug('No server class or object');
             }
         } else {
             self::Debug('Setting server object ' . get_class($class));
             $this->SoapServer->setObject($class);
         }
         // Add global methods
         $i = -1;
         $len = sizeof($this->Methods);
         while (++$i < $len) {
             if ($this->Methods[$i]->IsGlobal) {
                 self::Debug('Adding global method ' . $this->Methods[$i]->Name);
                 $this->SoapServer->addFunction($this->Methods[$i]->Name);
             }
         }
     }
     // Run the SOAP server
     if (self::CallHook('RunServerHook', array('server' => $this, 'soapserver' => &$this->SoapServer, 'wsdlfile' => &$wsdlFile, 'class' => &$class, 'useproxy' => &$useProxy, 'forcenowsdl' => &$forceNoWsdl, 'andexit' => &$andExit, 'user' => &$user, 'password' => &$password))) {
         self::Debug('Run the SOAP server');
         $this->SoapServer->handle();
         if ($andExit) {
             self::Debug('Exit script execution');
             exit;
         }
     }
     return true;
 }