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.ram;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  
24  import org.apache.commons.lang3.ArrayUtils;
25  import org.apache.commons.vfs2.FileObject;
26  import org.apache.commons.vfs2.FileSystemException;
27  import org.apache.commons.vfs2.FileSystemOptions;
28  import org.apache.commons.vfs2.FileType;
29  import org.apache.commons.vfs2.RandomAccessContent;
30  import org.apache.commons.vfs2.provider.AbstractFileName;
31  import org.apache.commons.vfs2.provider.AbstractFileObject;
32  import org.apache.commons.vfs2.util.FileObjectUtils;
33  import org.apache.commons.vfs2.util.RandomAccessMode;
34  
35  /**
36   * A RAM File contains a single RAM FileData instance, it provides methods to access the data by implementing FileObject
37   * interface.
38   */
39  public class RamFileObject extends AbstractFileObject<RamFileSystem> {
40  
41      /**
42       * RAM File Object Data.
43       */
44      private RamFileData data;
45  
46      /**
47       * Constructs a new instance.
48       *
49       * @param fileName the file name.
50       * @param fileSystem the file system.
51       */
52      protected RamFileObject(final AbstractFileName fileName, final RamFileSystem fileSystem) {
53          super(fileName, fileSystem);
54          getAbstractFileSystem().attach(this);
55      }
56  
57      /*
58       * (non-Javadoc)
59       *
60       * @see org.apache.commons.vfs2.provider.AbstractFileObject#doAttach()
61       */
62      @Override
63      protected void doAttach() throws Exception {
64          getAbstractFileSystem().attach(this);
65      }
66  
67      /*
68       * (non-Javadoc)
69       *
70       * @see org.apache.commons.vfs2.provider.AbstractFileObject#doCreateFolder()
71       */
72      @Override
73      protected void doCreateFolder() throws Exception {
74          injectType(FileType.FOLDER);
75          save();
76      }
77  
78      /*
79       * (non-Javadoc)
80       *
81       * @see org.apache.commons.vfs2.provider.AbstractFileObject#doDelete()
82       */
83      @Override
84      protected void doDelete() throws Exception {
85  
86          if (isContentOpen()) {
87              throw new FileSystemException(getName() + " cannot be deleted while the file is open");
88          }
89          getAbstractFileSystem().delete(this);
90      }
91  
92      /*
93       * (non-Javadoc)
94       *
95       * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetContentSize()
96       */
97      @Override
98      protected long doGetContentSize() throws Exception {
99          return size();
100     }
101 
102     /*
103      * (non-Javadoc)
104      *
105      * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetInputStream()
106      */
107     @Override
108     protected InputStream doGetInputStream(final int bufferSize) throws Exception {
109         // VFS-210: ram allows to gather an input stream even from a directory. So we need to check the type anyway.
110         if (!getType().hasContent()) {
111             throw new FileSystemException("vfs.provider/read-not-file.error", getName());
112         }
113 
114         return new ByteArrayInputStream(data.getContent());
115     }
116 
117     /*
118      * (non-Javadoc)
119      *
120      * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetLastModifiedTime()
121      */
122     @Override
123     protected long doGetLastModifiedTime() throws Exception {
124         return data.getLastModified();
125     }
126 
127     /*
128      * (non-Javadoc)
129      *
130      * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetOutputStream(boolean)
131      */
132     @Override
133     protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
134         if (!bAppend) {
135             data.setContent(ArrayUtils.EMPTY_BYTE_ARRAY);
136         }
137         return new RamFileOutputStream(this);
138     }
139 
140     /*
141      * (non-Javadoc)
142      *
143      * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetRandomAccessContent(
144      * org.apache.commons.vfs2.util.RandomAccessMode)
145      */
146     @Override
147     protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception {
148         return new RamFileRandomAccessContent(this, mode);
149     }
150 
151     /*
152      * (non-Javadoc)
153      *
154      * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetType()
155      */
156     @Override
157     protected FileType doGetType() throws Exception {
158         return data.getType();
159     }
160 
161     /*
162      * (non-Javadoc)
163      *
164      * @see org.apache.commons.vfs2.provider.AbstractFileObject#doListChildren()
165      */
166     @Override
167     protected String[] doListChildren() throws Exception {
168         return getAbstractFileSystem().listChildren(getName());
169     }
170 
171     /*
172      * (non-Javadoc)
173      *
174      * @see org.apache.commons.vfs2.provider.AbstractFileObject#doRename(org.apache.commons.vfs2.FileObject)
175      */
176     @Override
177     protected void doRename(final FileObject newFile) throws Exception {
178         final RamFileObject newRamFileObject = (RamFileObject) FileObjectUtils.getAbstractFileObject(newFile);
179         getAbstractFileSystem().rename(this, newRamFileObject);
180     }
181 
182     /*
183      * (non-Javadoc)
184      *
185      * @see org.apache.commons.vfs2.provider.AbstractFileObject#doSetLastModifiedTime(long)
186      */
187     /** @since 2.0 */
188     @Override
189     protected boolean doSetLastModifiedTime(final long modtime) throws Exception {
190         data.setLastModified(modtime);
191         return true;
192     }
193 
194     /*
195      * (non-Javadoc)
196      *
197      * @see org.apache.commons.vfs2.provider.AbstractFileObject#endOutput()
198      */
199     @Override
200     protected void endOutput() throws Exception {
201         super.endOutput();
202         save();
203     }
204 
205     /**
206      * @return the data.
207      */
208     RamFileData getData() {
209         return data;
210     }
211 
212     /*
213      * (non-Javadoc)
214      *
215      * @see org.apache.commons.vfs2.provider.AbstractFileObject#injectType(org.apache.commons.vfs2.FileType)
216      */
217     @Override
218     protected void injectType(final FileType fileType) {
219         data.setType(fileType);
220         super.injectType(fileType);
221     }
222 
223     /**
224      * @param newSize The new buffer size.
225      * @throws IOException if the new size exceeds the limit
226      */
227     synchronized void resize(final long newSize) throws IOException {
228         final RamFileSystem afs = getAbstractFileSystem();
229         final FileSystemOptions afsOptions = afs.getFileSystemOptions();
230         if (afsOptions != null) {
231             final long maxSize = RamFileSystemConfigBuilder.getInstance().getLongMaxSize(afsOptions);
232             if (afs.size() + newSize - size() > maxSize) {
233                 throw new IOException("FileSystem capacity (" + maxSize + ") exceeded.");
234             }
235         }
236         data.resize(newSize);
237     }
238 
239     private void save() throws FileSystemException {
240         getAbstractFileSystem().save(this);
241     }
242 
243     /**
244      * @param data The data to set.
245      */
246     void setData(final RamFileData data) {
247         this.data = data;
248     }
249 
250     /**
251      * @return the size of the {@link RamFileData}.
252      */
253     int size() {
254         return data == null ? 0 : data.size();
255     }
256 
257 }