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.vfs.provider.ram;
    18
    19  import java.io.BufferedOutputStream;
    20  import java.io.File;
    21  import java.io.IOException;
    22  import java.io.InputStream;
    23  import java.io.OutputStream;
    24  import java.io.Serializable;
    25  import java.util.Collection;
    26  import java.util.Collections;
    27  import java.util.HashMap;
    28  import java.util.Iterator;
    29  import java.util.Map;
    30
    31  import org.apache.commons.vfs.FileName;
    32  import org.apache.commons.vfs.FileObject;
    33  import org.apache.commons.vfs.FileSystemException;
    34  import org.apache.commons.vfs.FileSystemOptions;
    35  import org.apache.commons.vfs.FileType;
    36  import org.apache.commons.vfs.provider.AbstractFileSystem;
    37
    38  /***
    39   * A RAM File System
    40   */
    41  public class RamFileSystem extends AbstractFileSystem implements Serializable
    42  {
    43  	/***
    44  	 * Cache of RAM File Data
    45  	 */
    46  	private Map cache;
    47
    48  	/***
    49  	 * @param rootName
    50  	 * @param fileSystemOptions
    51  	 */
    52  	protected RamFileSystem(FileName rootName,
    53  			FileSystemOptions fileSystemOptions)
    54  	{
    55  		super(rootName, null, fileSystemOptions);
    56  		this.cache = Collections.synchronizedMap(new HashMap());
    57          // create root
    58          RamFileData rootData = new RamFileData(rootName) ;
    59          rootData.setType(FileType.FOLDER);
    60          rootData.setLastModified(System.currentTimeMillis());
    61          this.cache.put(rootName, rootData);
    62  	}
    63
    64  	/*
    65  	 * (non-Javadoc)
    66  	 *
    67  	 * @see org.apache.commons.vfs.provider.AbstractFileSystem#createFile(org.apache.commons.vfs.FileName)
    68  	 */
    69  	protected FileObject createFile(FileName name) throws Exception
    70  	{
    71  		RamFileObject file = new RamFileObject(name, this);
    72  		return file;
    73  	}
    74
    75  	/*
    76  	 * (non-Javadoc)
    77  	 *
    78  	 * @see org.apache.commons.vfs.provider.AbstractFileSystem#addCapabilities(java.util.Collection)
    79  	 */
    80  	protected void addCapabilities(Collection caps)
    81  	{
    82  		caps.addAll(RamFileProvider.capabilities);
    83  	}
    84
    85  	/***
    86  	 * @param name
    87  	 * @return children
    88  	 */
    89  	String[] listChildren(FileName name)
    90  	{
    91          RamFileData data = (RamFileData) this.cache.get(name);
    92  		Collection children = data.getChildren();
    93
    94          String[] names = new String[children.size()];
    95
    96          int pos = 0 ;
    97          Iterator iter = children.iterator() ;
    98          while (iter.hasNext())
    99          {
    100             RamFileData childData = (RamFileData) iter.next();
    101             names[pos] = childData.getName().getBaseName();
    102             pos++;
    103         }
    104
    105 		return names;
    106 	}
    107
    108 	/***
    109 	 * Delete a file
    110 	 *
    111 	 * @param file
    112 	 * @throws FileSystemException
    113 	 */
    114 	void delete(RamFileObject file) throws FileSystemException
    115 	{
    116 	    // root is read only check
    117         if (file.getParent()==null) {
    118             throw new FileSystemException("unable to delete root");
    119         }
    120
    121 		// Remove reference from cache
    122 		this.cache.remove(file.getName());
    123 		// Notify the parent
    124         RamFileObject parent = (RamFileObject) this.resolveFile(file
    125                 .getParent().getName());
    126         parent.getData().removeChild(file.getData());
    127 		parent.close();
    128 		// Close the file
    129 		file.getData().clear();
    130 		file.close();
    131 	}
    132
    133 	/***
    134 	 * Saves a file
    135 	 *
    136 	 * @param file
    137 	 * @throws FileSystemException
    138 	 */
    139 	void save(final RamFileObject file) throws FileSystemException
    140 	{
    141
    142 		// Validate name
    143 		if (file.getData().getName() == null)
    144 		{
    145 			throw new FileSystemException(new IllegalStateException(
    146 					"The data has no name. " + file));
    147 		}
    148
    149 		// Add to the parent
    150 		if (file.getName().getDepth() > 0)
    151 		{
    152 			RamFileData parentData = (RamFileData) this.cache.get(file
    153 					.getParent().getName());
    154 			// Only if not already added
    155 			if (!parentData.hasChildren(file.getData()))
    156 			{
    157 				RamFileObject parent = (RamFileObject) file.getParent();
    158 				parent.getData().addChild(file.getData());
    159 				parent.close();
    160 			}
    161 		}
    162 		// Store in cache
    163 		cache.put(file.getName(), file.getData());
    164 		file.getData().updateLastModified();
    165 		file.close();
    166 	}
    167
    168 	/***
    169 	 * @param from
    170 	 * @param to
    171 	 * @throws FileSystemException
    172 	 */
    173 	void rename(RamFileObject from, RamFileObject to)
    174 			throws FileSystemException
    175 	{
    176 		if (!this.cache.containsKey(from.getName()))
    177 		{
    178 			throw new FileSystemException("File does not exist: "
    179 					+ from.getName());
    180 		}
    181 		// Copy data
    182
    183 		to.getData().setBuffer(from.getData().getBuffer());
    184 		to.getData().setLastModified(from.getData().getLastModified());
    185 		to.getData().setType(from.getData().getType());
    186
    187 		this.save(to);
    188 		this.delete(from);
    189 	}
    190
    191 	public void attach(RamFileObject fo)
    192 	{
    193 		if (fo.getName() == null)
    194 		{
    195 			throw new IllegalArgumentException("Null argument");
    196 		}
    197 		RamFileData data = (RamFileData) this.cache.get(fo.getName());
    198 		if (data == null)
    199 		{
    200 			data = new RamFileData(fo.getName());
    201 		}
    202 		fo.setData(data);
    203 	}
    204
    205 	/***
    206 	 * Import a Tree
    207 	 *
    208 	 * @param file
    209 	 * @throws FileSystemException
    210 	 */
    211 	public void importTree(File file) throws FileSystemException
    212 	{
    213 		FileObject fileFo = getFileSystemManager().toFileObject(file);
    214 		this.toRamFileObject(fileFo, fileFo);
    215 	}
    216
    217 	/***
    218 	 * Import the given file with the name relative to the given root
    219 	 *
    220 	 * @param fo
    221 	 * @param root
    222 	 * @throws FileSystemException
    223 	 */
    224 	void toRamFileObject(FileObject fo, FileObject root)
    225 			throws FileSystemException
    226 	{
    227 		RamFileObject memFo = (RamFileObject) this.resolveFile(fo.getName()
    228 				.getPath().substring(root.getName().getPath().length()));
    229 		if (fo.getType().hasChildren())
    230 		{
    231 			// Create Folder
    232 			memFo.createFolder();
    233 			// Import recursively
    234 			FileObject[] fos = fo.getChildren();
    235 			for (int i = 0; i < fos.length; i++)
    236 			{
    237 				FileObject child = fos[i];
    238 				this.toRamFileObject(child, root);
    239 			}
    240 		}
    241 		else if (fo.getType().equals(FileType.FILE))
    242 		{
    243 			// Read bytes
    244 			try
    245 			{
    246 				InputStream is = fo.getContent().getInputStream();
    247 				try
    248 				{
    249 					OutputStream os = new BufferedOutputStream(memFo
    250 							.getOutputStream(), 512);
    251 					int i;
    252 					while ((i = is.read()) != -1)
    253 					{
    254 						os.write(i);
    255 					}
    256 					os.flush();
    257 					os.close();
    258 				}
    259 				finally
    260 				{
    261 					try
    262 					{
    263 						is.close();
    264 					}
    265 					catch (IOException e)
    266 					{
    267 						// ignore on close exception
    268 						;
    269 					}
    270 				}
    271 			}
    272 			catch (IOException e)
    273 			{
    274 				throw new FileSystemException(e.getClass().getName() + " "
    275 						+ e.getMessage());
    276 			}
    277 		}
    278 		else
    279 		{
    280 			throw new FileSystemException("File is not a folder nor a file "
    281 					+ memFo);
    282 		}
    283 	}
    284
    285 	/***
    286 	 * @return Returns the size of the FileSystem
    287 	 */
    288 	int size()
    289 	{
    290 		int size = 0;
    291 		Iterator iter = cache.values().iterator();
    292 		while (iter.hasNext())
    293 		{
    294 			RamFileData data = (RamFileData) iter.next();
    295 			size += data.size();
    296 		}
    297 		return size;
    298 	}
    299
    300 	/***
    301 	 * Close the RAMFileSystem
    302 	 */
    303 	public void close()
    304 	{
    305 		this.cache = null;
    306 		super.close();
    307 	}
    308 }