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.tar; 018 019import java.io.InputStream; 020import java.util.HashSet; 021 022import org.apache.commons.compress.archivers.tar.TarArchiveEntry; 023import org.apache.commons.vfs2.FileName; 024import org.apache.commons.vfs2.FileSystemException; 025import org.apache.commons.vfs2.FileType; 026import org.apache.commons.vfs2.provider.AbstractFileName; 027import org.apache.commons.vfs2.provider.AbstractFileObject; 028 029/** 030 * A file in a Tar file system. 031 */ 032public class TarFileObject extends AbstractFileObject<TarFileSystem> { 033 /** The TarArchiveEntry */ 034 private TarArchiveEntry entry; 035 private final HashSet<String> children = new HashSet<>(); 036 private FileType type; 037 038 protected TarFileObject(final AbstractFileName name, final TarArchiveEntry entry, final TarFileSystem fs, 039 final boolean tarExists) throws FileSystemException { 040 super(name, fs); 041 setTarEntry(entry); 042 if (!tarExists) { 043 type = FileType.IMAGINARY; 044 } 045 } 046 047 /** 048 * Sets the details for this file object. 049 * 050 * Consider this method package private. TODO Might be made package private in the next major version. 051 */ 052 protected void setTarEntry(final TarArchiveEntry entry) { 053 if (this.entry != null) { 054 return; 055 } 056 057 if (entry == null || entry.isDirectory()) { 058 type = FileType.FOLDER; 059 } else { 060 type = FileType.FILE; 061 } 062 063 this.entry = entry; 064 } 065 066 /** 067 * Attaches a child. 068 * 069 * @param childName Name of child to remember. 070 */ 071 protected void attachChild(final FileName childName) { 072 children.add(childName.getBaseName()); 073 } 074 075 /** 076 * Determines if this file can be written to. 077 * 078 * @return {@code true} if this file is writeable, {@code false} if not. 079 * @throws FileSystemException if an error occurs. 080 */ 081 @Override 082 public boolean isWriteable() throws FileSystemException { 083 return false; 084 } 085 086 /** 087 * Returns the file's type. 088 */ 089 @Override 090 protected FileType doGetType() { 091 return type; 092 } 093 094 /** 095 * Lists the children of the file. 096 */ 097 @Override 098 protected String[] doListChildren() { 099 try { 100 if (!getType().hasChildren()) { 101 return null; 102 } 103 } catch (final FileSystemException e) { 104 // should not happen as the type has already been cached. 105 throw new RuntimeException(e); 106 } 107 108 return children.toArray(new String[children.size()]); 109 } 110 111 /** 112 * Returns the size of the file content (in bytes). Is only called if {@link #doGetType} returns 113 * {@link FileType#FILE}. 114 */ 115 @Override 116 protected long doGetContentSize() { 117 if (entry == null) { 118 return 0; 119 } 120 121 return entry.getSize(); 122 } 123 124 /** 125 * Returns the last modified time of this file. 126 */ 127 @Override 128 protected long doGetLastModifiedTime() throws Exception { 129 if (entry == null) { 130 return 0; 131 } 132 133 return entry.getModTime().getTime(); 134 } 135 136 /** 137 * Creates an input stream to read the file content from. Is only called if {@link #doGetType} returns 138 * {@link FileType#FILE}. The input stream returned by this method is guaranteed to be closed before this method is 139 * called again. 140 */ 141 @Override 142 protected InputStream doGetInputStream() throws Exception { 143 // VFS-210: zip allows to gather an input stream even from a directory and will 144 // return -1 on the first read. getType should not be expensive and keeps the tests 145 // running 146 if (!getType().hasContent()) { 147 throw new FileSystemException("vfs.provider/read-not-file.error", getName()); 148 } 149 150 return getAbstractFileSystem().getInputStream(entry); 151 } 152}