1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 package org.apache.hadoop.hdfs.protocol;
20 
21 import java.io.IOException;
22 
23 import org.apache.hadoop.classification.InterfaceAudience;
24 import org.apache.hadoop.classification.InterfaceStability;
25 import org.apache.hadoop.fs.UnresolvedLinkException;
26 import org.apache.hadoop.fs.Path;
27 
28 /**
29  * Thrown when a symbolic link is encountered in a path.
30  */
31 @InterfaceAudience.Private
32 @InterfaceStability.Evolving
33 public final class UnresolvedPathException extends UnresolvedLinkException {
34   private static final long serialVersionUID = 1L;
35   private String path;        // The path containing the link
36   private String preceding;   // The path part preceding the link
37   private String remainder;   // The path part following the link
38   private String linkTarget;  // The link's target
39 
40   /**
41    * Used by RemoteException to instantiate an UnresolvedPathException.
42    */
UnresolvedPathException(String msg)43   public UnresolvedPathException(String msg) {
44     super(msg);
45   }
46 
UnresolvedPathException(String path, String preceding, String remainder, String linkTarget)47   public UnresolvedPathException(String path, String preceding,
48       String remainder, String linkTarget) {
49     this.path = path;
50     this.preceding = preceding;
51     this.remainder = remainder;
52     this.linkTarget = linkTarget;
53   }
54 
55   /**
56    * Return a path with the link resolved with the target.
57    */
getResolvedPath()58   public Path getResolvedPath() throws IOException {
59     // If the path is absolute we cam throw out the preceding part and
60     // just append the remainder to the target, otherwise append each
61     // piece to resolve the link in path.
62     boolean noRemainder = (remainder == null || "".equals(remainder));
63     Path target = new Path(linkTarget);
64     if (target.isUriPathAbsolute()) {
65       return noRemainder ? target : new Path(target, remainder);
66     } else {
67       return noRemainder
68         ? new Path(preceding, target)
69         : new Path(new Path(preceding, linkTarget), remainder);
70     }
71   }
72 
73   @Override
getMessage()74   public String getMessage() {
75     String msg = super.getMessage();
76     if (msg != null) {
77       return msg;
78     }
79     String myMsg = "Unresolved path " + path;
80     try {
81       return getResolvedPath().toString();
82     } catch (IOException e) {
83       // Ignore
84     }
85     return myMsg;
86   }
87 }
88