public function run(array $args)
    {
        $prog = array_shift($args);
        try {
            list($options, $params) = $this->parse($args);
        } catch (\Exception $e) {
            fprintf(STDERR, '%s: %s' . PHP_EOL, $prog, $e->getMessage());
            return 2;
        }

        // Show help.
        if ($options['h']) {
            $this->printUsage(new \fpoirotte\XRL\Output(STDOUT), $prog);
            return 0;
        }

        // Show version.
        if ($options['V']) {
            $version = self::getVersion();
            $license = self::getCopyrightAndLicense();
            echo 'XRL version ' . $version . PHP_EOL;
            echo PHP_EOL . $license . PHP_EOL;
            echo 'Visit https://github.com/fpoirotte/XRL for more!' . PHP_EOL;
            return 0;
        }

        // Do we have enough arguments to do something?
        if ($params['serverURL'] === null || $params['procedure'] === null) {
            $this->printUsage(new \fpoirotte\XRL\Output(STDERR), $prog);
            return 2;
        }

        // Then let's do it!
        $encoder    = new \fpoirotte\XRL\NativeEncoder(new \fpoirotte\XRL\Encoder($options['t'], true));
        $decoder    = new \fpoirotte\XRL\NativeDecoder(new \fpoirotte\XRL\Decoder($options['t'], $options['x']));
        $request    = new \fpoirotte\XRL\Request($params['procedure'], $params['additional']);

        // Change verbosity as necessary.
        if (class_exists('\\Plop\\Plop')) {
            $logging = \Plop\Plop::getInstance();
            $logging->getLogger()->setLevel(40 - min(4, $options['v']) * 10);
        } else {
            $logging = null;
        }

        // Prepare the request.
        $xml = $encoder->encodeRequest($request);
        $logging and $logging->debug(
            "Request:\n%(request)s",
            array('request' => $xml)
        );
        if ($options['n']) {
            echo 'Not sending the actual query due to dry run mode.' . PHP_EOL;
            return 0;
        }

        $headers    = array(
            'Content-Type: text/xml',
            'User-Agent: XRL/' . static::getVersion(),
        );

        // Prepare the context.
        $ctxOptions = array(
            'http' => array(
                'method'    => 'POST',
                'content'   => $xml,
                'header'    => $headers,
            ),
        );
        $context = stream_context_create($ctxOptions);
        libxml_set_streams_context($context);

        // Send the request and process the response.
        try {
            $result = $decoder->decodeResponse($params['serverURL']);
        } catch (\Exception $result) {
            // Nothing to do.
        }

        echo 'Result:' . PHP_EOL . print_r($result, true) . PHP_EOL;
        return 0;
    }