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 /** 070 * @see res.Resource#getPath() 071 */ 072 public String getPath() { 073 return provider.getScheme().concat("://").concat(getInnerPath()); 074 } 075 private String getInnerPath() { 076 if(parent==null) return "/"; 077 return parent.concat(name); 078 } 079 080 /** 081 * @see res.Resource#getFullName() 082 */ 083 public String getName() { 084 return name; 085 } 086 087 /** 088 * @see res.Resource#getParent() 089 */ 090 public String getParent() { 091 if(isRoot()) return null; 092 return provider.getScheme().concat("://").concat(ResourceUtil.translatePath(parent, true, false)); 093 } 094 095 /** 096 * @see res.Resource#isReadable() 097 */ 098 public boolean isReadable() { 099 return ModeUtil.isReadable(getMode()); 100 } 101 102 /** 103 * @see res.Resource#isWriteable() 104 */ 105 public boolean isWriteable() { 106 return ModeUtil.isWritable(getMode()); 107 } 108 109 /** 110 * @see res.Resource#removeE(boolean) 111 */ 112 public void remove(boolean force) throws IOException { 113 if(isRoot()) 114 throw new IOException("can't remove root resource ["+getPath()+"]"); 115 116 provider.read(this); 117 RamResourceCore core = getCore(); 118 if(core==null) 119 throw new IOException("can't remove resource ["+getPath()+"],resource does not exists"); 120 121 Resource[] children = listResources(); 122 if(children!=null && children.length>0) { 123 if(!force) { 124 throw new IOException("can't delete directory ["+getPath()+"], directory is not empty"); 125 } 126 for(int i=0;i<children.length;i++) { 127 children[i].remove(true); 128 } 129 } 130 removeCore(); 131 } 132 133 /** 134 * @see res.Resource#exists() 135 */ 136 public boolean exists() { 137 try { 138 provider.read(this); 139 } catch (IOException e) { 140 return true; 141 } 142 return getCore()!=null; 143 } 144 145 /** 146 * @see res.Resource#getParentResource() 147 */ 148 public Resource getParentResource() { 149 return getParentRamResource(); 150 } 151 152 153 private RamResource getParentRamResource() { 154 if(isRoot()) return null; 155 return new RamResource(provider,parent); 156 } 157 158 public Resource getRealResource(String realpath) { 159 realpath=ResourceUtil.merge(getInnerPath(), realpath); 160 if(realpath.startsWith("../"))return null; 161 162 return new RamResource(provider,realpath); 163 } 164 165 /** 166 * @see res.Resource#isAbsolute() 167 */ 168 public boolean isAbsolute() { 169 return true; 170 } 171 172 /** 173 * @see res.Resource#isDirectory() 174 */ 175 public boolean isDirectory() { 176 return exists() && getCore().getType()==RamResourceCore.TYPE_DIRECTORY; 177 } 178 179 /** 180 * @see res.Resource#isFile() 181 */ 182 public boolean isFile() { 183 return exists() && getCore().getType()==RamResourceCore.TYPE_FILE; 184 } 185 186 /** 187 * @see res.Resource#lastModified() 188 */ 189 public long lastModified() { 190 if(!exists()) return 0; 191 return getCore().getLastModified(); 192 } 193 194 /** 195 * @see res.Resource#length() 196 */ 197 public long length() { 198 if(!exists()) return 0; 199 byte[] data= getCore().getData(); 200 if(data==null) return 0; 201 return data.length; 202 } 203 204 /** 205 * @see res.Resource#list() 206 */ 207 public String[] list() { 208 if(!exists()) return null; 209 RamResourceCore core = getCore(); 210 if(core.getType()!=RamResourceCore.TYPE_DIRECTORY) 211 return null; 212 213 return core.getChildNames(); 214 /*List list = core.getChildren(); 215 if(list==null && list.size()==0) return new String[0]; 216 217 Iterator it = list.iterator(); 218 String[] children=new String[list.size()]; 219 RamResourceCore cc; 220 int count=0; 221 while(it.hasNext()) { 222 cc=(RamResourceCore) it.next(); 223 children[count++]=cc.getName(); 224 } 225 return children;*/ 226 } 227 228 /** 229 * @see res.Resource#listResources() 230 */ 231 public Resource[] listResources() { 232 String[] list = list(); 233 if(list==null)return null; 234 235 Resource[] children=new Resource[list.length]; 236 String p=getInnerPath(); 237 if(!isRoot())p=p.concat("/"); 238 for(int i=0;i<children.length;i++) { 239 children[i]=new RamResource(provider,p,list[i]); 240 } 241 return children; 242 } 243 244 /** 245 * @see res.Resource#setLastModified(long) 246 */ 247 public boolean setLastModified(long time) { 248 if(!exists()) return false; 249 getCore().setLastModified(time); 250 return true; 251 } 252 253 /** 254 * @see res.Resource#setReadOnly() 255 */ 256 public boolean setReadOnly() { 257 return setWritable(false); 258 } 259 260 /** 261 * @throws IOException 262 * @see res.Resource#createFile(boolean) 263 */ 264 public void createFile(boolean createParentWhenNotExists) throws IOException { 265 ResourceUtil.checkCreateFileOK(this,createParentWhenNotExists); 266 provider.lock(this); 267 try { 268 createCore(RamResourceCore.TYPE_FILE); 269 } 270 finally { 271 provider.unlock(this); 272 } 273 } 274 275 276 /** 277 * @see res.Resource#createDirectory(boolean) 278 */ 279 public void createDirectory(boolean createParentWhenNotExists) throws IOException { 280 ResourceUtil.checkCreateDirectoryOK(this,createParentWhenNotExists); 281 provider.lock(this); 282 try { 283 createCore(RamResourceCore.TYPE_DIRECTORY); 284 } 285 finally { 286 provider.unlock(this); 287 } 288 289 } 290 291 /** 292 * @see res.Resource#getInputStream() 293 */ 294 public InputStream getInputStream() throws IOException { 295 ResourceUtil.checkGetInputStreamOK(this); 296 297 provider.lock(this); 298 RamResourceCore core = getCore(); 299 300 byte[] data = core.getData(); 301 if(data==null)data=new byte[0]; 302 provider.unlock(this); 303 return new ByteArrayInputStream(data); 304 } 305 306 public OutputStream getOutputStream(boolean append) throws IOException { 307 ResourceUtil.checkGetOutputStreamOK(this); 308 provider.lock(this); 309 return new RamOutputStream(this,append); 310 } 311 312 /** 313 * 314 * @see railo.commons.io.res.Resource#getContentType() 315 */ 316 public ContentType getContentType() { 317 return ResourceUtil.getContentType(this); 318 } 319 320 /** 321 * @see res.Resource#getResourceProvider() 322 */ 323 public ResourceProvider getResourceProvider() { 324 return provider; 325 } 326 /** 327 * @see java.lang.Object#toString() 328 */ 329 public String toString() { 330 return getPath(); 331 } 332 333 334 /** 335 * This is useed by the MemoryResource too write back data to, that are written to outputstream 336 */ 337 class RamOutputStream extends ByteArrayOutputStream { 338 339 private RamResource res; 340 private boolean append; 341 342 /** 343 * Constructor of the class 344 * @param res 345 */ 346 public RamOutputStream(RamResource res, boolean append) { 347 this.append=append; 348 this.res=res; 349 } 350 351 /** 352 * @see java.io.ByteArrayOutputStream#close() 353 */ 354 public void close() throws IOException { 355 try { 356 super.close(); 357 RamResourceCore core = res.getCore(); 358 if(core==null)core=res.createCore(RamResourceCore.TYPE_FILE); 359 360 core.setData(this.toByteArray(),append); 361 } 362 finally { 363 res.getResourceProvider().unlock(res); 364 } 365 } 366 } 367 368 /** 369 * @see railo.commons.io.res.Resource#setReadable(boolean) 370 */ 371 public boolean setReadable(boolean value) { 372 if(!exists())return false; 373 try { 374 setMode(ModeUtil.setReadable(getMode(), value)); 375 return true; 376 } catch (IOException e) { 377 return false; 378 } 379 380 } 381 382 /** 383 * @see railo.commons.io.res.Resource#setWritable(boolean) 384 */ 385 public boolean setWritable(boolean value) { 386 if(!exists())return false; 387 try { 388 setMode(ModeUtil.setWritable(getMode(), value)); 389 return true; 390 } catch (IOException e) { 391 return false; 392 } 393 } 394 395 private boolean isRoot() { 396 return parent==null; 397 } 398 399 public int getMode() { 400 if(!exists())return 0; 401 return getCore().getMode(); 402 } 403 404 public void setMode(int mode) throws IOException { 405 if(!exists())throw new IOException("can't set mode on resource ["+this+"], resource does not exists"); 406 getCore().setMode(mode); 407 } 408 /** 409 * 410 * @see railo.commons.io.res.util.ResourceSupport#getAttribute(short) 411 */ 412 public boolean getAttribute(short attribute) { 413 if(!exists())return false; 414 return (getCore().getAttributes()&attribute)>0; 415 } 416 /** 417 * 418 * @see railo.commons.io.res.util.ResourceSupport#setAttribute(short, boolean) 419 */ 420 public void setAttribute(short attribute, boolean value) throws IOException { 421 if(!exists())throw new IOException("can't get attributes on resource ["+this+"], resource does not exists"); 422 int attr = getCore().getAttributes(); 423 if(value) { 424 if((attr&attribute)==0) attr+=attribute; 425 } 426 else { 427 if((attr&attribute)>0) attr-=attribute; 428 } 429 getCore().setAttributes(attr); 430 } 431 432 }