001package Torello.Java.Build;
002
003import Torello.Java.ReadOnly.ReadOnlyList;
004
005import Torello.Java.Shell;
006import Torello.Java.GSUTIL;
007import Torello.Java.OSResponse;
008import Torello.Java.OSExtras;
009import Torello.Java.StringParse;
010
011import Torello.Java.Additional.BiAppendable;
012import Torello.Java.Additional.AppendableSafe;
013
014import static Torello.Java.C.BYELLOW;
015import static Torello.Java.C.BGREEN;
016import static Torello.Java.C.RESET;
017
018import java.io.File;
019import java.io.IOException;
020import java.util.Vector;
021import java.util.stream.Stream;
022
023/**
024 * This is the fifth Build-Stage, and it is part of the synchronization of a project with Google
025 * Cloud Platform Stroage Buckets.  This class relies heavily on the GCP Shell-Command
026 * {@code 'gsutil'} and it's Java implementation - {@link GSUTIL Torello.Java.GSUTIL}.
027 * 
028 * <BR /><BR />This class' synchronization-efforts entail copying the File-System's Java-Doc
029 * Directory-Contents onto the (User-Specified) Google Cloud Server Storage-Bucket.
030 * 
031 * <EMBED CLASS='external-html' DATA-FILE-ID=S05_SYNC_JAVADOC>
032 */
033@Torello.JavaDoc.StaticFunctional
034public class S05_SyncJavaDoc
035{
036    // Completely irrelevant, and the 'private' modifier keeps it off of JavaDoc
037    private S05_SyncJavaDoc() { }
038
039    private static final String FS = java.io.File.separator;
040
041
042    // ********************************************************************************************
043    // ********************************************************************************************
044    // Copies entire 'javadoc/' directory-tree to GCS
045    // ********************************************************************************************
046    // ********************************************************************************************
047
048
049    public static void sync(Builder builder) throws IOException
050    {
051        builder.timers.startStage05();
052        Printing.startStep(5);
053
054        OSResponse      osr     = null;
055        StringBuilder   logOnly = new StringBuilder();
056
057        final AppendableSafe logAndScreen = new AppendableSafe(
058            new BiAppendable(System.out, logOnly),
059            AppendableSafe.USE_APPENDABLE_ERROR
060        );
061
062        // Uses Shell-Contructor:
063        // (outputAppendable, commandStrAppendable, standardOutput, errorOutput)
064
065        // GSUTIL gsutil = new GSUTIL(logOnly, logAndScreen, null, null);
066        builder.cloudSync.initStage05(logOnly, logAndScreen);
067        Shell shell = new Shell(logOnly, logAndScreen, null, null);
068
069        if (! builder.cli.SKIP_REMOVE_GCS_FILES)
070        {
071            // osr = gsutil.RM(builder.cli.GCS_DIR + "javadoc/" + "**");
072            osr = builder.cloudSync.removeCloudJavaDocDir();
073            Util.HALT_ON_ERROR(osr);
074            Printing.PLS(logOnly, false);
075        }
076
077        // TRICKY !!! Do not use 'GCS_JAVADOC_DIR' here - because then it will be
078        // 'javadoc/javadoc/!!!
079
080        // osr = gsutil.CP(builder.LOCAL_JAVADOC_DIR, builder.cli.GCS_DIR, "-r");
081        osr = builder.cloudSync.copyJavaDocDirToCloudDir();
082        Util.HALT_ON_ERROR(osr);
083        Printing.PLS(logOnly, false);
084
085        osr = shell.RM(builder.LOCAL_JAVADOC_DIR, "-r");
086        Util.HALT_ON_ERROR(osr);
087        Printing.PLS(logOnly, false);
088
089        if (builder.RUN_MAKE_PUBLIC)
090        {
091            Printing.PLS(logOnly, false);
092            // osr = gsutil.MP(builder.cli.GCS_DIR + "javadoc/**");
093            osr = builder.cloudSync.makePublicJavaDocDir();
094            Util.HALT_ON_ERROR(osr);
095        }
096
097        builder.logs.write_S05_LOG(logOnly.toString());
098        builder.cloudSync.endStage05();
099        builder.timers.endStage05();
100    }
101
102
103    // ********************************************************************************************
104    // ********************************************************************************************
105    // Copies only selected packages of the Java-Doc Directory to GCS
106    // ********************************************************************************************
107    // ********************************************************************************************
108
109
110    static void syncPart(Builder builder) throws IOException
111    {
112        builder.timers.startStage05();
113        Printing.startStep(5);
114
115        ReadOnlyList<BuildPackage> packageSyncList;
116
117        if (builder.cli.userSpecifiedPackages != null)
118        {
119            packageSyncList = builder.cli.userSpecifiedPackages;
120
121            for (BuildPackage bp : packageSyncList) if (! bp.mustDocument)
122                throw new IllegalArgumentException("Not allowd to document: " + bp.fullName);
123        }
124
125        else packageSyncList = builder.packageList;
126
127        OSResponse      osr     = null;
128        StringBuilder   logOnly = new StringBuilder();
129
130        final AppendableSafe logAndScreen = new AppendableSafe(
131            new BiAppendable(System.out, logOnly),
132            AppendableSafe.USE_APPENDABLE_ERROR
133        );
134
135        // Uses Shell-Contructor:
136        // (outputAppendable, commandStrAppendable, standardOutput, errorOutput)
137
138        Shell       shell   = new Shell(logOnly, logAndScreen, null, null);
139        OSExtras    ose     = new OSExtras();
140
141        // GSUTIL gsutil = new GSUTIL(logOnly, logAndScreen, null, null);
142        builder.cloudSync.initStage05(logOnly, logAndScreen);
143
144        Stream.Builder<String> aclCommandB = Stream.builder();
145        Vector<String> copyDirs = new Vector<>(4);
146
147        for (BuildPackage bp : packageSyncList)
148        {
149            final String PN_FS =
150                builder.LOCAL_JAVADOC_DIR + bp.fullName.replace(".", FS) + FS;
151
152            final String PN_GCS =
153                builder.cli.GCS_DIR + "javadoc/" + bp.fullName.replace('.', '/') + '/';
154
155            logAndScreen.append("\nCopying Package HTML: " + BYELLOW + bp.fullName + RESET + '\n');
156            // osr = gsutil.CP(PN_FS + '*', PN_GCS);
157            osr = builder.cloudSync.copySingleJDPackageToCloud(PN_FS, PN_GCS);
158
159            Util.HALT_ON_ERROR(osr);
160
161            // The GSUTIL.MP (Make-Public) Command is called once at the very end.
162            aclCommandB.accept(PN_GCS + '*');
163
164            // Empty out the previous calls stuff
165            copyDirs.clear();
166
167            if (new java.io.File(PN_FS + "doc-files" + FS).exists())
168            {
169                copyDirs.add("doc-files" + FS);
170                aclCommandB.accept(PN_GCS + "doc-files" + FS + "**");
171            }
172
173            if (new java.io.File(PN_FS + "hilite-files" + FS).exists())
174            {
175                copyDirs.add("hilite-files" + FS);
176                aclCommandB.accept(PN_GCS + "hilite-files" + FS + "**");
177            }
178
179            if (new java.io.File(PN_FS + "stylesheets" + FS).exists())
180            {
181                copyDirs.add("stylesheets" + FS);
182                aclCommandB.accept(PN_GCS + "stylesheets" + FS + "**");
183            }
184
185            ose.currentWorkingDirectory = new File(PN_FS);
186            // gsutil.osExtras = ose;
187
188            logAndScreen.append(
189                "\nOSExtras.currentWorkingDirectory was assigned:  " +
190                BYELLOW + PN_FS + RESET + '\n'
191            );
192
193            // osr = gsutil.CP(copyDirs, PN_GCS, "-r");
194            builder.cloudSync.copyOtherPackageDirsToCloudDir(ose, copyDirs, PN_GCS);
195            Util.HALT_ON_ERROR(osr);
196        }
197
198        String[] makePublicArr = aclCommandB.build().toArray(String[]::new);
199
200        // My Cute little hack for the day.  This will make Stage 8 a lot faster.
201        // Well, this isn't considered a hack anymore, because it works pretty well.
202        //
203        // NOTE: Even if "Make-Public" isn't executed on a directory because that GCP Bucket
204        //       directory has been assigned "Bucket-Level Permissions", it will stll be necessary
205        //       to run the "Set Max Age" (Stage 8 Stuff), if the user has requested it!  Therefore
206        //       we cannot just 'discard' the 'makePublicArr' when RUN_MAKE_PUBLIC is false.
207
208        builder.stage8GCSDirs = makePublicArr;
209
210        // REMEMBER: if this is ever invoked on a bucket that has bucket-level
211        // permissions, instead of object level permissions, THIS WOULD CRASH.
212        //
213        // NOTE: the content of the 'aclCommandB' Stream.Builder are just wholly ignored and
214        //       discarded (eventually), by the garbage-collector if the Storage-Bucket has been
215        //       assigned Bucket-Level permissions instead of Object-Level Permissions.
216
217        if (builder.RUN_MAKE_PUBLIC)
218        {
219            // Print these so they are legible
220            logAndScreen.append(BGREEN + "\nMake Copied Files Public:\n\n" + RESET);
221            for (String gcsDir : makePublicArr) logAndScreen.append('\t' + gcsDir + "\n");
222            logAndScreen.append('\n');
223
224            // Now do the actual "Make Public" Command
225            // osr = gsutil.MP(makePublicArr);
226            osr = builder.cloudSync.makePublicDirArr(makePublicArr);
227            Util.HALT_ON_ERROR(osr);
228        }
229
230        logAndScreen.append(BGREEN + "\nClean Up:\n" + RESET);
231        osr = shell.RM(builder.LOCAL_JAVADOC_DIR, "-r");
232        Util.HALT_ON_ERROR(osr);
233
234        builder.logs.write_S05_LOG(logOnly.toString());
235        builder.cloudSync.endStage05();
236        builder.timers.endStage05();
237    }
238}