3 * Copyright 2007 Google Inc.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 * Cloud Storage Rename Client handles rename() calls for renaming a GCS object.
22 namespace google\appengine\ext\cloud_storage_streams
;
25 * Client for deleting objects from Google Cloud Storage.
27 final class CloudStorageRenameClient
extends CloudStorageClient
{
33 public function __construct($from_bucket,
38 parent
::__construct($from_bucket, $from_object, $context);
40 $this->from_bucket
= $from_bucket;
41 $this->from_object
= $from_object;
42 $this->to_bucket
= $to_bucket;
43 $this->to_object
= $to_object;
47 * Perform the actual rename of a GCS storage object.
48 * Renaming an object has the following steps.
49 * 1. stat the 'from' object to get the ETag and content type.
50 * 2. Use x-goog-copy-source-if-match to copy the object.
51 * 3. Delete the original object.
53 public function rename() {
54 $token_header = $this->getOAuthTokenHeader(parent
::WRITE_SCOPE
);
55 if ($token_header === false) {
57 trigger_error("Unable to acquire OAuth token.", E_USER_WARNING
);
62 // Stat the from object to get the etag and content-type
63 $http_response = $this->makeHttpRequest($this->url
, "HEAD", $token_header);
64 if ($http_response === false) {
65 trigger_error("Unable to connect to Google Cloud Storage Service.",
69 $status_code = $http_response['status_code'];
71 if ($status_code != HttpResponse
::OK
) {
72 trigger_error(sprintf("Unable to rename: %s. Cloud Storage Error: %s",
76 HttpResponse
::getStatusMessage($status_code)),
81 $from_etag = $this->getHeaderValue('ETag', $http_response['headers']);
82 $content_type = $this->getHeaderValue('Content-Type',
83 $http_response['headers']);
86 'x-goog-copy-source' =>
87 sprintf("/%s%s", $this->from_bucket
, $this->from_object
),
88 'x-goog-copy-source-if-match' => $from_etag,
91 if (array_key_exists('Content-Type', $this->context_options
)) {
92 $copy_headers['content-type'] = $this->context_options
['Content-Type'];
94 $copy_headers['content-type'] = $content_type;
97 if (array_key_exists('metadata', $this->context_options
)) {
98 $copy_headers['x-goog-metadata-directive'] = 'REPLACE';
99 foreach ($this->context_options
['metadata'] as $key => $val) {
100 $copy_headers['x-goog-meta-' . $key] = $val;
103 $copy_headers['x-goog-metadata-directive'] = 'COPY';
106 if (array_key_exists("acl", $this->context_options
)) {
107 $acl = $this->context_options
["acl"];
108 if (in_array($acl, parent
::$valid_acl_values)) {
109 $copy_headers["x-goog-acl"] = $acl;
111 trigger_error(sprintf("Invalid ACL value: %s", $acl), E_USER_WARNING
);
116 $to_url = $this->createObjectUrl($this->to_bucket
, $this->to_object
);
117 $http_response = $this->makeHttpRequest($to_url, "PUT",
118 array_merge($token_header, $copy_headers));
120 if ($http_response === false) {
121 trigger_error("Unable to copy source to destination.", E_USER_WARNING
);
125 $status_code = $http_response['status_code'];
126 if ($status_code != HttpResponse
::OK
) {
127 trigger_error(sprintf("Error copying to %s. Cloud Storage Error: %s",
131 HttpResponse
::getStatusMessage($status_code)),
135 // Unlink the original file.
136 $http_response = $this->makeHttpRequest($this->url
,
140 if ($http_response === false) {
141 trigger_error("Failed to delete the from cloud storage object.",
146 $status_code = $http_response['status_code'];
147 if ($status_code !== HttpResponse
::NO_CONTENT
) {
148 trigger_error(sprintf("Unable to unlink: %s. Cloud Storage Error: %s",
152 HttpResponse
::getStatusMessage($status_code)),