/*******************************************************************************
* Copyright (c) 2009, 2010 Wind River 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.p2.touchpoint.natives.actions;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import org.apache.tools.bzip2.CBZip2InputStream;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.tar.TarInputStream;
import org.eclipse.cdt.internal.p2.Activator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.engine.Profile;
import org.eclipse.equinox.internal.p2.touchpoint.natives.Messages;
import org.eclipse.equinox.internal.p2.touchpoint.natives.Util;
import org.eclipse.equinox.internal.p2.touchpoint.natives.actions.ActionConstants;
import org.eclipse.equinox.internal.p2.touchpoint.natives.actions.UnzipAction;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.spi.ProvisioningAction;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.repository.artifact.IFileArtifactRepository;
import org.eclipse.osgi.util.NLS;
/**
* Untar the artifact with a choice of compression
*
* syntax: untar(source:@artifact, target:${installFolder}/<subdir>, compression:[gz|bz2])
*
* @author DSchaefe
*
*/
public class UntarAction extends ProvisioningAction {
private static final String ACTION_NAME = "untar";
private static final String PARM_COMPRESSION = "compression";
private static final String VALUE_GZ = "gz";
private static final String VALUE_BZ2 = "bz2";
private enum Compression {
none,
gz,
bz2
}
@Override
public IStatus execute(Map parameters) {
try {
return untar(parameters);
} catch (Exception e) {
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getLocalizedMessage(), e);
}
}
@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);
}
}
public static IStatus untar(Map parameters) throws Exception {
String source = (String)parameters.get(ActionConstants.PARM_SOURCE);
if (source == null)
return Util.createError(NLS.bind(Messages.param_not_set, ActionConstants.PARM_SOURCE, ACTION_NAME));
String originalSource = source;
String target = (String)parameters.get(ActionConstants.PARM_TARGET);
if (target == null)
return Util.createError(NLS.bind(Messages.param_not_set, ActionConstants.PARM_TARGET, ACTION_NAME));
String compressionStr = (String)parameters.get(PARM_COMPRESSION);
Compression compression;
if (compressionStr == null)
return Util.createError(NLS.bind(Messages.param_not_set, PARM_COMPRESSION, ACTION_NAME));
else if (compressionStr.equals(VALUE_GZ))
compression = Compression.gz;
else if (compressionStr.equals(VALUE_BZ2))
compression = Compression.bz2;
else
// TODO Should put out a log if compression is unknown
compression = Compression.none;
IInstallableUnit iu = (IInstallableUnit) parameters.get(ActionConstants.PARM_IU);
Profile profile = (Profile) parameters.get(ActionConstants.PARM_PROFILE);
IProvisioningAgent agent = (IProvisioningAgent) parameters.get(ActionConstants.PARM_AGENT);
if (source.equals(ActionConstants.PARM_AT_ARTIFACT)) {
//TODO: fix wherever this occurs -- investigate as this is probably not desired
if (iu.getArtifacts() == null || iu.getArtifacts().size() == 0)
return Status.OK_STATUS;
IArtifactKey artifactKey = iu.getArtifacts().iterator().next();
IFileArtifactRepository downloadCache;
try {
downloadCache = Util.getDownloadCacheRepo(agent);
} catch (ProvisionException e) {
return e.getStatus();
}
File fileLocation = downloadCache.getArtifactFile(artifactKey);
if ((fileLocation == null) || !fileLocation.exists())
return Util.createError(NLS.bind(Messages.artifact_not_available, artifactKey));
source = fileLocation.getAbsolutePath();
}
File[] unzippedFiles = untar(source, target, compression);
StringBuffer unzippedFileNameBuffer = new StringBuffer();
for (int i = 0; i < unzippedFiles.length; i++)
unzippedFileNameBuffer.append(unzippedFiles[i].getAbsolutePath()).append(ActionConstants.PIPE);
profile.setInstallableUnitProperty(iu, "unzipped" + ActionConstants.PIPE + originalSource + ActionConstants.PIPE + target, unzippedFileNameBuffer.toString()); //$NON-NLS-1$
return Status.OK_STATUS;
}
private static File[] untar(String source, String destination, Compression compression) throws Exception {
File zipFile = new File(source);
if (!zipFile.exists()) {
Util.log(UnzipAction.class.getName() + " the files to be unzipped is not here"); //$NON-NLS-1$
}
File target = new File(destination);
FileInputStream fileIn = new FileInputStream(zipFile);
InputStream compIn = fileIn;
if (compression.equals(Compression.gz))
compIn = new GZIPInputStream(fileIn);
else if (compression.equals(Compression.bz2)) {
// Skip the magic bytes first
fileIn.read(new byte[2]);
compIn = new CBZip2InputStream(fileIn);
}
ArrayList<File> fileList = new ArrayList<File>();
TarInputStream tarIn = new TarInputStream(compIn);
for (TarEntry tarEntry = tarIn.getNextEntry(); tarEntry != null; tarEntry = tarIn.getNextEntry()) {
File outFile = new File(target, tarEntry.getName());
if (tarEntry.isDirectory()) {
outFile.mkdirs();
} else {
if (outFile.exists())
outFile.delete();
else
outFile.getParentFile().mkdirs();
FileOutputStream outStream = new FileOutputStream(outFile);
tarIn.copyEntryContents(outStream);
outStream.close();
// Set last modified time from the tar entry
long lastModified = tarEntry.getModTime().getTime();
outFile.setLastModified(lastModified);
// Set the executable bits from the tar entry
// we let the umask determine the r/w
int mode = tarEntry.getMode();
boolean exec = (mode & 0x111) != 0;
boolean execOwner = (mode & 0x11) == 0;
// outFile.setExecutable(exec, execOwner);
fileList.add(outFile);
}
}
tarIn.close();
return fileList.toArray(new File[fileList.size()]);
}
}