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 | package Torello.Java.Build;
import Torello.Java.FileNode;
import Torello.Java.RTC;
import Torello.Java.EXCC;
import Torello.Java.Additional.ByteArrClassLoader;
import Torello.Java.ReadOnly.ReadOnlyList;
import Torello.Java.ReadOnly.ReadOnlyArrayList;
import static Torello.Java.C.BYELLOW;
import static Torello.Java.C.BGREEN;
import static Torello.Java.C.BRED;
import static Torello.Java.C.BWHITE;
import static Torello.Java.C.BRED_BKGND;
import static Torello.Java.C.RESET;
import java.io.IOException;
import java.io.File;
// All this thing does is enter the "bp" directory that is passed to this class
// only method. That directory is, suprisingly, "bp.pkgRootDirector" + "data-files/".
//
// It scans the *ENTIRE* directory-tree (which, literally, just means that directory and also any
// and all sub-directories it has) for all Java '.class'-Files.
//
// Each '.class' File that is found is checked to see whether it is Assignable-To the interface
// "Torello.Java.Build.DataFileBuilderClass.class". If a '.class'-File is assignable into that
// interface, then it must have a 'build(String rootDir)' method. Any '.class' File which does
// implement that interface (and therefore has the 'build' method just mention) is invoked!
//
// IT IS UP TO THE USER TO MAKE SURE THAT THE SPECIFIED 'build(String)' METHOD ACTUALLY OUTPUTS
// ANY-AND-ALL DATA-FILES EXPECTED FOR THAT PACKAGE, INTO ITS "data-files/" SUB-DIRECTORY.
class RunDataFilesBuilders
{
@SuppressWarnings({"unchecked", "rawtypes"})
static int run(final BuildPackage bp) throws IOException
{
final ByteArrClassLoader bacl = new ByteArrClassLoader();
final String rootDir = bp.pkgRootDirectory + "data-files" + File.separator;
// Read All '.class' Files, and then generate a List<Class> of all of the Class-Files which
// implement the DataFileBuilderClass interface. Save those classes into a ReadOnlyList
@SuppressWarnings("rawtypes")
final ReadOnlyList<Class> dfbClasses = FileNode
.createRoot(rootDir)
.loadTree(-1, FileNode.CLASS_FILES, null)
.flattenJustFiles(RTC.FULLPATH_STREAM())
.map((String fileName) -> (Class) bacl.readJavaClassNOIOE(fileName))
.filter((Class c) -> DataFileBuilderClass.class.isAssignableFrom(c))
.collect(ReadOnlyArrayList.streamCollector());
// If there are no such classes, print a message and return immediately
if (dfbClasses.size() == 0)
{
System.out.println(
'\n' +
"Data-Files Directory:\n " + BYELLOW + rootDir + RESET + '\n' +
"Does not contain any '.class' Files which implement the DataFileBuilderClass " +
"interface\n\n" +
"Exiting..."
);
return 0;
}
// Iterate all classes which implemented the DataFileBuilderClass interface!
for (final Class c : dfbClasses)
{
final String cName = c.getCanonicalName();
System.out.println(
'\n' +
BRED_BKGND + BWHITE + " Running Class: " + RESET + ' ' +
BGREEN + cName + RESET + '\n'
);
final DataFileBuilderClass dfbc;
try
{ dfbc = (DataFileBuilderClass) c.getDeclaredConstructor().newInstance(); }
// NOTE: Catching Throwable-Class "Error" is extremely uncommon in Java, but this
// really is one of the places where you have to do it.f
//
// The Method "newInstance" throws an "ExceptionInInitializerError" if the user's
// Class throws an exception when attempting to build a new instance using the class'
// Zero-Argument Constructor.
//
// Not Exactly sure why ExceptionInInitializerError is an Error, rather than Exception,
// but I'm really not going to argue about it right now...
catch (Exception | Error e)
{
System.out.println(
EXCC.toString(e) + '\n' +
e.getMessage() + "\n\n" +
"For DataFileBuildClass:\n " + BYELLOW + cName + RESET + '\n' +
"Unable to invoke the Zero-Argument Constructor for that Class.\n" +
"Did you remember to declare a public, Zero-Argument Constructor?\n"
);
System.exit(0); /* shhh compiler !! */ throw null;
}
dfbc.build(rootDir);
}
System.out.println();
// This is the count on how many Class-Files 'build(String)' methods were invoked.
// It is placed into a Counts-Table, so that a Count-Summary may be printed at the end
// of the "BuildDataFiles" experience!
return dfbClasses.size();
}
}
|