Initial changes needed to allow DistMaker to support Java 9.

This commit is contained in:
Norberto Lopez
2018-02-22 18:29:01 +00:00
parent 8fd1c0cfbb
commit 0ebb5049f2
34 changed files with 1433 additions and 373 deletions

View File

@@ -1,11 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7
org.eclipse.jdt.core.compiler.source=1.8

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,25 @@
package distMaker;
import distMaker.utils.PlainVersion;
import distMaker.utils.Version;
/**
* Provides main entry point.
* <P>
* Currently this will just print the library name and the version. This is used during the build process for making
* Distmaker releases.
*/
public class DistApp
{
/** The DistMaker version is defined here. */
public static final Version version = new PlainVersion(0, 48, 0);
/**
* Main entry point that will print out the version of DistMaker to stdout.
*/
public static void main(String[] aArgArr)
{
System.out.println("DistMaker " + DistApp.version);
}
}

View File

@@ -1,21 +1,12 @@
package distMaker;
import glum.gui.panel.generic.MessagePanel;
import glum.gui.panel.generic.PromptPanel;
import glum.gui.panel.task.FullTaskPanel;
import glum.io.IoUtil;
import glum.net.Credential;
import glum.reflect.FunctionRunnable;
import glum.task.*;
import glum.unit.DateUnit;
import glum.util.ThreadUtil;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.*;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.util.*;
@@ -30,12 +21,19 @@ import distMaker.gui.PickReleasePanel;
import distMaker.jre.*;
import distMaker.node.*;
import distMaker.platform.PlatformUtils;
import glum.gui.panel.generic.MessagePanel;
import glum.gui.panel.generic.PromptPanel;
import glum.gui.panel.task.FullTaskPanel;
import glum.io.IoUtil;
import glum.net.Credential;
import glum.task.*;
import glum.unit.DateUnit;
import glum.util.ThreadUtil;
public class DistMakerEngine
{
// Constants
private final String NonDistmakerAppMsg = "This application does not appear to be a properly configured DistMaker application.\n\n"
+ "Please check installation configuration.";
private final String NonDistmakerAppMsg = "This application does not appear to be a properly configured DistMaker application.\n\n" + "Please check installation configuration.";
// State vars
private URL updateSiteUrl;
@@ -100,7 +98,8 @@ public class DistMakerEngine
taskPanel.setVisible(true);
// Launch the actual checking of updates in a separate worker thread
ThreadUtil.launchRunnable(new FunctionRunnable(this, "checkForUpdatesWorker", taskPanel, listener), "thread-checkForUpdates");
Runnable tmpRunnable = () -> checkForUpdatesWorker(taskPanel, listener);
ThreadUtil.launchRunnable(tmpRunnable, "thread-checkForUpdates");
}
/**
@@ -150,7 +149,8 @@ public class DistMakerEngine
}
/**
* Sets in the credentials used to access the update site. If either argument is null, then the credentials will be cleared out.
* Sets in the credentials used to access the update site. If either argument is null, then the credentials will be
* cleared out.
*/
public void setCredentials(String aUsername, char[] aPassword)
{
@@ -243,7 +243,7 @@ public class DistMakerEngine
// Form the PickReleasePanel
pickVersionPanel = new PickReleasePanel(parentFrame, currRelease);
pickVersionPanel.setSize(550, 500); // 320, 350);
pickVersionPanel.setSize(550, 500);
// Notify the user of (any) update results
showUpdateResults();
@@ -254,7 +254,6 @@ public class DistMakerEngine
* <P>
* This method will be called via reflection.
*/
@SuppressWarnings("unused")
private void checkForUpdatesWorker(FullTaskPanel aTask, UpdateCheckListener listener)
{
List<AppRelease> fullList;
@@ -308,10 +307,8 @@ public class DistMakerEngine
aTask.infoAppendln("Please select the release to install...");
try
{
FunctionRunnable aFuncRunnable;
aFuncRunnable = new FunctionRunnable(this, "queryUserForInput", aTask, deltaPath, fullList);
SwingUtilities.invokeAndWait(aFuncRunnable);
Runnable tmpRunnable = () -> queryUserForInput(aTask, deltaPath, fullList);
SwingUtilities.invokeAndWait(tmpRunnable);
}
catch(Exception aExp)
{
@@ -348,7 +345,19 @@ public class DistMakerEngine
}
// Download the release
isPass = downloadAppRelease(aTask, chosenItem, deltaPath);
try
{
isPass = downloadAppRelease(aTask, chosenItem, deltaPath);
}
catch(Throwable aThrowable)
{
IoUtil.deleteDirectory(deltaPath);
aTask.infoAppendln("An error occurred while trying to perform an update.");
aTask.infoAppendln("Application update aborted.");
aTask.infoAppendln("\nStackTrace:\n" + ThreadUtil.getStackTraceClassic(aThrowable));
aTask.abort();
return;
}
if (isPass == false || aTask.isActive() == false)
{
IoUtil.deleteDirectory(deltaPath);
@@ -368,12 +377,9 @@ public class DistMakerEngine
*/
private void displayNotice(String aMsg)
{
Runnable silentRunnable = new Runnable() {
@Override
public void run()
{
; // Nothing to do
}
Runnable silentRunnable = () ->
{
; // Nothing to do
};
// Delegate to displayNoticeAndExecute
@@ -395,7 +401,8 @@ public class DistMakerEngine
// If the parentFrame is not visible then execute the code once it is made visible
if (parentFrame.isVisible() == false)
{
parentFrame.addComponentListener(new ComponentAdapter() {
parentFrame.addComponentListener(new ComponentAdapter()
{
@Override
public void componentShown(ComponentEvent aEvent)
{
@@ -574,7 +581,8 @@ public class DistMakerEngine
// Retrieve the reference to the appCfgFile
File appCfgFile = PlatformUtils.getConfigurationFile();
// Create the delta.cmd file which provides the Updater with the clean activities to perform (based on fail / pass conditions)
// Create the delta.cmd file which provides the Updater with the clean activities to perform
// (based on fail / pass conditions)
File deltaCmdFile = new File(destPath, "delta.cmd");
try (FileWriter tmpFW = new FileWriter(deltaCmdFile))
{
@@ -586,12 +594,12 @@ public class DistMakerEngine
tmpFW.write("# Define the fail section (clean up for failure)\n");
tmpFW.write("sect,fail\n");
tmpFW.write("copy," + "delta/" + appCfgFile.getName() + ".old," + MiscUtils.getRelativePath(rootPath, appCfgFile) + "\n");
tmpFW.write("reboot,trash,jre" + targJreVer.getLabel() + "\n");
tmpFW.write("reboot,trash," + JreUtils.getExpandJrePath(targJreVer) + "\n");
tmpFW.write("exit\n\n");
tmpFW.write("# Define the pass section (clean up for success)\n");
tmpFW.write("sect,pass\n");
tmpFW.write("trash,jre" + currJreVer.getLabel() + "\n");
tmpFW.write("trash," + JreUtils.getExpandJrePath(currJreVer) + "\n");
tmpFW.write("exit\n\n");
}
else
@@ -626,7 +634,7 @@ public class DistMakerEngine
// Since an updated JRE was needed...
// Moved the JRE (unpacked folder) from its drop path to the proper location
File jreDropPath = new File(destPath, "jre" + targJre.getVersion().getLabel());
File jreDropPath = new File(destPath, JreUtils.getExpandJrePath(targJre.getVersion()));
File jreTargPath = PlatformUtils.getJreLocation(targJre);
jreTargPath.getParentFile().setWritable(true);
if (jreDropPath.renameTo(jreTargPath) == false)
@@ -688,10 +696,10 @@ public class DistMakerEngine
updnStr = "upgraded";
aTask.infoAppendln("Your current JRE is not compatible with this release. It will need to be " + updnStr + "!");
aTask.infoAppendln("\tCurrent JRE: " + currJreVer.getLabel());
aTask.infoAppendln("\tMinimun JRE: " + aUpdateCat.getMinJreVersion().getLabel());
aTask.infoAppendln("\tMinimum JRE: " + aUpdateCat.getMinJreVersion().getLabel());
JreVersion tmpJreVer = aUpdateCat.getMaxJreVersion();
if (tmpJreVer != null)
aTask.infoAppendln("\tMaximun JRE: " + tmpJreVer.getLabel());
aTask.infoAppendln("\tMaximum JRE: " + tmpJreVer.getLabel());
aTask.infoAppendln("");
// Bail if we are running a bundled JRE
@@ -738,6 +746,15 @@ public class DistMakerEngine
}
JreVersion pickJreVer = pickJre.getVersion();
// Update the AppLauncher if required
AppLauncherRelease pickAppLauncher = null;
if (AppLauncherUtils.isAppLauncherUpdateNeeded(aTask, pickJre) == true)
{
pickAppLauncher = AppLauncherUtils.updateAppLauncher(aTask, pickJre, aDestPath, updateSiteUrl, refCredential);
if (pickAppLauncher == null)
return null;
}
// Update the number of bytes to be retrieved to take into account the JRE which we will be downloading
long tmpFileLen = pickJre.getFileLen();
releaseSizeFull += tmpFileLen;
@@ -761,21 +778,21 @@ public class DistMakerEngine
aTask.infoAppendln("The download of the JRE appears to be corrupted.");
aTask.infoAppendln("\tFile: " + dstFile);
aTask.infoAppendln("\t\tExpected " + targDigest.getDescr());
aTask.infoAppendln("\t\tRecieved " + testDigest.getDescr() + "\n");
aTask.infoAppendln("\t\tReceived " + testDigest.getDescr() + "\n");
return null;
}
// Unpack the JRE at the unpack location
aTask.infoAppendln("Finshed downloading JRE. Unpacking JRE...");
File jreRootPath = null;
File jreTargPath = new File(aDestPath, "jre" + pickJreVer.getLabel());
File jreTargPath = new File(aDestPath, JreUtils.getExpandJrePath(pickJreVer));
try
{
// Create the working unpack folder where the JRE will be initially unpacked to.
File unpackPath = new File(aDestPath, "unpack");
unpackPath.mkdirs();
// Unpack the JRE to the working unpack folder and ensure that the unpacked JRE results in a 1 top level root folder.
// Unpack the JRE to the working unpack folder. Ensure that the unpacked JRE results in 1 top level folder.
tmpTask = new PartialTask(aTask, aTask.getProgress(), (tmpFileLen * 0.25) / (releaseSizeFull + 0.00));
MiscUtils.unTar(tmpTask, dstFile, unpackPath);
File[] fileArr = unpackPath.listFiles();
@@ -793,6 +810,9 @@ public class DistMakerEngine
aTask.infoAppendln("Failed to properly untar archive. The update has been aborted.");
aTask.infoAppendln("\tTar File: " + dstFile);
aTask.infoAppendln("\tDestination: " + jreTargPath);
String errMsg = ThreadUtil.getStackTrace(aExp);
aTask.infoAppend("\nStack Trace:\n" + errMsg);
return null;
}
@@ -800,16 +820,17 @@ public class DistMakerEngine
}
/**
* Helper method that "reverts" an update. After this method is called the DistMaker application's configuration should be in the same state as before an
* update was applied. Reverting consists of the following:
* Helper method that "reverts" an update. After this method is called the DistMaker application's configuration
* should be in the same state as before an update was applied. Reverting consists of the following:
* <UL>
* <LI>Removal of any downloaded and installed JRE
* <LI>Removing the delta directory
* <LI>Removing the delta.cfg file
* </UL>
* <P>
* There should not be any issues with this roll back process. However if there are a best effort will be made to continue rolling back the updates - note
* that the application might be in an unstable state - and may not be able to be restarted.
* There should not be any issues with this roll back process. However if there are, a best effort will be made to
* continue rolling back the updates - note that the application might be in an unstable state - and may not be able
* to be restarted.
*/
private void revertUpdate(Task aTask)
{
@@ -883,8 +904,9 @@ public class DistMakerEngine
if (strArr.length == 1 && cmdStr.equals("exit") == true)
break;
// We are interested only in trash (or reboot,trash) commands. Execute the individual trash (or reboot,trash) commands.
// It is safe to execute reboot,trash commands now since the actual update is not running yet.
// We are interested only in trash (or reboot,trash) commands. Execute the individual trash (or
// reboot,trash) commands. It is safe to execute reboot,trash commands now since the actual update is not
// running yet.
String delTargStr = null;
if (inputStr.startsWith("trash,") == true)
delTargStr = inputStr.substring(6);
@@ -935,13 +957,12 @@ public class DistMakerEngine
* <P>
* This method will be called via reflection.
*/
@SuppressWarnings("unused")
private void queryUserForInput(Task aTask, File deltaPath, List<AppRelease> fullList)
private void queryUserForInput(Task aTask, File aDeltaPath, List<AppRelease> aFullList)
{
AppRelease chosenItem;
// Query the user, if the wish to destroy the old update
if (deltaPath.isDirectory() == true)
if (aDeltaPath.isDirectory() == true)
{
promptPanel.setTitle("Overwrite recent update?");
promptPanel.setInfo("An update has already been downloaded... If you proceed this update will be removed. Proceed?");
@@ -958,7 +979,7 @@ public class DistMakerEngine
}
// Query the user of the version to update to
pickVersionPanel.setConfiguration(fullList);
pickVersionPanel.setConfiguration(aFullList);
pickVersionPanel.setVisibleAsModal();
chosenItem = pickVersionPanel.getChosenItem();
if (chosenItem == null)
@@ -970,7 +991,8 @@ public class DistMakerEngine
}
/**
* Notification that the corresponding application has been fully initialized. This helper method will notify the user on the status of any update.
* Notification that the corresponding application has been fully initialized. This helper method will notify the
* user on the status of any update.
*/
private void showUpdateResults()
{
@@ -1000,7 +1022,8 @@ public class DistMakerEngine
}
// Setup the runnable that will clean up our delta folder
Runnable cleanDeltaRunnable = new Runnable() {
Runnable cleanDeltaRunnable = new Runnable()
{
@Override
public void run()
{

View File

@@ -22,18 +22,56 @@ import distMaker.digest.Digest;
import distMaker.digest.DigestType;
import distMaker.jre.JreVersion;
import distMaker.node.*;
import distMaker.utils.ParseUtils;
import distMaker.utils.PlainVersion;
import distMaker.utils.Version;
public class DistUtils
{
// Static members that may be automatically updated by the AppLauncher class loader.
// Do not rename or change these variables, without changing the AppLauncher class loader.
// -----------------------------------------------------------------------------------------------------------------
// Start of AppLauncher class loader related vars.
// Static members that will be automatically configured by the AppLauncher class loader.
// Do not rename or change the variables below, without changing the AppLauncher class loader.
// -----------------------------------------------------------------------------------------------------------------
private static String appLauncherVersion = null;
private static boolean isDevelopersEnvironment = true;
private static int updateCode = 0; // Static member to declare the update status, 0: None, 1: Pass, 2: Fail
private static String updateMsg = null;
// -----------------------------------------------------------------------------------------------------------------
// Do not rename or change the variables above, without changing the AppLauncher class loader.
// End of AppLauncher class loader related vars.
// -----------------------------------------------------------------------------------------------------------------
// Static field used only when developing DistMaker. Otherwise this field should always be null.
/** Cached value of the AppLauncherVersion. Note the cached value is of type Version rather than String */
private static Version cAppLauncherVersion;
/* Static field used only when developing DistMaker. Otherwise this field should always be null. */
private static File developAppPath = null;
/**
* Utility method to return the version of the AppLauncher that started this process.
* <P>
* If we are running in a developers environment then this value will be null.
*/
public static Version getAppLauncherVersion()
{
// Return the cached value
if (cAppLauncherVersion != null)
return cAppLauncherVersion;
// Return null if we are in a developers environment
if (isDevelopersEnvironment == true)
return null;
// Legacy AppLaunchers do not configure this field. All legacy AppLaunchers will be defined as version: 0.0
if (appLauncherVersion == null && isDevelopersEnvironment == false)
cAppLauncherVersion = PlainVersion.Zero;
else
cAppLauncherVersion = PlainVersion.parse(appLauncherVersion);
return cAppLauncherVersion;
}
/**
* Utility method to determine the path where the application is installed.
* <P>
@@ -66,6 +104,14 @@ public class DistUtils
return jarPath.getParentFile().getParentFile();
}
/**
* Returns the version of DistMaker which is running.
*/
public static Version getDistMakerVersion()
{
return DistApp.version;
}
/**
* Returns the JreVersion for the JRE which we are running on.
*/
@@ -124,10 +170,10 @@ public class DistUtils
/**
* Downloads the specified file from srcUrl to destFile. Returns true on success
* <P>
* Note the passed in task's progress will be updated from 0% to 100% at file download completion, If the specified file size is invalid (aFileSize <= 0) or
* the download turns out to be bigger than the specified size then there will be no progress update while the file is being downloaded - only at completion.
* Note the passed in task's progress will be updated from 0% to 100% at file download completion, If the specified
* file size is invalid (aFileSize <= 0) or the download turns out to be bigger than the specified size then there
* will be no progress update while the file is being downloaded - only at completion.
*/
@SuppressWarnings("resource")
public static boolean downloadFile(Task aTask, URL aUrl, File aFile, Credential aCredential, long aFileSize, MessageDigest aDigest)
{
URLConnection connection;
@@ -222,26 +268,23 @@ public class DistUtils
public static List<AppRelease> getAvailableAppReleases(Task aTask, URL aUpdateUrl, String appName, Credential aCredential)
{
List<AppRelease> fullList;
AppRelease workAR;
URL catUrl;
URLConnection connection;
InputStream inStream;
BufferedReader bufReader;
DateUnit dateUnit;
String errMsg;
errMsg = null;
fullList = new ArrayList<>();
catUrl = IoUtil.createURL(aUpdateUrl.toString() + "/" + appName + "/" + "releaseInfo.txt");
catUrl = IoUtil.createURL(aUpdateUrl.toString() + "/" + appName + "/" + "appCatalog.txt");
workAR = null;
connection = null;
inStream = null;
bufReader = null;
try
{
String[] tokens;
String strLine, verName;
long buildTime;
// Read the contents of the file
connection = catUrl.openConnection();
inStream = NetUtil.getInputStream(connection, aCredential);
@@ -250,30 +293,84 @@ public class DistUtils
// Read the lines
while (true)
{
String strLine;
strLine = bufReader.readLine();
// Bail once we are done
if (strLine == null)
break;
tokens = strLine.split(",");
// Ignore comments and empty lines
if (strLine.isEmpty() == true || strLine.startsWith("#") == true)
continue;
String[] tokenArr;
tokenArr = strLine.split(",");
if (tokenArr.length == 2 && tokenArr[0].equals("name") == true)
; // Nothing to do
else if (tokens.length == 2 && tokens[0].equals("name") == true)
; // Nothing to do
else if (tokens.length != 2)
aTask.infoAppendln("Unreconized line: " + strLine);
else
// if (tokens.length == 2)
// Logic to handle the 'exit' command
else if (tokenArr.length >= 1 && tokenArr[0].equals("exit") == true)
{
verName = tokens[0];
// We support exit commands with 3 tokens. All others
// we will just exit.
if (tokenArr.length != 3)
break;
String targName = tokenArr[1];
String needVer = tokenArr[2];
if (ParseUtils.shouldExitLogic(targName, needVer) == true)
break;
}
// Logic to handle a distribution release
else if (tokenArr.length == 3 && tokenArr[0].equals("R") == true)
{
DateUnit dateUnit;
String verName;
long buildTime;
verName = tokenArr[1];
dateUnit = new DateUnit("", "yyyyMMMdd HH:mm:ss");
buildTime = dateUnit.parseString(tokens[1], 0);
buildTime = dateUnit.parseString(tokenArr[2], 0);
fullList.add(new AppRelease(appName, verName, buildTime));
// Record the prior AppRelease
if (workAR != null)
fullList.add(workAR);
workAR = new AppRelease(appName, verName, buildTime);
}
// Record any comments and associate with the current AppRelease
else if (tokenArr.length >= 2 && tokenArr[0].equals("info") == true)
{
// We support the 'info,msg' instruction. Otherwise we just ignore info instructions silently
if (tokenArr[1].equals("msg") == true && workAR != null)
{
// Retokenize to ensure at most we get only 3 tokens
tokenArr = strLine.split(",", 3);
String infoMsg;
infoMsg = workAR.getInfoMsg();
if (infoMsg != null)
infoMsg += "\n";
else
infoMsg = "";
if (tokenArr.length > 2)
infoMsg += tokenArr[2];
// Form an updated AppRelease with the updated infoMsg
workAR = new AppRelease(workAR.getName(), workAR.getVersion(), workAR.getBuildTime(), infoMsg);
}
}
else
{
aTask.infoAppendln("Unreconized line: " + strLine);
}
}
// Add the last AppRelease
if (workAR != null)
fullList.add(workAR);
}
catch(IOException aExp)
{
@@ -310,40 +407,39 @@ public class DistUtils
*/
private static String getErrorCodeMessage(URL aUpdateUrl, URLConnection aConnection, IOException aExp)
{
URL fetchUrl;
Result result;
String errMsg;
// Form a user friendly exception
String errMsg;
errMsg = "The update site, " + aUpdateUrl + ", is not available.\n\t";
Result result;
result = NetUtil.getResult(aExp, aConnection);
switch (result)
{
case BadCredentials:
errMsg += "The update site is password protected and bad credentials were provided.\n";
break;
errMsg += "The update site is password protected and bad credentials were provided.\n";
break;
case ConnectFailure:
case UnreachableHost:
case UnsupportedConnection:
errMsg += "The update site appears to be unreachable.\n";
break;
errMsg += "The update site appears to be unreachable.\n";
break;
case Interrupted:
errMsg += "The retrival of the remote file has been interrupted.\n";
break;
errMsg += "The retrival of the remote file has been interrupted.\n";
break;
case InvalidResource:
errMsg += "The remote file does not appear to be valid.\n";
break;
errMsg += "The remote file does not appear to be valid.\n";
break;
default:
errMsg += "An undefined error occurred while retrieving the remote file.\n";
break;
errMsg += "An undefined error occurred while retrieving the remote file.\n";
break;
}
// Log the URL which we failed on
URL fetchUrl;
fetchUrl = aConnection.getURL();
errMsg += "\tURL: " + fetchUrl + "\n";
@@ -351,8 +447,9 @@ public class DistUtils
}
/**
* Utility method to determine if the specified path is fully writable by this process. This is done by making sure that all folders and child folders are
* writable by the current process. Note after this method is called, all folders will have the write permission bit set.
* Utility method to determine if the specified path is fully writable by this process. This is done by making sure
* that all folders and child folders are writable by the current process. Note after this method is called, all
* folders will have the write permission bit set.
*/
public static boolean isFullyWriteable(File aPath)
{
@@ -388,7 +485,6 @@ public class DistUtils
{
List<Node> nodeList;
JreVersion minJreVersion, maxJreVersion;
DigestType digestType;
String errMsg, strLine;
errMsg = null;
@@ -397,16 +493,17 @@ public class DistUtils
maxJreVersion = null;
// Default to DigestType of MD5
DigestType digestType;
digestType = DigestType.MD5;
try (BufferedReader bufReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(new FileInputStream(aCatalogFile))));)
try (BufferedReader tmpBR = new BufferedReader(new InputStreamReader(new BufferedInputStream(new FileInputStream(aCatalogFile))));)
{
String[] tokens;
// Read the contents of the file
while (true)
{
strLine = bufReader.readLine();
strLine = tmpBR.readLine();
// Bail once we are done
if (strLine == null)
@@ -450,8 +547,7 @@ public class DistUtils
{
if (minJreVersion != null)
{
aTask.infoAppendln("JRE version has already been specified. Current ver: " + minJreVersion.getLabel() + " Requested ver: " + tokens[1]
+ ". Skipping...");
aTask.infoAppendln("JRE version has already been specified. Current ver: " + minJreVersion.getLabel() + " Requested ver: " + tokens[1] + ". Skipping...");
continue;
}
@@ -487,7 +583,8 @@ public class DistUtils
}
/**
* Utility method to switch the DistMaker library into debug mode. You should never call this method unless you are modifying the DistMaker library.
* Utility method to switch the DistMaker library into debug mode. You should never call this method unless you are
* modifying the DistMaker library.
* <P>
* This functionality only exists to allow rapid development of DistMaker
*/

View File

@@ -7,31 +7,31 @@ import java.util.List;
public class LoggingTask extends SilentTask
{
private final List<String> messages = new ArrayList<>();
private final List<String> messages = new ArrayList<>();
@Override
public void infoAppend(String aMsg)
{
messages.add(aMsg);
super.infoAppend(aMsg);
}
@Override
public void infoAppend(String aMsg)
{
messages.add(aMsg);
super.infoAppend(aMsg);
}
@Override
public void infoAppendln(String aMsg)
{
messages.add(aMsg);
super.infoAppendln(aMsg);
}
@Override
public void infoAppendln(String aMsg)
{
messages.add(aMsg);
super.infoAppendln(aMsg);
}
@Override
public void infoUpdate(String aMsg)
{
messages.add(aMsg);
super.infoUpdate(aMsg);
}
@Override
public void infoUpdate(String aMsg)
{
messages.add(aMsg);
super.infoUpdate(aMsg);
}
List<String> getMessages()
{
return messages;
}
List<String> getMessages()
{
return messages;
}
}

View File

@@ -34,7 +34,7 @@ public class MiscUtils
*/
public static String convertUnixModeToStr(int aMode)
{
char permArr[] = { 'r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x' };
char permArr[] = {'r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x'};
for (int c1 = 8; c1 >= 0; c1--)
{
@@ -87,7 +87,8 @@ public class MiscUtils
/**
* Helper method that prints the exception of ErrorDM in an intelligent fashion to the specified task.
* <P>
* All ErrorDM exceptions (and their causes) will be printed. If the cause is not of type ErrorDM then the stack trace will be printed as well.
* All ErrorDM exceptions (and their causes) will be printed. If the cause is not of type ErrorDM then the stack
* trace will be printed as well.
*/
public static void printErrorDM(Task aTask, ErrorDM aErrorDM, int numTabs)
{
@@ -123,16 +124,15 @@ public class MiscUtils
* Source based off of:<BR>
* http://stackoverflow.com/questions/315618/how-do-i-extract-a-tar-file-in-java/7556307#7556307
* <P>
*
* The output file is created in the output folder, having the same name as the input file, minus the '.tar' extension.
* The output file is created in the output folder, having the same name as the input file, minus the '.tar'
* extension.
*
* @param inputFile
* the input .tar file
* the input .tar file
* @param aDestPath
* The destination folder where the content will be dumped.
* The destination folder where the content will be dumped.
* @throws IOException
* @throws FileNotFoundException
*
* @return The {@link List} of {@link File}s with the untared content.
* @throws ArchiveException
*/
@@ -176,6 +176,9 @@ public class MiscUtils
}
else if (entry.isSymbolicLink() == true)
{
// Ensure the parent folders exist
outputFile.getParentFile().mkdirs();
File tmpFile = new File(entry.getLinkName());
Files.createSymbolicLink(outputFile.toPath(), tmpFile.toPath());
@@ -194,7 +197,11 @@ public class MiscUtils
}
else if (entry.isFile() == true)
{
final OutputStream outputFileStream = new FileOutputStream(outputFile);
// Ensure the parent folders exist
outputFile.getParentFile().mkdirs();
// Copy over the file
OutputStream outputFileStream = new FileOutputStream(outputFile);
IOUtils.copy(debInputStream, outputFileStream);
outputFileStream.close();

View File

@@ -80,4 +80,4 @@ public class Digest
return true;
}
}
}

View File

@@ -3,7 +3,7 @@ package distMaker.digest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
import com.google.common.io.BaseEncoding;
/**
* Collection of utility methods to ease working with the MessageDigest and associated classes.
@@ -44,24 +44,24 @@ public class DigestUtils
}
/**
* Utility method that returns the hex string corresponding to the byte array.
* Utility method that returns the (lower case) hex string corresponding to the byte array.
* <P>
* Delegates to {@link BaseEncoding.base16().lowerCase().encode(CharSequence)}
*/
public static String byteArr2HexStr(byte[] aByteArr)
{
String retStr;
retStr = (new HexBinaryAdapter()).marshal(aByteArr).toLowerCase();
String retStr = BaseEncoding.base16().lowerCase().encode(aByteArr);
return retStr;
}
/**
* Utility method that returns a byte array corresponding to the hex string.
* <P>
* Delegates to {@link BaseEncoding.base16().lowerCase().decode(CharSequence)}
*/
public static byte[] hexStr2ByteArr(String aHexStr)
{
byte[] retArr;
retArr = (new HexBinaryAdapter()).unmarshal(aHexStr);
byte[] retArr = BaseEncoding.base16().lowerCase().decode(aHexStr);
return retArr;
}

View File

@@ -28,15 +28,17 @@ import distMaker.node.AppRelease;
public class PickReleasePanel extends GlassPanel implements ActionListener, ListSelectionListener
{
private static final long serialVersionUID = 1L;
// Constants
private static final long serialVersionUID = 1L;
private static final Color ColorFail = Color.red.darker().darker();
// GUI vars
// GUI vars
private JLabel titleL;
private JRadioButton newestRB, olderRB;
private ItemListPanel<AppRelease> listPanel;
private QueryTableCellRenderer col0Renderer, col1Renderer;
private JButton abortB, proceedB;
private JTextArea infoTA, warnTA;
private JTextArea headTA, infoTA;
private Font smallFont;
// State vars
@@ -57,7 +59,7 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, List
// Build the actual GUI
smallFont = (new JTextField()).getFont();
buildGuiArea();
setPreferredSize(new Dimension(250, getPreferredSize().height));
setPreferredSize(new Dimension(350, getPreferredSize().height));
// Set up some keyboard shortcuts
FocusUtil.addAncestorKeyBinding(this, "ESCAPE", new ClickAction(abortB));
@@ -74,17 +76,17 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, List
/**
* Sets in the configuration of available versions
*/
public void setConfiguration(List<AppRelease> itemList)
public void setConfiguration(List<AppRelease> aItemList)
{
DateUnit dateUnit;
// String currBuildStr;
String lastBuildStr;
String currVerStr, lastVerStr;
String appName, infoMsg;
String appName, headMsg;
// Sort the items, and isolate the newest item
LinkedList<AppRelease> linkedList;
linkedList = new LinkedList<>(itemList);
linkedList = new LinkedList<>(aItemList);
Collections.sort(linkedList);
Collections.reverse(linkedList); // reverse the list to show most recent versions on top
newestItem = linkedList.removeFirst();
@@ -104,20 +106,27 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, List
myItemProcessor.setItems(linkedList);
// Update the infoTA
if (newestItem.equals(installedItem) == true) {
titleL.setText(appName + " is up to date.");
infoMsg = "You are running the latest release "
+ " (" + lastVerStr + ") that was built on " + lastBuildStr + ". ";
infoMsg += "You may switch to an older release by choosing one of the versions below.";
} else {
titleL.setText(appName + " needs to be updated.");
infoMsg = "You are running version " + currVerStr + ". ";
infoMsg += "You may update to the latest release. You may also switch to an "
+ "older release by choosing another version below. ";
if (newestItem.equals(installedItem) == true)
{
titleL.setText(appName + " is up to date.");
headMsg = "You are running the latest release " + " (" + lastVerStr + ") that was built on " + lastBuildStr + ". ";
headMsg += "You may switch to an older release by choosing one of the versions below.";
}
infoMsg += "\n";
else if (installedItem.getBuildTime() > newestItem.getBuildTime())
{
titleL.setText(appName + " (Out-Of-Band Release)");
headMsg = "You are running version " + currVerStr + ". This version has never been released! ";
headMsg += "You may update to the latest release or switch to an older release by choosing another version below. ";
}
else
{
titleL.setText(appName + " needs to be updated.");
headMsg = "You are running version " + currVerStr + ". ";
headMsg += "You may update to the latest release. You may also switch to an " + "older release by choosing another version below. ";
}
headMsg += "\n";
infoTA.setText(infoMsg);
headTA.setText(headMsg);
updateGui();
}
@@ -161,38 +170,50 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, List
*/
private void buildGuiArea()
{
JPanel tmpPanel;
JPanel listPanel, mainPanel;
// Form the layout
setLayout(new MigLayout("", "[left][grow][]", "[]25[][][]3[grow]10[]"));
setLayout(new MigLayout("", "[left][grow][]", "[]"));
// Title Area
titleL = new JLabel("Please select an update", JLabel.CENTER); // this text gets replaced once the curent version status is known
// Title Area: Note that the default text gets replaced once the current version status is known
titleL = new JLabel("Please select an update", JLabel.CENTER);
add(titleL, "growx,span 2,wrap");
// Info area
infoTA = GuiUtil.createUneditableTextArea(2, 0);
add(infoTA, "w 0::,growx,span,wrap");
// Header area
headTA = GuiUtil.createUneditableTextArea(2, 0);
add(headTA, "w 0::,growx,span,wrap");
// Latest version area
newestRB = GuiUtil.createJRadioButton("Unspecified", this, smallFont);
newestRB.setSelected(true);
add(newestRB, "span,wrap");
// Older version area
olderRB = GuiUtil.createJRadioButton("Select an older release:", this, smallFont);
add(olderRB, "span,wrap");
tmpPanel = buildItemListTablePanel();
tmpPanel.setBorder(new EmptyBorder(0, 15, 0, 0));
add(tmpPanel, "growx,growy,span,wrap");
listPanel = buildItemListTablePanel();
listPanel.setBorder(new EmptyBorder(0, 15, 0, 0));
mainPanel = new JPanel(new MigLayout("", "0[left,grow]", "0[][]3[grow]0"));
mainPanel.add(newestRB, "wrap");
mainPanel.add(olderRB, "wrap");
mainPanel.add(listPanel, "growx,growy");
// Link the radio buttons
GuiUtil.linkRadioButtons(newestRB, olderRB);
// Warn Area
warnTA = GuiUtil.createUneditableTextArea(0, 0);
add(warnTA, "w 0::,growx,span,wrap");
// Info Area
JScrollPane tmpSP;
infoTA = GuiUtil.createUneditableTextArea(0, 0);
infoTA.setTabSize(3);
tmpSP = new JScrollPane(infoTA);
tmpSP.setBorder(new EmptyBorder(0, 5, 0, 5));
JSplitPane tmpPane;
tmpPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, mainPanel, tmpSP);
tmpPane.setBorder(null);
tmpPane.setResizeWeight(0.15);
// tmpPane.setDividerLocation(0.50);
add(tmpPane, "growx,growy,pushy,span,wrap");
// Action area
abortB = GuiUtil.createJButton("Abort", this, smallFont);
@@ -208,26 +229,26 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, List
*/
private JPanel buildItemListTablePanel()
{
QueryComposer<LookUp> aComposer;
QueryItemHandler<AppRelease> aItemHandler;
QueryComposer<LookUp> tmpComposer;
QueryItemHandler<AppRelease> tmpIH;
DateUnit dateUnit;
dateUnit = new DateUnit("", "yyyyMMMdd HH:mm");
aComposer = new QueryComposer<LookUp>();
aComposer.addAttribute(LookUp.Version, String.class, "Version", null);
aComposer.addAttribute(LookUp.BuildTime, new ConstUnitProvider(dateUnit), "Build Date", null);
tmpComposer = new QueryComposer<LookUp>();
tmpComposer.addAttribute(LookUp.Version, String.class, "Version", null);
tmpComposer.addAttribute(LookUp.BuildTime, new ConstUnitProvider(dateUnit), "Build Date", null);
col0Renderer = new QueryTableCellRenderer();
col1Renderer = new QueryTableCellRenderer();
col1Renderer.setUnit(dateUnit);
aComposer.setRenderer(LookUp.Version, col0Renderer);
aComposer.setRenderer(LookUp.BuildTime, col1Renderer);
tmpComposer.setRenderer(LookUp.Version, col0Renderer);
tmpComposer.setRenderer(LookUp.BuildTime, col1Renderer);
aItemHandler = new QueryItemHandler<AppRelease>(aComposer);
myItemProcessor = new StaticItemProcessor<AppRelease>();
tmpIH = new QueryItemHandler<AppRelease>(tmpComposer);
myItemProcessor = new StaticItemProcessor<>();
listPanel = new ItemListPanel<AppRelease>(aItemHandler, myItemProcessor, false, false);
listPanel = new ItemListPanel<>(tmpIH, myItemProcessor, false, false);
listPanel.setSortingEnabled(false);
listPanel.addListSelectionListener(this);
return listPanel;
@@ -239,7 +260,7 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, List
private void updateGui()
{
AppRelease pickItem;
String warnMsg;
String failMsg, infoMsg;
boolean isEnabled;
// Determine the selected version
@@ -258,15 +279,39 @@ public class PickReleasePanel extends GlassPanel implements ActionListener, List
col1Renderer.setEnabled(isEnabled);
// Determine the warnMsg
warnMsg = null;
failMsg = null;
infoMsg = null;
if (pickItem == null)
warnMsg = "Select the version you want to switch to.";
failMsg = "Select the version you want to switch to.";
else if (pickItem.equals(installedItem) == true)
warnMsg = "You cannot update to the same version you are running. You can switch to a different version.";
failMsg = "You cannot update to the same version you are running. You can switch to a different version.";
else if (pickItem.getBuildTime() < installedItem.getBuildTime())
warnMsg = "Please note that your current selection will revert back to an older version than the currently installed version.";
infoMsg = "Please note that your current selection will revert back to an older version than the currently installed version.";
warnTA.setText(warnMsg);
// Add the app release notes
if (pickItem != null)
{
String noteMsg;
noteMsg = pickItem.getInfoMsg();
if (noteMsg != null)
{
if (infoMsg != null)
infoMsg += "\n\n" + noteMsg;
else
infoMsg = noteMsg;
}
}
Color tmpColor = Color.BLACK;
if (failMsg != null)
tmpColor = ColorFail;
String tmpMsg = failMsg;
if (tmpMsg == null)
tmpMsg = infoMsg;
infoTA.setText(tmpMsg);
infoTA.setForeground(tmpColor);
}
}

View File

@@ -0,0 +1,80 @@
package distMaker.jre;
import distMaker.digest.Digest;
import distMaker.utils.PlainVersion;
import distMaker.utils.Version;
import distMaker.utils.VersionUtils;
/**
* Immutable class that describes an AppLauncher release.
* <P>
* The reference fileName should be a jar file.
*/
public class AppLauncherRelease implements Comparable<AppLauncherRelease>
{
private final Version version;
private final Digest digest;
private final String fileName;
private final long fileLen;
public AppLauncherRelease(String aVersion, String aFileName, Digest aDigest, long aFileLen)
{
version = PlainVersion.parse(aVersion);
fileName = aFileName;
digest = aDigest;
fileLen = aFileLen;
}
/**
* Returns the Digest associated with the AppLauncher (jar) file.
*/
public Digest getDigest()
{
return digest;
}
/**
* Returns the version of the AppLauncher corresponding to this release.
*/
public Version getVersion()
{
return version;
}
/**
* Returns the length of the associated file
*/
public long getFileLen()
{
return fileLen;
}
/**
* Returns the filename of this AppLauncher release.
*/
public String getFileName()
{
return fileName;
}
@Override
public int compareTo(AppLauncherRelease aItem)
{
int cmpVal;
cmpVal = VersionUtils.compare(version, aItem.version);
if (cmpVal != 0)
return cmpVal;
cmpVal = fileName.compareTo(aItem.fileName);
if (cmpVal != 0)
return cmpVal;
cmpVal = Long.compare(fileLen, aItem.fileLen);
if (cmpVal != 0)
return cmpVal;
return 0;
}
}

View File

@@ -0,0 +1,339 @@
package distMaker.jre;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import distMaker.DistUtils;
import distMaker.digest.Digest;
import distMaker.digest.DigestType;
import distMaker.digest.DigestUtils;
import distMaker.platform.PlatformUtils;
import distMaker.utils.ParseUtils;
import distMaker.utils.PlainVersion;
import distMaker.utils.Version;
import distMaker.utils.VersionUtils;
import glum.gui.GuiUtil;
import glum.io.IoUtil;
import glum.net.Credential;
import glum.net.NetUtil;
import glum.task.PartialTask;
import glum.task.Task;
import glum.util.ThreadUtil;
public class AppLauncherUtils
{
/**
* Returns a list of all the available AppLauncher releases specified at: <BR>
* {@literal <aUpdateSiteUrl>/launcher/appCatalog.txt}
*/
public static List<AppLauncherRelease> getAvailableAppLauncherReleases(Task aTask, URL aUpdateSiteUrl, Credential aCredential)
{
List<AppLauncherRelease> retList;
URL catUrl;
URLConnection connection;
InputStream inStream;
BufferedReader bufReader;
DigestType digestType;
String errMsg, strLine;
errMsg = null;
retList = new ArrayList<>();
catUrl = IoUtil.createURL(aUpdateSiteUrl.toString() + "/launcher/appCatalog.txt");
// Default to DigestType of MD5
digestType = DigestType.MD5;
inStream = null;
bufReader = null;
try
{
// Read the contents of the file
connection = catUrl.openConnection();
inStream = NetUtil.getInputStream(connection, aCredential);
bufReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(inStream)));
// Read the lines
while (true)
{
strLine = bufReader.readLine();
// Bail once we are done
if (strLine == null)
break;
// Ignore comments and empty lines
if (strLine.isEmpty() == true || strLine.startsWith("#") == true)
continue;
String[] tokens;
tokens = strLine.split(",", 5);
if (tokens.length == 2 && tokens[0].equals("name") == true && tokens[1].equals("AppLauncher") == true)
; // Nothing to do - we just entered the "JRE" section
// Logic to handle the 'exit' command
else if (tokens.length >= 1 && tokens[0].equals("exit") == true)
{
// We support exit commands with 3 tokens. All others
// we will just exit.
if (tokens.length != 3)
break;
String targName = tokens[1];
String needVer = tokens[2];
if (ParseUtils.shouldExitLogic(targName, needVer) == true)
break;
}
// Logic to handle the 'digest' command
else if (tokens.length == 2 && tokens[0].equals("digest") == true)
{
DigestType tmpDigestType;
tmpDigestType = DigestType.parse(tokens[1]);
if (tmpDigestType == null)
aTask.infoAppendln("Failed to locate DigestType for: " + tokens[1]);
else
digestType = tmpDigestType;
}
// Logic to handle the 'F' command: AppLauncher File
else if (tokens.length == 5 && tokens[0].equals("F") == true)
{
String filename, digestStr, version;
long fileLen;
// Form the JreRelease
digestStr = tokens[1];
fileLen = GuiUtil.readLong(tokens[2], -1);
filename = tokens[3];
version = tokens[4];
Digest tmpDigest = new Digest(digestType, digestStr);
retList.add(new AppLauncherRelease(version, filename, tmpDigest, fileLen));
}
else
{
aTask.infoAppendln("Unreconized line: " + strLine);
}
}
}
catch(FileNotFoundException aExp)
{
errMsg = "Failed to locate resource: " + catUrl;
}
catch(IOException aExp)
{
errMsg = ThreadUtil.getStackTrace(aExp);
}
finally
{
IoUtil.forceClose(inStream);
IoUtil.forceClose(bufReader);
}
// See if we are in a valid state
if (errMsg != null)
; // Nothing to do, as an earlier error has occurred
else if (retList.size() == 0)
errMsg = "The catalog appears to be invalid.";
// Bail if there were issues
if (errMsg != null)
{
aTask.infoAppendln(errMsg);
return null;
}
return retList;
}
/**
* Utility method that checks to see if the AppLauncher will need be updated in order to support the specified JRE.
* <P>
* Returns false if the AppLauncher does NOT need be updated. Otherwise true will be returned and the version info
* will be logged to the specified aTask.
*/
public static boolean isAppLauncherUpdateNeeded(Task aTask, JreRelease aJreRelease)
{
Version currVer, nMinVer, nMaxVer;
// Bail if the installed version of AppLauncher is equal to or later than the required version
currVer = DistUtils.getAppLauncherVersion();
nMinVer = aJreRelease.getAppLauncherMinVersion();
nMaxVer = aJreRelease.getAppLauncherMaxVersion();
if (VersionUtils.isInRange(currVer, nMinVer, nMaxVer) == true)
return false;
// Log the fact that we need to update our AppLauncher
aTask.infoAppendln("Your current AppLauncher is not compatible with this release. It will need to be upgraded!");
aTask.infoAppendln("\tCurrent ver: " + currVer);
if (nMinVer != PlainVersion.AbsMin)
aTask.infoAppendln("\tMinimum ver: " + nMinVer);
if (nMaxVer != PlainVersion.AbsMax)
aTask.infoAppendln("\tMaximum ver: " + nMaxVer);
aTask.infoAppendln("");
return true;
}
/**
* Utility method that will return the AppLauncherRelease that satisfies the requirements as specified by the
* JreRelease.
* <P>
* Returns null if no AppLauncherRelease is located that can satisfy the specified JreRelease.
* <P>
* Any issues that cropped up while searching for a valid AppLauncherRelease will be logged to the specified task,
* aTask.
* <P>
* TODO: Remove the comments below
* <P>
* corresponding to the AppLauncher that we to the specified version required by this JRE.
* <P>
* Returns false on any failure.
*/
public static AppLauncherRelease updateAppLauncher(Task aTask, JreRelease aJreRelease, File aDestPath, URL updateSiteUrl, Credential aCredential)
{
// Locate the list of available AppLaunchers
List<AppLauncherRelease> availList;
availList = AppLauncherUtils.getAvailableAppLauncherReleases(aTask, updateSiteUrl, aCredential);
if (availList == null)
{
aTask.infoAppendln("The update site does not have any deployed AppLaunchers.");
aTask.infoAppendln("Please contact the update site adminstartor.");
return null;
}
if (availList.size() == 0)
{
aTask.infoAppendln("No AppLauncher releases found!");
aTask.infoAppendln("Please contact the update site adminstartor.");
return null;
}
// Retrieve the AppLauncher that is compatible from the list
Version nMinVer = aJreRelease.getAppLauncherMinVersion();
Version nMaxVer = aJreRelease.getAppLauncherMaxVersion();
AppLauncherRelease pickRelease = null;
for (AppLauncherRelease aRelease : availList)
{
Version evalVer = aRelease.getVersion();
if (VersionUtils.isInRange(evalVer, nMinVer, nMaxVer) == false)
continue;
pickRelease = aRelease;
break;
}
// Bail if no compatible release could be found
if (pickRelease == null)
{
aTask.infoAppendln("No compatible AppLauncher releases have been deployed!");
aTask.infoAppendln("Please contact the update site adminstartor.");
return null;
}
// Get stats on the release
Version pickVer = pickRelease.getVersion();
long fileLen = pickRelease.getFileLen();
// Define the path to the launcher
File launcherPath;
if (PlatformUtils.getPlatform().equals("Apple") == true)
launcherPath = new File(aDestPath.getParentFile(), "Java");
else
launcherPath = new File(aDestPath.getParentFile(), "launcher");
// Download the AppLauncher
Digest targDigest, testDigest;
MessageDigest msgDigest;
targDigest = pickRelease.getDigest();
msgDigest = DigestUtils.getDigest(targDigest.getType());
aTask.infoAppendln("Downloading AppLauncher... Version: " + pickVer);
URL srcUrl = IoUtil.createURL(updateSiteUrl.toString() + "/launcher/appLauncher-" + pickVer + ".jar");
File dstFile = new File(launcherPath, pickRelease.getFileName());
int zios_2018Feb15; // TODO: Consider refactoring this code and making it cleaner...
Task tmpTask = new PartialTask(aTask, aTask.getProgress(), 0.01);
// Task tmpTask = new PartialTask(aTask, aTask.getProgress(), (tmpFileLen * 0.75) / (releaseSizeFull + 0.00));
// Task tmpTask = new SilentTask();
if (DistUtils.downloadFile(tmpTask, srcUrl, dstFile, aCredential, fileLen, msgDigest) == false)
{
aTask.infoAppendln("Failed to download updated AppLauncher.");
aTask.infoAppendln("\tSource: " + srcUrl);
aTask.infoAppendln("\tFile: " + dstFile + "\n");
return null;
}
// Validate that the AppLauncher was downloaded successfully
testDigest = new Digest(targDigest.getType(), msgDigest.digest());
if (targDigest.equals(testDigest) == false)
{
aTask.infoAppendln("The download of the AppLauncher appears to be corrupted.");
aTask.infoAppendln("\tFile: " + dstFile);
aTask.infoAppendln("\t\tExpected " + targDigest.getDescr());
aTask.infoAppendln("\t\tReceived " + testDigest.getDescr() + "\n");
return null;
}
// Update the appLauncher.jar file
File targFile = new File(launcherPath, "appLauncher.jar");
boolean isPass;
// Back up the "original" targFile (only if a backup has not already already been made). In case
// there are multiple updates we do not want to overwrite the "real" original
boolean isOriginalBackedUp = false;
File origFile = new File(launcherPath, "appLauncher.jar.orig");
if (origFile.exists() == false)
{
isPass = targFile.renameTo(origFile);
if (isPass == false)
{
aTask.infoAppendln("Failed to rename: " + targFile + " to " + origFile);
}
else
{
isOriginalBackedUp = true;
aTask.infoAppendln("Original file has been backed up.");
aTask.infoAppendln("\t" + targFile + " ---> " + origFile);
}
}
// Update the targFile with the newly downloaded file
isPass = dstFile.renameTo(targFile);
// targFile.renameTo(origFile);
if (isPass == false)
{
aTask.infoAppendln("Failed to rename: " + dstFile + " to " + targFile);
aTask.infoAppendln("Update is being aborted");
// We need to revert to the original backup
if (isOriginalBackedUp == true)
{
isPass = origFile.renameTo(targFile);
if (isPass == false)
{
aTask.infoAppendln("Failed to revert to the orginal AppLauncher.");
aTask.infoAppendln("\t" + targFile);
aTask.infoAppendln("Update has FAILED and left application in an invalid state.\n");
}
}
return null;
}
else
{
aTask.infoAppendln("Success updating AppLauncher... ");
aTask.infoAppendln("\t" + dstFile + " ---> " + targFile + "\n");
}
return pickRelease;
}
}

View File

@@ -1,6 +1,7 @@
package distMaker.jre;
import distMaker.digest.Digest;
import distMaker.utils.Version;
/**
* Immutable class that describes a JRE Release.
@@ -9,19 +10,39 @@ import distMaker.digest.Digest;
*/
public class JreRelease implements Comparable<JreRelease>
{
private String platform;
private JreVersion version;
private Digest digest;
private String fileName;
private long fileLen;
private final Version alMinVer;
private final Version alMaxVer;
private final String platform;
private final JreVersion version;
private final Digest digest;
private final String fileName;
private final long fileLen;
public JreRelease(String aPlatform, String aVersion, String aFileName, Digest aDigest, long aFileLen)
public JreRelease(String aPlatform, String aVersion, String aFileName, Digest aDigest, long aFileLen, Version aAlMinVer, Version aAlMaxVer)
{
platform = aPlatform;
version = new JreVersion(aVersion);
fileName = aFileName;
digest = aDigest;
fileLen = aFileLen;
alMinVer = aAlMinVer;
alMaxVer = aAlMaxVer;
}
/**
* Returns the minimum AppLauncher version compatible with this JRE release.
*/
public Version getAppLauncherMinVersion()
{
return alMinVer;
}
/**
* Returns the maximum AppLauncher version compatible with this JRE release.
*/
public Version getAppLauncherMaxVersion()
{
return alMaxVer;
}
/**

View File

@@ -1,5 +1,21 @@
package distMaker.jre;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import distMaker.digest.Digest;
import distMaker.digest.DigestType;
import distMaker.utils.ParseUtils;
import distMaker.utils.PlainVersion;
import glum.gui.GuiUtil;
import glum.io.IoUtil;
import glum.net.Credential;
@@ -7,19 +23,30 @@ import glum.net.NetUtil;
import glum.task.Task;
import glum.util.ThreadUtil;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import distMaker.digest.Digest;
import distMaker.digest.DigestType;
import distMaker.platform.PlatformUtils;
public class JreUtils
{
/**
* Returns a list of all the available JRE releases specified in &lt;aUpdateSiteUrl&gt;/jre/jreCatalog.txt
* Returns the relative path a JRE should be expanded to.
* <P>
* Namely legacy JRE versions (versions prior to Java 9) will be expanded to:<BR>
* <B>{@code <jre><version>}</B><BR>
* while non legacy versions will be expanded to something like:<BR>
* <B>{@code <jre>-<version>}</B>
*/
public static String getExpandJrePath(JreVersion aJreVersion)
{
String version;
version = aJreVersion.getLabel();
if (version.startsWith("1.") == true)
return "jre" + version;
else
return "jre-" + version;
}
/**
* Returns a list of all the available JRE releases specified at: <BR>
* {@literal <aUpdateSiteUrl>/jre/jreCatalog.txt}
*/
public static List<JreRelease> getAvailableJreReleases(Task aTask, URL aUpdateSiteUrl, Credential aCredential)
{
@@ -28,24 +55,22 @@ public class JreUtils
URLConnection connection;
InputStream inStream;
BufferedReader bufReader;
DigestType digestType;
String errMsg, strLine;
String version;
errMsg = null;
retList = new ArrayList<>();
catUrl = IoUtil.createURL(aUpdateSiteUrl.toString() + "/jre/jreCatalog.txt");
// Default to DigestType of MD5
digestType = DigestType.MD5;
version = null;
PlainVersion alMinVer = PlainVersion.Zero;
PlainVersion alMaxVer = PlainVersion.AbsMax;
DigestType digestType = DigestType.MD5;
String version = null;
inStream = null;
bufReader = null;
try
{
String[] tokens;
// Read the contents of the file
connection = catUrl.openConnection();
inStream = NetUtil.getInputStream(connection, aCredential);
@@ -60,13 +85,28 @@ public class JreUtils
if (strLine == null)
break;
tokens = strLine.split(",", 4);
// Ignore comments and empty lines
if (strLine.isEmpty() == true || strLine.startsWith("#") == true)
; // Nothing to do
else if (tokens.length >= 1 && tokens[0].equals("exit") == true)
break; // Bail once we get the 'exit' command
else if (tokens.length == 2 && tokens[0].equals("name") == true && tokens[1].equals("JRE") == true)
continue;
String[] tokens;
tokens = strLine.split(",", 5);
if (tokens.length == 2 && tokens[0].equals("name") == true && tokens[1].equals("JRE") == true)
; // Nothing to do - we just entered the "JRE" section
// Logic to handle the 'exit' command
else if (tokens.length >= 1 && tokens[0].equals("exit") == true)
{
// We support exit commands with 3 tokens. All others
// we will just exit.
if (tokens.length != 3)
break;
String targName = tokens[1];
String needVer = tokens[2];
if (ParseUtils.shouldExitLogic(targName, needVer) == true)
break;
}
// Logic to handle the 'digest' command
else if (tokens.length == 2 && tokens[0].equals("digest") == true)
{
DigestType tmpDigestType;
@@ -77,10 +117,57 @@ public class JreUtils
else
digestType = tmpDigestType;
}
// Logic to handle the 'jre' command
else if (tokens.length == 2 && tokens[0].equals("jre") == true)
{
version = tokens[1];
// On any new JRE version reset the default required AppLauncher versions
alMinVer = PlainVersion.Zero;
alMaxVer = new PlainVersion(0, 99, 0);
}
// Logic to handle the 'require' command: JRE File
else if (tokens.length >= 3 && tokens[0].equals("require") == true)
{
String target;
// Process the require,AppLauncher instruction
target = tokens[1];
if (target.equals("AppLauncher") == true && (tokens.length == 3 || tokens.length == 4))
{
alMinVer = PlainVersion.parse(tokens[2]);
alMaxVer = new PlainVersion(0, 99, 0);
if (tokens.length == 4)
alMaxVer = PlainVersion.parse(tokens[3]);
continue;
}
aTask.infoAppendln("Unreconized line: " + strLine);
}
// Logic to handle the 'F' command: JRE File
else if (tokens.length == 5 && tokens[0].equals("F") == true)
{
String platform, filename, digestStr;
long fileLen;
if (version == null)
{
aTask.infoAppendln("Skipping input: " + strLine);
aTask.infoAppendln("\tJRE version has not been specifed. Missing input line: jre,<jreVersion>");
continue;
}
// Form the JreRelease
digestStr = tokens[1];
fileLen = GuiUtil.readLong(tokens[2], -1);
platform = tokens[3];
filename = tokens[4];
Digest tmpDigest = new Digest(digestType, digestStr);
retList.add(new JreRelease(platform, version, filename, tmpDigest, fileLen, alMinVer, alMaxVer));
}
// Legacy Logic to handle the 'F' command: JRE File (pre DistMaker 0.50)
else if (tokens.length == 4 && tokens[0].equals("F") == true)
{
String platform, filename, digestStr;
@@ -98,7 +185,7 @@ public class JreUtils
fileLen = GuiUtil.readLong(tokens[2], -1);
filename = tokens[3];
platform = PlatformUtils.getPlatformOfJreTarGz(filename);
platform = JreUtils.getPlatformOfJreTarGz(filename);
if (platform == null)
{
aTask.infoAppendln("Skipping input: " + strLine);
@@ -106,7 +193,7 @@ public class JreUtils
continue;
}
retList.add(new JreRelease(platform, version, filename, new Digest(digestType, digestStr), fileLen));
retList.add(new JreRelease(platform, version, filename, new Digest(digestType, digestStr), fileLen, alMinVer, alMaxVer));
}
else
{
@@ -145,8 +232,8 @@ public class JreUtils
}
/**
* Utility method that returns a list of matching JREs. The list will be sorted in order from newest to oldest. All returned JREs will have a platform that
* matches aPlatform.
* Utility method that returns a list of matching JREs. The list will be sorted in order from newest to oldest. All
* returned JREs will have a platform that matches aPlatform.
*/
public static List<JreRelease> getMatchingPlatforms(List<JreRelease> aJreList, String aPlatform)
{
@@ -169,4 +256,25 @@ public class JreUtils
return retList;
}
/**
* Utility method that returns the platform of the JRE file.
* <P>
* This only examines the filename to determine the platform.
* <P>
* This method should be considered deprecated as of DistMaker 0.48
*/
@Deprecated
private static String getPlatformOfJreTarGz(String aFileName)
{
aFileName = aFileName.toUpperCase();
if (aFileName.contains("LINUX") == true)
return "Linux";
if (aFileName.contains("MACOSX") == true)
return "Apple";
if (aFileName.contains("WINDOWS") == true)
return "Windows";
return null;
}
}

View File

@@ -1,14 +1,46 @@
package distMaker.jre;
import java.util.ArrayList;
import com.google.common.collect.ImmutableList;
import distMaker.utils.Version;
import glum.gui.GuiUtil;
public class JreVersion implements Comparable<JreVersion>
/**
* Immutable class which defines a Java version.
*/
public class JreVersion implements Comparable<JreVersion>, Version
{
private String version;
/** String used to construct this JreVersion */
private final String label;
public JreVersion(String aVersion)
/** List of integers corresponding to the various components of the JRE version. */
private final ImmutableList<Integer> compL;
/** Flag for legacy JRE versions. JRE versions prior to 9.0 are considered legacy. */
private final boolean isLegacy;
public JreVersion(String aLabel)
{
version = aVersion;
label = aLabel;
String[] tokenArr = label.split("[._]");
ArrayList<Integer> workL = new ArrayList<>();
for (String aStr : tokenArr)
{
int tmpVal = GuiUtil.readInt(aStr, Integer.MIN_VALUE);
if (tmpVal == Integer.MIN_VALUE)
break;
workL.add(tmpVal);
}
compL = ImmutableList.copyOf(workL);
if (compL.size() >= 2 && compL.get(0) == 1)
isLegacy = true;
else
isLegacy = false;
}
/**
@@ -16,7 +48,7 @@ public class JreVersion implements Comparable<JreVersion>
*/
public String getLabel()
{
return version;
return label;
}
/**
@@ -29,43 +61,78 @@ public class JreVersion implements Comparable<JreVersion>
public static JreVersion getBetterVersion(JreVersion verA, JreVersion verB)
{
JreVersion defaultVer;
String[] tokenA, tokenB;
int valA, valB, idxCnt;
tokenA = verA.getLabel().split("[._]");
tokenB = verB.getLabel().split("[._]");
// Default JreVersion is the version that is more specific
defaultVer = null;
if (tokenA.length < tokenB.length)
if (verA.compL.size() < verB.compL.size())
defaultVer = verB;
else if (tokenB.length < tokenA.length)
else if (verB.compL.size() < verA.compL.size())
defaultVer = verA;
// Set the idxCnt to the less specific JreVersion
idxCnt = tokenA.length;
if (tokenB.length < tokenA.length)
idxCnt = tokenB.length;
idxCnt = Math.min(verA.compL.size(), verB.compL.size());
// Compare each component of the version string. Each component should be separated by '.'
// Assume each component is an integer where larger values correspond to later versions
// Compare each integral component (which originated from the label)
// Assume higher values correspond to later versions
for (int c1 = 0; c1 < idxCnt; c1++)
{
valA = GuiUtil.readInt(tokenA[c1], -1);
valB = GuiUtil.readInt(tokenB[c1], -1);
if (valA == -1 && valB == -1)
return null;
if (valB == -1 || valA > valB)
valA = verA.compL.get(c1);
valB = verB.compL.get(c1);
if (valA > valB)
return verA;
if (valA == -1 || valB > valA)
if (valB > valA)
return verB;
}
// Defaults to verA
// Defaults to the defaultVer
return defaultVer;
}
@Override
public int getMajorVersion()
{
if (isLegacy == true)
return compL.get(1);
if (compL.size() >= 1)
return compL.get(0);
return 0;
}
@Override
public int getMinorVersion()
{
if (isLegacy == true)
{
if (compL.size() >= 3)
return compL.get(2);
return 0;
}
if (compL.size() >= 2)
return compL.get(1);
return 0;
}
@Override
public int getPatchVersion()
{
if (isLegacy == true)
{
if (compL.size() >= 4)
return compL.get(3);
return 0;
}
if (compL.size() >= 3)
return compL.get(2);
return 0;
}
@Override
public int compareTo(JreVersion aItem)
{

View File

@@ -88,7 +88,7 @@ public class AppCatalog
*/
public boolean isJreVersionTooNew(JreVersion aJreVer)
{
// Check to make sure aJreVer is not too old
// Check to make sure aJreVer is not too new
if (maxJreVer != null && JreVersion.getBetterVersion(maxJreVer, aJreVer) == aJreVer)
return true;

View File

@@ -11,12 +11,19 @@ public class AppRelease implements Comparable<AppRelease>, QueryItem<LookUp>
private final String appName;
private final String version;
private final long buildTime;
private final String infoMsg;
public AppRelease(String aAppName, String aVersion, long aBuildTime)
public AppRelease(String aAppName, String aVersion, long aBuildTime, String aInfoMsg)
{
appName = aAppName;
version = aVersion;
buildTime = aBuildTime;
infoMsg = aInfoMsg;
}
public AppRelease(String aAppName, String aVersion, long aBuildTime)
{
this(aAppName, aVersion, aBuildTime, null);
}
/**
@@ -42,6 +49,16 @@ public class AppRelease implements Comparable<AppRelease>, QueryItem<LookUp>
{
return buildTime;
}
/**
* Returns the info message associated with this release.
* <P>
* Returns null if no infoMsg has been specified.
*/
public String getInfoMsg()
{
return infoMsg;
}
@Override
public int compareTo(AppRelease o)

View File

@@ -13,6 +13,7 @@ import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
import distMaker.*;
import distMaker.jre.JreUtils;
import distMaker.jre.JreVersion;
/**
@@ -54,8 +55,8 @@ public class AppleUtils
/**
* Utility method to update the specified version in the plist file (pFile) to the new version.
* <P>
* Note this method is very brittle, and assumes that the version will occur in the sibling node which immediately follows the node with a value of
* CFBundleVersion. TODO: Consider reducing brittleness.
* Note this method is very brittle, and assumes that the version will occur in the sibling node which immediately
* follows the node with a value of CFBundleVersion. TODO: Consider reducing brittleness.
* <P>
* On failure this method will throw an exception of type ErrorDM.
*/
@@ -68,8 +69,8 @@ public class AppleUtils
/**
* Utility method to update the specified version in the plist file (pFile) to the new version.
* <P>
* Note this method is very brittle, and assumes that the version will occur in the sibling node which immediately follows the node with a value of
* CFBundleVersion. TODO: Consider reducing brittleness.
* Note this method is very brittle, and assumes that the version will occur in the sibling node which immediately
* follows the node with a value of CFBundleVersion. TODO: Consider reducing brittleness.
* <P>
* On failure this method will throw an exception of type ErrorDM.
*/
@@ -170,7 +171,7 @@ public class AppleUtils
// Update the pFile
String regex = "<string>(.*?)</string>";
String repStr = "<string>jre" + aJreVersion.getLabel() + "</string>";
String repStr = "<string>" + JreUtils.getExpandJrePath(aJreVersion) + "</string>";
if (targLineNum == -1)
throw new ErrorDM("[" + pFile + "] The pFile does not specify a 'JVMRuntime' section.");
else if (targLineNum >= inputList.size())
@@ -183,10 +184,11 @@ public class AppleUtils
}
/**
* Utility method to update the specified max memory (-Xmx) value in the system plist file to the specified maxMemVal.
* Utility method to update the specified max memory (-Xmx) value in the system plist file to the specified
* maxMemVal.
* <P>
* In order for this method to succeed there must be a valid JVMOptions section followed by an array of string elements of JVM arguments. The array element
* may be empty but must be specified.
* In order for this method to succeed there must be a valid JVMOptions section followed by an array of string
* elements of JVM arguments. The array element may be empty but must be specified.
* <P>
* On failure this method will throw an exception of type ErrorDM.
*/
@@ -197,10 +199,11 @@ public class AppleUtils
}
/**
* Utility method to update the specified max memory (-Xmx) value in the plist file (pFile) to the specified maxMemVal.
* Utility method to update the specified max memory (-Xmx) value in the plist file (pFile) to the specified
* maxMemVal.
* <P>
* In order for this method to succeed there must be a valid JVMOptions section followed by an array of string elements of JVM arguments. The array element
* may be empty but must be specified.
* In order for this method to succeed there must be a valid JVMOptions section followed by an array of string
* elements of JVM arguments. The array element may be empty but must be specified.
* <P>
* On failure this method will throw an exception of type ErrorDM.
*/

View File

@@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.List;
import distMaker.*;
import distMaker.jre.JreUtils;
import distMaker.jre.JreVersion;
public class LinuxUtils
@@ -15,8 +16,8 @@ public class LinuxUtils
* <P>
* If there are multiple launch scripts then this method may grab the wrong file and fail.
* <P>
* TODO: In the future the launch script should pass itself as an argument to the JVM and DistMaker should keep track of that. If the script is significantly
* manipulated from the original the launch file may be improperly detected.
* TODO: In the future the launch script should pass itself as an argument to the JVM and DistMaker should keep track
* of that. If the script is significantly manipulated from the original the launch file may be improperly detected.
* <P>
* On failure this method will throw an exception of type ErrorDM.
*/
@@ -45,7 +46,7 @@ public class LinuxUtils
if (retFile.isFile() == false)
throw new ErrorDM("The script file is NOT a regular file.");
// Ensure the file is executable. If this is really the script file used to launch us then it should be executable!
// Ensure the file is executable. If this is the script file used to launch us then it should be executable!
if (Files.isExecutable(retFile.toPath()) == false)
throw new ErrorDM("The script file is NOT executable.");
@@ -107,7 +108,7 @@ public class LinuxUtils
// Update the script
if (targLineNum != -1)
inputList.set(targLineNum, "javaExe=../jre" + aJreVersion.getLabel() + "/bin/java");
inputList.set(targLineNum, "javaExe=../" + JreUtils.getExpandJrePath(aJreVersion) + "/bin/java");
else
throw new ErrorDM("[" + aScriptFile + "] The script does not specify 'javaExe'.");
@@ -118,11 +119,11 @@ public class LinuxUtils
/**
* Utility method to update the specified maxMem var in the script (aFile) to the requested number of bytes.
* <P>
* Note this method assumes the specified file is a shell script built by DistMaker where the var maxMem holds the proper (right side) specification for the
* JVM's -Xmx value.
* Note this method assumes the specified file is a shell script built by DistMaker where the var maxMem holds the
* proper (right side) specification for the JVM's -Xmx value.
* <P>
* If the maxMem var definition is moved in the script file to after the launch of the application then this method will (silently) fail to configure the
* value needed to launch the JVM.
* If the maxMem var definition is moved in the script file to after the launch of the application then this method
* will (silently) fail to configure the value needed to launch the JVM.
* <P>
* On failure this method will throw an exception of type ErrorDM.
*/
@@ -135,11 +136,11 @@ public class LinuxUtils
/**
* Utility method to update the specified maxMem var in the script (aFile) to the requested number of bytes.
* <P>
* Note this method assumes the specified file is a shell script built by DistMaker where the var maxMem holds the proper (right side) specification for the
* JVM's -Xmx value.
* Note this method assumes the specified file is a shell script built by DistMaker where the var maxMem holds the
* proper (right side) specification for the JVM's -Xmx value.
* <P>
* If the maxMem var definition is moved in the script file to after the launch of the application then this method will (silently) fail to configure the
* value needed to launch the JVM.
* If the maxMem var definition is moved in the script file to after the launch of the application then this method
* will (silently) fail to configure the value needed to launch the JVM.
* <P>
* On failure this method will throw an exception of type ErrorDM.
*/

View File

@@ -15,8 +15,8 @@ public class MemUtils
public static final long GB_SIZE = 1024 * 1024 * 1024;
/**
* Utility method that attempts to compute the installed system memory (ram). If the installed system ram can not be computed, then the system is assumed to
* have 4 GB.
* Utility method that attempts to compute the installed system memory (ram). If the installed system ram can not be
* computed, then the system is assumed to have 4 GB.
*/
public static long getInstalledSystemMemory()
{
@@ -57,7 +57,8 @@ public class MemUtils
}
/**
* Utility method that takes an inputStr, locates the fragment -Xmx*, and replaces the fragment with the appropriate -Xmx with respect to numBytes.
* Utility method that takes an inputStr, locates the fragment -Xmx*, and replaces the fragment with the appropriate
* -Xmx with respect to numBytes.
* <P>
* This method is a bit brittle in that it assumes the -Xmx string is surrounded with 1 white space character.
* <P>

View File

@@ -4,8 +4,7 @@ import java.io.File;
import distMaker.DistUtils;
import distMaker.ErrorDM;
import distMaker.jre.JreRelease;
import distMaker.jre.JreVersion;
import distMaker.jre.*;
import distMaker.node.AppRelease;
public class PlatformUtils
@@ -45,22 +44,22 @@ public class PlatformUtils
*/
public static File getJreLocation(JreVersion aJreVersion)
{
String platform, versionStr;
File jrePath, installPath;
String platform, relJrePathStr;
File installPath, retJrePath;
jrePath = null;
retJrePath = null;
installPath = DistUtils.getAppPath();
versionStr = aJreVersion.getLabel();
relJrePathStr = JreUtils.getExpandJrePath(aJreVersion);
platform = PlatformUtils.getPlatform().toUpperCase();
if (platform.equals("APPLE") == true)
jrePath = new File(installPath.getParentFile(), "PlugIns/jre" + versionStr);
retJrePath = new File(installPath.getParentFile(), "PlugIns/" + relJrePathStr);
else if (platform.equals("LINUX") == true)
jrePath = new File(installPath.getParentFile(), "jre" + versionStr);
retJrePath = new File(installPath.getParentFile(), relJrePathStr);
else if (platform.equals("WINDOWS") == true)
jrePath = new File(installPath.getParentFile(), "jre" + versionStr);
retJrePath = new File(installPath.getParentFile(), relJrePathStr);
return jrePath;
return retJrePath;
}
/**
@@ -81,24 +80,6 @@ public class PlatformUtils
return System.getProperty("os.name");
}
/**
* Returns the platform of the JRE file.
* <P>
* This only examines the filename to determine the platform.
*/
public static String getPlatformOfJreTarGz(String aFileName)
{
aFileName = aFileName.toUpperCase();
if (aFileName.contains("LINUX") == true)
return "Linux";
if (aFileName.contains("MACOSX") == true)
return "Apple";
if (aFileName.contains("WINDOWS") == true)
return "Windows";
return null;
}
/**
* Utility method to configure the JRE version used by the (active) DistMaker distribution.
* <P>
@@ -107,7 +88,7 @@ public class PlatformUtils
* On failure this method will throw an exception of type ErrorDM.
*
* @param aJrePath
* Path to top of the JRE.
* Path to top of the JRE.
*/
public static void setJreVersion(JreVersion aJreVersion)
{
@@ -133,7 +114,7 @@ public class PlatformUtils
* On failure this method will throw an exception of type ErrorDM.
*
* @param maxMemSize
* Maximum heap memory in bytes.
* Maximum heap memory in bytes.
*/
public static void setMaxHeapMem(long maxMemSize)
{

View File

@@ -84,7 +84,7 @@ public final class DeployUtils {
updateButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
public void actionPerformed(ActionEvent e)
{
UpdateCheckListener listener = new UpdateCheckListener() {
@Override
@@ -105,7 +105,7 @@ public final class DeployUtils {
configureMemoryButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
public void actionPerformed(ActionEvent e)
{
if(DistUtils.isDevelopersEnvironment()) {
JOptionPane.showMessageDialog(parentFrame, "Cannot configure memory in a developer environment.");

View File

@@ -0,0 +1,64 @@
package distMaker.utils;
import distMaker.DistUtils;
public class ParseUtils
{
/**
* Utility method that processes the 'exit' instruction.
* <P>
* Returns true if the processing of the configuration file should exit.
* <P>
* Processing of the configuration file should exit if the specified needed version is not met or the version string
* could not be parsed into major minor components.
*
* @param aTargName
* The target component whose version will be evaluated. Current supported values are one of the following:
* [AppLauncher, DistMaker]
* @param aNeededVer
* A string describing the minimum version that is required in order for this exit instruction to be ignored.
* @return Returns true if the needed version requirements are not met.
*/
public static boolean shouldExitLogic(String aTargName, String aNeededVer)
{
// We handle logic for the following targets: [AppLauncher, DistMaker]
// If not one of the specified targets then further parsing should stop
Version evalVer;
if (aTargName.equals("DistMaker") == true)
evalVer = DistUtils.getDistMakerVersion();
else if (aTargName.equals("AppLauncher") == true)
evalVer = DistUtils.getAppLauncherVersion();
else
return true;
// Determine the needed version
int needMajorVer = Integer.MAX_VALUE;
int needMinorVer = Integer.MAX_VALUE;
try
{
String[] versionArr;
versionArr = aNeededVer.split("\\.");
if (versionArr.length >= 1)
needMajorVer = Integer.parseInt(versionArr[0]);
if (versionArr.length >= 2)
needMinorVer = Integer.parseInt(versionArr[1]);
}
catch(Throwable aExp)
{
// Ignore just assume version components are whatever we managed to parse
}
Version needVer;
needVer = new PlainVersion(needMajorVer, needMinorVer, 0);
// Exit the logic if the needVer > evalVer
if (needVer.getMajorVersion() > evalVer.getMajorVersion())
return true;
if (needVer.getMajorVersion() == needVer.getMajorVersion() && needVer.getMinorVersion() > evalVer.getMinorVersion())
return true;
return false;
}
}

View File

@@ -0,0 +1,72 @@
package distMaker.utils;
/**
* Provides the standard implementation of the Version interface.
*/
public class PlainVersion implements Version
{
// Constants
public static PlainVersion AbsMin = new PlainVersion(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
public static PlainVersion AbsMax = new PlainVersion(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
public static PlainVersion Zero = new PlainVersion(0, 0, 0);
// Attributes
private final int major;
private final int minor;
private final int patch;
public PlainVersion(int aMajor, int aMinor, int aPatch)
{
major = aMajor;
minor = aMinor;
patch = aPatch;
}
/**
* Forms a PlainVersion from the specified string. The version should have have at most 3 integer components
* separated by the char: '.'. Any extra components after the first 3 will be ignored. A NumberFormatException will
* be thrown if the type of any of the first 3 are not integers.
*/
public static PlainVersion parse(String aStr)
{
String[] tokenArr = aStr.split("\\.");
int major = 0, minor = 0, patch = 0;
major = Integer.parseInt(tokenArr[0]);
if (tokenArr.length >= 2)
minor = Integer.parseInt(tokenArr[1]);
if (tokenArr.length >= 3)
patch = Integer.parseInt(tokenArr[2]);
return new PlainVersion(major, minor, patch);
}
@Override
public int getMajorVersion()
{
return major;
}
@Override
public int getMinorVersion()
{
return minor;
}
@Override
public int getPatchVersion()
{
return patch;
}
@Override
public String toString()
{
String retStr = "" + major + "." + minor;
if (patch != 0)
retStr += "." + patch;
return retStr;
}
}

View File

@@ -0,0 +1,29 @@
package distMaker.utils;
/**
* Interface which provides access to version components (major, minor, patch).
* <P>
* Each component is modeled as an integer and it is assumed that higher values correspond to more developed software.
* <P>
* Reference: https://semver.org/
* <P>
* Implementors of this interface should be immutable.
*/
public interface Version
{
/**
* Returns the major version component.
*/
public int getMajorVersion();
/**
* Returns the minor version component.
*/
public int getMinorVersion();
/**
* Returns the patch version component.
*/
public int getPatchVersion();
}

View File

@@ -0,0 +1,94 @@
package distMaker.utils;
/**
* Utility class that allows for comparing Versions.
* <P>
* Eventually when Java allows operator overloading then this class can go away since the standard mathematical
* comparison symbols would be much clearer.
*/
public class VersionUtils
{
/**
* Utility method that returns true if aVerA occurs after aVerB
*/
public static boolean isAfter(Version aVerA, Version aVerB)
{
int majorA = aVerA.getMajorVersion();
int minorA = aVerA.getMinorVersion();
int patchA = aVerA.getPatchVersion();
int majorB = aVerB.getMajorVersion();
int minorB = aVerB.getMinorVersion();
int patchB = aVerB.getPatchVersion();
if (majorA > majorB)
return true;
if (majorA == majorB && minorA > minorB)
return true;
if (majorA == majorB && minorA == minorB && patchA > patchB)
return true;
return false;
}
/**
* Utility method that returns true if aVerA occurs after aVerB
*/
public static boolean isAfterOrEquar(Version aVerA, Version aVerB)
{
// Delegate to isAfter
return isAfter(aVerB, aVerA) == false;
}
/**
* Utility method that returns true if the following statement is true:
* <P>
* aVerEval >= aVerMin && aVerEval <= aVerMax
* <P>
* A LogicError will be thrown if the aVerMin and aVerMax are inverted (aVerMin > aVerMax)
*/
public static boolean isInRange(Version aVerEval, Version aVerMin, Version aVerMax)
{
// Ensure the endpoints are not inverted
if (isAfter(aVerMin, aVerMax) == true)
throw new RuntimeException("Min/Max versions appear to be swapped. min: " + aVerMin + " max: " + aVerMax);
// Decompose and delegate
if (isAfter(aVerMin, aVerEval) == true)
return false;
if (isAfter(aVerEval, aVerMax) == true)
return false;
return true;
}
/**
* Utility method to allow the comparison of two versions.
*
* @param aVerA
* @param aVerB
* @return
*/
public static int compare(Version aVerA, Version aVerB)
{
int majorA = aVerA.getMajorVersion();
int minorA = aVerA.getMinorVersion();
int patchA = aVerA.getPatchVersion();
int majorB = aVerB.getMajorVersion();
int minorB = aVerB.getMinorVersion();
int patchB = aVerB.getPatchVersion();
int cmpVal;
cmpVal = majorA - majorB;
if (cmpVal != 0)
return cmpVal;
cmpVal = minorA - minorB;
if (cmpVal != 0)
return cmpVal;
cmpVal = patchA - patchB;
if (cmpVal != 0)
return cmpVal;
return 0;
}
}

Binary file not shown.

View File

@@ -1,30 +1,14 @@
#! /usr/bin/env python
import fnmatch
import argparse
import glob
import os
import subprocess
import shutil
import signal
import subprocess
import sys
import time
# Globals
# The default version of DistMaker
version = '0.47'
def logAndPrint(message="", indent=0, showTime=False):
while indent > 0:
indent -= 1
message = ' ' + message
if showTime == True:
message = '[' + getCurrTimeStr() + '] ' + message;
# logging.info(message)
print(message)
def buildRelease(version, doNotClean=False):
def getDistMakerVersion():
# Retrieve the install path
installPath = getInstallRoot()
installPath = os.path.dirname(installPath)
@@ -32,15 +16,38 @@ def buildRelease(version, doNotClean=False):
# Check for distMaker.jar library prerequisite
testPath = os.path.join(installPath, 'lib', 'distMaker.jar')
if os.path.exists(testPath) == False:
logAndPrint('Aborting DistMaker release build. The file ' + testPath + ' does not exist.', indent=1)
logAndPrint('Please run the buildDistMakerBin.jardesc from your workspace.', indent=1)
errPrintln('Aborting DistMaker release build. The file ' + testPath + ' does not exist.', indent=1)
errPrintln('Please run the buildDistMakerBin.jardesc from your workspace.', indent=1)
exit(-1)
try:
exeCmd = ['java', '-cp', 'lib/distMaker.jar', 'distMaker.DistApp', '--version']
output = subprocess.check_output(exeCmd).decode('utf-8')
version = output.split()[1]
return version
except:
errPrintln('Please run the buildDistMakerBin.jardesc from your workspace.', indent=1)
exit(-1)
def errPrintln(message="", indent=0):
"""Print the specified string with a trailing newline to stderr."""
while indent > 0:
indent -= 1
message = ' ' + message
sys.stderr.write(message + '\n')
def buildRelease(version, doNotClean=False):
# Retrieve the install path
installPath = getInstallRoot()
installPath = os.path.dirname(installPath)
# Check for static jre prerequisites
isPass = os.path.exists(os.path.join(installPath, 'jre'))
if isPass == False:
logAndPrint('Aborting DistMaker release build. The jre path is not properly configured.', indent=1)
logAndPrint('Please setup the jre path properly. A quick fix is to copy the jre tree from a previous release of DistMaker.', indent=1)
errPrintln('Aborting DistMaker release build. The jre path is not properly configured.', indent=1)
errPrintln('Please setup the jre path properly. A quick fix is to copy the jre tree from a previous release of DistMaker.', indent=1)
exit(-1)
# Determine the workPath
@@ -49,12 +56,12 @@ def buildRelease(version, doNotClean=False):
# Bail if the work folder for which we compose the release already exists
if os.path.exists(workPath) == True:
logAndPrint('Aborting DistMaker release build. Release folder already exists: ' + workPath, indent=1)
errPrintln('Aborting DistMaker release build. Release folder already exists: ' + workPath, indent=1)
exit(-1)
# Bail if the release already exists
if os.path.exists(destFileGZ) == True:
logAndPrint('Aborting DistMaker release build. Release already exists. File: ' + destFileGZ, indent=1)
errPrintln('Aborting DistMaker release build. Release already exists. File: ' + destFileGZ, indent=1)
exit(-1)
# Laydown the structure, and let the user know of the version we are building
@@ -113,16 +120,6 @@ def getInstallRoot():
return installRoot
def printUsage():
scriptName = os.path.split(sys.argv[0])[1]
print(scriptName + ' [-help,-doNotClean,-full],[-version <aVersion>]')
print(' -help: Show this help message and exit.')
print(' -version: Version to build. Default is: ' + version)
print(' -doNotClean: Do NOT remove temporary work folder created while generating release.')
print(' -full: Force a full build of the main jar file. (Unsupported action)')
exit(-1)
def handleSignal(signal, frame):
"""Signal handler, typically used to capture ctrl-c."""
print('User aborted processing!')
@@ -130,43 +127,31 @@ def handleSignal(signal, frame):
if __name__ == "__main__":
argv = sys.argv
argc = len(argv)
# Intercept any request for a help message and bail
for aArg in argv:
if aArg == '-h' or aArg == '-help':
printUsage()
exit()
doFullBuild = False
doNotClean = False
skipNext = False;
for currIdx in xrange(1, len(argv)):
aArg = argv[currIdx]
if skipNext == True:
skipNext = False
continue
if aArg == '-full':
doFullBuild = True
elif aArg == '-doNotClean':
doNotClean = True
elif aArg == '-version':
if currIdx == argc - 1:
print('\tPlease specify an actual version when using -version')
exit(-1)
else:
version = argv[currIdx + 1]
skipNext = True
else:
print(' Unrecognized argument: ' + aArg)
printUsage()
# Logic to capture Ctrl-C and bail
signal.signal(signal.SIGINT, handleSignal)
# TODO: Finish this functionality
if doFullBuild == True:
print("Unsupported action: [-full]. Skipping...")
tmpDescr = 'Utility to build a DistMaker release\n'
parser = argparse.ArgumentParser(prefix_chars='-', description=tmpDescr, add_help=False, fromfile_prefix_chars='@')
parser.add_argument('-help', '-h', help='Show this help message and exit.', action='help')
parser.add_argument('-doNotClean', default=False, action='store_true', help='Do NOT remove temporary work folder created while generating release.')
parser.add_argument('-doFullBuild', default=False, action='store_true', help='Force a full build of the main jar file. (Unsupported action)')
buildRelease(version, doNotClean)
# Intercept any request for a help message and bail
argv = sys.argv;
if '-h' in argv or '-help' in argv:
parser.print_help()
exit()
# Parse the args
parser.formatter_class.max_help_position = 50
args = parser.parse_args()
# Get the version of DistMaker we are building
version = getDistMakerVersion()
print('DistMaker version: ' + version)
# TODO: Finish this functionality
if args.doFullBuild == True:
print("Unsupported action: [-doFullBuild]. Skipping...")
buildRelease(version, args.doNotClean)