| /******************************************************************************* |
| * Copyright (c) 2009, 2017 Cloudsmith Inc. and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Cloudsmith Inc. - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.p2.touchpoint.natives.actions; |
| |
| import java.io.*; |
| import java.util.ArrayList; |
| import java.util.Map; |
| 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.*; |
| 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.osgi.util.NLS; |
| |
| /** |
| * Copies from PARM_COPY_SOURCE to PARAM_COPY_TARGET |
| * The optional parameter PARAM_COPY_OVERWRITE overwrites and existing file if set to true, else |
| * and existing file with the same name is an error. The default is false. |
| * If the source is a directory, a merge copy to the target is performed. |
| * Copy will copy files and directories (recursively). |
| * |
| */ |
| public class CopyAction extends ProvisioningAction { |
| public static final String ID = "cp"; //$NON-NLS-1$ |
| |
| @Override |
| public IStatus execute(Map<String, Object> parameters) { |
| return copy(parameters, true); |
| } |
| |
| /** Perform the copy. |
| * |
| * @param parameters action parameters |
| * @param restoreable flag indicating if the operation should be backed up |
| * @return status |
| */ |
| public static IStatus copy(Map<String, Object> parameters, boolean restoreable) { |
| String target = (String) parameters.get(ActionConstants.PARM_COPY_TARGET); |
| IBackupStore backupStore = restoreable ? (IBackupStore) parameters.get(NativeTouchpoint.PARM_BACKUP) : null; |
| |
| if (target == null) |
| return new Status(IStatus.ERROR, Activator.ID, IStatus.OK, NLS.bind(Messages.param_not_set, ActionConstants.PARM_COPY_TARGET, ID), null); |
| |
| String source = (String) parameters.get(ActionConstants.PARM_COPY_SOURCE); |
| if (source == null) |
| return new Status(IStatus.ERROR, Activator.ID, IStatus.OK, NLS.bind(Messages.param_not_set, ActionConstants.PARM_COPY_SOURCE, ID), null); |
| |
| String overwrite = (String) parameters.get(ActionConstants.PARM_COPY_OVERWRITE); |
| Profile profile = (Profile) parameters.get(ActionConstants.PARM_PROFILE); |
| IInstallableUnit iu = (IInstallableUnit) parameters.get(ActionConstants.PARM_IU); |
| |
| String originalSource = source; |
| if (source.equals(ActionConstants.PARM_AT_ARTIFACT)) { |
| String artifactLocation = (String) parameters.get(NativeTouchpoint.PARM_ARTIFACT_LOCATION); |
| if (artifactLocation == null) { |
| IArtifactKey artifactKey = (IArtifactKey) parameters.get(NativeTouchpoint.PARM_ARTIFACT); |
| return Util.createError(NLS.bind(Messages.artifact_not_available, artifactKey)); |
| } |
| source = artifactLocation; |
| } |
| |
| File sourceFile = new File(source); |
| File targetFile = new File(target); |
| File[] copiedFiles = null; |
| try { |
| copiedFiles = mergeCopy(sourceFile, targetFile, Boolean.parseBoolean(overwrite), backupStore); |
| } catch (IOException e) { |
| return new Status(IStatus.ERROR, Activator.ID, IStatus.OK, NLS.bind(Messages.copy_failed, sourceFile.getPath()), e); |
| } |
| // keep copied file in the profile as memento for CleanupCopy |
| StringBuffer copiedFileNameBuffer = new StringBuffer(); |
| for (File copiedFile : copiedFiles) { |
| copiedFileNameBuffer.append(copiedFile.getAbsolutePath()).append(ActionConstants.PIPE); |
| } |
| |
| profile.setInstallableUnitProperty(iu, "copied" + ActionConstants.PIPE + originalSource + ActionConstants.PIPE + target, copiedFileNameBuffer.toString()); //$NON-NLS-1$ |
| |
| return Status.OK_STATUS; |
| } |
| |
| @Override |
| public IStatus undo(Map<String, Object> parameters) { |
| return CleanupcopyAction.cleanupcopy(parameters, false); |
| } |
| |
| /** |
| * Merge-copy file or directory. |
| * @param source |
| * @param target |
| * @param overwrite |
| * @throws IOException |
| */ |
| private static File[] mergeCopy(File source, File target, boolean overwrite, IBackupStore backupStore) throws IOException { |
| ArrayList<File> copiedFiles = new ArrayList<>(); |
| xcopy(copiedFiles, source, target, overwrite, backupStore); |
| return copiedFiles.toArray(new File[copiedFiles.size()]); |
| } |
| |
| /** |
| * Merge-copy file or directory. |
| * @param copiedFiles - ArrayList where copied files are collected |
| * @param source |
| * @param target |
| * @param overwrite |
| * @throws IOException |
| */ |
| private static void xcopy(ArrayList<File> copiedFiles, File source, File target, boolean overwrite, IBackupStore backupStore) throws IOException { |
| if (!source.exists()) |
| throw new IOException("Source: " + source + "does not exists"); //$NON-NLS-1$//$NON-NLS-2$ |
| |
| if (source.isDirectory()) { |
| if (target.exists() && target.isFile()) { |
| if (!overwrite) |
| throw new IOException("Target: " + target + " already exists"); //$NON-NLS-1$//$NON-NLS-2$ |
| if (backupStore != null) |
| backupStore.backup(target); |
| else |
| target.delete(); |
| } |
| if (!target.exists()) |
| target.mkdirs(); |
| copiedFiles.add(target); |
| File[] children = source.listFiles(); |
| if (children == null) |
| throw new IOException("Error while retrieving children of directory: " + source); //$NON-NLS-1$ |
| for (File child : children) { |
| xcopy(copiedFiles, child, new File(target, child.getName()), overwrite, backupStore); |
| } |
| return; |
| } |
| if (target.exists() && !overwrite) |
| throw new IOException("Target: " + target + " already exists"); //$NON-NLS-1$//$NON-NLS-2$ |
| |
| if (!target.getParentFile().exists() && !target.getParentFile().mkdirs()) |
| throw new IOException("Target: Path " + target.getParent() + " could not be created"); //$NON-NLS-1$//$NON-NLS-2$ |
| |
| try { |
| Util.copyStream(new FileInputStream(source), true, new FileOutputStream(target), true); |
| } catch (IOException e) { |
| // get the original IOException to the log |
| e.printStackTrace(); |
| throw new IOException("Error while copying:" + source.getAbsolutePath()); //$NON-NLS-1$ |
| } |
| copiedFiles.add(target); |
| } |
| } |