diff options
author | Doug Schaefer | 2016-05-20 01:09:23 +0000 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org | 2016-05-24 05:00:06 +0000 |
commit | c2316a0b184372b1420aad32a5cc83619ff1d5db (patch) | |
tree | 04dd15cbae94d2cde8d9d2d936d036a5e3d39044 /toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core | |
parent | 3d94e24317361141fa2b78b2787d3f5524e11024 (diff) | |
download | org.eclipse.cdt-c2316a0b184372b1420aad32a5cc83619ff1d5db.tar.gz org.eclipse.cdt-c2316a0b184372b1420aad32a5cc83619ff1d5db.tar.xz org.eclipse.cdt-c2316a0b184372b1420aad32a5cc83619ff1d5db.zip |
Arduino Downloads Manager and lots of cleanup around that.
Change-Id: Ie2e4d987849831006d443bae98349861871a4057
Diffstat (limited to 'toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core')
14 files changed, 790 insertions, 418 deletions
diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/Activator.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/Activator.java index e34ed5e625d..85aaa0a2f49 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/Activator.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/Activator.java @@ -59,4 +59,17 @@ public class Activator extends Plugin { return ref != null ? context.getService(ref) : null; } + public static CoreException coreException(Throwable e) { + if (e instanceof RuntimeException && e.getCause() instanceof CoreException) { + return (CoreException) e.getCause(); + } else if (e instanceof CoreException) { + return (CoreException) e; + } + return new CoreException(new Status(IStatus.ERROR, getId(), e.getLocalizedMessage(), e)); + } + + public static CoreException coreException(String message, Throwable e) { + return new CoreException(new Status(IStatus.ERROR, getId(), message, e)); + } + } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoPreferences.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoPreferences.java index 07d3d81bfa5..c8ac61c5258 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoPreferences.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoPreferences.java @@ -7,9 +7,15 @@ *******************************************************************************/ package org.eclipse.cdt.arduino.core.internal; +import java.net.MalformedURLException; +import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.osgi.service.prefs.BackingStoreException; @@ -36,6 +42,18 @@ public class ArduinoPreferences { return getPrefs().get(BOARD_URLS, defaultBoardUrls); } + public static Collection<URL> getBoardUrlList() throws CoreException { + List<URL> urlList = new ArrayList<>(); + for (String url : getBoardUrls().split("\n")) { //$NON-NLS-1$ + try { + urlList.add(new URL(url.trim())); + } catch (MalformedURLException e) { + throw Activator.coreException(e); + } + } + return urlList; + } + public static void setBoardUrls(String boardUrls) { IEclipsePreferences prefs = getPrefs(); prefs.put(BOARD_URLS, boardUrls); diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoLibrary.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoLibrary.java index 162c3ab0497..0cd02f6a424 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoLibrary.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoLibrary.java @@ -10,6 +10,7 @@ package org.eclipse.cdt.arduino.core.internal.board; import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; @@ -18,14 +19,15 @@ import java.util.Collections; import java.util.List; import java.util.Properties; +import org.eclipse.cdt.arduino.core.internal.Activator; import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences; import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; public class ArduinoLibrary { + // JSON fields private String name; private String version; private String author; @@ -40,18 +42,22 @@ public class ArduinoLibrary { private String archiveFileName; private int size; private String checksum; + // end JSON fields private Path installPath; + private ArduinoPlatform platform; public ArduinoLibrary() { } - public ArduinoLibrary(Path propertiesFile) throws IOException { + public ArduinoLibrary(Path propertiesFile) throws CoreException { installPath = propertiesFile.getParent(); Properties props = new Properties(); try (FileReader reader = new FileReader(propertiesFile.toFile())) { props.load(reader); + } catch (IOException e) { + throw Activator.coreException(e); } name = props.getProperty("name"); //$NON-NLS-1$ @@ -64,6 +70,11 @@ public class ArduinoLibrary { architectures = Arrays.asList(props.getProperty("architectures").split(",")); //$NON-NLS-1$ //$NON-NLS-2$ } + public ArduinoLibrary(Path propertiesFile, ArduinoPlatform platform) throws CoreException { + this(propertiesFile); + this.platform = platform; + } + public String getName() { return name; } @@ -177,21 +188,33 @@ public class ArduinoLibrary { } public Path getInstallPath() { - return installPath != null ? installPath - : ArduinoPreferences.getArduinoHome().resolve("libraries").resolve(name.replace(' ', '_')) //$NON-NLS-1$ - .resolve(version); + return installPath == null + ? ArduinoPreferences.getArduinoHome().resolve("libraries").resolve(name.replace(' ', '_')) //$NON-NLS-1$ + : installPath; } - public boolean isInstalled() { - return getInstallPath().toFile().exists(); + public ArduinoPlatform getPlatform() { + return platform; } - public IStatus install(IProgressMonitor monitor) { - if (isInstalled()) { - return Status.OK_STATUS; + public void install(IProgressMonitor monitor) throws CoreException { + if (Files.exists(getInstallPath())) { + uninstall(monitor); + } + + try { + ArduinoManager.downloadAndInstall(url, archiveFileName, getInstallPath(), monitor); + } catch (IOException e) { + throw Activator.coreException(e); } + } - return ArduinoManager.downloadAndInstall(url, archiveFileName, getInstallPath(), monitor); + public void uninstall(IProgressMonitor monitor) throws CoreException { + try { + ArduinoManager.recursiveDelete(getInstallPath()); + } catch (IOException e) { + throw Activator.coreException(e); + } } public Collection<Path> getIncludePath() { @@ -240,17 +263,69 @@ public class ArduinoLibrary { } @Override - public boolean equals(Object obj) { - if (obj instanceof ArduinoLibrary) { - return getName().equals(((ArduinoLibrary) obj).getName()); - } else { - return false; + public String toString() { + return getName(); + } + + private String fixText(String text) { + String fixed = text.replaceAll("&", "&"); //$NON-NLS-1$ //$NON-NLS-2$ + fixed = fixed.replaceAll("<", "<"); //$NON-NLS-1$ //$NON-NLS-2$ + return fixed; + } + + public String toFormText() { + StringBuilder text = new StringBuilder(); + + text.append("<form>"); //$NON-NLS-1$ + text.append(String.format("<p><b>%s: %s</b></p>", "Library", fixText(getName()))); //$NON-NLS-1$ + + if (getMaintainer() != null) { + text.append(String.format("<p>%s: %s</p>", "Maintainer", fixText(getMaintainer()))); //$NON-NLS-1$ } + + if (getWebsite() != null) { + text.append(String.format("<p><a href=\"%s\">%s</a></p>", getWebsite(), "Online help")); //$NON-NLS-1$ + } + + text.append(String.format("<p>%s</p>", getSentence())); + if (getParagraph() != null && !getParagraph().equals(getSentence())) { + text.append(String.format("<p>%s</p>", getParagraph())); + } + + text.append("</form>"); + + return text.toString(); } @Override public int hashCode() { - return getName().hashCode(); + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((platform == null) ? 0 : platform.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ArduinoLibrary other = (ArduinoLibrary) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (platform == null) { + if (other.platform != null) + return false; + } else if (!platform.equals(other.platform)) + return false; + return true; } } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java index 87af37bc380..556c80082ce 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java @@ -11,13 +11,12 @@ package org.eclipse.cdt.arduino.core.internal.board; import java.io.BufferedInputStream; -import java.io.File; import java.io.FileInputStream; import java.io.FileReader; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.Reader; -import java.lang.reflect.Type; import java.net.URL; import java.net.URLConnection; import java.nio.file.FileVisitResult; @@ -30,8 +29,13 @@ import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.PosixFilePermission; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Properties; import java.util.Set; import org.apache.commons.compress.archivers.ArchiveEntry; @@ -43,23 +47,21 @@ import org.apache.commons.compress.compressors.CompressorException; import org.apache.commons.compress.compressors.CompressorStreamFactory; import org.eclipse.cdt.arduino.core.internal.Activator; import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences; -import org.eclipse.cdt.arduino.core.internal.Messages; -import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration; -import org.eclipse.cdt.core.build.ICBuildConfiguration; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.osgi.service.prefs.BackingStoreException; import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; public class ArduinoManager { @@ -70,205 +72,460 @@ public class ArduinoManager { public static final String AVR_TOOLCHAIN_ID = "org.eclipse.cdt.arduino.toolChain.avr"; //$NON-NLS-1$ public static final String LIBRARIES_URL = "http://downloads.arduino.cc/libraries/library_index.json"; //$NON-NLS-1$ + public static final String LIBRARIES_FILE = "library_index.json"; //$NON-NLS-1$ - private List<PackageIndex> packageIndices; - private LibraryIndex libraryIndex; + private static final String LIBRARIES = "libraries"; //$NON-NLS-1$ - public void loadIndices() { - new Job(Messages.ArduinoBoardManager_0) { - @Override - protected IStatus run(IProgressMonitor monitor) { - synchronized (ArduinoManager.this) { - String[] boardUrls = ArduinoPreferences.getBoardUrls().split("\n"); //$NON-NLS-1$ - packageIndices = new ArrayList<>(boardUrls.length); - for (String boardUrl : boardUrls) { - loadPackageIndex(boardUrl, true); - } + // arduinocdt install properties + private static final String VERSION_KEY = "version"; //$NON-NLS-1$ + private static final String ACCEPTED_KEY = "accepted"; //$NON-NLS-1$ + private static final String VERSION = "2"; //$NON-NLS-1$ + + private Properties props; + + private Map<String, ArduinoPackage> packages; + private Map<String, ArduinoLibrary> installedLibraries; - loadLibraryIndex(true); - return Status.OK_STATUS; + private Path getVersionFile() { + return ArduinoPreferences.getArduinoHome().resolve(".version"); //$NON-NLS-1$ + } + + private void init() throws CoreException { + if (props == null) { + if (!Files.exists(ArduinoPreferences.getArduinoHome())) { + try { + Files.createDirectories(ArduinoPreferences.getArduinoHome()); + } catch (IOException e) { + throw Activator.coreException(e); } } - }.schedule(); + + props = new Properties(); + Path propsFile = getVersionFile(); + if (Files.exists(propsFile)) { + try (FileReader reader = new FileReader(propsFile.toFile())) { + props.load(reader); + } catch (IOException e) { + throw Activator.coreException(e); + } + } + + // See if we need a conversion + int version = Integer.parseInt(props.getProperty(VERSION_KEY, "1")); //$NON-NLS-1$ + if (version < Integer.parseInt(VERSION)) { + // Need to move the directories around + convertPackageDirs(); + + props.setProperty(VERSION_KEY, VERSION); + try (FileWriter writer = new FileWriter(getVersionFile().toFile())) { + props.store(writer, ""); //$NON-NLS-1$ + } catch (IOException e) { + throw Activator.coreException(e); + } + } + } } - private void loadPackageIndex(String url, boolean download) { + private void convertPackageDirs() throws CoreException { + Path packagesDir = ArduinoPreferences.getArduinoHome().resolve("packages"); //$NON-NLS-1$ + if (!Files.isDirectory(packagesDir)) { + return; + } + try { - URL packageUrl = new URL(url.trim()); - Path packagePath = ArduinoPreferences.getArduinoHome() - .resolve(Paths.get(packageUrl.getPath()).getFileName()); - File packageFile = packagePath.toFile(); - if (download) { - Files.createDirectories(ArduinoPreferences.getArduinoHome()); + Files.list(packagesDir).forEach(path -> { try { - Files.copy(packageUrl.openStream(), packagePath, StandardCopyOption.REPLACE_EXISTING); + Path hardwarePath = path.resolve("hardware"); //$NON-NLS-1$ + Path badPath = hardwarePath.resolve(path.getFileName()); + Path tmpDir = Files.createTempDirectory(packagesDir, "tbd"); //$NON-NLS-1$ + Path badPath2 = tmpDir.resolve(badPath.getFileName()); + Files.move(badPath, badPath2); + Files.list(badPath2).forEach(archPath -> { + try { + Optional<Path> latest = Files.list(archPath) + .reduce((path1, path2) -> compareVersions(path1.getFileName().toString(), + path2.getFileName().toString()) > 0 ? path1 : path2); + if (latest.isPresent()) { + Files.move(latest.get(), hardwarePath.resolve(archPath.getFileName())); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + recursiveDelete(tmpDir); } catch (IOException e) { - // make sure we add the package anyway if it exists - Activator.log(e); + throw new RuntimeException(e); } - } - if (packageFile.exists()) { - try (Reader reader = new FileReader(packageFile)) { - PackageIndex index = new Gson().fromJson(reader, PackageIndex.class); - index.setOwners(ArduinoManager.this); - packageIndices.add(index); + }); + } catch (RuntimeException | IOException e) { + throw Activator.coreException(e); + } + } + + public void convertLibrariesDir() throws CoreException { + Path librariesDir = ArduinoPreferences.getArduinoHome().resolve("libraries"); //$NON-NLS-1$ + if (!Files.isDirectory(librariesDir)) { + return; + } + + try { + Path tmpDir = Files.createTempDirectory("alib"); //$NON-NLS-1$ + Path tmpLibDir = tmpDir.resolve("libraries"); //$NON-NLS-1$ + Files.move(librariesDir, tmpLibDir); + Files.list(tmpLibDir).forEach(path -> { + try { + Optional<Path> latest = Files.list(path) + .reduce((path1, path2) -> compareVersions(path1.getFileName().toString(), + path2.getFileName().toString()) > 0 ? path1 : path2); + if (latest.isPresent()) { + Files.move(latest.get(), librariesDir.resolve(path.getFileName())); + } + } catch (IOException e) { + throw new RuntimeException(e); } - } + }); + recursiveDelete(tmpDir); + } catch (RuntimeException | IOException e) { + throw Activator.coreException(e); + } + + } + + public boolean licenseAccepted() throws CoreException { + init(); + return Boolean.getBoolean(props.getProperty(ACCEPTED_KEY, Boolean.FALSE.toString())); + } + + public void acceptLicense() throws CoreException { + init(); + props.setProperty(ACCEPTED_KEY, Boolean.TRUE.toString()); + try (FileWriter writer = new FileWriter(getVersionFile().toFile())) { + props.store(writer, ""); //$NON-NLS-1$ } catch (IOException e) { - Activator.log(e); + throw Activator.coreException(e); } } - public synchronized List<PackageIndex> getPackageIndices() { - if (packageIndices == null) { - String[] boardUrls = ArduinoPreferences.getBoardUrls().split("\n"); //$NON-NLS-1$ - packageIndices = new ArrayList<>(boardUrls.length); - for (String boardUrl : boardUrls) { - loadPackageIndex(boardUrl, false); - } + public Collection<ArduinoPlatform> getInstalledPlatforms() throws CoreException { + List<ArduinoPlatform> platforms = new ArrayList<>(); + for (ArduinoPackage pkg : getPackages()) { + platforms.addAll(pkg.getInstalledPlatforms()); } - return packageIndices; + return platforms; } - public void loadLibraryIndex(boolean download) { - try { - URL librariesUrl = new URL(LIBRARIES_URL); - Path librariesPath = ArduinoPreferences.getArduinoHome() - .resolve(Paths.get(librariesUrl.getPath()).getFileName()); - File librariesFile = librariesPath.toFile(); - if (download) { + public ArduinoPlatform getInstalledPlatform(String packageName, String architecture) throws CoreException { + ArduinoPackage pkg = getPackage(packageName); + return pkg != null ? pkg.getInstalledPlatform(architecture) : null; + } + + public Collection<ArduinoPlatform> getAvailablePlatforms(IProgressMonitor monitor) throws CoreException { + List<ArduinoPlatform> platforms = new ArrayList<>(); + Collection<URL> urls = ArduinoPreferences.getBoardUrlList(); + SubMonitor sub = SubMonitor.convert(monitor, urls.size() + 1); + + sub.beginTask("Downloading package descriptions", urls.size()); //$NON-NLS-1$ + for (URL url : urls) { + Path packagePath = ArduinoPreferences.getArduinoHome() + .resolve(Paths.get(url.getPath()).getFileName()); + try { Files.createDirectories(ArduinoPreferences.getArduinoHome()); - Files.copy(librariesUrl.openStream(), librariesPath, StandardCopyOption.REPLACE_EXISTING); - } - if (librariesFile.exists()) { - try (Reader reader = new FileReader(librariesFile)) { - libraryIndex = new Gson().fromJson(reader, LibraryIndex.class); - libraryIndex.resolve(); + try (InputStream in = url.openStream()) { + Files.copy(in, packagePath, StandardCopyOption.REPLACE_EXISTING); } + } catch (IOException e) { + throw Activator.coreException(String.format("Error loading %s", url.toString()), e); //$NON-NLS-1$ } - } catch (IOException e) { - Activator.log(e); + sub.worked(1); + } + + sub.beginTask("Loading available packages", 1); //$NON-NLS-1$ + resetPackages(); + for (ArduinoPackage pkg : getPackages()) { + platforms.addAll(pkg.getAvailablePlatforms()); } + sub.done(); + return platforms; } - public LibraryIndex getLibraryIndex() throws CoreException { - if (libraryIndex == null) { - loadLibraryIndex(false); + public void installPlatforms(Collection<ArduinoPlatform> platforms, IProgressMonitor monitor) throws CoreException { + SubMonitor sub = SubMonitor.convert(monitor, platforms.size()); + for (ArduinoPlatform platform : platforms) { + sub.setTaskName(String.format("Installing %s", platform.getName())); //$NON-NLS-1$ + platform.install(sub); + sub.worked(1); } - return libraryIndex; + sub.done(); } - public ArduinoBoard getBoard(String boardName, String platformName, String packageName) throws CoreException { - for (PackageIndex index : getPackageIndices()) { - ArduinoPackage pkg = index.getPackage(packageName); - if (pkg != null) { - ArduinoPlatform platform = pkg.getPlatform(platformName); - if (platform != null) { - ArduinoBoard board = platform.getBoard(boardName); - if (board != null) { - return board; - } - } + public void uninstallPlatforms(Collection<ArduinoPlatform> platforms, IProgressMonitor monitor) { + SubMonitor sub = SubMonitor.convert(monitor, platforms.size()); + for (ArduinoPlatform platform : platforms) { + sub.setTaskName(String.format("Uninstalling %s", platform.getName())); //$NON-NLS-1$ + platform.uninstall(sub); + sub.worked(1); + } + sub.done(); + } + + public static List<ArduinoPlatform> getSortedPlatforms(Collection<ArduinoPlatform> platforms) { + List<ArduinoPlatform> result = new ArrayList<>(platforms); + Collections.sort(result, (plat1, plat2) -> { + int c1 = plat1.getPackage().getName().compareToIgnoreCase(plat2.getPackage().getName()); + if (c1 > 0) { + return 1; + } else if (c1 < 0) { + return -1; + } else { + return plat1.getArchitecture().compareToIgnoreCase(plat2.getArchitecture()); + } + }); + return result; + } + + public static List<ArduinoLibrary> getSortedLibraries(Collection<ArduinoLibrary> libraries) { + List<ArduinoLibrary> result = new ArrayList<>(libraries); + Collections.sort(result, (lib1, lib2) -> { + return lib1.getName().compareToIgnoreCase(lib2.getName()); + }); + return result; + } + + private void initPackages() throws CoreException { + if (packages == null) { + init(); + packages = new HashMap<>(); + + try { + Files.list(ArduinoPreferences.getArduinoHome()) + .filter(path -> path.getFileName().toString().startsWith("package_")) //$NON-NLS-1$ + .forEach(path -> { + try (Reader reader = new FileReader(path.toFile())) { + PackageIndex index = new Gson().fromJson(reader, PackageIndex.class); + for (ArduinoPackage pkg : index.getPackages()) { + pkg.init(); + packages.put(pkg.getName(), pkg); + } + } catch (IOException e) { + Activator.log(e); + } + }); + } catch (IOException e) { + throw Activator.coreException(e); } } - return null; } - public List<ArduinoBoard> getInstalledBoards() throws CoreException { + private Collection<ArduinoPackage> getPackages() throws CoreException { + initPackages(); + return packages.values(); + } + + public void resetPackages() { + packages = null; + } + + private ArduinoPackage getPackage(String packageName) throws CoreException { + if (packageName == null) { + return null; + } else { + initPackages(); + return packages.get(packageName); + } + } + + public Collection<ArduinoBoard> getInstalledBoards() throws CoreException { List<ArduinoBoard> boards = new ArrayList<>(); - for (PackageIndex index : getPackageIndices()) { - for (ArduinoPackage pkg : index.getPackages()) { - for (ArduinoPlatform platform : pkg.getInstalledPlatforms().values()) { - boards.addAll(platform.getBoards()); - } - } + for (ArduinoPlatform platform : getInstalledPlatforms()) { + boards.addAll(platform.getBoards()); } return boards; } - public ArduinoPackage getPackage(String packageName) throws CoreException { - for (PackageIndex index : getPackageIndices()) { - ArduinoPackage pkg = index.getPackage(packageName); - if (pkg != null) { - return pkg; + public ArduinoBoard getBoard(String packageName, String architecture, String boardId) throws CoreException { + for (ArduinoPlatform platform : getInstalledPlatforms()) { + if (platform.getPackage().getName().equals(packageName) + && platform.getArchitecture().equals(architecture)) { + return platform.getBoard(boardId); + } + } + + // For backwards compat, check platform name + for (ArduinoPlatform platform : getInstalledPlatforms()) { + if (platform.getPackage().getName().equals(packageName) + && platform.getName().equals(architecture)) { + return platform.getBoardByName(boardId); } } + return null; } - public ArduinoTool getTool(String packageName, String toolName, String version) throws CoreException { - for (PackageIndex index : getPackageIndices()) { - ArduinoPackage pkg = index.getPackage(packageName); - if (pkg != null) { - ArduinoTool tool = pkg.getTool(toolName, version); - if (tool != null) { - return tool; + public ArduinoTool getTool(String packageName, String toolName, String version) { + ArduinoPackage pkg = packages.get(packageName); + return pkg != null ? pkg.getTool(toolName, version) : null; + } + + public void initInstalledLibraries() throws CoreException { + init(); + if (installedLibraries == null) { + installedLibraries = new HashMap<>(); + + Path librariesDir = ArduinoPreferences.getArduinoHome().resolve("libraries"); //$NON-NLS-1$ + if (Files.isDirectory(librariesDir)) { + try { + Files.find(librariesDir, 2, + (path, attrs) -> path.getFileName().toString().equals("library.properties")) //$NON-NLS-1$ + .forEach(path -> { + try { + ArduinoLibrary library = new ArduinoLibrary(path); + installedLibraries.put(library.getName(), library); + } catch (CoreException e) { + throw new RuntimeException(e); + } + }); + } catch (IOException e) { + throw Activator.coreException(e); } } } - return null; } - private static final String LIBRARIES = "libraries"; //$NON-NLS-1$ + public Collection<ArduinoLibrary> getInstalledLibraries() throws CoreException { + initInstalledLibraries(); + return installedLibraries.values(); + } - private IEclipsePreferences getSettings(IProject project) { - return new ProjectScope(project).getNode(Activator.getId()); + public ArduinoLibrary getInstalledLibrary(String name) throws CoreException { + initInstalledLibraries(); + return installedLibraries.get(name); } - public Collection<ArduinoLibrary> getLibraries(IProject project) throws CoreException { + public Collection<ArduinoLibrary> getAvailableLibraries(IProgressMonitor monitor) throws CoreException { + try { + initInstalledLibraries(); + Map<String, ArduinoLibrary> libs = new HashMap<>(); + + SubMonitor sub = SubMonitor.convert(monitor, "Downloading library index", 2); + Path librariesPath = ArduinoPreferences.getArduinoHome().resolve(LIBRARIES_FILE); + URL librariesUrl = new URL(LIBRARIES_URL); + Files.createDirectories(ArduinoPreferences.getArduinoHome()); + Files.copy(librariesUrl.openStream(), librariesPath, StandardCopyOption.REPLACE_EXISTING); + sub.worked(1); + + try (Reader reader = new FileReader(librariesPath.toFile())) { + sub.setTaskName("Calculating available libraries"); + LibraryIndex libraryIndex = new Gson().fromJson(reader, LibraryIndex.class); + for (ArduinoLibrary library : libraryIndex.getLibraries()) { + String libraryName = library.getName(); + if (!installedLibraries.containsKey(libraryName)) { + ArduinoLibrary current = libs.get(libraryName); + if (current == null || compareVersions(library.getVersion(), current.getVersion()) > 0) { + libs.put(libraryName, library); + } + } + } + } + sub.done(); + return libs.values(); + } catch (IOException e) { + throw Activator.coreException(e); + } + } + + public void installLibraries(Collection<ArduinoLibrary> libraries, IProgressMonitor monitor) throws CoreException { + SubMonitor sub = SubMonitor.convert(monitor, libraries.size()); + for (ArduinoLibrary library : libraries) { + sub.setTaskName(String.format("Installing %s", library.getName())); //$NON-NLS-1$ + library.install(sub); + try { + ArduinoLibrary newLibrary = new ArduinoLibrary(library.getInstallPath().resolve("library.properties")); //$NON-NLS-1$ + installedLibraries.put(newLibrary.getName(), newLibrary); + } catch (CoreException e) { + throw new RuntimeException(e); + } + sub.worked(1); + } + sub.done(); + } + + public void uninstallLibraries(Collection<ArduinoLibrary> libraries, IProgressMonitor monitor) + throws CoreException { + SubMonitor sub = SubMonitor.convert(monitor, libraries.size()); + for (ArduinoLibrary library : libraries) { + sub.setTaskName(String.format("Installing %s", library.getName())); //$NON-NLS-1$ + library.uninstall(sub); + installedLibraries.remove(library.getName()); + sub.worked(1); + } + sub.done(); + } + + public Collection<ArduinoLibrary> getLibraries(IProject project) + throws CoreException { + initInstalledLibraries(); IEclipsePreferences settings = getSettings(project); String librarySetting = settings.get(LIBRARIES, "[]"); //$NON-NLS-1$ - Type stringSet = new TypeToken<Set<String>>() { - }.getType(); - Set<String> libraryNames = new Gson().fromJson(librarySetting, stringSet); - LibraryIndex index = Activator.getService(ArduinoManager.class).getLibraryIndex(); - - ICBuildConfiguration cconfig = project.getActiveBuildConfig().getAdapter(ICBuildConfiguration.class); - ArduinoPlatform platform = cconfig.getAdapter(ArduinoBuildConfiguration.class).getBoard().getPlatform(); - List<ArduinoLibrary> libraries = new ArrayList<>(libraryNames.size()); - for (String name : libraryNames) { - ArduinoLibrary lib = index.getLibrary(name); - if (lib == null) { - lib = platform.getLibrary(name); - } - if (lib != null) { - libraries.add(lib); + JsonArray libArray = new JsonParser().parse(librarySetting).getAsJsonArray(); + + List<ArduinoLibrary> libraries = new ArrayList<>(libArray.size()); + for (JsonElement libElement : libArray) { + if (libElement.isJsonPrimitive()) { + String libName = libElement.getAsString(); + ArduinoLibrary lib = installedLibraries.get(libName); + if (lib != null) { + libraries.add(lib); + } + } else { + JsonObject libObj = libElement.getAsJsonObject(); + String packageName = libObj.get("package").getAsString(); //$NON-NLS-1$ + String platformName = libObj.get("platform").getAsString(); //$NON-NLS-1$ + String libName = libObj.get("library").getAsString(); //$NON-NLS-1$ + ArduinoPackage pkg = getPackage(packageName); + if (pkg != null) { + ArduinoPlatform platform = pkg.getInstalledPlatform(platformName); + if (platform != null) { + ArduinoLibrary lib = platform.getLibrary(libName); + if (lib != null) { + libraries.add(lib); + } + } + } } } return libraries; } public void setLibraries(final IProject project, final Collection<ArduinoLibrary> libraries) throws CoreException { - List<String> libraryNames = new ArrayList<>(libraries.size()); + JsonArray elements = new JsonArray(); for (ArduinoLibrary library : libraries) { - libraryNames.add(library.getName()); + ArduinoPlatform platform = library.getPlatform(); + if (platform != null) { + JsonObject libObj = new JsonObject(); + libObj.addProperty("package", platform.getPackage().getName()); //$NON-NLS-1$ + libObj.addProperty("platform", platform.getArchitecture()); //$NON-NLS-1$ + libObj.addProperty("library", library.getName()); //$NON-NLS-1$ + elements.add(libObj); + } else { + elements.add(new JsonPrimitive(library.getName())); + } } IEclipsePreferences settings = getSettings(project); - settings.put(LIBRARIES, new Gson().toJson(libraryNames)); + settings.put(LIBRARIES, new Gson().toJson(elements)); try { settings.flush(); } catch (BackingStoreException e) { - Activator.log(e); + throw Activator.coreException(e); } + } - new Job(Messages.ArduinoManager_0) { - @Override - protected IStatus run(IProgressMonitor monitor) { - MultiStatus mstatus = new MultiStatus(Activator.getId(), 0, Messages.ArduinoManager_1, null); - for (ArduinoLibrary library : libraries) { - IStatus status = library.install(monitor); - if (!status.isOK()) { - mstatus.add(status); - } - } - return mstatus; - } - }.schedule(); + private IEclipsePreferences getSettings(IProject project) { + return new ProjectScope(project).getNode(Activator.getId()); } - public static IStatus downloadAndInstall(String url, String archiveFileName, Path installPath, - IProgressMonitor monitor) { + public static void downloadAndInstall(String url, String archiveFileName, Path installPath, + IProgressMonitor monitor) throws IOException { Exception error = null; for (int retries = 3; retries > 0 && !monitor.isCanceled(); --retries) { try { @@ -351,15 +608,19 @@ public class ArduinoManager { archiveIn.close(); } } - - return Status.OK_STATUS; + return; } catch (IOException | CompressorException | ArchiveException e) { error = e; // retry } } + // out of retries - return new Status(IStatus.ERROR, Activator.getId(), Messages.ArduinoManager_2, error); + if (error instanceof IOException) { + throw (IOException) error; + } else { + throw new IOException(error); + } } public static int compareVersions(String version1, String version2) { diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPackage.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPackage.java index 1d18767598a..3aba4a82eda 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPackage.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPackage.java @@ -7,17 +7,25 @@ *******************************************************************************/ package org.eclipse.cdt.arduino.core.internal.board; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Properties; +import org.eclipse.cdt.arduino.core.internal.Activator; import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences; +import org.eclipse.core.runtime.CoreException; public class ArduinoPackage { + // JSON fields private String name; private String maintainer; private String websiteURL; @@ -25,22 +33,9 @@ public class ArduinoPackage { private ArduinoHelp help; private List<ArduinoPlatform> platforms; private List<ArduinoTool> tools; + // end JSON fields - private transient ArduinoManager manager; - - void setOwner(ArduinoManager manager) { - this.manager = manager; - for (ArduinoPlatform platform : platforms) { - platform.setOwner(this); - } - for (ArduinoTool tool : tools) { - tool.setOwner(this); - } - } - - ArduinoManager getManager() { - return manager; - } + private Map<String, ArduinoPlatform> installedPlatforms; public String getName() { return name; @@ -66,51 +61,96 @@ public class ArduinoPackage { return Collections.unmodifiableCollection(platforms); } + void init() { + for (ArduinoPlatform platform : platforms) { + platform.init(this); + } + for (ArduinoTool tool : tools) { + tool.init(this); + } + } + + public ArduinoPlatform getPlatform(String architecture, String version) { + if (platforms != null) { + for (ArduinoPlatform plat : platforms) { + if (plat.getArchitecture().equals(architecture) && plat.getVersion().equals(version)) { + return plat; + } + } + } + return null; + } + public Path getInstallPath() { return ArduinoPreferences.getArduinoHome().resolve("packages").resolve(getName()); //$NON-NLS-1$ } - /** - * Only the latest versions of the platforms. - * - * @return latest platforms - */ - public Map<String, ArduinoPlatform> getAvailablePlatforms() { - Map<String, ArduinoPlatform> platformMap = new HashMap<>(); - for (ArduinoPlatform platform : platforms) { - ArduinoPlatform p = platformMap.get(platform.getName()); - if (p == null || ArduinoManager.compareVersions(platform.getVersion(), p.getVersion()) > 0) { - platformMap.put(platform.getName(), platform); + private void initInstalledPlatforms() throws CoreException { + if (installedPlatforms == null) { + installedPlatforms = new HashMap<>(); + + if (Files.isDirectory(getInstallPath())) { + Path platformTxt = Paths.get("platform.txt"); //$NON-NLS-1$ + try { + Files.find(getInstallPath().resolve("hardware"), 2, //$NON-NLS-1$ + (path, attrs) -> path.getFileName().equals(platformTxt)) + .forEach(path -> { + try (FileReader reader = new FileReader(path.toFile())) { + Properties platformProperties = new Properties(); + platformProperties.load(reader); + String arch = path.getName(path.getNameCount() - 2).toString(); + String version = platformProperties.getProperty("version"); //$NON-NLS-1$ + + ArduinoPlatform platform = getPlatform(arch, version); + if (platform != null) { + platform.setPlatformProperties(platformProperties); + installedPlatforms.put(arch, platform); + } // TODO manually add it if was removed from index + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } catch (IOException e) { + throw Activator.coreException(e); + } } } - return platformMap; } - public Map<String, ArduinoPlatform> getInstalledPlatforms() { - Map<String, ArduinoPlatform> platformMap = new HashMap<>(); - for (ArduinoPlatform platform : platforms) { - if (platform.isInstalled()) { - platformMap.put(platform.getName(), platform); - } + public Collection<ArduinoPlatform> getInstalledPlatforms() throws CoreException { + initInstalledPlatforms(); + return installedPlatforms.values(); + } + + public ArduinoPlatform getInstalledPlatform(String architecture) throws CoreException { + if (architecture == null) { + return null; + } else { + initInstalledPlatforms(); + return installedPlatforms.get(architecture); } - return platformMap; } - public ArduinoPlatform getPlatform(String name) { - ArduinoPlatform foundPlatform = null; + void platformInstalled(ArduinoPlatform platform) { + installedPlatforms.put(platform.getArchitecture(), platform); + } + + void platformUninstalled(ArduinoPlatform platform) { + installedPlatforms.remove(platform.getArchitecture()); + } + + public Collection<ArduinoPlatform> getAvailablePlatforms() throws CoreException { + initInstalledPlatforms(); + Map<String, ArduinoPlatform> platformMap = new HashMap<>(); for (ArduinoPlatform platform : platforms) { - if (platform.getName().equals(name)) { - if (foundPlatform == null) { - foundPlatform = platform; - } else { - if (platform.isInstalled() - && ArduinoManager.compareVersions(platform.getVersion(), foundPlatform.getVersion()) > 0) { - foundPlatform = platform; - } + if (!installedPlatforms.containsKey(platform.getArchitecture())) { + ArduinoPlatform p = platformMap.get(platform.getName()); + if (p == null || ArduinoManager.compareVersions(platform.getVersion(), p.getVersion()) > 0) { + platformMap.put(platform.getName(), platform); } } } - return foundPlatform; + return platformMap.values(); } public List<ArduinoTool> getTools() { diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java index 55eaddf405a..3e85fa1b87a 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java @@ -37,9 +37,11 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; public class ArduinoPlatform { + // JSON fields private String name; private String architecture; private String version; @@ -50,6 +52,7 @@ public class ArduinoPlatform { private String size; private List<ArduinoBoard> boards; private List<ToolDependency> toolsDependencies; + // end JSON fields private ArduinoPackage pkg; private HierarchicalProperties boardsProperties; @@ -57,13 +60,13 @@ public class ArduinoPlatform { private Map<String, String> menus = new HashMap<>(); private Map<String, ArduinoLibrary> libraries; - void setOwner(ArduinoPackage pkg) { + void init(ArduinoPackage pkg) { this.pkg = pkg; + for (ArduinoBoard board : boards) { - board.setOwners(this); - } - for (ToolDependency toolDep : toolsDependencies) { - toolDep.setOwner(this); + if (board != null) { + board.setOwners(this); + } } } @@ -103,33 +106,39 @@ public class ArduinoPlatform { return size; } + public void setPlatformProperties(Properties platformProperties) { + this.platformProperties = platformProperties; + } + public List<ArduinoBoard> getBoards() { - if (isInstalled() && boardsProperties == null) { + if (boardsProperties == null) { Properties boardProps = new Properties(); - try (InputStream is = new FileInputStream(getInstallPath().resolve("boards.txt").toFile()); //$NON-NLS-1$ - Reader reader = new InputStreamReader(is, "UTF-8")) { //$NON-NLS-1$ - boardProps.load(reader); - } catch (IOException e) { - Activator.log(e); - } + if (Files.exists(getInstallPath())) { + try (InputStream is = new FileInputStream(getInstallPath().resolve("boards.txt").toFile()); //$NON-NLS-1$ + Reader reader = new InputStreamReader(is, "UTF-8")) { //$NON-NLS-1$ + boardProps.load(reader); + } catch (IOException e) { + Activator.log(e); + } - boardsProperties = new HierarchicalProperties(boardProps); + boardsProperties = new HierarchicalProperties(boardProps); - // Replace the boards with a real ones - boards = new ArrayList<>(); - for (Map.Entry<String, HierarchicalProperties> entry : boardsProperties.getChildren().entrySet()) { - if (entry.getValue().getChild("name") != null) { //$NON-NLS-1$ - // assume things with names are boards - boards.add(new ArduinoBoard(entry.getKey(), entry.getValue()).setOwners(this)); + // Replace the boards with a real ones + boards = new ArrayList<>(); + for (Map.Entry<String, HierarchicalProperties> entry : boardsProperties.getChildren().entrySet()) { + if (entry.getValue().getChild("name") != null) { //$NON-NLS-1$ + // assume things with names are boards + boards.add(new ArduinoBoard(entry.getKey(), entry.getValue()).setOwners(this)); + } } - } - // Build the menu - HierarchicalProperties menuProp = boardsProperties.getChild("menu"); //$NON-NLS-1$ - if (menuProp != null) { - for (Map.Entry<String, HierarchicalProperties> entry : menuProp.getChildren().entrySet()) { - menus.put(entry.getKey(), entry.getValue().getValue()); + // Build the menu + HierarchicalProperties menuProp = boardsProperties.getChild("menu"); //$NON-NLS-1$ + if (menuProp != null) { + for (Map.Entry<String, HierarchicalProperties> entry : menuProp.getChildren().entrySet()) { + menus.put(entry.getKey(), entry.getValue().getValue()); + } } } } @@ -140,7 +149,16 @@ public class ArduinoPlatform { return boardsProperties; } - public ArduinoBoard getBoard(String name) throws CoreException { + public ArduinoBoard getBoard(String id) throws CoreException { + for (ArduinoBoard board : getBoards()) { + if (id.equals(board.getId())) { + return board; + } + } + return null; + } + + public ArduinoBoard getBoardByName(String name) throws CoreException { for (ArduinoBoard board : getBoards()) { if (name.equals(board.getName())) { return board; @@ -187,32 +205,8 @@ public class ArduinoPlatform { return platformProperties; } - public boolean isInstalled() { - return getInstallPath().resolve("boards.txt").toFile().exists(); //$NON-NLS-1$ - } - public Path getInstallPath() { - // TODO remove migration in Neon - Path oldPath = ArduinoPreferences.getArduinoHome().resolve("hardware").resolve(pkg.getName()) //$NON-NLS-1$ - .resolve(architecture).resolve(version); - Path newPath = getPackage().getInstallPath().resolve("hardware").resolve(pkg.getName()).resolve(architecture) //$NON-NLS-1$ - .resolve(version); - if (Files.exists(oldPath)) { - try { - Files.createDirectories(newPath.getParent()); - Files.move(oldPath, newPath); - for (Path parent = oldPath.getParent(); parent != null; parent = parent.getParent()) { - if (Files.newDirectoryStream(parent).iterator().hasNext()) { - break; - } else { - Files.delete(parent); - } - } - } catch (IOException e) { - Activator.log(e); - } - } - return newPath; + return getPackage().getInstallPath().resolve("hardware").resolve(architecture); //$NON-NLS-1$ } public List<Path> getIncludePath() { @@ -249,18 +243,17 @@ public class ArduinoPlatform { } private void initLibraries() throws CoreException { - libraries = new HashMap<>(); - File[] libraryDirs = getInstallPath().resolve("libraries").toFile().listFiles(); //$NON-NLS-1$ - if (libraryDirs != null) { - for (File libraryDir : libraryDirs) { - Path propsPath = libraryDir.toPath().resolve("library.properties"); //$NON-NLS-1$ - if (propsPath.toFile().exists()) { - try { - ArduinoLibrary lib = new ArduinoLibrary(propsPath); - libraries.put(lib.getName(), lib); - } catch (IOException e) { - throw new CoreException( - new Status(IStatus.ERROR, Activator.getId(), "Loading " + propsPath, e)); //$NON-NLS-1$ + if (libraries == null) { + libraries = new HashMap<>(); + if (Files.exists(getInstallPath())) { + File[] libraryDirs = getInstallPath().resolve("libraries").toFile().listFiles(); //$NON-NLS-1$ + if (libraryDirs != null) { + for (File libraryDir : libraryDirs) { + Path propsPath = libraryDir.toPath().resolve("library.properties"); //$NON-NLS-1$ + if (propsPath.toFile().exists()) { + ArduinoLibrary lib = new ArduinoLibrary(propsPath, this); + libraries.put(lib.getName(), lib); + } } } } @@ -268,24 +261,35 @@ public class ArduinoPlatform { } public synchronized Collection<ArduinoLibrary> getLibraries() throws CoreException { - if (libraries == null && isInstalled()) { - initLibraries(); - } + initLibraries(); return libraries.values(); } public synchronized ArduinoLibrary getLibrary(String name) throws CoreException { - if (libraries == null && isInstalled()) { - initLibraries(); - } + initLibraries(); return libraries != null ? libraries.get(name) : null; } - public IStatus install(IProgressMonitor monitor) { + public void install(IProgressMonitor monitor) throws CoreException { + int work = 1 + toolsDependencies.size(); + + boolean exists = Files.exists(getInstallPath()); + if (exists) + work++; + + Path makePath = ArduinoPreferences.getArduinoHome().resolve("make.exe"); //$NON-NLS-1$ + boolean needMake = Platform.getOS().equals(Platform.OS_WIN32) && !Files.exists(makePath); + if (needMake) + work++; + + SubMonitor sub = SubMonitor.convert(monitor, work); + // Check if we're installed already - if (isInstalled()) { + if (exists) { try { + sub.setTaskName(String.format("Removing old package %s", getName())); ArduinoManager.recursiveDelete(getInstallPath()); + sub.worked(1); } catch (IOException e) { // just log it, shouldn't break the install Activator.log(e); @@ -294,39 +298,41 @@ public class ArduinoPlatform { // Install the tools for (ToolDependency toolDep : toolsDependencies) { - IStatus status = toolDep.install(monitor); - if (!status.isOK()) { - return status; - } + sub.setTaskName(String.format("Installing tool %s", toolDep.getName())); + toolDep.install(monitor); + sub.worked(1); } // On Windows install make from bintray - if (Platform.getOS().equals(Platform.OS_WIN32)) { + if (needMake) { try { - Path makePath = ArduinoPreferences.getArduinoHome().resolve("make.exe"); //$NON-NLS-1$ - if (!makePath.toFile().exists()) { - Files.createDirectories(makePath.getParent()); - URL makeUrl = new URL("https://bintray.com/artifact/download/cdtdoug/tools/make.exe"); //$NON-NLS-1$ - Files.copy(makeUrl.openStream(), makePath); - makePath.toFile().setExecutable(true, false); - } + sub.setTaskName("Installing make"); + Files.createDirectories(makePath.getParent()); + URL makeUrl = new URL("https://bintray.com/artifact/download/cdtdoug/tools/make.exe"); //$NON-NLS-1$ + Files.copy(makeUrl.openStream(), makePath); + makePath.toFile().setExecutable(true, false); + sub.worked(1); } catch (IOException e) { - return new Status(IStatus.ERROR, Activator.getId(), Messages.ArduinoPlatform_0, e); + throw Activator.coreException(e); } } // Download platform archive - IStatus status = ArduinoManager.downloadAndInstall(url, archiveFileName, getInstallPath(), monitor); - if (!status.isOK()) { - return status; + sub.setTaskName(String.format("Downloading and installing %s", getName())); + try { + ArduinoManager.downloadAndInstall(url, archiveFileName, getInstallPath(), monitor); + } catch (IOException e) { + throw Activator.coreException(e); } + sub.done(); - return Status.OK_STATUS; + pkg.platformInstalled(this); } public IStatus uninstall(IProgressMonitor monitor) { try { ArduinoManager.recursiveDelete(getInstallPath()); + pkg.platformUninstalled(this); // TODO delete tools that aren't needed any more return Status.OK_STATUS; } catch (IOException e) { @@ -335,6 +341,40 @@ public class ArduinoPlatform { } @Override + public String toString() { + return name; + } + + private String fixText(String text) { + String fixed = text.replaceAll("&", "&"); //$NON-NLS-1$ //$NON-NLS-2$ + fixed = fixed.replaceAll("<", ">"); //$NON-NLS-1$ //$NON-NLS-2$ + fixed = fixed.replaceAll("<", "<"); //$NON-NLS-1$ //$NON-NLS-2$ + return fixed; + } + + public String toFormText() { + StringBuilder text = new StringBuilder(); + + text.append("<form>"); //$NON-NLS-1$ + text.append(String.format("<p><b>%s: %s</b></p>", "Package", getName())); //$NON-NLS-1$ + text.append(String.format("<p>%s: %s</p>", "Maintainer", fixText(getPackage().getMaintainer()))); //$NON-NLS-1$ + + ArduinoHelp help = getPackage().getHelp(); + if (help != null && help.getOnline() != null) { + text.append(String.format("<p><a href=\"%s\">%s</a></p>", help.getOnline(), "Online help")); //$NON-NLS-1$ + } + + text.append(String.format("<p>%s:</p>", "Supported boards")); //$NON-NLS-1$ + for (ArduinoBoard board : getBoards()) { + text.append(String.format("<li>%s</li>", fixText(board.getName()))); //$NON-NLS-1$ + } + + text.append("</form>"); //$NON-NLS-1$ + + return text.toString(); + } + + @Override public int hashCode() { final int prime = 31; int result = 1; diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoTool.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoTool.java index 5361b1d7727..c3a9bf42af2 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoTool.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoTool.java @@ -16,6 +16,7 @@ import java.util.Properties; import org.eclipse.cdt.arduino.core.internal.Activator; import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences; import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; @@ -28,13 +29,6 @@ public class ArduinoTool { private transient ArduinoPackage pkg; - public void setOwner(ArduinoPackage pkg) { - this.pkg = pkg; - for (ArduinoToolSystem system : systems) { - system.setOwner(this); - } - } - public ArduinoPackage getPackage() { return pkg; } @@ -51,6 +45,13 @@ public class ArduinoTool { return systems; } + void init(ArduinoPackage pkg) { + this.pkg = pkg; + for (ArduinoToolSystem system : systems) { + system.setOwner(this); + } + } + public Path getInstallPath() { // TODO remove migration in Neon Path oldPath = ArduinoPreferences.getArduinoHome().resolve("tools").resolve(pkg.getName()).resolve(name) //$NON-NLS-1$ @@ -78,24 +79,25 @@ public class ArduinoTool { return getInstallPath().toFile().exists(); } - public IStatus install(IProgressMonitor monitor) { + public void install(IProgressMonitor monitor) throws CoreException { if (isInstalled()) { - return Status.OK_STATUS; + return; } for (ArduinoToolSystem system : systems) { if (system.isApplicable()) { - return system.install(monitor); + system.install(monitor); } } // No valid system - return new Status(IStatus.ERROR, Activator.getId(), "No valid system found for " + name); //$NON-NLS-1$ + throw new CoreException( + new Status(IStatus.ERROR, Activator.getId(), String.format("No valid system found for %s", name))); //$NON-NLS-1$ } public Properties getToolProperties() { Properties properties = new Properties(); - properties.put("runtime.tools." + name + ".path", ArduinoBuildConfiguration.pathString(getInstallPath())); //$NON-NLS-1$ //$NON-NLS-1$//$NON-NLS-2$ + properties.put("runtime.tools." + name + ".path", ArduinoBuildConfiguration.pathString(getInstallPath())); //$NON-NLS-1$//$NON-NLS-2$ properties.put("runtime.tools." + name + '-' + version + ".path", //$NON-NLS-1$//$NON-NLS-2$ ArduinoBuildConfiguration.pathString(getInstallPath())); //$NON-NLS-1$ return properties; diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoToolSystem.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoToolSystem.java index 7fa5b1b20f0..cf457af06ff 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoToolSystem.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoToolSystem.java @@ -7,8 +7,11 @@ *******************************************************************************/ package org.eclipse.cdt.arduino.core.internal.board; +import java.io.IOException; + +import org.eclipse.cdt.arduino.core.internal.Activator; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; public class ArduinoToolSystem { @@ -83,8 +86,12 @@ public class ArduinoToolSystem { } } - public IStatus install(IProgressMonitor monitor) { - return ArduinoManager.downloadAndInstall(url, archiveFileName, tool.getInstallPath(), monitor); + public void install(IProgressMonitor monitor) throws CoreException { + try { + ArduinoManager.downloadAndInstall(url, archiveFileName, tool.getInstallPath(), monitor); + } catch (IOException e) { + throw Activator.coreException(e); + } } } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/LibraryIndex.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/LibraryIndex.java index 6643f0292b9..e6551672d48 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/LibraryIndex.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/LibraryIndex.java @@ -7,72 +7,14 @@ *******************************************************************************/ package org.eclipse.cdt.arduino.core.internal.board; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; public class LibraryIndex { private List<ArduinoLibrary> libraries; - public static final String UNCATEGORIZED = "Uncategorized"; //$NON-NLS-1$ - // category name to library name - private Map<String, Set<String>> categories = new HashMap<>(); - // library name to latest version of library - private Map<String, ArduinoLibrary> latestLibs = new HashMap<>(); - - public void resolve() throws IOException { - for (ArduinoLibrary library : libraries) { - String name = library.getName(); - - String category = library.getCategory(); - if (category == null) { - category = UNCATEGORIZED; - } - - Set<String> categoryLibs = categories.get(category); - if (categoryLibs == null) { - categoryLibs = new HashSet<>(); - categories.put(category, categoryLibs); - } - categoryLibs.add(name); - - ArduinoLibrary current = latestLibs.get(name); - if (current != null) { - if (ArduinoManager.compareVersions(library.getVersion(), current.getVersion()) > 0) { - latestLibs.put(name, library); - } - } else { - latestLibs.put(name, library); - } - } - } - - public ArduinoLibrary getLibrary(String name) { - return latestLibs.get(name); - } - - public Collection<String> getCategories() { - return Collections.unmodifiableCollection(categories.keySet()); - } - - public Collection<ArduinoLibrary> getLibraries(String category) { - Set<String> categoryLibs = categories.get(category); - if (categoryLibs == null) { - return new ArrayList<>(0); - } - - List<ArduinoLibrary> libs = new ArrayList<>(categoryLibs.size()); - for (String name : categoryLibs) { - libs.add(latestLibs.get(name)); - } - return libs; + public List<ArduinoLibrary> getLibraries() { + return libraries; } } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/PackageIndex.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/PackageIndex.java index 9a1abc96c8b..4ad0157a512 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/PackageIndex.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/PackageIndex.java @@ -7,29 +7,15 @@ *******************************************************************************/ package org.eclipse.cdt.arduino.core.internal.board; +import java.util.Collection; import java.util.List; public class PackageIndex { private List<ArduinoPackage> packages; - public List<ArduinoPackage> getPackages() { + public Collection<ArduinoPackage> getPackages() { return packages; } - public ArduinoPackage getPackage(String packageName) { - for (ArduinoPackage pkg : packages) { - if (pkg.getName().equals(packageName)) { - return pkg; - } - } - return null; - } - - void setOwners(ArduinoManager manager) { - for (ArduinoPackage pkg : packages) { - pkg.setOwner(manager); - } - } - } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ToolDependency.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ToolDependency.java index 8bd1ef3635d..ac9f5c0dff0 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ToolDependency.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ToolDependency.java @@ -19,12 +19,6 @@ public class ToolDependency { private String name; private String version; - private transient ArduinoPlatform platform; - - public void setOwner(ArduinoPlatform platform) { - this.platform = platform; - } - public String getPackager() { return packager; } @@ -38,25 +32,16 @@ public class ToolDependency { } public ArduinoTool getTool() throws CoreException { - ArduinoPackage pkg = platform.getPackage(); - if (!pkg.getName().equals(packager)) { - pkg = pkg.getManager().getPackage(packager); - } - - return pkg.getTool(name, version); + return Activator.getService(ArduinoManager.class).getTool(packager, name, version); } - public IStatus install(IProgressMonitor monitor) { - try { - ArduinoTool tool = getTool(); - if (tool == null) { - return new Status(IStatus.ERROR, Activator.getId(), - String.format("Tool not found %s %s", name, version)); - } - return getTool().install(monitor); - } catch (CoreException e) { - return e.getStatus(); + public void install(IProgressMonitor monitor) throws CoreException { + ArduinoTool tool = getTool(); + if (tool == null) { + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), + String.format("Tool not found %s %s", name, version))); } + getTool().install(monitor); } } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java index 6ef03d51bd5..39af24d8fd0 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java @@ -98,15 +98,15 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te String packageName = settings.get(PACKAGE_NAME, ""); //$NON-NLS-1$ String platformName = settings.get(PLATFORM_NAME, ""); //$NON-NLS-1$ String boardName = settings.get(BOARD_NAME, ""); //$NON-NLS-1$ - ArduinoBoard b = manager.getBoard(boardName, platformName, packageName); + ArduinoBoard b = manager.getBoard(packageName, platformName, boardName); if (b == null) { // Default to Uno or first one we find b = manager.getBoard("Arduino/Genuino Uno", "Arduino AVR Boards", "arduino"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ if (b == null) { - List<ArduinoBoard> boards = manager.getInstalledBoards(); + Collection<ArduinoBoard> boards = manager.getInstalledBoards(); if (!boards.isEmpty()) { - b = boards.get(0); + b = boards.iterator().next(); } } } @@ -116,7 +116,8 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te this.launchMode = name.substring(i + 1); } - ArduinoBuildConfiguration(IBuildConfiguration config, String name, ArduinoBoard board, String launchMode, IToolChain toolChain) + ArduinoBuildConfiguration(IBuildConfiguration config, String name, ArduinoBoard board, String launchMode, + IToolChain toolChain) throws CoreException { super(config, name, toolChain); this.board = board; diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfigurationProvider.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfigurationProvider.java index ead1a26531f..0dfda4599c2 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfigurationProvider.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfigurationProvider.java @@ -7,7 +7,7 @@ *******************************************************************************/ package org.eclipse.cdt.arduino.core.internal.build; -import java.util.List; +import java.util.Collection; import org.eclipse.cdt.arduino.core.internal.Activator; import org.eclipse.cdt.arduino.core.internal.board.ArduinoBoard; @@ -44,11 +44,11 @@ public class ArduinoBuildConfigurationProvider implements ICBuildConfigurationPr @Override public ICBuildConfiguration getDefaultCBuildConfiguration(IProject project) throws CoreException { - ArduinoBoard board = arduinoManager.getBoard("Arduino/Genuino Uno", "Arduino AVR Boards", "arduino"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + ArduinoBoard board = arduinoManager.getBoard("arduino", "avr", "Arduino/Genuino Uno"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ if (board == null) { - List<ArduinoBoard> boards = arduinoManager.getInstalledBoards(); + Collection<ArduinoBoard> boards = arduinoManager.getInstalledBoards(); if (!boards.isEmpty()) { - board = boards.get(0); + board = boards.iterator().next(); } } if (board != null) { @@ -112,7 +112,8 @@ public class ArduinoBuildConfigurationProvider implements ICBuildConfigurationPr IToolChainProvider provider = toolChainManager.getProvider(ArduinoToolChainProvider.ID); IToolChain toolChain = new ArduinoToolChain(provider, config); toolChainManager.addToolChain(toolChain); - ArduinoBuildConfiguration arduinoConfig = new ArduinoBuildConfiguration(config, configName, target, launchMode, toolChain); + ArduinoBuildConfiguration arduinoConfig = new ArduinoBuildConfiguration(config, configName, target, launchMode, + toolChain); configManager.addBuildConfiguration(config, arduinoConfig); return arduinoConfig; } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java index f66344b7fef..380ec26be88 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java @@ -95,14 +95,15 @@ public class ArduinoRemoteConnection } public ArduinoBoard getBoard() throws CoreException { - return Activator.getService(ArduinoManager.class).getBoard(remoteConnection.getAttribute(BOARD_NAME), - remoteConnection.getAttribute(PLATFORM_NAME), remoteConnection.getAttribute(PACKAGE_NAME)); + return Activator.getService(ArduinoManager.class).getBoard(remoteConnection.getAttribute(PACKAGE_NAME), + remoteConnection.getAttribute(PLATFORM_NAME), remoteConnection.getAttribute(BOARD_NAME)); } public String getPortName() { return remoteConnection.getAttribute(PORT_NAME); } + @Override public IRemoteProcess getCommandShell(int flags) throws IOException { if (serialPort != null && serialPort.isOpen()) { // can only have one open at a time |