/*Argus -- A Zip Installer for Circumventing Common Educational Web Blocks
Copyright (C) 2014 Matthew Crocco
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package com.mattc.argus;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.swing.JFileChooser;
import javax.swing.UIManager;
import com.mattc.argus.concurrent.ArchiveThreadFactory;
import com.mattc.argus.concurrent.ZipProcess;
import com.mattc.argus.config.Config;
import com.mattc.argus.config.ConfigFilter;
import com.mattc.argus.config.DefaultFilter;
import com.mattc.argus.config.Permissions;
import com.mattc.argus.replace.Eclipse;
import com.mattc.argus.util.Console;
import com.mattc.argus.util.Utility;
import com.mattc.argus.util.Utility.OS;
/**
* Application Entry Point
*
* @author Matthew Crocco
*/
public class LaunchPoint{
//TODO Switch to an Open Source (OpenJDK?) Java Option
//Using Oracle Binaries may be against its License due to re-distribution
public static List<Future<?>> processes = new ArrayList<Future<?>>();
public static Permissions perms = new Permissions();
public static Config config = Config.getConfig();
private static ExecutorService service = Executors.newFixedThreadPool(6, new ArchiveThreadFactory());
public static void main(String[] args) throws IOException{
File destination = new File(Ref.getDesktopPath());
File current = new File(Ref.getJarDir(), "archives");
FileFilter filter;
Notifications.init();
if(!current.exists()){
current.mkdirs();
}
destination = determineDestination(destination);
if(destination == null){
Runtime.getRuntime().exit(0);
}
if(LaunchPoint.config == null){
filter = new DefaultFilter();
}else
filter = new ConfigFilter(LaunchPoint.config);
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
Console.debug("Nimbus Look And Feel Set!");
} catch (Exception e){
Console.error("Failure to Set Nimbus Look and Feel!...Setting System Look and Feel!");
Console.exception(e);
}finally{
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(Exception e){
Console.error("Failure to Set System Look and Feel!... Defaulting");
Console.exception(e);
}
Console.info("");
}
logSystemInfo();
Console.debug("JDir=" + current.getAbsolutePath()); //Print Jar Directory
Console.debug("IsDir=" + current.isDirectory()); //Is Directory
Console.debug("DDir=" + destination.getAbsolutePath()); //Print Desktop Directory
Console.debug("IsDir=" + destination.isDirectory()); //Is Directory
Notifications.displayInProgress(); //Show Progress Window
for(File f: current.listFiles(filter)){
//User Pre-Determined Destination, Pass in Actual File Name Without Suffix
//UnzipProcess a = new UnzipProcess(f, new File(destination, f.getName().substring(0, f.getName().lastIndexOf("."))));
processes.add(service.submit(new ZipProcess(f, new File(destination, f.getName().substring(0, f.getName().lastIndexOf("."))))));
}
//Hang While Processes are Running
while(isAThreadAlive());
//Commands on Linux
if(OS.get() == OS.UNIX){
perms.applyToAll(destination);
}
//Generate Replace Eclipse.ini
Eclipse.generateEclipseReplace(destination);
updateReplacements(destination);
Console.info("");
Notifications.updateLog("INSTALLATION COMPLETE!");
Notifications.switchToFinished(); //End Progress
Console.info("All Extraction Complete!");
service.shutdown();
}
/**
* Determine Install Directory by prompting with JFileChooser
* @param defaultDestination
* @return
*/
public static File determineDestination(File defaultDestination){
JFileChooser fc = new JFileChooser(defaultDestination.getAbsolutePath());
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int value = fc.showDialog(Notifications.getCurrentProgressWindow(), "Select Destination Directory");
if(value == JFileChooser.APPROVE_OPTION)
return fc.getSelectedFile();
else{
Notifications.alert("No Directory Chosen! Exiting!...");
return null;
}
}
/**
* Determines Whether Or Not there are STILL Unzip Threads Running
* @return
*/
public static boolean isAThreadAlive(){
//Waits Until All Threads are Dead Before Returning, Ensuring the Main Thread Hangs
for(Future<?> f: processes){
try {
if(f.get() != null)
return true;
} catch (InterruptedException e) {
return true;
} catch (ExecutionException e) {
return true;
}
}
//All Processes Have is in the dead state, Clear References and Return
processes.clear();
return false;
}
/**
* Go through proposed replacements and either skip and report a failed replacement or replace the original file.
* @param base
*/
public static void updateReplacements(File base){
ArrayList<String> archives = config.getRegisteredZips(); //Archives we Extracted
Map<String, String[]> replace = config.getReplacements(); //Replacement Map (Archive, List of Replacements)
File replaceDir = new File(".", "replace"); //Replacement File Directory
File[] replaceFiles; //List of Directories
if(!replaceDir.exists())
replaceDir.mkdirs();
replaceFiles = replaceDir.listFiles(); //Get Replacements In Existence
for(String s: archives){ //Go Through Extracted Archives
if(!replace.keySet().contains(s)) continue; //If Has No Replacements, Skip
File root = new File(base, s); //Directory of Unzipped Files (Java.zip -> <InstallPath>/Java)
String[] swaps = replace.get(s); //Get Files to Replace
for(String filename: swaps){ //For Each Proposed Replacement
File file = new File(root, filename); //Get Original File to Replace
if(!file.exists()){ //If Doesnt Exist, Report Failure
Console.warn("Failure to Replace file! " + file.getAbsolutePath() + " does not exist!");
continue;
}else{
for(File f: replaceFiles){ //Search Through All Files in ./replace
Console.info("REP: Comparing " + f.getName() + " and " + file.getName());
if(f.getName().equalsIgnoreCase(file.getName()))
Utility.copyFile(f, file); //Copy Replacement Over Original File
else
Console.info("REP: Comparison FAILED"); //Report Failure
}
}
}
}
}
/**
* Write System Info to Logging Utility
*/
public static void logSystemInfo(){
String home = "JAVA_HOME = " + System.getProperty("java.home", "Unable to Get Java Home!");
String vendor = "JAVA_VENDOR = " + System.getProperty("java.vendor", "No Vendor Found!");
String vendor_url = "VURL = " + System.getProperty("java.vendor.url", "No Url!");
String jversion = "RUNNING Java " + System.getProperty("java.version", "Undef");
String os = "OS = " + System.getProperty("os.name", "Unknown OS") + " " + System.getProperty("os.arch", "x??") + " " + System.getProperty("os.version", "v??");
String classpath = "CP = " + System.getProperty("java.class.path", "??? CLASSPATH ???");
Console.debug("");
Console.debug("========== SYS INFO ==========");
Console.debug(home);
Console.debug(jversion);
Console.debug(vendor);
Console.debug(vendor_url);
Console.debug(os);
Console.debug(classpath);
Console.debug("========== SYS INFO ==========");
Console.debug("");
}
}