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<String>();
37      private FileType type;
38  
39      protected TarFileObject(final AbstractFileName name,
40                              final TarArchiveEntry entry,
41                              final TarFileSystem fs,
42                              final boolean tarExists) throws FileSystemException
43      {
44          super(name, fs);
45          setTarEntry(entry);
46          if (!tarExists)
47          {
48              type = FileType.IMAGINARY;
49          }
50      }
51  
52      /**
53       * Sets the details for this file object.
54       * 
55       * Consider this method package private. TODO Might be made package private in the next major version. 
56       */
57      protected void setTarEntry(final TarArchiveEntry entry)
58      {
59          if (this.entry != null)
60          {
61              return;
62          }
63  
64          if (entry == null || entry.isDirectory())
65          {
66              type = FileType.FOLDER;
67          }
68          else
69          {
70              type = FileType.FILE;
71          }
72  
73          this.entry = entry;
74      }
75  
76      /**
77       * Attaches a child.
78       * @param childName Name of child to remember.
79       */
80      protected void attachChild(final FileName childName)
81      {
82          children.add(childName.getBaseName());
83      }
84  
85      /**
86       * Determines if this file can be written to.
87       *
88       * @return {@code true} if this file is writeable, {@code false} if not.
89       * @throws FileSystemException if an error occurs.
90       */
91      @Override
92      public boolean isWriteable() throws FileSystemException
93      {
94          return false;
95      }
96  
97      /**
98       * Returns the file's type.
99       */
100     @Override
101     protected FileType doGetType()
102     {
103         return type;
104     }
105 
106     /**
107      * Lists the children of the file.
108      */
109     @Override
110     protected String[] doListChildren()
111     {
112         try
113         {
114             if (!getType().hasChildren())
115             {
116                 return null;
117             }
118         }
119         catch (final FileSystemException e)
120         {
121             // should not happen as the type has already been cached.
122             throw new RuntimeException(e);
123         }
124 
125         return children.toArray(new String[children.size()]);
126     }
127 
128     /**
129      * Returns the size of the file content (in bytes).  Is only called if
130      * {@link #doGetType} returns {@link FileType#FILE}.
131      */
132     @Override
133     protected long doGetContentSize()
134     {
135         if (entry == null)
136         {
137             return 0;
138         }
139 
140         return entry.getSize();
141     }
142 
143     /**
144      * Returns the last modified time of this file.
145      */
146     @Override
147     protected long doGetLastModifiedTime() throws Exception
148     {
149         if (entry == null)
150         {
151             return 0;
152         }
153 
154         return entry.getModTime().getTime();
155     }
156 
157     /**
158      * Creates an input stream to read the file content from.  Is only called
159      * if  {@link #doGetType} returns {@link FileType#FILE}.  The input stream
160      * returned by this method is guaranteed to be closed before this
161      * method is called again.
162      */
163     @Override
164     protected InputStream doGetInputStream() throws Exception
165     {
166         // VFS-210: zip allows to gather an input stream even from a directory and will
167         // return -1 on the first read. getType should not be expensive and keeps the tests
168         // running
169         if (!getType().hasContent())
170         {
171             throw new FileSystemException("vfs.provider/read-not-file.error", getName());
172         }
173 
174         return getAbstractFileSystem().getInputStream(entry);
175     }
176 }