EnumSet<Order> phasePre = EnumSet.of(Order.PRE, Order.PRIMARY);
EnumSet<Order> phasePost = EnumSet.of(Order.POST);
// Instantiate instances of the Linkers
for (Class<? extends Linker> clazz : linkerClasses) {
Linker linker;
// Create an instance of the Linker
try {
linker = clazz.newInstance();
linkerStack.push(linker);
} catch (InstantiationException e) {
logger.log(TreeLogger.ERROR, "Unable to create LinkerContextShim", e);
throw new UnableToCompleteException();
} catch (IllegalAccessException e) {
logger.log(TreeLogger.ERROR, "Unable to create LinkerContextShim", e);
throw new UnableToCompleteException();
}
// Detemine if we need to invoke the Linker in the current link phase
Order order = clazz.getAnnotation(LinkerOrder.class).value();
if (!phasePre.contains(order)) {
continue;
}
// The primary Linker is guaranteed to be last in the order
if (order == Order.PRIMARY) {
assert linkerClasses.get(linkerClasses.size() - 1).equals(clazz);
}
TreeLogger linkerLogger = logger.branch(TreeLogger.TRACE,
"Invoking Linker " + linker.getDescription(), null);
workingArtifacts.freeze();
try {
workingArtifacts = linker.link(linkerLogger, this, workingArtifacts);
} catch (Exception e) {
linkerLogger.log(TreeLogger.ERROR, "Failed to link", e);
throw new UnableToCompleteException();
}
}
// Pop the primary linker off of the stack
linkerStack.pop();
// Unwind the stack
while (!linkerStack.isEmpty()) {
Linker linker = linkerStack.pop();
Class<? extends Linker> linkerType = linker.getClass();
// See if the Linker should be run in the current phase
Order order = linkerType.getAnnotation(LinkerOrder.class).value();
if (phasePost.contains(order)) {
TreeLogger linkerLogger = logger.branch(TreeLogger.TRACE,
"Invoking Linker " + linker.getDescription(), null);
workingArtifacts.freeze();
try {
workingArtifacts = linker.link(linkerLogger, this, workingArtifacts);
} catch (Exception e) {
linkerLogger.log(TreeLogger.ERROR, "Failed to link", e);
throw new UnableToCompleteException();
}
}