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.Serializable;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.Collections;
23  
24  import org.apache.commons.lang3.ArrayUtils;
25  import org.apache.commons.vfs2.FileName;
26  import org.apache.commons.vfs2.FileSystemException;
27  import org.apache.commons.vfs2.FileType;
28  
29  /**
30   * RAM File Object Data.
31   */
32  final class RamFileData implements Serializable {
33  
34      /**
35       * serialVersionUID format is YYYYMMDD for the date of the last binary change.
36       */
37      private static final long serialVersionUID = 20101208L;
38  
39      /**
40       * File Name.
41       */
42      private FileName name;
43  
44      /**
45       * File Type.
46       */
47      private FileType type;
48  
49      /**
50       * Bytes.
51       */
52      private byte[] content;
53  
54      /**
55       * Last modified time
56       */
57      private long lastModifiedMillis;
58  
59      /**
60       * Children
61       */
62      private final Collection<RamFileData> children;
63  
64      /**
65       * Constructs a new instance.
66       *
67       * @param name The file name.
68       */
69      RamFileData(final FileName name) {
70          children = Collections.synchronizedCollection(new ArrayList<>());
71          clear();
72          if (name == null) {
73              throw new IllegalArgumentException("name cannot be null");
74          }
75          this.name = name;
76      }
77  
78      /**
79       * Add a child.
80       *
81       * @param data The file data.
82       * @throws FileSystemException if an error occurs.
83       */
84      void addChild(final RamFileData data) throws FileSystemException {
85          if (!getType().hasChildren()) {
86              throw new FileSystemException("A child can only be added in a folder");
87          }
88  
89          FileSystemException.requireNonNull(data, "No child can be null");
90  
91          if (children.contains(data)) {
92              throw new FileSystemException("Child already exists. " + data);
93          }
94  
95          children.add(data);
96          updateLastModified();
97      }
98  
99      /**
100      */
101     void clear() {
102         content = ArrayUtils.EMPTY_BYTE_ARRAY;
103         updateLastModified();
104         type = FileType.IMAGINARY;
105         children.clear();
106         name = null;
107     }
108 
109     /*
110      * (non-Javadoc)
111      *
112      * @see Object#equals(Object)
113      */
114     @Override
115     public boolean equals(final Object o) {
116         if (this == o) {
117             return true;
118         }
119         if (!(o instanceof RamFileData)) {
120             return false;
121         }
122         final RamFileData data = (RamFileData) o;
123         return getName().equals(data.getName());
124     }
125 
126     /**
127      * @return the children.
128      */
129     Collection<RamFileData> getChildren() {
130         if (name == null) {
131             throw new IllegalStateException("Data is clear");
132         }
133         return children;
134     }
135 
136     /**
137      * @return the buffer.
138      */
139     byte[] getContent() {
140         return content;
141     }
142 
143     /**
144      * @return the lastModified.
145      */
146     long getLastModified() {
147         return lastModifiedMillis;
148     }
149 
150     /**
151      * @return the name.
152      */
153     FileName getName() {
154         return name;
155     }
156 
157     /**
158      * @return the type.
159      */
160     FileType getType() {
161         return type;
162     }
163 
164     boolean hasChildren(final RamFileData data) {
165         return children.contains(data);
166     }
167 
168     /*
169      * (non-Javadoc)
170      *
171      * @see Object#hashCode()
172      */
173     @Override
174     public int hashCode() {
175         return getName().hashCode();
176     }
177 
178     /**
179      * Remove a child.
180      *
181      * @param data The file data.
182      * @throws FileSystemException if an error occurs.
183      */
184     void removeChild(final RamFileData data) throws FileSystemException {
185         if (!getType().hasChildren()) {
186             throw new FileSystemException("A child can only be removed from a folder");
187         }
188         if (!children.contains(data)) {
189             throw new FileSystemException("Child not found. " + data);
190         }
191         children.remove(data);
192         updateLastModified();
193     }
194 
195     /**
196      * Resize the buffer
197      *
198      * @param newSize The new buffer size.
199      */
200     void resize(final long newSize) {
201         // A future implementation may allow longs/multiple buffer/and so on
202         if (newSize > Integer.MAX_VALUE) {
203             throw new IllegalArgumentException(
204                     String.format("newSize(%d) > Integer.MAX_VALUE(%d)", newSize, Integer.MAX_VALUE));
205         }
206         final int resize = (int) newSize;
207         final int size = size();
208         final byte[] newBuf = new byte[resize];
209         System.arraycopy(content, 0, newBuf, 0, Math.min(resize, size));
210         content = newBuf;
211         updateLastModified();
212     }
213 
214     /**
215      * @param content The buffer.
216      */
217     void setContent(final byte[] content) {
218         updateLastModified();
219         this.content = content;
220     }
221 
222     /**
223      * @param lastModifiedMillis The lastModified to set.
224      */
225     void setLastModified(final long lastModifiedMillis) {
226         this.lastModifiedMillis = lastModifiedMillis;
227     }
228 
229     /**
230      * @param type The type to set.
231      */
232     void setType(final FileType type) {
233         this.type = type;
234     }
235 
236     /**
237      * @return the size of the buffer
238      */
239     int size() {
240         return content.length;
241     }
242 
243     /*
244      * (non-Javadoc)
245      *
246      * @see Object#toString()
247      */
248     @Override
249     public String toString() {
250         return name.toString();
251     }
252 
253     void updateLastModified() {
254         lastModifiedMillis = System.currentTimeMillis();
255     }
256 
257 }