@@ -904,7 +904,7 @@ public boolean deleteAcl(String bucket, Entity entity, BucketSourceOption... opt
904
904
}
905
905
long metageneration = resp .getMetageneration ();
906
906
907
- UpdateBucketRequest req = createUpdateAclRequest (bucket , newAcls , metageneration );
907
+ UpdateBucketRequest req = createUpdateBucketAclRequest (bucket , newAcls , metageneration );
908
908
909
909
com .google .storage .v2 .Bucket updateResult = updateBucket (req );
910
910
// read the response to ensure there is no longer an acl for the specified entity
@@ -954,7 +954,7 @@ public Acl updateAcl(String bucket, Acl acl, BucketSourceOption... options) {
954
954
.collect (ImmutableList .toImmutableList ());
955
955
956
956
UpdateBucketRequest req =
957
- createUpdateAclRequest (bucket , newDefaultAcls , resp .getMetageneration ());
957
+ createUpdateBucketAclRequest (bucket , newDefaultAcls , resp .getMetageneration ());
958
958
959
959
com .google .storage .v2 .Bucket updateResult = updateBucket (req );
960
960
@@ -1109,27 +1109,117 @@ public List<Acl> listDefaultAcls(String bucket) {
1109
1109
1110
1110
@ Override
1111
1111
public Acl getAcl (BlobId blob , Entity entity ) {
1112
- return throwNotYetImplemented (fmtMethodName ("getAcl" , BlobId .class , Entity .class ));
1112
+ try {
1113
+ Object req = codecs .blobId ().encode (blob );
1114
+ Object resp = getObjectWithAcls (req );
1115
+
1116
+ Predicate <ObjectAccessControl > entityPredicate =
1117
+ objectAclEntityOrAltEq (codecs .entity ().encode (entity ));
1118
+
1119
+ Optional <ObjectAccessControl > first =
1120
+ resp .getAclList ().stream ().filter (entityPredicate ).findFirst ();
1121
+
1122
+ // HttpStorageRpc defaults to null if Not Found
1123
+ return first .map (codecs .objectAcl ()::decode ).orElse (null );
1124
+ } catch (NotFoundException e ) {
1125
+ return null ;
1126
+ } catch (StorageException se ) {
1127
+ if (se .getCode () == 404 ) {
1128
+ return null ;
1129
+ } else {
1130
+ throw se ;
1131
+ }
1132
+ }
1113
1133
}
1114
1134
1115
1135
@ Override
1116
1136
public boolean deleteAcl (BlobId blob , Entity entity ) {
1117
- return throwNotYetImplemented (fmtMethodName ("deleteAcl" , BlobId .class , Entity .class ));
1137
+ try {
1138
+ Object obj = codecs .blobId ().encode (blob );
1139
+ Object resp = getObjectWithAcls (obj );
1140
+ String encode = codecs .entity ().encode (entity );
1141
+
1142
+ Predicate <ObjectAccessControl > entityPredicate = objectAclEntityOrAltEq (encode );
1143
+
1144
+ List <ObjectAccessControl > currentDefaultAcls = resp .getAclList ();
1145
+ ImmutableList <ObjectAccessControl > newDefaultAcls =
1146
+ currentDefaultAcls .stream ()
1147
+ .filter (entityPredicate .negate ())
1148
+ .collect (ImmutableList .toImmutableList ());
1149
+ if (newDefaultAcls .equals (currentDefaultAcls )) {
1150
+ // we didn't actually filter anything out, no need to send an RPC, simply return false
1151
+ return false ;
1152
+ }
1153
+ long metageneration = resp .getMetageneration ();
1154
+
1155
+ UpdateObjectRequest req = createUpdateObjectAclRequest (obj , newDefaultAcls , metageneration );
1156
+
1157
+ Object updateResult = updateObject (req );
1158
+ // read the response to ensure there is no longer an acl for the specified entity
1159
+ Optional <ObjectAccessControl > first =
1160
+ updateResult .getAclList ().stream ().filter (entityPredicate ).findFirst ();
1161
+ return !first .isPresent ();
1162
+ } catch (NotFoundException e ) {
1163
+ // HttpStorageRpc returns false if the bucket doesn't exist :(
1164
+ return false ;
1165
+ } catch (StorageException se ) {
1166
+ if (se .getCode () == 404 ) {
1167
+ return false ;
1168
+ } else {
1169
+ throw se ;
1170
+ }
1171
+ }
1118
1172
}
1119
1173
1120
1174
@ Override
1121
1175
public Acl createAcl (BlobId blob , Acl acl ) {
1122
- return throwNotYetImplemented ( fmtMethodName ( "createAcl" , BlobId . class , Acl . class ) );
1176
+ return updateAcl ( blob , acl );
1123
1177
}
1124
1178
1125
1179
@ Override
1126
1180
public Acl updateAcl (BlobId blob , Acl acl ) {
1127
- return throwNotYetImplemented (fmtMethodName ("updateAcl" , BlobId .class , Acl .class ));
1181
+ try {
1182
+ Object obj = codecs .blobId ().encode (blob );
1183
+ Object resp = getObjectWithAcls (obj );
1184
+ ObjectAccessControl encode = codecs .objectAcl ().encode (acl );
1185
+ String entity = encode .getEntity ();
1186
+
1187
+ Predicate <ObjectAccessControl > entityPredicate = objectAclEntityOrAltEq (entity );
1188
+
1189
+ ImmutableList <ObjectAccessControl > newDefaultAcls =
1190
+ Streams .concat (
1191
+ resp .getAclList ().stream ().filter (entityPredicate .negate ()), Stream .of (encode ))
1192
+ .collect (ImmutableList .toImmutableList ());
1193
+
1194
+ UpdateObjectRequest req =
1195
+ createUpdateObjectAclRequest (obj , newDefaultAcls , resp .getMetageneration ());
1196
+
1197
+ Object updateResult = updateObject (req );
1198
+
1199
+ Optional <Acl > first =
1200
+ updateResult .getAclList ().stream ()
1201
+ .filter (entityPredicate )
1202
+ .findFirst ()
1203
+ .map (codecs .objectAcl ()::decode );
1204
+
1205
+ return first .orElseThrow (
1206
+ () -> new StorageException (0 , "Acl update call success, but not in response" ));
1207
+ } catch (NotFoundException e ) {
1208
+ throw StorageException .coalesce (e );
1209
+ }
1128
1210
}
1129
1211
1130
1212
@ Override
1131
1213
public List <Acl > listAcls (BlobId blob ) {
1132
- return throwNotYetImplemented (fmtMethodName ("listAcls" , BlobId .class ));
1214
+ try {
1215
+ Object req = codecs .blobId ().encode (blob );
1216
+ Object resp = getObjectWithAcls (req );
1217
+ return resp .getAclList ().stream ()
1218
+ .map (codecs .objectAcl ()::decode )
1219
+ .collect (ImmutableList .toImmutableList ());
1220
+ } catch (NotFoundException e ) {
1221
+ throw StorageException .coalesce (e );
1222
+ }
1133
1223
}
1134
1224
1135
1225
@ Override
@@ -1637,7 +1727,7 @@ private static UpdateBucketRequest createUpdateDefaultAclRequest(
1637
1727
.build ();
1638
1728
}
1639
1729
1640
- private static UpdateBucketRequest createUpdateAclRequest (
1730
+ private static UpdateBucketRequest createUpdateBucketAclRequest (
1641
1731
String bucket , ImmutableList <BucketAccessControl > newDefaultAcls , long metageneration ) {
1642
1732
com .google .storage .v2 .Bucket update =
1643
1733
com .google .storage .v2 .Bucket .newBuilder ()
@@ -1653,4 +1743,50 @@ private static UpdateBucketRequest createUpdateAclRequest(
1653
1743
.setBucket (update )
1654
1744
.build ();
1655
1745
}
1746
+
1747
+ private Object getObjectWithAcls (Object obj ) {
1748
+ Fields fields =
1749
+ UnifiedOpts .fields (ImmutableSet .of (BucketField .ACL , BucketField .METAGENERATION ));
1750
+ GrpcCallContext grpcCallContext = GrpcCallContext .createDefault ();
1751
+ GetObjectRequest req =
1752
+ fields
1753
+ .getObject ()
1754
+ .apply (GetObjectRequest .newBuilder ())
1755
+ .setBucket (obj .getBucket ())
1756
+ .setObject (obj .getName ())
1757
+ .build ();
1758
+
1759
+ return Retrying .run (
1760
+ getOptions (),
1761
+ retryAlgorithmManager .getFor (req ),
1762
+ () -> storageClient .getObjectCallable ().call (req , grpcCallContext ),
1763
+ Decoder .identity ());
1764
+ }
1765
+
1766
+ private static UpdateObjectRequest createUpdateObjectAclRequest (
1767
+ Object obj , ImmutableList <ObjectAccessControl > newAcls , long metageneration ) {
1768
+ Object update =
1769
+ Object .newBuilder ()
1770
+ .setBucket (obj .getBucket ())
1771
+ .setName (obj .getName ())
1772
+ .addAllAcl (newAcls )
1773
+ .build ();
1774
+ Opts <BucketTargetOpt > opts =
1775
+ Opts .from (
1776
+ UnifiedOpts .fields (ImmutableSet .of (BlobField .ACL )),
1777
+ UnifiedOpts .metagenerationMatch (metageneration ));
1778
+ return opts .updateObjectsRequest ()
1779
+ .apply (UpdateObjectRequest .newBuilder ())
1780
+ .setObject (update )
1781
+ .build ();
1782
+ }
1783
+
1784
+ private Object updateObject (UpdateObjectRequest req ) {
1785
+ GrpcCallContext grpcCallContext = GrpcCallContext .createDefault ();
1786
+ return Retrying .run (
1787
+ getOptions (),
1788
+ retryAlgorithmManager .getFor (req ),
1789
+ () -> storageClient .updateObjectCallable ().call (req , grpcCallContext ),
1790
+ Decoder .identity ());
1791
+ }
1656
1792
}
0 commit comments