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: */
017: package org.apache.commons.vfs.provider.ram;
018:
019: import java.io.BufferedOutputStream;
020: import java.io.File;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024: import java.io.Serializable;
025: import java.util.Collection;
026: import java.util.Collections;
027: import java.util.HashMap;
028: import java.util.Iterator;
029: import java.util.Map;
030:
031: import org.apache.commons.vfs.FileName;
032: import org.apache.commons.vfs.FileObject;
033: import org.apache.commons.vfs.FileSystemException;
034: import org.apache.commons.vfs.FileSystemOptions;
035: import org.apache.commons.vfs.FileType;
036: import org.apache.commons.vfs.provider.AbstractFileSystem;
037:
038: /**
039: * A RAM File System
040: */
041: public class RamFileSystem extends AbstractFileSystem implements
042: Serializable {
043: /**
044: * Cache of RAM File Data
045: */
046: private Map cache;
047:
048: /**
049: * @param rootName
050: * @param fileSystemOptions
051: */
052: protected RamFileSystem(FileName rootName,
053: FileSystemOptions fileSystemOptions) {
054: super (rootName, null, fileSystemOptions);
055: this .cache = Collections.synchronizedMap(new HashMap());
056: // create root
057: RamFileData rootData = new RamFileData(rootName);
058: rootData.setType(FileType.FOLDER);
059: rootData.setLastModified(System.currentTimeMillis());
060: this .cache.put(rootName, rootData);
061: }
062:
063: /*
064: * (non-Javadoc)
065: *
066: * @see org.apache.commons.vfs.provider.AbstractFileSystem#createFile(org.apache.commons.vfs.FileName)
067: */
068: protected FileObject createFile(FileName name) throws Exception {
069: RamFileObject file = new RamFileObject(name, this );
070: return file;
071: }
072:
073: /*
074: * (non-Javadoc)
075: *
076: * @see org.apache.commons.vfs.provider.AbstractFileSystem#addCapabilities(java.util.Collection)
077: */
078: protected void addCapabilities(Collection caps) {
079: caps.addAll(RamFileProvider.capabilities);
080: }
081:
082: /**
083: * @param name
084: * @return children
085: */
086: String[] listChildren(FileName name) {
087: RamFileData data = (RamFileData) this .cache.get(name);
088: Collection children = data.getChildren();
089:
090: String[] names = new String[children.size()];
091:
092: int pos = 0;
093: Iterator iter = children.iterator();
094: while (iter.hasNext()) {
095: RamFileData childData = (RamFileData) iter.next();
096: names[pos] = childData.getName().getBaseName();
097: pos++;
098: }
099:
100: return names;
101: }
102:
103: /**
104: * Delete a file
105: *
106: * @param file
107: * @throws FileSystemException
108: */
109: void delete(RamFileObject file) throws FileSystemException {
110: // root is read only check
111: if (file.getParent() == null) {
112: throw new FileSystemException("unable to delete root");
113: }
114:
115: // Remove reference from cache
116: this .cache.remove(file.getName());
117: // Notify the parent
118: RamFileObject parent = (RamFileObject) this .resolveFile(file
119: .getParent().getName());
120: parent.getData().removeChild(file.getData());
121: parent.close();
122: // Close the file
123: file.getData().clear();
124: file.close();
125: }
126:
127: /**
128: * Saves a file
129: *
130: * @param file
131: * @throws FileSystemException
132: */
133: void save(final RamFileObject file) throws FileSystemException {
134:
135: // Validate name
136: if (file.getData().getName() == null) {
137: throw new FileSystemException(new IllegalStateException(
138: "The data has no name. " + file));
139: }
140:
141: // Add to the parent
142: if (file.getName().getDepth() > 0) {
143: RamFileData parentData = (RamFileData) this .cache.get(file
144: .getParent().getName());
145: // Only if not already added
146: if (!parentData.hasChildren(file.getData())) {
147: RamFileObject parent = (RamFileObject) file.getParent();
148: parent.getData().addChild(file.getData());
149: parent.close();
150: }
151: }
152: // Store in cache
153: cache.put(file.getName(), file.getData());
154: file.getData().updateLastModified();
155: file.close();
156: }
157:
158: /**
159: * @param from
160: * @param to
161: * @throws FileSystemException
162: */
163: void rename(RamFileObject from, RamFileObject to)
164: throws FileSystemException {
165: if (!this .cache.containsKey(from.getName())) {
166: throw new FileSystemException("File does not exist: "
167: + from.getName());
168: }
169: // Copy data
170:
171: to.getData().setBuffer(from.getData().getBuffer());
172: to.getData().setLastModified(from.getData().getLastModified());
173: to.getData().setType(from.getData().getType());
174:
175: this .save(to);
176: this .delete(from);
177: }
178:
179: public void attach(RamFileObject fo) {
180: if (fo.getName() == null) {
181: throw new IllegalArgumentException("Null argument");
182: }
183: RamFileData data = (RamFileData) this .cache.get(fo.getName());
184: if (data == null) {
185: data = new RamFileData(fo.getName());
186: }
187: fo.setData(data);
188: }
189:
190: /**
191: * Import a Tree
192: *
193: * @param file
194: * @throws FileSystemException
195: */
196: public void importTree(File file) throws FileSystemException {
197: FileObject fileFo = getFileSystemManager().toFileObject(file);
198: this .toRamFileObject(fileFo, fileFo);
199: }
200:
201: /**
202: * Import the given file with the name relative to the given root
203: *
204: * @param fo
205: * @param root
206: * @throws FileSystemException
207: */
208: void toRamFileObject(FileObject fo, FileObject root)
209: throws FileSystemException {
210: RamFileObject memFo = (RamFileObject) this .resolveFile(fo
211: .getName().getPath().substring(
212: root.getName().getPath().length()));
213: if (fo.getType().hasChildren()) {
214: // Create Folder
215: memFo.createFolder();
216: // Import recursively
217: FileObject[] fos = fo.getChildren();
218: for (int i = 0; i < fos.length; i++) {
219: FileObject child = fos[i];
220: this .toRamFileObject(child, root);
221: }
222: } else if (fo.getType().equals(FileType.FILE)) {
223: // Read bytes
224: try {
225: InputStream is = fo.getContent().getInputStream();
226: try {
227: OutputStream os = new BufferedOutputStream(memFo
228: .getOutputStream(), 512);
229: int i;
230: while ((i = is.read()) != -1) {
231: os.write(i);
232: }
233: os.flush();
234: os.close();
235: } finally {
236: try {
237: is.close();
238: } catch (IOException e) {
239: // ignore on close exception
240: ;
241: }
242: }
243: } catch (IOException e) {
244: throw new FileSystemException(e.getClass().getName()
245: + " " + e.getMessage());
246: }
247: } else {
248: throw new FileSystemException(
249: "File is not a folder nor a file " + memFo);
250: }
251: }
252:
253: /**
254: * @return Returns the size of the FileSystem
255: */
256: int size() {
257: int size = 0;
258: Iterator iter = cache.values().iterator();
259: while (iter.hasNext()) {
260: RamFileData data = (RamFileData) iter.next();
261: size += data.size();
262: }
263: return size;
264: }
265:
266: /**
267: * Close the RAMFileSystem
268: */
269: public void close() {
270: this.cache = null;
271: super.close();
272: }
273: }
|