001/*
002 * (C) Copyright 2006-2014 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     bstefanescu
016 */
017package org.nuxeo.connect.update.task.standalone.commands;
018
019import java.io.File;
020import java.io.IOException;
021import java.util.Map;
022
023import org.apache.commons.logging.Log;
024import org.apache.commons.logging.LogFactory;
025import org.w3c.dom.Element;
026import org.nuxeo.common.utils.FileRef;
027import org.nuxeo.connect.update.PackageException;
028import org.nuxeo.connect.update.ValidationStatus;
029import org.nuxeo.connect.update.task.Command;
030import org.nuxeo.connect.update.task.Task;
031import org.nuxeo.connect.update.util.IOUtils;
032import org.nuxeo.connect.update.xml.XmlWriter;
033
034/**
035 * The delete command. This command takes 2 arguments: the file path to delete and an optional md5. If md5 is set then
036 * the command fails if the target file has not the same md5.
037 * <p>
038 * The inverse of the delete command is a copy command.
039 *
040 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
041 */
042public class Delete extends AbstractCommand {
043
044    protected static final Log log = LogFactory.getLog(Delete.class);
045
046    public static final String ID = "delete";
047
048    protected File file; // the file to restore
049
050    protected String md5;
051
052    protected boolean onExit;
053
054    public Delete() {
055        super(ID);
056    }
057
058    public Delete(File file, String md5) {
059        this(file, md5, false);
060    }
061
062    public Delete(File file, String md5, boolean onExit) {
063        super(ID);
064        this.file = file;
065        this.md5 = md5;
066        this.onExit = onExit;
067    }
068
069    @Override
070    protected void doValidate(Task task, ValidationStatus status) {
071        if (file == null) {
072            status.addError("Invalid delete syntax: No file specified");
073        }
074        if (file.isDirectory()) {
075            status.addError("Cannot delete directories: " + file.getName());
076        }
077    }
078
079    @Override
080    protected Command doRun(Task task, Map<String, String> prefs) throws PackageException {
081        try {
082            if (file.isFile()) {
083                if (md5 != null && !md5.equals(IOUtils.createMd5(file))) {
084                    // ignore the command since the md5 doesn't match
085                    return null;
086                }
087                File bak = IOUtils.backup(task.getPackage(), file);
088                if (onExit) {
089                    file.deleteOnExit();
090                } else {
091                    if (!file.delete()) {
092                        throw new PackageException("Cannot delete " + file.getName());
093                    }
094                }
095                return new Copy(bak, file, md5, false, onExit);
096            } else {
097                return null;
098            }
099        } catch (IOException e) {
100            throw new PackageException("Failed to create backup when deleting: " + file.getName(), e);
101        }
102    }
103
104    @Override
105    public void readFrom(Element element) throws PackageException {
106        String v = element.getAttribute("file");
107        if (v.length() > 0) {
108            FileRef ref = FileRef.newFileRef(v);
109            ref.fillPatternVariables(guardVars);
110            file = ref.getFile();
111            guardVars.put("file", file);
112        }
113        v = element.getAttribute("md5");
114        if (v.length() > 0) {
115            md5 = v;
116        }
117        v = element.getAttribute("onExit");
118        if (v.length() > 0) {
119            onExit = Boolean.parseBoolean(v);
120        }
121    }
122
123    @Override
124    public void writeTo(XmlWriter writer) {
125        writer.start(ID);
126        if (file != null) {
127            writer.attr("file", file.getAbsolutePath());
128        }
129        if (md5 != null) {
130            writer.attr("md5", md5);
131        }
132        if (onExit) {
133            writer.attr("onExit", "true");
134        }
135        writer.end();
136    }
137}