mirror of
https://github.com/JHUAPL/DistMaker.git
synced 2026-01-07 21:54:07 -05:00
Updated logic to support
- Code cleanup / refactor - Improved Java versioning related logic - Added support for Java version range (rather than just minimum version) - Added support for JRE updating - Improved update revert logic - Added support to untar jvm tar.gz archives
This commit is contained in:
@@ -10,10 +10,12 @@ 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.Files;
|
||||
import java.nio.file.*;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
|
||||
@@ -21,13 +23,13 @@ import javax.swing.JFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import distMaker.digest.Digest;
|
||||
import distMaker.digest.DigestUtils;
|
||||
import distMaker.gui.PickReleasePanel;
|
||||
import distMaker.jre.*;
|
||||
import distMaker.node.*;
|
||||
import distMaker.platform.AppleUtils;
|
||||
import distMaker.platform.PlatformUtils;
|
||||
|
||||
public class DistMakerEngine
|
||||
@@ -110,6 +112,14 @@ public class DistMakerEngine
|
||||
return currRelease;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL where software updates for this application are retrieved from.
|
||||
*/
|
||||
public URL getUpdateSite()
|
||||
{
|
||||
return updateSiteUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns
|
||||
*
|
||||
@@ -154,7 +164,6 @@ public class DistMakerEngine
|
||||
private void initialize()
|
||||
{
|
||||
File appPath, cfgFile;
|
||||
BufferedReader br;
|
||||
DateUnit dateUnit;
|
||||
String currInstr, strLine;
|
||||
String appName, verName, buildStr;
|
||||
@@ -180,11 +189,8 @@ public class DistMakerEngine
|
||||
}
|
||||
|
||||
// Read in the configuration file
|
||||
br = null;
|
||||
try
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(cfgFile))))
|
||||
{
|
||||
br = new BufferedReader(new InputStreamReader(new FileInputStream(cfgFile)));
|
||||
|
||||
// Read the lines
|
||||
currInstr = "None";
|
||||
while (true)
|
||||
@@ -215,10 +221,6 @@ public class DistMakerEngine
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
IoUtil.forceClose(br);
|
||||
}
|
||||
|
||||
if (appName == null || verName == null)
|
||||
{
|
||||
@@ -343,7 +345,7 @@ public class DistMakerEngine
|
||||
}
|
||||
|
||||
// Download the release
|
||||
isPass = downloadRelease(aTask, chosenItem, deltaPath);
|
||||
isPass = downloadAppRelease(aTask, chosenItem, deltaPath);
|
||||
if (isPass == false || aTask.isActive() == false)
|
||||
{
|
||||
IoUtil.deleteDirectory(deltaPath);
|
||||
@@ -370,6 +372,29 @@ public class DistMakerEngine
|
||||
aMsg += "Please check installation configuration.";
|
||||
}
|
||||
|
||||
// If the parentFrame is not visible then delay the showing until it is visible
|
||||
if (parentFrame.isVisible() == false)
|
||||
{
|
||||
final String tmpMsg = aMsg;
|
||||
parentFrame.addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentShown(ComponentEvent aEvent)
|
||||
{
|
||||
msgPanel.setTitle("Application Updater");
|
||||
msgPanel.setInfo(tmpMsg);
|
||||
msgPanel.setVisible(true);
|
||||
|
||||
// Deregister for events after the parentFrame is made visible
|
||||
parentFrame.removeComponentListener(this);
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Transform tabs to 3 spaces
|
||||
aMsg = aMsg.replace("\t", " ");
|
||||
|
||||
// Display the message
|
||||
msgPanel.setTitle("Application Updater");
|
||||
msgPanel.setInfo(aMsg);
|
||||
@@ -381,7 +406,7 @@ public class DistMakerEngine
|
||||
* <P>
|
||||
* Returns true if the release was downloaded properly.
|
||||
*/
|
||||
private boolean downloadRelease(Task aTask, AppRelease aRelease, File destPath)
|
||||
private boolean downloadAppRelease(Task aTask, AppRelease aRelease, File destPath)
|
||||
{
|
||||
AppCatalog staleCat, updateCat;
|
||||
Node staleNode, updateNode;
|
||||
@@ -390,7 +415,6 @@ public class DistMakerEngine
|
||||
Task mainTask, tmpTask;
|
||||
double progressVal;
|
||||
long tmpFileLen;
|
||||
boolean isPass;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -404,20 +428,21 @@ public class DistMakerEngine
|
||||
return false;
|
||||
}
|
||||
|
||||
// Download the update catalog to the (local) delta location (Progress -> [0% - 1%])
|
||||
catUrl = IoUtil.createURL(updateUrl.toString() + "/catalog.txt");
|
||||
catalogFile = new File(destPath, "catalog.txt");
|
||||
if (DistUtils.downloadFile(new PartialTask(aTask, 0.00, 0.01), catUrl, catalogFile, refCredential, -1L, null) == false)
|
||||
return false;
|
||||
|
||||
// Load the stale catalog
|
||||
catalogFile = new File(DistUtils.getAppPath(), "catalog.txt");
|
||||
staleCat = DistUtils.readAppCatalog(aTask, catalogFile, staleUrl);
|
||||
if (staleCat == null)
|
||||
return false;
|
||||
|
||||
// Download the update app catalog to the (local) delta location (Progress -> [0% - 1%])
|
||||
File appNewPath = new File(destPath, "app");
|
||||
appNewPath.mkdirs();
|
||||
catUrl = IoUtil.createURL(updateUrl.toString() + "/catalog.txt");
|
||||
catalogFile = new File(appNewPath, "catalog.txt");
|
||||
if (DistUtils.downloadFile(new PartialTask(aTask, 0.00, 0.01), catUrl, catalogFile, refCredential, -1L, null) == false)
|
||||
return false;
|
||||
|
||||
// Load the update catalog
|
||||
catalogFile = new File(destPath, "catalog.txt");
|
||||
updateCat = DistUtils.readAppCatalog(aTask, catalogFile, updateUrl);
|
||||
if (updateCat == null)
|
||||
return false;
|
||||
@@ -433,136 +458,29 @@ public class DistMakerEngine
|
||||
// Set up the mainTask for downloading of remote content (Progress -> [1% - 95%])
|
||||
mainTask = new PartialTask(aTask, 0.01, 0.94);
|
||||
|
||||
// Ensure our JRE version is sufficient for this release
|
||||
// Ensure our JRE version is compatible for this release
|
||||
JreRelease targJre = null;
|
||||
JreVersion currJreVer = DistUtils.getJreVersion();
|
||||
JreVersion targJreVer = updateCat.getJreVersion();
|
||||
if (targJreVer != null && JreVersion.getBetterVersion(targJreVer, currJreVer) != currJreVer)
|
||||
if (updateCat.isJreVersionCompatible(currJreVer) == false)
|
||||
{
|
||||
List<JreRelease> jreList;
|
||||
|
||||
aTask.infoAppendln("Your current JRE is too old. It will need to be updated!");
|
||||
aTask.infoAppendln("\tCurrent JRE: " + currJreVer.getLabel());
|
||||
aTask.infoAppendln("\tMinimun JRE: " + targJreVer.getLabel() + "\n");
|
||||
|
||||
// Get list of all available JREs
|
||||
jreList = JreUtils.getAvailableJreReleases(aTask, updateSiteUrl, refCredential);
|
||||
if (jreList == null)
|
||||
{
|
||||
aTask.infoAppendln("The update site has not had any JREs deployed.");
|
||||
aTask.infoAppendln("Please contact the update site adminstartor.");
|
||||
// Bail if we failed to download a compatible JRE
|
||||
targJre = downloadJreUpdate(mainTask, updateCat, destPath, releaseSizeFull);
|
||||
if (targJre == null)
|
||||
return false;
|
||||
}
|
||||
if (jreList.size() == 0)
|
||||
{
|
||||
aTask.infoAppendln("No JRE releases found!");
|
||||
aTask.infoAppendln("Please contact the update site adminstartor.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the latest appropriate JreRelease
|
||||
String platform = DistUtils.getPlatform();
|
||||
jreList = JreUtils.getMatchingPlatforms(jreList, platform);
|
||||
if (jreList.size() == 0)
|
||||
{
|
||||
aTask.infoAppendln("There are no JRE releases available for the platform: " + platform + "!");
|
||||
return false;
|
||||
}
|
||||
|
||||
JreRelease pickJre = jreList.get(0);
|
||||
JreVersion pickJreVer = pickJre.getVersion();
|
||||
|
||||
if (JreVersion.getBetterVersion(pickJreVer, targJreVer) == currJreVer)
|
||||
{
|
||||
aTask.infoAppendln("The latest available JRE on the update site is not recent enought!");
|
||||
aTask.infoAppendln("Minimun required JRE: " + targJreVer.getLabel());
|
||||
aTask.infoAppendln("Latest available JRE: " + pickJreVer.getLabel());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the number of bytes to be retrieved to take into account the JRE which we will be downloading
|
||||
// and form the appropriate tmpTask
|
||||
tmpFileLen = pickJre.getFileLen();
|
||||
releaseSizeFull += tmpFileLen;
|
||||
tmpTask = new PartialTask(mainTask, mainTask.getProgress(), tmpFileLen / (releaseSizeFull + 0.00));
|
||||
|
||||
// Download the JRE
|
||||
Digest targDigest, testDigest;
|
||||
targDigest = pickJre.getDigest();
|
||||
MessageDigest msgDigest;
|
||||
msgDigest = DigestUtils.getDigest(targDigest.getType());
|
||||
mainTask.infoAppendln("Downloading JRE... Version: " + pickJre.getVersion().getLabel());
|
||||
URL srcUrl = IoUtil.createURL(updateSiteUrl.toString() + "/jre/" + pickJre.getFileName());
|
||||
File dstFile = new File(new File(destPath, "jre"), pickJre.getFileName());
|
||||
DistUtils.downloadFile(tmpTask, srcUrl, dstFile, refCredential, tmpFileLen, msgDigest);
|
||||
|
||||
// Validate that the JRE was downloaded successfully
|
||||
testDigest = new Digest(targDigest.getType(), msgDigest.digest());
|
||||
if (targDigest.equals(testDigest) == false)
|
||||
{
|
||||
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");
|
||||
return false;
|
||||
}
|
||||
releaseSizeCurr += tmpFileLen;
|
||||
// Update the progress to reflect the downloaded / updated JRE
|
||||
releaseSizeCurr += targJre.getFileLen();
|
||||
releaseSizeFull += targJre.getFileLen();
|
||||
progressVal = releaseSizeCurr / (releaseSizeFull + 0.00);
|
||||
mainTask.setProgress(progressVal);
|
||||
|
||||
// TODO: Unpack the JRE at the proper location and then delete it
|
||||
File jrePath = PlatformUtils.getJreLocation(pickJre);
|
||||
try
|
||||
{
|
||||
int finish_me_and_clean_me;
|
||||
// Files.createTempDirectory(dstFile, prefix, attrs)
|
||||
// Files.createTempDir();
|
||||
|
||||
|
||||
File unpackPath;
|
||||
unpackPath = new File(destPath, "jre/unpack");
|
||||
unpackPath.mkdirs();
|
||||
MiscUtils.unTar(dstFile, unpackPath);
|
||||
|
||||
File[] fileArr;
|
||||
fileArr = unpackPath.listFiles();
|
||||
if (fileArr.length != 1 && fileArr[0].isDirectory() == false)
|
||||
throw new Exception("Expected only one (top level) folder to be unpacked. Items extracted: " + fileArr.length + " Path: " + unpackPath);
|
||||
|
||||
File jreUnpackedPath;
|
||||
jreUnpackedPath = fileArr[0];
|
||||
|
||||
// Moved the unpacked file to the "standardized" jrePath
|
||||
jreUnpackedPath.renameTo(jrePath);
|
||||
// MiscUtils.unTar(dstFile, jrePath);
|
||||
|
||||
// TODO: Remove the unpacked folder...
|
||||
}
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aTask.infoAppendln("Failed to untar archive. The update has been aborted.");
|
||||
aTask.infoAppendln("\tTar File: " + dstFile);
|
||||
aTask.infoAppendln("\tDestination: " + jrePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Update the launch script or launch config file to point to the proper JRE
|
||||
if (PlatformUtils.setJreLocation(jrePath) == false)
|
||||
{
|
||||
aTask.infoAppendln("Failed to update the configuration to point to the updated JRE!");
|
||||
aTask.infoAppendln("\tCurrent JRE: " + currJreVer.getLabel());
|
||||
aTask.infoAppendln("\t Chosen JRE: " + pickJreVer.getLabel());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
// TODO: Eventually remove the old JRE - perhaps from the app launcher
|
||||
}
|
||||
|
||||
// Download the individual application files
|
||||
mainTask.infoAppendln("Downloading release: " + aRelease.getVersion() + " Nodes: " + updateCat.getAllNodesList().size());
|
||||
for (Node aNode : updateCat.getAllNodesList())
|
||||
{
|
||||
boolean isPass;
|
||||
|
||||
// Bail if we have been aborted
|
||||
if (mainTask.isActive() == false)
|
||||
return false;
|
||||
@@ -580,9 +498,9 @@ public class DistMakerEngine
|
||||
{
|
||||
// Note we pass the SilentTask since
|
||||
// - This should be fairly fast since this should result in a local disk copy
|
||||
// - This may fail, (but the failuer is recoverable and this serves just as an optimization)
|
||||
// - This may fail, (but the failure is recoverable and this serves just as an optimization)
|
||||
// isPass = staleNode.transferContentTo(tmpTask, refCredential, destPath);
|
||||
isPass = staleNode.transferContentTo(new SilentTask(), refCredential, destPath);
|
||||
isPass = staleNode.transferContentTo(new SilentTask(), refCredential, appNewPath);
|
||||
if (isPass == true)
|
||||
mainTask.infoAppendln("\t(L) " + staleNode.getFileName());
|
||||
}
|
||||
@@ -590,7 +508,7 @@ public class DistMakerEngine
|
||||
// Use the remote update copy, if we were not able to use a local stale copy
|
||||
if (isPass == false && mainTask.isActive() == true)
|
||||
{
|
||||
isPass = updateNode.transferContentTo(tmpTask, refCredential, destPath);
|
||||
isPass = updateNode.transferContentTo(tmpTask, refCredential, appNewPath);
|
||||
if (isPass == true)
|
||||
mainTask.infoAppendln("\t(R) " + updateNode.getFileName());
|
||||
}
|
||||
@@ -601,7 +519,7 @@ public class DistMakerEngine
|
||||
mainTask.infoAppendln("Failed to download from update site.");
|
||||
mainTask.infoAppendln("\tSite: " + updateUrl);
|
||||
mainTask.infoAppendln("\tFile: " + updateNode.getFileName());
|
||||
mainTask.infoAppendln("\tDest: " + destPath);
|
||||
mainTask.infoAppendln("\tDest: " + appNewPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -610,11 +528,246 @@ public class DistMakerEngine
|
||||
progressVal = releaseSizeCurr / (releaseSizeFull + 0.00);
|
||||
mainTask.setProgress(progressVal);
|
||||
}
|
||||
mainTask.infoAppendln("Finished downloading release.\n");
|
||||
|
||||
// Update the platform configuration files
|
||||
isPass = updatePlatformConfigFiles(aTask, aRelease);
|
||||
try
|
||||
{
|
||||
PlatformUtils.updateAppRelease(aRelease);
|
||||
}
|
||||
catch(ErrorDM aExp)
|
||||
{
|
||||
aTask.infoAppendln("Failed updating application configuration.");
|
||||
printErrorDM(aTask, aExp, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
return isPass;
|
||||
// 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)
|
||||
File deltaCmdFile = new File(destPath, "delta.cmd");
|
||||
try (FileWriter tmpFW = new FileWriter(deltaCmdFile))
|
||||
{
|
||||
if (targJre != null)
|
||||
{
|
||||
File rootPath = DistUtils.getAppPath().getParentFile();
|
||||
|
||||
JreVersion targJreVer = targJre.getVersion();
|
||||
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("move,jre" + targJreVer.getLabel() + ",delta" + "\n");
|
||||
tmpFW.write("reboot\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("exit\n\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpFW.write("# Define the fail section (clean up for failure)\n");
|
||||
tmpFW.write("sect,fail\n");
|
||||
tmpFW.write("exit\n\n");
|
||||
|
||||
tmpFW.write("# Define the pass section (clean up for success)\n");
|
||||
tmpFW.write("sect,pass\n");
|
||||
tmpFW.write("exit\n\n");
|
||||
}
|
||||
|
||||
tmpFW.write("# Define the reboot section\n");
|
||||
tmpFW.write("sect,reboot\n");
|
||||
tmpFW.write("exit\n\n");
|
||||
|
||||
tmpFW.write("# Define the test section\n");
|
||||
tmpFW.write("sect,test\n");
|
||||
tmpFW.write("exit\n\n");
|
||||
}
|
||||
catch(IOException aExp)
|
||||
{
|
||||
aTask.infoAppendln("Failed to generate the delta.cfg file.");
|
||||
aTask.infoAppendln(ThreadUtil.getStackTrace(aExp));
|
||||
return false;
|
||||
}
|
||||
|
||||
// We are done if there was no updated JRE
|
||||
if (targJre == null)
|
||||
return true;
|
||||
|
||||
// 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 jreTargPath = PlatformUtils.getJreLocation(targJre);
|
||||
jreTargPath.getParentFile().setWritable(true);
|
||||
if (jreDropPath.renameTo(jreTargPath) == false)
|
||||
{
|
||||
aTask.infoAppendln("Failed to move the updated JRE to its target location!");
|
||||
aTask.infoAppendln("\t Current path: " + jreDropPath);
|
||||
aTask.infoAppendln("\tOfficial path: " + jreTargPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Backup the application configuration
|
||||
try
|
||||
{
|
||||
Files.copy(appCfgFile.toPath(), new File(destPath, appCfgFile.getName() + ".old").toPath(), StandardCopyOption.COPY_ATTRIBUTES);
|
||||
}
|
||||
catch(IOException aExp)
|
||||
{
|
||||
aTask.infoAppendln("Failed to backup application configuration file: " + deltaCmdFile);
|
||||
aTask.infoAppendln(ThreadUtil.getStackTrace(aExp));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the application configuration to reflect the proper JRE
|
||||
try
|
||||
{
|
||||
PlatformUtils.setJreVersion(targJre.getVersion());
|
||||
}
|
||||
catch(ErrorDM aExp)
|
||||
{
|
||||
aTask.infoAppendln("Failed to update the configuration to point to the updated JRE!");
|
||||
aTask.infoAppendln("\tCurrent JRE: " + currJreVer.getLabel());
|
||||
aTask.infoAppendln("\t Chosen JRE: " + targJre.getVersion().getLabel());
|
||||
printErrorDM(aTask, aExp, 1);
|
||||
|
||||
// Remove the just installed JRE
|
||||
IoUtil.deleteDirectory(jreTargPath);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to download a compatible JreRelease for the AppCatalog to the specified destPath.
|
||||
* <P>
|
||||
* On success the JreVersion that was downloaded is returned.
|
||||
*/
|
||||
private JreRelease downloadJreUpdate(Task aTask, AppCatalog aUpdateCat, File aDestPath, long releaseSizeFull)
|
||||
{
|
||||
List<JreRelease> jreList;
|
||||
|
||||
// Ensure our JRE version is compatible for this release
|
||||
JreVersion currJreVer = DistUtils.getJreVersion();
|
||||
|
||||
// Let the user know why their version is not compatible
|
||||
String updnStr = "downgraded";
|
||||
if (aUpdateCat.isJreVersionTooOld(currJreVer) == true)
|
||||
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());
|
||||
JreVersion tmpJreVer = aUpdateCat.getMaxJreVersion();
|
||||
if (tmpJreVer != null)
|
||||
aTask.infoAppendln("\tMaximun JRE: " + tmpJreVer.getLabel());
|
||||
aTask.infoAppendln("");
|
||||
|
||||
// Bail if we are running a bundled JRE
|
||||
if (DistUtils.isJreBundled() == false)
|
||||
{
|
||||
aTask.infoAppend("This is the non bundled JRE version of the application. You are running the system JRE. ");
|
||||
aTask.infoAppendln("Please update the JRE (or path) to reflect a compatible JRE version.\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get list of all available JREs
|
||||
jreList = JreUtils.getAvailableJreReleases(aTask, updateSiteUrl, refCredential);
|
||||
if (jreList == null)
|
||||
{
|
||||
aTask.infoAppendln("The update site has not had any JREs deployed.");
|
||||
aTask.infoAppendln("Please contact the update site adminstartor.");
|
||||
return null;
|
||||
}
|
||||
if (jreList.size() == 0)
|
||||
{
|
||||
aTask.infoAppendln("No JRE releases found!");
|
||||
aTask.infoAppendln("Please contact the update site adminstartor.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Retrieve the latest appropriate JreRelease
|
||||
String platform = PlatformUtils.getPlatform();
|
||||
jreList = JreUtils.getMatchingPlatforms(jreList, platform);
|
||||
if (jreList.size() == 0)
|
||||
{
|
||||
aTask.infoAppendln("There are no JRE releases available for the platform: " + platform + "!");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Retrieve the JRE that is compatible from the list
|
||||
JreRelease pickJre = aUpdateCat.getCompatibleJre(jreList);
|
||||
if (pickJre == null)
|
||||
{
|
||||
aTask.infoAppendln("There are no compatible JREs found on the deploy site. Available JREs: " + jreList.size());
|
||||
for (JreRelease aJreRelease : jreList)
|
||||
aTask.infoAppendln("\t" + aJreRelease.getFileName() + " ---> (JRE: " + aJreRelease.getVersion().getLabel() + ")");
|
||||
aTask.infoAppendln("\nPlease contact the update site adminstartor.");
|
||||
return null;
|
||||
}
|
||||
JreVersion pickJreVer = pickJre.getVersion();
|
||||
|
||||
// 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;
|
||||
|
||||
// Download the JRE
|
||||
Digest targDigest, testDigest;
|
||||
targDigest = pickJre.getDigest();
|
||||
MessageDigest msgDigest;
|
||||
msgDigest = DigestUtils.getDigest(targDigest.getType());
|
||||
aTask.infoAppendln("Downloading JRE... Version: " + pickJreVer.getLabel());
|
||||
URL srcUrl = IoUtil.createURL(updateSiteUrl.toString() + "/jre/" + pickJreVer.getLabel() + "/" + pickJre.getFileName());
|
||||
File dstFile = new File(aDestPath, pickJre.getFileName());
|
||||
Task tmpTask = new PartialTask(aTask, aTask.getProgress(), (tmpFileLen * 0.75) / (releaseSizeFull + 0.00));
|
||||
if (DistUtils.downloadFile(tmpTask, srcUrl, dstFile, refCredential, tmpFileLen, msgDigest) == false)
|
||||
return null;
|
||||
|
||||
// Validate that the JRE was downloaded successfully
|
||||
testDigest = new Digest(targDigest.getType(), msgDigest.digest());
|
||||
if (targDigest.equals(testDigest) == false)
|
||||
{
|
||||
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");
|
||||
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());
|
||||
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.
|
||||
tmpTask = new PartialTask(aTask, aTask.getProgress(), (tmpFileLen * 0.25) / (releaseSizeFull + 0.00));
|
||||
MiscUtils.unTar(tmpTask, dstFile, unpackPath);
|
||||
File[] fileArr = unpackPath.listFiles();
|
||||
if (fileArr.length != 1 && fileArr[0].isDirectory() == false)
|
||||
throw new Exception("Expected only one (top level) folder to be unpacked. Items extracted: " + fileArr.length + " Path: " + unpackPath);
|
||||
jreRootPath = fileArr[0];
|
||||
|
||||
// Moved the unpacked JRE to aDestPath/jre/ folder and remove the working unpack folder and the tar.gz file
|
||||
jreRootPath.renameTo(jreTargPath);
|
||||
unpackPath.delete();
|
||||
dstFile.delete();
|
||||
}
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aTask.infoAppendln("Failed to properly untar archive. The update has been aborted.");
|
||||
aTask.infoAppendln("\tTar File: " + dstFile);
|
||||
aTask.infoAppendln("\tDestination: " + jreTargPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
return pickJre;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -652,6 +805,39 @@ public class DistMakerEngine
|
||||
displayNotice(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private void printErrorDM(Task aTask, ErrorDM aErrorDM, int numTabs)
|
||||
{
|
||||
Throwable cause;
|
||||
String tabStr;
|
||||
|
||||
tabStr = Strings.repeat("\t", numTabs);
|
||||
|
||||
aTask.infoAppendln(tabStr + "Reason: " + aErrorDM.getMessage());
|
||||
cause = aErrorDM.getCause();
|
||||
while (cause != null)
|
||||
{
|
||||
if (cause instanceof ErrorDM)
|
||||
{
|
||||
aTask.infoAppendln(tabStr + "Reason: " + cause.getMessage());
|
||||
}
|
||||
else
|
||||
{
|
||||
aTask.infoAppendln(tabStr + "StackTrace: ");
|
||||
aTask.infoAppendln(ThreadUtil.getStackTrace(cause));
|
||||
break;
|
||||
}
|
||||
|
||||
cause = aErrorDM.getCause();
|
||||
}
|
||||
|
||||
aTask.infoAppendln("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that prompts the user for forms of input depending on the state of the App
|
||||
* <P>
|
||||
@@ -675,11 +861,8 @@ public class DistMakerEngine
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the retrieved update, and restore the platform configuration files to this (running) release
|
||||
// It is necessary to do this, since the user may later cancel the update request and it is important to
|
||||
// leave the program and configuration files in a stable state.
|
||||
IoUtil.deleteDirectory(deltaPath);
|
||||
updatePlatformConfigFiles(aTask, currRelease);
|
||||
// Revert the update
|
||||
revertUpdate(aTask);
|
||||
}
|
||||
|
||||
// Query the user of the version to update to
|
||||
@@ -695,37 +878,126 @@ public class DistMakerEngine
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to update platform specific configuration files
|
||||
* 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.
|
||||
*/
|
||||
private boolean updatePlatformConfigFiles(Task aTask, AppRelease aRelease)
|
||||
private void revertUpdate(Task aTask)
|
||||
{
|
||||
File installPath, pFile;
|
||||
String errMsg;
|
||||
|
||||
// Get the top level install path
|
||||
installPath = DistUtils.getAppPath().getParentFile();
|
||||
|
||||
// Apple specific platform files
|
||||
pFile = new File(installPath, "Info.plist");
|
||||
if (pFile.isFile() == false)
|
||||
pFile = new File(installPath.getParentFile(), "Info.plist");
|
||||
|
||||
if (pFile.isFile() == true)
|
||||
// Revert our application's configuration (which will be loaded when it is restarted) to reflect the proper JRE
|
||||
try
|
||||
{
|
||||
errMsg = null;
|
||||
if (pFile.setWritable(true) == false)
|
||||
errMsg = "Failure. No writable permmisions for file: " + pFile;
|
||||
else
|
||||
errMsg = AppleUtils.updateVersion(pFile, aRelease.getVersion());
|
||||
|
||||
if (errMsg != null)
|
||||
{
|
||||
aTask.infoAppendln(errMsg);
|
||||
return false;
|
||||
}
|
||||
JreVersion currJreVer = DistUtils.getJreVersion();
|
||||
PlatformUtils.setJreVersion(currJreVer);
|
||||
}
|
||||
catch(ErrorDM aExp)
|
||||
{
|
||||
aTask.infoAppendln("Failed to revert application's JRE!");
|
||||
aTask.infoAppendln("\tApplication may be in an unstable state.");
|
||||
printErrorDM(aTask, aExp, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
// Revert any platform specific config files
|
||||
try
|
||||
{
|
||||
PlatformUtils.updateAppRelease(currRelease);
|
||||
}
|
||||
catch(ErrorDM aExp)
|
||||
{
|
||||
aTask.infoAppendln("Failed to revert application configuration!");
|
||||
aTask.infoAppendln("\tApplication may be in an unstable state.");
|
||||
printErrorDM(aTask, aExp, 1);
|
||||
}
|
||||
|
||||
// Determine the path to the delta (update) folder
|
||||
File rootPath = DistUtils.getAppPath().getParentFile();
|
||||
File deltaPath = new File(rootPath, "delta");
|
||||
|
||||
// It is necessary to do this, since the user may later cancel the update request and it is important to
|
||||
// leave the program and configuration files in a stable state.
|
||||
|
||||
// Execute any trash commands from the "fail" section of the delta.cmd file
|
||||
File deltaCmdFile = new File(deltaPath, "delta.cmd");
|
||||
try (BufferedReader br = MiscUtils.openFileAsBufferedReader(deltaCmdFile))
|
||||
{
|
||||
String currSect = null;
|
||||
while (true)
|
||||
{
|
||||
String inputStr = br.readLine();
|
||||
|
||||
// Delta command files should always have a proper exit (or reboot) and thus never arrive here
|
||||
if (inputStr == null)
|
||||
throw new ErrorDM("Command file (" + deltaCmdFile + ") is incomplete.");
|
||||
|
||||
// Ignore empty lines and comments
|
||||
if (inputStr.isEmpty() == true || inputStr.startsWith("#") == true)
|
||||
continue;
|
||||
|
||||
// Tokenize the input and retrieve the command
|
||||
String[] strArr = inputStr.split(",");
|
||||
String cmdStr = strArr[0];
|
||||
|
||||
// Skip to next line when we read a new section
|
||||
if (strArr.length == 2 && cmdStr.equals("sect") == true)
|
||||
{
|
||||
currSect = strArr[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip to the next line if we are not in the "fail" section
|
||||
if (currSect != null && currSect.equals("fail") == false)
|
||||
continue;
|
||||
else if (currSect == null)
|
||||
throw new ErrorDM("Command specified outside of section. Command: " + inputStr);
|
||||
|
||||
// Exit if we reach the exit or reboot command
|
||||
if (strArr.length == 1 && cmdStr.equals("exit") == true)
|
||||
break;
|
||||
else if (strArr.length == 1 && cmdStr.equals("reboot") == true)
|
||||
break;
|
||||
|
||||
// Execute the individual (trash) commands
|
||||
if (strArr.length == 2 && cmdStr.equals("trash") == true)
|
||||
{
|
||||
// Resolve the argument to the corresponding file and ensure it is relative to our rootPath
|
||||
File tmpFile = new File(rootPath, strArr[1]).getCanonicalFile();
|
||||
if (MiscUtils.getRelativePath(rootPath, tmpFile) == null)
|
||||
throw new ErrorDM("File (" + tmpFile + ") is not relative to folder: " + rootPath);
|
||||
|
||||
if (tmpFile.isFile() == true)
|
||||
{
|
||||
if (tmpFile.delete() == false)
|
||||
throw new ErrorDM("Failed to delete file: " + tmpFile);
|
||||
}
|
||||
else if (tmpFile.isDirectory() == true)
|
||||
{
|
||||
if (IoUtil.deleteDirectory(tmpFile) == false)
|
||||
throw new ErrorDM("Failed to delete folder: " + tmpFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ErrorDM("File type is not recognized: " + tmpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(IOException aExp)
|
||||
{
|
||||
aTask.infoAppendln("Failed to revert application configuration!");
|
||||
aTask.infoAppendln("\tApplication may be in an unstable state.");
|
||||
aTask.infoAppendln(ThreadUtil.getStackTrace(aExp));
|
||||
}
|
||||
|
||||
// Remove the entire delta folder
|
||||
if (IoUtil.deleteDirectory(deltaPath) == false)
|
||||
throw new ErrorDM("Failed to delete folder: " + deltaPath);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import glum.util.ThreadUtil;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
@@ -75,24 +77,6 @@ public class DistUtils
|
||||
return new JreVersion(jreVer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the platform (Apple, Linux, or Windows) on which the current JRE is running on.
|
||||
*/
|
||||
public static String getPlatform()
|
||||
{
|
||||
String osName;
|
||||
|
||||
osName = System.getProperty("os.name").toUpperCase();
|
||||
if (osName.startsWith("LINUX") == true)
|
||||
return "Linux";
|
||||
if (osName.startsWith("MAC OS X") == true)
|
||||
return "Apple";
|
||||
if (osName.startsWith("WINDOWS") == true)
|
||||
return "Windows";
|
||||
|
||||
return System.getProperty("os.name");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code associated with the update.
|
||||
*/
|
||||
@@ -117,6 +101,26 @@ public class DistUtils
|
||||
return isDevelopersEnvironment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to determine if the JRE is embedded with this application.
|
||||
*/
|
||||
public static boolean isJreBundled()
|
||||
{
|
||||
Path rootPath, jrePath;
|
||||
|
||||
// Get the top level folder of our installation
|
||||
rootPath = getAppPath().toPath().getParent();
|
||||
|
||||
// Get the path to the JRE
|
||||
jrePath = Paths.get(System.getProperty("java.home"));
|
||||
|
||||
// Determine if the java.home JRE is a subdirectory of the top level app folder
|
||||
if (jrePath.startsWith(rootPath) == true)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the specified file from srcUrl to destFile. Returns true on success
|
||||
* <P>
|
||||
@@ -383,28 +387,23 @@ public class DistUtils
|
||||
public static AppCatalog readAppCatalog(Task aTask, File aCatalogFile, URL aUpdateUrl)
|
||||
{
|
||||
List<Node> nodeList;
|
||||
JreVersion jreVersion;
|
||||
InputStream inStream;
|
||||
BufferedReader bufReader;
|
||||
JreVersion minJreVersion, maxJreVersion;
|
||||
DigestType digestType;
|
||||
String errMsg, strLine;
|
||||
|
||||
errMsg = null;
|
||||
nodeList = new ArrayList<>();
|
||||
jreVersion = null;
|
||||
minJreVersion = null;
|
||||
maxJreVersion = null;
|
||||
|
||||
// Default to DigestType of MD5
|
||||
digestType = DigestType.MD5;
|
||||
|
||||
inStream = null;
|
||||
bufReader = null;
|
||||
try
|
||||
try (BufferedReader bufReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(new FileInputStream(aCatalogFile))));)
|
||||
{
|
||||
String[] tokens;
|
||||
|
||||
// Read the contents of the file
|
||||
inStream = new FileInputStream(aCatalogFile);
|
||||
bufReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(inStream)));
|
||||
while (true)
|
||||
{
|
||||
strLine = bufReader.readLine();
|
||||
@@ -447,16 +446,18 @@ public class DistUtils
|
||||
else
|
||||
digestType = tmpDigestType;
|
||||
}
|
||||
else if (tokens.length == 2 && tokens[0].equals("jre") == true)
|
||||
else if ((tokens.length == 2 || tokens.length == 3) && tokens[0].equals("jre") == true)
|
||||
{
|
||||
if (jreVersion != null)
|
||||
if (minJreVersion != null)
|
||||
{
|
||||
aTask.infoAppendln("JRE version has already been specified. Current ver: " + jreVersion.getLabel() + " Requested ver: " + tokens[1]
|
||||
aTask.infoAppendln("JRE version has already been specified. Current ver: " + minJreVersion.getLabel() + " Requested ver: " + tokens[1]
|
||||
+ ". Skipping...");
|
||||
continue;
|
||||
}
|
||||
|
||||
jreVersion = new JreVersion(tokens[1]);
|
||||
minJreVersion = new JreVersion(tokens[1]);
|
||||
if (tokens.length == 3)
|
||||
maxJreVersion = new JreVersion(tokens[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -468,11 +469,6 @@ public class DistUtils
|
||||
{
|
||||
errMsg = ThreadUtil.getStackTrace(aExp);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IoUtil.forceClose(inStream);
|
||||
IoUtil.forceClose(bufReader);
|
||||
}
|
||||
|
||||
// See if we are in a valid state
|
||||
if (errMsg != null)
|
||||
@@ -487,7 +483,7 @@ public class DistUtils
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AppCatalog(jreVersion, nodeList);
|
||||
return new AppCatalog(nodeList, minJreVersion, maxJreVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
37
src/distMaker/ErrorDM.java
Normal file
37
src/distMaker/ErrorDM.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package distMaker;
|
||||
|
||||
/**
|
||||
* Generic runtime exception thrown by various DistMaker modules/routines.
|
||||
*/
|
||||
public class ErrorDM extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// State vars
|
||||
private String subject;
|
||||
|
||||
public ErrorDM(Throwable aCause, String aMessage, String aSubject)
|
||||
{
|
||||
super(aMessage, aCause);
|
||||
subject = aSubject;
|
||||
}
|
||||
|
||||
public ErrorDM(Throwable aCause, String aMessage)
|
||||
{
|
||||
this(aCause, aMessage, null);
|
||||
}
|
||||
|
||||
public ErrorDM(String aMessage)
|
||||
{
|
||||
this(null, aMessage, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subject specific to this error. May be null if this is just a generic error.
|
||||
*/
|
||||
public String getSubject()
|
||||
{
|
||||
return subject;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +1,54 @@
|
||||
package distMaker;
|
||||
|
||||
import glum.task.Task;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.nio.file.attribute.PosixFilePermissions;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.apache.commons.compress.archivers.ArchiveException;
|
||||
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||
import org.apache.commons.compress.utils.IOUtils;
|
||||
|
||||
import com.google.common.io.CountingInputStream;
|
||||
|
||||
/**
|
||||
* Collection of generic utility methods that should be migrated to another library.
|
||||
* Collection of generic utility methods that should be migrated to another library / class.
|
||||
*/
|
||||
public class MiscUtils
|
||||
{
|
||||
public static void unTar(final File inputFile, final File aDestPath) throws Exception
|
||||
{
|
||||
throw new Exception("Incomplete...");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to convert a Unix base-10 mode into the equivalent string.
|
||||
* Utility method to convert a Unix base-10 mode into the equivalent string.
|
||||
* <P>
|
||||
* Example: 493 -> 'rwxr-xr-x'
|
||||
* <P>
|
||||
* The returned string will always be of length 9
|
||||
* The returned string will always be of length 9
|
||||
*/
|
||||
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--)
|
||||
{
|
||||
if (((aMode >> c1) & 0x01) != 1)
|
||||
permArr[8 - c1] = '-';
|
||||
}
|
||||
|
||||
|
||||
return new String(permArr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to convert a Unix base-10 mode into the Set<PosixFilePermission>.
|
||||
* Utility method to convert a Unix base-10 mode into the Set<PosixFilePermission>.
|
||||
* <P>
|
||||
* Example: 493 -> 'rwxr-xr-x'
|
||||
* <P>
|
||||
* The returned string will always be of length 9
|
||||
* The returned string will always be of length 9
|
||||
*/
|
||||
public static Set<PosixFilePermission> convertUnixModeToPFP(int aMode)
|
||||
{
|
||||
@@ -49,9 +56,143 @@ public class MiscUtils
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to output the specified strings to aFile
|
||||
* Returns the relative path component of aAbsolutePath relative to aBasePath.
|
||||
* <P>
|
||||
* Returns null if aAbsolutePath does not start with aBasePath.
|
||||
*/
|
||||
public static boolean writeDoc(File aFile, List<String> strList)
|
||||
public static String getRelativePath(File aBasePath, File aAbsolutePath)
|
||||
{
|
||||
Path relPath;
|
||||
|
||||
// Bail if aAbsolutePath does not start with aBasePath
|
||||
if (aAbsolutePath.toPath().startsWith(aBasePath.toPath()) == false)
|
||||
return null;
|
||||
|
||||
relPath = aBasePath.toPath().relativize(aAbsolutePath.toPath());
|
||||
return relPath.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns a BufferedReader corresponding to the specified file.
|
||||
* <P>
|
||||
* This helps reduce boiler plate code.
|
||||
*/
|
||||
public static BufferedReader openFileAsBufferedReader(File aFile) throws IOException
|
||||
{
|
||||
return new BufferedReader(new InputStreamReader(new FileInputStream(aFile)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Untar an input file into an output file.
|
||||
* <P>
|
||||
* 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.
|
||||
*
|
||||
* @param inputFile
|
||||
* the input .tar file
|
||||
* @param aDestPath
|
||||
* 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
|
||||
*/
|
||||
public static List<File> unTar(Task aTask, final File inputFile, final File aDestPath) throws FileNotFoundException, IOException, ArchiveException
|
||||
{
|
||||
Map<File, Long> pathMap;
|
||||
InputStream iStream;
|
||||
|
||||
final List<File> untaredFiles = new ArrayList<>();
|
||||
long fullLen = inputFile.length();
|
||||
|
||||
// Open up the stream to the tar file (set up a counting stream to allow for progress updates)
|
||||
CountingInputStream cntStream = new CountingInputStream(new FileInputStream(inputFile));
|
||||
iStream = cntStream;
|
||||
if (inputFile.getName().toUpperCase().endsWith(".GZ") == true)
|
||||
iStream = new GZIPInputStream(iStream);
|
||||
|
||||
pathMap = new LinkedHashMap<>();
|
||||
final TarArchiveInputStream debInputStream = (TarArchiveInputStream)new ArchiveStreamFactory().createArchiveInputStream("tar", iStream);
|
||||
TarArchiveEntry entry = null;
|
||||
while ((entry = (TarArchiveEntry)debInputStream.getNextEntry()) != null)
|
||||
{
|
||||
final File outputFile = new File(aDestPath, entry.getName());
|
||||
if (entry.isDirectory())
|
||||
{
|
||||
if (!outputFile.exists())
|
||||
{
|
||||
if (!outputFile.mkdirs())
|
||||
{
|
||||
throw new IllegalStateException(String.format("Couldn't create directory %s.", outputFile.getAbsolutePath()));
|
||||
}
|
||||
}
|
||||
|
||||
long tmpUtc = entry.getModTime().getTime();
|
||||
outputFile.setLastModified(tmpUtc);
|
||||
pathMap.put(outputFile, tmpUtc);
|
||||
}
|
||||
else if (entry.isSymbolicLink() == true)
|
||||
{
|
||||
File tmpFile = new File(entry.getLinkName());
|
||||
Path outLink = Files.createSymbolicLink(outputFile.toPath(), tmpFile.toPath());
|
||||
|
||||
long tmpUtc = entry.getModTime().getTime();
|
||||
outputFile.setLastModified(tmpUtc);
|
||||
}
|
||||
else if (entry.isFile() == true)
|
||||
{
|
||||
final OutputStream outputFileStream = new FileOutputStream(outputFile);
|
||||
IOUtils.copy(debInputStream, outputFileStream);
|
||||
outputFileStream.close();
|
||||
|
||||
// Update the modified time of the file
|
||||
long tmpUtc = entry.getModTime().getTime();
|
||||
outputFile.setLastModified(tmpUtc);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println(String.format("Unrecognized entry: %s", entry.getName()));
|
||||
}
|
||||
|
||||
// Update the mode on all (non symbolic) files / paths
|
||||
int mode = entry.getMode();
|
||||
if (entry.isSymbolicLink() == false)
|
||||
{
|
||||
String permStr;
|
||||
|
||||
permStr = convertUnixModeToStr(mode);
|
||||
Files.setPosixFilePermissions(outputFile.toPath(), PosixFilePermissions.fromString(permStr));
|
||||
// System.out.println(String.format("\tMode: %d %x %s %s name: %s", mode, mode, Integer.toOctalString(mode), permStr, entry.getName()));
|
||||
}
|
||||
|
||||
untaredFiles.add(outputFile);
|
||||
|
||||
// Update the progress bar
|
||||
aTask.infoUpdate("\tUnpacked: " + entry.getName());
|
||||
long currLen = cntStream.getCount();
|
||||
aTask.setProgress(currLen / (fullLen + 0.0));
|
||||
}
|
||||
debInputStream.close();
|
||||
|
||||
// Update all of the times on the folders last
|
||||
for (File aDir : pathMap.keySet())
|
||||
aDir.setLastModified(pathMap.get(aDir));
|
||||
|
||||
aTask.infoAppendln("\tUnpacked: " + untaredFiles.size() + " files\n");
|
||||
|
||||
return untaredFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to output the specified strings to aFile
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void writeDoc(File aFile, List<String> strList)
|
||||
{
|
||||
// Output the strList
|
||||
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(aFile)));)
|
||||
@@ -60,13 +201,10 @@ public class MiscUtils
|
||||
for (String aStr : strList)
|
||||
bw.write(aStr + '\n');
|
||||
}
|
||||
catch(Exception aExp)
|
||||
catch(IOException aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return false;
|
||||
throw new ErrorDM(aExp, "Failed to write the file: " + aFile);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import glum.gui.component.GSlider;
|
||||
import glum.gui.panel.GlassPanel;
|
||||
import glum.gui.panel.generic.MessagePanel;
|
||||
import glum.unit.ByteUnit;
|
||||
import glum.util.ThreadUtil;
|
||||
import glum.zio.raw.ZioRaw;
|
||||
|
||||
import java.awt.*;
|
||||
@@ -22,6 +23,7 @@ import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import distMaker.ErrorDM;
|
||||
import distMaker.platform.MemUtils;
|
||||
import distMaker.platform.PlatformUtils;
|
||||
import static distMaker.platform.MemUtils.KB_SIZE;
|
||||
@@ -123,9 +125,26 @@ public class MemoryConfigPanel extends GlassPanel implements ActionListener, Zio
|
||||
targMemSize = (long)targMemS.getModelValue();
|
||||
targMemSize = roundToMB(targMemSize);
|
||||
|
||||
// Bail if we are not able to set the DistMaker max heap memory
|
||||
if (PlatformUtils.setMaxHeapMem(warnPanel, targMemSize) == false)
|
||||
return;
|
||||
try
|
||||
{
|
||||
// Delegate the updating of the memory
|
||||
PlatformUtils.setMaxHeapMem(targMemSize);
|
||||
}
|
||||
catch(ErrorDM aExp)
|
||||
{
|
||||
String subjectStr = aExp.getSubject();
|
||||
if (subjectStr == null)
|
||||
subjectStr = "Application Configuration Error";
|
||||
|
||||
String messageStr = aExp.getMessage();
|
||||
if (aExp.getCause() != null)
|
||||
messageStr += "\n\n" + ThreadUtil.getStackTrace(aExp.getCause());
|
||||
|
||||
// Show the user the details of the failure
|
||||
warnPanel.setTitle(subjectStr);
|
||||
warnPanel.setInfo(messageStr);
|
||||
warnPanel.setVisible(true);
|
||||
}
|
||||
|
||||
// Update our state vars
|
||||
instMemSize = targMemSize;
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.*;
|
||||
|
||||
import distMaker.digest.Digest;
|
||||
import distMaker.digest.DigestType;
|
||||
import distMaker.platform.PlatformUtils;
|
||||
|
||||
public class JreUtils
|
||||
{
|
||||
@@ -29,6 +30,7 @@ public class JreUtils
|
||||
BufferedReader bufReader;
|
||||
DigestType digestType;
|
||||
String errMsg, strLine;
|
||||
String version;
|
||||
|
||||
errMsg = null;
|
||||
retList = new ArrayList<>();
|
||||
@@ -36,6 +38,7 @@ public class JreUtils
|
||||
|
||||
// Default to DigestType of MD5
|
||||
digestType = DigestType.MD5;
|
||||
version = null;
|
||||
|
||||
inStream = null;
|
||||
bufReader = null;
|
||||
@@ -62,6 +65,8 @@ public class JreUtils
|
||||
; // 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)
|
||||
; // Nothing to do - we just entered the "JRE" section
|
||||
else if (tokens.length == 2 && tokens[0].equals("digest") == true)
|
||||
{
|
||||
DigestType tmpDigestType;
|
||||
@@ -72,17 +77,35 @@ public class JreUtils
|
||||
else
|
||||
digestType = tmpDigestType;
|
||||
}
|
||||
else if (tokens.length == 6 && tokens[0].equals("jre") == true)
|
||||
else if (tokens.length == 2 && tokens[0].equals("jre") == true)
|
||||
{
|
||||
String platform, version, filename, digestStr;
|
||||
version = tokens[1];
|
||||
}
|
||||
else if (tokens.length == 4 && 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];
|
||||
platform = tokens[2];
|
||||
version = tokens[3];
|
||||
fileLen = GuiUtil.readLong(tokens[4], -1);
|
||||
filename = tokens[5];
|
||||
fileLen = GuiUtil.readLong(tokens[2], -1);
|
||||
filename = tokens[3];
|
||||
|
||||
platform = PlatformUtils.getPlatformOfJreTarGz(filename);
|
||||
if (platform == null)
|
||||
{
|
||||
aTask.infoAppendln("Skipping input: " + strLine);
|
||||
aTask.infoAppendln("\tFailed to determine the target platform of the JRE.");
|
||||
continue;
|
||||
}
|
||||
|
||||
retList.add(new JreRelease(platform, version, filename, new Digest(digestType, digestStr), fileLen));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -24,7 +24,7 @@ public class JreVersion implements Comparable<JreVersion>
|
||||
* <P>
|
||||
* The better version is defined as the later version (and the more specific version).
|
||||
* <P>
|
||||
* Returns null if the better version can not be determined
|
||||
* Returns null if the better version can not be determined or if the versions are equal.
|
||||
*/
|
||||
public static JreVersion getBetterVersion(JreVersion verA, JreVersion verB)
|
||||
{
|
||||
@@ -35,10 +35,12 @@ public class JreVersion implements Comparable<JreVersion>
|
||||
tokenA = verA.getLabel().split("[._]");
|
||||
tokenB = verB.getLabel().split("[._]");
|
||||
|
||||
// Default return JreVersion is verA or the version that is more specific
|
||||
defaultVer = verA;
|
||||
// Default JreVersion is the version that is more specific
|
||||
defaultVer = null;
|
||||
if (tokenA.length < tokenB.length)
|
||||
defaultVer = verB;
|
||||
else if (tokenB.length < tokenA.length)
|
||||
defaultVer = verA;
|
||||
|
||||
// Set the idxCnt to the less specific JreVersion
|
||||
idxCnt = tokenA.length;
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.util.*;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import distMaker.jre.JreVersion;
|
||||
import distMaker.jre.*;
|
||||
|
||||
/**
|
||||
* Object that describes the structure (files, folders, and JRE version) of a Java application.
|
||||
@@ -13,23 +13,98 @@ import distMaker.jre.JreVersion;
|
||||
public class AppCatalog
|
||||
{
|
||||
/** The minimum JRE version required. */
|
||||
private JreVersion jreVersion;
|
||||
private JreVersion minJreVer;
|
||||
|
||||
/** The maximum JRE version allowed. This will be null if there is no maximum. */
|
||||
private JreVersion maxJreVer;
|
||||
|
||||
/** A mapping of filename to to corresponding Node */
|
||||
private ImmutableMap<String, Node> nodeMap;
|
||||
|
||||
public AppCatalog(JreVersion aJreVersion, List<Node> aNodeList)
|
||||
public AppCatalog(List<Node> aNodeList, JreVersion aMinJreVer, JreVersion aMaxJreVer)
|
||||
{
|
||||
jreVersion = aJreVersion;
|
||||
minJreVer = aMinJreVer;
|
||||
maxJreVer = aMaxJreVer;
|
||||
nodeMap = ImmutableMap.copyOf(formNameMap(aNodeList));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum JreVersion required.
|
||||
* Returns the most recent JRE from the specified release that is compatible with this Appcatalog.
|
||||
* <P>
|
||||
* Returns null if there are no JREs that are compatible.
|
||||
*/
|
||||
public JreVersion getJreVersion()
|
||||
public JreRelease getCompatibleJre(List<JreRelease> aJreList)
|
||||
{
|
||||
return jreVersion;
|
||||
// Sort the platforms, but reverse the order so that the newest version is first
|
||||
Collections.sort(aJreList);
|
||||
Collections.reverse(aJreList);
|
||||
|
||||
for (JreRelease aRelease : aJreList)
|
||||
{
|
||||
if (isJreVersionTooNew(aRelease.getVersion()) == true)
|
||||
continue;
|
||||
|
||||
if (isJreVersionTooOld(aRelease.getVersion()) == true)
|
||||
continue;
|
||||
|
||||
return aRelease;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum JreVersion that is compatible.
|
||||
*/
|
||||
public JreVersion getMinJreVersion()
|
||||
{
|
||||
return minJreVer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum JreVersion that is compatible.
|
||||
*/
|
||||
public JreVersion getMaxJreVersion()
|
||||
{
|
||||
return maxJreVer;
|
||||
}
|
||||
|
||||
public boolean isJreVersionCompatible(JreVersion aJreVer)
|
||||
{
|
||||
// Check to make sure aJreVer is not too old
|
||||
if (isJreVersionTooOld(aJreVer) == true)
|
||||
return false;
|
||||
|
||||
// Check to make sure aJreVer is not too new
|
||||
if (isJreVersionTooNew(aJreVer) == true)
|
||||
return false;
|
||||
|
||||
// The version aJreVer must be compatible
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified version is not compatible (too new) with this AppCatalog.
|
||||
*/
|
||||
public boolean isJreVersionTooNew(JreVersion aJreVer)
|
||||
{
|
||||
// Check to make sure aJreVer is not too old
|
||||
if (maxJreVer != null && JreVersion.getBetterVersion(maxJreVer, aJreVer) == aJreVer)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified version is not compatible (too old) with this AppCatalog.
|
||||
*/
|
||||
public boolean isJreVersionTooOld(JreVersion aJreVer)
|
||||
{
|
||||
// Check to make sure aJreVer is not too old
|
||||
if (minJreVer != null && JreVersion.getBetterVersion(minJreVer, aJreVer) == minJreVer)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,7 +129,7 @@ public class AppCatalog
|
||||
* TODO: This should be renamed formNameMap to formDigestMap<BR>
|
||||
* TODO: This should probably be a mapping of Digest to Node rather than filename to Node
|
||||
*/
|
||||
public Map<String, Node> formNameMap(List<Node> aNodeList)
|
||||
private Map<String, Node> formNameMap(List<Node> aNodeList)
|
||||
{
|
||||
Map<String, Node> retMap;
|
||||
|
||||
|
||||
@@ -71,9 +71,9 @@ public class AppRelease implements Comparable<AppRelease>, QueryItem<LookUp>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(@SuppressWarnings("unused") LookUp aEnum, @SuppressWarnings("unused") Object aObj)
|
||||
public void setValue(LookUp aEnum, Object aObj)
|
||||
{
|
||||
throw new RuntimeException("Unsupported operation");
|
||||
throw new RuntimeException("Unsupported operation setValue(aEnum: " + aEnum + " aObj: " + aObj + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package distMaker.platform;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
@@ -11,30 +12,22 @@ import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.w3c.dom.*;
|
||||
|
||||
import distMaker.DistUtils;
|
||||
import distMaker.*;
|
||||
import distMaker.jre.JreVersion;
|
||||
|
||||
/**
|
||||
* Utility class which contains a set of methods to interact with an Apple Info.plist file.
|
||||
*/
|
||||
public class AppleUtils
|
||||
{
|
||||
/**
|
||||
* Utility method to update the JRE to reflect the specified path.
|
||||
* <P>
|
||||
* TODO: Complete this comment and method.
|
||||
*/
|
||||
public static boolean updateJrePath(File aPath)
|
||||
{
|
||||
int zios_finish;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plist file used to configure apple applications.
|
||||
* <P>
|
||||
* Two locations will be searched.... TODO: Add more details of those locations.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
private static File getPlistFile()
|
||||
public static File getPlistFile()
|
||||
{
|
||||
File installPath;
|
||||
File pFile;
|
||||
@@ -42,58 +35,54 @@ public class AppleUtils
|
||||
// Get the top level install path
|
||||
installPath = DistUtils.getAppPath().getParentFile();
|
||||
|
||||
// Attempt to locate the pList file
|
||||
// Attempt to locate the pList file (from one of the possible locations)
|
||||
pFile = new File(installPath, "Info.plist");
|
||||
if (pFile.isFile() == false)
|
||||
pFile = new File(installPath.getParentFile(), "Info.plist");
|
||||
|
||||
// Bail if we failed to locate the plist file
|
||||
if (pFile.exists() == false)
|
||||
throw new ErrorDM("The plist file could not be located.");
|
||||
|
||||
// Bail if the plist file is not a regular file.
|
||||
if (pFile.isFile() == false)
|
||||
pFile = null;
|
||||
throw new ErrorDM("The plist file does not appear to be a regular file: " + pFile);
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the specified max memory (-Xmx) value in the plist file (aFile) to the specified maxMemVal.
|
||||
* Utility method to update the specified version in the plist file (pFile) to the new version.
|
||||
* <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.
|
||||
*
|
||||
* @return Returns null on success or an error message describing the issue.
|
||||
* 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.
|
||||
*/
|
||||
public static String updateMaxMem(long numBytes)
|
||||
public static void updateAppVersion(String aNewVersion)
|
||||
{
|
||||
// Utilize the system pList file and delegate.
|
||||
return updateMaxMem(numBytes, getPlistFile());
|
||||
updateAppVersion(aNewVersion, getPlistFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the specified max memory (-Xmx) value in the plist file (aFile) to the specified maxMemVal.
|
||||
* Utility method to update the specified version in the plist file (pFile) to the new version.
|
||||
* <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.
|
||||
*
|
||||
* @return Returns null on success or an error message describing the issue.
|
||||
* 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.
|
||||
*/
|
||||
public static String updateMaxMem(long numBytes, File pFile)
|
||||
public static void updateAppVersion(String aNewVersin, File pFile)
|
||||
{
|
||||
Document doc;
|
||||
Element docElement;
|
||||
String evalStr, updateStr;
|
||||
NodeList dictList, childList;
|
||||
Node childNode, targNode;
|
||||
Element evalE, arrE, memE;
|
||||
String tagStr, valStr, currKeyVal;
|
||||
int zios_Clean;
|
||||
NodeList nodeList;
|
||||
Node keyNode, strNode;
|
||||
|
||||
// Bail if we failed to locate the pList file.
|
||||
if (pFile == null)
|
||||
return "The plist file could not be located.";
|
||||
// Bail if the plist file is not a regular file.
|
||||
if (pFile.isFile() == false)
|
||||
return "The plist file does not appear to be a regular file: " + pFile;
|
||||
// Bail if the plist file is not writeable.
|
||||
// Bail if the pFile is not writable.
|
||||
if (pFile.setWritable(true) == false)
|
||||
return "The plist file is not writeable: " + pFile;
|
||||
throw new ErrorDM("The plist file is not writeable: " + pFile);
|
||||
|
||||
// Load the XML document via the javax.xml.parsers.* package
|
||||
try
|
||||
@@ -103,14 +92,148 @@ public class AppleUtils
|
||||
}
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return "Failed to parse XML document. File: " + pFile;
|
||||
throw new ErrorDM(aExp, "Failed to parse XML document. File: " + pFile);
|
||||
}
|
||||
|
||||
nodeList = docElement.getElementsByTagName("*");
|
||||
for (int c1 = 0; c1 < nodeList.getLength(); c1++)
|
||||
{
|
||||
keyNode = nodeList.item(c1).getFirstChild();
|
||||
if (keyNode != null && keyNode.getNodeValue().equals("CFBundleVersion") == true)
|
||||
{
|
||||
System.out.println("Updating contents of file: " + pFile);
|
||||
|
||||
strNode = nodeList.item(c1 + 1).getFirstChild();
|
||||
System.out.println(" Old Version: " + strNode.getNodeValue());
|
||||
|
||||
strNode.setNodeValue(aNewVersin);
|
||||
System.out.println(" New Version: " + strNode.getNodeValue());
|
||||
}
|
||||
}
|
||||
|
||||
// Update the file with the changed document
|
||||
saveDoc(pFile, doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the JRE to point to the specified path in the system plist file.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void updateJreVersion(JreVersion aJreVersion)
|
||||
{
|
||||
// Utilize the system pList file and delegate.
|
||||
updateJreVersion(aJreVersion, getPlistFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the JRE to point to the specified path in the plist file (pFile).
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void updateJreVersion(JreVersion aJreVersion, File pFile)
|
||||
{
|
||||
List<String> inputList;
|
||||
String evalStr, tmpStr;
|
||||
int currLineNum, targLineNum;
|
||||
|
||||
// Bail if the pFile is not writable
|
||||
if (pFile.setWritable(true) == false)
|
||||
throw new ErrorDM("The pFile is not writeable: " + pFile);
|
||||
|
||||
// Process our input
|
||||
inputList = new ArrayList<>();
|
||||
try (BufferedReader br = MiscUtils.openFileAsBufferedReader(pFile))
|
||||
{
|
||||
// Read the lines
|
||||
currLineNum = 0;
|
||||
targLineNum = -1;
|
||||
while (true)
|
||||
{
|
||||
evalStr = br.readLine();
|
||||
if (evalStr == null)
|
||||
break;
|
||||
|
||||
// Record the start of the JVMRunitme section. Note the JRE should be specified on the next line
|
||||
tmpStr = evalStr.trim();
|
||||
if (tmpStr.equals("<key>JVMRuntime</key>") == true)
|
||||
targLineNum = currLineNum + 1;
|
||||
|
||||
inputList.add(evalStr);
|
||||
currLineNum++;
|
||||
}
|
||||
}
|
||||
catch(IOException aExp)
|
||||
{
|
||||
throw new ErrorDM(aExp, "Failed while processing the pFile: " + pFile);
|
||||
}
|
||||
|
||||
// Update the pFile
|
||||
String regex = "<string>(.*?)</string>";
|
||||
String repStr = "<string>jre" + aJreVersion.getLabel() + "</string>";
|
||||
if (targLineNum == -1)
|
||||
throw new ErrorDM("[" + pFile + "] The pFile does not specify a 'JVMRuntime' section.");
|
||||
else if (targLineNum >= inputList.size())
|
||||
throw new ErrorDM("[" + pFile + "] The pFile appears to be incomplete!");
|
||||
else
|
||||
inputList.set(targLineNum, inputList.get(targLineNum).replaceFirst(regex, repStr));
|
||||
|
||||
// Write the pFile
|
||||
MiscUtils.writeDoc(pFile, inputList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void updateMaxMem(long numBytes)
|
||||
{
|
||||
// Utilize the system pList file and delegate.
|
||||
updateMaxMem(numBytes, getPlistFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void updateMaxMem(long numBytes, File pFile)
|
||||
{
|
||||
Document doc;
|
||||
Element docElement;
|
||||
String evalStr, updateStr;
|
||||
NodeList dictList, childList;
|
||||
Node childNode, targNode;
|
||||
Element evalE, arrE, memE;
|
||||
String tagStr, valStr, currKeyVal;
|
||||
int zzz_Clean_this;
|
||||
|
||||
// Bail if the pFile is not writable.
|
||||
if (pFile.setWritable(true) == false)
|
||||
throw new ErrorDM("The plist file is not writeable: " + pFile);
|
||||
|
||||
// Load the XML document via the javax.xml.parsers.* package
|
||||
try
|
||||
{
|
||||
doc = loadDoc(pFile);
|
||||
docElement = doc.getDocumentElement();
|
||||
}
|
||||
catch(Exception aExp)
|
||||
{
|
||||
throw new ErrorDM(aExp, "Failed to parse XML document. File: " + pFile);
|
||||
}
|
||||
|
||||
// Locate the <dict> element
|
||||
dictList = docElement.getElementsByTagName("dict");
|
||||
if (dictList.getLength() == 0)
|
||||
return "No <dict> element found! File: " + pFile;
|
||||
throw new ErrorDM("No <dict> element found! File: " + pFile);
|
||||
|
||||
arrE = null;
|
||||
currKeyVal = null;
|
||||
@@ -148,7 +271,7 @@ public class AppleUtils
|
||||
|
||||
// Bail if we failed to locate the array element
|
||||
if (arrE == null)
|
||||
return "Failed to locate the element <array> following the element: <key>JVMOptions</key>\nFile: " + pFile;
|
||||
throw new ErrorDM("Failed to locate the element <array> following the element: <key>JVMOptions</key>\nFile: " + pFile);
|
||||
|
||||
memE = null;
|
||||
childList = arrE.getChildNodes();
|
||||
@@ -192,57 +315,11 @@ public class AppleUtils
|
||||
evalStr = targNode.getNodeValue();
|
||||
updateStr = MemUtils.transformMaxMemHeapString(evalStr, numBytes);
|
||||
if (updateStr == null)
|
||||
return "Failed to transform the memory spec value. Original value: " + evalStr + "\nFile: " + pFile;
|
||||
throw new ErrorDM("Failed to transform the memory spec value. Original value: " + evalStr + "\nFile: " + pFile);
|
||||
targNode.setNodeValue(updateStr);
|
||||
|
||||
// Update the file with the changed document
|
||||
System.out.println("Updating contents of file: " + pFile);
|
||||
return saveDoc(pFile, doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the specified version in the plist file (aFile) 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.
|
||||
*/
|
||||
public static String updateVersion(File aFile, String aNewVersin)
|
||||
{
|
||||
Document doc;
|
||||
Element docElement;
|
||||
NodeList nodeList;
|
||||
Node keyNode, strNode;
|
||||
|
||||
// Load the XML document via the javax.xml.parsers.* package
|
||||
try
|
||||
{
|
||||
doc = loadDoc(aFile);
|
||||
docElement = doc.getDocumentElement();
|
||||
}
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return "Failed to parse XML document. File: " + aFile;
|
||||
}
|
||||
|
||||
nodeList = docElement.getElementsByTagName("*");
|
||||
for (int c1 = 0; c1 < nodeList.getLength(); c1++)
|
||||
{
|
||||
keyNode = nodeList.item(c1).getFirstChild();
|
||||
if (keyNode != null && keyNode.getNodeValue().equals("CFBundleVersion") == true)
|
||||
{
|
||||
System.out.println("Updating contents of file: " + aFile);
|
||||
|
||||
strNode = nodeList.item(c1 + 1).getFirstChild();
|
||||
System.out.println(" Old Version: " + strNode.getNodeValue());
|
||||
|
||||
strNode.setNodeValue(aNewVersin);
|
||||
System.out.println(" New Version: " + strNode.getNodeValue());
|
||||
}
|
||||
}
|
||||
|
||||
// Update the file with the changed document
|
||||
return saveDoc(aFile, doc);
|
||||
saveDoc(pFile, doc);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,8 +341,10 @@ public class AppleUtils
|
||||
|
||||
/**
|
||||
* Helper method to output aDoc to the specified file.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
private static String saveDoc(File aFile, Document aDoc)
|
||||
private static void saveDoc(File aFile, Document aDoc)
|
||||
{
|
||||
try (FileOutputStream oStream = new FileOutputStream(aFile);)
|
||||
{
|
||||
@@ -282,11 +361,8 @@ public class AppleUtils
|
||||
}
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return "Failed to write the file: " + aFile;
|
||||
throw new ErrorDM(aExp, "Failed to write the file: " + aFile);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,20 +5,114 @@ import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import distMaker.DistUtils;
|
||||
import distMaker.MiscUtils;
|
||||
import distMaker.*;
|
||||
import distMaker.jre.JreVersion;
|
||||
|
||||
public class LinuxUtils
|
||||
{
|
||||
/**
|
||||
* Utility method to update the JRE to reflect the specified path.
|
||||
* Returns the executable script used to launch the JVM.
|
||||
* <P>
|
||||
* TODO: Complete this comment and method.
|
||||
* 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.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static boolean updateJrePath(File aPath)
|
||||
public static File getScriptFile()
|
||||
{
|
||||
int zios_finish;
|
||||
return false;
|
||||
File[] fileArr;
|
||||
File installPath;
|
||||
File retFile;
|
||||
|
||||
installPath = DistUtils.getAppPath().getParentFile();
|
||||
fileArr = installPath.listFiles();
|
||||
|
||||
// Attempt to locate the path that matches run* file
|
||||
retFile = null;
|
||||
for (File aFile : fileArr)
|
||||
{
|
||||
if (aFile.getName().startsWith("run") == true)
|
||||
retFile = aFile;
|
||||
}
|
||||
|
||||
// Bail if we failed to locate a regular file
|
||||
if (retFile == null)
|
||||
throw new ErrorDM("The script file could not be located.");
|
||||
|
||||
// Ensure the file is a regular fie
|
||||
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!
|
||||
if (Files.isExecutable(retFile.toPath()) == false)
|
||||
throw new ErrorDM("The script file is NOT executable.");
|
||||
|
||||
return retFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the configuration to reflect the specified JRE version.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void updateJreVersion(JreVersion aJreVersion)
|
||||
{
|
||||
// Utilize the system scriptFile and delegate.
|
||||
updateJreVersion(aJreVersion, getScriptFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the configuration to reflect the specified JRE version.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void updateJreVersion(JreVersion aJreVersion, File aScriptFile)
|
||||
{
|
||||
List<String> inputList;
|
||||
String evalStr, tmpStr;
|
||||
int currLineNum, targLineNum;
|
||||
|
||||
// Bail if the scritpFile is not writable
|
||||
if (aScriptFile.setWritable(true) == false)
|
||||
throw new ErrorDM("The script file is not writeable: " + aScriptFile);
|
||||
|
||||
// Process our input
|
||||
inputList = new ArrayList<>();
|
||||
try (BufferedReader br = MiscUtils.openFileAsBufferedReader(aScriptFile))
|
||||
{
|
||||
// Read the lines
|
||||
currLineNum = 0;
|
||||
targLineNum = -1;
|
||||
while (true)
|
||||
{
|
||||
evalStr = br.readLine();
|
||||
if (evalStr == null)
|
||||
break;
|
||||
|
||||
// Locate where the java executable is specified
|
||||
tmpStr = evalStr.trim();
|
||||
if (tmpStr.startsWith("javaExe=") == true)
|
||||
targLineNum = currLineNum;
|
||||
|
||||
inputList.add(evalStr);
|
||||
currLineNum++;
|
||||
}
|
||||
}
|
||||
catch(IOException aExp)
|
||||
{
|
||||
throw new ErrorDM(aExp, "Failed while processing the script file: " + aScriptFile);
|
||||
}
|
||||
|
||||
// Update the script
|
||||
if (targLineNum != -1)
|
||||
inputList.set(targLineNum, "javaExe=../jre" + aJreVersion.getLabel() + "/bin/java");
|
||||
else
|
||||
throw new ErrorDM("[" + aScriptFile + "] The script does not specify 'javaExe'.");
|
||||
|
||||
// Write the scriptFile
|
||||
MiscUtils.writeDoc(aScriptFile, inputList);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,28 +123,39 @@ public class LinuxUtils
|
||||
* <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.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static String updateMaxMem(long numBytes)
|
||||
public static void updateMaxMem(long numBytes)
|
||||
{
|
||||
// Utilize the system scriptFile and delegate.
|
||||
updateMaxMem(numBytes, getScriptFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <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.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void updateMaxMem(long numBytes, File aScriptFile)
|
||||
{
|
||||
List<String> inputList;
|
||||
File scriptFile;
|
||||
String evalStr, memStr, tmpStr;
|
||||
int currLineNum, injectLineNum, targLineNum;
|
||||
|
||||
// Bail if we fail to locate the scriptFile.
|
||||
scriptFile = getScriptFile();
|
||||
if (scriptFile == null)
|
||||
return "The script file could not be located.";
|
||||
// Bail if the script file is not a regular file.
|
||||
if (scriptFile.isFile() == false)
|
||||
return "The script file does not appear to be a regular file: " + scriptFile;
|
||||
// Bail if the script file is not writeable.
|
||||
if (scriptFile.setWritable(true) == false)
|
||||
return "The script file is not writeable: " + scriptFile;
|
||||
// Bail if the scriptFile is not writable
|
||||
if (aScriptFile.setWritable(true) == false)
|
||||
throw new ErrorDM("The script file is not writeable: " + aScriptFile);
|
||||
|
||||
// Process our input
|
||||
inputList = new ArrayList<>();
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(scriptFile)));)
|
||||
try (BufferedReader br = MiscUtils.openFileAsBufferedReader(aScriptFile))
|
||||
{
|
||||
// Read the lines
|
||||
currLineNum = 0;
|
||||
@@ -73,10 +178,9 @@ public class LinuxUtils
|
||||
currLineNum++;
|
||||
}
|
||||
}
|
||||
catch(Exception aExp)
|
||||
catch(IOException aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return "Failed while processing the script file: " + scriptFile;
|
||||
throw new ErrorDM(aExp, "Failed while processing the script file: " + aScriptFile);
|
||||
}
|
||||
|
||||
// Determine the memStr to use
|
||||
@@ -96,48 +200,8 @@ public class LinuxUtils
|
||||
inputList.add(1, "maxMem=" + memStr + "\n");
|
||||
}
|
||||
|
||||
// Update the script
|
||||
System.out.println("Updating contents of file: " + scriptFile);
|
||||
if (MiscUtils.writeDoc(scriptFile, inputList) == false)
|
||||
return "Failed to write the script file: " + scriptFile;
|
||||
|
||||
// On success return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the executable script used to launch the JVM. If one can not be determined then this method will return null.
|
||||
* <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.
|
||||
*/
|
||||
private static File getScriptFile()
|
||||
{
|
||||
File[] fileArr;
|
||||
File installPath;
|
||||
File retFile;
|
||||
|
||||
installPath = DistUtils.getAppPath().getParentFile();
|
||||
fileArr = installPath.listFiles();
|
||||
|
||||
// Attempt to locate the path that matches run* file
|
||||
retFile = null;
|
||||
for (File aFile : fileArr)
|
||||
{
|
||||
if (aFile.getName().startsWith("run") == true)
|
||||
retFile = aFile;
|
||||
}
|
||||
|
||||
if (retFile == null)
|
||||
return null;
|
||||
|
||||
if (retFile.isFile() == false && Files.isExecutable(retFile.toPath()) == false)
|
||||
return null;
|
||||
|
||||
System.out.println("Linux launch file: " + retFile);
|
||||
return retFile;
|
||||
// Write the scriptFile
|
||||
MiscUtils.writeDoc(aScriptFile, inputList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,104 +1,171 @@
|
||||
package distMaker.platform;
|
||||
|
||||
import glum.gui.panel.generic.MessagePanel;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import distMaker.DistUtils;
|
||||
import distMaker.ErrorDM;
|
||||
import distMaker.jre.JreRelease;
|
||||
import distMaker.jre.JreVersion;
|
||||
import distMaker.node.AppRelease;
|
||||
|
||||
public class PlatformUtils
|
||||
{
|
||||
/**
|
||||
* Utility method that returns the platform specific configuration file for the java application.
|
||||
*/
|
||||
public static File getConfigurationFile()
|
||||
{
|
||||
File cfgFile;
|
||||
String platform;
|
||||
|
||||
platform = PlatformUtils.getPlatform().toUpperCase();
|
||||
if (platform.equals("APPLE") == true)
|
||||
cfgFile = AppleUtils.getPlistFile();
|
||||
else if (platform.equals("LINUX") == true)
|
||||
cfgFile = LinuxUtils.getScriptFile();
|
||||
else if (platform.equals("WINDOWS") == true)
|
||||
cfgFile = WindowsUtils.getConfigFile();
|
||||
else
|
||||
throw new ErrorDM("Unsupported platform: " + platform);
|
||||
|
||||
return cfgFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns the path where the specified JRE should be unpacked to.
|
||||
*/
|
||||
public static File getJreLocation(JreRelease aJreRelease)
|
||||
{
|
||||
// Delegate to actual worker method
|
||||
return getJreLocation(aJreRelease.getVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns the path where the specified JRE should be unpacked to.
|
||||
*/
|
||||
public static File getJreLocation(JreVersion aJreVersion)
|
||||
{
|
||||
String platform, versionStr;
|
||||
File jrePath, installPath;
|
||||
|
||||
jrePath = null;
|
||||
installPath = DistUtils.getAppPath();
|
||||
versionStr = aJreRelease.getVersion().getLabel();
|
||||
versionStr = aJreVersion.getLabel();
|
||||
|
||||
platform = DistUtils.getPlatform().toUpperCase();
|
||||
platform = PlatformUtils.getPlatform().toUpperCase();
|
||||
if (platform.equals("APPLE") == true)
|
||||
jrePath = new File(installPath.getParentFile(), "PlugIns/jre" + versionStr);
|
||||
else if (platform.equals("LINUX") == true)
|
||||
jrePath = new File(installPath.getParentFile(), "jre" + versionStr);
|
||||
else if (platform.equals("Windows") == true)
|
||||
else if (platform.equals("WINDOWS") == true)
|
||||
jrePath = new File(installPath.getParentFile(), "jre" + versionStr);
|
||||
|
||||
return jrePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to configure the JRE location used by the active DistMaker distribution.
|
||||
* <P>
|
||||
* Note this will only take effect after the application has been relaunched.
|
||||
* Returns the platform (Apple, Linux, or Windows) on which the current JRE is running on.
|
||||
*/
|
||||
public static boolean setJreLocation(File aPath)
|
||||
public static String getPlatform()
|
||||
{
|
||||
String osName;
|
||||
|
||||
osName = System.getProperty("os.name").toUpperCase();
|
||||
if (osName.startsWith("LINUX") == true)
|
||||
return "Linux";
|
||||
if (osName.startsWith("MAC OS X") == true)
|
||||
return "Apple";
|
||||
if (osName.startsWith("WINDOWS") == true)
|
||||
return "Windows";
|
||||
|
||||
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>
|
||||
* Note this will only take effect after the application has been restarted.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*
|
||||
* @param aJrePath
|
||||
* Path to top of the JRE.
|
||||
*/
|
||||
public static void setJreVersion(JreVersion aJreVersion)
|
||||
{
|
||||
String platform;
|
||||
boolean isPass;
|
||||
|
||||
isPass = false;
|
||||
platform = DistUtils.getPlatform().toUpperCase();
|
||||
// Delegate to the proper platform code
|
||||
platform = PlatformUtils.getPlatform().toUpperCase();
|
||||
if (platform.equals("APPLE") == true)
|
||||
isPass = AppleUtils.updateJrePath(aPath);
|
||||
AppleUtils.updateJreVersion(aJreVersion);
|
||||
else if (platform.equals("LINUX") == true)
|
||||
isPass = LinuxUtils.updateJrePath(aPath);
|
||||
else if (platform.equals("Windows") == true)
|
||||
isPass = WindowsUtils.updateJrePath(aPath);
|
||||
|
||||
return isPass;
|
||||
LinuxUtils.updateJreVersion(aJreVersion);
|
||||
else if (platform.equals("WINDOWS") == true)
|
||||
WindowsUtils.updateJreVersion(aJreVersion);
|
||||
else
|
||||
throw new ErrorDM("Unrecognized platform: " + platform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to configure the (active) DistMaker distribution to use the specified maxMem.
|
||||
* <P>
|
||||
* Method will return false on failure.
|
||||
* Note this will only take effect after the application has been restarted.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*
|
||||
* @param warnPanel
|
||||
* GUI message panel to route error messages.
|
||||
* @param maxMemSize
|
||||
* Maximum heap memory in bytes.
|
||||
*/
|
||||
public static boolean setMaxHeapMem(MessagePanel warnPanel, long maxMemSize)
|
||||
public static void setMaxHeapMem(long maxMemSize)
|
||||
{
|
||||
String platform;
|
||||
String errMsg;
|
||||
|
||||
// Delegate to the proper platform code
|
||||
errMsg = null;
|
||||
platform = DistUtils.getPlatform().toUpperCase();
|
||||
platform = PlatformUtils.getPlatform().toUpperCase();
|
||||
if (platform.equals("APPLE") == true)
|
||||
errMsg = AppleUtils.updateMaxMem(maxMemSize);
|
||||
AppleUtils.updateMaxMem(maxMemSize);
|
||||
else if (platform.equals("LINUX") == true)
|
||||
errMsg = LinuxUtils.updateMaxMem(maxMemSize);
|
||||
else if (platform.equals("Windows") == true)
|
||||
errMsg = WindowsUtils.updateMaxMem(maxMemSize);
|
||||
LinuxUtils.updateMaxMem(maxMemSize);
|
||||
else if (platform.equals("WINDOWS") == true)
|
||||
WindowsUtils.updateMaxMem(maxMemSize);
|
||||
else
|
||||
errMsg = "Unrecognized platform: " + platform;
|
||||
throw new ErrorDM(null, "Unrecognized platform: " + platform, "Unsupported Platform");
|
||||
}
|
||||
|
||||
// Display the warnPanel with the the error condition
|
||||
if (errMsg != null)
|
||||
{
|
||||
if (platform.equals("APPLE") == true)
|
||||
warnPanel.setTitle("Failed setting Apple properties.");
|
||||
else if (platform.equals("LINUX") == true)
|
||||
warnPanel.setTitle("Failed setting Linux configuration.");
|
||||
else if (platform.equals("Windows") == true)
|
||||
warnPanel.setTitle("Failed setting Windows configuration.");
|
||||
else
|
||||
warnPanel.setTitle("Platform is not supported.");
|
||||
/**
|
||||
* Utility method to update the (active) DistMaker distribution to reflect the specified AppRelease.
|
||||
* <P>
|
||||
* Note this will only take effect after the application has been restarted.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void updateAppRelease(AppRelease aRelease)
|
||||
{
|
||||
String platform;
|
||||
|
||||
warnPanel.setInfo(errMsg);
|
||||
warnPanel.setVisible(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// Delegate to the proper platform code
|
||||
platform = getPlatform().toUpperCase();
|
||||
if (platform.equals("APPLE") == true)
|
||||
AppleUtils.updateAppVersion(aRelease.getVersion());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,20 +4,87 @@ import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import distMaker.DistUtils;
|
||||
import distMaker.MiscUtils;
|
||||
import distMaker.*;
|
||||
import distMaker.jre.JreVersion;
|
||||
|
||||
public class WindowsUtils
|
||||
{
|
||||
/**
|
||||
* Utility method to update the JRE to reflect the specified path.
|
||||
* Returns the l4j runtime configuration file. If one can not be determined then this method will return null.
|
||||
* <P>
|
||||
* TODO: Complete this comment and method.
|
||||
* If the configuration file is determined but does not exist, then an empty configuration file will be created.
|
||||
* <P>
|
||||
* Note this method looks for a file that ends in .l4j.cfg, or an exe file and creates the corresponding config file.
|
||||
* <P>
|
||||
* If there are multiple .exe or .l4j.cfg files, then this method may grab the wrong file and fail.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static boolean updateJrePath(File aPath)
|
||||
public static File getConfigFile()
|
||||
{
|
||||
int zios_finish;
|
||||
return false;
|
||||
File[] fileArr;
|
||||
File installPath;
|
||||
File retFile;
|
||||
|
||||
installPath = DistUtils.getAppPath().getParentFile();
|
||||
fileArr = installPath.listFiles();
|
||||
|
||||
// Attempt to locate the <appExe>.l4j.ini file
|
||||
retFile = null;
|
||||
for (File aFile : fileArr)
|
||||
{
|
||||
if (aFile.getName().endsWith(".l4j.ini") == true)
|
||||
retFile = aFile;
|
||||
}
|
||||
|
||||
if (retFile == null)
|
||||
{
|
||||
for (File aFile : fileArr)
|
||||
{
|
||||
if (aFile.getName().endsWith(".exe") == true)
|
||||
retFile = new File(aFile.getParentFile(), aFile.getName().substring(0, aFile.getName().length() - 4) + ".l4j.ini");
|
||||
}
|
||||
}
|
||||
|
||||
if (retFile == null)
|
||||
throw new ErrorDM("The config file could not be located.");
|
||||
|
||||
if (retFile.isFile() == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
retFile.createNewFile();
|
||||
}
|
||||
catch(IOException aExp)
|
||||
{
|
||||
throw new ErrorDM(aExp, "A default config file could not be created.");
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Windows config file: " + retFile);
|
||||
return retFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the configuration to reflect the specified JRE version.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void updateJreVersion(JreVersion aJreVersion)
|
||||
{
|
||||
// Utilize the system configFile and delegate.
|
||||
updateJreVersion(aJreVersion, getConfigFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the configuration to reflect the specified JRE version.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void updateJreVersion(JreVersion aJreVersion, File aConfigFile)
|
||||
{
|
||||
int zzz_incomplete_logic;
|
||||
throw new ErrorDM("The logic is incomplete.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,24 +92,39 @@ public class WindowsUtils
|
||||
* <P>
|
||||
* Note this method is very brittle, and assumes that there is a single value where the string, -Xmx, is specified in the script. It assumes this string will
|
||||
* be surrounded by a single space character on each side.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static String updateMaxMem(long numBytes)
|
||||
public static void updateMaxMem(long numBytes)
|
||||
{
|
||||
// Utilize the system configFile and delegate.
|
||||
updateMaxMem(numBytes, getConfigFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the specified max memory (-Xmx) value in the text file (aFile) to the specified maxMemVal.
|
||||
* <P>
|
||||
* Note this method is very brittle, and assumes that there is a single value where the string, -Xmx, is specified in the script. It assumes this string will
|
||||
* be surrounded by a single space character on each side.
|
||||
* <P>
|
||||
* On failure this method will throw an exception of type ErrorDM.
|
||||
*/
|
||||
public static void updateMaxMem(long numBytes, File aConfigFile)
|
||||
{
|
||||
File configFile;
|
||||
List<String> inputList;
|
||||
String strLine, updateStr;
|
||||
boolean isProcessed;
|
||||
|
||||
// Bail if we fail to locate the configFile.
|
||||
configFile = getConfigFile();
|
||||
if (configFile != null && configFile.isFile() == true)
|
||||
return "The config file could not be located.";
|
||||
// Bail if the configFile is not writable
|
||||
aConfigFile = getConfigFile();
|
||||
if (aConfigFile.setWritable(true) == false)
|
||||
throw new ErrorDM("The config file is not writeable: " + aConfigFile);
|
||||
|
||||
isProcessed = false;
|
||||
inputList = new ArrayList<>();
|
||||
|
||||
// Process our input
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(configFile))))
|
||||
try (BufferedReader br = MiscUtils.openFileAsBufferedReader(aConfigFile))
|
||||
{
|
||||
// Read the lines
|
||||
while (true)
|
||||
@@ -72,72 +154,11 @@ public class WindowsUtils
|
||||
}
|
||||
catch(Exception aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return "Failed while processing the config file: " + configFile;
|
||||
throw new ErrorDM(aExp, "Failed while processing the config file: " + aConfigFile);
|
||||
}
|
||||
|
||||
// Update the script
|
||||
System.out.println("Updating contents of file: " + configFile);
|
||||
if (MiscUtils.writeDoc(configFile, inputList) == false)
|
||||
return "Failed to write the config file: " + configFile;
|
||||
|
||||
// On success return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the l4j runtime configuration file. If one can not be determined then this method will return null.
|
||||
* <P>
|
||||
* If the configuration file is determined but does not exist, then an empty configuration file will be created.
|
||||
* <P>
|
||||
* Note this method looks for a file that ends in .l4j.cfg, or an exe file and creates the corresponding config file.
|
||||
* <P>
|
||||
* If there are multiple .exe or .l4j.cfg files, then this method may grab the wrong file and fail.
|
||||
*/
|
||||
public static File getConfigFile()
|
||||
{
|
||||
File[] fileArr;
|
||||
File installPath;
|
||||
File retFile;
|
||||
|
||||
installPath = DistUtils.getAppPath().getParentFile();
|
||||
fileArr = installPath.listFiles();
|
||||
|
||||
// Attempt to locate the <appExe>.l4j.ini file
|
||||
retFile = null;
|
||||
for (File aFile : fileArr)
|
||||
{
|
||||
if (aFile.getName().endsWith(".l4j.ini") == true)
|
||||
retFile = aFile;
|
||||
}
|
||||
|
||||
if (retFile == null)
|
||||
{
|
||||
for (File aFile : fileArr)
|
||||
{
|
||||
if (aFile.getName().endsWith(".exe") == true)
|
||||
retFile = new File(aFile.getParentFile(), aFile.getName().substring(0, aFile.getName().length() - 4) + ".l4j.ini");
|
||||
}
|
||||
}
|
||||
|
||||
if (retFile == null)
|
||||
return null;
|
||||
|
||||
if (retFile.isFile() == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
retFile.createNewFile();
|
||||
}
|
||||
catch(IOException aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Windows config file: " + retFile);
|
||||
return retFile;
|
||||
MiscUtils.writeDoc(aConfigFile, inputList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user