Some much need love for the eclipse plugins.

Features/bug fixes include:
- Paul's progress bar for the installers
- Fix to prevent repeatede installation
- Right clicking and running Java projects works now
- Better logging to help find issues (Window > Show View > Other > Error Log)

Change-Id: I2cc791a58752cdeffec27f73880e7afcd1e95771
This commit is contained in:
Alex Henning
2014-06-18 13:46:22 -07:00
parent d9c1a4edfd
commit c106939bc2
31 changed files with 341 additions and 254 deletions

View File

@@ -11,6 +11,7 @@ import java.util.Properties;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
@@ -29,7 +30,7 @@ public class WPILibCore extends AbstractUIPlugin {
// The shared instance
private static WPILibCore plugin;
/**
* The constructor
*/
@@ -38,18 +39,24 @@ public class WPILibCore extends AbstractUIPlugin {
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
*
* @see
* org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
* )
*/
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
new ToolsInstaller(getDefaultVersion()).installIfNecessary();
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
*
* @see
* org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
* )
*/
public void stop(BundleContext context) throws Exception {
plugin = null;
@@ -58,7 +65,7 @@ public class WPILibCore extends AbstractUIPlugin {
/**
* Returns the shared instance
*
*
* @return the shared instance
*/
public static WPILibCore getDefault() {
@@ -66,58 +73,63 @@ public class WPILibCore extends AbstractUIPlugin {
}
/**
* Returns an image descriptor for the image file at the given
* plug-in relative path
*
* @param path the path
* Returns an image descriptor for the image file at the given plug-in
* relative path
*
* @param path
* the path
* @return the image descriptor
*/
public static ImageDescriptor getImageDescriptor(String path) {
return imageDescriptorFromPlugin(PLUGIN_ID, path);
}
public Properties getProjectProperties(IProject project) {
List<InputStream> streams = new ArrayList<InputStream>();
try {
if (project != null) {
try {
streams.add(project.getFile("build.properties").getContents());
} catch (CoreException e) {} // No properties file
streams.add(project.getFile("build.properties")
.getContents());
} catch (CoreException e) {
} // No properties file
}
File file = new File(getWPILibBaseDir()+"/wpilib.properties");
File file = new File(getWPILibBaseDir() + "/wpilib.properties");
streams.add(new FileInputStream(file));
return new AntPropertiesParser(streams).getProperties();
} catch (Exception e) {
e.printStackTrace();
WPILibCore.logError("Error loading project properties.", e);
return new Properties();
}
}
public void saveGlobalProperties(Properties props) {
try {
props.store(new FileOutputStream(new File(WPILibCore.getDefault().getWPILibBaseDir()+"/wpilib.properties")),
public void saveGlobalProperties(Properties props) {
try {
props.store(new FileOutputStream(new File(WPILibCore.getDefault()
.getWPILibBaseDir() + "/wpilib.properties")),
"Don't add new properties, they will be deleted by the eclipse plugin.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
WPILibCore.logError("Error saving global properties.", e);
}
}
public int getTeamNumber(IProject project) {
return Integer.parseInt(getProjectProperties(project).getProperty("team-number", "0"));
}
public int getTeamNumber(IProject project) {
return Integer.parseInt(getProjectProperties(project).getProperty(
"team-number", "0"));
}
public String getTargetIP(IProject project) {
String target = getProjectProperties(project).getProperty("target");
if (target != null) return target;
if (target != null)
return target;
else {
int teamNumber = getTeamNumber(project);
return "10."+(teamNumber/100)+"."+(teamNumber%100)+".2";
return "10." + (teamNumber / 100) + "." + (teamNumber % 100) + ".2";
}
}
public String getWPILibBaseDir() {
return System.getProperty("user.home")+"/wpilib";
return System.getProperty("user.home") + "/wpilib";
}
public String getDefaultVersion() {
@@ -125,6 +137,15 @@ public class WPILibCore extends AbstractUIPlugin {
}
public String getCurrentVersion() {
return getPreferenceStore().getString(PreferenceConstants.TOOLS_VERSION);
return getPreferenceStore()
.getString(PreferenceConstants.TOOLS_VERSION);
}
public static void logInfo(String msg) {
getDefault().getLog().log(new Status(Status.INFO, PLUGIN_ID, Status.OK, msg, null));
}
public static void logError(String msg, Exception e) {
getDefault().getLog().log(new Status(Status.ERROR, PLUGIN_ID, Status.OK, msg, e));
}
}

View File

@@ -39,7 +39,7 @@ public class RunOutlineViewerAction implements IWorkbenchWindowActionDelegate {
try {
DebugPlugin.exec(cmd, new File(System.getProperty("user.home")));
} catch (CoreException e) {
e.printStackTrace();
WPILibCore.logError("Error running outline viewer.", e);
}
}

View File

@@ -46,7 +46,7 @@ public class RunRobotBuilderAction implements IWorkbenchWindowActionDelegate {
try {
DebugPlugin.exec(cmd, new File(System.getProperty("user.home")));
} catch (CoreException e) {
e.printStackTrace();
WPILibCore.logError("Error running RobotBuilder.", e);
}
}
@@ -75,4 +75,4 @@ public class RunRobotBuilderAction implements IWorkbenchWindowActionDelegate {
*/
public void init(IWorkbenchWindow window) {
}
}
}

View File

@@ -39,7 +39,7 @@ public class RunSFXDashboardAction implements IWorkbenchWindowActionDelegate {
try {
DebugPlugin.exec(cmd, new File(System.getProperty("user.home")));
} catch (CoreException e) {
e.printStackTrace();
WPILibCore.logError("Error running SFXDashboard.", e);
}
}

View File

@@ -39,7 +39,7 @@ public class RunSmartDashboardAction implements IWorkbenchWindowActionDelegate {
try {
DebugPlugin.exec(cmd, new File(System.getProperty("user.home")));
} catch (CoreException e) {
e.printStackTrace();
WPILibCore.logError("Error running SmartDashboard.", e);
}
}
@@ -68,4 +68,4 @@ public class RunSmartDashboardAction implements IWorkbenchWindowActionDelegate {
*/
public void init(IWorkbenchWindow window) {
}
}
}

View File

@@ -11,6 +11,8 @@ import java.util.regex.Pattern;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Status;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
public class AntPropertiesParser {
List<InputStream> files;
@@ -44,9 +46,8 @@ public class AntPropertiesParser {
else props = new Properties(defaults);
try {
props.load(resource);
} catch (IOException e1) {
System.out.println("Issue loading file: "+resource);
e1.printStackTrace();
} catch (IOException e) {
WPILibCore.logError("Error loading property file: "+resource, e);
return null;
}

View File

@@ -10,7 +10,12 @@ import java.util.zip.ZipInputStream;
import javax.swing.JOptionPane;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugPlugin;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
@@ -29,130 +34,161 @@ public abstract class AbstractInstaller {
* @return The name of the feature being installed.
*/
protected abstract String getFeatureName();
/**
* Update the installed version to the latest version.
* @param version The latest version installed.
*/
protected abstract void updateInstalledVersion(String version);
/**
* @return The input stream to the zip file being installed.
*/
protected abstract InputStream getInstallResourceStream();
public void installIfNecessary() {
System.out.println("Installing "+getFeatureName()+" if necessary");
try {
System.out.println("Install Location: "
+ installLocation.getCanonicalPath());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
final Job installJob = new Job("Install " + getFeatureName()) {
@Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask(getTaskMessage(), IProgressMonitor.UNKNOWN);
WPILibCore.logInfo("Installing "+getFeatureName()+" if necessary");
if (!isInstalled()) {
System.out.println("Install necessary");
try {
install();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
if (!isInstalled()) {
WPILibCore.logInfo("Install necessary");
try {
install();
} catch (InstallException e) {
WPILibCore.logError("Error installing "+getFeatureName(), e);
return new Status(IStatus.ERROR, WPILibCore.PLUGIN_ID,
getErrorMessage(e));
}
}
updateInstalledVersion(version);
WPILibCore.logInfo("Installed");
return Status.OK_STATUS;
}
}
updateInstalledVersion(version);
System.out.println("Installed");
private String getErrorMessage(InstallException ex) {
String message = "Unable to install " + getFeatureName();
if (ex.getCause() != null) {
message += ": " + ex.getCause().getMessage();
} else if (ex.getMessage() != null) {
message += ": " + ex.getMessage();
}
message += ". See console for details.";
return message;
}
private String getTaskMessage() {
try {
return "Extracting to " + installLocation.getCanonicalPath();
} catch (IOException ex) {
WPILibCore.logError("installIfNecessary().getTaskMessage()", ex);
return "Extracting";
}
}
};
installJob.setUser(true);
installJob.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
installJob.schedule();
}
/**
* This function has been updated to guarantee that the wpilib folder date
* is older than the jar file being run, which ensures up to date tools.
*
*
* @return True for is there and newer, false otherwise.
*/
public boolean isInstalled() {
if(installLocation.exists())
{
File coreJar = new File(AbstractInstaller.class.getProtectionDomain()
.getCodeSource().getLocation().getPath());
if(installLocation.lastModified() <= coreJar.lastModified())
{
return false;
}
else return true;
}
else return false;
protected boolean isInstalled() {
return installLocation.exists();
}
/**
* This function will delete an old wpilib subfolder if necessary and then copy
* the resource stream to the intended directory.
*
* @throws IOException if bad things happen ...
*
* @throws InstallException if bad things happen ...
*/
public void install() throws IOException {
protected void install() throws InstallException {
if(installLocation.exists()) {
if(!removeFileHandler(installLocation, true)) {
JOptionPane.showMessageDialog(null,
JOptionPane.showMessageDialog(null,
String.format("Could not update the old wpilib folder.%n"
+ "Please close any WPILib tools and restart Eclipse."));
}
else
removeFileHandler(installLocation, false);
}
installLocation.mkdirs();
final String osName = System.getProperty("os.name");
if (osName.startsWith("Mac OS X") || osName.startsWith("Linux")) { // Unix-like OSes must preserve the executable bit; call unzip
InputStream zip = getInstallResourceStream();
File tmpFile = File.createTempFile(getFeatureName()+"-", ".zip");
FileOutputStream fout = new FileOutputStream(tmpFile);
copyStreams(zip, fout);
zip.close();
fout.close();
String[] cmd = {"unzip", tmpFile.getAbsolutePath(), "-d", installLocation.getAbsolutePath()};
System.out.println("unzip "+tmpFile.getAbsolutePath()+" -d "+installLocation.getAbsolutePath());
try {
InputStream is = DebugPlugin.exec(cmd, installLocation).getInputStream();
copyStreams(is, System.out);
} catch (CoreException e) {
e.printStackTrace();
}
} else {
ZipInputStream zip = new ZipInputStream(getInstallResourceStream());
ZipEntry entry = zip.getNextEntry();
while (entry != null) {
System.out.println("\tZipEntry " + entry + ": " + entry.getSize());
File f = new File(installLocation, entry.getName());
if (entry.isDirectory()) {
f.mkdirs();
} else {
FileOutputStream fo = new FileOutputStream(f);
copyStreams(zip, fo);
fo.close();
try {
if (osName.startsWith("Mac OS X") || osName.startsWith("Linux")) { // Unix-like OSes must preserve the executable bit; call unzip
final File tmpFile = File.createTempFile(getFeatureName()+"-", ".zip");
try {
// Copy to temporary file
try (final InputStream zip = getInstallResourceStream();
final FileOutputStream fout = new FileOutputStream(tmpFile)) {
copyStreams(zip, fout);
}
// Call 'unzip'
final String[] cmd = {"unzip", tmpFile.getAbsolutePath(), "-d", installLocation.getAbsolutePath()};
WPILibCore.logInfo("unzip "+tmpFile.getAbsolutePath()+" -d "+installLocation.getAbsolutePath());
final Process unzipProcess = DebugPlugin.exec(cmd, installLocation);
try (final InputStream is = unzipProcess.getInputStream()) {
copyStreams(is, System.out); // Copy output to console
}
// Check result
final int exitCode = unzipProcess.waitFor();
if (exitCode > 1 || exitCode < 0) { // Exit code 1 indicates success with warnings
throw new InstallException("Unzip process failed with code " + exitCode);
}
} finally {
tmpFile.delete();
}
zip.closeEntry();
entry = zip.getNextEntry();
} else {
ZipInputStream zip = new ZipInputStream(getInstallResourceStream());
ZipEntry entry = zip.getNextEntry();
while (entry != null) {
WPILibCore.logInfo("\tZipEntry " + entry + ": " + entry.getSize());
File f = new File(installLocation, entry.getName());
if (entry.isDirectory()) {
f.mkdirs();
} else {
FileOutputStream fo = new FileOutputStream(f);
copyStreams(zip, fo);
fo.close();
}
zip.closeEntry();
entry = zip.getNextEntry();
}
zip.close();
}
zip.close();
} catch (IOException | CoreException | InterruptedException ex) {
throw new InstallException("Install encountered a problem", ex);
}
}
private static void copyStreams(InputStream source, OutputStream destination) throws IOException {
byte[] buffer = new byte[1024];
int len;
while((len = source.read(buffer)) >= 0){
destination.write(buffer,0,len);
}
}
/**
* Recursively remove all of the files and folders described by this file handler.
*
*
* @param file The file to remove
* @param testRun True to just test if the files can be deleted
* @return True if this and all subFiles were removed, false otherwise.
@@ -173,6 +209,35 @@ public abstract class AbstractInstaller {
else return file.delete();
}
// I'm not sure what to do if the file is not normal or a directory ...
else return false;
else return false;
}
/**
* Indicates that an attempt to install a resource failed.
*/
private static class InstallException extends Exception {
private static final long serialVersionUID = 4883122446098399588L;
/**
* @see Exception#Exception()
*/
@SuppressWarnings("unused")
public InstallException() {
super();
}
/**
* @see Exception#Exception(String)
*/
public InstallException(String message) {
super(message);
}
/**
* @see Exception#Exception(String, Throwable)
*/
public InstallException(String message, Throwable cause) {
super(message, cause);
}
}
}

View File

@@ -23,7 +23,7 @@ public class ToolsInstaller extends AbstractInstaller {
protected void updateInstalledVersion(String version) {
IPreferenceStore prefs = WPILibCore.getDefault().getPreferenceStore();
if (prefs.getBoolean(PreferenceConstants.UPDATE_TOOLS_VERSION)) {
System.out.println("Forcing library version to "+version);
WPILibCore.logInfo("Forcing library version to "+version);
Properties props = WPILibCore.getDefault().getProjectProperties(null);
props.setProperty("version", version);
WPILibCore.getDefault().saveGlobalProperties(props);

View File

@@ -18,6 +18,8 @@ import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.IConsoleConstants;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
/**
* Contains functions to launch ant scripts while having the output sent to the
* console. Allows for the use of arguments, the specification of targets, and
@@ -125,13 +127,15 @@ public class AntLauncher {
launcher = workingCopy.doSave();
//Launch the modified configuration in the specified mode
try{ret = launcher.launch(mode, null, true, true);}catch(Exception e){
try {
ret = launcher.launch(mode, null, true, true);
} catch(Exception e) {
//Does not need Output, handled and resolved internally
e.printStackTrace();
WPILibCore.logError("Error running launch.", e);
return null;
}
}catch(Exception e){
e.printStackTrace();
} catch(Exception e) {
WPILibCore.logError("Error running ant file", e);
return null;
}

View File

@@ -79,7 +79,7 @@ public class WPILibPreferencePage
* @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
*/
public void init(IWorkbench workbench) {
System.out.println("Preferences initialized.");
WPILibCore.logInfo("Preferences initialized.");
Properties props = WPILibCore.getDefault().getProjectProperties(null);
getPreferenceStore().setValue(PreferenceConstants.TEAM_NUMBER,
Integer.parseInt(props.getProperty("team-number", "0")));
@@ -95,4 +95,4 @@ public class WPILibPreferencePage
WPILibCore.getDefault().saveGlobalProperties(props);
return super.performOk();
}
}
}

View File

@@ -13,6 +13,8 @@ import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWizard;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
public abstract class ExampleWizard extends Wizard implements INewWizard {
private ExampleWizardChoicePage page1;
private IWizardPage page2;
@@ -71,7 +73,7 @@ public abstract class ExampleWizard extends Wizard implements INewWizard {
try {
doFinish(page1.getExampleProject(), TeamNumberPage.getTeamNumberFromPage(teamNumberPage));
} catch (CoreException e) {
e.printStackTrace();
WPILibCore.logError("Error finishing example.", e);
MessageDialog.openError(getShell(), "Error", e.getMessage());
return false;
}

View File

@@ -28,6 +28,8 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
/**
* The "New" wizard page allows setting the container for the new file as well
* as the file name. The page will only accept file name without the extension
@@ -113,8 +115,8 @@ public class ExampleWizardChoicePage extends WizardPage {
}
}
System.out.println(examples);
System.out.println(tags);
WPILibCore.logInfo(examples.toString());
WPILibCore.logInfo(tags.toString());
// Generate the tags tree
for (Tag tag : tags) {
@@ -169,7 +171,7 @@ public class ExampleWizardChoicePage extends WizardPage {
try {
url = new URL(installURL, filename);
} catch (final MalformedURLException e) {
e.printStackTrace();
WPILibCore.logError("loadXMLResource()", e);
return null;
}
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
@@ -179,13 +181,13 @@ public class ExampleWizardChoicePage extends WizardPage {
dBuilder = dbFactory.newDocumentBuilder();
doc = dBuilder.parse(url.openStream());
} catch (ParserConfigurationException e) {
e.printStackTrace();
WPILibCore.logError("Error parsing "+filename, e);
return null;
} catch (SAXException e) {
e.printStackTrace();
WPILibCore.logError("SAX issue with "+filename, e);
return null;
} catch (IOException e) {
e.printStackTrace();
WPILibCore.logError("Error reading "+filename, e);
return null;
}
doc.getDocumentElement().normalize();
@@ -235,4 +237,4 @@ public class ExampleWizardChoicePage extends WizardPage {
public IExampleProject getExampleProject() {
return selectedExample;
}
}
}

View File

@@ -2,7 +2,6 @@ package edu.wpi.first.wpilib.plugins.core.wizards;
import java.util.Map;
import javax.activation.FileDataSource;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@@ -14,7 +13,6 @@ import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;

View File

@@ -22,6 +22,8 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
/**
* Utilities for creating a new project and files from templates. Uses
* IProjectCreator to provide hooks for generating the directory
@@ -51,7 +53,7 @@ public class ProjectCreationUtils {
addFilesToProject(project, creator);
creator.finalize(project);
} catch (CoreException e) {
e.printStackTrace();
WPILibCore.logError("Error creating project "+creator.getName(), e);
project = null;
}
@@ -75,7 +77,7 @@ public class ProjectCreationUtils {
newProject.open(null);
}
} catch (CoreException e) {
e.printStackTrace();
WPILibCore.logError("Can't create new project.", e);
}
}
@@ -121,8 +123,7 @@ public class ProjectCreationUtils {
URL url = new URL(creator.getProjectType().getBaseURL(), e.getValue());
createTemplateFile(project, e.getKey(), url, creator.getValues());
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
WPILibCore.logError("Error adding file "+e.toString()+" to project.", e1);
}
}
}
@@ -150,9 +151,9 @@ public class ProjectCreationUtils {
try {
return makeTemplateInputStream(url.openStream(), vals);
} catch (final MalformedURLException e) {
e.printStackTrace();
WPILibCore.logError("Malformed URL "+url, e);
} catch (final IOException e) {
e.printStackTrace();
WPILibCore.logError("Issue opening input stream.", e);
}
return null;
}
@@ -163,7 +164,7 @@ public class ProjectCreationUtils {
str = readInput(stream);
stream.close();
} catch (final IOException e) {
e.printStackTrace();
WPILibCore.logError("Error reading template.", e);
return null;
}
@@ -183,11 +184,10 @@ public class ProjectCreationUtils {
while ((ch = in.read()) > -1) {
buffer.append((char)ch);
}
System.out.print("\n");
in.close();
return buffer.toString();
} catch (IOException e) {
e.printStackTrace();
WPILibCore.logError("Error reading input.", e);
return null;
}
}