Boards Manager: downloading additional files as specified in preference 'boardsmanager.additional.urls'

This commit is contained in:
Federico Fissore 2015-04-30 14:02:10 +02:00
parent 0292d8b30f
commit ecf432fadc
6 changed files with 104 additions and 37 deletions

View File

@ -149,6 +149,8 @@ public class ContributionManagerUI extends InstallerJDialog {
try { try {
setProgressVisible(true, ""); setProgressVisible(true, "");
installer.updateIndex(); installer.updateIndex();
List<String> downloadedPackageIndexFiles = installer.updateIndex();
installer.deleteUnknownFiles(downloadedPackageIndexFiles);
onIndexesUpdated(); onIndexesUpdated();
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);

View File

@ -322,7 +322,8 @@ public class Base {
lastStatus = progress.getStatus(); lastStatus = progress.getStatus();
} }
}; };
installer.updateIndex(); List<String> downloadedPackageIndexFiles = installer.updateIndex();
installer.deleteUnknownFiles(downloadedPackageIndexFiles);
indexer.parseIndex(); indexer.parseIndex();
indexer.syncWithFilesystem(getHardwareFolder()); indexer.syncWithFilesystem(getHardwareFolder());

View File

@ -0,0 +1,23 @@
package cc.arduino.contributions.packages;
import java.util.Arrays;
import java.util.List;
public class Constants {
public static final String DEFAULT_INDEX_FILE_NAME = "package_index.json";
public static final List<String> PROTECTED_PACKAGE_NAMES = Arrays.asList("arduino", "Intel");
public static final String PACKAGE_INDEX_URL;
public static final String PREFERENCES_BOARDS_MANAGER_ADDITIONAL_URLS = "boardsmanager.additional.urls";
static {
String extenalPackageIndexUrl = System.getProperty("PACKAGE_INDEX_URL");
if (extenalPackageIndexUrl != null && !"".equals(extenalPackageIndexUrl)) {
PACKAGE_INDEX_URL = extenalPackageIndexUrl;
} else {
PACKAGE_INDEX_URL = "http://downloads.arduino.cc/packages/package_index.json";
}
}
}

View File

@ -28,6 +28,7 @@
*/ */
package cc.arduino.contributions.packages; package cc.arduino.contributions.packages;
import cc.arduino.contributions.GPGDetachedSignatureVerifier;
import cc.arduino.utils.ArchiveExtractor; import cc.arduino.utils.ArchiveExtractor;
import cc.arduino.utils.MultiStepProgress; import cc.arduino.utils.MultiStepProgress;
import cc.arduino.utils.Progress; import cc.arduino.utils.Progress;
@ -36,6 +37,8 @@ import com.google.common.collect.Collections2;
import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.Executor; import org.apache.commons.exec.Executor;
import processing.app.BaseNoGui; import processing.app.BaseNoGui;
import processing.app.I18n;
import processing.app.PreferencesData;
import processing.app.helpers.FileUtils; import processing.app.helpers.FileUtils;
import processing.app.helpers.filefilters.OnlyDirs; import processing.app.helpers.filefilters.OnlyDirs;
import processing.app.tools.CollectStdOutStdErrExecutor; import processing.app.tools.CollectStdOutStdErrExecutor;
@ -44,27 +47,13 @@ import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.Collection; import java.util.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import static processing.app.I18n._; import static processing.app.I18n._;
import static processing.app.I18n.format; import static processing.app.I18n.format;
public class ContributionInstaller { public class ContributionInstaller {
private static final String PACKAGE_INDEX_URL;
static {
String extenalPackageIndexUrl = System.getProperty("PACKAGE_INDEX_URL");
if (extenalPackageIndexUrl != null && !"".equals(extenalPackageIndexUrl)) {
PACKAGE_INDEX_URL = extenalPackageIndexUrl;
} else {
PACKAGE_INDEX_URL = "http://downloads.arduino.cc/packages/package_index.json";
}
}
private final ContributionsIndexer indexer; private final ContributionsIndexer indexer;
private final DownloadableContributionsDownloader downloader; private final DownloadableContributionsDownloader downloader;
@ -239,22 +228,46 @@ public class ContributionInstaller {
} }
public List<String> updateIndex() throws Exception { public List<String> updateIndex() throws Exception {
List<String> errors = new LinkedList<String>();
MultiStepProgress progress = new MultiStepProgress(1); MultiStepProgress progress = new MultiStepProgress(1);
downloadIndex(progress, PACKAGE_INDEX_URL); List<String> downloadedPackageIndexFilesAccumulator = new LinkedList<String>();
try { downloadIndexAndSignature(progress, downloadedPackageIndexFilesAccumulator, Constants.PACKAGE_INDEX_URL);
downloadIndex(progress, PACKAGE_INDEX_URL + ".sig");
} catch (Exception e) { Set<String> packageIndexURLs = new HashSet<String>();
//ignore errors String additionalURLs = PreferencesData.get(Constants.PREFERENCES_BOARDS_MANAGER_ADDITIONAL_URLS, "");
if (!"".equals(additionalURLs)) {
packageIndexURLs.addAll(Arrays.asList(additionalURLs.split(",")));
}
for (String packageIndexURL : packageIndexURLs) {
downloadIndexAndSignature(progress, downloadedPackageIndexFilesAccumulator, packageIndexURL);
} }
progress.stepDone(); progress.stepDone();
return errors; return downloadedPackageIndexFilesAccumulator;
} }
private void downloadIndex(MultiStepProgress progress, String packageIndexUrl) throws Exception { private void downloadIndexAndSignature(MultiStepProgress progress, List<String> downloadedPackagedIndexFilesAccumulator, String packageIndexUrl) throws Exception {
File packageIndex = downloadIndex(progress, packageIndexUrl);
downloadedPackagedIndexFilesAccumulator.add(packageIndex.getName());
try {
File packageIndexSignature = downloadIndex(progress, packageIndexUrl + ".sig");
boolean signatureVerified = new GPGDetachedSignatureVerifier().verify(packageIndex, packageIndexSignature, new File(BaseNoGui.getContentFile("lib"), "public.gpg.key"));
if (signatureVerified) {
downloadedPackagedIndexFilesAccumulator.add(packageIndexSignature.getName());
} else {
downloadedPackagedIndexFilesAccumulator.remove(packageIndex.getName());
packageIndex.delete();
packageIndexSignature.delete();
System.err.println(I18n.format(_("{0} file signature verification failed. File ignored."), packageIndexUrl));
}
} catch (Exception e) {
//ignore errors
}
}
private File downloadIndex(MultiStepProgress progress, String packageIndexUrl) throws Exception {
String statusText = _("Downloading platforms index..."); String statusText = _("Downloading platforms index...");
URL url = new URL(packageIndexUrl); URL url = new URL(packageIndexUrl);
String[] urlPathParts = url.getFile().split("/"); String[] urlPathParts = url.getFile().split("/");
@ -269,9 +282,24 @@ public class ContributionInstaller {
if (!tmpFile.renameTo(outputFile)) { if (!tmpFile.renameTo(outputFile)) {
throw new Exception("An error occurred while updating platforms index!"); throw new Exception("An error occurred while updating platforms index!");
} }
return outputFile;
} }
protected void onProgress(Progress progress) { protected void onProgress(Progress progress) {
// Empty // Empty
} }
public void deleteUnknownFiles(List<String> downloadedPackageIndexFiles) {
File preferencesFolder = indexer.getIndexFile(".").getParentFile();
File[] additionalPackageIndexFiles = preferencesFolder.listFiles(new PackageIndexFilenameFilter(Constants.DEFAULT_INDEX_FILE_NAME));
if (additionalPackageIndexFiles == null) {
return;
}
for (File additionalPackageIndexFile : additionalPackageIndexFiles) {
if (!downloadedPackageIndexFiles.contains(additionalPackageIndexFile.getName())) {
additionalPackageIndexFile.delete();
}
}
}
} }

