View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs2.provider.tar;
18  
19  import java.io.InputStream;
20  import java.util.HashSet;
21  
22  import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
23  import org.apache.commons.vfs2.FileName;
24  import org.apache.commons.vfs2.FileSystemException;
25  import org.apache.commons.vfs2.FileType;
26  import org.apache.commons.vfs2.provider.AbstractFileName;
27  import org.apache.commons.vfs2.provider.AbstractFileObject;
28  
29  /**
30   * A file in a Tar file system.
31   */
32  public class TarFileObject extends AbstractFileObject<TarFileSystem> {
33  
34      /** The TarArchiveEntry */
35      private TarArchiveEntry entry;
36      private final HashSet<String> children = new HashSet<>();
37      private FileType type;
38  
39      protected TarFileObject(final AbstractFileName name, final TarArchiveEntry entry, final TarFileSystem fs,
40              final boolean tarExists) throws FileSystemException {
41          super(name, fs);
42          setTarEntry(entry);
43          if (!tarExists) {
44              type = FileType.IMAGINARY;
45          }
46      }
47  
48      /**
49       * Sets the details for this file object.
50       *
51       * Consider this method package private. TODO Might be made package private in the next major version.
52       *
53       * @param entry Tar archive entry.
54       */
55      protected void setTarEntry(final TarArchiveEntry entry) {
56          if (this.entry != null) {
57              return;
58          }
59  
60          if (entry == null || entry.isDirectory()) {
61              type = FileType.FOLDER;
62          } else {
63              type = FileType.FILE;
64          }
65  
66          this.entry = entry;
67      }
68  
69      /**
70       * Attaches a child.
71       *
72       * @param childName Name of child to remember.
73       */
74      protected void attachChild(final FileName childName) {
75          children.add(childName.getBaseName());
76      }
77  
78      /**
79       * Determines if this file can be written to.
80       *
81       * @return {@code true} if this file is writeable, {@code false} if not.
82       * @throws FileSystemException if an error occurs.
83       */
84      @Override
85      public boolean isWriteable() throws FileSystemException {
86          return false;
87      }
88  
89      /**
90       * Returns the file's type.
91       */
92      @Override
93      protected FileType doGetType() {
94          return type;
95      }
96  
97      /**
98       * Lists the children of the file.
99       */
100     @Override
101     protected String[] doListChildren() {
102         try {
103             if (!getType().hasChildren()) {
104                 return null;
105             }
106         } catch (final FileSystemException e) {
107             // should not happen as the type has already been cached.
108             throw new RuntimeException(e);
109         }
110 
111         return children.toArray(new String[children.size()]);
112     }
113 
114     /**
115      * Returns the size of the file content (in bytes). Is only called if {@link #doGetType} returns
116      * {@link FileType#FILE}.
117      */
118     @Override
119     protected long doGetContentSize() {
120         if (entry == null) {
121             return 0;
122         }
123 
124         return entry.getSize();
125     }
126 
127     /**
128      * Returns the last modified time of this file.
129      */
130     @Override
131     protected long doGetLastModifiedTime() throws Exception {
132         if (entry == null) {
133             return 0;
134         }
135 
136         return entry.getModTime().getTime();
137     }
138 
139     /**
140      * Creates an input stream to read the file content from. Is only called if {@link #doGetType} returns
141      * {@link FileType#FILE}. The input stream returned by this method is guaranteed to be closed before this method is
142      * called again.
143      */
144     @Override
145     protected InputStream doGetInputStream() throws Exception {
146         // VFS-210: zip allows to gather an input stream even from a directory and will
147         // return -1 on the first read. getType should not be expensive and keeps the tests
148         // running
149         if (!getType().hasContent()) {
150             throw new FileSystemException("vfs.provider/read-not-file.error", getName());
151         }
152 
153         return getAbstractFileSystem().getInputStream(entry);
154     }
155 }