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 */
018 package org.apache.hadoop.fs;
019
020 import java.io.DataInput;
021 import java.io.DataOutput;
022 import java.io.IOException;
023
024 import org.apache.hadoop.classification.InterfaceAudience;
025 import org.apache.hadoop.classification.InterfaceStability;
026 import org.apache.hadoop.fs.permission.FsPermission;
027 import org.apache.hadoop.io.Text;
028 import org.apache.hadoop.io.Writable;
029
030 /** Interface that represents the client side information for a file.
031 */
032 @InterfaceAudience.Public
033 @InterfaceStability.Stable
034 public class FileStatus implements Writable, Comparable {
035
036 private Path path;
037 private long length;
038 private boolean isdir;
039 private short block_replication;
040 private long blocksize;
041 private long modification_time;
042 private long access_time;
043 private FsPermission permission;
044 private String owner;
045 private String group;
046 private Path symlink;
047
048 public FileStatus() { this(0, false, 0, 0, 0, 0, null, null, null, null); }
049
050 //We should deprecate this soon?
051 public FileStatus(long length, boolean isdir, int block_replication,
052 long blocksize, long modification_time, Path path) {
053
054 this(length, isdir, block_replication, blocksize, modification_time,
055 0, null, null, null, path);
056 }
057
058 /**
059 * Constructor for file systems on which symbolic links are not supported
060 */
061 public FileStatus(long length, boolean isdir,
062 int block_replication,
063 long blocksize, long modification_time, long access_time,
064 FsPermission permission, String owner, String group,
065 Path path) {
066 this(length, isdir, block_replication, blocksize, modification_time,
067 access_time, permission, owner, group, null, path);
068 }
069
070 public FileStatus(long length, boolean isdir,
071 int block_replication,
072 long blocksize, long modification_time, long access_time,
073 FsPermission permission, String owner, String group,
074 Path symlink,
075 Path path) {
076 this.length = length;
077 this.isdir = isdir;
078 this.block_replication = (short)block_replication;
079 this.blocksize = blocksize;
080 this.modification_time = modification_time;
081 this.access_time = access_time;
082 if (permission != null) {
083 this.permission = permission;
084 } else if (isdir) {
085 this.permission = FsPermission.getDirDefault();
086 } else if (symlink!=null) {
087 this.permission = FsPermission.getDefault();
088 } else {
089 this.permission = FsPermission.getFileDefault();
090 }
091 this.owner = (owner == null) ? "" : owner;
092 this.group = (group == null) ? "" : group;
093 this.symlink = symlink;
094 this.path = path;
095 // The variables isdir and symlink indicate the type:
096 // 1. isdir implies directory, in which case symlink must be null.
097 // 2. !isdir implies a file or symlink, symlink != null implies a
098 // symlink, otherwise it's a file.
099 assert (isdir && symlink == null) || !isdir;
100 }
101
102 /**
103 * Get the length of this file, in bytes.
104 * @return the length of this file, in bytes.
105 */
106 public long getLen() {
107 return length;
108 }
109
110 /**
111 * Is this a file?
112 * @return true if this is a file
113 */
114 public boolean isFile() {
115 return !isdir && !isSymlink();
116 }
117
118 /**
119 * Is this a directory?
120 * @return true if this is a directory
121 */
122 public boolean isDirectory() {
123 return isdir;
124 }
125
126 /**
127 * Old interface, instead use the explicit {@link FileStatus#isFile()},
128 * {@link FileStatus#isDirectory()}, and {@link FileStatus#isSymlink()}
129 * @return true if this is a directory.
130 * @deprecated Use {@link FileStatus#isFile()},
131 * {@link FileStatus#isDirectory()}, and {@link FileStatus#isSymlink()}
132 * instead.
133 */
134 @Deprecated
135 public boolean isDir() {
136 return isdir;
137 }
138
139 /**
140 * Is this a table type
141 * @return true if this is a table object, it cannot be a diretory.
142 */
143 public boolean isTable() {
144 return false;
145 }
146
147 /**
148 * Is this a symbolic link?
149 * @return true if this is a symbolic link
150 */
151 public boolean isSymlink() {
152 return symlink != null;
153 }
154
155 /**
156 * Get the block size of the file.
157 * @return the number of bytes
158 */
159 public long getBlockSize() {
160 return blocksize;
161 }
162
163 /**
164 * Get the replication factor of a file.
165 * @return the replication factor of a file.
166 */
167 public short getReplication() {
168 return block_replication;
169 }
170
171 /**
172 * Get the modification time of the file.
173 * @return the modification time of file in milliseconds since January 1, 1970 UTC.
174 */
175 public long getModificationTime() {
176 return modification_time;
177 }
178
179 /**
180 * Get the access time of the file.
181 * @return the access time of file in milliseconds since January 1, 1970 UTC.
182 */
183 public long getAccessTime() {
184 return access_time;
185 }
186
187 /**
188 * Get FsPermission associated with the file.
189 * @return permssion. If a filesystem does not have a notion of permissions
190 * or if permissions could not be determined, then default
191 * permissions equivalent of "rwxrwxrwx" is returned.
192 */
193 public FsPermission getPermission() {
194 return permission;
195 }
196
197 /**
198 * Get the owner of the file.
199 * @return owner of the file. The string could be empty if there is no
200 * notion of owner of a file in a filesystem or if it could not
201 * be determined (rare).
202 */
203 public String getOwner() {
204 return owner;
205 }
206
207 /**
208 * Get the group associated with the file.
209 * @return group for the file. The string could be empty if there is no
210 * notion of group of a file in a filesystem or if it could not
211 * be determined (rare).
212 */
213 public String getGroup() {
214 return group;
215 }
216
217 public Path getPath() {
218 return path;
219 }
220
221 public void setPath(final Path p) {
222 path = p;
223 }
224
225 /* These are provided so that these values could be loaded lazily
226 * by a filesystem (e.g. local file system).
227 */
228
229 /**
230 * Sets permission.
231 * @param permission if permission is null, default value is set
232 */
233 protected void setPermission(FsPermission permission) {
234 this.permission = (permission == null) ?
235 FsPermission.getFileDefault() : permission;
236 }
237
238 /**
239 * Sets owner.
240 * @param owner if it is null, default value is set
241 */
242 protected void setOwner(String owner) {
243 this.owner = (owner == null) ? "" : owner;
244 }
245
246 /**
247 * Sets group.
248 * @param group if it is null, default value is set
249 */
250 protected void setGroup(String group) {
251 this.group = (group == null) ? "" : group;
252 }
253
254 /**
255 * @return The contents of the symbolic link.
256 */
257 public Path getSymlink() throws IOException {
258 if (!isSymlink()) {
259 throw new IOException("Path " + path + " is not a symbolic link");
260 }
261 return symlink;
262 }
263
264 public void setSymlink(final Path p) {
265 symlink = p;
266 }
267
268 //////////////////////////////////////////////////
269 // Writable
270 //////////////////////////////////////////////////
271 @Override
272 public void write(DataOutput out) throws IOException {
273 Text.writeString(out, getPath().toString(), Text.DEFAULT_MAX_LEN);
274 out.writeLong(getLen());
275 out.writeBoolean(isDirectory());
276 out.writeShort(getReplication());
277 out.writeLong(getBlockSize());
278 out.writeLong(getModificationTime());
279 out.writeLong(getAccessTime());
280 getPermission().write(out);
281 Text.writeString(out, getOwner(), Text.DEFAULT_MAX_LEN);
282 Text.writeString(out, getGroup(), Text.DEFAULT_MAX_LEN);
283 out.writeBoolean(isSymlink());
284 if (isSymlink()) {
285 Text.writeString(out, getSymlink().toString(), Text.DEFAULT_MAX_LEN);
286 }
287 }
288
289 @Override
290 public void readFields(DataInput in) throws IOException {
291 String strPath = Text.readString(in, Text.DEFAULT_MAX_LEN);
292 this.path = new Path(strPath);
293 this.length = in.readLong();
294 this.isdir = in.readBoolean();
295 this.block_replication = in.readShort();
296 blocksize = in.readLong();
297 modification_time = in.readLong();
298 access_time = in.readLong();
299 permission.readFields(in);
300 owner = Text.readString(in, Text.DEFAULT_MAX_LEN);
301 group = Text.readString(in, Text.DEFAULT_MAX_LEN);
302 if (in.readBoolean()) {
303 this.symlink = new Path(Text.readString(in, Text.DEFAULT_MAX_LEN));
304 } else {
305 this.symlink = null;
306 }
307 }
308
309 /**
310 * Compare this object to another object
311 *
312 * @param o the object to be compared.
313 * @return a negative integer, zero, or a positive integer as this object
314 * is less than, equal to, or greater than the specified object.
315 *
316 * @throws ClassCastException if the specified object's is not of
317 * type FileStatus
318 */
319 @Override
320 public int compareTo(Object o) {
321 FileStatus other = (FileStatus)o;
322 return this.getPath().compareTo(other.getPath());
323 }
324
325 /** Compare if this object is equal to another object
326 * @param o the object to be compared.
327 * @return true if two file status has the same path name; false if not.
328 */
329 @Override
330 public boolean equals(Object o) {
331 if (o == null) {
332 return false;
333 }
334 if (this == o) {
335 return true;
336 }
337 if (!(o instanceof FileStatus)) {
338 return false;
339 }
340 FileStatus other = (FileStatus)o;
341 return this.getPath().equals(other.getPath());
342 }
343
344 /**
345 * Returns a hash code value for the object, which is defined as
346 * the hash code of the path name.
347 *
348 * @return a hash code value for the path name.
349 */
350 @Override
351 public int hashCode() {
352 return getPath().hashCode();
353 }
354
355 @Override
356 public String toString() {
357 StringBuilder sb = new StringBuilder();
358 sb.append(getClass().getSimpleName());
359 sb.append("{");
360 sb.append("path=" + path);
361 sb.append("; isDirectory=" + isdir);
362 if(!isDirectory()){
363 sb.append("; length=" + length);
364 sb.append("; replication=" + block_replication);
365 sb.append("; blocksize=" + blocksize);
366 }
367 sb.append("; modification_time=" + modification_time);
368 sb.append("; access_time=" + access_time);
369 sb.append("; owner=" + owner);
370 sb.append("; group=" + group);
371 sb.append("; permission=" + permission);
372 sb.append("; isSymlink=" + isSymlink());
373 if(isSymlink()) {
374 sb.append("; symlink=" + symlink);
375 }
376 sb.append("}");
377 return sb.toString();
378 }
379 }