View File

@ -47,16 +47,16 @@ import processing.app.debug.TargetPlatform;
import processing.app.debug.TargetPlatformException; import processing.app.debug.TargetPlatformException;
import processing.app.helpers.PreferencesMap; import processing.app.helpers.PreferencesMap;
import java.io.*; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*; import java.util.*;
import static processing.app.helpers.filefilters.OnlyDirs.ONLY_DIRS; import static processing.app.helpers.filefilters.OnlyDirs.ONLY_DIRS;
public class ContributionsIndexer { public class ContributionsIndexer {
private static final String DEFAULT_INDEX_FILE_NAME = "package_index.json";
private static final List<String> PROTECTED_PACKAGE_NAMES = Arrays.asList("arduino", "Intel");
private final File packagesFolder; private final File packagesFolder;
private final File stagingFolder; private final File stagingFolder;
private final File preferencesFolder; private final File preferencesFolder;
@ -69,18 +69,13 @@ public class ContributionsIndexer {
} }
public void parseIndex() throws Exception { public void parseIndex() throws Exception {
File defaultIndexFile = getIndexFile(DEFAULT_INDEX_FILE_NAME); File defaultIndexFile = getIndexFile(Constants.DEFAULT_INDEX_FILE_NAME);
if (!isSigned(defaultIndexFile)) { if (!isSigned(defaultIndexFile)) {
throw new SignatureVerificationFailedException(DEFAULT_INDEX_FILE_NAME); throw new SignatureVerificationFailedException(Constants.DEFAULT_INDEX_FILE_NAME);
} }
index = parseIndex(defaultIndexFile); index = parseIndex(defaultIndexFile);
File[] indexFiles = preferencesFolder.listFiles(new FilenameFilter() { File[] indexFiles = preferencesFolder.listFiles(new PackageIndexFilenameFilter(Constants.DEFAULT_INDEX_FILE_NAME));
@Override
public boolean accept(File file, String name) {
return !DEFAULT_INDEX_FILE_NAME.equals(name) && name.startsWith("package_") && name.endsWith("_index.json");
}
});
for (File indexFile : indexFiles) { for (File indexFile : indexFiles) {
ContributionsIndex contributionsIndex = parseIndex(indexFile); ContributionsIndex contributionsIndex = parseIndex(indexFile);
@ -137,7 +132,7 @@ public class ContributionsIndexer {
} }
private boolean mergeAllowed(ContributedPackage contributedPackage, File indexFile) { private boolean mergeAllowed(ContributedPackage contributedPackage, File indexFile) {
return !PROTECTED_PACKAGE_NAMES.contains(contributedPackage.getName()) || isSigned(indexFile); return !Constants.PROTECTED_PACKAGE_NAMES.contains(contributedPackage.getName()) || isSigned(indexFile);
} }
private boolean isSigned(File indexFile) { private boolean isSigned(File indexFile) {

View File

@ -0,0 +1,18 @@
package cc.arduino.contributions.packages;
import java.io.File;
import java.io.FilenameFilter;
public class PackageIndexFilenameFilter implements FilenameFilter {
private final String defaultPackageIndexFileName;
public PackageIndexFilenameFilter(String defaultPackageIndexFileName) {
this.defaultPackageIndexFileName = defaultPackageIndexFileName;
}
@Override
public boolean accept(File file, String name) {
return !defaultPackageIndexFileName.equals(name) && name.startsWith("package_") && name.endsWith("_index.json");
}
}