From b2460aaf539f4b26db24950b95a3ac8176e5aedf Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Fri, 6 Mar 2015 12:03:28 -0500 Subject: Bug 461438 - Start of unpack native touchpoint action. This can be used for downloading and extracting toolchains into the Eclipse install folder. It will be used for the Arduino CDT. Change-Id: Iada25cff0fb2b2d9e5a55bedcaa8dbf9074058d8 --- p2/org.eclipse.cdt.p2/.classpath | 1 - p2/org.eclipse.cdt.p2/META-INF/MANIFEST.MF | 3 +- .../src/org/eclipse/cdt/internal/p2/Activator.java | 40 +++--- .../natives/actions/CleanupUnpackAction.java | 5 + .../p2/touchpoint/natives/actions/Messages.java | 16 +++ .../touchpoint/natives/actions/UnpackAction.java | 135 +++++++++++++++++++++ .../touchpoint/natives/actions/messages.properties | 2 + 7 files changed, 183 insertions(+), 19 deletions(-) create mode 100644 p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/CleanupUnpackAction.java create mode 100644 p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/Messages.java create mode 100644 p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/UnpackAction.java create mode 100644 p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/messages.properties diff --git a/p2/org.eclipse.cdt.p2/.classpath b/p2/org.eclipse.cdt.p2/.classpath index bc1f5c87991..9cc8a048b7e 100644 --- a/p2/org.eclipse.cdt.p2/.classpath +++ b/p2/org.eclipse.cdt.p2/.classpath @@ -4,7 +4,6 @@ - diff --git a/p2/org.eclipse.cdt.p2/META-INF/MANIFEST.MF b/p2/org.eclipse.cdt.p2/META-INF/MANIFEST.MF index af4f9aa93b7..afbbbd84cc0 100644 --- a/p2/org.eclipse.cdt.p2/META-INF/MANIFEST.MF +++ b/p2/org.eclipse.cdt.p2/META-INF/MANIFEST.MF @@ -13,7 +13,8 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.equinox.p2.engine;bundle-version="1.0.1", org.apache.ant;bundle-version="1.7.0", org.eclipse.equinox.p2.touchpoint.natives;bundle-version="1.0.0", - org.eclipse.equinox.p2.repository;bundle-version="1.0.0" + org.eclipse.equinox.p2.repository;bundle-version="1.0.0", + org.apache.commons.compress;bundle-version="1.6.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.cdt.internal.p2, diff --git a/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/Activator.java b/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/Activator.java index 87f4f38c623..0beb80ceb83 100644 --- a/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/Activator.java +++ b/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/Activator.java @@ -10,8 +10,8 @@ *******************************************************************************/ package org.eclipse.cdt.internal.p2; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Status; import org.osgi.framework.BundleContext; @@ -23,11 +23,11 @@ import org.osgi.framework.ServiceReference; public class Activator extends Plugin { // The plug-in ID - public static final String PLUGIN_ID = "org.eclipse.cdt.p2"; + public static final String PLUGIN_ID = "org.eclipse.cdt.p2"; //$NON-NLS-1$ // The shared instance private static Activator plugin; - + /** * The constructor */ @@ -64,31 +64,37 @@ public class Activator extends Plugin { public static BundleContext getContext() { return plugin.getBundle().getBundleContext(); } - + /** * Return a service from our context. * * @param name name of the service * @return the service */ - @SuppressWarnings("unchecked") public static T getService(Class clazz) { BundleContext context = plugin.getBundle().getBundleContext(); - ServiceReference ref = context.getServiceReference(clazz.getName()); - return (ref != null) ? (T)context.getService(ref) : null; + ServiceReference ref = context.getServiceReference(clazz); + return (ref != null) ? context.getService(ref) : null; } - - /** - * Spit out the log. - * - * @param status - */ - public static void log(int severity, String message, Throwable exception) { - Platform.getLog(plugin.getBundle()).log(new Status(severity, PLUGIN_ID, message, exception)); + + public static IStatus getStatus(int severity, String message) { + return new Status(severity, PLUGIN_ID, message); } - + + public static IStatus getStatus(int severity, Throwable e) { + return new Status(severity, PLUGIN_ID, e.getLocalizedMessage(), e); + } + public static void log(IStatus status) { - Platform.getLog(plugin.getBundle()).log(status); + plugin.getLog().log(status); + } + + public static void log(CoreException e) { + plugin.getLog().log(e.getStatus()); } + public static void log(Throwable e) { + plugin.getLog().log(getStatus(IStatus.ERROR, e)); + } + } diff --git a/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/CleanupUnpackAction.java b/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/CleanupUnpackAction.java new file mode 100644 index 00000000000..4e13bf19833 --- /dev/null +++ b/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/CleanupUnpackAction.java @@ -0,0 +1,5 @@ +package org.eclipse.cdt.internal.p2.touchpoint.natives.actions; + +public class CleanupUnpackAction { + +} diff --git a/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/Messages.java b/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/Messages.java new file mode 100644 index 00000000000..73433131850 --- /dev/null +++ b/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/Messages.java @@ -0,0 +1,16 @@ +package org.eclipse.cdt.internal.p2.touchpoint.natives.actions; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.p2.touchpoint.natives.actions.messages"; //$NON-NLS-1$ + public static String UnpackAction_ParmNotPresent; + public static String UnpackAction_TargetDirExists; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/UnpackAction.java b/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/UnpackAction.java new file mode 100644 index 00000000000..9953449665c --- /dev/null +++ b/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/UnpackAction.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.eclipse.cdt.internal.p2.touchpoint.natives.actions; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Map; + +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; +import org.apache.commons.compress.compressors.xz.XZCompressorInputStream; +import org.eclipse.cdt.internal.p2.Activator; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.equinox.p2.engine.IProfile; +import org.eclipse.equinox.p2.engine.spi.ProvisioningAction; + +/** + * Unpack the artifact with a choice of compression + * + * syntax: unpack(source:, targetDir:${installFolder}/, compression:[gz|bz2]) + */ +public class UnpackAction extends ProvisioningAction { + + private static final String ACTION_NAME = "unpack"; //$NON-NLS-1$ + private static final String PARM_SOURCE = "source"; //$NON-NLS-1$ + private static final String PARM_TARGET_DIR = "targetDir"; //$NON-NLS-1$ + private static final String PARM_FORMAT = "format"; //$NON-NLS-1$ + + @Override + public IStatus execute(Map parameters) { + try { + String source = (String)parameters.get(PARM_SOURCE); + if (source == null) { + return Activator.getStatus(IStatus.ERROR, String.format(Messages.UnpackAction_ParmNotPresent, PARM_SOURCE, ACTION_NAME)); + } + + String targetDir = (String)parameters.get(PARM_TARGET_DIR); + if (targetDir == null) { + return Activator.getStatus(IStatus.ERROR, String.format(Messages.UnpackAction_ParmNotPresent, PARM_TARGET_DIR, ACTION_NAME)); + } + + String format = (String)parameters.get(PARM_FORMAT); + if (format == null) { + return Activator.getStatus(IStatus.ERROR, String.format(Messages.UnpackAction_ParmNotPresent, PARM_FORMAT, ACTION_NAME)); + } + + IProfile profile = (IProfile) parameters.get("profile"); //$NON-NLS-1$ + File installFolder = new File(profile.getProperty(IProfile.PROP_INSTALL_FOLDER)); + File destDir = new File(installFolder, targetDir); + if (destDir.exists()) { + return Activator.getStatus(IStatus.ERROR, String.format(org.eclipse.cdt.internal.p2.touchpoint.natives.actions.Messages.UnpackAction_TargetDirExists, destDir.getAbsolutePath())); + } + + URL url = new URL(source); + InputStream fileIn = new BufferedInputStream(url.openStream()); + + switch (format) { + case "tar.gz": //$NON-NLS-1$ + InputStream gzIn = new GzipCompressorInputStream(fileIn); + untar(gzIn, destDir); + break; + case "tar.bz2": //$NON-NLS-1$ + InputStream bzIn = new BZip2CompressorInputStream(fileIn); + untar(bzIn, destDir); + break; + case "tar.xz": //$NON-NLS-1$ + InputStream xzIn = new XZCompressorInputStream(fileIn); + untar(xzIn, destDir); + break; + case "zip": //$NON-NLS-1$ + + } + + return Status.OK_STATUS; + } catch (Throwable e) { + return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getLocalizedMessage(), e); + } + } + + private void untar(InputStream in, File destDir) throws IOException { + byte[] buff = new byte[4096]; + try (TarArchiveInputStream tarIn = new TarArchiveInputStream(in)) { + for (TarArchiveEntry entry = tarIn.getNextTarEntry(); entry != null; entry = tarIn.getNextTarEntry()) { + String name = entry.getName(); + File destFile = new File(destDir, name); + if (entry.isSymbolicLink()) { + Files.createSymbolicLink(destFile.toPath(), Paths.get(name)); + } else { + try (FileOutputStream out = new FileOutputStream(destFile)) { + long size = entry.getSize(); + while (size > 0) { + int n = tarIn.read(buff, 0, (int)Math.min(size, buff.length)); + out.write(buff, 0, n); + size -= n; + } + } + chmod(destFile, entry.getMode()); + } + } + } + } + + private void chmod(File file, int mode) { + file.setExecutable((mode & 0111) != 0, (mode & 0110) == 0); + file.setWritable((mode & 0222) != 0, (mode & 0220) == 0); + file.setReadable((mode & 0444) != 0, (mode & 0440) == 0); + } + + @Override + public IStatus undo(Map parameters) { + try { + return CleanupUntarAction.cleanup(parameters); + } catch (Exception e) { + return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getLocalizedMessage(), e); + } + } + +} diff --git a/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/messages.properties b/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/messages.properties new file mode 100644 index 00000000000..ec202bf7636 --- /dev/null +++ b/p2/org.eclipse.cdt.p2/src/org/eclipse/cdt/internal/p2/touchpoint/natives/actions/messages.properties @@ -0,0 +1,2 @@ +UnpackAction_ParmNotPresent=The "{0}" parameter was not set in the "{1}" action. +UnpackAction_TargetDirExists=The target directory exists: {0} -- cgit v1.2.3