1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
package Torello.Java.Build;

import Torello.Java.OSResponse;
import Torello.Java.OSExtras;
import Torello.Java.GSUTIL;
import Torello.Java.StringParse;

import java.util.Vector;
import java.io.IOException;

/**
 * An implementation of the {@link CloudSync} Java-Interface that utilizes the Google-Provided
 * Python Based Tool known as {@code 'GSUTIL'} (see: {@link GSUTIL}).
 * 
 * <BR /><BR />I have used this infernal thing, everyday, for 6 years (GSUTIL, that is)
 */
public class CloudSyncGSUTIL extends CloudSync
{
    // ********************************************************************************************
    // ********************************************************************************************
    // Implement the Protected Methods 
    // ********************************************************************************************
    // ********************************************************************************************


    private GSUTIL gsutil = null;

    protected final void initStage(Appendable a1, Appendable a2)
    { gsutil = new GSUTIL(a1, a2, null, null); }

    protected final void initStageLogSync()
    { gsutil = new GSUTIL(null, null, System.out, System.out); }

    protected final void endStage()
    {
        gsutil.commandStrAppendable    = null;
        gsutil.outputAppendable        = null;
        gsutil.errorOutput             = null;
        gsutil.standardOutput          = null;
        gsutil                         = null;
    }


    // ********************************************************************************************
    // ********************************************************************************************
    // GSUTILCloudSync Fields
    // ********************************************************************************************
    // ********************************************************************************************


    // Currently this field is simply the above directory-name plus the sub-string "logs/"
    private final String CLOUD_LOG_DIR;

    // Currently this field is simply the above directory-name plus the sub-string "jar/"
    private final String CLOUD_JAR_DIR;

    // The name of the "javadoc/" subdirectory
    private final String CLOUD_JAVADOC_DIR;

    /**
     * The location for backing up the code in this project.  This should be the root-directory
     * inside of any GCP Storage-Bucket that will allow your Build-Tool to save a copy of your
     * Project's Backup {@code '.tar'}-File.
     * 
     * <BR /><BR />The file that is saved will be named after the date on which the build is run.
     * This does mean, indeed, that no more than one backup-file can be saved per day.  At the
     * moment there isn't any way for the Synchroniztion-Code to allow for saving more than a
     * single {@code '.tar'}-File per day.
     */
    public final String CODE_DRIVE_BACKUP_FILE_START;

    /**
     * Constructs an instance of the {@link GSUTIL}-based Cloud-Synchroniztion Class (this class).
     * 
     * @param GOOGLE_STORAGE_DIR This must be the name of the Google Cloud Storage Bucket 
     * Directory-Name to be used for hosting / synchronizing your Java-Doc ouptut Web-Pages.
     * 
     * @param BACKUP_TAR_FILE_GCS_DIR This should be the name of any Google Cloud Storage Bucket
     * Directory-Name where your Project's output "Backup {@code '.tar'} File" may be copied for
     * saving &amp; backing up your work.
     * 
     * <BR /><BR /><B STYLE='color: red;'>NOTE:</B> This parameter may remain null, and if it is,
     * it will be silently ignored.  When ignored, your Project's Backup {@code '.tar'} File will
     * stay in your home directory, instead.
     * 
     * @param shouldRunMakePublic Goole Cloud Platform allows for Storage-Buckets to be conifgured
     * with "Bucket Level Permissions", or "Object Level Permissions".  When Bucket-Level
     * Permissions are selected, there is no need to modify the permissions for each file or
     * directory of files that are synchronized with the Cloud.
     * 
     * <BR /><BR />Under the Bucket-Level-Permissions setup (for a GCP Storage-Bucket), all "Access
     * Control Lists" are changed at the "top level" for the entire bucket.  Under such a
     * configuration scenario, there is no need to run "Make Public" inside of a build.  By
     * definition, everything (should) already be public in the Bucket that's being used.
     * 
     * <BR /><BR />However, when Object-Level Permissions are selected, each file that is copied
     * to the Cloud, likely needs its "Access Control" to be updated in order for it to be publicly
     * visible on your Web-Site.  Object-Level Permissions Buckets will not allow the Storage-API
     * Web-Server to read or see your HTML Files if these permissions are not updated to allow
     * (at least) "Read Access."
     * 
     * @param allowPartialBuilds If an output Storage-Bucket is considered public-release, and is
     * viewable to the entire Internet, this Built-Tool allows for prohibiting Partil-Builds to be
     * executed and dropped onto the output Web-Page Bucket.
     * 
     * <BR /><BR />For quite a long time, this parameter was simply called "ReleaseOrDeveloper",
     * and accepted {@code TRUE} or {@code FALSE}.
     * 
     * @param includeSetMaxAgeOption Specifies whether or not there should be a build-option
     * that includes Stage-8, which sets a Browser-Cache Meta-Content value.
     */
    public CloudSyncGSUTIL(
            final String    GOOGLE_STORAGE_DIR,
            final String    BACKUP_TAR_FILE_GCS_DIR,
            final boolean   shouldRunMakePublic,
            final boolean   allowPartialBuilds,
            final boolean   includeSetMaxAgeOption,
            final String    nickName
        )
    {
        super(
            // final boolean shouldSyncMainTarGzFile,
            (BACKUP_TAR_FILE_GCS_DIR != null),

            // Formerly known as "Bucket Or Object Level Permissions"
            shouldRunMakePublic,

            // Formerly known as "Release or Developer"
            allowPartialBuilds,

            // The Browser Cache, Cache-Control "Max-Age" value to a 30 seconds, or something very
            // low.  This allows for reviewing changes to your pages during development more easily
            // without the browser caching old version, making your changes/updates invisible.

            includeSetMaxAgeOption,

            // final String nickName
            nickName,

            // final String cloudRootStorageDir
            GOOGLE_STORAGE_DIR
        );

        // NOTE: The 'super' constructor assigns "GOOGLE_STORAGE_DIR" to "cloudRootStorageDir"

        this.CLOUD_LOG_DIR      = this.cloudRootStorageDir + "logs/";
        this.CLOUD_JAR_DIR      = this.cloudRootStorageDir + "jar/";
        this.CLOUD_JAVADOC_DIR  = this.cloudRootStorageDir + "javadoc/";

        this.CODE_DRIVE_BACKUP_FILE_START = this.shouldSyncMainTarGzFile
            ? (BACKUP_TAR_FILE_GCS_DIR +
                StringParse.ymDateStr('/', true) + '/' +
                StringParse.dateStr('-') + '-')
            : null;

        /*
        // You wills screw this simple little thing up again, guaranteed.  Don't delete this.

        System.out.println(
            "BACKUP_TAR_FILE_GCS_DIR:           " + BACKUP_TAR_FILE_GCS_DIR + '\n' +
            "this.shouldSyncMainTarGzFile:      " + this.shouldSyncMainTarGzFile + '\n' +
            "this.CODE_DRIVE_BACKUP_FILE_START: " + this.CODE_DRIVE_BACKUP_FILE_START
        );
        */
    }


