001package Torello.Java.Build; 002 003import Torello.Java.FileNodeFilter; 004import Torello.Java.ReadOnly.ReadOnlyList; 005import Torello.Java.ReadOnly.ROVectorBuilder; 006 007import java.io.File; 008import java.util.Objects; 009 010public class JarInclude 011{ 012 // This is a Package-Visible Inner-Class. It is only usable inside Torello.Java.Build 013 // Instances of this class are included in the ReadOnlyList returned by method 014 // getAllDesriptors. This is also a Package-Visible method 015 016 static class Descriptor 017 { 018 final String workingDirectory, subDirectory; 019 final boolean traverseTree; 020 final FileNodeFilter fileFilter, dirFilter; 021 022 Descriptor( 023 String workingDirectory, 024 String subDirectory, 025 boolean traverseTree, 026 FileNodeFilter fileFilter, 027 FileNodeFilter dirFilter 028 ) 029 { 030 this.workingDirectory = workingDirectory; 031 this.subDirectory = subDirectory; 032 this.traverseTree = traverseTree; 033 this.fileFilter = fileFilter; 034 this.dirFilter = dirFilter; 035 } 036 037 public String toString() { return workingDirectory + subDirectory; } 038 } 039 040 /** Build an instance of this class */ 041 public JarInclude() { } 042 043 private final ROVectorBuilder<JarInclude.Descriptor> descriptors = 044 new ROVectorBuilder<>(); 045 046 // This is only invoked by class Builder 047 ReadOnlyList<JarInclude.Descriptor> getAllDesriptors() { return descriptors.build(); } 048 049 private static final String M1 = "Parameter '"; 050 private static final String M2 = "' was passed null, but this is not allowed"; 051 052 /** 053 * Convenience Method. 054 * <BR />Adds a Jar-Include Directive that <B>DOES NOT</B> recurse the directory-tree 055 * <BR />Invokes: {@link #add(String, String, boolean, FileNodeFilter, FileNodeFilter)} 056 */ 057 public JarInclude add( 058 String workingDirectory, 059 String subDirectory, 060 FileNodeFilter fileFilter 061 ) 062 { return add(workingDirectory, subDirectory, false, fileFilter, null); } 063 064 /** 065 * Inserts a request for files to be included in the Tar-Jar Build Stage (Stage 4). 066 * 067 * @param workingDirectory When files are added to a {@code '.jar'}-File, the "Working 068 * Directory" part of the File-System Path <B>is not included</B> in the name of the files that 069 * are inserted. 070 * 071 * @param subDirectory The "Sub-Directory" part of the File-System Path <B>is included</B> into 072 * the names of any and all files that are inserted in the {@code '.jar'}. 073 * 074 * @param traverseTree Indicates whether the the {@code String}-Parameter 075 * {@code 'subDirectory'} should be interpreted as a directory-name - <I>or as an entire tree 076 * branch</I> whose own sub-directories should be traversed by the file-scanner. 077 * 078 * @param fileFilter A filter / "chooser" / specifier for deciding which files residing on the 079 * File-System inside {@code 'subDirectory'} (or {@code 'subDirectory'}, and its own 080 * sub-directories - in the case that {@code 'traverseTree'} was passed {@code TRUE}), are to 081 * be included in the {@code '.jar'}. 082 * 083 * <BR /><BR />This filter must return {@code TRUE} if a file this filter is testing 084 * <B><I>should</I></B> be inserted into the {@code '.jar'}, and {@code FALSE}, if the file 085 * <B><I>should not</I></B> be. 086 * 087 * <BR /><BR />This parameter may be passed null, and if it is it will be quietly ignored. 088 * When this filter is null, all files that reside within {@code 'subDirectory'} will be 089 * inserted into the {@code '.jar'}-File. 090 * 091 * <BR /><BR />If this parameter were passed null, and {@code 'traverseTree'} were passed 092 * {@code TRUE}, then all files inside of {@code 'subDirectory'} would be inserted into the 093 * {@code '.jar'} - <I>and furthermore, all files in all sub-directories of 094 * {@code 'subDirectory'} would also be inserted</I>. 095 * 096 * @param dirFilter This filter can only be employed if {@code 'traverseTree'} has been passed 097 * {@code TRUE}. 098 * 099 * <BR /><BR />When {@code 'traverseTree'} is {@code TRUE} as the directory tree rooted at 100 * {@code workingDirectory/subDirectory/} is traversed, each sub-directory that is encountered 101 * will be passed to this filter. When this test is performed, the filter should return 102 * {@code TRUE} to indicate that it would like a particular sub-directory searched, and 103 * {@code FALSE} to indicate that it must be skipped. 104 * 105 * <BR /><BR />This parameter may be passed null, and if it is it will be silently ignored. 106 * If this parameter is null, and {@code 'traverseTree'} is {@code TRUE}, all sub-directories 107 * of {@code workingDirectory/subDirectory/} will be entered / traversed. 108 * 109 * <BR /><BR ><B>NOTE:</B> If this parameter is passed a non-null filter, but 110 * {@code 'traverseTree'} has been passed {@code FALSE}, then an 111 * {@code IllegalArgumentException} will throw. Parameter {@code 'dirFilter'} has no use or 112 * application if the named directory-tree is not going to be traversed! 113 * 114 * @return {@code 'this'} instance, for convenience and invocation-chaining. 115 * 116 * @throws NullPointerException If either {@code 'workingDirectory'} or {@code 'subDirectory'} 117 * is passed null. 118 * 119 * @throws IllegalArgumentException If either {@code 'workingDirectory'} or 120 * {@code 'subDirectory'} do not name real directories that actually exist on the File-System. 121 * 122 * <BR /><BR />This exception will also throw if {@code 'traverseTree'} is passed {@code FALSE} 123 * but {@code 'dirFilter'} is non-null. 124 */ 125 public JarInclude add( 126 String workingDirectory, 127 String subDirectory, 128 boolean traverseTree, 129 FileNodeFilter fileFilter, 130 FileNodeFilter dirFilter 131 ) 132 { 133 File f; 134 135 Objects.requireNonNull(workingDirectory, M1 + "workingDirectory" + M2); 136 Objects.requireNonNull(subDirectory, M1 + "subDirectory" + M2); 137 138 if (workingDirectory.length() > 0) 139 { 140 f = new File(workingDirectory); 141 142 if (! f.exists()) throw new IllegalArgumentException( 143 "The directory-name provided to parameter 'workingDirectory' does not exist on " + 144 "the File-System:\n[" + workingDirectory + ']' 145 ); 146 147 if (! f.isDirectory()) throw new IllegalArgumentException( 148 "The directory-name provided to parameter 'workingDirectory' is not the name of " + 149 "an actual File-System directory:\n[" + workingDirectory + ']' 150 ); 151 } 152 153 if (! workingDirectory.endsWith(File.separator)) 154 if (workingDirectory.length() > 0) 155 workingDirectory = workingDirectory + File.separator; 156 157 String subDir = workingDirectory + subDirectory; 158 159 if (subDir.length() > 0) 160 { 161 f = new File(subDir); 162 163 if ((! f.exists()) || (! f.isDirectory())) throw new IllegalArgumentException( 164 "The directory-name provided to parameter 'subDirectory' does not exist on the " + 165 "File-System as a Sub-Directory of 'workingDirectory':\n" + 166 "[" + subDirectory + ']' 167 ); 168 } 169 170 if (! subDirectory.endsWith(File.separator)) 171 if (subDirectory.length() > 0) 172 subDirectory = subDirectory + File.separator; 173 174 if ((! traverseTree) && (dirFilter != null)) throw new IllegalArgumentException( 175 "You have passed FALSE to 'traverseTree', but a non-null filter to parameter " + 176 "'dirFilter'. This is not allowed." 177 ); 178 179 this.descriptors.add 180 (new Descriptor(workingDirectory, subDirectory, traverseTree, fileFilter, dirFilter)); 181 182 return this; 183 } 184}