/******************************************************************************* * Copyright (c) 2015 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * QNX Software Systems - Initial API and implementation * Jan Baeyens integrated in and extended for the arduino eclipse plugin named Sloeber *******************************************************************************/ package io.sloeber.core.managers; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import org.eclipse.core.runtime.IPath; 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.ui.statushandlers.StatusManager; import com.google.gson.Gson; import io.sloeber.core.Activator; import io.sloeber.core.api.Defaults; import io.sloeber.core.api.LibraryManager; import io.sloeber.core.common.Common; import io.sloeber.core.common.ConfigurationPreferences; import io.sloeber.core.tools.MyMultiStatus; public class Manager { static private List<PackageIndex> packageIndices; private static boolean myIsReady = false; public static boolean isReady() { return myIsReady; } private Manager() { } public static void addJsonURLs(HashSet<String> jsonUrlsToAdd, boolean forceDownload) { HashSet<String> originalJsonUrls = new HashSet<>(Arrays.asList(ConfigurationPreferences.getJsonURLList())); jsonUrlsToAdd.addAll(originalJsonUrls); ConfigurationPreferences.setJsonURLs(jsonUrlsToAdd); loadJsons(forceDownload); } /** * Loads all stuff needed and if this is the first time downloads the avr * boards and needed tools * * @param monitor */ public static void startup_Pluging(IProgressMonitor monitor) { loadJsons(ConfigurationPreferences.getUpdateJasonFilesFlag()); List<Board> allBoards = getInstalledBoards(); if (allBoards.isEmpty()) { // If boards are installed do nothing LibraryManager.InstallDefaultLibraries(monitor); MyMultiStatus mstatus = new MyMultiStatus("Failed to configer Sloeber"); //$NON-NLS-1$ // Download sample programs mstatus.addErrors(downloadAndInstall(Defaults.EXAMPLES_URL, Defaults.EXAMPLE_PACKAGE, Paths.get(ConfigurationPreferences.getInstallationPathExamples().toString()), false, monitor)); if (mstatus.isOK()) { // if successfully installed the examples: add the boards Package pkg = getPackageIndices().get(0).getPackages().get(0); if (pkg != null) { ArduinoPlatform platform = pkg.getLatestPlatform(Defaults.PLATFORM_NAME); if (platform == null) { ArduinoPlatform[] platformList = new ArduinoPlatform[pkg.getLatestPlatforms().size()]; pkg.getLatestPlatforms().toArray(platformList); platform = platformList[0]; } if (platform != null) { mstatus.addErrors(downloadAndInstall(platform, false, monitor)); } } } if (!mstatus.isOK()) { StatusManager stMan = StatusManager.getManager(); stMan.handle(mstatus, StatusManager.LOG | StatusManager.SHOW | StatusManager.BLOCK); } } myIsReady = true; } /** * Given a platform description in a json file download and install all * needed stuff. All stuff is including all tools and core files and * hardware specific libraries. That is (on windows) inclusive the make.exe * * @param platform * @param monitor * @param object * @return */ static public IStatus downloadAndInstall(ArduinoPlatform platform, boolean forceDownload, IProgressMonitor monitor) { MyMultiStatus mstatus = new MyMultiStatus("Failed to install " + platform.getName()); //$NON-NLS-1$ mstatus.addErrors(downloadAndInstall(platform.getUrl(), platform.getArchiveFileName(), platform.getInstallPath(), forceDownload, monitor)); if (!mstatus.isOK()) { // no use going on installing tools if the boards failed installing return mstatus; } if (platform.getToolsDependencies() != null) { for (ToolDependency tool : platform.getToolsDependencies()) { monitor.setTaskName(InstallProgress.getRandomMessage()); mstatus.addErrors(tool.install(monitor)); } } // On Windows install make if (Platform.getOS().equals(Platform.OS_WIN32)) { Path localMakePath = Paths.get(ConfigurationPreferences.getMakePath().toString()); if (!ConfigurationPreferences.getMakePath().append("make.exe").toFile().exists()) { //$NON-NLS-1$ mstatus.addErrors( downloadAndInstall("http://eclipse.baeyens.it/download/make.zip", "make.zip", localMakePath, //$NON-NLS-1$ //$NON-NLS-2$ forceDownload, monitor)); } } return mstatus; } static private void loadJsons(boolean forceDownload) { packageIndices = new ArrayList<>(); LibraryManager.flushIndices(); String[] jsonUrls = ConfigurationPreferences.getJsonURLList(); for (String jsonUrl : jsonUrls) { loadJson(jsonUrl, forceDownload); } } /** * convert a web url to a local file name. The local file name is the cache * of the web * * @param url * url of the file we want a local cache * @return the file that represents the file that is the local cache. the * file itself may not exists. If the url is malformed return null; * @throws MalformedURLException */ public static File getLocalFileName(String url) { URL packageUrl; try { packageUrl = new URL(url.trim()); } catch (MalformedURLException e) { Common.log(new Status(IStatus.ERROR, Activator.getId(), "Malformed url " + url, e)); //$NON-NLS-1$ return null; } String localFileName = Paths.get(packageUrl.getPath()).getFileName().toString(); Path packagePath = Paths.get(ConfigurationPreferences.getInstallationPath().append(localFileName).toString()); return packagePath.toFile(); } /** * convert a local file name to a baeyens it alternative download name There * is no check wether the file exists only a conversion * * @param url * url of the file we want a local * @return the file that represents the file on Baeyens.it */ private static String getBaeyensItAlternativeDownload(String localFileName) { return "http://eclipse.baeyens.it/download/" + localFileName; //$NON-NLS-1$ } /** * This method takes a json boards file url and downloads it and parses it * for usage in the boards manager * * @param url * the url of the file to download and load * @param forceDownload * set true if you want to download the file even if it is * already available locally */ static private void loadJson(String url, boolean forceDownload) { File jsonFile = getLocalFileName(url); if (jsonFile == null) { return; } if (!jsonFile.exists() || forceDownload) { jsonFile.getParentFile().mkdirs(); String alternativeDownloadurl = getBaeyensItAlternativeDownload(jsonFile.getName()); try { myCopy(new URL(alternativeDownloadurl.trim()), jsonFile); } catch (IOException e0) { try { myCopy(new URL(url.trim()), jsonFile); } catch (IOException e) { Common.log(new Status(IStatus.ERROR, Activator.getId(), "Unable to download " + url, e)); //$NON-NLS-1$ } } } if (jsonFile.exists()) { if (jsonFile.getName().toLowerCase().startsWith("package_")) { //$NON-NLS-1$ loadPackage(jsonFile); } else if (jsonFile.getName().toLowerCase().startsWith("library_")) { //$NON-NLS-1$ LibraryManager.loadJson(jsonFile); } } } static private void loadPackage(File jsonFile) { try (Reader reader = new FileReader(jsonFile)) { PackageIndex index = new Gson().fromJson(reader, PackageIndex.class); index.setOwners(null); index.setJsonFile(jsonFile); packageIndices.add(index); } catch (Exception e) { Common.log(new Status(IStatus.ERROR, Activator.getId(), Messages.Manager_Failed_to_parse.replace("${FILE}", jsonFile.getAbsolutePath()), e)); //$NON-NLS-1$ jsonFile.delete();// Delete the file so it stops damaging } } static public List<PackageIndex> getPackageIndices() { if (packageIndices == null) { loadJsons(false); } return packageIndices; } static public Board getBoard(String boardName, String platformName, String packageName) { for (PackageIndex index : getPackageIndices()) { Package pkg = index.getPackage(packageName); if (pkg != null) { ArduinoPlatform platform = pkg.getLatestPlatform(platformName); if (platform != null) { Board board = platform.getBoard(boardName); if (board != null) { return board; } } } } return null; } static public List<Board> getBoards() { List<Board> boards = new ArrayList<>(); for (PackageIndex index : getPackageIndices()) { for (Package pkg : index.getPackages()) { for (ArduinoPlatform platform : pkg.getLatestPlatforms()) { boards.addAll(platform.getBoards()); } } } return boards; } public static List<ArduinoPlatform> getPlatforms() { List<ArduinoPlatform> platforms = new ArrayList<>(); for (PackageIndex index : getPackageIndices()) { for (Package pkg : index.getPackages()) { platforms.addAll(pkg.getPlatforms()); } } return platforms; } public static IPath getPlatformInstallPath(String vendor, String architecture) { for (PackageIndex index : getPackageIndices()) { for (Package pkg : index.getPackages()) { for (ArduinoPlatform curPlatform : pkg.getInstalledPlatforms()) { if (architecture.equalsIgnoreCase(curPlatform.getArchitecture()) && (vendor.equalsIgnoreCase(pkg.getName()))) { return new org.eclipse.core.runtime.Path(curPlatform.getInstallPath().toString()); } } } } return null; } /** * Given a platform.txt file find the platform in the platform manager * * @param platformTxt * @return the found platform otherwise null */ public static ArduinoPlatform getPlatform(File platformTxt) { for (PackageIndex index : getPackageIndices()) { for (Package pkg : index.getPackages()) { for (ArduinoPlatform curPlatform : pkg.getPlatforms()) { if (curPlatform.getPlatformFile().equals(platformTxt)) { return curPlatform; } } } } return null; } static public List<ArduinoPlatform> getInstalledPlatforms() { List<ArduinoPlatform> platforms = new ArrayList<>(); for (PackageIndex index : getPackageIndices()) { for (Package pkg : index.getPackages()) { platforms.addAll(pkg.getInstalledPlatforms()); } } return platforms; } static public List<Board> getInstalledBoards() { List<Board> boards = new ArrayList<>(); for (PackageIndex index : getPackageIndices()) { for (Package pkg : index.getPackages()) { for (ArduinoPlatform platform : pkg.getInstalledPlatforms()) { boards.addAll(platform.getBoards()); } } } return boards; } static public List<Package> getPackages() { List<Package> packages = new ArrayList<>(); for (PackageIndex index : getPackageIndices()) { packages.addAll(index.getPackages()); } return packages; } static public Package getPackage(String JasonName, String packageName) { for (PackageIndex index : getPackageIndices()) { if (index.getJsonFileName().equals(JasonName)) { return index.getPackage(packageName); } } return null; } static public Package getPackage(String packageName) { for (PackageIndex index : getPackageIndices()) { Package pkg = index.getPackage(packageName); if (pkg != null) { return pkg; } } return null; } static public Tool getTool(String packageName, String toolName, String version) { for (PackageIndex index : getPackageIndices()) { Package pkg = index.getPackage(packageName); if (pkg != null) { Tool tool = pkg.getTool(toolName, version); if (tool != null) { return tool; } } } return null; } /** * downloads an archive file from the internet and saves it in the download * folder under the name "pArchiveFileName" then extrats the file to * pInstallPath if pForceDownload is true the file will be downloaded even * if the download file already exists if pForceDownload is false the file * will only be downloaded if the download file does not exists The * extraction is done with processArchive so only files types supported by * this method will be properly extracted * * @param pURL * the url of the file to download * @param pArchiveFileName * the name of the file in the download folder * @param pInstallPath * @param pForceDownload * @param pMonitor * @return */ public static IStatus downloadAndInstall(String pURL, String pArchiveFileName, Path pInstallPath, boolean pForceDownload, IProgressMonitor pMonitor) { IPath dlDir = ConfigurationPreferences.getInstallationPathDownload(); IPath archivePath = dlDir.append(pArchiveFileName); try { URL dl = new URL(pURL); dlDir.toFile().mkdir(); if (!archivePath.toFile().exists() || pForceDownload) { pMonitor.subTask("Downloading " + pArchiveFileName + " .."); //$NON-NLS-1$ //$NON-NLS-2$ myCopy(dl, archivePath.toFile()); } } catch (IOException e) { return new Status(IStatus.ERROR, Activator.getId(), Messages.Manager_Failed_to_download + pURL, e); } return processArchive(pArchiveFileName, pInstallPath, pForceDownload, archivePath.toString(), pMonitor); } private static IStatus processArchive(String pArchiveFileName, Path pInstallPath, boolean pForceDownload, String pArchiveFullFileName, IProgressMonitor pMonitor) { // Create an ArchiveInputStream with the correct archiving algorithm String faileToExtractMessage = Messages.Manager_Failed_to_extract + pArchiveFullFileName; if (pArchiveFileName.endsWith("tar.bz2")) { //$NON-NLS-1$ try (ArchiveInputStream inStream = new TarArchiveInputStream( new BZip2CompressorInputStream(new FileInputStream(pArchiveFullFileName)))) { return extract(inStream, pInstallPath.toFile(), 1, pForceDownload, pMonitor); } catch (IOException | InterruptedException e) { return new Status(IStatus.ERROR, Activator.getId(), faileToExtractMessage, e); } } else if (pArchiveFileName.endsWith("zip")) { //$NON-NLS-1$ try (ArchiveInputStream in = new ZipArchiveInputStream(new FileInputStream(pArchiveFullFileName))) { return extract(in, pInstallPath.toFile(), 1, pForceDownload, pMonitor); } catch (IOException | InterruptedException e) { return new Status(IStatus.ERROR, Activator.getId(), faileToExtractMessage, e); } } else if (pArchiveFileName.endsWith("tar.gz")) { //$NON-NLS-1$ try (ArchiveInputStream in = new TarArchiveInputStream( new GzipCompressorInputStream(new FileInputStream(pArchiveFullFileName)))) { return extract(in, pInstallPath.toFile(), 1, pForceDownload, pMonitor); } catch (IOException | InterruptedException e) { return new Status(IStatus.ERROR, Activator.getId(), faileToExtractMessage, e); } } else if (pArchiveFileName.endsWith("tar")) { //$NON-NLS-1$ try (ArchiveInputStream in = new TarArchiveInputStream(new FileInputStream(pArchiveFullFileName))) { return extract(in, pInstallPath.toFile(), 1, pForceDownload, pMonitor); } catch (IOException | InterruptedException e) { return new Status(IStatus.ERROR, Activator.getId(), faileToExtractMessage, e); } } else { return new Status(IStatus.ERROR, Activator.getId(), Messages.Manager_Format_not_supported); } } public static IStatus extract(ArchiveInputStream in, File destFolder, int stripPath, boolean overwrite, IProgressMonitor pMonitor) throws IOException, InterruptedException { // Folders timestamps must be set at the end of archive extraction // (because creating a file in a folder alters the folder's timestamp) Map<File, Long> foldersTimestamps = new HashMap<>(); String pathPrefix = ""; //$NON-NLS-1$ Map<File, File> hardLinks = new HashMap<>(); Map<File, Integer> hardLinksMode = new HashMap<>(); Map<File, String> symLinks = new HashMap<>(); Map<File, Long> symLinksModifiedTimes = new HashMap<>(); // Cycle through all the archive entries while (true) { ArchiveEntry entry = in.getNextEntry(); if (entry == null) { break; } // Extract entry info long size = entry.getSize(); String name = entry.getName(); boolean isDirectory = entry.isDirectory(); boolean isLink = false; boolean isSymLink = false; String linkName = null; Integer mode = null; Long modifiedTime = new Long(entry.getLastModifiedDate().getTime()); pMonitor.subTask("Processing " + name); //$NON-NLS-1$ { // Skip MacOSX metadata // http://superuser.com/questions/61185/why-do-i-get-files-like-foo-in-my-tarball-on-os-x int slash = name.lastIndexOf('/'); if (slash == -1) { if (name.startsWith("._")) { //$NON-NLS-1$ continue; } } else { if (name.substring(slash + 1).startsWith("._")) { //$NON-NLS-1$ continue; } } } // Skip git metadata // http://www.unix.com/unix-for-dummies-questions-and-answers/124958-file-pax_global_header-means-what.html if (name.contains("pax_global_header")) { //$NON-NLS-1$ continue; } if (entry instanceof TarArchiveEntry) { TarArchiveEntry tarEntry = (TarArchiveEntry) entry; mode = new Integer(tarEntry.getMode()); isLink = tarEntry.isLink(); isSymLink = tarEntry.isSymbolicLink(); linkName = tarEntry.getLinkName(); } // On the first archive entry, if requested, detect the common path // prefix to be stripped from filenames int localstripPath = stripPath; if (localstripPath > 0 && pathPrefix.isEmpty()) { int slash = 0; while (localstripPath > 0) { slash = name.indexOf("/", slash); //$NON-NLS-1$ if (slash == -1) { throw new IOException(Messages.Manager_no_single_root_folder); } slash++; localstripPath--; } pathPrefix = name.substring(0, slash); } // Strip the common path prefix when requested if (!name.startsWith(pathPrefix)) { throw new IOException(Messages.Manager_no_single_root_folder_while_file + name + Messages.Manager_is_outside + pathPrefix); } name = name.substring(pathPrefix.length()); if (name.isEmpty()) { continue; } File outputFile = new File(destFolder, name); File outputLinkedFile = null; if (isLink && linkName != null) { if (!linkName.startsWith(pathPrefix)) { throw new IOException(Messages.Manager_no_single_root_folder_while_file + linkName + Messages.Manager_is_outside + pathPrefix); } linkName = linkName.substring(pathPrefix.length()); outputLinkedFile = new File(destFolder, linkName); } if (isSymLink) { // Symbolic links are referenced with relative paths outputLinkedFile = new File(linkName); if (outputLinkedFile.isAbsolute()) { System.err.println(Messages.Manager_Warning_file + outputFile + Messages.Manager_links_to_absolute_path + outputLinkedFile); System.err.println(); } } // Safety check if (isDirectory) { if (outputFile.isFile() && !overwrite) { throw new IOException( Messages.Manager_Cant_create_folder + outputFile + Messages.Manager_File_exists); } } else { // - isLink // - isSymLink // - anything else if (outputFile.exists() && !overwrite) { throw new IOException( Messages.Manager_Cant_extract_file + outputFile + Messages.Manager_File_already_exists); } } // Extract the entry if (isDirectory) { if (!outputFile.exists() && !outputFile.mkdirs()) { throw new IOException(Messages.Manager_Cant_create_folder + outputFile); } foldersTimestamps.put(outputFile, modifiedTime); } else if (isLink) { hardLinks.put(outputFile, outputLinkedFile); hardLinksMode.put(outputFile, mode); } else if (isSymLink) { symLinks.put(outputFile, linkName); symLinksModifiedTimes.put(outputFile, modifiedTime); } else { // Create the containing folder if not exists if (!outputFile.getParentFile().isDirectory()) { outputFile.getParentFile().mkdirs(); } copyStreamToFile(in, size, outputFile); outputFile.setLastModified(modifiedTime.longValue()); } // Set file/folder permission if (mode != null && !isSymLink && outputFile.exists()) { chmod(outputFile, mode.intValue()); } } for (Map.Entry<File, File> entry : hardLinks.entrySet()) { if (entry.getKey().exists() && overwrite) { entry.getKey().delete(); } link(entry.getValue(), entry.getKey()); Integer mode = hardLinksMode.get(entry.getKey()); if (mode != null) { chmod(entry.getKey(), mode.intValue()); } } for (Map.Entry<File, String> entry : symLinks.entrySet()) { if (entry.getKey().exists() && overwrite) { entry.getKey().delete(); } symlink(entry.getValue(), entry.getKey()); entry.getKey().setLastModified(symLinksModifiedTimes.get(entry.getKey()).longValue()); } // Set folders timestamps for (Map.Entry<File, Long> entry : foldersTimestamps.entrySet()) { entry.getKey().setLastModified(entry.getValue().longValue()); } return Status.OK_STATUS; } private static void symlink(String from, File to) throws IOException, InterruptedException { if (Platform.getOS().equals(Platform.OS_WIN32)) { // needs special rights only one board seems to fail due to this // Process process = Runtime.getRuntime().exec(new String[] { // "mklink", from, to.getAbsolutePath() }, //$NON-NLS-1$ // null, to.getParentFile()); // process.waitFor(); } else { Process process = Runtime.getRuntime().exec(new String[] { "ln", "-s", from, to.getAbsolutePath() }, //$NON-NLS-1$ //$NON-NLS-2$ null, to.getParentFile()); process.waitFor(); } } private static void link(File something, File somewhere) throws IOException, InterruptedException { Process process = Runtime.getRuntime() .exec(new String[] { "ln", something.getAbsolutePath(), somewhere.getAbsolutePath() }, null, null); //$NON-NLS-1$ process.waitFor(); } private static void chmod(File file, int mode) throws IOException, InterruptedException { String octal = Integer.toOctalString(mode); if (Platform.getOS().equals(Platform.OS_WIN32)) { boolean ownerExecute = (((mode / (8 * 8)) & 1) == 1); boolean ownerRead = (((mode / (8 * 8)) & 4) == 4); boolean ownerWrite = (((mode / (8 * 8)) & 2) == 2); boolean everyoneExecute = (((mode / 8) & 1) == 1); boolean everyoneRead = (((mode / 8) & 4) == 4); boolean everyoneWrite = (((mode / 8) & 2) == 2); file.setWritable(true, false); file.setExecutable(ownerExecute, !everyoneExecute); file.setReadable(ownerRead, !everyoneRead); file.setWritable(ownerWrite, !everyoneWrite); } else { Process process = Runtime.getRuntime().exec(new String[] { "chmod", octal, file.getAbsolutePath() }, null, //$NON-NLS-1$ null); process.waitFor(); } } private static void copyStreamToFile(InputStream in, long size, File outputFile) throws IOException { try (FileOutputStream fos = new FileOutputStream(outputFile)) { // if size is not available, copy until EOF... if (size == -1) { byte[] buffer = new byte[4096]; int length; while ((length = in.read(buffer)) != -1) { fos.write(buffer, 0, length); } return; } // ...else copy just the needed amount of bytes byte[] buffer = new byte[4096]; long leftToWrite = size; while (leftToWrite > 0) { int length = in.read(buffer); if (length <= 0) { throw new IOException(Messages.Manager_Failed_to_extract + outputFile.getAbsolutePath()); } fos.write(buffer, 0, length); leftToWrite -= length; } } } /** * This method removes the json files from disk and removes memory * references to these files or their content * * @param packageUrlsToRemove */ public static void removePackageURLs(Set<String> packageUrlsToRemove) { // remove the files from memory Set<String> activeUrls = new HashSet<>(Arrays.asList(ConfigurationPreferences.getJsonURLList())); activeUrls.removeAll(packageUrlsToRemove); ConfigurationPreferences.setJsonURLs(activeUrls.toArray(null)); // remove the files from disk for (String curJson : packageUrlsToRemove) { File localFile = getLocalFileName(curJson); if (localFile.exists()) { localFile.delete(); } } // reload the indices (this will remove all potential remaining // references // existing files do not need to be refreshed as they have been // refreshed at startup loadJsons(false); } public static String[] getJsonURLList() { return ConfigurationPreferences.getJsonURLList(); } /** * Completely replace the list with jsons with a new list * * @param newJsonUrls */ public static void setJsonURL(String[] newJsonUrls) { String curJsons[] = getJsonURLList(); HashSet<String> origJsons = new HashSet<>(Arrays.asList(curJsons)); HashSet<String> currentSelectedJsons = new HashSet<>(Arrays.asList(newJsonUrls)); currentSelectedJsons.removeAll(origJsons); // remove the files from disk which were in the old lst but not in the // new one for (String curJson : currentSelectedJsons) { File localFile = getLocalFileName(curJson); if (localFile.exists()) { localFile.delete(); } } // save to configurationsettings before calling LoadIndices ConfigurationPreferences.setJsonURLs(newJsonUrls); // reload the indices (this will remove all potential remaining // references // existing files do not need to be refreshed as they have been // refreshed at startup // new files will be added loadJsons(false); } public static void setReady(boolean b) { myIsReady = b; } /** * copy a url locally taking into account redirections * * @param url * @param localFile * @throws IOException */ @SuppressWarnings("nls") private static void myCopy(URL url, File localFile) throws IOException { try { HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(5000); conn.addRequestProperty("Accept-Language", "en-US,en;q=0.8"); conn.addRequestProperty("User-Agent", "Mozilla"); conn.addRequestProperty("Referer", "google.com"); // normally, 3xx is redirect int status = conn.getResponseCode(); if (status == HttpURLConnection.HTTP_OK) { Files.copy(url.openStream(), localFile.toPath(), REPLACE_EXISTING); return; } if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM || status == HttpURLConnection.HTTP_SEE_OTHER) { Files.copy(new URL(conn.getHeaderField("Location")).openStream(), localFile.toPath(), REPLACE_EXISTING); return; } Common.log(new Status(IStatus.WARNING, Activator.getId(), "Failed to download url " + url + " error code is: " + status, null)); throw new IOException("Failed to download url " + url + " error code is: " + status); } catch (Exception e) { Common.log(new Status(IStatus.WARNING, Activator.getId(), "Failed to download url " + url, e)); throw e; } } public static void onlyKeepLatestPlatforms() { List<Package> allPackages = getPackages(); for (Package curPackage : allPackages) { curPackage.onlyKeepLatestPlatforms(); } } }