|
21 | 21 |
|
22 | 22 | import com.google.common.collect.ImmutableList;
|
23 | 23 | import com.google.common.collect.Iterables;
|
| 24 | +import com.google.common.collect.Lists; |
24 | 25 | import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials;
|
25 | 26 | import com.google.gcloud.Service;
|
26 | 27 | import com.google.gcloud.spi.StorageRpc;
|
| 28 | +import com.google.gcloud.spi.StorageRpc.Tuple; |
27 | 29 |
|
28 | 30 | import java.io.InputStream;
|
29 | 31 | import java.io.Serializable;
|
|
33 | 35 | import java.util.LinkedHashSet;
|
34 | 36 | import java.util.LinkedList;
|
35 | 37 | import java.util.List;
|
| 38 | +import java.util.Objects; |
36 | 39 | import java.util.Set;
|
37 | 40 | import java.util.concurrent.TimeUnit;
|
38 | 41 |
|
@@ -146,65 +149,103 @@ public static BlobTargetOption metagenerationNotMatch() {
|
146 | 149 | return new BlobTargetOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH);
|
147 | 150 | }
|
148 | 151 |
|
149 |
| - static BlobWriteOption[] convert(BlobTargetOption[] options, BlobWriteOption... optionsToAdd) { |
150 |
| - BlobWriteOption[] writeOptions = new BlobWriteOption[options.length + optionsToAdd.length]; |
151 |
| - int index = 0; |
152 |
| - for (BlobTargetOption option : options) { |
153 |
| - writeOptions[index++] = new BlobWriteOption(option); |
154 |
| - } |
155 |
| - for (BlobWriteOption option : optionsToAdd) { |
156 |
| - writeOptions[index++] = option; |
| 152 | + static Tuple<BlobInfo, BlobTargetOption[]> convert(BlobInfo info, BlobWriteOption... options) { |
| 153 | + BlobInfo.Builder infoBuilder = info.toBuilder().crc32c(null).md5(null); |
| 154 | + List<BlobTargetOption> targetOptions = Lists.newArrayListWithCapacity(options.length); |
| 155 | + for (BlobWriteOption option : options) { |
| 156 | + switch (option.option) { |
| 157 | + case IF_CRC32C_MATCH: |
| 158 | + infoBuilder.crc32c(info.crc32c()); |
| 159 | + break; |
| 160 | + case IF_MD5_MATCH: |
| 161 | + infoBuilder.md5(info.md5()); |
| 162 | + break; |
| 163 | + default: |
| 164 | + targetOptions.add(option.toTargetOption()); |
| 165 | + break; |
| 166 | + } |
157 | 167 | }
|
158 |
| - return writeOptions; |
| 168 | + return Tuple.of(infoBuilder.build(), |
| 169 | + targetOptions.toArray(new BlobTargetOption[targetOptions.size()])); |
159 | 170 | }
|
160 | 171 | }
|
161 | 172 |
|
162 |
| - class BlobWriteOption extends Option { |
| 173 | + class BlobWriteOption implements Serializable { |
163 | 174 |
|
164 | 175 | private static final long serialVersionUID = -3880421670966224580L;
|
165 | 176 |
|
166 |
| - BlobWriteOption(BlobTargetOption option) { |
167 |
| - super(option.rpcOption(), option.value()); |
| 177 | + private final Option option; |
| 178 | + private final Object value; |
| 179 | + |
| 180 | + enum Option { |
| 181 | + PREDEFINED_ACL, IF_GENERATION_MATCH, IF_GENERATION_NOT_MATCH, IF_METAGENERATION_MATCH, |
| 182 | + IF_METAGENERATION_NOT_MATCH, IF_MD5_MATCH, IF_CRC32C_MATCH; |
| 183 | + |
| 184 | + StorageRpc.Option toRpcOption() { |
| 185 | + return StorageRpc.Option.valueOf(this.name()); |
| 186 | + } |
168 | 187 | }
|
169 | 188 |
|
170 |
| - private BlobWriteOption(StorageRpc.Option rpcOption, Object value) { |
171 |
| - super(rpcOption, value); |
| 189 | + BlobTargetOption toTargetOption() { |
| 190 | + return new BlobTargetOption(this.option.toRpcOption(), this.value); |
172 | 191 | }
|
173 | 192 |
|
174 |
| - private BlobWriteOption(StorageRpc.Option rpcOption) { |
175 |
| - this(rpcOption, null); |
| 193 | + private BlobWriteOption(Option option, Object value) { |
| 194 | + this.option = option; |
| 195 | + this.value = value; |
| 196 | + } |
| 197 | + |
| 198 | + private BlobWriteOption(Option option) { |
| 199 | + this(option, null); |
| 200 | + } |
| 201 | + |
| 202 | + @Override |
| 203 | + public int hashCode() { |
| 204 | + return Objects.hash(option, value); |
| 205 | + } |
| 206 | + |
| 207 | + @Override |
| 208 | + public boolean equals(Object obj) { |
| 209 | + if (obj == null) { |
| 210 | + return false; |
| 211 | + } |
| 212 | + if (!(obj instanceof BlobWriteOption)) { |
| 213 | + return false; |
| 214 | + } |
| 215 | + final BlobWriteOption other = (BlobWriteOption) obj; |
| 216 | + return this.option == other.option && Objects.equals(this.value, other.value); |
176 | 217 | }
|
177 | 218 |
|
178 | 219 | public static BlobWriteOption predefinedAcl(PredefinedAcl acl) {
|
179 |
| - return new BlobWriteOption(StorageRpc.Option.PREDEFINED_ACL, acl.entry()); |
| 220 | + return new BlobWriteOption(Option.PREDEFINED_ACL, acl.entry()); |
180 | 221 | }
|
181 | 222 |
|
182 | 223 | public static BlobWriteOption doesNotExist() {
|
183 |
| - return new BlobWriteOption(StorageRpc.Option.IF_GENERATION_MATCH, 0L); |
| 224 | + return new BlobWriteOption(Option.IF_GENERATION_MATCH, 0L); |
184 | 225 | }
|
185 | 226 |
|
186 | 227 | public static BlobWriteOption generationMatch() {
|
187 |
| - return new BlobWriteOption(StorageRpc.Option.IF_GENERATION_MATCH); |
| 228 | + return new BlobWriteOption(Option.IF_GENERATION_MATCH); |
188 | 229 | }
|
189 | 230 |
|
190 | 231 | public static BlobWriteOption generationNotMatch() {
|
191 |
| - return new BlobWriteOption(StorageRpc.Option.IF_GENERATION_NOT_MATCH); |
| 232 | + return new BlobWriteOption(Option.IF_GENERATION_NOT_MATCH); |
192 | 233 | }
|
193 | 234 |
|
194 | 235 | public static BlobWriteOption metagenerationMatch() {
|
195 |
| - return new BlobWriteOption(StorageRpc.Option.IF_METAGENERATION_MATCH); |
| 236 | + return new BlobWriteOption(Option.IF_METAGENERATION_MATCH); |
196 | 237 | }
|
197 | 238 |
|
198 | 239 | public static BlobWriteOption metagenerationNotMatch() {
|
199 |
| - return new BlobWriteOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH); |
| 240 | + return new BlobWriteOption(Option.IF_METAGENERATION_NOT_MATCH); |
200 | 241 | }
|
201 | 242 |
|
202 | 243 | public static BlobWriteOption md5Match() {
|
203 |
| - return new BlobWriteOption(StorageRpc.Option.IF_MD5_MATCH, true); |
| 244 | + return new BlobWriteOption(Option.IF_MD5_MATCH, true); |
204 | 245 | }
|
205 | 246 |
|
206 | 247 | public static BlobWriteOption crc32cMatch() {
|
207 |
| - return new BlobWriteOption(StorageRpc.Option.IF_CRC32C_MATCH, true); |
| 248 | + return new BlobWriteOption(Option.IF_CRC32C_MATCH, true); |
208 | 249 | }
|
209 | 250 | }
|
210 | 251 |
|
@@ -582,7 +623,9 @@ public static Builder builder() {
|
582 | 623 |
|
583 | 624 | /**
|
584 | 625 | * Create a new blob. Direct upload is used to upload {@code content}. For large content,
|
585 |
| - * {@link #writer} is recommended as it uses resumable upload. |
| 626 | + * {@link #writer} is recommended as it uses resumable upload. By default any md5 and crc32c |
| 627 | + * values in the given {@code blobInfo} are ignored unless requested via the |
| 628 | + * {@code BlobWriteOption.md5Match} and {@code BlobWriteOption.crc32cMatch} options. |
586 | 629 | *
|
587 | 630 | * @return a complete blob information.
|
588 | 631 | * @throws StorageException upon failure
|
@@ -742,7 +785,9 @@ public static Builder builder() {
|
742 | 785 | BlobReadChannel reader(BlobId blob, BlobSourceOption... options);
|
743 | 786 |
|
744 | 787 | /**
|
745 |
| - * Create a blob and return a channel for writing its content. |
| 788 | + * Create a blob and return a channel for writing its content. By default any md5 and crc32c |
| 789 | + * values in the given {@code blobInfo} are ignored unless requested via the |
| 790 | + * {@code BlobWriteOption.md5Match} and {@code BlobWriteOption.crc32cMatch} options. |
746 | 791 | *
|
747 | 792 | * @throws StorageException upon failure
|
748 | 793 | */
|
|
0 commit comments