001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.vfs2.provider.hdfs; 018 019import java.io.FileNotFoundException; 020import java.io.IOException; 021import java.io.InputStream; 022import java.io.OutputStream; 023import java.util.HashMap; 024import java.util.Map; 025import java.util.Objects; 026import java.util.stream.Stream; 027 028import org.apache.commons.vfs2.FileNotFolderException; 029import org.apache.commons.vfs2.FileObject; 030import org.apache.commons.vfs2.FileSystemException; 031import org.apache.commons.vfs2.FileType; 032import org.apache.commons.vfs2.RandomAccessContent; 033import org.apache.commons.vfs2.provider.AbstractFileName; 034import org.apache.commons.vfs2.provider.AbstractFileObject; 035import org.apache.commons.vfs2.util.RandomAccessMode; 036import org.apache.hadoop.fs.FileStatus; 037import org.apache.hadoop.fs.FileSystem; 038import org.apache.hadoop.fs.Path; 039 040/** 041 * A VFS representation of an HDFS file. 042 * 043 * @since 2.1 044 */ 045public class HdfsFileObject extends AbstractFileObject<HdfsFileSystem> { 046 047 private final HdfsFileSystem fs; 048 private final FileSystem hdfs; 049 private final Path path; 050 private FileStatus stat; 051 052 /** 053 * Constructs a new HDFS FileObject 054 * 055 * @param name FileName 056 * @param fs HdfsFileSystem instance 057 * @param hdfs Hadoop FileSystem instance 058 * @param path Path to the file in HDFS 059 */ 060 protected HdfsFileObject(final AbstractFileName name, final HdfsFileSystem fs, final FileSystem hdfs, 061 final Path path) { 062 super(name, fs); 063 this.fs = fs; 064 this.hdfs = hdfs; 065 this.path = path; 066 } 067 068 /** 069 * @see org.apache.commons.vfs2.provider.AbstractFileObject#canRenameTo(org.apache.commons.vfs2.FileObject) 070 */ 071 @Override 072 public boolean canRenameTo(final FileObject newfile) { 073 if (!super.canRenameTo(newfile)) { 074 return false; 075 } 076 try { 077 return hdfs.getFileStatus(new Path(newfile.getName().getPath())) == null; 078 } catch (final FileNotFoundException e) { 079 return false; 080 } catch (final IOException e) { 081 throw new IllegalStateException(e); 082 } 083 } 084 085 /** 086 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doAttach() 087 */ 088 @Override 089 protected void doAttach() throws Exception { 090 try { 091 stat = hdfs.getFileStatus(path); 092 } catch (final FileNotFoundException e) { 093 stat = null; 094 } 095 } 096 097 /** 098 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doCreateFolder() 099 * @since 2.7.0 100 */ 101 @Override 102 protected void doCreateFolder() throws Exception { 103 hdfs.mkdirs(path); 104 } 105 106 /** 107 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doDelete() 108 * @since 2.7.0 109 */ 110 @Override 111 protected void doDelete() throws Exception { 112 hdfs.delete(path, true); 113 } 114 115 /** 116 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetAttributes() 117 */ 118 @Override 119 protected Map<String, Object> doGetAttributes() throws Exception { 120 if (null == stat) { 121 return super.doGetAttributes(); 122 } 123 final Map<String, Object> attrs = new HashMap<>(); 124 attrs.put(HdfsFileAttributes.LAST_ACCESS_TIME.toString(), stat.getAccessTime()); 125 attrs.put(HdfsFileAttributes.BLOCK_SIZE.toString(), stat.getBlockSize()); 126 attrs.put(HdfsFileAttributes.GROUP.toString(), stat.getGroup()); 127 attrs.put(HdfsFileAttributes.OWNER.toString(), stat.getOwner()); 128 attrs.put(HdfsFileAttributes.PERMISSIONS.toString(), stat.getPermission().toString()); 129 attrs.put(HdfsFileAttributes.LENGTH.toString(), stat.getLen()); 130 attrs.put(HdfsFileAttributes.MODIFICATION_TIME.toString(), stat.getModificationTime()); 131 return attrs; 132 } 133 134 /** 135 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetContentSize() 136 */ 137 @Override 138 protected long doGetContentSize() throws Exception { 139 return stat.getLen(); 140 } 141 142 /** 143 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetInputStream(int) 144 */ 145 @Override 146 protected InputStream doGetInputStream(final int bufferSize) throws Exception { 147 return hdfs.open(path, bufferSize); 148 } 149 150 /** 151 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetLastModifiedTime() 152 */ 153 @Override 154 protected long doGetLastModifiedTime() throws Exception { 155 doAttach(); 156 if (null != stat) { 157 return stat.getModificationTime(); 158 } 159 return -1; 160 } 161 162 /** 163 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetOutputStream(boolean) 164 * @since 2.7.0 165 */ 166 @Override 167 protected OutputStream doGetOutputStream(final boolean append) throws Exception { 168 if (append) { 169 throw new FileSystemException("vfs.provider/write-append-not-supported.error", path.getName()); 170 } 171 return hdfs.create(path); 172 } 173 174 /** 175 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetRandomAccessContent 176 * (org.apache.commons.vfs2.util.RandomAccessMode) 177 */ 178 @Override 179 protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception { 180 if (mode.equals(RandomAccessMode.READWRITE)) { 181 throw new UnsupportedOperationException(); 182 } 183 return new HdfsRandomAccessContent(path, hdfs); 184 } 185 186 /** 187 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetType() 188 */ 189 @Override 190 protected FileType doGetType() throws Exception { 191 try { 192 doAttach(); 193 if (null == stat) { 194 return FileType.IMAGINARY; 195 } 196 if (stat.isDirectory()) { 197 return FileType.FOLDER; 198 } 199 return FileType.FILE; 200 } catch (final FileNotFoundException fnfe) { 201 return FileType.IMAGINARY; 202 } 203 } 204 205 /** 206 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doIsHidden() 207 */ 208 @Override 209 protected boolean doIsHidden() throws Exception { 210 return false; 211 } 212 213 /** 214 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doIsReadable() 215 */ 216 @Override 217 protected boolean doIsReadable() throws Exception { 218 return true; 219 } 220 221 /** 222 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doIsWriteable() 223 */ 224 @Override 225 protected boolean doIsWriteable() throws Exception { 226 return true; 227 } 228 229 /** 230 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doListChildren() 231 */ 232 @Override 233 protected String[] doListChildren() throws Exception { 234 if (doGetType() != FileType.FOLDER) { 235 throw new FileNotFolderException(this); 236 } 237 238 final FileStatus[] fileStatuses = hdfs.listStatus(path); 239 return Stream.of(fileStatuses).filter(Objects::nonNull).map(status -> status.getPath().getName()).toArray(String[]::new); 240 } 241 242 /** 243 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doListChildrenResolved() 244 */ 245 @Override 246 protected FileObject[] doListChildrenResolved() throws Exception { 247 if (doGetType() != FileType.FOLDER) { 248 return null; 249 } 250 final String[] children = doListChildren(); 251 final FileObject[] fo = new FileObject[children.length]; 252 for (int i = 0; i < children.length; i++) { 253 final Path p = new Path(path, children[i]); 254 fo[i] = fs.resolveFile(p.toUri().toString()); 255 } 256 return fo; 257 } 258 259 /** 260 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doRemoveAttribute(String) 261 */ 262 @Override 263 protected void doRemoveAttribute(final String attrName) throws Exception { 264 throw new UnsupportedOperationException(); 265 } 266 267 /** 268 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doRename(FileObject) 269 * @since 2.7.0 270 */ 271 @Override 272 protected void doRename(final FileObject newfile) throws Exception { 273 hdfs.rename(path, new Path(newfile.getName().getPath())); 274 } 275 276 /** 277 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doSetAttribute(String, Object) 278 */ 279 @Override 280 protected void doSetAttribute(final String attrName, final Object value) throws Exception { 281 throw new UnsupportedOperationException(); 282 } 283 284 /** 285 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doSetLastModifiedTime(long) 286 */ 287 @Override 288 protected boolean doSetLastModifiedTime(final long modtime) throws Exception { 289 try { 290 hdfs.setTimes(path, modtime, System.currentTimeMillis()); 291 } catch (final IOException ioe) { 292 throw new FileSystemException(ioe); 293 } 294 return true; 295 } 296 297 /** 298 * @see org.apache.commons.vfs2.provider.AbstractFileObject#exists() 299 * @return boolean true if file exists, false if not 300 */ 301 @Override 302 public boolean exists() throws FileSystemException { 303 try { 304 doAttach(); 305 return stat != null; 306 } catch (final FileNotFoundException fne) { 307 return false; 308 } catch (final Exception e) { 309 throw new FileSystemException("Unable to check existence ", e); 310 } 311 } 312 313}