001 package railo.commons.io.res.type.ram; 002 003 import java.io.ByteArrayInputStream; 004 import java.io.ByteArrayOutputStream; 005 import java.io.IOException; 006 import java.io.InputStream; 007 import java.io.OutputStream; 008 009 import railo.commons.io.ModeUtil; 010 import railo.commons.io.res.ContentType; 011 import railo.commons.io.res.Resource; 012 import railo.commons.io.res.ResourceProvider; 013 import railo.commons.io.res.util.ResourceSupport; 014 import railo.commons.io.res.util.ResourceUtil; 015 import railo.commons.lang.StringUtil; 016 017 018 /** 019 * a ram resource 020 */ 021 public final class RamResource extends ResourceSupport { 022 023 private final RamResourceProviderOld provider; 024 025 private final String parent; 026 private final String name; 027 private RamResourceCore _core; 028 029 RamResource(RamResourceProviderOld provider, String path) { 030 this.provider=provider; 031 if(path.equals("/") || StringUtil.isEmpty(path)) { 032 //if(path.equals("/")) { 033 this.parent=null; 034 this.name=""; 035 } 036 else { 037 String[] pn = ResourceUtil.translatePathName(path); 038 this.parent=pn[0]; 039 this.name=pn[1]; 040 } 041 042 } 043 044 private RamResource(RamResourceProviderOld provider, String parent,String name) { 045 this.provider=provider; 046 this.parent=parent ; 047 this.name=name; 048 } 049 050 RamResourceCore getCore() { 051 if(_core==null || _core.getType()==0) { 052 _core=provider.getCore(getInnerPath()); 053 } 054 return _core; 055 } 056 057 058 void removeCore() { 059 if(_core==null)return; 060 _core.remove(); 061 _core=null; 062 } 063 064 private RamResourceCore createCore(int type) throws IOException { 065 return _core=provider.createCore(getInnerPath(),type); 066 } 067 068 069 @Override 070 public String getPath() { 071 return provider.getScheme().concat("://").concat(getInnerPath()); 072 } 073 private String getInnerPath() { 074 if(parent==null) return "/"; 075 return parent.concat(name); 076 } 077 078 @Override 079 public String getName() { 080 return name; 081 } 082 083 @Override 084 public String getParent() { 085 if(isRoot()) return null; 086 return provider.getScheme().concat("://").concat(ResourceUtil.translatePath(parent, true, false)); 087 } 088 089 @Override 090 public boolean isReadable() { 091 return ModeUtil.isReadable(getMode()); 092 } 093 094 @Override 095 public boolean isWriteable() { 096 return ModeUtil.isWritable(getMode()); 097 } 098 099 @Override 100 public void remove(boolean force) throws IOException { 101 if(isRoot()) 102 throw new IOException("can't remove root resource ["+getPath()+"]"); 103 104 provider.read(this); 105 RamResourceCore core = getCore(); 106 if(core==null) 107 throw new IOException("can't remove resource ["+getPath()+"],resource does not exist"); 108 109 Resource[] children = listResources(); 110 if(children!=null && children.length>0) { 111 if(!force) { 112 throw new IOException("can't delete directory ["+getPath()+"], directory is not empty"); 113 } 114 for(int i=0;i<children.length;i++) { 115 children[i].remove(true); 116 } 117 } 118 removeCore(); 119 } 120 121 @Override 122 public boolean exists() { 123 try { 124 provider.read(this); 125 } catch (IOException e) { 126 return true; 127 } 128 return getCore()!=null; 129 } 130 131 @Override 132 public Resource getParentResource() { 133 return getParentRamResource(); 134 } 135 136 137 private RamResource getParentRamResource() { 138 if(isRoot()) return null; 139 return new RamResource(provider,parent); 140 } 141 142 public Resource getRealResource(String realpath) { 143 realpath=ResourceUtil.merge(getInnerPath(), realpath); 144 if(realpath.startsWith("../"))return null; 145 146 return new RamResource(provider,realpath); 147 } 148 149 @Override 150 public boolean isAbsolute() { 151 return true; 152 } 153 154 @Override 155 public boolean isDirectory() { 156 return exists() && getCore().getType()==RamResourceCore.TYPE_DIRECTORY; 157 } 158 159 @Override 160 public boolean isFile() { 161 return exists() && getCore().getType()==RamResourceCore.TYPE_FILE; 162 } 163 164 @Override 165 public long lastModified() { 166 if(!exists()) return 0; 167 return getCore().getLastModified(); 168 } 169 170 @Override 171 public long length() { 172 if(!exists()) return 0; 173 byte[] data= getCore().getData(); 174 if(data==null) return 0; 175 return data.length; 176 } 177 178 @Override 179 public String[] list() { 180 if(!exists()) return null; 181 RamResourceCore core = getCore(); 182 if(core.getType()!=RamResourceCore.TYPE_DIRECTORY) 183 return null; 184 185 return core.getChildNames(); 186 /*List list = core.getChildren(); 187 if(list==null && list.size()==0) return new String[0]; 188 189 Iterator it = list.iterator(); 190 String[] children=new String[list.size()]; 191 RamResourceCore cc; 192 int count=0; 193 while(it.hasNext()) { 194 cc=(RamResourceCore) it.next(); 195 children[count++]=cc.getName(); 196 } 197 return children;*/ 198 } 199 200 @Override 201 public Resource[] listResources() { 202 String[] list = list(); 203 if(list==null)return null; 204 205 Resource[] children=new Resource[list.length]; 206 String p=getInnerPath(); 207 if(!isRoot())p=p.concat("/"); 208 for(int i=0;i<children.length;i++) { 209 children[i]=new RamResource(provider,p,list[i]); 210 } 211 return children; 212 } 213 214 @Override 215 public boolean setLastModified(long time) { 216 if(!exists()) return false; 217 getCore().setLastModified(time); 218 return true; 219 } 220 221 @Override 222 public boolean setReadOnly() { 223 return setWritable(false); 224 } 225 226 @Override 227 public void createFile(boolean createParentWhenNotExists) throws IOException { 228 ResourceUtil.checkCreateFileOK(this,createParentWhenNotExists); 229 provider.lock(this); 230 try { 231 createCore(RamResourceCore.TYPE_FILE); 232 } 233 finally { 234 provider.unlock(this); 235 } 236 } 237 238 239 @Override 240 public void createDirectory(boolean createParentWhenNotExists) throws IOException { 241 ResourceUtil.checkCreateDirectoryOK(this,createParentWhenNotExists); 242 provider.lock(this); 243 try { 244 createCore(RamResourceCore.TYPE_DIRECTORY); 245 } 246 finally { 247 provider.unlock(this); 248 } 249 250 } 251 252 @Override 253 public InputStream getInputStream() throws IOException { 254 ResourceUtil.checkGetInputStreamOK(this); 255 256 provider.lock(this); 257 RamResourceCore core = getCore(); 258 259 byte[] data = core.getData(); 260 if(data==null)data=new byte[0]; 261 provider.unlock(this); 262 return new ByteArrayInputStream(data); 263 } 264 265 public OutputStream getOutputStream(boolean append) throws IOException { 266 ResourceUtil.checkGetOutputStreamOK(this); 267 provider.lock(this); 268 return new RamOutputStream(this,append); 269 } 270 271 public ContentType getContentType() { 272 return ResourceUtil.getContentType(this); 273 } 274 275 @Override 276 public ResourceProvider getResourceProvider() { 277 return provider; 278 } 279 @Override 280 public String toString() { 281 return getPath(); 282 } 283 284 285 /** 286 * This is useed by the MemoryResource too write back data to, that are written to outputstream 287 */ 288 class RamOutputStream extends ByteArrayOutputStream { 289 290 private RamResource res; 291 private boolean append; 292 293 /** 294 * Constructor of the class 295 * @param res 296 */ 297 public RamOutputStream(RamResource res, boolean append) { 298 this.append=append; 299 this.res=res; 300 } 301 302 @Override 303 public void close() throws IOException { 304 try { 305 super.close(); 306 RamResourceCore core = res.getCore(); 307 if(core==null)core=res.createCore(RamResourceCore.TYPE_FILE); 308 309 core.setData(this.toByteArray(),append); 310 } 311 finally { 312 res.getResourceProvider().unlock(res); 313 } 314 } 315 } 316 317 @Override 318 public boolean setReadable(boolean value) { 319 if(!exists())return false; 320 try { 321 setMode(ModeUtil.setReadable(getMode(), value)); 322 return true; 323 } catch (IOException e) { 324 return false; 325 } 326 327 } 328 329 @Override 330 public boolean setWritable(boolean value) { 331 if(!exists())return false; 332 try { 333 setMode(ModeUtil.setWritable(getMode(), value)); 334 return true; 335 } catch (IOException e) { 336 return false; 337 } 338 } 339 340 private boolean isRoot() { 341 return parent==null; 342 } 343 344 public int getMode() { 345 if(!exists())return 0; 346 return getCore().getMode(); 347 } 348 349 public void setMode(int mode) throws IOException { 350 if(!exists())throw new IOException("can't set mode on resource ["+this+"], resource does not exist"); 351 getCore().setMode(mode); 352 } 353 @Override 354 public boolean getAttribute(short attribute) { 355 if(!exists())return false; 356 return (getCore().getAttributes()&attribute)>0; 357 } 358 @Override 359 public void setAttribute(short attribute, boolean value) throws IOException { 360 if(!exists())throw new IOException("can't get attributes on resource ["+this+"], resource does not exist"); 361 int attr = getCore().getAttributes(); 362 if(value) { 363 if((attr&attribute)==0) attr+=attribute; 364 } 365 else { 366 if((attr&attribute)>0) attr-=attribute; 367 } 368 getCore().setAttributes(attr); 369 } 370 371 }