/******************************************************************************* * Copyright (c) 2015 ARM Ltd. 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: * Eclipse Project - generation from template * Liviu Ionescu - initial implementation * ARM Ltd and ARM Germany GmbH - application-specific implementation *******************************************************************************/ package com.arm.cmsis.pack.installer; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InterruptedIOException; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.rtf.RTFEditorKit; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider; import org.eclipse.ui.wizards.datatransfer.ImportOperation; import com.arm.cmsis.pack.CpPlugIn; import com.arm.cmsis.pack.ICpEnvironmentProvider; import com.arm.cmsis.pack.ICpPackInstaller; import com.arm.cmsis.pack.ICpRepoServiceProvider; import com.arm.cmsis.pack.common.CmsisConstants; import com.arm.cmsis.pack.data.CpPack; import com.arm.cmsis.pack.data.ICpExample; import com.arm.cmsis.pack.data.ICpItem; import com.arm.cmsis.pack.data.ICpPack; import com.arm.cmsis.pack.data.ICpPack.PackState; import com.arm.cmsis.pack.data.ICpPackCollection; import com.arm.cmsis.pack.events.RteEvent; import com.arm.cmsis.pack.events.RtePackJobResult; import com.arm.cmsis.pack.generic.IAttributes; import com.arm.cmsis.pack.installer.jobs.CpPackImportFolderJob; import com.arm.cmsis.pack.installer.jobs.CpPackImportJob; import com.arm.cmsis.pack.installer.jobs.CpPackInstallJob; import com.arm.cmsis.pack.installer.jobs.CpPackJob; import com.arm.cmsis.pack.installer.jobs.CpPackRemoveJob; import com.arm.cmsis.pack.installer.jobs.CpPackUnpackJob; import com.arm.cmsis.pack.installer.jobs.LicenseDialog; import com.arm.cmsis.pack.preferences.CpPreferenceInitializer; import com.arm.cmsis.pack.repository.CpRepositoryList; import com.arm.cmsis.pack.repository.ICpRepository; import com.arm.cmsis.pack.utils.Utils; import com.arm.cmsis.pack.utils.VersionComparator; /** * Default implementation of {@link ICpPackInstaller} */ public class CpPackInstaller extends PlatformObject implements ICpPackInstaller { protected CpPackJob fJob; protected IProgressMonitor fMonitor; protected Map<String, CpPackJob> fJobQueue; // job ID -> pack job /** * Pack ID -> Collection of required packs' IDs installing */ protected Map<String, Collection<String>> fResolvingPacks; private final static int TIME_OUT = 10000; int wait; boolean licAgreed; protected ICpRepoServiceProvider fRepoServiceProvider; public CpPackInstaller() { fJobQueue = Collections.synchronizedMap(new HashMap<>()); fResolvingPacks = Collections.synchronizedMap(new HashMap<>()); fRepoServiceProvider = new CpRepoServiceProvider(); } @Override public void installPack(String packId) { installPack(packId, true); } @Override public void installPack(String packId, boolean installRequiredPacks) { final ICpPackCollection allPacks = CpPlugIn.getPackManager().getPacks(); if (allPacks == null) { popupInstallError(Messages.CpPackInstaller_OpenPackManagerToUpdatePacks); return; } ICpPack pack = allPacks.getPack(packId); if (pack != null) { if (pack.getPackState() == PackState.INSTALLED) { return; } else if (pack.getPackState() == PackState.DOWNLOADED) { unpackPack(pack, installRequiredPacks); } else { installPack(pack.getPackId(), pack.getUrl(), installRequiredPacks); } } else { String familyId = CpPack.familyFromId(packId); ICpPack latestPack = allPacks.getPack(familyId); if (latestPack == null) { printInConsole(NLS.bind(Messages.CpPackInstaller_PackFamilyNotFound, familyId), ConsoleType.ERROR); return; } if (CpPack.isPackFamilyId(packId)) { packId += '.' + latestPack.getVersion(); } installPack(packId, latestPack.getUrl(), installRequiredPacks); } } @Override public void installPack(IAttributes packAttributes) { String packId = CpPack.constructPackId(packAttributes); installPack(packId, true); } @Override public Collection<String> installRequiredPacks(ICpPack pack) { if (pack == null || pack.getPackState() != PackState.INSTALLED || pack.isRequiredPacksInstalled()) { return null; } Collection<? extends ICpItem> requiredPacks = pack.getRequiredPacks(); if (requiredPacks == null || requiredPacks.isEmpty()) { return null; } Collection<String> reqPacks = new HashSet<>(); for (ICpItem requiredPack : requiredPacks) { ICpPackCollection installedPacks = CpPlugIn.getPackManager().getInstalledPacks(); if (installedPacks != null && installedPacks.getPack(requiredPack.attributes()) != null) { continue; } // check releases' versions String vendor = requiredPack.getVendor(); String name = requiredPack.getName(); String versionRange = requiredPack.getVersion(); String familyId = vendor + '.' + name; ICpPack latestPack = CpPlugIn.getPackManager().getPacks().getPack(familyId); if (latestPack == null) { printInConsole(NLS.bind(Messages.CpPackInstaller_RequiredPackFamilyNotExist, familyId), ConsoleType.WARNING); continue; } Collection<? extends ICpItem> releases = latestPack.getReleases(); if (releases == null) { printInConsole(NLS.bind(Messages.CpPackInstaller_NoVersionOfPackFamilyIsFound, familyId), ConsoleType.WARNING); continue; } boolean compatibleVersionFound = false; for (ICpItem release : releases) { String version = release.getAttribute(CmsisConstants.VERSION); if (VersionComparator.matchVersionRange(version, versionRange)) { boolean addedToJobQueue; String packId = familyId + '.' + version; ICpPack downloadedPack = CpPlugIn.getPackManager().getPacks().getPack(packId); if (downloadedPack != null && downloadedPack.getPackState() == PackState.DOWNLOADED) { addedToJobQueue = unpackPack(downloadedPack, true); } else { addedToJobQueue = installPack(packId, latestPack.getUrl(), true); } if (addedToJobQueue) { reqPacks.add(packId); } compatibleVersionFound = true; break; } } if (!compatibleVersionFound) { printInConsole(NLS.bind(Messages.CpPackInstaller_NoCompatibleVersionIsFound, familyId, versionRange), ConsoleType.WARNING); continue; } } if (!reqPacks.isEmpty()) { StringBuilder output = new StringBuilder(NLS.bind(Messages.CpPackInstaller_InstallingRequiredPacks, pack.getId())); for (String reqPack : reqPacks) { output.append(reqPack + ", "); //$NON-NLS-1$ } output.delete(output.length()-2, output.length()); printInConsole(output.toString(), ConsoleType.INFO); } return reqPacks; } /** * Install pack with pack id and download url * * @param packId full pack id with version * @param url URL of this pack family * @param installRequiredPacks True if the required packs should also be installed * @return True if the job is added to the job queue */ private boolean installPack(String packId, String url, boolean installRequiredPacks) { if (fJobQueue.containsKey(packId)) { return false; } fJob = new CpPackInstallJob(NLS.bind(Messages.CpPackInstaller_InstallingPack, packId), this, packId, url, installRequiredPacks); fJob.setUser(true); fJobQueue.put(packId, fJob); fJob.schedule(); return true; } protected void popupInstallError(String errorMessage) { Display.getDefault().asyncExec(() -> { MessageDialog.openError(null, Messages.CpPackInstaller_NoPacksFound, errorMessage); }); } @Override public void importPack(String filePath) { String packId = Utils.extractBaseFileName(filePath); if (fJobQueue.containsKey(packId)) { return; } fJob = new CpPackImportJob(NLS.bind(Messages.CpPackInstaller_ImportingPack, packId), this, packId, filePath); fJob.setUser(true); fJobQueue.put(packId, fJob); fJob.schedule(); } @Override public void importFolderPacks(String rootPath) { List<String> files = new LinkedList<String>();; Utils.findPdscFiles(new File(rootPath), files, 256); String jobId = files.stream().map(filename -> CpPlugIn.getPackManager().readPack(filename)) .filter(pack -> pack != null).map(pack -> pack.getId()) .collect(Collectors.joining(",")); //$NON-NLS-1$ fJob = new CpPackImportFolderJob( NLS.bind(Messages.CpPackInstaller_ImportingFolderPacks, rootPath), this, jobId, rootPath); fJob.setUser(true); fJobQueue.put(jobId, fJob); fJob.schedule(); } /** * Unpack the pack that stays in the .Download folder * @param pack The pack to unzip * @param installRequiredPacks true if the required packs should also be installed * @return True if the job is added to the job queue */ private boolean unpackPack(ICpPack pack, boolean installRequiredPacks) { if (fJobQueue.containsKey(pack.getId())) { return false; } fJob = new CpPackUnpackJob(NLS.bind(Messages.CpPackInstaller_UnpackingPack, pack.getId()), this, pack.getId(), installRequiredPacks); fJob.setUser(true); fJobQueue.put(pack.getId(), fJob); fJob.schedule(); return true; } @Override public void removePack(ICpPack pack, boolean delete) { if (fJobQueue.containsKey(pack.getId())) { return; } String jobName = NLS.bind(Messages.CpPackInstaller_RemovingPack, pack.getId()); if (delete) { jobName = NLS.bind(Messages.CpPackInstaller_DeletingPack, pack.getId()); } fJob = new CpPackRemoveJob(jobName, this, pack, delete); fJob.setUser(true); if (pack.getPackState() == PackState.ERROR) { fJobQueue.put(pack.getTag(), fJob); } else { fJobQueue.put(pack.getId(), fJob); } fJob.schedule(); } @Override public boolean unzip(File archiveFile, IPath destPath, IProgressMonitor monitor) throws IOException { SubMonitor progress = SubMonitor.convert(monitor, Utils.getFilesCount(archiveFile)); if (destPath.toFile().exists()) { Utils.deleteFolderRecursive(destPath.toFile()); } File tempFolder = File.createTempFile("temp", null); //$NON-NLS-1$ tempFolder.delete(); tempFolder.mkdir(); IPath tempDestPath = new Path(tempFolder.getAbsolutePath()); boolean unzipFinished = false; try { unzipFinished = unzipTemp(archiveFile, tempDestPath, progress); if (unzipFinished) { Utils.copyDirectory(tempDestPath.toFile(), destPath.toFile()); return true; } } catch (BadLocationException e) { } finally { Utils.deleteFolderRecursive(tempDestPath.toFile()); } return false; } @Override public IProject copyExample(ICpExample example) { if (example == null) { return null; } ICpEnvironmentProvider envProvider = CpPlugIn.getEnvironmentProvider(); if (envProvider == null) { return null; } String loadPath = example.getAbsoluteLoadPath(envProvider.getName()); if (loadPath == null || loadPath.isEmpty()) { return null; } IPath examplePath = new Path(loadPath); // default implementation assumes that the example is an Eclipse project IProjectDescription projDesc = getProjectDescription(examplePath); if (projDesc == null) { popupCopyError(NLS.bind(Messages.CpPackInstaller_ErrorWhileReadingProjectDescriptionFile, examplePath)); return null; } String projectName = projDesc.getName(); final IWorkspace workspace = ResourcesPlugin.getWorkspace(); final IProject project = workspace.getRoot().getProject(projectName); File destFile = ResourcesPlugin.getWorkspace().getRoot().getLocation() .append(project.getName()).toFile(); if (!confirmCopyExample(example, destFile, project)) { return null; } if (project.exists()) { try { project.delete(true, true, new NullProgressMonitor()); } catch (CoreException e) { popupCopyError(NLS.bind(Messages.CpPackInstaller_ErrorWhileOverwritingExistingProject, project.getName())); return null; } } else if (destFile.exists()) { Utils.deleteFolderRecursive(destFile); } CpPlugIn.getDefault().emitRteEvent(RteEvent.PRE_IMPORT, null); File importSource = new File(projDesc.getLocationURI()); FileSystemStructureProvider structureProvider = FileSystemStructureProvider.INSTANCE; ImportOperation operation = new ImportOperation(project.getFullPath(), importSource, structureProvider, new OverwriteQuery(null), structureProvider.getChildren(importSource)); operation.setContext(null); operation.setOverwriteResources(true); // need to overwrite operation.setCreateContainerStructure(false); try { operation.run(new NullProgressMonitor()); } catch (InvocationTargetException | InterruptedException e) { popupCopyError(NLS.bind(Messages.CpPackInstaller_FailedImportFilesFromFolder, examplePath.removeLastSegments(1))); return null; } Utils.clearReadOnly(project.getLocation().toFile(), CmsisConstants.EMPTY_STRING); CpPlugIn.getDefault().emitRteEvent(RteEvent.POST_IMPORT, project); return project; } protected boolean confirmCopyExample(ICpExample example, File destFile, IProject project) { CopyExampleDialog copyDialog = new CopyExampleDialog(null, example.getName(), example.getPackId(), destFile.toString(), project.getName(), project.exists() || destFile.exists()); return copyDialog.open() == Window.OK; } protected void popupCopyError(String errorMessage) { Display.getDefault().asyncExec(() -> { MessageDialog.openError(null, Messages.CpPackInstaller_ErrorWhileCopyingExample, errorMessage); }); } private IProjectDescription getProjectDescription(IPath path) { try { return ResourcesPlugin.getWorkspace().loadProjectDescription(path); } catch (CoreException e) { return null; } } @Override public void updatePacks(IProgressMonitor monitor) { fMonitor = monitor; updatePacks(); } @Override public void jobFinished(String jobId, String jobTopic, RtePackJobResult jobResult) { CpPackJob job = fJobQueue.remove(jobId); String jobName = job != null ? job.getName() : Messages.CpPackInstaller_Processing; // job is finished, update the resolving status (fResolvingPacks) updateResolvingPacks(jobId); String output = new SimpleDateFormat("HH:mm:ss").format(new Date()); //$NON-NLS-1$ output += ": " + jobName; //$NON-NLS-1$ if (jobResult != null && jobResult.isSuccess()) { output += Messages.CpPackInstaller_Completed; printInConsole(output, ConsoleType.OUTPUT); if(job != null && job.installRequiredPacks()) { Collection<String> reqPacks = installRequiredPacks(jobResult.getPack()); if (reqPacks != null && !reqPacks.isEmpty()) { fResolvingPacks.put(jobId, reqPacks); } } CpPlugIn.getDefault().emitRteEvent(jobTopic, jobResult); } else { output += Messages.CpPackInstaller_WasNotSuccessful; if (jobResult != null) { output += jobResult.getErrorString(); } printInConsole(output, ConsoleType.ERROR); // anyway notify the recipients that the job has completed CpPlugIn.getDefault().emitRteEvent(jobTopic, jobResult); } } @Override public ICpRepoServiceProvider getRepoServiceProvider() { return fRepoServiceProvider; } @Override public void setRepoServiceProvider(ICpRepoServiceProvider repoServiceProvider) { fRepoServiceProvider = repoServiceProvider; } @Override public synchronized boolean isBusy() { return !fJobQueue.isEmpty(); } @Override public synchronized boolean isProcessing(String packId) { return fJobQueue.containsKey(packId) || fResolvingPacks.containsKey(packId) || fJobQueue.keySet().stream().filter(jobId -> jobId.contains(packId)).count() > 0; } @Override public synchronized boolean isProcessing(IAttributes packAttributes) { String packId = CpPack.constructPackId(packAttributes); return isProcessing(packId); } @Override public synchronized void reset() { for (Job job : fJobQueue.values()) { job.cancel(); } fJobQueue.clear(); } @Override public void printInConsole(String message, ConsoleType type) { switch (type) { case OUTPUT: CpPlugIn.getDefault().emitRteEvent(RteEvent.PRINT_OUTPUT, message); break; case INFO: CpPlugIn.getDefault().emitRteEvent(RteEvent.PRINT_INFO, message); break; case WARNING: CpPlugIn.getDefault().emitRteEvent(RteEvent.PRINT_WARNING, message); break; case ERROR: CpPlugIn.getDefault().emitRteEvent(RteEvent.PRINT_ERROR, message); break; default : break; } } /***************** Here begins the Update Packs part *****************/ protected void updatePacks() { if (CpPlugIn.getPackManager().getCmsisPackRootDirectory() == null || CpPlugIn.getPackManager().getCmsisPackRootDirectory().isEmpty()) { // if this is not an automatic update, print the message on the console if (!(fMonitor instanceof NullProgressMonitor)) { printInConsole(Messages.CpPackInstaller_SetCmsisPackRootFolderAndTryAgain, ConsoleType.ERROR); } return; } boolean success = true; CpRepositoryList repos = CpPlugIn.getPackManager().getCpRepositoryList(); // String[] { url, name, version } List<String[]> list = new LinkedList<String[]>(); try { boolean needsUpdate = false; List<ICpRepository> reposList = repos.getList(); for (ICpRepository repo : reposList) { if (fMonitor.isCanceled()) { break; } String type = repo.getType(); String indexUrl = repo.getUrl(); if (CmsisConstants.REPO_PACK_TYPE.equals(type)) { // collect all pdsc references in this site int count = readCmsisIndex(indexUrl, list); if (count > 0) { list.add(0, new String[]{Utils.extractPath(indexUrl, true), Utils.extractFileName(indexUrl), CmsisConstants.EMPTY_STRING}); needsUpdate = true; } else if (count == -1) { // this index file is not correctly downloaded/parsed success = false; } } else { printInConsole(NLS.bind(Messages.CpPackInstaller_RepoTypeNotSupported, type), ConsoleType.WARNING); } } // Set total number of work units to the number of pdsc files fMonitor.beginTask(Messages.CpPackInstaller_RefreshAllPacks, list.size() + 3); // Read all .pdsc files and collect summary if index.pidx's time stamp changes if (needsUpdate) { aggregateCmsis(list); } fMonitor.worked(1); // Should reach 100% now } catch (Exception e) { printInConsole(e.toString(), ConsoleType.ERROR); } if (fMonitor.isCanceled()) { printInConsole(Messages.CpPackInstaller_JobCancelled, ConsoleType.WARNING); } else if (success) { cleanWebFolder(list); CpPreferenceInitializer.updateLastUpdateTime(true); } printInConsole(Messages.CpPackInstaller_PackUpdatesCompleted, ConsoleType.INFO); CpPlugIn.getPackManager().reload(); } /** * Remove .pdsc files that are in .Web folder but not listed in index.pidx file * @param list a list of .pdsc files in index.pidx, each item is { url, name, version } */ protected void cleanWebFolder(List<String[]> list) { File webFile = new File(CpPlugIn.getPackManager().getCmsisPackWebDir()); if (!webFile.exists()) { return; } // put the .pdsc files listed in index.pidx in a set Set<String> webPdscFiles = new HashSet<>(); for (String[] entry : list) { webPdscFiles.add(webFile.getAbsolutePath() + File.separator + entry[1]); } Collection<String> availablePdscFiles = Utils.findPdscFiles(webFile, null, 0); for (String pdscFile : availablePdscFiles) { if (!webPdscFiles.contains(pdscFile)) { new File(pdscFile).delete(); } } } /** * Reads the .index file * * @param indexUrl url of .index file * @param pdscList list of pdsc files * @return number of pdsc files that needs to be updated. -1 if exception occurs. */ protected int readCmsisIndex(String indexUrl, List<String[]> pdscList) { printInConsole(NLS.bind(Messages.CpPackInstaller_Parsing, indexUrl), ConsoleType.INFO); try { return fRepoServiceProvider.readIndexFile(indexUrl, pdscList); } catch (FileNotFoundException e) { printInConsole(Messages.CpPackInstaller_FileNotFound + e.getMessage(), ConsoleType.ERROR); } catch (UnknownHostException e) { printInConsole(NLS.bind(Messages.CpPackInstallJob_UnknownHostException, e.getMessage()), ConsoleType.ERROR); } catch (Exception e) { printInConsole(e.toString(), ConsoleType.ERROR); } return -1; } /** * Collects pack info from index file * @param list List of packs, each entry is like {url, name, version} */ protected void aggregateCmsis(List<String[]> list) { IPath webFolder = new Path(CpPlugIn.getPackManager().getCmsisPackWebDir()); if (!webFolder.toFile().exists()) { webFolder.toFile().mkdir(); } // repo keys: { "type", "url", "list" } // String[] { url, name, version } for (int i = 0; i < list.size(); i++) { String[] pdsc = list.get(i); if (fMonitor.isCanceled()) { break; } // Make url always ends in '/' final String pdscUrl = CmsisConstants.REPO_KEIL_PACK_SERVER/*Utils.addTrailingSlash(pdsc[0])*/; final String pdscName = pdsc[1]; final String pdscVersion = pdsc[2]; final String packFamilyId = Utils.extractBaseFileName(pdscName); fMonitor.subTask(NLS.bind(Messages.CpPackInstaller_Updating, pdscName, pdscUrl)); // if this is not .idx file and we have already higher version, then // skip if (pdscName.endsWith(CmsisConstants.EXT_PDSC) && skipUpdate(pdscUrl, packFamilyId, pdscVersion)) { fMonitor.worked(1); continue; } String destFileName = webFolder.append(pdscName).toOSString(); try { fRepoServiceProvider.getPdscFile(pdscUrl, pdscName, destFileName, fMonitor); } catch (FileNotFoundException e) { printInConsole(e.getMessage(), ConsoleType.ERROR); } catch (UnknownHostException e) { printInConsole(NLS.bind(Messages.CpPackInstallJob_UnknownHostException, e.getMessage()), ConsoleType.ERROR); } catch (SocketTimeoutException e) { wait = timeoutQuestion(pdscUrl); if (wait == 0) { // Yes i--; continue; } else if (wait == 1) { // No printInConsole(NLS.bind(Messages.CpPackInstaller_TimeoutConsoleMessage, pdscName, pdscUrl), ConsoleType.WARNING); } else { // Cancel fMonitor.setCanceled(true); break; } } catch (InterruptedIOException e) { printInConsole(e.getMessage(), ConsoleType.ERROR); } catch (IOException e) { printInConsole(NLS.bind(Messages.CpPackInstaller_ErrorWhileRefreshingIgnored, e.getMessage()), ConsoleType.WARNING); } // One more unit completed fMonitor.worked(1); } } /***************** Here begins utility function part *****************/ protected boolean unzipTemp(File archiveFile, IPath destPath, IProgressMonitor progress) throws IOException, BadLocationException { boolean result = true; boolean containLic = false; String licenseFileName = CmsisConstants.EMPTY_STRING; File licenseFile = null; licAgreed = true; ZipInputStream zipInput; zipInput = new ZipInputStream(new FileInputStream(archiveFile)); ZipEntry zipEntry = zipInput.getNextEntry(); int countBytes = 0; while (zipEntry != null) { if (progress.isCanceled()) { result = false; break; } if (!zipEntry.isDirectory()) { String fileName = zipEntry.getName(); IPath path = destPath.append(fileName); File outFile = new File(path.toOSString()); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } OutputStream output = new FileOutputStream(outFile); byte[] buf = new byte[1024]; int bytesRead; while ((bytesRead = zipInput.read(buf)) > 0) { output.write(buf, 0, bytesRead); countBytes += bytesRead; } output.close(); outFile.setReadOnly(); if (outFile.toString().endsWith(CmsisConstants.EXT_PDSC)) { ICpPack pack = CpPlugIn.getPackManager().readPack(outFile.toString()); if (pack != null && pack.getFirstChild(CmsisConstants.LICENSE_TAG) != null) { containLic = true; licenseFileName = pack.getFirstChild(CmsisConstants.LICENSE_TAG).getText().replace('\\', '/'); } } if (containLic && licenseFileName.equals(fileName)) { licenseFile = outFile; } progress.worked(1); } zipEntry = zipInput.getNextEntry(); } zipInput.closeEntry(); zipInput.close(); if (countBytes <= 0) { throw new IOException(); } // if not cancelled by user, contains license file, ask if the user to agree if (result && containLic && licenseFile != null) { progress.setTaskName(Messages.PackInstallerUtils_PleaseAgreeLicenseAgreement); String absolutePath = licenseFile.getAbsolutePath(); byte[] allBytes = Files.readAllBytes(Paths.get(absolutePath)); String fileExt = Utils.extractFileExtension(absolutePath); String packName = Utils.extractBaseFileName(archiveFile.getName()); String text; if ("rtf".equalsIgnoreCase(fileExt)) { //$NON-NLS-1$ RTFEditorKit rtfParser = new RTFEditorKit(); Document document = rtfParser.createDefaultDocument(); rtfParser.read(new ByteArrayInputStream(allBytes), document, 0); text = document.getText(0, document.getLength()); } else { text = new String(allBytes, Charset.defaultCharset()); } licAgreed = licenseQuestion(packName, text, destPath); if (!licAgreed) { Utils.deleteFolderRecursive(destPath.toFile()); } result = licAgreed; } progress.setTaskName(Messages.CpPackInstaller_FinishingOperation); return result; } protected int timeoutQuestion(String pdscUrl) { Display.getDefault().syncExec(() -> { MessageDialog dialog = new MessageDialog(null, Messages.CpPackInstaller_Timout, null, NLS.bind(Messages.CpPackInstaller_TimeoutMessage, pdscUrl, TIME_OUT / 1000), MessageDialog.QUESTION_WITH_CANCEL, new String[]{IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL}, 0); wait = dialog.open(); }); return wait; } protected boolean licenseQuestion(String packname, String licenseText, IPath destPath) { Display.getDefault().syncExec(() -> { LicenseDialog dlg = new LicenseDialog(null, packname, licenseText); licAgreed = dlg.open() == Window.OK; }); return licAgreed; } /** * Determine if this .pdsc file should be skipped when updating from the web * * @param pdscUrl pdsc file's url * @param packFamilyId pack family id * @param pdscVersion pdsc file's version * @return true if should be skipped for updating */ protected boolean skipUpdate(String pdscUrl, String packFamilyId, String pdscVersion) { if (CpPlugIn.getPackManager().getPacks() == null) { return false; } if (CpPlugIn.getPackManager().getPacks().getPacksByPackFamilyId(packFamilyId) == null) { return false; } for (ICpPack pack : CpPlugIn.getPackManager().getPacks().getPacksByPackFamilyId(packFamilyId)) { if (VersionComparator.versionCompare(pack.getVersion(), pdscVersion) >= 0) { return true; } } return false; } /** * Update the resolving pack's status * @param packId Pack ID of the pack that just finished installation (maybe unsuccessful) */ protected void updateResolvingPacks(String packId) { Iterator<Entry<String, Collection<String>>> iter = fResolvingPacks.entrySet().iterator(); while (iter.hasNext()) { Entry<String, Collection<String>> entry = iter.next(); entry.getValue().remove(packId); if (entry.getValue().isEmpty()) { // all required packs are installed iter.remove(); } } } }