001 package railo.commons.io; 002 003 import java.io.IOException; 004 005 import railo.commons.io.res.Resource; 006 import railo.commons.lang.StringUtil; 007 import railo.runtime.SourceFile; 008 import railo.runtime.type.Array; 009 import railo.runtime.type.util.ListUtil; 010 011 /** 012 * represent a cfml file on the runtime system 013 */ 014 public final class SourceFileImpl implements SourceFile { 015 016 private final Resource root; 017 private Resource file; 018 private String realpath; 019 private boolean isOutSide=false; 020 private String name; 021 private String className; 022 private String packageName; 023 private String javaName; 024 private boolean trusted; 025 private boolean hasArchive; 026 027 028 /** 029 * constructor of the class 030 * @param root rott directory of the file 031 * @param realPath relative path to root directory 032 */ 033 public SourceFileImpl(Resource root, String realPath) { 034 035 this.root=root; 036 037 this.realpath=realPath.replace('\\','/'); 038 039 if(realPath.indexOf('/')==0) { 040 041 } 042 else if(realPath.startsWith("../")) { 043 isOutSide=true; 044 } 045 else if(realPath.startsWith("./")) { 046 this.realpath=this.realpath.substring(1); 047 } 048 else { 049 this.realpath="/"+this.realpath; 050 } 051 } 052 053 /** 054 * constructor of the class 055 * @param parent parent sourceFile 056 * @param realPath relapath to parent sourc file (not root) 057 */ 058 public SourceFileImpl(SourceFileImpl parent, String realPath) { 059 realpath=realPath.replace('\\','/'); 060 if(realPath.equals(".") || realPath.equals(".."))realPath+="/"; 061 this.root=parent.root; 062 063 name=parent.name; 064 trusted=parent.trusted; 065 hasArchive=parent.hasArchive; 066 isOutSide=parent.isOutSide; 067 068 if(realPath.indexOf('/')==0) { 069 isOutSide=false; 070 this.realpath=realPath; 071 } 072 else if(realPath.indexOf("./")==0) { 073 this.realpath=mergeRealPathes(parent.getRealpath(), realPath.substring(2)); 074 } 075 else { 076 this.realpath=mergeRealPathes(parent.getRealpath(), realPath); 077 } 078 } 079 080 /** 081 * merge to realpath to one 082 * @param parentRealPath 083 * @param newRealPath 084 * @return merged realpath 085 */ 086 private String mergeRealPathes(String parentRealPath, String newRealPath) { 087 // remove file from parent 088 parentRealPath=pathRemoveLast(parentRealPath); 089 090 while(newRealPath.startsWith("../")) { 091 parentRealPath=pathRemoveLast(parentRealPath); 092 newRealPath=newRealPath.substring(3); 093 } 094 // check if come back 095 String path=parentRealPath+"/"+newRealPath; 096 097 if(path.startsWith("../")) { 098 int count=0; 099 while(path.startsWith("../")) { 100 count++; 101 path=path.substring(3); 102 } 103 104 String strRoot=root.getAbsolutePath().replace('\\','/'); 105 if(strRoot.lastIndexOf('/')!=strRoot.length()-1) { 106 strRoot+='/'; 107 } 108 int rootLen=strRoot.length(); 109 String[] arr=path.split("/"); 110 for(int i=count;i>0;i--) { 111 if(arr.length>i) { 112 String tmp="/"+list(arr,0,i); 113 if(strRoot.lastIndexOf(tmp)==rootLen-tmp.length()) { 114 StringBuilder rtn=new StringBuilder(); 115 while(i<count-i) { 116 count--; 117 rtn.append("../"); 118 } 119 isOutSide=rtn.length()!=0; 120 return rtn.toString()+(rtn.length()==0?"/":"")+list(arr,i,arr.length); 121 } 122 } 123 } 124 //System.out.println(strRoot+" - "+path); 125 } 126 127 return parentRealPath+"/"+newRealPath; 128 } 129 130 /** 131 * convert a String array to a string list, but only part of it 132 * @param arr String Array 133 * @param from start from here 134 * @param len how many element 135 * @return String list 136 */ 137 private String list(String[] arr,int from, int len) { 138 StringBuilder sb=new StringBuilder(); 139 for(int i=from;i<len;i++) { 140 sb.append(arr[i]); 141 if(i+1!=arr.length)sb.append('/'); 142 } 143 return sb.toString(); 144 } 145 146 147 148 /** 149 * remove the last elemtn of a path 150 * @param path path to remove last element from it 151 * @return path with removed element 152 */ 153 private String pathRemoveLast(String path) { 154 if(path.length()==0) { 155 isOutSide=true; 156 return ".."; 157 } 158 else if(path.lastIndexOf("..")==path.length()-2){ 159 isOutSide=true; 160 return path+"/.."; 161 } 162 return path.substring(0,path.lastIndexOf('/')); 163 } 164 165 public Resource getFile() { 166 return getResource(); 167 } 168 169 @Override 170 public Resource getResource() { 171 if(file==null) { 172 if(isOutSide) { 173 try { 174 file=root.getRealResource(realpath).getCanonicalResource(); 175 } catch (IOException e) { 176 } 177 } 178 file=root.getRealResource(realpath); 179 } 180 return file; 181 } 182 183 /** 184 * @return Returns the realpath. 185 */ 186 public String getRealpath() { 187 return realpath; 188 } 189 /** 190 * @return Returns the root. 191 */ 192 public Resource getRoot() { 193 return root; 194 } 195 196 /** 197 * @return returns a variable string based on realpath and return it 198 */ 199 public String getRealPathAsVariableString() { 200 return StringUtil.toIdentityVariableName(getRealpath()); 201 //return StringUtil.toClassName(getRealpath()); 202 } 203 204 /** 205 * @return returns the a classname matching to filename 206 */ 207 public String getClassName() { 208 if(className==null) createClassAndPackage(); 209 return className; 210 } 211 212 /** 213 * @return returns the java name 214 */ 215 public String getJavaName() { 216 if(javaName==null) createClassAndPackage(); 217 return javaName; 218 } 219 220 /** 221 * @return returns the a package matching to file 222 */ 223 public String getPackageName() { 224 if(packageName==null) createClassAndPackage(); 225 return packageName; 226 } 227 228 private void createClassAndPackage() { 229 String str=realpath; 230 StringBuilder packageName=new StringBuilder(); 231 StringBuilder javaName=new StringBuilder(); 232 while(str.indexOf('/')==0)str=str.substring(1); 233 while(str.lastIndexOf('/')==str.length()-1)str=str.substring(0,str.length()-1); 234 235 //String[] arr=str.split("/"); 236 Array arr = ListUtil.listToArray(str, '/'); 237 int len=arr.size(); 238 String value; 239 for(int i=1;i<=len;i++) { 240 value=(String) arr.get(i,""); 241 String varName=StringUtil.toVariableName(value); 242 javaName.append("/"+varName); 243 if(i==len) { 244 className=varName.toLowerCase(); 245 } 246 else { 247 if(i!=0) packageName.append('.'); 248 packageName.append(varName); 249 } 250 } 251 this.packageName=packageName.toString().toLowerCase(); 252 this.javaName=javaName.toString().toLowerCase(); 253 } 254 255 256 257 /** 258 * @return returns a variable string based on root and return it 259 */ 260 public String getRootPathAsVariableString() { 261 return StringUtil.toIdentityVariableName(root.getAbsolutePath()); 262 } 263 264 /** 265 * @return has context a archive or not 266 */ 267 public boolean hasArchive() { 268 return hasArchive; 269 } 270 271 /** 272 * @return returns if is trusted or not 273 */ 274 public boolean isTrusted() { 275 return trusted; 276 } 277 278 @Override 279 public Resource getPhyscalFile() { 280 return getFile(); 281 } 282 283 @Override 284 public String getDisplayPath() { 285 return getFile().getAbsolutePath(); 286 } 287 288 @Override 289 public String getFullClassName() { 290 String p=getPackageName(); 291 if(p.length()==0) return getClassName(); 292 return p.concat(".").concat(getClassName()); 293 } 294 }