1 /******************************************************************************* 2 * Copyright (c) 2009, 2017 Cloudsmith Inc. and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * Cloudsmith Inc. - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.equinox.internal.p2.touchpoint.natives.actions; 15 16 import java.io.*; 17 import java.util.ArrayList; 18 import java.util.Map; 19 import org.eclipse.core.runtime.IStatus; 20 import org.eclipse.core.runtime.Status; 21 import org.eclipse.equinox.internal.p2.engine.Profile; 22 import org.eclipse.equinox.internal.p2.touchpoint.natives.*; 23 import org.eclipse.equinox.p2.engine.spi.ProvisioningAction; 24 import org.eclipse.equinox.p2.metadata.IArtifactKey; 25 import org.eclipse.equinox.p2.metadata.IInstallableUnit; 26 import org.eclipse.osgi.util.NLS; 27 28 /** 29 * Copies from PARM_COPY_SOURCE to PARAM_COPY_TARGET 30 * The optional parameter PARAM_COPY_OVERWRITE overwrites and existing file if set to true, else 31 * and existing file with the same name is an error. The default is false. 32 * If the source is a directory, a merge copy to the target is performed. 33 * Copy will copy files and directories (recursively). 34 * 35 */ 36 public class CopyAction extends ProvisioningAction { 37 public static final String ID = "cp"; //$NON-NLS-1$ 38 39 @Override execute(Map<String, Object> parameters)40 public IStatus execute(Map<String, Object> parameters) { 41 return copy(parameters, true); 42 } 43 44 /** Perform the copy. 45 * 46 * @param parameters action parameters 47 * @param restoreable flag indicating if the operation should be backed up 48 * @return status 49 */ copy(Map<String, Object> parameters, boolean restoreable)50 public static IStatus copy(Map<String, Object> parameters, boolean restoreable) { 51 String target = (String) parameters.get(ActionConstants.PARM_COPY_TARGET); 52 IBackupStore backupStore = restoreable ? (IBackupStore) parameters.get(NativeTouchpoint.PARM_BACKUP) : null; 53 54 if (target == null) 55 return new Status(IStatus.ERROR, Activator.ID, IStatus.OK, NLS.bind(Messages.param_not_set, ActionConstants.PARM_COPY_TARGET, ID), null); 56 57 String source = (String) parameters.get(ActionConstants.PARM_COPY_SOURCE); 58 if (source == null) 59 return new Status(IStatus.ERROR, Activator.ID, IStatus.OK, NLS.bind(Messages.param_not_set, ActionConstants.PARM_COPY_SOURCE, ID), null); 60 61 String overwrite = (String) parameters.get(ActionConstants.PARM_COPY_OVERWRITE); 62 Profile profile = (Profile) parameters.get(ActionConstants.PARM_PROFILE); 63 IInstallableUnit iu = (IInstallableUnit) parameters.get(ActionConstants.PARM_IU); 64 65 String originalSource = source; 66 if (source.equals(ActionConstants.PARM_AT_ARTIFACT)) { 67 String artifactLocation = (String) parameters.get(NativeTouchpoint.PARM_ARTIFACT_LOCATION); 68 if (artifactLocation == null) { 69 IArtifactKey artifactKey = (IArtifactKey) parameters.get(NativeTouchpoint.PARM_ARTIFACT); 70 return Util.createError(NLS.bind(Messages.artifact_not_available, artifactKey)); 71 } 72 source = artifactLocation; 73 } 74 75 File sourceFile = new File(source); 76 File targetFile = new File(target); 77 File[] copiedFiles = null; 78 try { 79 copiedFiles = mergeCopy(sourceFile, targetFile, Boolean.parseBoolean(overwrite), backupStore); 80 } catch (IOException e) { 81 return new Status(IStatus.ERROR, Activator.ID, IStatus.OK, NLS.bind(Messages.copy_failed, sourceFile.getPath()), e); 82 } 83 // keep copied file in the profile as memento for CleanupCopy 84 StringBuffer copiedFileNameBuffer = new StringBuffer(); 85 for (File copiedFile : copiedFiles) { 86 copiedFileNameBuffer.append(copiedFile.getAbsolutePath()).append(ActionConstants.PIPE); 87 } 88 89 profile.setInstallableUnitProperty(iu, "copied" + ActionConstants.PIPE + originalSource + ActionConstants.PIPE + target, copiedFileNameBuffer.toString()); //$NON-NLS-1$ 90 91 return Status.OK_STATUS; 92 } 93 94 @Override undo(Map<String, Object> parameters)95 public IStatus undo(Map<String, Object> parameters) { 96 return CleanupcopyAction.cleanupcopy(parameters, false); 97 } 98 99 /** 100 * Merge-copy file or directory. 101 * @param source 102 * @param target 103 * @param overwrite 104 * @throws IOException 105 */ mergeCopy(File source, File target, boolean overwrite, IBackupStore backupStore)106 private static File[] mergeCopy(File source, File target, boolean overwrite, IBackupStore backupStore) throws IOException { 107 ArrayList<File> copiedFiles = new ArrayList<>(); 108 xcopy(copiedFiles, source, target, overwrite, backupStore); 109 return copiedFiles.toArray(new File[copiedFiles.size()]); 110 } 111 112 /** 113 * Merge-copy file or directory. 114 * @param copiedFiles - ArrayList where copied files are collected 115 * @param source 116 * @param target 117 * @param overwrite 118 * @throws IOException 119 */ xcopy(ArrayList<File> copiedFiles, File source, File target, boolean overwrite, IBackupStore backupStore)120 private static void xcopy(ArrayList<File> copiedFiles, File source, File target, boolean overwrite, IBackupStore backupStore) throws IOException { 121 if (!source.exists()) 122 throw new IOException("Source: " + source + "does not exists"); //$NON-NLS-1$//$NON-NLS-2$ 123 124 if (source.isDirectory()) { 125 if (target.exists() && target.isFile()) { 126 if (!overwrite) 127 throw new IOException("Target: " + target + " already exists"); //$NON-NLS-1$//$NON-NLS-2$ 128 if (backupStore != null) 129 backupStore.backup(target); 130 else 131 target.delete(); 132 } 133 if (!target.exists()) 134 target.mkdirs(); 135 copiedFiles.add(target); 136 File[] children = source.listFiles(); 137 if (children == null) 138 throw new IOException("Error while retrieving children of directory: " + source); //$NON-NLS-1$ 139 for (File child : children) { 140 xcopy(copiedFiles, child, new File(target, child.getName()), overwrite, backupStore); 141 } 142 return; 143 } 144 if (target.exists() && !overwrite) 145 throw new IOException("Target: " + target + " already exists"); //$NON-NLS-1$//$NON-NLS-2$ 146 147 if (!target.getParentFile().exists() && !target.getParentFile().mkdirs()) 148 throw new IOException("Target: Path " + target.getParent() + " could not be created"); //$NON-NLS-1$//$NON-NLS-2$ 149 150 try { 151 Util.copyStream(new FileInputStream(source), true, new FileOutputStream(target), true); 152 } catch (IOException e) { 153 // get the original IOException to the log 154 e.printStackTrace(); 155 throw new IOException("Error while copying:" + source.getAbsolutePath()); //$NON-NLS-1$ 156 } 157 copiedFiles.add(target); 158 } 159 } 160