001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.commons.io.res.type.compress; 020 021import java.io.IOException; 022import java.io.InputStream; 023import java.io.OutputStream; 024 025import lucee.commons.io.res.Resource; 026import lucee.commons.io.res.ResourceProvider; 027import lucee.commons.io.res.util.ResourceSupport; 028import lucee.commons.io.res.util.ResourceUtil; 029import lucee.commons.lang.StringUtil; 030 031public final class CompressResource extends ResourceSupport { 032 033 private final CompressResourceProvider provider; 034 private final Compress zip; 035 private final String path; 036 private final String name; 037 private final String parent; 038 private final boolean caseSensitive; 039 040 /** 041 * Constructor of the class 042 * @param provider 043 * @param zip 044 * @param path 045 * @param caseSensitive 046 */ 047 CompressResource(CompressResourceProvider provider, Compress zip, String path, boolean caseSensitive) { 048 if(StringUtil.isEmpty(path)) path="/"; 049 this.provider=provider; 050 this.zip=zip; 051 this.path=path; 052 053 if("/".equals(path)) { 054 this.parent=null; 055 this.name=""; 056 } 057 else { 058 String[] pn = ResourceUtil.translatePathName(path); 059 this.parent=pn[0]; 060 this.name=pn[1]; 061 } 062 063 this.caseSensitive=caseSensitive; 064 } 065 066 /** 067 * @return return ram resource that contain the data 068 */ 069 private Resource getRamResource() { 070 return zip.getRamProviderResource(path); 071 } 072 073 @Override 074 public boolean exists() { 075 try { 076 provider.read(this); 077 } 078 catch (IOException e) { 079 return false; 080 } 081 return getRamResource().exists(); 082 } 083 084 @Override 085 public InputStream getInputStream() throws IOException { 086 ResourceUtil.checkGetInputStreamOK(this); 087 return getRamResource().getInputStream(); 088 } 089 090 public Resource getCompressResource() { 091 return zip.getCompressFile(); 092 } 093 094 public String getCompressPath() { 095 return path; 096 } 097 098 @Override 099 public String getName() { 100 return name; 101 } 102 103 @Override 104 public String getParent() { 105 if(StringUtil.isEmpty(parent))return null; 106 return provider.getScheme().concat("://").concat(zip.getCompressFile().getPath()).concat("!").concat(parent); 107 } 108 109 @Override 110 public Resource getParentResource() { 111 if(StringUtil.isEmpty(parent))return null; 112 return new CompressResource(provider,zip,parent,caseSensitive); 113 } 114 115 @Override 116 public String getPath() { 117 return provider.getScheme().concat("://").concat(zip.getCompressFile().getPath()).concat("!").concat(path); 118 } 119 120 @Override 121 public Resource getRealResource(String realpath) { 122 realpath=ResourceUtil.merge(path, realpath); 123 if(realpath.startsWith("../"))return null; 124 return new CompressResource(provider,zip,realpath,caseSensitive); 125 } 126 127 @Override 128 public ResourceProvider getResourceProvider() { 129 return provider; 130 } 131 132 @Override 133 public boolean isAbsolute() { 134 return getRamResource().isAbsolute(); 135 } 136 137 @Override 138 public boolean isDirectory() { 139 return getRamResource().isDirectory(); 140 } 141 142 @Override 143 public boolean isFile() { 144 return getRamResource().isFile(); 145 } 146 147 @Override 148 public boolean isReadable() { 149 return getRamResource().isReadable(); 150 } 151 152 @Override 153 public boolean isWriteable() { 154 return getRamResource().isWriteable(); 155 } 156 157 @Override 158 public long lastModified() { 159 return getRamResource().lastModified(); 160 } 161 162 @Override 163 public long length() { 164 return getRamResource().length(); 165 } 166 167 @Override 168 public Resource[] listResources() { 169 String[] names = list(); 170 if(names==null) return null; 171 Resource[] children = new Resource[names.length]; 172 for(int i=0;i<children.length;i++) { 173 children[i]=new CompressResource(provider,zip,path.concat("/").concat(names[i]),caseSensitive); 174 } 175 return children; 176 } 177 178 @Override 179 public String[] list() { 180 return getRamResource().list(); 181 } 182 183 @Override 184 public void remove(boolean force) throws IOException { 185 Resource rr = getRamResource(); 186 if(rr.getParent()==null) 187 throw new IOException("can't remove root resource ["+getPath()+"]"); 188 189 if(!rr.exists()) 190 throw new IOException("can't remove resource ["+getPath()+"],resource does not exist"); 191 192 Resource[] children = listResources(); 193 if(children!=null && children.length>0) { 194 if(!force) { 195 throw new IOException("can't delete directory ["+getPath()+"], directory is not empty"); 196 } 197 for(int i=0;i<children.length;i++) { 198 children[i].remove(true); 199 } 200 } 201 rr.remove(force); 202 } 203 204 @Override 205 public boolean setLastModified(long time) { 206 boolean lm = getRamResource().setLastModified(time); 207 zip.synchronize(provider.async); 208 return lm; 209 } 210 211 @Override 212 public void createDirectory(boolean createParentWhenNotExists) throws IOException { 213 ResourceUtil.checkCreateDirectoryOK(this,createParentWhenNotExists); 214 getRamResource().createDirectory(createParentWhenNotExists); 215 zip.synchronize(provider.async); 216 } 217 218 @Override 219 public void createFile(boolean createParentWhenNotExists) throws IOException { 220 ResourceUtil.checkCreateFileOK(this,createParentWhenNotExists); 221 getRamResource().createFile(createParentWhenNotExists); 222 zip.synchronize(provider.async); 223 } 224 225 @Override 226 public OutputStream getOutputStream() throws IOException { 227 ResourceUtil.checkGetOutputStreamOK(this); 228 //Resource res = getRamResource(); 229 //Resource p = res.getParentResource(); 230 //if(p!=null && !p.exists())p.mkdirs(); 231 return new CompressOutputStreamSynchronizer(getRamResource().getOutputStream(),zip,provider.async); 232 } 233 234 @Override 235 public OutputStream getOutputStream(boolean append) throws IOException { 236 return new CompressOutputStreamSynchronizer(getRamResource().getOutputStream(append),zip,provider.async); 237 } 238 239 @Override 240 public int getMode() { 241 return getRamResource().getMode(); 242 } 243 244 @Override 245 public void setMode(int mode) throws IOException { 246 getRamResource().setMode(mode); 247 zip.synchronize(provider.async); 248 249 } 250 251 @Override 252 public boolean setReadable(boolean value) { 253 if(!isFile())return false; 254 getRamResource().setReadable(value); 255 zip.synchronize(provider.async); 256 return true; 257 } 258 259 @Override 260 public boolean setWritable(boolean value) { 261 if(!isFile())return false; 262 getRamResource().setWritable(value); 263 zip.synchronize(provider.async); 264 return true; 265 } 266 267}