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
022/**
023 * Exceptions based on standard posix/linux style exceptions for path related
024 * errors. Returns an exception with the format "path: standard error string".
025 * 
026 * This exception corresponds to Error Input/ouput(EIO)
027 */
028public class PathIOException extends IOException {
029  static final long serialVersionUID = 0L;
030  private static final String EIO = "Input/output error";
031  // NOTE: this really should be a Path, but a Path is buggy and won't
032  // return the exact string used to construct the path, and it mangles
033  // uris with no authority
034  private String operation;
035  private String path;
036  private String fullyQualifiedPath;
037  private String targetPath;
038
039  /**
040   * Constructor a generic I/O error exception
041   *  @param path for the exception
042   */
043  public PathIOException(String path) {
044    this(path, EIO);
045  }
046
047  /**
048   * Appends the text of a Throwable to the default error message
049   * @param path for the exception
050   * @param cause a throwable to extract the error message
051   */
052  public PathIOException(String path, Throwable cause) {
053    this(path, EIO, cause);
054  }
055
056  /**
057   * Avoid using this method.  Use a subclass of PathIOException if
058   * possible.
059   * @param path for the exception
060   * @param error custom string to use an the error text
061   */
062  public PathIOException(String path, String error) {
063    super(error);
064    this.path = path;
065  }
066
067  protected PathIOException(String path, String error, Throwable cause) {
068    super(error, cause);
069    this.path = path;
070  }
071
072  public PathIOException withFullyQualifiedPath(String fqPath) {
073    fullyQualifiedPath = fqPath;
074    return this;
075  }
076
077  /** Format:
078   * cmd: {operation} `path' {to `target'}: error string
079   */
080  @Override
081  public String getMessage() {
082    StringBuilder message = new StringBuilder();
083    if (operation != null) {
084      message.append(operation + " ");
085    }
086    message.append(formatPath(path));
087    if (targetPath != null) {
088      message.append(" to " + formatPath(targetPath));
089    }
090    message.append(": " + super.getMessage());
091    if (getCause() != null) {
092      message.append(": " + getCause().getMessage());
093    }
094    if (fullyQualifiedPath != null && !fullyQualifiedPath.equals(path)) {
095      message.append(": ").append(formatPath(fullyQualifiedPath));
096    }
097    return message.toString();
098  }
099
100  /** @return Path that generated the exception */
101  public Path getPath()  { return new Path(path); }
102
103  /** @return Path if the operation involved copying or moving, else null */
104  public Path getTargetPath() {
105    return (targetPath != null) ? new Path(targetPath) : null;
106  }    
107  
108  /**
109   * Optional operation that will preface the path
110   * @param operation a string
111   */
112  public void setOperation(String operation) {
113    this.operation = operation;
114  }
115  
116  /**
117   * Optional path if the exception involved two paths, ex. a copy operation
118   * @param targetPath the of the operation
119   */
120  public void setTargetPath(String targetPath) {
121    this.targetPath = targetPath;
122  }
123  
124  private String formatPath(String path) {
125    return "`" + path + "'";
126  }
127}