package railo.commons.io.res.util; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import railo.commons.io.IOUtil; import railo.commons.io.SystemUtil; import railo.commons.io.res.ContentType; import railo.commons.io.res.ContentTypeImpl; import railo.commons.io.res.Resource; import railo.commons.io.res.ResourcesImpl; import railo.commons.io.res.filter.ExtensionResourceFilter; import railo.commons.io.res.filter.IgnoreSystemFiles; import railo.commons.io.res.filter.ResourceFilter; import railo.commons.io.res.filter.ResourceNameFilter; import railo.commons.io.res.type.http.HTTPResource; import railo.commons.lang.StringUtil; import railo.runtime.PageContext; import railo.runtime.PageContextImpl; import railo.runtime.PageSource; import railo.runtime.PageSourceImpl; import railo.runtime.config.Config; import railo.runtime.config.ConfigWebImpl; import railo.runtime.exp.ExpressionException; import railo.runtime.exp.PageException; import railo.runtime.type.util.ArrayUtil; import railo.runtime.type.util.ListUtil; public final class ResourceUtil { public static final int MIMETYPE_CHECK_EXTENSION=1; public static final int MIMETYPE_CHECK_HEADER=2; /** * Field <code>FILE_SEPERATOR</code> */ public static final char FILE_SEPERATOR=File.separatorChar; /** * Field <code>FILE_ANTI_SEPERATOR</code> */ public static final char FILE_ANTI_SEPERATOR=(FILE_SEPERATOR=='/')?'\\':'/'; /** * Field <code>TYPE_DIR</code> */ public static final short TYPE_DIR=0; /** * Field <code>TYPE_FILE</code> */ public static final short TYPE_FILE=1; /** * Field <code>LEVEL_FILE</code> */ public static final short LEVEL_FILE=0; /** * Field <code>LEVEL_PARENT_FILE</code> */ public static final short LEVEL_PARENT_FILE=1; /** * Field <code>LEVEL_GRAND_PARENT_FILE</code> */ public static final short LEVEL_GRAND_PARENT_FILE=2; private static boolean isUnix=SystemUtil.isUnix(); private static final HashMap<String, String> EXT_MT=new HashMap<String, String>(); static { EXT_MT.put("ai","application/postscript"); EXT_MT.put("aif","audio/x-aiff"); EXT_MT.put("aifc","audio/x-aiff"); EXT_MT.put("aiff","audio/x-aiff"); EXT_MT.put("au","audio/basic"); EXT_MT.put("avi","video/x-msvideo"); EXT_MT.put("bin","application/octet-stream"); EXT_MT.put("bmp","image/x-ms-bmp"); EXT_MT.put("cgm","image/cgm"); EXT_MT.put("cmx","image/x-cmx"); EXT_MT.put("csh","application/x-csh"); EXT_MT.put("cfm","text/html"); EXT_MT.put("cfml","text/html"); EXT_MT.put("css","text/css"); EXT_MT.put("doc","application/msword"); EXT_MT.put("docx","application/msword"); EXT_MT.put("eps","application/postscript"); EXT_MT.put("exe","application/octet-stream"); EXT_MT.put("gif","image/gif"); EXT_MT.put("gtar","application/x-gtar"); EXT_MT.put("hqx","application/mac-binhex40"); EXT_MT.put("htm","text/html"); EXT_MT.put("html","text/html"); EXT_MT.put("jpe","image/jpeg"); EXT_MT.put("jpeg","image/jpeg"); EXT_MT.put("jpg","image/jpeg"); EXT_MT.put("js","text/javascript"); EXT_MT.put("mmid","x-music/x-midi"); EXT_MT.put("mov","video/quicktime"); EXT_MT.put("mp2a","audio/x-mpeg-2"); EXT_MT.put("mp2v","video/mpeg-2"); EXT_MT.put("mp3","audio/mpeg"); EXT_MT.put("mp4","video/mp4"); EXT_MT.put("mpa","audio/x-mpeg"); EXT_MT.put("mpa2","audio/x-mpeg-2"); EXT_MT.put("mpeg","video/mpeg"); EXT_MT.put("mpega","audio/x-mpeg"); EXT_MT.put("mpg","video/mpeg"); EXT_MT.put("mpv2","video/mpeg-2"); EXT_MT.put("pbm","image/x-portable-bitmap"); EXT_MT.put("pcd","image/x-photo-cd"); EXT_MT.put("pdf","application/pdf"); EXT_MT.put("pgm","image/x-portable-graymap"); EXT_MT.put("pict","image/x-pict"); EXT_MT.put("pl","application/x-perl"); EXT_MT.put("png","image/png"); EXT_MT.put("php","text/html"); EXT_MT.put("pnm","image/x-portable-anymap"); EXT_MT.put("ppm","image/x-portable-pixmap"); EXT_MT.put("ppt","application/vnd.ms-powerpoint"); EXT_MT.put("pptx","application/vnd.ms-powerpoint"); EXT_MT.put("ps","application/postscript"); EXT_MT.put("qt","video/quicktime"); EXT_MT.put("rgb","image/rgb"); EXT_MT.put("rtf","application/rtf"); EXT_MT.put("sh","application/x-sh"); EXT_MT.put("sit","application/x-stuffit"); EXT_MT.put("swf","application/x-shockwave-flash"); EXT_MT.put("tar","application/x-tar"); EXT_MT.put("tcl","application/x-tcl"); EXT_MT.put("tif","image/tiff"); EXT_MT.put("tiff","image/tiff"); EXT_MT.put("txt","text/plain"); EXT_MT.put("wav","audio/x-wav"); EXT_MT.put("wma","audio/x-ms-wma"); EXT_MT.put("wmv","video/x-ms-wmv"); EXT_MT.put("xbm","image/x-xbitmap"); EXT_MT.put("xhtml","application/xhtml+xml"); EXT_MT.put("xls","application/vnd.ms-excel"); EXT_MT.put("xlsx","application/vnd.ms-excel"); EXT_MT.put("xpm","image/x-xpixmap"); EXT_MT.put("zip","application/zip"); } //private static Magic mimeTypeParser; /** * cast a String (argumet destination) to a File Object, * if destination is not a absolute, file object will be relative to current position (get from PageContext) * file must exist otherwise throw exception * @param pc Page Context to et actuell position in filesystem * @param path relative or absolute path for file object * @return file object from destination * @throws ExpressionException */ public static Resource toResourceExisting(PageContext pc ,String path) throws ExpressionException { return toResourceExisting(pc, path,pc.getConfig().allowRealPath()); } public static Resource toResourceExisting(PageContext pc ,String path,boolean allowRealpath) throws ExpressionException { path=path.replace('\\','/'); Resource res = pc.getConfig().getResource(path); // not allow realpath if(!allowRealpath){ if(res.exists()) return res; throw new ExpressionException("file or directory "+path+" not exist"); } if(res.isAbsolute() && res.exists()) { return res; } //if(allowRealpath){ if(StringUtil.startsWith(path,'/')) { PageContextImpl pci=(PageContextImpl) pc; ConfigWebImpl cwi=(ConfigWebImpl) pc.getConfig(); PageSource[] sources = cwi.getPageSources(pci, pc.getApplicationContext().getMappings(), path, false, pci.useSpecialMappings(), true); //Resource[] reses = cwi.getPhysicalResourcesX(pc,pc.getApplicationContext().getMappings(),path,false,pci.useSpecialMappings(),true); if(!ArrayUtil.isEmpty(sources)) { for(int i=0;i<sources.length;i++){ if(sources[i].exists()) return sources[i].getResource(); } } //res = pc.getPhysical(path,true); //if(res!=null && res.exists()) return res; } res=getRealResource(pc, path, res); if(res.exists()) return res; //} throw new ExpressionException("file or directory "+path+" not exist"); } public static Resource toResourceExisting(Config config ,String path) throws ExpressionException { path=path.replace('\\','/'); Resource res = config.getResource(path); if(res.exists()) return res; throw new ExpressionException("file or directory "+path+" not exist"); } public static Resource toResourceNotExisting(Config config ,String path) { Resource res; path=path.replace('\\','/'); res=config.getResource(path); return res; } /** * cast a String (argumet destination) to a File Object, * if destination is not a absolute, file object will be relative to current position (get from PageContext) * at least parent must exist * @param pc Page Context to et actuell position in filesystem * @param destination relative or absolute path for file object * @return file object from destination * @throws ExpressionException */ public static Resource toResourceExistingParent(PageContext pc ,String destination) throws ExpressionException { return toResourceExistingParent(pc, destination, pc.getConfig().allowRealPath()); } public static Resource toResourceExistingParent(PageContext pc ,String destination, boolean allowRealpath) throws ExpressionException { destination=destination.replace('\\','/'); Resource res=pc.getConfig().getResource(destination); // not allow realpath if(!allowRealpath){ if(res.exists() || parentExists(res)) return res; throw new ExpressionException("parent directory "+res.getParent()+" for file "+destination+" doesn't exist"); } // allow realpath if(res.isAbsolute() && (res.exists() || parentExists(res))) { return res; } if(StringUtil.startsWith(destination,'/')) { PageContextImpl pci=(PageContextImpl) pc; ConfigWebImpl cwi=(ConfigWebImpl) pc.getConfig(); PageSource[] sources = cwi.getPageSources(pci, pc.getApplicationContext().getMappings(), destination, false, pci.useSpecialMappings(),true); //Resource[] reses = cwi.getPhysicalResourcesX(pc,pc.getApplicationContext().getMappings(),destination,false,pci.useSpecialMappings(),true); if(!ArrayUtil.isEmpty(sources)) { for(int i=0;i<sources.length;i++){ if(sources[i].exists() || parentExists(sources[i])) { res=sources[i].getResource(); if(res!=null) return res; } } } } res=getRealResource(pc, destination, res); if(res!=null && (res.exists() || parentExists(res))) return res; throw new ExpressionException("parent directory "+res.getParent()+" for file "+destination+" doesn't exist"); } /** * cast a String (argument destination) to a File Object, * if destination is not a absolute, file object will be relative to current position (get from PageContext) * existing file is prefered but dont must exist * @param pc Page Context to et actuell position in filesystem * @param destination relative or absolute path for file object * @return file object from destination */ public static Resource toResourceNotExisting(PageContext pc ,String destination) { return toResourceNotExisting(pc ,destination,pc.getConfig().allowRealPath()); } public static Resource toResourceNotExisting(PageContext pc ,String destination,boolean allowRealpath) { Resource res; destination=destination.replace('\\','/'); if(!allowRealpath){ res=pc.getConfig().getResource(destination); return res; } boolean isUNC; if(!(isUNC=isUNCPath(destination)) && StringUtil.startsWith(destination,'/')) { PageContextImpl pci=(PageContextImpl) pc; ConfigWebImpl cwi=(ConfigWebImpl) pc.getConfig(); PageSource[] sources = cwi.getPageSources(pci, pc.getApplicationContext().getMappings(), destination, false, pci.useSpecialMappings(), SystemUtil.isWindows()); //Resource[] arr = cwi.getPhysicalResources(pc,pc.getApplicationContext().getMappings(),destination,false,pci.useSpecialMappings(),SystemUtil.isWindows()); if(!ArrayUtil.isEmpty(sources)) { for(int i=0;i<sources.length;i++){ res=sources[i].getResource(); if(res!=null) return res; } } //Resource res2 = pc.getPhysical(destination,SystemUtil.isWindows()); //if(res2!=null) return res2; } if(isUNC) { res=pc.getConfig().getResource(destination.replace('/','\\')); } else res=pc.getConfig().getResource(destination); if(res.isAbsolute()) return res; return getRealResource(pc,destination,res); } private static Resource getRealResource(PageContext pc, String destination, Resource defaultValue) { PageSource ps = pc.getCurrentPageSource(); if(ps!=null) { ps=ps.getRealPage(destination); if(ps!=null){ Resource res = ps.getResource(); if(res!=null)return getCanonicalResourceEL(res); } } return defaultValue; } public static boolean isUNCPath(String path) { return SystemUtil.isWindows() && ( path.startsWith("//") || path.startsWith( "\\\\" ) ); } /** * transalte the path of the file to a existing file path by changing case of letters * Works only on Linux, becasue * * Example Unix: * we have a existing file with path "/usr/virtual/myFile.txt" * now you call this method with path "/Usr/Virtual/myfile.txt" * the result of the method will be "/usr/virtual/myFile.txt" * * if there are more file with rhe same name but different cases * Example: * /usr/virtual/myFile.txt * /usr/virtual/myfile.txt * /Usr/Virtual/myFile.txt * the nearest case wil returned * * @param res * @return file */ public static Resource toExactResource(Resource res) { res=getCanonicalResourceEL(res); if(isUnix) { if(res.exists()) return res; return _check(res); } return res; } private static Resource _check(Resource file) { // todo cascade durch while ersetzten Resource parent=file.getParentResource(); if(parent==null) return file; if(!parent.exists()) { Resource op=parent; parent=_check(parent); if(op==parent) return file; if((file = parent.getRealResource(file.getName())).exists()) return file; } String[] files = parent.list(); if(files==null) return file; String name=file.getName(); for(int i=0;i<files.length;i++) { if(name.equalsIgnoreCase(files[i])) return parent.getRealResource(files[i]); } return file; } /** * create a file if possible, return file if ok, otherwise return null * @param res file to touch * @param level touch also parent and grand parent * @param type is file or directory * @return file if exists, otherwise null */ public static Resource createResource(Resource res, short level, short type) { boolean asDir=type==TYPE_DIR; // File if(level>=LEVEL_FILE && res.exists() && ((res.isDirectory() && asDir)||(res.isFile() && !asDir))) { return getCanonicalResourceEL(res); } // Parent Resource parent=res.getParentResource(); if(level>=LEVEL_PARENT_FILE && parent!=null && parent.exists() && canRW(parent)) { if(asDir) { if(res.mkdirs()) return getCanonicalResourceEL(res); } else { if(createNewResourceEL(res))return getCanonicalResourceEL(res); } return getCanonicalResourceEL(res); } // Grand Parent if(level>=LEVEL_GRAND_PARENT_FILE && parent!=null) { Resource gparent=parent.getParentResource(); if(gparent!=null && gparent.exists() && canRW(gparent)) { if(asDir) { if(res.mkdirs())return getCanonicalResourceEL(res); } else { if(parent.mkdirs() && createNewResourceEL(res)) return getCanonicalResourceEL(res); } } } return null; } public static void setAttribute(Resource res,String attributes) throws IOException { /*if(res instanceof File && SystemUtil.isWindows()) { if(attributes.length()>0) { attributes=ResourceUtil.translateAttribute(attributes); Runtime.getRuntime().exec("attrib "+attributes+" " + res.getAbsolutePath()); } } else {*/ short[] flags = strAttrToBooleanFlags(attributes); if(flags[READ_ONLY]==YES)res.setWritable(false); else if(flags[READ_ONLY]==NO)res.setWritable(true); if(flags[HIDDEN]==YES) res.setAttribute(Resource.ATTRIBUTE_HIDDEN, true);//setHidden(true); else if(flags[HIDDEN]==NO) res.setAttribute(Resource.ATTRIBUTE_HIDDEN, false);//res.setHidden(false); if(flags[ARCHIVE]==YES) res.setAttribute(Resource.ATTRIBUTE_ARCHIVE, true);//res.setArchive(true); else if(flags[ARCHIVE]==NO) res.setAttribute(Resource.ATTRIBUTE_ARCHIVE, false);//res.setArchive(false); if(flags[SYSTEM]==YES) res.setAttribute(Resource.ATTRIBUTE_SYSTEM, true);//res.setSystem(true); else if(flags[SYSTEM]==NO) res.setAttribute(Resource.ATTRIBUTE_SYSTEM, false);//res.setSystem(false); //} } //private static final int NORMAL=0; private static final int READ_ONLY=0; private static final int HIDDEN=1; private static final int ARCHIVE=2; private static final int SYSTEM=3; //private static final int IGNORE=0; private static final int NO=1; private static final int YES=2; private static short[] strAttrToBooleanFlags(String attributes) throws IOException { String[] arr; try { arr = ListUtil.toStringArray(ListUtil.listToArrayRemoveEmpty(attributes.toLowerCase(),',')); } catch (PageException e) { arr=new String[0]; } boolean hasNormal=false; boolean hasReadOnly=false; boolean hasHidden=false; boolean hasArchive=false; boolean hasSystem=false; for(int i=0;i<arr.length;i++) { String str=arr[i].trim().toLowerCase(); if(str.equals("readonly") || str.equals("read-only") || str.equals("+r")) hasReadOnly=true; else if(str.equals("normal") || str.equals("temporary")) hasNormal=true; else if(str.equals("hidden") || str.equals("+h")) hasHidden=true; else if(str.equals("system") || str.equals("+s")) hasSystem=true; else if(str.equals("archive") || str.equals("+a")) hasArchive=true; else throw new IOException("invalid attribute definition ["+str+"]"); } short[] flags=new short[4]; if(hasReadOnly)flags[READ_ONLY]=YES; else if(hasNormal)flags[READ_ONLY]=NO; if(hasHidden)flags[HIDDEN]=YES; else if(hasNormal)flags[HIDDEN]=NO; if(hasSystem)flags[SYSTEM]=YES; else if(hasNormal)flags[SYSTEM]=NO; if(hasArchive)flags[ARCHIVE]=YES; else if(hasNormal)flags[ARCHIVE]=NO; return flags; } /** * sets attributes of a file on Windows system * @param res * @param attributes * @throws PageException * @throws IOException */ public static String translateAttribute(String attributes) throws IOException { short[] flags = strAttrToBooleanFlags(attributes); StringBuilder sb=new StringBuilder(); if(flags[READ_ONLY]==YES)sb.append(" +R"); else if(flags[READ_ONLY]==NO)sb.append(" -R"); if(flags[HIDDEN]==YES)sb.append(" +H"); else if(flags[HIDDEN]==NO)sb.append(" -H"); if(flags[SYSTEM]==YES)sb.append(" +S"); else if(flags[SYSTEM]==NO)sb.append(" -S"); if(flags[ARCHIVE]==YES)sb.append(" +A"); else if(flags[ARCHIVE]==NO)sb.append(" -A"); return sb.toString(); } /* * * transalte a path in a proper form * example susi\petere -> /susi/peter * @param path * @return path * / public static String translatePath(String path) { /*path=prettifyPath(path); if(path.indexOf('/')!=0)path='/'+path; int index=path.lastIndexOf('/'); // remove slash at the end if(index==path.length()-1) path=path.substring(0,path.length()-1); return path;* / return translatePath(path, true, false); }*/ /* * * transalte a path in a proper form * example susi\petere -> susi/peter/ * @param path * @return path * / public static String translatePath2x(String path) { /*path=prettifyPath(path); if(path.indexOf('/')==0)path=path.substring(1); int index=path.lastIndexOf('/'); // remove slash at the end if(index!=path.length()-1) path=path+'/';* / return translatePath(path, false, true); }*/ public static String translatePath(String path, boolean slashAdBegin, boolean slashAddEnd) { path=prettifyPath(path); // begin if(slashAdBegin) { if(path.indexOf('/')!=0)path='/'+path; } else { if(path.indexOf('/')==0)path=path.substring(1); } // end int index=path.lastIndexOf('/'); if(slashAddEnd) { if(index!=path.length()-1) path=path+'/'; } else { if(index==path.length()-1 && index>-1) path=path.substring(0,path.length()-1); } return path; } /** * transalte a path in a proper form and cut name away * example susi\petere -> /susi/ and peter * @param path * @return */ public static String[] translatePathName(String path) { path=prettifyPath(path); if(path.indexOf('/')!=0)path='/'+path; int index=path.lastIndexOf('/'); // remove slash at the end if(index==path.length()-1) path=path.substring(0,path.length()-1); index=path.lastIndexOf('/'); String name; if(index==-1) { name=path; path = "/"; } else { name = path.substring(index+1); path = path.substring(0,index+1); } return new String[] {path,name}; } public static String prettifyPath(String path) { if(path==null) return null; path=path.replace('\\','/'); return StringUtil.replace(path, "//", "/", false); // TODO /aaa/../bbb/ } public static String removeScheme(String scheme, String path) { if(path.indexOf("://")==scheme.length() && StringUtil.startsWithIgnoreCase(path,scheme)) path=path.substring(3+scheme.length()); return path; } /** * merge to path parts to one * @param parent * @param child * @return */ public static String merge(String parent, String child) { if(child.length()<=2) { if(child.length()==0) return parent; if(child.equals(".")) return parent; if(child.equals("..")) child="../"; } parent=translatePath(parent, true, false); child=prettifyPath(child);//child.replace('\\', '/'); if(child.startsWith("./"))child=child.substring(2); if(StringUtil.startsWith(child, '/'))return parent.concat(child); if(!StringUtil.startsWith(child, '.'))return parent.concat("/").concat(child); while(child.startsWith("../")) { parent=pathRemoveLast(parent); child=child.substring(3); } if(StringUtil.startsWith(child, '/'))return parent.concat(child); return parent.concat("/").concat(child); } private static String pathRemoveLast(String path) { if(path.length()==0) return ".."; else if(path.endsWith("..")){ return path.concat("/.."); } return path.substring(0,path.lastIndexOf('/')); } /** * Returns the canonical form of this abstract pathname. * @param res file to get canoncial form from it * * @return The canonical pathname string denoting the same file or * directory as this abstract pathname * * @throws SecurityException * If a required system property value cannot be accessed. */ public static String getCanonicalPathEL(Resource res) { try { return res.getCanonicalPath(); } catch (IOException e) { return res.toString(); } } /** * Returns the canonical form of this abstract pathname. * @param res file to get canoncial form from it * * @return The canonical pathname string denoting the same file or * directory as this abstract pathname * * @throws SecurityException * If a required system property value cannot be accessed. */ public static Resource getCanonicalResourceEL(Resource res) { if(res==null) return res; try { return res.getCanonicalResource(); } catch (IOException e) { return res.getAbsoluteResource(); } } /** * creates a new File * @param res * @return was successfull */ public static boolean createNewResourceEL(Resource res) { try { res.createFile(false); return true; } catch (IOException e) { return false; } } public static boolean exists(Resource res) { return res!=null && res.exists(); } /** * check if file is read and writable * @param res * @return is or not */ public static boolean canRW(Resource res) { return res.isReadable() && res.isWriteable(); } /** * similat to linux bash fuction toch, create file if not exist oherwise change last modified date * @param res * @throws IOException */ public static void touch(Resource res) throws IOException { if(res.exists()) { res.setLastModified(System.currentTimeMillis()); } else { res.createFile(true); } } public static void clear(Resource res) throws IOException { if(res.exists()) { IOUtil.write(res, new byte[0]); } else { res.createFile(true); } } /** * return the mime type of a file, dont check extension * @param res * @param defaultValue * @return mime type of the file */ public static String getMimeType(Resource res, String defaultValue) { return getMimeType(res, MIMETYPE_CHECK_HEADER,defaultValue); } public static String getMimeType(Resource res, int checkingType, String defaultValue) { // check Extension if((checkingType&MIMETYPE_CHECK_EXTENSION)!=0) { String ext = getExtension(res, null); if(!StringUtil.isEmpty(ext)){ String mt=EXT_MT.get(ext.trim().toLowerCase()); if(mt!=null) return mt; } } // check mimetype if((checkingType&MIMETYPE_CHECK_HEADER)!=0) { InputStream is=null; try { is = res.getInputStream(); return IOUtil.getMimeType(is, defaultValue); } catch (Throwable t) { return defaultValue; } finally { IOUtil.closeEL(is); } } return defaultValue; } /** * check if file is a child of given directory * @param file file to search * @param dir directory to search * @return is inside or not */ public static boolean isChildOf(Resource file, Resource dir) { while(file!=null) { if(file.equals(dir)) return true; file=file.getParentResource(); } return false; } /** * return diffrents of one file to a other if first is child of second otherwise return null * @param file file to search * @param dir directory to search */ public static String getPathToChild(Resource file, Resource dir) { if(dir==null || !file.getResourceProvider().getScheme().equals(dir.getResourceProvider().getScheme())) return null; boolean isFile=file.isFile(); String str="/"; while(file!=null) { if(file.equals(dir)) { if(isFile) return str.substring(0,str.length()-1); return str; } str="/"+file.getName()+str; file=file.getParentResource(); } return null; } /** * get the Extension of a file * @param res * @return extension of file */ public static String getExtension(Resource res, String defaultValue) { return getExtension(res.getName(),defaultValue); } /** * get the Extension of a file * @param strFile * @return extension of file */ public static String getExtension(String strFile, String defaultValue) { int pos=strFile.lastIndexOf('.'); if(pos==-1)return defaultValue; return strFile.substring(pos+1); } public static String getName(String strFileName) { int pos=strFileName.lastIndexOf('.'); if(pos==-1)return strFileName; return strFileName.substring(0,pos); } /** * split a FileName in Parts * @param fileName * @return new String[]{name[,extension]} */ public static String[] splitFileName(String fileName) { int pos=fileName.lastIndexOf('.'); if(pos==-1) { return new String[]{fileName}; } return new String[]{fileName.substring(0,pos),fileName.substring(pos+1)}; } /** * change extesnion of file and return new file * @param file * @param newExtension * @return file with new Extension */ public static Resource changeExtension(Resource file, String newExtension) { String ext=getExtension(file,null); if(ext==null) return file.getParentResource().getRealResource(file.getName()+'.'+newExtension); //new File(file.getParentFile(),file.getName()+'.'+newExtension); String name=file.getName(); return file.getParentResource().getRealResource(name.substring(0,name.length()-ext.length())+newExtension); //new File(file.getParentFile(),name.substring(0,name.length()-ext.length())+newExtension); } /** * @param res delete the content of a directory */ public static void deleteContent(Resource src,ResourceFilter filter) { _deleteContent(src, filter,false); } public static void _deleteContent(Resource src,ResourceFilter filter,boolean deleteDirectories) { if(src.isDirectory()) { Resource[] files=filter==null?src.listResources():src.listResources(filter); for(int i=0;i<files.length;i++) { _deleteContent(files[i],filter,true); if(deleteDirectories){ try { src.remove(false); } catch (IOException e) {} } } } else if(src.isFile()) { src.delete(); } } /** * copy a file or directory recursive (with his content) * @param res file or directory to delete * @throws IOException * @throws FileNotFoundException */ public static void copyRecursive(Resource src,Resource trg) throws IOException { copyRecursive(src, trg,null); } /** * copy a file or directory recursive (with his content) * @param src * @param trg * @param filter * @throws IOException * @throws FileNotFoundException */ public static void copyRecursive(Resource src,Resource trg,ResourceFilter filter) throws IOException { //print.out(src); //print.out(trg); if(!src.exists()) return ; if(src.isDirectory()) { if(!trg.exists())trg.createDirectory(true); Resource[] files=filter==null?src.listResources():src.listResources(filter); for(int i=0;i<files.length;i++) { copyRecursive(files[i],trg.getRealResource(files[i].getName()),filter); } } else if(src.isFile()) { touch(trg); IOUtil.copy(src,trg); } } public static void copy(Resource src, Resource trg) throws IOException { if(src.equals(trg)) return; ResourceUtil.checkCopyToOK(src,trg); IOUtil.copy(src,trg); } /** * return if parent file exists * @param res file to check * @return parent exists? */ private static boolean parentExists(Resource res) { res=res.getParentResource(); return res!=null && res.exists(); } private static boolean parentExists(PageSource ps) { PageSource p = ((PageSourceImpl)ps).getParent(); return p!=null && p.exists(); } public static void removeChildren(Resource res) throws IOException { removeChildren(res, (ResourceFilter)null); } public static void removeChildren(Resource res,ResourceNameFilter filter) throws IOException { Resource[] children = filter==null?res.listResources():res.listResources(filter); if(children==null) return; for(int i=0;i<children.length;i++) { children[i].remove(true); } } public static void removeChildren(Resource res,ResourceFilter filter) throws IOException { Resource[] children = filter==null?res.listResources():res.listResources(filter); if(children==null) return; for(int i=0;i<children.length;i++) { children[i].remove(true); } } public static void removeChildrenEL(Resource res,ResourceNameFilter filter) { try { removeChildren(res,filter); } catch(Throwable e) {} } public static void removeChildrenEL(Resource res,ResourceFilter filter) { try { removeChildren(res,filter); } catch(Throwable e) {} } public static void removeChildrenEL(Resource res) { try { removeChildren(res); } catch(Throwable e) {} } public static void removeEL(Resource res, boolean force) { try { res.remove(force); } catch (Throwable t) {} } public static void createFileEL(Resource res, boolean force) { try { res.createFile(force); } catch (IOException e) {} } public static void createDirectoryEL(Resource res, boolean force) { try { res.createDirectory(force); } catch (IOException e) {} } public static ContentType getContentType(Resource resource) { // TODO make this part of a interface if(resource instanceof HTTPResource) { try { return ((HTTPResource)resource).getContentType(); } catch (IOException e) {} } InputStream is=null; try { is = resource.getInputStream(); return new ContentTypeImpl(is); } catch(IOException e) { return ContentTypeImpl.APPLICATION_UNKNOW; } finally { IOUtil.closeEL(is); } } public static void moveTo(Resource src, Resource dest, boolean useResourceMethod) throws IOException { ResourceUtil.checkMoveToOK(src, dest); if(src.isFile()){ try{ if(useResourceMethod)src.moveTo(dest); } catch(IOException e){ useResourceMethod=false; } if(!useResourceMethod) { if(!dest.exists()) dest.createFile(false); IOUtil.copy(src,dest); src.remove(false); } } else { if(!dest.exists()) dest.createDirectory(false); Resource[] children = src.listResources(); for(int i=0;i<children.length;i++){ moveTo(children[i],dest.getRealResource(children[i].getName()),useResourceMethod); } src.remove(false); } dest.setLastModified(System.currentTimeMillis()); } /** * return the size of the Resource, other than method length of Resource this mthod return the size of all files in a directory * @param collectionDir * @return */ public static long getRealSize(Resource res) { return getRealSize(res,null); } /** * return the size of the Resource, other than method length of Resource this mthod return the size of all files in a directory * @param collectionDir * @return */ public static long getRealSize(Resource res, ResourceFilter filter) { if(res.isFile()) { return res.length(); } else if(res.isDirectory()) { long size=0; Resource[] children = filter==null?res.listResources():res.listResources(filter); for(int i=0;i<children.length;i++) { size+=getRealSize(children[i]); } return size; } return 0; } public static int getChildCount(Resource res) { return getChildCount(res, null); } public static int getChildCount(Resource res, ResourceFilter filter) { if(res.isFile()) { return 1; } else if(res.isDirectory()) { int size=0; Resource[] children = filter==null?res.listResources():res.listResources(filter); for(int i=0;i<children.length;i++) { size+=getChildCount(children[i]); } return size; } return 0; } /** * return if Resource is empty, means is directory and has no children or a empty file, * if not exist return false. * @param res * @return */ public static boolean isEmpty(Resource res) { return isEmptyDirectory(res,null) || isEmptyFile(res); } /** * return Boolean.True when directory is empty, Boolean.FALSE when directory s not empty and null if directory does not exists * @param res * @return */ public static boolean isEmptyDirectory(Resource res, ResourceFilter filter) { if(res.isDirectory()) { Resource[] children = filter==null? res.listResources(): res.listResources(filter); if(children==null || children.length==0) return true; for(int i=0;i<children.length;i++){ if(children[i].isFile()) return false; if(children[i].isDirectory() && !isEmptyDirectory(children[i], filter)) return false; } } return true; } public static boolean isEmptyFile(Resource res) { if(res.isFile()) { return res.length()==0; } return false; } public static Resource toResource(File file) { return ResourcesImpl.getFileResourceProvider().getResource(file.getPath()); } /** * list childrn of all given resources * @param resources * @return */ public static Resource[] listResources(Resource[] resources,ResourceFilter filter) { int count=0; Resource[] children; ArrayList<Resource[]> list=new ArrayList<Resource[]>(); for(int i=0;i<resources.length;i++) { children=filter==null?resources[i].listResources():resources[i].listResources(filter); if(children!=null){ count+=children.length; list.add(children); } else list.add(new Resource[0]); } Resource[] rtn=new Resource[count]; int index=0; for(int i=0;i<resources.length;i++) { children=list.get(i); for(int y=0;y<children.length;y++) { rtn[index++]=children[y]; } } //print.out(rtn); return rtn; } public static Resource[] listResources(Resource res,ResourceFilter filter) { return filter==null?res.listResources():res.listResources(filter); } public static void deleteFileOlderThan(Resource res, long date, ExtensionResourceFilter filter) { if(res.isFile()) { if(res.lastModified()<=date) res.delete(); } else if(res.isDirectory()) { Resource[] children = filter==null?res.listResources():res.listResources(filter); for(int i=0;i<children.length;i++) { deleteFileOlderThan(children[i],date,filter); } } } /** * check if directory creation is ok with the rules for the Resource interface, to not change this rules. * @param resource * @param createParentWhenNotExists * @throws IOException */ public static void checkCreateDirectoryOK(Resource resource, boolean createParentWhenNotExists) throws IOException { if(resource.exists()) { if(resource.isFile()) throw new IOException("can't create directory ["+resource.getPath()+"], resource already exists as a file"); if(resource.isDirectory()) throw new IOException("can't create directory ["+resource.getPath()+"], directory already exists"); } Resource parent = resource.getParentResource(); // when there is a parent but the parent does not exist if(parent!=null) { if(!parent.exists()) { if(createParentWhenNotExists)parent.createDirectory(true); else throw new IOException("can't create file ["+resource.getPath()+"], missing parent directory"); } else if(parent.isFile()) { throw new IOException("can't create directory ["+resource.getPath()+"], parent is a file"); } } } /** * check if file creating is ok with the rules for the Resource interface, to not change this rules. * @param resource * @param createParentWhenNotExists * @throws IOException */ public static void checkCreateFileOK(Resource resource, boolean createParentWhenNotExists) throws IOException { if(resource.exists()) { if(resource.isDirectory()) throw new IOException("can't create file ["+resource.getPath()+"], resource already exists as a directory"); if(resource.isFile()) throw new IOException("can't create file ["+resource.getPath()+"], file already exists"); } Resource parent = resource.getParentResource(); // when there is a parent but the parent does not exist if(parent!=null) { if(!parent.exists()) { if(createParentWhenNotExists)parent.createDirectory(true); else throw new IOException("can't create file ["+resource.getPath()+"], missing parent directory"); } else if(parent.isFile()) { throw new IOException("can't create file ["+resource.getPath()+"], parent is a file"); } } } /** * check if copying a file is ok with the rules for the Resource interface, to not change this rules. * @param source * @param target * @throws IOException */ public static void checkCopyToOK(Resource source, Resource target) throws IOException { if(!source.isFile()) { if(source.isDirectory()) throw new IOException("can't copy ["+source.getPath()+"] to ["+target.getPath()+"], source is a directory"); throw new IOException("can't copy ["+source.getPath()+"] to ["+target.getPath()+"], source file does not exist"); } else if(target.isDirectory()) { throw new IOException("can't copy ["+source.getPath()+"] to ["+target.getPath()+"], target is a directory"); } } /** * check if moveing a file is ok with the rules for the Resource interface, to not change this rules. * @param source * @param target * @throws IOException */ public static void checkMoveToOK(Resource source, Resource target) throws IOException { if(!source.exists()) { throw new IOException("can't move ["+source.getPath()+"] to ["+target.getPath()+"], source file does not exist"); } if(source.isDirectory() && target.isFile()) throw new IOException("can't move ["+source.getPath()+"] directory to ["+target.getPath()+"], target is a file"); if(source.isFile() && target.isDirectory()) throw new IOException("can't move ["+source.getPath()+"] file to ["+target.getPath()+"], target is a directory"); } /** * check if getting a inputstream of the file is ok with the rules for the Resource interface, to not change this rules. * @param resource * @throws IOException */ public static void checkGetInputStreamOK(Resource resource) throws IOException { if(!resource.exists()) throw new IOException("file ["+resource.getPath()+"] does not exist"); if(resource.isDirectory()) throw new IOException("can't read directory ["+resource.getPath()+"] as a file"); } /** * check if getting a outputstream of the file is ok with the rules for the Resource interface, to not change this rules. * @param resource * @throws IOException */ public static void checkGetOutputStreamOK(Resource resource) throws IOException { if(resource.exists() && !resource.isWriteable()) { throw new IOException("can't write to file ["+resource.getPath()+"],file is readonly"); } if(resource.isDirectory()) throw new IOException("can't write directory ["+resource.getPath()+"] as a file"); if(!resource.getParentResource().exists()) throw new IOException("can't write file ["+resource.getPath()+"] as a file, missing parent directory ["+resource.getParent()+"]"); } /** * check if removing the file is ok with the rules for the Resource interface, to not change this rules. * @param resource * @throws IOException */ public static void checkRemoveOK(Resource resource) throws IOException { if(!resource.exists())throw new IOException("can't delete resource "+resource+", resource does not exist"); if(!resource.canWrite())throw new IOException("can't delete resource "+resource+", no access"); } public static void deleteEmptyFolders(Resource res) throws IOException { if(res.isDirectory()){ Resource[] children = res.listResources(); for(int i=0;i<children.length;i++){ deleteEmptyFolders(children[i]); } if(res.listResources().length==0){ res.remove(false); } } } /** * if the pageSource is based on a archive, translate the source to a zip:// Resource * @return return the Resource matching this PageSource * @param pc the Page Context Object * @deprecated use instead <code>PageSource.getResourceTranslated(PageContext)</code> */ public static Resource getResource(PageContext pc,PageSource ps) throws PageException { return ps.getResourceTranslated(pc); } public static Resource getResource(PageContext pc,PageSource ps, Resource defaultValue) { try { return ps.getResourceTranslated(pc); } catch (Throwable t) { return defaultValue; } } public static int directrySize(Resource dir,ResourceFilter filter) { if(dir==null || !dir.isDirectory()) return 0; if(filter==null) return dir.list().length; return dir.list(filter).length; } public static int directrySize(Resource dir,ResourceNameFilter filter) { if(dir==null || !dir.isDirectory()) return 0; if(filter==null) return dir.list().length; return dir.list(filter).length; } public static String[] names(Resource[] resources) { String[] names=new String[resources.length]; for(int i=0;i<names.length;i++){ names[i]=resources[i].getName(); } return names; } public static Resource[] merge(Resource[] srcs, Resource[] trgs) { java.util.List<Resource> list=new ArrayList<Resource>(); if(srcs!=null){ for(int i=0;i<srcs.length;i++){ list.add(srcs[i]); } } if(trgs!=null){ for(int i=0;i<trgs.length;i++){ if(!list.contains(trgs[i]))list.add(trgs[i]); } } return list.toArray(new Resource[list.size()]); } public static void removeEmptyFolders(Resource dir) throws IOException { if(!dir.isDirectory()) return; Resource[] children = dir.listResources(IgnoreSystemFiles.INSTANCE); if(!ArrayUtil.isEmpty(children)) { boolean hasFiles=false; for(int i=0;i<children.length;i++){ if(children[i].isDirectory()) removeEmptyFolders(children[i]); else if(children[i].isFile()) { hasFiles=true; } } if(!hasFiles){ children = dir.listResources(IgnoreSystemFiles.INSTANCE); } } if(ArrayUtil.isEmpty(children)) dir.remove(true); } }