mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
- Added programmatic access to BuildID and Version through methods on FModel.getBuildInfo().
- Added class forge.model.BuildInfo with unit test. - Added unit test for forge.model.FModel. - Added exception class forge.model.MultipleForgeJarsFoundError. - Updated forge.view.swing.Main with some preliminary code for progress monitoring. - Reduced CheckStyle, FindBugs, and PMD violations in these files and in net.slightlymagic.braids.util.testng.BraidsAssertFunctions. - Added missing package-info in net.slightlymagic.braids.util.testng.
This commit is contained in:
234
src/main/java/forge/model/BuildInfo.java
Normal file
234
src/main/java/forge/model/BuildInfo.java
Normal file
@@ -0,0 +1,234 @@
|
||||
package forge.model;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Provides access to information about the current version and build ID.
|
||||
*/
|
||||
public class BuildInfo {
|
||||
/** Exception-free means of getting the ASCII Charset. */
|
||||
public static final Charset US_ASCII_CHARSET = Charset.forName("US-ASCII");
|
||||
|
||||
/** Convenience for file.separator. */
|
||||
private static final String FILE_SEP = System.getProperty("file.separator");
|
||||
|
||||
/** Convenience for path.separator. */
|
||||
private static final String PATH_SEP = System.getProperty("path.separator");
|
||||
|
||||
private static final Pattern FORGE_JAR_REGEX_2G = // NOPMD by Braids on 8/12/11 10:18 AM
|
||||
Pattern.compile("^(.*" + Pattern.quote(FILE_SEP) + ")?"
|
||||
+ Pattern.quote("forge-")
|
||||
+ "([^" + Pattern.quote(FILE_SEP) + Pattern.quote(PATH_SEP) + "]*)"
|
||||
+ Pattern.quote("-with-dependencies.jar") + "$",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
|
||||
|
||||
private transient String pathToForgeJar;
|
||||
|
||||
/**
|
||||
* Construct a standard BuildInfo object.
|
||||
*
|
||||
* Package access is intentional for unit testing.
|
||||
*
|
||||
* @see FModel.getBuildInfo()
|
||||
*/
|
||||
BuildInfo() {
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit-testable constructor which allows a specific jar file to be set.
|
||||
*
|
||||
* Dependency injection! Relax, this won't hurt a bit.
|
||||
*
|
||||
* @param pathToMockJarFile where to find the mock Forge jar
|
||||
*/
|
||||
public BuildInfo(final String pathToMockJarFile) {
|
||||
pathToForgeJar = pathToMockJarFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current build ID for Forge.
|
||||
*
|
||||
* @return a String representing the build identifier, or null if we could
|
||||
* not determine the value.
|
||||
*/
|
||||
public final String getBuildID() {
|
||||
String manifestResult;
|
||||
String result;
|
||||
try {
|
||||
manifestResult = getManifestAttribute("Implementation-Build");
|
||||
} catch (IOException exn1) {
|
||||
manifestResult = null; // NOPMD by Braids on 8/12/11 10:21 AM
|
||||
}
|
||||
|
||||
if (manifestResult == null) {
|
||||
// Try getting the SVN version number by running the svnversion
|
||||
// command. This is a long shot, but it works on some developers'
|
||||
// systems.
|
||||
|
||||
Process proc = null;
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
proc = Runtime.getRuntime().exec("svnversion");
|
||||
final InputStream procStdoutStream = proc.getInputStream();
|
||||
final Reader procReader = new InputStreamReader(procStdoutStream, US_ASCII_CHARSET);
|
||||
reader = new BufferedReader(procReader);
|
||||
|
||||
result = reader.readLine(); // may be null
|
||||
|
||||
} catch (IOException exn2) {
|
||||
result = null; // NOPMD by Braids on 8/12/11 10:21 AM
|
||||
} finally {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (Throwable exn3) { // NOPMD by Braids on 8/12/11 10:21 AM
|
||||
// ignored
|
||||
}
|
||||
|
||||
try {
|
||||
proc.destroy();
|
||||
} catch (Throwable exn4) { // NOPMD by Braids on 8/12/11 10:21 AM
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = manifestResult;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current version of Forge.
|
||||
*
|
||||
* @return a String representing the version specifier, or "SVN" if
|
||||
* unknown.
|
||||
*/
|
||||
public final String getVersion() {
|
||||
String manifestResult;
|
||||
String result;
|
||||
|
||||
try {
|
||||
manifestResult = getManifestAttribute("Implementation-Version");
|
||||
} catch (IOException exn) {
|
||||
manifestResult = null; // NOPMD by Braids on 8/12/11 10:21 AM
|
||||
}
|
||||
|
||||
if (manifestResult == null) {
|
||||
result = "SVN";
|
||||
}
|
||||
else {
|
||||
result = manifestResult;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an attribute from the Forge main jar's manifest.
|
||||
*
|
||||
* @param manifestAttrName the name of the attribute you want from the manifest
|
||||
* @return the attribute's value, which may be empty or null
|
||||
* @throws IOException if a (unique) Forge jar could not be found
|
||||
*/
|
||||
protected final String getManifestAttribute(final String manifestAttrName) throws IOException {
|
||||
String result = null;
|
||||
JarFile jar = null;
|
||||
InputStream manifestStream = null;
|
||||
|
||||
try {
|
||||
if (pathToForgeJar == null) {
|
||||
// We're definitely not unit testing. Try to load from the
|
||||
// currently running jar.
|
||||
|
||||
manifestStream = ClassLoader.getSystemResourceAsStream("META-INF/MANIFEST.MF");
|
||||
final Manifest manifest = new Manifest(manifestStream);
|
||||
|
||||
result = getMainManifestAttribute(manifest, manifestAttrName);
|
||||
}
|
||||
|
||||
if (result == null && pathToForgeJar == null) {
|
||||
|
||||
// Try to find a unique Forge jar in the class path.
|
||||
|
||||
final String classPath = System.getProperty("java.class.path");
|
||||
final String[] paths = classPath.split(PATH_SEP);
|
||||
|
||||
for (String path : paths) {
|
||||
final Matcher matcher = FORGE_JAR_REGEX_2G.matcher(path);
|
||||
|
||||
if (matcher.matches()) {
|
||||
if (pathToForgeJar == null) {
|
||||
pathToForgeJar = path;
|
||||
}
|
||||
else {
|
||||
// Error: we found more than one.
|
||||
pathToForgeJar = null; // NOPMD by Braids on 8/12/11 10:21 AM
|
||||
|
||||
throw new MultipleForgeJarsFoundError(
|
||||
"Classpath = " + System.getProperty("java.class.path"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result == null && pathToForgeJar == null) {
|
||||
throw new FileNotFoundException(
|
||||
"There is nothing matching forge-*-with-dependencies.jar in the class path.");
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
jar = new JarFile(pathToForgeJar);
|
||||
final Manifest manifest = jar.getManifest();
|
||||
|
||||
if (manifest == null) {
|
||||
throw new IOException("Forge jar at <<" + pathToForgeJar + ">> has no manifest.");
|
||||
}
|
||||
|
||||
result = getMainManifestAttribute(manifest, manifestAttrName);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
manifestStream.close();
|
||||
} catch (Throwable ignored) { // NOPMD by Braids on 8/12/11 10:21 AM
|
||||
// ignored
|
||||
}
|
||||
|
||||
try {
|
||||
jar.close();
|
||||
} catch (Throwable ignored) { // NOPMD by Braids on 8/12/11 10:21 AM
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convience method for fetching an attribute from the main section of a
|
||||
* jar's manifest.
|
||||
*
|
||||
* @param manifest the manifest that provides attributes
|
||||
* @param manifestAttrName the name of the attribute to fetch
|
||||
* @return the value of the attribute, or null if not set
|
||||
*/
|
||||
protected final String getMainManifestAttribute(final Manifest manifest, final String manifestAttrName) {
|
||||
final Attributes atts = manifest.getMainAttributes();
|
||||
return atts.getValue(manifestAttrName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,39 +3,107 @@ package forge.model;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
//import net.slightlymagic.braids.util.progress_monitor.BaseProgressMonitor;
|
||||
import net.slightlymagic.braids.util.progress_monitor.BraidsProgressMonitor;
|
||||
import arcane.util.MultiplexOutputStream;
|
||||
|
||||
/**
|
||||
* The default Model implementation for Forge.
|
||||
*
|
||||
* This used to be an interface, but it seems unlikely that we will ever use a
|
||||
* This used to be an interface, but it seems unlikely that we will ever use a
|
||||
* different model.
|
||||
*
|
||||
* In case we need to convert it into an interface in the future, all fields of
|
||||
* this class must be either private or public static final.
|
||||
*/
|
||||
public class FModel {
|
||||
//private static final int NUM_INIT_PHASES = 1;
|
||||
|
||||
private final transient OutputStream logFileStream;
|
||||
private final transient PrintStream oldSystemOut;
|
||||
private final transient PrintStream oldSystemErr;
|
||||
private BuildInfo buildInfo;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param theMonitor a progress monitor (from the View) that shows the
|
||||
* progress of the model's initialization.
|
||||
*
|
||||
* @throws FileNotFoundException if we could not find or write to the log file.
|
||||
*/
|
||||
public FModel() throws FileNotFoundException {
|
||||
public FModel(final BraidsProgressMonitor theMonitor) throws FileNotFoundException {
|
||||
/* To be implemented later. -Braids
|
||||
BraidsProgressMonitor monitor;
|
||||
if (theMonitor == null) {
|
||||
monitor = new BaseProgressMonitor(NUM_INIT_PHASES, 1);
|
||||
}
|
||||
else {
|
||||
monitor = theMonitor;
|
||||
}
|
||||
*/
|
||||
|
||||
final File logFile = new File("forge.log");
|
||||
final boolean deleteSucceeded = logFile.delete();
|
||||
|
||||
if (logFile.exists() && !deleteSucceeded) {
|
||||
if (logFile.exists() && !deleteSucceeded && logFile.length() != 0) {
|
||||
throw new IllegalStateException("Could not delete existing logFile:" + logFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
// This used to be a BufferedOutputStream, but that seems inappropriate for a log. --Braids
|
||||
final OutputStream logFileStream = new FileOutputStream(logFile);
|
||||
logFileStream = new FileOutputStream(logFile);
|
||||
|
||||
oldSystemOut = System.out;
|
||||
System.setOut(new PrintStream(new MultiplexOutputStream(System.out, logFileStream), true));
|
||||
oldSystemErr = System.err;
|
||||
System.setErr(new PrintStream(new MultiplexOutputStream(System.err, logFileStream), true));
|
||||
|
||||
setBuildInfo(new BuildInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor for FModel.
|
||||
* @throws Throwable indirectly
|
||||
*/
|
||||
@Override
|
||||
protected final void finalize() throws Throwable {
|
||||
close();
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opposite of constructor; resets all system resources and closes the
|
||||
* log file.
|
||||
*/
|
||||
public final void close() {
|
||||
System.setOut(oldSystemOut);
|
||||
System.setErr(oldSystemErr);
|
||||
try {
|
||||
logFileStream.close();
|
||||
} catch (IOException e) { // NOPMD by Braids on 8/12/11 10:25 AM
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for buildInfo.
|
||||
*
|
||||
* @return the buildInfo
|
||||
*/
|
||||
public final BuildInfo getBuildInfo() {
|
||||
return buildInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for buildInfo.
|
||||
*
|
||||
* @param neoBuildInfo the buildInfo to set
|
||||
*/
|
||||
protected final void setBuildInfo(final BuildInfo neoBuildInfo) {
|
||||
this.buildInfo = neoBuildInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
23
src/main/java/forge/model/MultipleForgeJarsFoundError.java
Normal file
23
src/main/java/forge/model/MultipleForgeJarsFoundError.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package forge.model;
|
||||
|
||||
//import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Exception thrown by model when it is trying to find a single forge jar, but
|
||||
* it finds more than one.
|
||||
*/
|
||||
public class MultipleForgeJarsFoundError extends RuntimeException {
|
||||
/** Automatically generated. */
|
||||
private static final long serialVersionUID = 8899307272033517172L;
|
||||
|
||||
|
||||
/**
|
||||
* Create an exception with a message.
|
||||
*
|
||||
* @param message the message, which could be the System's class path.
|
||||
*/
|
||||
public MultipleForgeJarsFoundError(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public final class Main {
|
||||
public static void main(final String[] args) {
|
||||
ExceptionHandler.registerErrorHandling();
|
||||
try {
|
||||
final FModel model = new FModel();
|
||||
final FModel model = new FModel(null);
|
||||
Singletons.setModel(model);
|
||||
final FView view = new ApplicationView();
|
||||
Singletons.setView(view);
|
||||
|
||||
Reference in New Issue
Block a user