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.vfs2.FileObject; 025import org.apache.commons.vfs2.FileSystemException; 026import org.apache.commons.vfs2.FileSystemOptions; 027import org.apache.commons.vfs2.FileType; 028import org.apache.commons.vfs2.RandomAccessContent; 029import org.apache.commons.vfs2.provider.AbstractFileName; 030import org.apache.commons.vfs2.provider.AbstractFileObject; 031import org.apache.commons.vfs2.util.FileObjectUtils; 032import org.apache.commons.vfs2.util.RandomAccessMode; 033 034/** 035 * A RAM File contains a single RAM FileData instance, it provides methods to access the data by implementing FileObject 036 * interface. 037 */ 038public class RamFileObject extends AbstractFileObject<RamFileSystem> { 039 /** 040 * RAM File Object Data. 041 */ 042 private RamFileData data; 043 044 /** 045 * @param name The name of the file. 046 * @param fs The FileSystem. 047 */ 048 protected RamFileObject(final AbstractFileName name, final RamFileSystem fs) { 049 super(name, fs); 050 this.getAbstractFileSystem().attach(this); 051 } 052 053 private void save() throws FileSystemException { 054 this.getAbstractFileSystem().save(this); 055 } 056 057 /* 058 * (non-Javadoc) 059 * 060 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetType() 061 */ 062 @Override 063 protected FileType doGetType() throws Exception { 064 return data.getType(); 065 } 066 067 /* 068 * (non-Javadoc) 069 * 070 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doListChildren() 071 */ 072 @Override 073 protected String[] doListChildren() throws Exception { 074 return this.getAbstractFileSystem().listChildren(this.getName()); 075 } 076 077 /* 078 * (non-Javadoc) 079 * 080 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetContentSize() 081 */ 082 @Override 083 protected long doGetContentSize() throws Exception { 084 return this.size(); 085 } 086 087 /* 088 * (non-Javadoc) 089 * 090 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetInputStream() 091 */ 092 @Override 093 protected InputStream doGetInputStream() throws Exception { 094 // VFS-210: ram allows to gather an input stream even from a directory. So we need to check the type anyway. 095 if (!getType().hasContent()) { 096 throw new FileSystemException("vfs.provider/read-not-file.error", getName()); 097 } 098 099 return new ByteArrayInputStream(this.data.getContent()); 100 } 101 102 /* 103 * (non-Javadoc) 104 * 105 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetOutputStream(boolean) 106 */ 107 @Override 108 protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception { 109 if (!bAppend) { 110 this.data.setContent(RamFileData.EMPTY); 111 } 112 return new RamFileOutputStream(this); 113 } 114 115 /* 116 * (non-Javadoc) 117 * 118 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doDelete() 119 */ 120 @Override 121 protected void doDelete() throws Exception { 122 123 if (this.isContentOpen()) { 124 throw new FileSystemException(this.getName() + " cannot be deleted while the file is openg"); 125 } 126 getAbstractFileSystem().delete(this); 127 } 128 129 /* 130 * (non-Javadoc) 131 * 132 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetLastModifiedTime() 133 */ 134 @Override 135 protected long doGetLastModifiedTime() throws Exception { 136 return data.getLastModified(); 137 } 138 139 /* 140 * (non-Javadoc) 141 * 142 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doSetLastModifiedTime(long) 143 */ 144 /** @since 2.0 */ 145 @Override 146 protected boolean doSetLastModifiedTime(final long modtime) throws Exception { 147 data.setLastModified(modtime); 148 return true; 149 } 150 151 /* 152 * (non-Javadoc) 153 * 154 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doCreateFolder() 155 */ 156 @Override 157 protected void doCreateFolder() throws Exception { 158 this.injectType(FileType.FOLDER); 159 this.save(); 160 } 161 162 /* 163 * (non-Javadoc) 164 * 165 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doRename(org.apache.commons.vfs2.FileObject) 166 */ 167 @Override 168 protected void doRename(final FileObject newFile) throws Exception { 169 final RamFileObject newRamFileObject = (RamFileObject) FileObjectUtils.getAbstractFileObject(newFile); 170 getAbstractFileSystem().rename(this, newRamFileObject); 171 } 172 173 /* 174 * (non-Javadoc) 175 * 176 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetRandomAccessContent( 177 * org.apache.commons.vfs2.util.RandomAccessMode) 178 */ 179 @Override 180 protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception { 181 return new RamFileRandomAccessContent(this, mode); 182 } 183 184 /* 185 * (non-Javadoc) 186 * 187 * @see org.apache.commons.vfs2.provider.AbstractFileObject#doAttach() 188 */ 189 @Override 190 protected void doAttach() throws Exception { 191 this.getAbstractFileSystem().attach(this); 192 } 193 194 /** 195 * @return Returns the data. 196 */ 197 RamFileData getData() { 198 return data; 199 } 200 201 /** 202 * @param data The data to set. 203 */ 204 void setData(final RamFileData data) { 205 this.data = data; 206 } 207 208 /* 209 * (non-Javadoc) 210 * 211 * @see org.apache.commons.vfs2.provider.AbstractFileObject#injectType(org.apache.commons.vfs2.FileType) 212 */ 213 @Override 214 protected void injectType(final FileType fileType) { 215 this.data.setType(fileType); 216 super.injectType(fileType); 217 } 218 219 /* 220 * (non-Javadoc) 221 * 222 * @see org.apache.commons.vfs2.provider.AbstractFileObject#endOutput() 223 */ 224 @Override 225 protected void endOutput() throws Exception { 226 super.endOutput(); 227 this.save(); 228 } 229 230 /** 231 * @return Returns the size of the {@link RamFileData}. 232 */ 233 int size() { 234 return data == null ? 0 : data.size(); 235 } 236 237 /** 238 * @param newSize 239 * @throws IOException if the new size exceeds the limit 240 */ 241 synchronized void resize(final long newSize) throws IOException { 242 final RamFileSystem afs = getAbstractFileSystem(); 243 final FileSystemOptions afsOptions = afs.getFileSystemOptions(); 244 if (afsOptions != null) { 245 final long maxSize = RamFileSystemConfigBuilder.getInstance().getLongMaxSize(afsOptions); 246 if (afs.size() + newSize - this.size() > maxSize) { 247 throw new IOException("FileSystem capacity (" + maxSize + ") exceeded."); 248 } 249 } 250 this.data.resize(newSize); 251 } 252 253}