public function save(Object $obj, $file = NULL) {

    if (empty($this->token)) {
      throw new \HPCloud\Exception('Container does not have an auth token.');
    }
    if (empty($this->url)) {
      throw new \HPCloud\Exception('Container does not have a URL to send data.');
    }

    //$url = $this->url . '/' . rawurlencode($obj->name());
    $url = self::objectUrl($this->url, $obj->name());

    // See if we have any metadata.
    $headers = array();
    $md = $obj->metadata();
    if (!empty($md)) {
      $headers = self::generateMetadataHeaders($md, Container::METADATA_HEADER_PREFIX);
    }


    // Set the content type.
    $headers['Content-Type'] = $obj->contentType();


    // Add content encoding, if necessary.
    $encoding = $obj->encoding();
    if (!empty($encoding)) {
      $headers['Content-Encoding'] = rawurlencode($encoding);
    }

    // Add content disposition, if necessary.
    $disposition = $obj->disposition();
    if (!empty($disposition)) {
      $headers['Content-Disposition'] = $disposition;
    }

    // Auth token.
    $headers['X-Auth-Token'] = $this->token;

    // Add any custom headers:
    $moreHeaders = $obj->additionalHeaders();
    if (!empty($moreHeaders)) {
      $headers += $moreHeaders;
    }

    $client = \HPCloud\Transport::instance();

    if (empty($file)) {
      // Now build up the rest of the headers:
      $headers['Etag'] = $obj->eTag();

      // If chunked, we set transfer encoding; else
      // we set the content length.
      if ($obj->isChunked()) {
        // How do we handle this? Does the underlying
        // stream wrapper pay any attention to this?
        $headers['Transfer-Encoding'] = 'chunked';
      }
      else {
        $headers['Content-Length'] = $obj->contentLength();
      }
      $response = $client->doRequest($url, 'PUT', $headers, $obj->content());
    }
    else {
      // Rewind the file.
      rewind($file);


      // XXX: What do we do about Content-Length header?
      //$headers['Transfer-Encoding'] = 'chunked';
      $stat = fstat($file);
      $headers['Content-Length'] = $stat['size'];

      // Generate an eTag:
      $hash = hash_init('md5');
      hash_update_stream($hash, $file);
      $etag = hash_final($hash);
      $headers['Etag'] = $etag;

      // Not sure if this is necessary:
      rewind($file);

      $response = $client->doRequestWithResource($url, 'PUT', $headers, $file);

    }

    if ($response->status() != 201) {
      throw new \HPCloud\Exception('An unknown error occurred while saving: ' . $response->status());
    }
    return TRUE;
  }