001    package railo.commons.io;
002    
003    import java.io.File;
004    import java.io.IOException;
005    import java.io.PrintWriter;
006    import java.lang.management.ManagementFactory;
007    import java.lang.management.MemoryPoolMXBean;
008    import java.lang.management.MemoryType;
009    import java.lang.management.MemoryUsage;
010    import java.lang.reflect.Field;
011    import java.lang.reflect.Method;
012    import java.net.MalformedURLException;
013    import java.net.URL;
014    import java.net.URLClassLoader;
015    import java.util.ArrayList;
016    import java.util.Iterator;
017    import java.util.LinkedList;
018    import java.util.Map;
019    import java.util.Map.Entry;
020    
021    import javax.servlet.ServletContext;
022    
023    import railo.commons.digest.MD5;
024    import railo.commons.io.res.Resource;
025    import railo.commons.io.res.ResourceProvider;
026    import railo.commons.io.res.ResourcesImpl;
027    import railo.commons.io.res.util.ResourceUtil;
028    import railo.commons.lang.ClassUtil;
029    import railo.commons.lang.StringUtil;
030    import railo.loader.TP;
031    import railo.loader.engine.CFMLEngineFactory;
032    import railo.runtime.Info;
033    import railo.runtime.config.Config;
034    import railo.runtime.exp.ApplicationException;
035    import railo.runtime.exp.DatabaseException;
036    import railo.runtime.functions.other.CreateUniqueId;
037    import railo.runtime.net.http.ReqRspUtil;
038    import railo.runtime.op.Caster;
039    import railo.runtime.type.Array;
040    import railo.runtime.type.Collection;
041    import railo.runtime.type.KeyImpl;
042    import railo.runtime.type.Query;
043    import railo.runtime.type.QueryImpl;
044    import railo.runtime.type.Struct;
045    import railo.runtime.type.StructImpl;
046    import railo.runtime.type.util.KeyConstants;
047    import railo.runtime.type.util.ListUtil;
048    
049    import com.jezhumble.javasysmon.CpuTimes;
050    import com.jezhumble.javasysmon.JavaSysMon;
051    import com.jezhumble.javasysmon.MemoryStats;
052    
053    /**
054     * 
055     */
056    public final class SystemUtil {
057    
058            public static final int MEMORY_TYPE_ALL=0;
059            public static final int MEMORY_TYPE_HEAP=1;
060            public static final int MEMORY_TYPE_NON_HEAP=2;
061    
062            public static final int ARCH_UNKNOW=0;
063            public static final int ARCH_32=32;
064            public static final int ARCH_64=64;
065    
066            public static final char CHAR_DOLLAR=(char)36;
067            public static final char CHAR_POUND=(char)163;
068            public static final char CHAR_EURO=(char)8364;
069            
070    
071            public static final int OUT = 0;
072            public static final int ERR = 1;
073            
074            private static final PrintWriter PRINTWRITER_OUT = new PrintWriter(System.out);
075            private static final PrintWriter PRINTWRITER_ERR = new PrintWriter(System.err);
076            
077            private static PrintWriter[] printWriter=new PrintWriter[2];
078        
079        
080            private static final boolean isWindows=System.getProperty("os.name").toLowerCase().startsWith("windows");
081        private static final boolean isUnix=!isWindows &&  File.separatorChar == '/';
082            
083        private static Resource tempFile;
084        private static Resource homeFile;
085        private static Resource[] classPathes;
086        private static String charset=System.getProperty("file.encoding");
087        private static String lineSeparator=System.getProperty("line.separator","\n");
088        private static MemoryPoolMXBean permGenSpaceBean;
089    
090            public static int osArch=-1;
091            public static int jreArch=-1;
092            
093            static {
094                    if(charset==null || charset.equalsIgnoreCase("MacRoman"))
095                            charset="cp1252";
096                    
097                    // Perm Gen
098                    permGenSpaceBean=getPermGenSpaceBean();
099                    // make sure the JVM does not always a new bean
100                    MemoryPoolMXBean tmp = getPermGenSpaceBean();
101                    if(tmp!=permGenSpaceBean)permGenSpaceBean=null;
102            }
103            
104            
105            
106            public static MemoryPoolMXBean getPermGenSpaceBean() {
107                    java.util.List<MemoryPoolMXBean> manager = ManagementFactory.getMemoryPoolMXBeans();
108                    MemoryPoolMXBean bean;
109                    // PERM GEN
110                    Iterator<MemoryPoolMXBean> it = manager.iterator();
111                    while(it.hasNext()){
112                            bean = it.next();
113                            if("Perm Gen".equalsIgnoreCase(bean.getName()) || "CMS Perm Gen".equalsIgnoreCase(bean.getName())) {
114                                    return bean;
115                            }
116                    }
117                    it = manager.iterator();
118                    while(it.hasNext()){
119                            bean = it.next();
120                            if(StringUtil.indexOfIgnoreCase(bean.getName(),"Perm Gen")!=-1 || StringUtil.indexOfIgnoreCase(bean.getName(),"PermGen")!=-1) {
121                                    return bean;
122                            }
123                    }
124                    // take none-heap when only one
125                    it = manager.iterator();
126                    LinkedList<MemoryPoolMXBean> beans=new LinkedList<MemoryPoolMXBean>();
127                    while(it.hasNext()){
128                            bean = it.next();
129                            if(bean.getType().equals(MemoryType.NON_HEAP)) {
130                                    beans.add(bean);
131                                    return bean;
132                            }
133                    }
134                    if(beans.size()==1) return beans.getFirst();
135                    
136                    // Class Memory/ClassBlock Memory?
137                    it = manager.iterator();
138                    while(it.hasNext()){
139                            bean = it.next();
140                            if(StringUtil.indexOfIgnoreCase(bean.getName(),"Class Memory")!=-1) {
141                                    return bean;
142                            }
143                    }
144                    
145                    
146                    return null;
147            }
148            
149        private static Boolean isFSCaseSensitive;
150            private static JavaSysMon jsm;
151            private static Boolean isCLI;
152            private static double loaderVersion=0D; 
153    
154        /**
155         * returns if the file system case sensitive or not
156         * @return is the file system case sensitive or not
157         */
158        public static boolean isFSCaseSensitive() { 
159            if(isFSCaseSensitive==null) { 
160                    try { 
161                            _isFSCaseSensitive(File.createTempFile("abcx","txt"));
162                    } 
163                    catch (IOException e) { 
164                            File f = new File("abcx.txt").getAbsoluteFile();
165                            try {
166                                                    f.createNewFile();
167                                _isFSCaseSensitive(f);
168                                                    
169                                            } catch (IOException e1) {
170                                                    throw new RuntimeException(e1.getMessage());
171                                            }
172                    } 
173            } 
174            return isFSCaseSensitive.booleanValue(); 
175        }
176        private static void _isFSCaseSensitive(File f) { 
177            File temp=new File(f.getPath().toUpperCase()); 
178            isFSCaseSensitive=temp.exists()?Boolean.FALSE:Boolean.TRUE; 
179            f.delete(); 
180        }
181            
182        /**
183         * @return is local machine a Windows Machine
184         */
185        public static boolean isWindows() {
186            return isWindows;
187        }
188    
189        /**
190         * @return is local machine a Unix Machine
191         */
192        public static boolean isUnix() {
193            return isUnix;
194        }
195    
196        /**
197         * @return return System directory
198         */
199        public static Resource getSystemDirectory() {
200            String pathes=System.getProperty("java.library.path");
201            ResourceProvider fr = ResourcesImpl.getFileResourceProvider();
202            if(pathes!=null) {
203                String[] arr=ListUtil.toStringArrayEL(ListUtil.listToArray(pathes,File.pathSeparatorChar));
204                for(int i=0;i<arr.length;i++) {    
205                    if(arr[i].toLowerCase().indexOf("windows\\system")!=-1) {
206                        Resource file = fr.getResource(arr[i]);
207                        if(file.exists() && file.isDirectory() && file.isWriteable()) return ResourceUtil.getCanonicalResourceEL(file);
208                        
209                    }
210                }
211                for(int i=0;i<arr.length;i++) {    
212                    if(arr[i].toLowerCase().indexOf("windows")!=-1) {
213                            Resource file = fr.getResource(arr[i]);
214                        if(file.exists() && file.isDirectory() && file.isWriteable()) return ResourceUtil.getCanonicalResourceEL(file);
215                        
216                    }
217                }
218                for(int i=0;i<arr.length;i++) {    
219                    if(arr[i].toLowerCase().indexOf("winnt")!=-1) {
220                            Resource file = fr.getResource(arr[i]);
221                        if(file.exists() && file.isDirectory() && file.isWriteable()) return ResourceUtil.getCanonicalResourceEL(file);
222                        
223                    }
224                }
225                for(int i=0;i<arr.length;i++) {    
226                    if(arr[i].toLowerCase().indexOf("win")!=-1) {
227                            Resource file = fr.getResource(arr[i]);
228                        if(file.exists() && file.isDirectory() && file.isWriteable()) return ResourceUtil.getCanonicalResourceEL(file);
229                        
230                    }
231                }
232                for(int i=0;i<arr.length;i++) {
233                    Resource file = fr.getResource(arr[i]);
234                    if(file.exists() && file.isDirectory() && file.isWriteable()) return ResourceUtil.getCanonicalResourceEL(file);
235                }
236            }
237            return null;
238        }
239        
240        /**
241         * @return return running context root
242         */
243        public static Resource getRuningContextRoot() {
244            ResourceProvider frp = ResourcesImpl.getFileResourceProvider();
245            
246            try {
247                return frp.getResource(".").getCanonicalResource();
248            } catch (IOException e) {}
249            URL url=new Info().getClass().getClassLoader().getResource(".");
250            try {
251                return frp.getResource(FileUtil.URLToFile(url).getAbsolutePath());
252            } catch (MalformedURLException e) {
253                return null;
254            }
255        }
256        
257        /**
258         * returns the Temp Directory of the System
259         * @return temp directory
260         */
261        public static Resource getTempDirectory() {
262            if(tempFile!=null) return tempFile;
263            ResourceProvider fr = ResourcesImpl.getFileResourceProvider();
264            String tmpStr = System.getProperty("java.io.tmpdir");
265            if(tmpStr!=null) {
266                tempFile=fr.getResource(tmpStr);
267                if(tempFile.exists()) {
268                    tempFile=ResourceUtil.getCanonicalResourceEL(tempFile);
269                    return tempFile;
270                }
271            }
272            File tmp =null;
273            try {
274                    tmp = File.createTempFile("a","a");
275                tempFile=fr.getResource(tmp.getParent());
276                tempFile=ResourceUtil.getCanonicalResourceEL(tempFile);   
277            }
278            catch(IOException ioe) {}
279            finally {
280                    if(tmp!=null)tmp.delete();
281            }
282            return tempFile;
283        }
284        
285    
286        /**
287         * returns the a unique temp file (with no auto delete)
288         * @param extension 
289         * @return temp directory
290         * @throws IOException 
291         */
292        public static Resource getTempFile(String extension, boolean touch) throws IOException {
293            String filename=CreateUniqueId.invoke();
294            if(!StringUtil.isEmpty(extension,true)){
295                    if(extension.startsWith("."))filename+=extension;
296                    else filename+="."+extension;
297            }
298                    Resource file = getTempDirectory().getRealResource(filename);
299                    if(touch)ResourceUtil.touch(file);
300                    return file;
301            }
302        
303        /**
304         * returns the Hoome Directory of the System
305         * @return home directory
306         */
307        public static Resource getHomeDirectory() {
308            if(homeFile!=null) return homeFile;
309            
310            ResourceProvider frp = ResourcesImpl.getFileResourceProvider();
311            
312            String homeStr = System.getProperty("user.home");
313            if(homeStr!=null) {
314                homeFile=frp.getResource(homeStr);
315                homeFile=ResourceUtil.getCanonicalResourceEL(homeFile);
316            }
317            return homeFile;
318        }
319        
320        public static Resource getClassLoadeDirectory(){
321            return ResourceUtil.toResource(CFMLEngineFactory.getClassLoaderRoot(TP.class.getClassLoader()));
322        }
323    
324        /**
325         * get class pathes from all url ClassLoaders
326         * @param ucl URL Class Loader
327         * @param pathes Hashmap with allpathes
328         */
329        private static void getClassPathesFromClassLoader(URLClassLoader ucl, ArrayList pathes) {
330            ClassLoader pcl=ucl.getParent();
331            // parent first
332            if(pcl instanceof URLClassLoader)
333                getClassPathesFromClassLoader((URLClassLoader) pcl, pathes);
334    
335            ResourceProvider frp = ResourcesImpl.getFileResourceProvider();
336            // get all pathes
337            URL[] urls=ucl.getURLs();
338            for(int i=0;i<urls.length;i++) {
339                Resource file=frp.getResource(urls[i].getPath());
340                if(file.exists())
341                    pathes.add(ResourceUtil.getCanonicalResourceEL(file));
342            }
343            
344        }
345        
346        /**
347         * @return returns a string list of all pathes
348         */
349        public static Resource[] getClassPathes() {
350            
351            if(classPathes!=null) 
352                return classPathes;
353            
354            ArrayList pathes=new ArrayList();
355            String pathSeperator=System.getProperty("path.separator");
356            if(pathSeperator==null)pathSeperator=";";
357                
358        // java.ext.dirs
359            ResourceProvider frp = ResourcesImpl.getFileResourceProvider();
360            
361            
362        // pathes from system properties
363            String strPathes=System.getProperty("java.class.path");
364            if(strPathes!=null) {
365                Array arr=ListUtil.listToArrayRemoveEmpty(strPathes,pathSeperator);
366                int len=arr.size();
367                for(int i=1;i<=len;i++) {
368                    Resource file=frp.getResource(Caster.toString(arr.get(i,""),"").trim());
369                    if(file.exists())
370                        pathes.add(ResourceUtil.getCanonicalResourceEL(file));
371                }
372            }
373            
374            
375        // pathes from url class Loader (dynamic loaded classes)
376            ClassLoader cl = new Info().getClass().getClassLoader();
377            if(cl instanceof URLClassLoader) 
378                getClassPathesFromClassLoader((URLClassLoader) cl, pathes);
379            
380            return classPathes=(Resource[]) pathes.toArray(new Resource[pathes.size()]);
381            
382        }
383    
384        public static long getUsedMemory() {
385            Runtime r = Runtime.getRuntime();
386            return r.totalMemory()-r.freeMemory();
387        }
388        public static long getAvailableMemory() {
389            Runtime r = Runtime.getRuntime();
390            return r.freeMemory();
391        }
392    
393        /**
394         * replace path placeholder with the real path, placeholders are [{temp-directory},{system-directory},{home-directory}]
395         * @param path
396         * @return updated path
397         */
398        public static String parsePlaceHolder(String path) {
399            if(path==null) return path;
400            // Temp
401            if(path.startsWith("{temp")) {
402                if(path.startsWith("}",5)) path=getTempDirectory().getRealResource(path.substring(6)).toString();
403                else if(path.startsWith("-dir}",5)) path=getTempDirectory().getRealResource(path.substring(10)).toString();
404                else if(path.startsWith("-directory}",5)) path=getTempDirectory().getRealResource(path.substring(16)).toString();
405            }
406            // System
407            else if(path.startsWith("{system")) {
408                if(path.startsWith("}",7)) path=getSystemDirectory().getRealResource(path.substring(8)).toString();
409                else if(path.startsWith("-dir}",7)) path=getSystemDirectory().getRealResource(path.substring(12)).toString();
410                else if(path.startsWith("-directory}",7)) path=getSystemDirectory().getRealResource(path.substring(18)).toString();
411            }
412            // Home
413            else if(path.startsWith("{home")) {
414                if(path.startsWith("}",5)) path=getHomeDirectory().getRealResource(path.substring(6)).toString();
415                else if(path.startsWith("-dir}",5)) path=getHomeDirectory().getRealResource(path.substring(10)).toString();
416                else if(path.startsWith("-directory}",5)) path=getHomeDirectory().getRealResource(path.substring(16)).toString();
417            }
418            // ClassLoaderDir
419            else if(path.startsWith("{classloader")) {
420                if(path.startsWith("}",12)) path=getClassLoadeDirectory().getRealResource(path.substring(13)).toString();
421                else if(path.startsWith("-dir}",12)) path=getClassLoadeDirectory().getRealResource(path.substring(17)).toString();
422                else if(path.startsWith("-directory}",12)) path=getClassLoadeDirectory().getRealResource(path.substring(23)).toString();
423            }
424            return path;
425        }
426        
427        public static String addPlaceHolder(Resource file, String defaultValue) {
428         // Temp
429            String path=addPlaceHolder(getTempDirectory(),file,"{temp-directory}");
430            if(!StringUtil.isEmpty(path)) return path;
431         // System
432            path=addPlaceHolder(getSystemDirectory(),file,"{system-directory}");
433            if(!StringUtil.isEmpty(path)) return path;
434         // Home
435            path=addPlaceHolder(getHomeDirectory(),file,"{home-directory}");
436            if(!StringUtil.isEmpty(path)) return path;
437            
438          
439            return defaultValue;
440        }
441        
442        private static String addPlaceHolder(Resource dir, Resource file,String placeholder) {
443            if(ResourceUtil.isChildOf(file, dir)){
444                    try {
445                                    return StringUtil.replace(file.getCanonicalPath(), dir.getCanonicalPath(), placeholder, true);
446                            } 
447                    catch (IOException e) {}
448            }
449            return null;
450            }
451        
452    
453            public static String addPlaceHolder(Resource file,  Config config, String defaultValue) {
454            //ResourceProvider frp = ResourcesImpl.getFileResourceProvider();
455            
456            // temp
457                    Resource dir = config.getTempDirectory();
458                    String path = addPlaceHolder(dir,file,"{temp-directory}");
459                    if(!StringUtil.isEmpty(path)) return path;
460                    
461            // Config 
462                    dir = config.getConfigDir();
463                    path = addPlaceHolder(dir,file,"{railo-config-directory}");
464                    if(!StringUtil.isEmpty(path)) return path;
465    
466            /* / Config WEB
467                    dir = config.getConfigDir();
468                    path = addPlaceHolder(dir,file,"{railo-server-directory}");
469                    if(!StringUtil.isEmpty(path)) return path;
470    */
471            // Web root
472                    dir = config.getRootDirectory();
473                    path = addPlaceHolder(dir,file,"{web-root-directory}");
474                    if(!StringUtil.isEmpty(path)) return path;
475    
476            return addPlaceHolder(file, defaultValue);
477        }
478            
479            public static String parsePlaceHolder(String path, ServletContext sc, Map<String,String> labels) {
480                    if(path==null) return null;
481            if(path.indexOf('{')!=-1){
482                    if((path.indexOf("{web-context-label}"))!=-1){
483                            String id=hash(sc);
484                            
485                            String label=labels.get(id);
486                            if(StringUtil.isEmpty(label)) label=id;
487                            
488                            path=StringUtil.replace(path, "{web-context-label}", label, false);
489                    }
490            }
491            return parsePlaceHolder(path, sc);
492        }
493        
494            public static String parsePlaceHolder(String path, ServletContext sc) {
495            ResourceProvider frp = ResourcesImpl.getFileResourceProvider();
496            
497            
498            if(path==null) return null;
499            if(path.indexOf('{')!=-1){
500                    if(StringUtil.startsWith(path,'{')){
501                        
502                        // Web Root
503                        if(path.startsWith("{web-root")) {
504                            if(path.startsWith("}",9))                                      path=frp.getResource(ReqRspUtil.getRootPath(sc)).getRealResource(path.substring(10)).toString();
505                            else if(path.startsWith("-dir}",9))             path=frp.getResource(ReqRspUtil.getRootPath(sc)).getRealResource(path.substring(14)).toString();
506                            else if(path.startsWith("-directory}",9))       path=frp.getResource(ReqRspUtil.getRootPath(sc)).getRealResource(path.substring(20)).toString();
507            
508                        }
509                        else path=SystemUtil.parsePlaceHolder(path);
510                    }
511                    
512                    if((path.indexOf("{web-context-hash}"))!=-1){
513                            String id=hash(sc);
514                            path=StringUtil.replace(path, "{web-context-hash}", id, false);
515                    }
516            }
517            return path;
518        }
519            
520            public static String hash(ServletContext sc) {
521            String id=null;
522                    try {
523                            id=MD5.getDigestAsString(ReqRspUtil.getRootPath(sc));
524                    } 
525                    catch (IOException e) {}
526                    return id;
527        }
528    
529        public static String getCharset() {
530            return charset;
531        }
532    
533            public static void setCharset(String charset) {
534                    SystemUtil.charset = charset;
535            }
536    
537            public static String getOSSpecificLineSeparator() {
538                    return lineSeparator;
539            }
540    
541            public static void sleep(int time) {
542                    try {
543                            Thread.sleep(time);
544                    } catch (InterruptedException e) {}
545            }
546    
547            public static void sleep(long time) {
548                    try {
549                            Thread.sleep(time);
550                    } catch (InterruptedException e) {}
551            }
552            public static void join(Thread t) {
553                    try {
554                            t.join();
555                    } catch (InterruptedException e) {}
556            }
557            
558            /**
559             * locks the object (synchronized) before calling wait
560             * @param lock
561             * @param timeout
562             * @throws InterruptedException
563             */
564            public static void wait(Object lock, long timeout) {
565                    try {
566                            synchronized (lock) {lock.wait(timeout);}
567                    } catch (InterruptedException e) {}
568            }
569    
570            /**
571             * locks the object (synchronized) before calling wait (no timeout)
572             * @param lock
573             * @throws InterruptedException
574             */
575            public static void wait(Object lock) {
576                    try {
577                            synchronized (lock) {lock.wait();}
578                    } catch (InterruptedException e) {}
579            }
580            
581            
582            
583            /**
584             * locks the object (synchronized) before calling notify
585             * @param lock
586             * @param timeout
587             * @throws InterruptedException
588             */
589            public static void notify(Object lock) {
590                    synchronized (lock) {lock.notify();}
591            }
592            
593            /**
594             * locks the object (synchronized) before calling notifyAll
595             * @param lock
596             * @param timeout
597             * @throws InterruptedException
598             */
599            public static void notifyAll(Object lock) {
600                    synchronized (lock) {lock.notifyAll();}
601            }
602    
603            /**
604             * return the operating system architecture
605             * @return one of the following SystemUtil.ARCH_UNKNOW, SystemUtil.ARCH_32, SystemUtil.ARCH_64
606             */
607            public static int getOSArch(){
608                    if(osArch==-1) {
609                            osArch = toIntArch(System.getProperty("os.arch.data.model"));
610                            if(osArch==ARCH_UNKNOW)osArch = toIntArch(System.getProperty("os.arch"));
611                    }
612                    return osArch;
613            }
614            
615            /**
616             * return the JRE (Java Runtime Engine) architecture, this can be different from the operating system architecture
617             * @return one of the following SystemUtil.ARCH_UNKNOW, SystemUtil.ARCH_32, SystemUtil.ARCH_64
618             */
619            public static int getJREArch(){
620                    if(jreArch==-1) {
621                            jreArch = toIntArch(System.getProperty("sun.arch.data.model"));
622                            if(jreArch==ARCH_UNKNOW)jreArch = toIntArch(System.getProperty("com.ibm.vm.bitmode"));
623                            if(jreArch==ARCH_UNKNOW)jreArch = toIntArch(System.getProperty("java.vm.name"));
624                            if(jreArch==ARCH_UNKNOW) {
625                                    int addrSize = getAddressSize();
626                                    if(addrSize==4) return ARCH_32;
627                                    if(addrSize==8) return ARCH_64;
628                            }
629                            
630                    }
631                    return jreArch;
632            }
633            
634            private static int toIntArch(String strArch){
635                    if(!StringUtil.isEmpty(strArch)) {
636                            if(strArch.indexOf("64")!=-1) return ARCH_64;
637                            if(strArch.indexOf("32")!=-1) return ARCH_32;
638                            if(strArch.indexOf("i386")!=-1) return ARCH_32;
639                            if(strArch.indexOf("x86")!=-1) return ARCH_32;
640                    }
641                    return ARCH_UNKNOW;
642            }
643            
644    
645            
646            public static int getAddressSize() {
647                    try {
648                            Class unsafe = ClassUtil.loadClass(null,"sun.misc.Unsafe",null);
649                            if(unsafe==null) return 0;
650                    
651                            Field unsafeField = unsafe.getDeclaredField("theUnsafe");
652                        unsafeField.setAccessible(true);
653                        Object obj = unsafeField.get(null);
654                        Method addressSize = unsafe.getMethod("addressSize", new Class[0]);
655                        
656                        Object res = addressSize.invoke(obj, new Object[0]);
657                        return Caster.toIntValue(res,0);
658                    }
659                    catch(Throwable t){
660                            return 0;
661                    }
662                
663            }
664            /*private static MemoryUsage getPermGenSpaceSize() {
665                    MemoryUsage mu = getPermGenSpaceSize(null);
666                    if(mu!=null) return mu;
667                    
668                    // create error message including info about available memory blocks
669                    StringBuilder sb=new StringBuilder();
670                    java.util.List<MemoryPoolMXBean> manager = ManagementFactory.getMemoryPoolMXBeans();
671                    Iterator<MemoryPoolMXBean> it = manager.iterator();
672                    MemoryPoolMXBean bean;
673                    while(it.hasNext()){
674                            bean = it.next();
675                            if(sb.length()>0)sb.append(", ");
676                            sb.append(bean.getName());
677                    }
678                    throw new RuntimeException("PermGen Space information not available, available Memory blocks are ["+sb+"]");
679            }*/
680            
681            private static MemoryUsage getPermGenSpaceSize(MemoryUsage defaultValue) {
682                    if(permGenSpaceBean!=null) return permGenSpaceBean.getUsage();
683                    // create on the fly when the bean is not permanent
684                    MemoryPoolMXBean tmp = getPermGenSpaceBean();
685                    if(tmp!=null) return tmp.getUsage();
686                    
687                    return defaultValue;
688            }
689            
690    
691            public static long getFreePermGenSpaceSize() {
692                    MemoryUsage mu = getPermGenSpaceSize(null);
693                    if(mu==null) return -1;
694                    
695                    long max = mu.getMax();
696                    long used = mu.getUsed();
697                    if(max<0 || used<0) return -1;
698                    return max-used;
699            }
700            
701            public static int getFreePermGenSpacePromille() {
702                    MemoryUsage mu = getPermGenSpaceSize(null);
703                    if(mu==null) return -1;
704                    
705                    long max = mu.getMax();
706                    long used = mu.getUsed();
707                    if(max<0 || used<0) return -1;
708                    return (int)(1000L-(1000L*used/max));
709            }
710            
711            public static Query getMemoryUsageAsQuery(int type) throws DatabaseException {
712                    
713                    
714                    java.util.List<MemoryPoolMXBean> manager = ManagementFactory.getMemoryPoolMXBeans();
715                    Iterator<MemoryPoolMXBean> it = manager.iterator();
716                    Query qry=new QueryImpl(new Collection.Key[]{
717                                    KeyConstants._name,
718                                    KeyConstants._type,
719                                    KeyConstants._used,
720                                    KeyConstants._max,
721                                    KeyConstants._init
722                    },0,"memory");
723                    
724                    int row=0;
725                    MemoryPoolMXBean bean;
726                    MemoryUsage usage;
727                    MemoryType _type;
728                    while(it.hasNext()){
729                            bean = it.next();
730                            usage = bean.getUsage();
731                            _type = bean.getType();
732                            if(type==MEMORY_TYPE_HEAP && _type!=MemoryType.HEAP)continue;
733                            if(type==MEMORY_TYPE_NON_HEAP && _type!=MemoryType.NON_HEAP)continue;
734                                    
735                            row++;
736                            qry.addRow();
737                            qry.setAtEL(KeyConstants._name, row, bean.getName());
738                            qry.setAtEL(KeyConstants._type, row, _type.name());
739                            qry.setAtEL(KeyConstants._max, row, Caster.toDouble(usage.getMax()));
740                            qry.setAtEL(KeyConstants._used, row, Caster.toDouble(usage.getUsed()));
741                            qry.setAtEL(KeyConstants._init, row, Caster.toDouble(usage.getInit()));
742                            
743                    }
744                    return qry;
745            }
746            
747            public static Struct getMemoryUsageAsStruct(int type) {
748                    java.util.List<MemoryPoolMXBean> manager = ManagementFactory.getMemoryPoolMXBeans();
749                    Iterator<MemoryPoolMXBean> it = manager.iterator();
750                    
751                    MemoryPoolMXBean bean;
752                    MemoryUsage usage;
753                    MemoryType _type;
754                    long used=0,max=0,init=0;
755                    while(it.hasNext()){
756                            bean = it.next();
757                            usage = bean.getUsage();
758                            _type = bean.getType();
759                            if((type==MEMORY_TYPE_HEAP && _type==MemoryType.HEAP) || (type==MEMORY_TYPE_NON_HEAP && _type==MemoryType.NON_HEAP)){
760                                    used+=usage.getUsed();
761                                    max+=usage.getMax();
762                                    init+=usage.getInit();
763                            }
764                    }
765                    Struct sct=new StructImpl();
766                    sct.setEL(KeyConstants._used, Caster.toDouble(used));
767                    sct.setEL(KeyConstants._max, Caster.toDouble(max));
768                    sct.setEL(KeyConstants._init, Caster.toDouble(init));
769                    sct.setEL(KeyImpl.init("available"), Caster.toDouble(max-used));
770                    return sct;
771            }
772            
773    
774            public static Struct getMemoryUsageCompact(int type) {
775                    java.util.List<MemoryPoolMXBean> manager = ManagementFactory.getMemoryPoolMXBeans();
776                    Iterator<MemoryPoolMXBean> it = manager.iterator();
777                    
778                    MemoryPoolMXBean bean;
779                    MemoryUsage usage;
780                    MemoryType _type;
781                    Struct sct=new StructImpl();
782                    while(it.hasNext()){
783                            bean = it.next();
784                            usage = bean.getUsage();
785                            _type = bean.getType();
786                            if(type==MEMORY_TYPE_HEAP && _type!=MemoryType.HEAP)continue;
787                            if(type==MEMORY_TYPE_NON_HEAP && _type!=MemoryType.NON_HEAP)continue;
788                                    
789                            double d=((int)(100D/usage.getMax()*usage.getUsed()))/100D;
790                            sct.setEL(KeyImpl.init(bean.getName()), Caster.toDouble(d));
791                    }
792                    return sct;
793            }
794            
795            public static String getPropertyEL(String key) {
796                    try{
797                            String str = System.getProperty(key);
798                            if(!StringUtil.isEmpty(str,true)) return str;
799                            
800                            Iterator<Entry<Object, Object>> it = System.getProperties().entrySet().iterator();
801                            Entry<Object, Object> e;
802                            String n;
803                            while(it.hasNext()){
804                                    e = it.next();
805                                    n=(String) e.getKey();
806                                    if(key.equalsIgnoreCase(n)) return (String) e.getValue();
807                            }
808                            
809                    }
810                    catch(Throwable t){}
811                    return null;
812            }
813            public static long microTime() {
814                    return System.nanoTime()/1000L;
815            }
816            
817            public static TemplateLine getCurrentContext() {
818                    return _getCurrentContext(new Exception("Stack trace"));
819            }
820            private static TemplateLine _getCurrentContext(Throwable t) {
821                    
822                    //Throwable root = t.getRootCause();
823                    Throwable cause = t.getCause(); 
824                    if(cause!=null)_getCurrentContext(cause);
825                    StackTraceElement[] traces = t.getStackTrace();
826                    
827                    
828            int line=0;
829                    String template;
830                    
831                    StackTraceElement trace=null;
832                    for(int i=0;i<traces.length;i++) {
833                            trace=traces[i];
834                            template=trace.getFileName();
835                            if(trace.getLineNumber()<=0 || template==null || ResourceUtil.getExtension(template,"").equals("java")) continue;
836                            line=trace.getLineNumber();
837                            return new TemplateLine(template,line);
838                    }
839                    return null;
840            }
841            
842            public static class TemplateLine {
843    
844                    public final String template;
845                    public final int line;
846    
847                    public TemplateLine(String template, int line) {
848                            this.template=template;
849                            this.line=line;
850                    }
851                    public String toString(){
852                            return template+":"+line;
853                    }
854            }
855    
856            public static long getFreeBytes() throws ApplicationException {
857                    return physical().getFreeBytes();
858            }
859    
860            public static long getTotalBytes() throws ApplicationException {
861                    return physical().getTotalBytes();
862            }
863            
864            public static double getCpuUsage(long time) throws ApplicationException {
865                    if(time<1) throw new ApplicationException("time has to be bigger than 0");
866                    if(jsm==null) jsm=new JavaSysMon();
867                    CpuTimes cput = jsm.cpuTimes();
868                    if(cput==null) throw new ApplicationException("CPU information are not available for this OS");
869                    CpuTimes previous = new CpuTimes(cput.getUserMillis(),cput.getSystemMillis(),cput.getIdleMillis());
870            sleep(time);
871            
872            return jsm.cpuTimes().getCpuUsage(previous)*100D;
873        }
874            
875    
876            private synchronized static MemoryStats physical() throws ApplicationException {
877                    if(jsm==null) jsm=new JavaSysMon();
878                    MemoryStats p = jsm.physical();
879                    if(p==null) throw new ApplicationException("Memory information are not available for this OS");
880                    return p;
881            }
882            public static void setPrintWriter(int type,PrintWriter pw) {
883                    printWriter[type]=pw;
884            }
885            public static PrintWriter getPrintWriter(int type) {
886                    if(printWriter[type]==null) {
887                            if(type==OUT) printWriter[OUT]=PRINTWRITER_OUT;
888                            else printWriter[ERR]=PRINTWRITER_ERR;
889                    }
890                    return printWriter[type];
891            }
892            public static boolean isCLICall() {
893            if(isCLI==null){
894                    isCLI=Caster.toBoolean(System.getProperty("railo.cli.call"),Boolean.FALSE);
895            }
896            return isCLI.booleanValue();
897            }
898            
899            public static double getLoaderVersion() {
900                    // this is done via reflection to make it work in older version, where the class railo.loader.Version does not exist
901                    if(loaderVersion==0D) {
902                            loaderVersion=4D;
903                            Class cVersion = ClassUtil.loadClass(TP.class.getClassLoader(),"railo.loader.Version",null);
904                            if(cVersion!=null) {
905                                    try {
906                                            Field f = cVersion.getField("VERSION");
907                                            loaderVersion=f.getDouble(null);
908                                    } 
909                                    catch (Throwable t) {t.printStackTrace();}
910                            }
911                    }
912                    return loaderVersion;
913            }
914    }