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 */ 017package org.apache.commons.vfs2.provider.ram; 018 019import java.io.ByteArrayInputStream; 020import java.io.IOException; 021import java.io.InputStream; 022import java.io.OutputStream; 023 024import org.apache.commons.lang3.ArrayUtils; 025import org.apache.commons.vfs2.FileObject; 026import org.apache.commons.vfs2.FileSystemException; 027import org.apache.commons.vfs2.FileSystemOptions; 028import org.apache.commons.vfs2.FileType; 029import org.apache.commons.vfs2.RandomAccessContent; 030import org.apache.commons.vfs2.provider.AbstractFileName; 031import org.apache.commons.vfs2.provider.AbstractFileObject; 032import org.apache.commons.vfs2.util.FileObjectUtils; 033import org.apache.commons.vfs2.util.RandomAccessMode; 034 035/** 036 * A RAM File contains a single RAM FileData instance, it provides methods to access the data by implementing FileObject 037 * interface. 038 */ 039public class RamFileObject extends AbstractFileObject<RamFileSystem> { 040 041 /** 042 * RAM File Object Data. 043 */ 044 private RamFileData data; 045 046 /** 047 * Constructs a new instance. 048 * 049 * @param fileName the file name. 050 * @param fileSystem the file system. 051 */ 052 protected RamFileObject(final AbstractFileName fileName, final RamFileSystem fileSystem) { 053 super(fileName, fileSystem); 054 getAbstractFileSystem().attach(this); 055 } 056 057 /* 058 * (non-Javadoc) 059 * 060 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doAttach() 061 */ 062 @Override 063 protected void doAttach() throws Exception { 064 getAbstractFileSystem().attach(this); 065 } 066 067 /* 068 * (non-Javadoc) 069 * 070 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doCreateFolder() 071 */ 072 @Override 073 protected void doCreateFolder() throws Exception { 074 injectType(FileType.FOLDER); 075 save(); 076 } 077 078 /* 079 * (non-Javadoc) 080 * 081 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doDelete() 082 */ 083 @Override 084 protected void doDelete() throws Exception { 085 086 if (isContentOpen()) { 087 throw new FileSystemException(getName() + " cannot be deleted while the file is open"); 088 } 089 getAbstractFileSystem().delete(this); 090 } 091 092 /* 093 * (non-Javadoc) 094 * 095 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetContentSize() 096 */ 097 @Override 098 protected long doGetContentSize() throws Exception { 099 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}