001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.fs;
019
020import java.io.IOException;
021
022import org.apache.hadoop.classification.InterfaceAudience;
023import org.apache.hadoop.classification.InterfaceStability;
024import org.apache.hadoop.conf.Configuration;
025import org.apache.hadoop.conf.Configured;
026
027/** 
028 * Provides a trash facility which supports pluggable Trash policies. 
029 *
030 * See the implementation of the configured TrashPolicy for more
031 * details.
032 */
033@InterfaceAudience.Public
034@InterfaceStability.Stable
035public class Trash extends Configured {
036  private TrashPolicy trashPolicy; // configured trash policy instance
037
038  /** 
039   * Construct a trash can accessor.
040   * @param conf a Configuration
041   */
042  public Trash(Configuration conf) throws IOException {
043    this(FileSystem.get(conf), conf);
044  }
045
046  /**
047   * Construct a trash can accessor for the FileSystem provided.
048   * @param fs the FileSystem
049   * @param conf a Configuration
050   */
051  public Trash(FileSystem fs, Configuration conf) throws IOException {
052    super(conf);
053    trashPolicy = TrashPolicy.getInstance(conf, fs, fs.getHomeDirectory());
054  }
055
056  /**
057   * In case of the symlinks or mount points, one has to move the appropriate
058   * trashbin in the actual volume of the path p being deleted.
059   *
060   * Hence we get the file system of the fully-qualified resolved-path and
061   * then move the path p to the trashbin in that volume,
062   * @param fs - the filesystem of path p
063   * @param p - the  path being deleted - to be moved to trasg
064   * @param conf - configuration
065   * @return false if the item is already in the trash or trash is disabled
066   * @throws IOException on error
067   */
068  public static boolean moveToAppropriateTrash(FileSystem fs, Path p,
069      Configuration conf) throws IOException {
070    Path fullyResolvedPath = fs.resolvePath(p);
071    FileSystem fullyResolvedFs =
072        FileSystem.get(fullyResolvedPath.toUri(), conf);
073    // If the trash interval is configured server side then clobber this
074    // configuration so that we always respect the server configuration.
075    try {
076      long trashInterval = fullyResolvedFs.getServerDefaults(
077          fullyResolvedPath).getTrashInterval();
078      if (0 != trashInterval) {
079        Configuration confCopy = new Configuration(conf);
080        confCopy.setLong(CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_KEY,
081            trashInterval);
082        conf = confCopy;
083      }
084    } catch (Exception e) {
085      // If we can not determine that trash is enabled server side then
086      // bail rather than potentially deleting a file when trash is enabled.
087      throw new IOException("Failed to get server trash configuration", e);
088    }
089    Trash trash = new Trash(fullyResolvedFs, conf);
090    boolean success = trash.moveToTrash(fullyResolvedPath);
091    if (success) {
092      System.out.println("Moved: '" + p + "' to trash at: " +
093          trash.getCurrentTrashDir() );
094    }
095    return success;
096  }
097  
098  /**
099   * Returns whether the trash is enabled for this filesystem
100   */
101  public boolean isEnabled() {
102    return trashPolicy.isEnabled();
103  }
104
105  /** Move a file or directory to the current trash directory.
106   * @return false if the item is already in the trash or trash is disabled
107   */ 
108  public boolean moveToTrash(Path path) throws IOException {
109    return trashPolicy.moveToTrash(path);
110  }
111
112  /** Create a trash checkpoint. */
113  public void checkpoint() throws IOException {
114    trashPolicy.createCheckpoint();
115  }
116
117  /** Delete old checkpoint(s). */
118  public void expunge() throws IOException {
119    trashPolicy.deleteCheckpoint();
120  }
121
122  /** get the current working directory */
123  Path getCurrentTrashDir() {
124    return trashPolicy.getCurrentTrashDir();
125  }
126
127  /** get the configured trash policy */
128  TrashPolicy getTrashPolicy() {
129    return trashPolicy;
130  }
131
132  /** Return a {@link Runnable} that periodically empties the trash of all
133   * users, intended to be run by the superuser.
134   */
135  public Runnable getEmptier() throws IOException {
136    return trashPolicy.getEmptier();
137  }
138}