    // ********************************************************************************************
    // ********************************************************************************************
    // public class S05_SyncJavaDoc - SYNCHRONIZE ENTIRE PROJECT
    // ********************************************************************************************
    // ********************************************************************************************


    public OSResponse removeCloudJavaDocDir() throws IOException
    { return this.gsutil.RM(CLOUD_JAVADOC_DIR + "**"); }

    public OSResponse copyJavaDocDirToCloudDir() throws IOException
    { return this.gsutil.CP(this.brec.LOCAL_JAVADOC_DIR, this.cloudRootStorageDir, "-r"); }

    public OSResponse makePublicJavaDocDir() throws IOException
    { return this.gsutil.MP(CLOUD_JAVADOC_DIR + "**"); }


    // ********************************************************************************************
    // ********************************************************************************************
    // public class S05_SyncJavaDoc - SYNCHRONIZE SPECIFIED LIST OF PROJECT PACKAGES
    // ********************************************************************************************
    // ********************************************************************************************


    public OSResponse copySingleJDPackageToCloud
        (String pkgRootLocalDir, String pkgRootCloudStorageDir)
        throws IOException
    { return this.gsutil.CP(pkgRootLocalDir + '*', pkgRootCloudStorageDir); }

    public OSResponse copyOtherPackageDirsToCloudDir
        (OSExtras ose, Vector<String> copyDirs, String pkgRootCloudStorageDir)
        throws IOException
    {
        this.gsutil.osExtras = ose;
        return this.gsutil.CP(copyDirs, pkgRootCloudStorageDir, "-r");
    }

    public OSResponse makePublicDirArr(String[] dirArr) throws IOException
    { return this.gsutil.MP(dirArr); }


    // ********************************************************************************************
    // ********************************************************************************************
    // public class S06_SyncTarJar
    // ********************************************************************************************
    // ********************************************************************************************


    public OSResponse copyJDTarAndJarToCloud() throws IOException
    {
        String[] cpArr = { this.brec.JAVADOC_TAR_FILE, this.brec.JAR_FILE };
        return this.gsutil.CP(cpArr, CLOUD_JAR_DIR);
    }

    public OSResponse makeJDTarAndJarPublic() throws IOException
    {
        return this.gsutil.MP(
            CLOUD_JAR_DIR + this.brec.JAR_FILE,
            CLOUD_JAR_DIR + this.brec.JAVADOC_TAR_FILE
        );
    }

    public OSResponse backupMainTarGzFile() throws IOException
    {
        return this.gsutil.CP(
            this.brec.TAR_FILE,
            CODE_DRIVE_BACKUP_FILE_START + this.brec.TAR_FILE
        );
    }


    // ********************************************************************************************
    // ********************************************************************************************
    // public class S07_SyncLogs
    // ********************************************************************************************
    // ********************************************************************************************


    public OSResponse copyLogDirToCloud() throws IOException
    { return this.gsutil.CP(this.brec.logs.LOG_DIR + '*', CLOUD_LOG_DIR); }

    public OSResponse setCloudLogsContentType() throws IOException
    {
        return this.gsutil.CONTENT_TYPE
            (CLOUD_LOG_DIR + "*.html", Torello.Java.GSUTIL.SCT_HTML_UTF8);
    }

    public OSResponse makeLogsPublic() throws IOException
    { return this.gsutil.MP(CLOUD_LOG_DIR + "*"); }


    // ********************************************************************************************
    // ********************************************************************************************
    // public class S08_SetMaxAge
    // ********************************************************************************************
    // ********************************************************************************************


    public OSResponse setMaxAgeAll() throws IOException
    { return this.gsutil.SMA(this.cloudRootStorageDir + "**", 120); }

    public OSResponse setMaxAgeSome() throws IOException
    { return this.gsutil.SMA(this.brec.stage8GCSDirs, 120); }
}