20
20
import com .google .cloud .AuthCredentials .ServiceAccountAuthCredentials ;
21
21
import com .google .cloud .ReadChannel ;
22
22
import com .google .cloud .WriteChannel ;
23
+ import com .google .cloud .examples .compute .ComputeExample ;
24
+ import com .google .cloud .storage .Acl ;
23
25
import com .google .cloud .storage .Blob ;
24
26
import com .google .cloud .storage .BlobId ;
25
27
import com .google .cloud .storage .BlobInfo ;
30
32
import com .google .cloud .storage .Storage .CopyRequest ;
31
33
import com .google .cloud .storage .Storage .SignUrlOption ;
32
34
import com .google .cloud .storage .StorageOptions ;
35
+ import com .google .cloud .storage .spi .StorageRpc ;
33
36
import com .google .cloud .storage .spi .StorageRpc .Tuple ;
37
+ import com .google .common .collect .ImmutableMap ;
34
38
35
39
import java .io .FileOutputStream ;
36
40
import java .io .IOException ;
51
55
import java .util .Arrays ;
52
56
import java .util .HashMap ;
53
57
import java .util .Iterator ;
58
+ import java .util .LinkedList ;
54
59
import java .util .List ;
55
60
import java .util .Map ;
56
61
import java .util .concurrent .TimeUnit ;
75
80
* cp <from_bucket> <from_path> <to_bucket> <to_path> |
76
81
* compose <bucket> <from_path>+ <to_path> |
77
82
* update_metadata <bucket> <file> [key=value]* |
78
- * sign_url <service_account_private_key_file> <service_account_email> <bucket> <path>"}</pre>
83
+ * sign_url <service_account_private_key_file> <service_account_email> <bucket> <path> |
84
+ * add-acl domain <bucket> <path>? <domain> OWNER|READER|WRITER |
85
+ * add-acl project <bucket> <path>? <projectId>:(OWNERS|EDITORS|VIEWERS) OWNER|READER|WRITER |
86
+ * add-acl user <bucket> <path>? <userEmail>|allUsers|allAuthenticatedUsers OWNER|READER|WRITER |
87
+ * add-acl group <bucket> <path>? <group> OWNER|READER|WRITER"}</pre>
79
88
* </li>
80
89
* </ol>
81
90
*
87
96
public class StorageExample {
88
97
89
98
private static final Map <String , StorageAction > ACTIONS = new HashMap <>();
99
+ private static final Map <String , StorageAction > ACL_ACTIONS = new HashMap <>();
90
100
91
101
private abstract static class StorageAction <T > {
92
102
@@ -119,6 +129,48 @@ public String params() {
119
129
}
120
130
}
121
131
132
+ private static class ParentAction extends StorageAction <StorageRpc .Tuple <StorageAction , Object >> {
133
+
134
+ private final Map <String , StorageAction > subActions ;
135
+
136
+ ParentAction (Map <String , StorageAction > subActions ) {
137
+ this .subActions = ImmutableMap .copyOf (subActions );
138
+ }
139
+
140
+ @ Override
141
+ @ SuppressWarnings ("unchecked" )
142
+ void run (Storage storage , StorageRpc .Tuple <StorageAction , Object > subaction ) throws Exception {
143
+ subaction .x ().run (storage , subaction .y ());
144
+ }
145
+
146
+ @ Override
147
+ StorageRpc .Tuple <StorageAction , Object > parse (String ... args ) throws Exception {
148
+ if (args .length >= 1 ) {
149
+ StorageAction action = subActions .get (args [0 ]);
150
+ if (action != null ) {
151
+ Object actionArguments = action .parse (Arrays .copyOfRange (args , 1 , args .length ));
152
+ return StorageRpc .Tuple .of (action , actionArguments );
153
+ } else {
154
+ throw new IllegalArgumentException ("Unrecognized entity '" + args [0 ] + "'." );
155
+ }
156
+ }
157
+ throw new IllegalArgumentException ("Missing required entity." );
158
+ }
159
+
160
+ @ Override
161
+ public String params () {
162
+ StringBuilder builder = new StringBuilder ();
163
+ for (Map .Entry <String , StorageAction > entry : subActions .entrySet ()) {
164
+ builder .append ('\n' ).append (entry .getKey ());
165
+ String param = entry .getValue ().params ();
166
+ if (param != null && !param .isEmpty ()) {
167
+ builder .append (' ' ).append (param );
168
+ }
169
+ }
170
+ return builder .toString ();
171
+ }
172
+ }
173
+
122
174
/**
123
175
* This class demonstrates how to retrieve Bucket or Blob metadata.
124
176
* If more than one blob is supplied a Batch operation would be used to get all blobs metadata
@@ -512,6 +564,188 @@ public String params() {
512
564
}
513
565
}
514
566
567
+ private abstract static class AclAction extends StorageAction <Tuple <BlobId , Acl >> {
568
+
569
+ @ Override
570
+ public void run (Storage storage , Tuple <BlobId , Acl > params ) {
571
+ BlobId blobId = params .x ();
572
+ Acl acl = params .y ();
573
+ if (blobId .name ().isEmpty ()) {
574
+ Bucket bucket = storage .get (blobId .bucket ());
575
+ if (bucket == null ) {
576
+ System .out .printf ("Bucket %s does not exist%n" , blobId .bucket ());
577
+ return ;
578
+ }
579
+ bucket .toBuilder ().acl (addAcl (bucket .acl (), acl )).build ().update ();
580
+ System .out .printf ("Added ACL %s to bucket %s%n" , acl , blobId .bucket ());
581
+ } else {
582
+ Blob blob = storage .get (blobId );
583
+ if (blob == null ) {
584
+ System .out .printf ("Blob %s does not exist%n" , blobId );
585
+ return ;
586
+ }
587
+ blob .toBuilder ().acl (addAcl (blob .acl (), acl )).build ().update ();
588
+ System .out .printf ("Added ACL %s to blob %s%n" , acl , blobId );
589
+ }
590
+ }
591
+
592
+ private static List <Acl > addAcl (List <Acl > acls , Acl newAcl ) {
593
+ List <Acl > newAcls = new LinkedList <>(acls );
594
+ newAcls .add (newAcl );
595
+ return newAcls ;
596
+ }
597
+ }
598
+
599
+ /**
600
+ * This class demonstrates how to add an ACL to a blob or a bucket for a group of users
601
+ * (identified by the group's email).
602
+ *
603
+ * @see <a href="https://cloud.google.com/storage/docs/access-control/lists#permissions">Access
604
+ * Control Lists (ACLs)</a>
605
+ */
606
+ private static class AddGroupAclAction extends AclAction {
607
+
608
+ @ Override
609
+ Tuple <BlobId , Acl > parse (String ... args ) {
610
+ if (args .length >= 3 ) {
611
+ BlobId blob ;
612
+ int nextArg ;
613
+ if (args .length == 3 ) {
614
+ blob = BlobId .of (args [0 ], "" );
615
+ nextArg = 1 ;
616
+ } else if (args .length == 4 ) {
617
+ blob = BlobId .of (args [0 ], args [1 ]);
618
+ nextArg = 2 ;
619
+ } else {
620
+ throw new IllegalArgumentException ("Too many arguments." );
621
+ }
622
+ String group = args [nextArg ++];
623
+ Acl .Role role = Acl .Role .valueOf (args [nextArg ]);
624
+ return Tuple .of (blob , Acl .of (new Acl .Group (group ), role ));
625
+ }
626
+ throw new IllegalArgumentException ("Missing required bucket, groupEmail or role arguments." );
627
+ }
628
+
629
+ @ Override
630
+ public String params () {
631
+ return "<bucket> <path>? <group> OWNER|READER|WRITER" ;
632
+ }
633
+ }
634
+
635
+ /**
636
+ * This class demonstrates how to add an ACL to a blob or a bucket for a domain.
637
+ *
638
+ * @see <a href="https://cloud.google.com/storage/docs/access-control/lists#permissions">Access
639
+ * Control Lists (ACLs)</a>
640
+ */
641
+ private static class AddDomainAclAction extends AclAction {
642
+
643
+ @ Override
644
+ Tuple <BlobId , Acl > parse (String ... args ) {
645
+ if (args .length >= 3 ) {
646
+ BlobId blob ;
647
+ int nextArg ;
648
+ if (args .length == 3 ) {
649
+ blob = BlobId .of (args [0 ], "" );
650
+ nextArg = 1 ;
651
+ } else if (args .length == 4 ) {
652
+ blob = BlobId .of (args [0 ], args [1 ]);
653
+ nextArg = 2 ;
654
+ } else {
655
+ throw new IllegalArgumentException ("Too many arguments." );
656
+ }
657
+ String domain = args [nextArg ++];
658
+ Acl .Role role = Acl .Role .valueOf (args [nextArg ]);
659
+ return Tuple .of (blob , Acl .of (new Acl .Domain (domain ), role ));
660
+ }
661
+ throw new IllegalArgumentException ("Missing required bucket, domain or role arguments." );
662
+ }
663
+
664
+ @ Override
665
+ public String params () {
666
+ return "<bucket> <path>? <domain> OWNER|READER|WRITER" ;
667
+ }
668
+ }
669
+
670
+ /**
671
+ * This class demonstrates how to add an ACL to a blob or a bucket for either a user (if an email
672
+ * is provided), all users (if {@code allUsers} is provided), or all authenticated users (if
673
+ * {@code allAuthenticatedUsers} is provided).
674
+ *
675
+ * @see <a href="https://cloud.google.com/storage/docs/access-control/lists#permissions">Access
676
+ * Control Lists (ACLs)</a>
677
+ */
678
+ private static class AddUserAclAction extends AclAction {
679
+
680
+ @ Override
681
+ Tuple <BlobId , Acl > parse (String ... args ) {
682
+ if (args .length >= 3 ) {
683
+ BlobId blob ;
684
+ int nextArg ;
685
+ if (args .length == 3 ) {
686
+ blob = BlobId .of (args [0 ], "" );
687
+ nextArg = 1 ;
688
+ } else if (args .length == 4 ) {
689
+ blob = BlobId .of (args [0 ], args [1 ]);
690
+ nextArg = 2 ;
691
+ } else {
692
+ throw new IllegalArgumentException ("Too many arguments." );
693
+ }
694
+ String user = args [nextArg ++];
695
+ Acl .Role role = Acl .Role .valueOf (args [nextArg ]);
696
+ return Tuple .of (blob , Acl .of (new Acl .User (user ), role ));
697
+ }
698
+ throw new IllegalArgumentException ("Missing required bucket, userEmail or role arguments." );
699
+ }
700
+
701
+ @ Override
702
+ public String params () {
703
+ return "<bucket> <path>? <userEmail>|allUsers|allAuthenticatedUsers OWNER|READER|WRITER" ;
704
+ }
705
+ }
706
+
707
+ /**
708
+ * This class demonstrates how to add an ACL to a blob or a bucket for all users that have a
709
+ * specific role in a provided project.
710
+ *
711
+ * @see <a href="https://cloud.google.com/storage/docs/access-control/lists#permissions">Access
712
+ * Control Lists (ACLs)</a>
713
+ */
714
+ private static class AddProjectAclAction extends AclAction {
715
+
716
+ @ Override
717
+ Tuple <BlobId , Acl > parse (String ... args ) {
718
+ if (args .length >= 3 ) {
719
+ BlobId blob ;
720
+ int nextArg ;
721
+ if (args .length == 3 ) {
722
+ blob = BlobId .of (args [0 ], "" );
723
+ nextArg = 1 ;
724
+ } else if (args .length == 4 ) {
725
+ blob = BlobId .of (args [0 ], args [1 ]);
726
+ nextArg = 2 ;
727
+ } else {
728
+ throw new IllegalArgumentException ("Too many arguments." );
729
+ }
730
+ String [] projectAndRole = args [nextArg ++].split (":" );
731
+ if (projectAndRole .length != 2 ) {
732
+ throw new IllegalArgumentException (
733
+ "Project entity must be specified as <projectId>:(OWNERS|READERS|WRITERS)" );
734
+ } else {
735
+ Acl .Project .ProjectRole projectRole = Acl .Project .ProjectRole .valueOf (projectAndRole [1 ]);
736
+ Acl .Role role = Acl .Role .valueOf (args [nextArg ]);
737
+ return Tuple .of (blob , Acl .of (new Acl .Project (projectRole , projectAndRole [0 ]), role ));
738
+ }
739
+ }
740
+ throw new IllegalArgumentException ("Missing required bucket, project or role arguments." );
741
+ }
742
+
743
+ @ Override
744
+ public String params () {
745
+ return "<bucket> <path>? <projectId>:(OWNERS|EDITORS|VIEWERS) OWNER|READER|WRITER" ;
746
+ }
747
+ }
748
+
515
749
static {
516
750
ACTIONS .put ("info" , new InfoAction ());
517
751
ACTIONS .put ("delete" , new DeleteAction ());
@@ -522,6 +756,11 @@ public String params() {
522
756
ACTIONS .put ("compose" , new ComposeAction ());
523
757
ACTIONS .put ("update_metadata" , new UpdateMetadataAction ());
524
758
ACTIONS .put ("sign_url" , new SignUrlAction ());
759
+ ACL_ACTIONS .put ("group" , new AddGroupAclAction ());
760
+ ACL_ACTIONS .put ("domain" , new AddDomainAclAction ());
761
+ ACL_ACTIONS .put ("user" , new AddUserAclAction ());
762
+ ACL_ACTIONS .put ("project" , new AddProjectAclAction ());
763
+ ACTIONS .put ("add-acl" , new ParentAction (ACL_ACTIONS ));
525
764
}
526
765
527
766
private static void printUsage () {
@@ -531,11 +770,12 @@ private static void printUsage() {
531
770
532
771
String param = entry .getValue ().params ();
533
772
if (param != null && !param .isEmpty ()) {
534
- actionAndParams .append (' ' ).append (param );
773
+ // Add extra padding for multi-line action
774
+ actionAndParams .append (' ' ).append (param .replace ("\n " , "\n \t \t " ));
535
775
}
536
776
}
537
- System .out .printf ("Usage: %s [<project_id>] operation <args>*%s%n" ,
538
- StorageExample .class .getSimpleName (), actionAndParams );
777
+ System .out .printf ("Usage: %s [<project_id>] operation [entity] <args>*%s%n" ,
778
+ ComputeExample .class .getSimpleName (), actionAndParams );
539
779
}
540
780
541
781
@ SuppressWarnings ("unchecked" )
0 commit comments