package io.lumify.tools.version;
import static com.google.common.base.Preconditions.*;
import io.lumify.core.cmdline.CommandLineBase;
import java.io.File;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import io.lumify.core.version.BuildInfo;
import io.lumify.core.version.ProjectInfo;
import io.lumify.core.version.ProjectInfoScanner;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
/**
* This utility searches all elements of the target classpath for
* META-INF/lumify/*-build.properties files and outputs version
* information for all available Lumify components.
*/
public class VersionInspector extends CommandLineBase {
private static final String SEP_LINE = fill(60, '-');
private static final String SCAN_PATH = "scanpath";
private static final String fill(int count, char fillChar) {
StringBuilder builder = new StringBuilder();
for (int idx = 0; idx < count; idx++) {
builder.append(fillChar);
}
return builder.toString();
}
private ProjectInfoScanner scanner;
private OutputFormat format;
public VersionInspector() {
initFramework = false;
}
@Override
protected Options getOptions() {
Options options = super.getOptions();
options.addOption(OptionBuilder
.withLongOpt(SCAN_PATH)
.withDescription("The Java classpath to scan for Lumify project information. "
+ "This classpath may include both directories and zip archives (ZIP, JAR, EAR, WAR).")
.hasArg(true)
.withArgName(SCAN_PATH)
.isRequired()
.create());
options.addOption(OptionBuilder
.withLongOpt("short")
.withDescription("Write minimal details about each Lumify component.")
.create('s'));
options.addOption(OptionBuilder
.withLongOpt("verbose")
.withDescription("Write full details about each Lumify component.")
.create('v'));
return options;
}
@Override
protected void processOptions(final CommandLine cmd) throws Exception {
super.processOptions(cmd);
String scanPath = cmd.getOptionValue(SCAN_PATH);
checkNotNull(scanPath, "scanpath must be provided");
Set<File> scanFiles = new HashSet<File>();
for (String path : scanPath.trim().split(File.pathSeparator)) {
scanFiles.add(new File(path));
}
checkArgument(!scanFiles.isEmpty(), "scanpath must contain at least one element");
scanner = new ProjectInfoScanner(scanFiles);
if (cmd.hasOption('v')) {
format = OutputFormat.LONG;
} else if (cmd.hasOption('s')) {
format = OutputFormat.SHORT;
} else {
format = OutputFormat.NORMAL;
}
}
@Override
protected int run(CommandLine cmd) throws Exception {
Map<String, String[]> rows = new TreeMap<String, String[]>();
int colCount = 0;
for (ProjectInfo info : scanner) {
String[] row = format.format(info);
colCount = row.length;
rows.put(info.getName(), row);
}
if (!rows.isEmpty()) {
int[] maxColWidths = new int[colCount];
for (int col = 0; col < colCount; col++) {
maxColWidths[col] = 0;
}
for (String[] row : rows.values()) {
for (int col=0; col < colCount; col++) {
maxColWidths[col] = Math.max(maxColWidths[col], row[col].length());
}
}
StringBuilder output = new StringBuilder();
for (String[] row : rows.values()) {
if (row.length == 1) {
output.append(row[0]).append('\n');
} else {
for (int col=0; col < colCount; col++) {
output.append(String.format("%-" + maxColWidths[col] + "s", row[col])).append(" ");
}
output.append('\n');
}
}
System.out.print(output.toString());
} else {
System.out.println("No Lumify Components Found");
}
return 0;
}
private static enum OutputFormat {
SHORT,
NORMAL,
LONG;
public String[] format(final ProjectInfo info) {
switch (this) {
case SHORT: return VersionInspector.shortFormat(info);
case NORMAL: return VersionInspector.normalFormat(info);
case LONG: return VersionInspector.longFormat(info);
default: throw new IllegalStateException("Unknown OutputFormat: " + this);
}
}
}
private static String[] shortFormat(final ProjectInfo info) {
// lumify-core 1.0-SNAPSHOT [53b87d] Wednesday, February 12, 2014 00:08:49.049 EST
return new String[] {
info.getArtifactId(),
info.getVersion(),
String.format("[%s]", info.getScmRevision()),
info.getBuildInfo().getDate()
};
}
private static String[] normalFormat(final ProjectInfo info) {
// Lumify: Core (io.lumify:lumify-core:1.0-SNAPSHOT) [53b87d] Wednesday, February 12, 2014 00:08:49.049 EST
return new String[] {
info.getName(),
String.format("(%s)", info.getCoordinates()),
String.format("[%s]", info.getScmRevision()),
info.getBuildInfo().getDate()
};
}
private static String[] longFormat(final ProjectInfo info) {
// ---------------
// Project: Lumify: Core
// Group ID: io.lumify
// Artifact ID: lumify-core
// Version: 1.0-SNAPSHOT
// SCM Revision: 53b87d...
// Location: lumify-web.war::/WEB-INF/lib/lumify-core.jar::/META-INF/lumify/lumify-core-build.properties
// Built On: Wednesday, February 12, 2014 00:08:49.049 EST
// Built By: gshankman
// Build Platform: Mac OS X 10.9.1 (x86_64)
// Build JVM: 1.7.0_51-b13 (Oracle Corporation)
// Built By Maven: 3.1.1
// ---------------
BuildInfo build = info.getBuildInfo();
return new String[] {
new StringBuilder()
.append(SEP_LINE).append('\n')
.append("Project: ").append(info.getName()).append('\n')
.append("Group ID: ").append(info.getGroupId()).append('\n')
.append("Artifact ID: ").append(info.getArtifactId()).append('\n')
.append("Version: ").append(info.getVersion()).append('\n')
.append("SCM Revision: ").append(info.getScmRevision()).append('\n')
.append("Location: ").append(info.getSource()).append('\n')
.append("Built On: ").append(build.getDate()).append('\n')
.append("Built By: ").append(build.getUser()).append('\n')
.append("Build Platform: ").append(build.osSpec()).append('\n')
.append("Build JVM: ").append(build.jvmSpec()).append('\n')
.append("Built By Maven: ").append(build.getMavenVersion()).append('\n')
.append(SEP_LINE).append('\n')
.toString()
};
}
public static void main(String[] args) throws Exception {
int res = new VersionInspector().run(args);
if (res != 0) {
System.exit(res);
}
}
}