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.List; 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 for(int y=0;i<count-i;y++) rtn.append("../"); 116 isOutSide=rtn.length()!=0; 117 return rtn.toString()+(rtn.length()==0?"/":"")+list(arr,i,arr.length); 118 } 119 } 120 } 121 //System.out.println(strRoot+" - "+path); 122 } 123 124 return parentRealPath+"/"+newRealPath; 125 } 126 127 /** 128 * convert a String array to a string list, but only part of it 129 * @param arr String Array 130 * @param from start from here 131 * @param len how many element 132 * @return String list 133 */ 134 private String list(String[] arr,int from, int len) { 135 StringBuilder sb=new StringBuilder(); 136 for(int i=from;i<len;i++) { 137 sb.append(arr[i]); 138 if(i+1!=arr.length)sb.append('/'); 139 } 140 return sb.toString(); 141 } 142 143 144 145 /** 146 * remove the last elemtn of a path 147 * @param path path to remove last element from it 148 * @return path with removed element 149 */ 150 private String pathRemoveLast(String path) { 151 if(path.length()==0) { 152 isOutSide=true; 153 return ".."; 154 } 155 else if(path.lastIndexOf("..")==path.length()-2){ 156 isOutSide=true; 157 return path+"/.."; 158 } 159 return path.substring(0,path.lastIndexOf('/')); 160 } 161 162 /** 163 * @see railo.runtime.SourceFile#getFile() 164 */ 165 public Resource getFile() { 166 if(file==null) { 167 if(isOutSide) { 168 try { 169 file=root.getRealResource(realpath).getCanonicalResource(); 170 } catch (IOException e) { 171 } 172 } 173 file=root.getRealResource(realpath); 174 } 175 return file; 176 } 177 178 /** 179 * @return Returns the realpath. 180 */ 181 public String getRealpath() { 182 return realpath; 183 } 184 /** 185 * @return Returns the root. 186 */ 187 public Resource getRoot() { 188 return root; 189 } 190 191 /** 192 * @return returns a variable string based on realpath and return it 193 */ 194 public String getRealPathAsVariableString() { 195 return StringUtil.toIdentityVariableName(getRealpath()); 196 //return StringUtil.toClassName(getRealpath()); 197 } 198 199 /** 200 * @return returns the a classname matching to filename 201 */ 202 public String getClassName() { 203 if(className==null) createClassAndPackage(); 204 return className; 205 } 206 207 /** 208 * @return returns the java name 209 */ 210 public String getJavaName() { 211 if(javaName==null) createClassAndPackage(); 212 return javaName; 213 } 214 215 /** 216 * @return returns the a package matching to file 217 */ 218 public String getPackageName() { 219 if(packageName==null) createClassAndPackage(); 220 return packageName; 221 } 222 223 private void createClassAndPackage() { 224 String str=realpath; 225 StringBuilder packageName=new StringBuilder(); 226 StringBuilder javaName=new StringBuilder(); 227 while(str.indexOf('/')==0)str=str.substring(1); 228 while(str.lastIndexOf('/')==str.length()-1)str=str.substring(0,str.length()-1); 229 230 //String[] arr=str.split("/"); 231 Array arr = List.listToArray(str, '/'); 232 int len=arr.size(); 233 String value; 234 for(int i=1;i<=len;i++) { 235 value=(String) arr.get(i,""); 236 String varName=StringUtil.toVariableName(value); 237 javaName.append("/"+varName); 238 if(i==len) { 239 className=varName.toLowerCase(); 240 } 241 else { 242 if(i!=0) packageName.append('.'); 243 packageName.append(varName); 244 } 245 } 246 this.packageName=packageName.toString().toLowerCase(); 247 this.javaName=javaName.toString().toLowerCase(); 248 } 249 250 251 252 /** 253 * @return returns a variable string based on root and return it 254 */ 255 public String getRootPathAsVariableString() { 256 return StringUtil.toIdentityVariableName(root.getAbsolutePath()); 257 } 258 259 /** 260 * @return has context a archive or not 261 */ 262 public boolean hasArchive() { 263 return hasArchive; 264 } 265 266 /** 267 * @return returns if is trusted or not 268 */ 269 public boolean isTrusted() { 270 return trusted; 271 } 272 273 /** 274 * @see railo.runtime.SourceFile#getPhyscalFile() 275 */ 276 public Resource getPhyscalFile() { 277 return getFile(); 278 } 279 280 /** 281 * @see railo.runtime.SourceFile#getDisplayPath() 282 */ 283 public String getDisplayPath() { 284 return getFile().getAbsolutePath(); 285 } 286 287 /** 288 * @see railo.runtime.SourceFile#getFullClassName() 289 */ 290 public String getFullClassName() { 291 String p=getPackageName(); 292 if(p.length()==0) return getClassName(); 293 return p.concat(".").concat(getClassName()); 294 } 295 }