001package Torello.Java.Build;
002
003import Torello.Java.OSResponse;
004import Torello.Java.OSExtras;
005import Torello.Java.GSUTIL;
006import Torello.Java.StringParse;
007
008import java.util.Vector;
009import java.io.IOException;
010
011/**
012 * An implementation of the {@link CloudSync} Java-Interface that utilizes the Google-Provided
013 * Python Based Tool known as {@code 'GSUTIL'} (see: {@link GSUTIL}).
014 * 
015 * <BR /><BR />I have used this infernal thing, everyday, for 6 years (GSUTIL, that is)
016 */
017public class CloudSyncGSUTIL extends CloudSync
018{
019    // ********************************************************************************************
020    // ********************************************************************************************
021    // Implement the Protected Methods 
022    // ********************************************************************************************
023    // ********************************************************************************************
024
025
026    private GSUTIL gsutil = null;
027
028    protected final void initStage(Appendable a1, Appendable a2)
029    { gsutil = new GSUTIL(a1, a2, null, null); }
030
031    protected final void initStageLogSync()
032    { gsutil = new GSUTIL(null, null, System.out, System.out); }
033
034    protected final void endStage()
035    {
036        gsutil.commandStrAppendable    = null;
037        gsutil.outputAppendable        = null;
038        gsutil.errorOutput             = null;
039        gsutil.standardOutput          = null;
040        gsutil                         = null;
041    }
042
043
044    // ********************************************************************************************
045    // ********************************************************************************************
046    // GSUTILCloudSync Fields
047    // ********************************************************************************************
048    // ********************************************************************************************
049
050
051    // Currently this field is simply the above directory-name plus the sub-string "logs/"
052    private final String CLOUD_LOG_DIR;
053
054    // Currently this field is simply the above directory-name plus the sub-string "jar/"
055    private final String CLOUD_JAR_DIR;
056
057    // The name of the "javadoc/" subdirectory
058    private final String CLOUD_JAVADOC_DIR;
059
060    /**
061     * The location for backing up the code in this project.  This should be the root-directory
062     * inside of any GCP Storage-Bucket that will allow your Build-Tool to save a copy of your
063     * Project's Backup {@code '.tar'}-File.
064     * 
065     * <BR /><BR />The file that is saved will be named after the date on which the build is run.
066     * This does mean, indeed, that no more than one backup-file can be saved per day.  At the
067     * moment there isn't any way for the Synchroniztion-Code to allow for saving more than a
068     * single {@code '.tar'}-File per day.
069     */
070    public final String CODE_DRIVE_BACKUP_FILE_START;
071
072    /**
073     * Constructs an instance of the {@link GSUTIL}-based Cloud-Synchroniztion Class (this class).
074     * 
075     * @param GOOGLE_STORAGE_DIR This must be the name of the Google Cloud Storage Bucket 
076     * Directory-Name to be used for hosting / synchronizing your Java-Doc ouptut Web-Pages.
077     * 
078     * @param BACKUP_TAR_FILE_GCS_DIR This should be the name of any Google Cloud Storage Bucket
079     * Directory-Name where your Project's output "Backup {@code '.tar'} File" may be copied for
080     * saving &amp; backing up your work.
081     * 
082     * <BR /><BR /><B STYLE='color: red;'>NOTE:</B> This parameter may remain null, and if it is,
083     * it will be silently ignored.  When ignored, your Project's Backup {@code '.tar'} File will
084     * stay in your home directory, instead.
085     * 
086     * @param shouldRunMakePublic Goole Cloud Platform allows for Storage-Buckets to be conifgured
087     * with "Bucket Level Permissions", or "Object Level Permissions".  When Bucket-Level
088     * Permissions are selected, there is no need to modify the permissions for each file or
089     * directory of files that are synchronized with the Cloud.
090     * 
091     * <BR /><BR />Under the Bucket-Level-Permissions setup (for a GCP Storage-Bucket), all "Access
092     * Control Lists" are changed at the "top level" for the entire bucket.  Under such a
093     * configuration scenario, there is no need to run "Make Public" inside of a build.  By
094     * definition, everything (should) already be public in the Bucket that's being used.
095     * 
096     * <BR /><BR />However, when Object-Level Permissions are selected, each file that is copied
097     * to the Cloud, likely needs its "Access Control" to be updated in order for it to be publicly
098     * visible on your Web-Site.  Object-Level Permissions Buckets will not allow the Storage-API
099     * Web-Server to read or see your HTML Files if these permissions are not updated to allow
100     * (at least) "Read Access."
101     * 
102     * @param allowPartialBuilds If an output Storage-Bucket is considered public-release, and is
103     * viewable to the entire Internet, this Built-Tool allows for prohibiting Partil-Builds to be
104     * executed and dropped onto the output Web-Page Bucket.
105     * 
106     * <BR /><BR />For quite a long time, this parameter was simply called "ReleaseOrDeveloper",
107     * and accepted {@code TRUE} or {@code FALSE}.
108     * 
109     * @param includeSetMaxAgeOption Specifies whether or not there should be a build-option
110     * that includes Stage-8, which sets a Browser-Cache Meta-Content value.
111     */
112    public CloudSyncGSUTIL(
113            final String    GOOGLE_STORAGE_DIR,
114            final String    BACKUP_TAR_FILE_GCS_DIR,
115            final boolean   shouldRunMakePublic,
116            final boolean   allowPartialBuilds,
117            final boolean   includeSetMaxAgeOption,
118            final String    nickName
119        )
120    {
121        super(
122            // final boolean shouldSyncMainTarGzFile,
123            (BACKUP_TAR_FILE_GCS_DIR != null),
124
125            // Formerly known as "Bucket Or Object Level Permissions"
126            shouldRunMakePublic,
127
128            // Formerly known as "Release or Developer"
129            allowPartialBuilds,
130
131            // The Browser Cache, Cache-Control "Max-Age" value to a 30 seconds, or something very
132            // low.  This allows for reviewing changes to your pages during development more easily
133            // without the browser caching old version, making your changes/updates invisible.
134
135            includeSetMaxAgeOption,
136
137            // final String nickName
138            nickName,
139
140            // final String cloudRootStorageDir
141            GOOGLE_STORAGE_DIR
142        );
143
144        // NOTE: The 'super' constructor assigns "GOOGLE_STORAGE_DIR" to "cloudRootStorageDir"
145
146        this.CLOUD_LOG_DIR      = this.cloudRootStorageDir + "logs/";
147        this.CLOUD_JAR_DIR      = this.cloudRootStorageDir + "jar/";
148        this.CLOUD_JAVADOC_DIR  = this.cloudRootStorageDir + "javadoc/";
149
150        this.CODE_DRIVE_BACKUP_FILE_START = this.shouldSyncMainTarGzFile
151            ? (BACKUP_TAR_FILE_GCS_DIR +
152                StringParse.ymDateStr('/', true) + '/' +
153                StringParse.dateStr('-') + '-')
154            : null;
155
156        /*
157        // You wills screw this simple little thing up again, guaranteed.  Don't delete this.
158
159        System.out.println(
160            "BACKUP_TAR_FILE_GCS_DIR:           " + BACKUP_TAR_FILE_GCS_DIR + '\n' +
161            "this.shouldSyncMainTarGzFile:      " + this.shouldSyncMainTarGzFile + '\n' +
162            "this.CODE_DRIVE_BACKUP_FILE_START: " + this.CODE_DRIVE_BACKUP_FILE_START
163        );
164        */
165    }
166
167
168    // ********************************************************************************************
169    // ********************************************************************************************
170    // public class S05_SyncJavaDoc - SYNCHRONIZE ENTIRE PROJECT
171    // ********************************************************************************************
172    // ********************************************************************************************
173
174
175    public OSResponse removeCloudJavaDocDir() throws IOException
176    { return this.gsutil.RM(CLOUD_JAVADOC_DIR + "**"); }
177
178    public OSResponse copyJavaDocDirToCloudDir() throws IOException
179    { return this.gsutil.CP(this.brec.LOCAL_JAVADOC_DIR, this.cloudRootStorageDir, "-r"); }
180
181    public OSResponse makePublicJavaDocDir() throws IOException
182    { return this.gsutil.MP(CLOUD_JAVADOC_DIR + "**"); }
183
184
185    // ********************************************************************************************
186    // ********************************************************************************************
187    // public class S05_SyncJavaDoc - SYNCHRONIZE SPECIFIED LIST OF PROJECT PACKAGES
188    // ********************************************************************************************
189    // ********************************************************************************************
190
191
192    public OSResponse copySingleJDPackageToCloud
193        (String pkgRootLocalDir, String pkgRootCloudStorageDir)
194        throws IOException
195    { return this.gsutil.CP(pkgRootLocalDir + '*', pkgRootCloudStorageDir); }
196
197    public OSResponse copyOtherPackageDirsToCloudDir
198        (OSExtras ose, Vector<String> copyDirs, String pkgRootCloudStorageDir)
199        throws IOException
200    {
201        this.gsutil.osExtras = ose;
202        return this.gsutil.CP(copyDirs, pkgRootCloudStorageDir, "-r");
203    }
204
205    public OSResponse makePublicDirArr(String[] dirArr) throws IOException
206    { return this.gsutil.MP(dirArr); }
207
208
209    // ********************************************************************************************
210    // ********************************************************************************************
211    // public class S06_SyncTarJar
212    // ********************************************************************************************
213    // ********************************************************************************************
214
215
216    public OSResponse copyJDTarAndJarToCloud() throws IOException
217    {
218        String[] cpArr = { this.brec.JAVADOC_TAR_FILE, this.brec.JAR_FILE };
219        return this.gsutil.CP(cpArr, CLOUD_JAR_DIR);
220    }
221
222    public OSResponse makeJDTarAndJarPublic() throws IOException
223    {
224        return this.gsutil.MP(
225            CLOUD_JAR_DIR + this.brec.JAR_FILE,
226            CLOUD_JAR_DIR + this.brec.JAVADOC_TAR_FILE
227        );
228    }
229
230    public OSResponse backupMainTarGzFile() throws IOException
231    {
232        return this.gsutil.CP(
233            this.brec.TAR_FILE,
234            CODE_DRIVE_BACKUP_FILE_START + this.brec.TAR_FILE
235        );
236    }
237
238
239    // ********************************************************************************************
240    // ********************************************************************************************
241    // public class S07_SyncLogs
242    // ********************************************************************************************
243    // ********************************************************************************************
244
245
246    public OSResponse copyLogDirToCloud() throws IOException
247    { return this.gsutil.CP(this.brec.logs.LOG_DIR + '*', CLOUD_LOG_DIR); }
248
249    public OSResponse setCloudLogsContentType() throws IOException
250    {
251        return this.gsutil.CONTENT_TYPE
252            (CLOUD_LOG_DIR + "*.html", Torello.Java.GSUTIL.SCT_HTML_UTF8);
253    }
254
255    public OSResponse makeLogsPublic() throws IOException
256    { return this.gsutil.MP(CLOUD_LOG_DIR + "*"); }
257
258
259    // ********************************************************************************************
260    // ********************************************************************************************
261    // public class S08_SetMaxAge
262    // ********************************************************************************************
263    // ********************************************************************************************
264
265
266    public OSResponse setMaxAgeAll() throws IOException
267    { return this.gsutil.SMA(this.cloudRootStorageDir + "**", 120); }
268
269    public OSResponse setMaxAgeSome() throws IOException
270    { return this.gsutil.SMA(this.brec.stage8GCSDirs, 120); }
271}