001package Torello.Java.Build; 002 003import Torello.JavaDoc.Upgrade; 004 005import Torello.Java.Verbosity; 006import Torello.Java.StrCmpr; 007import Torello.Java.EmptyListException; 008import Torello.Java.WritableDirectoryException; 009import Torello.Java.GSUTIL; // Needed for a javadoc '@link' 010 011import Torello.Java.ReadOnly.ReadOnlyList; 012 013import Torello.HTML.Tools.Images.IF; 014 015import java.io.File; 016import java.io.FileNotFoundException; 017 018import java.util.Objects; 019import java.util.regex.Pattern; 020 021import java.util.function.Consumer; 022import java.util.function.Predicate; 023 024/** 025 * This class provides a list of fields, all of which may be modified and configured, for providing 026 * any needed settings to class {@link Builder}. 027 * 028 * <BR /><BR />Use the {@code public} constructor offered by this class, and then set and change 029 * the values of any of the Configuration-Fields. Once this class Configuration-Fields have been 030 * appropriately set to contain your project's data, pass the instance to the {@link Builder} class 031 * only constructor (along with an argv {@code String[]}-Array). 032 * 033 * <BR /><BR />This will inform the {@code Builder}-Constructor of all of your nedded settings, and 034 * once built, will make running your project's build script very easy. 035 */ 036public final class Config 037{ 038 // ******************************************************************************************** 039 // ******************************************************************************************** 040 // Validator Constants 041 // ******************************************************************************************** 042 // ******************************************************************************************** 043 044 045 /** 046 * Project-Name validation {@code String}. The value passed to configuration field/parameter 047 * must match this regular expression. This is used in this class {@link #validate()} method. 048 * 049 * @see #PROJECT_NAME 050 * @see Builder#PROJECT_NAME 051 * @see #validate() 052 */ 053 public static final Predicate<String> projectNameValidator = 054 Pattern.compile("^\\w[\\w\\d]*$").asPredicate(); 055 056 057 // ******************************************************************************************** 058 // ******************************************************************************************** 059 // Configuration Instance Fields 060 // ******************************************************************************************** 061 // ******************************************************************************************** 062 063 064 /** 065 * To-Do, Explain This 066 * @see Builder#HOME_DIR 067 */ 068 public String HOME_DIR = null; 069 070 /** 071 * The File-System Directory-Location where Java-Doc Output is sent for storage. Also the 072 * directory that the Upgrader searches to retrieve and parse JavaDoc Files. 073 * 074 * @see Builder#LOCAL_JAVADOC_DIR 075 */ 076 public String LOCAL_JAVADOC_DIR = "javadoc" + java.io.File.separator; 077 078 /** 079 * A simple name for this Project. Name must pass the {@link #projectNameValidator} 080 * Regular-Expression. 081 * 082 * @see Builder#PROJECT_NAME 083 * @see #projectNameValidator 084 */ 085 public String PROJECT_NAME = null; 086 087 /** 088 * The Major Version Number of the Current Build. This class {@link #validate()} method checks 089 * to ensure that this field contains a positive integer / byte value. 090 * 091 * @see Builder#VERSION_MAJOR_NUMBER 092 */ 093 public byte VERSION_MAJOR_NUMBER = 1; 094 095 /** 096 * The Minor Version Number of the Current Build. This class {@link #validate()} method checks 097 * to ensure that this field contains a positive integer / byte value. 098 * 099 * @see Builder#VERSION_MINOR_NUMBER 100 */ 101 public byte VERSION_MINOR_NUMBER = 0; 102 103 /** 104 * The full or partial Path-Name of the {@code 'javac'} binary to use for compiling this 105 * project. This parameter / field may not be null, or a {@code NullPointerException} will 106 * throw. 107 * 108 * <BR /><BR /><B CLASS=JDDescLabel>Default Setting:</B> 109 * 110 * <BR />The default setting for this Configuration-Field is just the command name, which 111 * is to presume that the {@code PATH} environment-variable has been set to facilitate finding 112 * {@code 'javac'} 113 * 114 * @see Builder#JAVAC_BIN 115 */ 116 public String JAVAC_BIN = "javac"; 117 118 /** 119 * The full or partial Path-Name of the {@code 'javac'} binary to use for compiling this 120 * project. This parameter / field may not be null, or a {@code NullPointerException} will 121 * throw. 122 * 123 * <BR /><BR /><B CLASS=JDDescLabel>Default Setting:</B> 124 * 125 * <BR />The default setting for this Configuration-Field is just the command name, which 126 * is to presume that the {@code PATH} environment-variable has been set to facilitate finding 127 * {@code 'javadoc'}. 128 * 129 * @see Builder#JAVADOC_BIN 130 */ 131 public String JAVADOC_BIN = "javadoc"; 132 133 /** 134 * The number to provide to the {@code --release} switch to {@code javac}. This number may be 135 * set to any negative value, and it will prevent the {@code Builder} from using this switch at 136 * all 137 * 138 * @see Builder#JAVA_RELEASE_NUM_SWITCH 139 */ 140 public byte JAVA_RELEASE_NUM_SWITCH = -1; 141 142 /** 143 * Currently unused, but originally used to indicate the {@code javadoc} version being used 144 * @see Builder#JAVADOC_VER 145 */ 146 public byte JAVADOC_VER = 11; 147 148 /** 149 * If the <B>Stage 3</B> {@link Upgrade}-Process utilizes a favicon on its Web-Pages, then this 150 * field may be assigned to the location on disk where that favicon is located. 151 * 152 * <BR /><BR />When this field contains a non-null Image-File, that image will be copied (after 153 * upgrade has completed) directly to the {@code 'javadoc'} output directory. When this field 154 * is left null, it will be ignored and no favicon image is copied. 155 * 156 * @see Builder#FAVICON 157 */ 158 public String FAVICON = null; 159 160 /** 161 * Source-Directory to be used as root directory for archiving 162 * @see Builder#TAR_SOURCE_DIR 163 */ 164 public String TAR_SOURCE_DIR = null; 165 166 /** 167 * The Google Cloud Platform Storage-Bucket into which jar, log & documentation files will 168 * be copied by this Build-Tool. This Storage-Bucket Directory is intended for use with a 169 * boiler-plate & "still under development" {@code URL}. 170 * 171 * <BR /><BR />If this parameter remains null, several of the user menu options will be 172 * removed, because several are designed for coying data to the Developer Site. When it is 173 * null such options are removed, and this Configuration-Field is ignored. 174 * 175 * @see Builder#GCS_DIR_DEV 176 * @see #GCS_DIR_RELEASE 177 * @see Builder#GCS_DIR_RELEASE 178 */ 179 public String GCS_DIR_DEV = null; 180 181 /** 182 * Another Google Cloud Platform Storage-Bucket for storing and providing jar, log & 183 * Code-Documentation Files. 184 * 185 * <BR /><BR />Similary to Configuration-Field {@link #GCS_DIR_DEV}, this parameter may also be 186 * null, and when it is it will be ignored, but a few User-Interface Menu-Options will not be 187 * present at the Build-Menu. 188 * 189 * @see Builder#GCS_DIR_RELEASE 190 * @see #GCS_DIR_DEV 191 * @see Builder#GCS_DIR_DEV 192 */ 193 public String GCS_DIR_RELEASE = null; 194 195 /** 196 * Informs the Build-Tool whether or not the {@link GSUTIL} method for making the output 197 * directory content public needs to be run. This {@code boolean} controls whether or not 198 * {@code javadoc} content synchronized / copied to the {@link #GCS_DIR_DEV} is assigned the 199 * public read-only access level. 200 * 201 * <BR /><BR />When {@link #GCS_DIR_DEV} is left null, thi flag is ignored. 202 * 203 * <BR /><BR />There is also a {@code boolean} setting for the {@link #GCS_DIR_RELEASE} flag. 204 * 205 * <BR /><BR />The default setting for both of these flags is {@code FALSE}. 206 * 207 * @see #GCS_DIR_DEV 208 * @see Builder#GCS_DIR_DEV 209 * @see #RUN_MAKE_PUBLIC_RELEASE 210 */ 211 public boolean RUN_MAKE_PUBLIC_DEV = false; 212 213 /** 214 * Informs the Build-Tool whether or not the {@link GSUTIL} method for making the output 215 * directory content public needs to be run. This {@code boolean} controls whether or not 216 * {@code javadoc} content synchronized / copied to the {@link #GCS_DIR_RELEASE} is assigned 217 * the public read-only access level. 218 * 219 * <BR /><BR />When {@link #GCS_DIR_RELEASE} is left null, thi flag is ignored. 220 * 221 * <BR /><BR />There is also a {@code boolean} setting for the {@link #GCS_DIR_DEV} flag. 222 * 223 * <BR /><BR />The default setting for both of these flags is {@code FALSE}. 224 * 225 * @see #GCS_DIR_RELEASE 226 * @see Builder#GCS_DIR_RELEASE 227 * @see #RUN_MAKE_PUBLIC_DEV 228 */ 229 public boolean RUN_MAKE_PUBLIC_RELEASE = false; 230 231 /** 232 * A Storage-Bucket on Google Cloud Platform for saving the generated backup {@code '.tar'} 233 * File. This Configuration-Field may remain null, and if it is it will be silently ignored. 234 * In this case, the generated backup {@code '.tar'} File will not be copied onto any Google 235 * Cloud Platform Storage-Buckets. 236 * 237 * @see Builder#BACKUP_TAR_FILE_GCS_DIR 238 */ 239 public String BACKUP_TAR_FILE_GCS_DIR = null; 240 241 /** 242 * This optional configuration field is optional, and may be used to move / relocate the 243 * {@code '.jar'} File after it's built by this Build-Processor. If there is a diretory or 244 * location on the File-System into which the {@code '.jar'} should be moved, then provide that 245 * directory's name here. 246 * 247 * <BR /><BR />When this field is left null, it will be silently ignored; furthermore, the 248 * {@code '.jar'} File which the Build-Processor creates will be left in the Current Working 249 * Directory. 250 */ 251 public String JAR_FILE_MOVE_DIR = null; 252 253 /** 254 * The directory location where log information will be saved. This configuration field may 255 * not be null, or a {@code NullPointerException} will throw. 256 */ 257 public String LOG_DIR = null; 258 259 /** 260 * The <B>Stage 3</B> {@link Upgrade} instance to invoke. This parameter-field configuration 261 * may not be null, or a {@code NullPointerException} will throw. 262 */ 263 public Upgrade upgrader = null; 264 265 /** 266 * The script invoked <B STYLE='color: red'><I>before</I></B> the <B>Stage 3</B> call to 267 * {@link Upgrade}. This configuration may be assigned null, and in such cases, no script will 268 * be invoked before the upgrader runs. 269 * 270 * @see Builder#preUpgraderScript 271 */ 272 public UpgradeProcessor preUpgraderScript = null; 273 274 /** 275 * The script invoked <B STYLE='color: red'><I>after</I></B> the <B>Stage 3</B> call to 276 * {@link Upgrade}. This configuration may be assigned null, and in such cases, no script will 277 * be invoked before the upgrader runs. 278 * 279 * @see Builder#postUpgraderScript 280 */ 281 public UpgradeProcessor postUpgraderScript = null; 282 283 /** 284 * For Stage 1, the Java-Compiler Stage, this Configuration-Field may be assigned any 285 * switch-{@code String's}, and they will be passed to the {@code javac} invocation. 286 * 287 * <BR /><BR />This field's value may be left null, or assigned a zero-length 288 * {@code String[]}-Array and, in both cases, it shall be ignored. 289 * 290 * @see Builder#extraSwitchesJAVAC 291 */ 292 public String[] extraSwitchesJAVAC = null; 293 294 /** 295 * For Stage 2, the {@code javadoc} Stage, this Configuration-Field may be assigned any 296 * switch-{@code String's}, and they will be passed to the {@code javadoc} invocation. 297 * 298 * <BR /><BR />This field's value may be left or null, or assigned a zero-length 299 * {@code String[]}-Array, and, in both cases, it shall be ignored. 300 * 301 * @see Builder#extraSwitchesJAVADOC 302 */ 303 public String[] extraSwitchesJAVADOC = null; 304 305 /** 306 * The list of Java Packages to compile. This list may be neither empty nor null, or an 307 * exception will throw. 308 * 309 * @see Builder#packageList 310 */ 311 public BuildPackage[] packageList = null; 312 313 /** 314 * The Root Class-File Directories to use with {@code 'javac'}. This is used to generate the 315 * value passed to the {@code -cp} switch passed when <B>Stage 1</B> invokes the Java-Compiler. 316 * This parameter / field may be empty or null, and if it is, it will be ignored. 317 */ 318 public String[] CLASS_PATH = null; 319 320 /** 321 * This allows for specifying a list of files to manually add into the {@code '.jar'} that is 322 * built by this package. 323 * 324 * <BR /><BR /><B CLASS=JDDescLabel>Constructor Call:</B> 325 * 326 * <BR />Because it isn't necessary to include any "Extra Files" into the {@code '.jar'}, there 327 * is some likelihood that this Configuration-Field wouldn't ever be needed / used. Make sure 328 * to call the {@link JarInclude} constructor, first, to build an instance of this Config-Field 329 * before attempting to use it. Notice that it is initially initialized to null! 330 * 331 * <BR /><BR /><B CLASS=JDDescLabel>Common Usess:</B> 332 * 333 * <BR />Java-HTML has quite a few Data-Files that are inserted into the Jar-File, manually, 334 * using this class. There may also be the need to insert {@code META-INF/} directory files 335 * that name things like Annotation-Processor locations, taglets, or other Java Services. 336 * 337 * @see Builder#jarIncludes 338 */ 339 public JarInclude jarIncludes = null; 340 341 /** 342 * Requests that when {@code 'javac'} is invoked, the switch {@code -Xlint:all,-processing} is 343 * included in the command-line invocation. 344 * 345 * @see Builder#USE_XLINT_SWITCH 346 */ 347 public boolean USE_XLINT_SWITCH = true; 348 349 /** 350 * Requests that when {@code 'javac'} is invoked, the switch {@code -Xdiags:verbose} is 351 * included in the command-line invocation. 352 * 353 * @see Builder#USE_XDIAGS_SWITCH 354 */ 355 public boolean USE_XDIAGS_SWITCH = true; 356 357 /** 358 * JavaDoc Frames were a true majesty that should never have been eliminated. If you would 359 * prefer to remove them, or you are using JDK 21+ which no longer accepts the {@code --frames} 360 * switch, then set this Configuration-Field to {@code FALSE}. 361 * 362 * @see Builder#NO_JAVADOC_FRAMES_SWITCH 363 */ 364 public boolean NO_JAVADOC_FRAMES_SWITCH = false; 365 366 367 // ******************************************************************************************** 368 // ******************************************************************************************** 369 // Configuration Instance Fields 370 // ******************************************************************************************** 371 // ******************************************************************************************** 372 373 374 /** 375 * Creates an instance of this class, with all default values assigned to the parameter / 376 * fields. 377 * 378 * <BR /><BR />The intention is that an instance of this class will have its 379 * Configuration-Fields property assigned, according to the needs of the Project being built. 380 * Afterwards, the {@code 'Config'} instance may be passed to the {@code 'Builder'}-Constructor 381 * and then that instance may be used to build the project. 382 * 383 * @see Builder#Builder(Config, String...) 384 * @see Builder#build() 385 */ 386 public Config() { } 387 388 389 // ******************************************************************************************** 390 // ******************************************************************************************** 391 // Configuration Instance Fields 392 // ******************************************************************************************** 393 // ******************************************************************************************** 394 395 396 /** 397 * Used by class {@link Builder} to validate all user-provided data on a best efforts basis. 398 * 399 * @throws NullPointerException If any of the configuration parameter/fields listed here have 400 * been assigned null 401 * 402 * <BR /><UL CLASS=JDUL> 403 * <LI>{@link #LOCAL_JAVADOC_DIR}</LI> 404 * <LI>{@link #PROJECT_NAME}</LI> 405 * <LI>{@link #JAVAC_BIN}</LI> 406 * <LI>{@link #JAVADOC_BIN}</LI> 407 * <LI>{@link #TAR_SOURCE_DIR}</LI> 408 * <LI>{@link #LOG_DIR}</LI> 409 * <LI>{@link #upgrader}</LI> 410 * <LI>{@link #packageList}</LI> 411 * </UL> 412 * 413 * <BR />This exception will also be thrown if these lists contain any null-valued 414 * entries: 415 * <BR /><UL CLASS=JDUL> 416 * <LI>{@link #packageList}</LI> 417 * <LI>{@link #CLASS_PATH}</LI> 418 * </UL> 419 * 420 * @throws IllegalArgumentException If any of these configuration fields were assigned a 421 * negative number: 422 * <BR /><UL CLASS=JDUL> 423 * <LI>{@link VERSION_MAJOR_NUMBER}</LI> 424 * <LI>{@link VERSION_MINOR_NUMBER}</LI> 425 * <LI>{@link JAVADOC_VER}</LI> 426 * </UL> 427 * 428 * <BR />This exception will also be thrown if: 429 * <BR /><UL CLASS=JDUL> 430 * <LI> {@link #PROJECT_NAME} does not pass the {@link #projectNameValidator} test.</LI> 431 * </UL> 432 * 433 * @throws FileNotFoundException This exception will throw if either of these fields are not 434 * assigned a valid File-System Directory-Name: 435 * <BR /><UL CLASS=JDUL> 436 * <LI> {@link #FAVICON}</LI> 437 * <LI> {@link #TAR_SOURCE_DIR}</LI> 438 * </UL> 439 * 440 * @throws UnrecognizedImageExtException If the {@link #FAVICON} Image-Format cannot be 441 * properly "guessed" by class {@link IF}. 442 * 443 * @throws EmptyListException If {@link #packageList} has been assigned an empty list. 444 * 445 * @throws WriteableDirectoryException If parameter {@link #JAR_FILE_MOVE_DIR} is assigned a 446 * non-null value, but the {@code String} assigned it does not point to a File-System 447 * directory, or that directory is not writeable. 448 * 449 * <BR /><BR />Also throws if {@link #LOG_DIR} is not a valid directory-name, that allows 450 * write-access. 451 */ 452 public final void validate() throws java.io.FileNotFoundException 453 { 454 Objects.requireNonNull(LOCAL_JAVADOC_DIR, M1 + "LOCAL_JAVADOC_DIR" + M2); 455 Objects.requireNonNull(PROJECT_NAME, M1 + "PROJECT_NAME" + M2); 456 Objects.requireNonNull(JAVAC_BIN, M1 + "JAVAC_BIN" + M2); 457 Objects.requireNonNull(JAVADOC_BIN, M1 + "JAVADOC_BIN" + M2); 458 Objects.requireNonNull(TAR_SOURCE_DIR, M1 + "TAR_SOURCE_DIR" + M2); 459 Objects.requireNonNull(LOG_DIR, M1 + "LOG_DIR" + M2); 460 Objects.requireNonNull(upgrader, M1 + "upgrader" + M2); 461 Objects.requireNonNull(packageList, M1 + "packageList" + M2); 462 463 if (! projectNameValidator.test(PROJECT_NAME)) throw new IllegalArgumentException 464 (M1 + "PROJECT_NAME] was not passed a valid name."); 465 466 if (VERSION_MAJOR_NUMBER < 0) throw new IllegalArgumentException 467 (M1 + "VERSION_MAJOR_NUMBER" + M3 + VERSION_MAJOR_NUMBER); 468 469 if (VERSION_MINOR_NUMBER < 0) throw new IllegalArgumentException 470 (M1 + "VERSION_MINOR_NUMBER" + M3 + VERSION_MINOR_NUMBER); 471 472 if (JAVADOC_VER < 0) throw new IllegalArgumentException 473 (M1 + "JAVADOC_VER" + M3 + JAVADOC_VER); 474 475 if (FAVICON != null) 476 { 477 File f = new File(FAVICON); 478 479 if ((! f.exists()) || (! f.isFile())) throw new FileNotFoundException( 480 "Field 'FAVICON' [" + FAVICON + "] points to a file that was not found, or " + 481 "isn't a File" 482 ); 483 484 IF.guessOrThrow(FAVICON); 485 } 486 487 if (packageList.length == 0) throw new EmptyListException 488 (M1 + "packageList] was passed a list of size 0."); 489 490 for (BuildPackage bp : packageList) if (bp == null) throw new NullPointerException 491 (M1 + "packageList] contains a null value."); 492 493 for (String p : CLASS_PATH) if (p == null) throw new NullPointerException 494 (M1 + "CLASS_PATH] contains a null value."); 495 496 File f = new File(TAR_SOURCE_DIR); 497 if (! (f.exists() && f.isDirectory())) throw new FileNotFoundException 498 (M1 + "] was not passed a vaild File-System Directory-Name."); 499 500 if (JAR_FILE_MOVE_DIR != null) 501 { 502 WritableDirectoryException.check(JAR_FILE_MOVE_DIR); 503 504 if (! JAR_FILE_MOVE_DIR.endsWith(File.separator)) 505 JAR_FILE_MOVE_DIR = JAR_FILE_MOVE_DIR + File.separator; 506 } 507 508 WritableDirectoryException.check(LOG_DIR); 509 510 if (! LOG_DIR.endsWith(File.separator)) LOG_DIR = LOG_DIR + File.separator; 511 } 512 513 private static final String M1 = "The Parameter-Field Configuration ["; 514 private static final String M2 = "] was ultimately assigned null."; 515 private static final String M3 = "] was passed a negative number: "; 516 517 final String classPathStr(boolean INCLUDE_JAR_IN_CP, String JAR_FILE_NAME) 518 { 519 if (CLASS_PATH == null) return INCLUDE_JAR_IN_CP ? JAR_FILE_NAME : null; 520 521 final String sep = StrCmpr.containsIgnoreCase(System.getProperty("os.name"), "win") 522 ? ";" 523 : ":"; 524 525 final StringBuilder sb = new StringBuilder(); 526 527 for (int i=0; i < CLASS_PATH.length; i++) sb.append(((i==0) ? "" : sep) + CLASS_PATH[i]); 528 529 if (INCLUDE_JAR_IN_CP) sb.append(sep + JAR_FILE_NAME); 530 531 return sb.toString(); 532 } 533}