91
91
import java .util .concurrent .TimeoutException ;
92
92
import java .util .function .Function ;
93
93
import java .util .function .Supplier ;
94
+ import org .checkerframework .checker .nullness .qual .NonNull ;
94
95
import org .checkerframework .checker .nullness .qual .Nullable ;
95
96
96
97
final class StorageImpl extends BaseService <StorageOptions > implements Storage , StorageInternal {
@@ -147,7 +148,8 @@ public Blob create(BlobInfo blobInfo, BlobTargetOption... options) {
147
148
.setMd5 (EMPTY_BYTE_ARRAY_MD5 )
148
149
.setCrc32c (EMPTY_BYTE_ARRAY_CRC32C )
149
150
.build ();
150
- return internalCreate (updatedInfo , EMPTY_BYTE_ARRAY , 0 , 0 , options );
151
+ final Opts <ObjectTargetOpt > objectTargetOptOpts = Opts .unwrap (options ).resolveFrom (updatedInfo );
152
+ return internalCreate (updatedInfo , EMPTY_BYTE_ARRAY , 0 , 0 , objectTargetOptOpts );
151
153
}
152
154
153
155
@ Override
@@ -161,7 +163,8 @@ public Blob create(BlobInfo blobInfo, byte[] content, BlobTargetOption... option
161
163
BaseEncoding .base64 ()
162
164
.encode (Ints .toByteArray (Hashing .crc32c ().hashBytes (content ).asInt ())))
163
165
.build ();
164
- return internalCreate (updatedInfo , content , 0 , content .length , options );
166
+ final Opts <ObjectTargetOpt > objectTargetOptOpts = Opts .unwrap (options ).resolveFrom (updatedInfo );
167
+ return internalCreate (updatedInfo , content , 0 , content .length , objectTargetOptOpts );
165
168
}
166
169
167
170
@ Override
@@ -180,7 +183,8 @@ public Blob create(
180
183
Ints .toByteArray (
181
184
Hashing .crc32c ().hashBytes (content , offset , length ).asInt ())))
182
185
.build ();
183
- return internalCreate (updatedInfo , content , offset , length , options );
186
+ final Opts <ObjectTargetOpt > objectTargetOptOpts = Opts .unwrap (options ).resolveFrom (updatedInfo );
187
+ return internalCreate (updatedInfo , content , offset , length , objectTargetOptOpts );
184
188
}
185
189
186
190
@ Override
@@ -203,12 +207,11 @@ public Blob create(BlobInfo blobInfo, InputStream content, BlobWriteOption... op
203
207
204
208
private Blob internalCreate (
205
209
BlobInfo info ,
206
- final byte [] content ,
210
+ final byte @ NonNull [] content ,
207
211
final int offset ,
208
212
final int length ,
209
- BlobTargetOption ... options ) {
213
+ Opts < ObjectTargetOpt > opts ) {
210
214
Preconditions .checkNotNull (content );
211
- Opts <ObjectTargetOpt > opts = Opts .unwrap (options ).resolveFrom (info );
212
215
final Map <StorageRpc .Option , ?> optionsMap = opts .getRpcOptions ();
213
216
214
217
BlobInfo updated = opts .blobInfoMapper ().apply (info .toBuilder ()).build ();
@@ -1647,4 +1650,48 @@ public BlobWriteSession blobWriteSession(BlobInfo blobInfo, BlobWriteOption... o
1647
1650
writerFactory .writeSession (this , blobInfo , opts );
1648
1651
return BlobWriteSessions .of (writableByteChannelSession );
1649
1652
}
1653
+
1654
+ @ Override
1655
+ public BlobInfo internalCreateFrom (Path path , BlobInfo info , Opts <ObjectTargetOpt > opts )
1656
+ throws IOException {
1657
+ if (Files .isDirectory (path )) {
1658
+ throw new StorageException (0 , path + " is a directory" );
1659
+ }
1660
+ long size = Files .size (path );
1661
+ if (size == 0L ) {
1662
+ return internalCreate (info , EMPTY_BYTE_ARRAY , 0 , 0 , opts );
1663
+ }
1664
+ final Map <StorageRpc .Option , ?> optionsMap = opts .getRpcOptions ();
1665
+ BlobInfo .Builder builder = info .toBuilder ().setMd5 (null ).setCrc32c (null );
1666
+ BlobInfo updated = opts .blobInfoMapper ().apply (builder ).build ();
1667
+ StorageObject encode = codecs .blobInfo ().encode (updated );
1668
+
1669
+ Supplier <String > uploadIdSupplier =
1670
+ ResumableMedia .startUploadForBlobInfo (
1671
+ getOptions (),
1672
+ updated ,
1673
+ optionsMap ,
1674
+ retryAlgorithmManager .getForResumableUploadSessionCreate (optionsMap ));
1675
+ JsonResumableWrite jsonResumableWrite =
1676
+ JsonResumableWrite .of (encode , optionsMap , uploadIdSupplier .get (), 0 );
1677
+
1678
+ JsonResumableSession session =
1679
+ ResumableSession .json (
1680
+ HttpClientContext .from (storageRpc ),
1681
+ getOptions ().asRetryDependencies (),
1682
+ retryAlgorithmManager .idempotent (),
1683
+ jsonResumableWrite );
1684
+ HttpContentRange contentRange =
1685
+ HttpContentRange .of (ByteRangeSpec .relativeLength (0L , size ), size );
1686
+ ResumableOperationResult <StorageObject > put =
1687
+ session .put (RewindableContent .of (path ), contentRange );
1688
+ // all exception translation is taken care of down in the JsonResumableSession
1689
+ StorageObject object = put .getObject ();
1690
+ if (object == null ) {
1691
+ // if by some odd chance the put didn't get the StorageObject, query for it
1692
+ ResumableOperationResult <StorageObject > query = session .query ();
1693
+ object = query .getObject ();
1694
+ }
1695
+ return codecs .blobInfo ().decode (object );
1696
+ }
1650
1697
}
0 commit comments