001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.commons.io; 020 021import java.io.File; 022import java.io.IOException; 023import java.io.PrintWriter; 024import java.io.Serializable; 025import java.lang.management.ManagementFactory; 026import java.lang.management.MemoryPoolMXBean; 027import java.lang.management.MemoryType; 028import java.lang.management.MemoryUsage; 029import java.lang.reflect.Field; 030import java.lang.reflect.InvocationTargetException; 031import java.lang.reflect.Method; 032import java.net.InetAddress; 033import java.net.MalformedURLException; 034import java.net.NetworkInterface; 035import java.net.URL; 036import java.net.URLClassLoader; 037import java.nio.charset.Charset; 038import java.util.ArrayList; 039import java.util.Iterator; 040import java.util.LinkedList; 041import java.util.Map; 042import java.util.Map.Entry; 043 044import javax.servlet.ServletContext; 045 046import lucee.aprint; 047import lucee.commons.digest.MD5; 048import lucee.commons.io.log.Log; 049import lucee.commons.io.log.LogUtil; 050import lucee.commons.io.res.Resource; 051import lucee.commons.io.res.ResourceProvider; 052import lucee.commons.io.res.ResourcesImpl; 053import lucee.commons.io.res.util.ResourceUtil; 054import lucee.commons.lang.ClassUtil; 055import lucee.commons.lang.ExceptionUtil; 056import lucee.commons.lang.StringUtil; 057import lucee.loader.TP; 058import lucee.loader.engine.CFMLEngineFactory; 059import lucee.runtime.Info; 060import lucee.runtime.PageContext; 061import lucee.runtime.PageContextImpl; 062import lucee.runtime.config.Config; 063import lucee.runtime.exp.ApplicationException; 064import lucee.runtime.exp.DatabaseException; 065import lucee.runtime.exp.StopException; 066import lucee.runtime.functions.other.CreateUniqueId; 067import lucee.runtime.net.http.ReqRspUtil; 068import lucee.runtime.op.Caster; 069import lucee.runtime.type.Array; 070import lucee.runtime.type.Collection; 071import lucee.runtime.type.KeyImpl; 072import lucee.runtime.type.Query; 073import lucee.runtime.type.QueryImpl; 074import lucee.runtime.type.Struct; 075import lucee.runtime.type.StructImpl; 076import lucee.runtime.type.util.KeyConstants; 077import lucee.runtime.type.util.ListUtil; 078 079import com.jezhumble.javasysmon.CpuTimes; 080import com.jezhumble.javasysmon.JavaSysMon; 081import com.jezhumble.javasysmon.MemoryStats; 082 083/** 084 * 085 */ 086public final class SystemUtil { 087 088 public static final int MEMORY_TYPE_ALL=0; 089 public static final int MEMORY_TYPE_HEAP=1; 090 public static final int MEMORY_TYPE_NON_HEAP=2; 091 092 public static final int ARCH_UNKNOW=0; 093 public static final int ARCH_32=32; 094 public static final int ARCH_64=64; 095 096 public static final char CHAR_DOLLAR=(char)36; 097 public static final char CHAR_POUND=(char)163; 098 public static final char CHAR_EURO=(char)8364; 099 100 101 public static final int JAVA_VERSION_1_0 = 0; 102 public static final int JAVA_VERSION_1_1 = 1; 103 public static final int JAVA_VERSION_1_2 = 2; 104 public static final int JAVA_VERSION_1_3 = 3; 105 public static final int JAVA_VERSION_1_4 = 4; 106 public static final int JAVA_VERSION_1_5 = 5; 107 public static final int JAVA_VERSION_1_6 = 6; 108 public static final int JAVA_VERSION_1_7 = 7; 109 public static final int JAVA_VERSION_1_8 = 8; 110 public static final int JAVA_VERSION_1_9 = 9; 111 112 113 public static final int OUT = 0; 114 public static final int ERR = 1; 115 116 private static final PrintWriter PRINTWRITER_OUT = new PrintWriter(System.out); 117 private static final PrintWriter PRINTWRITER_ERR = new PrintWriter(System.err); 118 119 private static PrintWriter[] printWriter=new PrintWriter[2]; 120 121 122 private static final boolean isWindows=System.getProperty("os.name").toLowerCase().startsWith("windows"); 123 private static final boolean isUnix=!isWindows && File.separatorChar == '/'; 124 125 private static final String JAVA_VERSION_STRING = System.getProperty("java.version"); 126 public static final int JAVA_VERSION; 127 static { 128 if(JAVA_VERSION_STRING.startsWith("1.9.")) JAVA_VERSION=JAVA_VERSION_1_9; 129 else if(JAVA_VERSION_STRING.startsWith("1.8.")) JAVA_VERSION=JAVA_VERSION_1_8; 130 else if(JAVA_VERSION_STRING.startsWith("1.7.")) JAVA_VERSION=JAVA_VERSION_1_7; 131 else if(JAVA_VERSION_STRING.startsWith("1.6.")) JAVA_VERSION=JAVA_VERSION_1_6; 132 else if(JAVA_VERSION_STRING.startsWith("1.5.")) JAVA_VERSION=JAVA_VERSION_1_5; 133 else if(JAVA_VERSION_STRING.startsWith("1.4.")) JAVA_VERSION=JAVA_VERSION_1_4; 134 else if(JAVA_VERSION_STRING.startsWith("1.3.")) JAVA_VERSION=JAVA_VERSION_1_3; 135 else if(JAVA_VERSION_STRING.startsWith("1.2.")) JAVA_VERSION=JAVA_VERSION_1_2; 136 else if(JAVA_VERSION_STRING.startsWith("1.1.")) JAVA_VERSION=JAVA_VERSION_1_1; 137 else JAVA_VERSION=JAVA_VERSION_1_0; 138 } 139 140 private static Resource tempFile; 141 private static Resource homeFile; 142 private static Resource[] classPathes; 143 private static Charset charset; 144 private static String lineSeparator=System.getProperty("line.separator","\n"); 145 private static MemoryPoolMXBean permGenSpaceBean; 146 147 public static int osArch=-1; 148 public static int jreArch=-1; 149 150 static { 151 String strCharset=System.getProperty("file.encoding"); 152 if(strCharset==null || strCharset.equalsIgnoreCase("MacRoman")) 153 strCharset="cp1252"; 154 155 if(strCharset.equalsIgnoreCase("utf-8")) charset=CharsetUtil.UTF8; 156 else if(strCharset.equalsIgnoreCase("iso-8859-1")) charset=CharsetUtil.ISO88591; 157 else charset=CharsetUtil.toCharset(strCharset,null); 158 159 // Perm Gen 160 permGenSpaceBean=getPermGenSpaceBean(); 161 // make sure the JVM does not always a new bean 162 MemoryPoolMXBean tmp = getPermGenSpaceBean(); 163 if(tmp!=permGenSpaceBean)permGenSpaceBean=null; 164 } 165 166 167 168 public static MemoryPoolMXBean getPermGenSpaceBean() { 169 java.util.List<MemoryPoolMXBean> manager = ManagementFactory.getMemoryPoolMXBeans(); 170 MemoryPoolMXBean bean; 171 // PERM GEN 172 Iterator<MemoryPoolMXBean> it = manager.iterator(); 173 while(it.hasNext()){ 174 bean = it.next(); 175 if("Perm Gen".equalsIgnoreCase(bean.getName()) || "CMS Perm Gen".equalsIgnoreCase(bean.getName())) { 176 return bean; 177 } 178 } 179 it = manager.iterator(); 180 while(it.hasNext()){ 181 bean = it.next(); 182 if(StringUtil.indexOfIgnoreCase(bean.getName(),"Perm Gen")!=-1 || StringUtil.indexOfIgnoreCase(bean.getName(),"PermGen")!=-1) { 183 return bean; 184 } 185 } 186 // take none-heap when only one 187 it = manager.iterator(); 188 LinkedList<MemoryPoolMXBean> beans=new LinkedList<MemoryPoolMXBean>(); 189 while(it.hasNext()){ 190 bean = it.next(); 191 if(bean.getType().equals(MemoryType.NON_HEAP)) { 192 beans.add(bean); 193 return bean; 194 } 195 } 196 if(beans.size()==1) return beans.getFirst(); 197 198 // Class Memory/ClassBlock Memory? 199 it = manager.iterator(); 200 while(it.hasNext()){ 201 bean = it.next(); 202 if(StringUtil.indexOfIgnoreCase(bean.getName(),"Class Memory")!=-1) { 203 return bean; 204 } 205 } 206 207 208 return null; 209 } 210 211 private static Boolean isFSCaseSensitive; 212 private static JavaSysMon jsm; 213 private static Boolean isCLI; 214 private static double loaderVersion=0D; 215 private static String macAddress; 216 217 /** 218 * returns if the file system case sensitive or not 219 * @return is the file system case sensitive or not 220 */ 221 public static boolean isFSCaseSensitive() { 222 if(isFSCaseSensitive==null) { 223 try { 224 _isFSCaseSensitive(File.createTempFile("abcx","txt")); 225 } 226 catch (IOException e) { 227 File f = new File("abcx.txt").getAbsoluteFile(); 228 try { 229 f.createNewFile(); 230 _isFSCaseSensitive(f); 231 232 } catch (IOException e1) { 233 throw new RuntimeException(e1.getMessage()); 234 } 235 } 236 } 237 return isFSCaseSensitive.booleanValue(); 238 } 239 private static void _isFSCaseSensitive(File f) { 240 File temp=new File(f.getPath().toUpperCase()); 241 isFSCaseSensitive=temp.exists()?Boolean.FALSE:Boolean.TRUE; 242 f.delete(); 243 } 244 245 246 /** 247 * fixes a java canonical path to a Windows path 248 * e.g. /C:/Windows/System32 will be changed to C:\Windows\System32 249 * 250 * @param path 251 * @return 252 */ 253 public static String fixWindowsPath(String path) { 254 if ( isWindows && path.length() > 3 && path.charAt(0) == '/' && path.charAt(2) == ':' ) { 255 path = path.substring(1).replace( '/', '\\' ); 256 } 257 return path; 258 } 259 260 261 /** 262 * @return is local machine a Windows Machine 263 */ 264 public static boolean isWindows() { 265 return isWindows; 266 } 267 268 /** 269 * @return is local machine a Unix Machine 270 */ 271 public static boolean isUnix() { 272 return isUnix; 273 } 274 275 /** 276 * @return return System directory 277 */ 278 public static Resource getSystemDirectory() { 279 String pathes=System.getProperty("java.library.path"); 280 ResourceProvider fr = ResourcesImpl.getFileResourceProvider(); 281 if(pathes!=null) { 282 String[] arr=ListUtil.toStringArrayEL(ListUtil.listToArray(pathes,File.pathSeparatorChar)); 283 for(int i=0;i<arr.length;i++) { 284 if(arr[i].toLowerCase().indexOf("windows\\system")!=-1) { 285 Resource file = fr.getResource(arr[i]); 286 if(file.exists() && file.isDirectory() && file.isWriteable()) return ResourceUtil.getCanonicalResourceEL(file); 287 288 } 289 } 290 for(int i=0;i<arr.length;i++) { 291 if(arr[i].toLowerCase().indexOf("windows")!=-1) { 292 Resource file = fr.getResource(arr[i]); 293 if(file.exists() && file.isDirectory() && file.isWriteable()) return ResourceUtil.getCanonicalResourceEL(file); 294 295 } 296 } 297 for(int i=0;i<arr.length;i++) { 298 if(arr[i].toLowerCase().indexOf("winnt")!=-1) { 299 Resource file = fr.getResource(arr[i]); 300 if(file.exists() && file.isDirectory() && file.isWriteable()) return ResourceUtil.getCanonicalResourceEL(file); 301 302 } 303 } 304 for(int i=0;i<arr.length;i++) { 305 if(arr[i].toLowerCase().indexOf("win")!=-1) { 306 Resource file = fr.getResource(arr[i]); 307 if(file.exists() && file.isDirectory() && file.isWriteable()) return ResourceUtil.getCanonicalResourceEL(file); 308 309 } 310 } 311 for(int i=0;i<arr.length;i++) { 312 Resource file = fr.getResource(arr[i]); 313 if(file.exists() && file.isDirectory() && file.isWriteable()) return ResourceUtil.getCanonicalResourceEL(file); 314 } 315 } 316 return null; 317 } 318 319 /** 320 * @return return running context root 321 */ 322 public static Resource getRuningContextRoot() { 323 ResourceProvider frp = ResourcesImpl.getFileResourceProvider(); 324 325 try { 326 return frp.getResource(".").getCanonicalResource(); 327 } catch (IOException e) {} 328 URL url=new Info().getClass().getClassLoader().getResource("."); 329 try { 330 return frp.getResource(FileUtil.URLToFile(url).getAbsolutePath()); 331 } catch (MalformedURLException e) { 332 return null; 333 } 334 } 335 336 /** 337 * returns the Temp Directory of the System 338 * @return temp directory 339 */ 340 public static Resource getTempDirectory() { 341 if(tempFile!=null) return tempFile; 342 ResourceProvider fr = ResourcesImpl.getFileResourceProvider(); 343 String tmpStr = System.getProperty("java.io.tmpdir"); 344 if(tmpStr!=null) { 345 tempFile=fr.getResource(tmpStr); 346 if(tempFile.exists()) { 347 tempFile=ResourceUtil.getCanonicalResourceEL(tempFile); 348 return tempFile; 349 } 350 } 351 File tmp =null; 352 try { 353 tmp = File.createTempFile("a","a"); 354 tempFile=fr.getResource(tmp.getParent()); 355 tempFile=ResourceUtil.getCanonicalResourceEL(tempFile); 356 } 357 catch(IOException ioe) {} 358 finally { 359 if(tmp!=null)tmp.delete(); 360 } 361 return tempFile; 362 } 363 364 365 /** 366 * returns the a unique temp file (with no auto delete) 367 * @param extension 368 * @return temp directory 369 * @throws IOException 370 */ 371 public static Resource getTempFile(String extension, boolean touch) throws IOException { 372 String filename=CreateUniqueId.invoke(); 373 if(!StringUtil.isEmpty(extension,true)){ 374 if(extension.startsWith("."))filename+=extension; 375 else filename+="."+extension; 376 } 377 Resource file = getTempDirectory().getRealResource(filename); 378 if(touch)ResourceUtil.touch(file); 379 return file; 380 } 381 382 /** 383 * returns the Hoome Directory of the System 384 * @return home directory 385 */ 386 public static Resource getHomeDirectory() { 387 if(homeFile!=null) return homeFile; 388 389 ResourceProvider frp = ResourcesImpl.getFileResourceProvider(); 390 391 String homeStr = System.getProperty("user.home"); 392 if(homeStr!=null) { 393 homeFile=frp.getResource(homeStr); 394 homeFile=ResourceUtil.getCanonicalResourceEL(homeFile); 395 } 396 return homeFile; 397 } 398 399 public static Resource getClassLoadeDirectory(){ 400 return ResourceUtil.toResource(CFMLEngineFactory.getClassLoaderRoot(TP.class.getClassLoader())); 401 } 402 403 /** 404 * get class pathes from all url ClassLoaders 405 * @param ucl URL Class Loader 406 * @param pathes Hashmap with allpathes 407 */ 408 private static void getClassPathesFromClassLoader(URLClassLoader ucl, ArrayList pathes) { 409 ClassLoader pcl=ucl.getParent(); 410 // parent first 411 if(pcl instanceof URLClassLoader) 412 getClassPathesFromClassLoader((URLClassLoader) pcl, pathes); 413 414 ResourceProvider frp = ResourcesImpl.getFileResourceProvider(); 415 // get all pathes 416 URL[] urls=ucl.getURLs(); 417 for(int i=0;i<urls.length;i++) { 418 Resource file=frp.getResource(urls[i].getPath()); 419 if(file.exists()) 420 pathes.add(ResourceUtil.getCanonicalResourceEL(file)); 421 } 422 423 } 424 425 /** 426 * @return returns a string list of all pathes 427 */ 428 public static Resource[] getClassPathes() { 429 430 if(classPathes!=null) 431 return classPathes; 432 433 ArrayList pathes=new ArrayList(); 434 String pathSeperator=System.getProperty("path.separator"); 435 if(pathSeperator==null)pathSeperator=";"; 436 437 // java.ext.dirs 438 ResourceProvider frp = ResourcesImpl.getFileResourceProvider(); 439 440 441 // pathes from system properties 442 String strPathes=System.getProperty("java.class.path"); 443 if(strPathes!=null) { 444 Array arr=ListUtil.listToArrayRemoveEmpty(strPathes,pathSeperator); 445 int len=arr.size(); 446 for(int i=1;i<=len;i++) { 447 Resource file=frp.getResource(Caster.toString(arr.get(i,""),"").trim()); 448 if(file.exists()) 449 pathes.add(ResourceUtil.getCanonicalResourceEL(file)); 450 } 451 } 452 453 454 // pathes from url class Loader (dynamic loaded classes) 455 ClassLoader cl = new Info().getClass().getClassLoader(); 456 if(cl instanceof URLClassLoader) 457 getClassPathesFromClassLoader((URLClassLoader) cl, pathes); 458 459 return classPathes=(Resource[]) pathes.toArray(new Resource[pathes.size()]); 460 461 } 462 463 public static long getUsedMemory() { 464 Runtime r = Runtime.getRuntime(); 465 return r.totalMemory()-r.freeMemory(); 466 } 467 public static long getAvailableMemory() { 468 Runtime r = Runtime.getRuntime(); 469 return r.freeMemory(); 470 } 471 472 /** 473 * replace path placeholder with the real path, placeholders are [{temp-directory},{system-directory},{home-directory}] 474 * @param path 475 * @return updated path 476 */ 477 public static String parsePlaceHolder(String path) { 478 if(path==null) return path; 479 // Temp 480 if(path.startsWith("{temp")) { 481 if(path.startsWith("}",5)) path=getTempDirectory().getRealResource(path.substring(6)).toString(); 482 else if(path.startsWith("-dir}",5)) path=getTempDirectory().getRealResource(path.substring(10)).toString(); 483 else if(path.startsWith("-directory}",5)) path=getTempDirectory().getRealResource(path.substring(16)).toString(); 484 } 485 // System 486 else if(path.startsWith("{system")) { 487 if(path.startsWith("}",7)) path=getSystemDirectory().getRealResource(path.substring(8)).toString(); 488 else if(path.startsWith("-dir}",7)) path=getSystemDirectory().getRealResource(path.substring(12)).toString(); 489 else if(path.startsWith("-directory}",7)) path=getSystemDirectory().getRealResource(path.substring(18)).toString(); 490 } 491 // Home 492 else if(path.startsWith("{home")) { 493 if(path.startsWith("}",5)) path=getHomeDirectory().getRealResource(path.substring(6)).toString(); 494 else if(path.startsWith("-dir}",5)) path=getHomeDirectory().getRealResource(path.substring(10)).toString(); 495 else if(path.startsWith("-directory}",5)) path=getHomeDirectory().getRealResource(path.substring(16)).toString(); 496 } 497 // ClassLoaderDir 498 else if(path.startsWith("{classloader")) { 499 if(path.startsWith("}",12)) path=getClassLoadeDirectory().getRealResource(path.substring(13)).toString(); 500 else if(path.startsWith("-dir}",12)) path=getClassLoadeDirectory().getRealResource(path.substring(17)).toString(); 501 else if(path.startsWith("-directory}",12)) path=getClassLoadeDirectory().getRealResource(path.substring(23)).toString(); 502 } 503 return path; 504 } 505 506 public static String addPlaceHolder(Resource file, String defaultValue) { 507 // Temp 508 String path=addPlaceHolder(getTempDirectory(),file,"{temp-directory}"); 509 if(!StringUtil.isEmpty(path)) return path; 510 // System 511 path=addPlaceHolder(getSystemDirectory(),file,"{system-directory}"); 512 if(!StringUtil.isEmpty(path)) return path; 513 // Home 514 path=addPlaceHolder(getHomeDirectory(),file,"{home-directory}"); 515 if(!StringUtil.isEmpty(path)) return path; 516 517 518 return defaultValue; 519 } 520 521 private static String addPlaceHolder(Resource dir, Resource file,String placeholder) { 522 if(ResourceUtil.isChildOf(file, dir)){ 523 try { 524 return StringUtil.replace(file.getCanonicalPath(), dir.getCanonicalPath(), placeholder, true); 525 } 526 catch (IOException e) {} 527 } 528 return null; 529 } 530 531 532 public static String addPlaceHolder(Resource file, Config config, String defaultValue) { 533 //ResourceProvider frp = ResourcesImpl.getFileResourceProvider(); 534 535 // temp 536 Resource dir = config.getTempDirectory(); 537 String path = addPlaceHolder(dir,file,"{temp-directory}"); 538 if(!StringUtil.isEmpty(path)) return path; 539 540 // Config 541 dir = config.getConfigDir(); 542 path = addPlaceHolder(dir,file,"{lucee-config-directory}"); 543 if(!StringUtil.isEmpty(path)) return path; 544 545 /* / Config WEB 546 dir = config.getConfigDir(); 547 path = addPlaceHolder(dir,file,"{lucee-server-directory}"); 548 if(!StringUtil.isEmpty(path)) return path; 549*/ 550 // Web root 551 dir = config.getRootDirectory(); 552 path = addPlaceHolder(dir,file,"{web-root-directory}"); 553 if(!StringUtil.isEmpty(path)) return path; 554 555 return addPlaceHolder(file, defaultValue); 556 } 557 558 public static String parsePlaceHolder(String path, ServletContext sc, Map<String,String> labels) { 559 if(path==null) return null; 560 if(path.indexOf('{')!=-1){ 561 if((path.indexOf("{web-context-label}"))!=-1){ 562 String id=hash(sc); 563 564 String label=labels.get(id); 565 if(StringUtil.isEmpty(label)) label=id; 566 567 path=StringUtil.replace(path, "{web-context-label}", label, false); 568 } 569 } 570 return parsePlaceHolder(path, sc); 571 } 572 573 public static String parsePlaceHolder(String path, ServletContext sc) { 574 ResourceProvider frp = ResourcesImpl.getFileResourceProvider(); 575 576 577 if(path==null) return null; 578 if(path.indexOf('{')!=-1){ 579 if(StringUtil.startsWith(path,'{')){ 580 581 // Web Root 582 if(path.startsWith("{web-root")) { 583 if(path.startsWith("}",9)) path=frp.getResource(ReqRspUtil.getRootPath(sc)).getRealResource(path.substring(10)).toString(); 584 else if(path.startsWith("-dir}",9)) path=frp.getResource(ReqRspUtil.getRootPath(sc)).getRealResource(path.substring(14)).toString(); 585 else if(path.startsWith("-directory}",9)) path=frp.getResource(ReqRspUtil.getRootPath(sc)).getRealResource(path.substring(20)).toString(); 586 587 } 588 else path=SystemUtil.parsePlaceHolder(path); 589 } 590 591 if((path.indexOf("{web-context-hash}"))!=-1){ 592 String id=hash(sc); 593 path=StringUtil.replace(path, "{web-context-hash}", id, false); 594 } 595 } 596 return path; 597 } 598 599 public static String hash(ServletContext sc) { 600 String id=null; 601 try { 602 id=MD5.getDigestAsString(ReqRspUtil.getRootPath(sc)); 603 } 604 catch (IOException e) {} 605 return id; 606 } 607 608 public static Charset getCharset() { 609 return charset; 610 } 611 612 public static void setCharset(String charset) { 613 SystemUtil.charset = CharsetUtil.toCharset(charset); 614 } 615 public static void setCharset(Charset charset) { 616 SystemUtil.charset = charset; 617 } 618 619 public static String getOSSpecificLineSeparator() { 620 return lineSeparator; 621 } 622 623 public static void sleep(int time) { 624 try { 625 Thread.sleep(time); 626 } catch (InterruptedException e) {} 627 } 628 629 public static void sleep(long time) { 630 try { 631 Thread.sleep(time); 632 } catch (InterruptedException e) {} 633 } 634 public static void join(Thread t) { 635 try { 636 t.join(); 637 } catch (InterruptedException e) {} 638 } 639 640 /** 641 * locks the object (synchronized) before calling wait 642 * @param lock 643 * @param timeout 644 * @throws InterruptedException 645 */ 646 public static void wait(Object lock, long timeout) { 647 try { 648 synchronized (lock) {lock.wait(timeout);} 649 } catch (InterruptedException e) {} 650 } 651 652 /** 653 * locks the object (synchronized) before calling wait (no timeout) 654 * @param lock 655 * @throws InterruptedException 656 */ 657 public static void wait(Object lock) { 658 try { 659 synchronized (lock) {lock.wait();} 660 } catch (InterruptedException e) {} 661 } 662 663 664 665 /** 666 * locks the object (synchronized) before calling notify 667 * @param lock 668 * @param timeout 669 * @throws InterruptedException 670 */ 671 public static void notify(Object lock) { 672 synchronized (lock) {lock.notify();} 673 } 674 675 /** 676 * locks the object (synchronized) before calling notifyAll 677 * @param lock 678 * @param timeout 679 * @throws InterruptedException 680 */ 681 public static void notifyAll(Object lock) { 682 synchronized (lock) {lock.notifyAll();} 683 } 684 685 /** 686 * return the operating system architecture 687 * @return one of the following SystemUtil.ARCH_UNKNOW, SystemUtil.ARCH_32, SystemUtil.ARCH_64 688 */ 689 public static int getOSArch(){ 690 if(osArch==-1) { 691 osArch = toIntArch(System.getProperty("os.arch.data.model")); 692 if(osArch==ARCH_UNKNOW)osArch = toIntArch(System.getProperty("os.arch")); 693 } 694 return osArch; 695 } 696 697 /** 698 * return the JRE (Java Runtime Engine) architecture, this can be different from the operating system architecture 699 * @return one of the following SystemUtil.ARCH_UNKNOW, SystemUtil.ARCH_32, SystemUtil.ARCH_64 700 */ 701 public static int getJREArch(){ 702 if(jreArch==-1) { 703 jreArch = toIntArch(System.getProperty("sun.arch.data.model")); 704 if(jreArch==ARCH_UNKNOW)jreArch = toIntArch(System.getProperty("com.ibm.vm.bitmode")); 705 if(jreArch==ARCH_UNKNOW)jreArch = toIntArch(System.getProperty("java.vm.name")); 706 if(jreArch==ARCH_UNKNOW) { 707 int addrSize = getAddressSize(); 708 if(addrSize==4) return ARCH_32; 709 if(addrSize==8) return ARCH_64; 710 } 711 712 } 713 return jreArch; 714 } 715 716 private static int toIntArch(String strArch){ 717 if(!StringUtil.isEmpty(strArch)) { 718 if(strArch.indexOf("64")!=-1) return ARCH_64; 719 if(strArch.indexOf("32")!=-1) return ARCH_32; 720 if(strArch.indexOf("i386")!=-1) return ARCH_32; 721 if(strArch.indexOf("x86")!=-1) return ARCH_32; 722 } 723 return ARCH_UNKNOW; 724 } 725 726 727 728 public static int getAddressSize() { 729 try { 730 Class unsafe = ClassUtil.loadClass(null,"sun.misc.Unsafe",null); 731 if(unsafe==null) return 0; 732 733 Field unsafeField = unsafe.getDeclaredField("theUnsafe"); 734 unsafeField.setAccessible(true); 735 Object obj = unsafeField.get(null); 736 Method addressSize = unsafe.getMethod("addressSize", new Class[0]); 737 738 Object res = addressSize.invoke(obj, new Object[0]); 739 return Caster.toIntValue(res,0); 740 } 741 catch(Throwable t){ 742 ExceptionUtil.rethrowIfNecessary(t); 743 return 0; 744 } 745 746 } 747 /*private static MemoryUsage getPermGenSpaceSize() { 748 MemoryUsage mu = getPermGenSpaceSize(null); 749 if(mu!=null) return mu; 750 751 // create error message including info about available memory blocks 752 StringBuilder sb=new StringBuilder(); 753 java.util.List<MemoryPoolMXBean> manager = ManagementFactory.getMemoryPoolMXBeans(); 754 Iterator<MemoryPoolMXBean> it = manager.iterator(); 755 MemoryPoolMXBean bean; 756 while(it.hasNext()){ 757 bean = it.next(); 758 if(sb.length()>0)sb.append(", "); 759 sb.append(bean.getName()); 760 } 761 throw new RuntimeException("PermGen Space information not available, available Memory blocks are ["+sb+"]"); 762 }*/ 763 764 private static MemoryUsage getPermGenSpaceSize(MemoryUsage defaultValue) { 765 if(permGenSpaceBean!=null) return permGenSpaceBean.getUsage(); 766 // create on the fly when the bean is not permanent 767 MemoryPoolMXBean tmp = getPermGenSpaceBean(); 768 if(tmp!=null) return tmp.getUsage(); 769 770 return defaultValue; 771 } 772 773 774 public static long getFreePermGenSpaceSize() { 775 MemoryUsage mu = getPermGenSpaceSize(null); 776 if(mu==null) return -1; 777 778 long max = mu.getMax(); 779 long used = mu.getUsed(); 780 if(max<0 || used<0) return -1; 781 return max-used; 782 } 783 784 public static int getPermGenFreeSpaceAsAPercentageOfAvailable() { 785 MemoryUsage mu = getPermGenSpaceSize(null); 786 if(mu == null) return -1; 787 788 long max = mu.getMax(); 789 long used = mu.getUsed(); 790 if( max < 0 || used < 0) return -1; 791 792 //return a value that equates to a percentage of available free memory 793 return 100 - ((int)(100 * (((double)used) / ((double)max)))); 794 } 795 796 public static int getFreePermGenSpacePromille() { 797 MemoryUsage mu = getPermGenSpaceSize(null); 798 if(mu==null) return -1; 799 800 long max = mu.getMax(); 801 long used = mu.getUsed(); 802 if(max<0 || used<0) return -1; 803 return (int)(1000L-(1000L*used/max)); 804 } 805 806 public static Query getMemoryUsageAsQuery(int type) throws DatabaseException { 807 808 809 java.util.List<MemoryPoolMXBean> manager = ManagementFactory.getMemoryPoolMXBeans(); 810 Iterator<MemoryPoolMXBean> it = manager.iterator(); 811 Query qry=new QueryImpl(new Collection.Key[]{ 812 KeyConstants._name, 813 KeyConstants._type, 814 KeyConstants._used, 815 KeyConstants._max, 816 KeyConstants._init 817 },0,"memory"); 818 819 int row=0; 820 MemoryPoolMXBean bean; 821 MemoryUsage usage; 822 MemoryType _type; 823 while(it.hasNext()){ 824 bean = it.next(); 825 usage = bean.getUsage(); 826 _type = bean.getType(); 827 if(type==MEMORY_TYPE_HEAP && _type!=MemoryType.HEAP)continue; 828 if(type==MEMORY_TYPE_NON_HEAP && _type!=MemoryType.NON_HEAP)continue; 829 830 row++; 831 qry.addRow(); 832 qry.setAtEL(KeyConstants._name, row, bean.getName()); 833 qry.setAtEL(KeyConstants._type, row, _type.name()); 834 qry.setAtEL(KeyConstants._max, row, Caster.toDouble(usage.getMax())); 835 qry.setAtEL(KeyConstants._used, row, Caster.toDouble(usage.getUsed())); 836 qry.setAtEL(KeyConstants._init, row, Caster.toDouble(usage.getInit())); 837 838 } 839 return qry; 840 } 841 842 public static Struct getMemoryUsageAsStruct(int type) { 843 java.util.List<MemoryPoolMXBean> manager = ManagementFactory.getMemoryPoolMXBeans(); 844 Iterator<MemoryPoolMXBean> it = manager.iterator(); 845 846 MemoryPoolMXBean bean; 847 MemoryUsage usage; 848 MemoryType _type; 849 long used=0,max=0,init=0; 850 while(it.hasNext()){ 851 bean = it.next(); 852 usage = bean.getUsage(); 853 _type = bean.getType(); 854 if((type==MEMORY_TYPE_HEAP && _type==MemoryType.HEAP) || (type==MEMORY_TYPE_NON_HEAP && _type==MemoryType.NON_HEAP)){ 855 used+=usage.getUsed(); 856 max+=usage.getMax(); 857 init+=usage.getInit(); 858 } 859 } 860 Struct sct=new StructImpl(); 861 sct.setEL(KeyConstants._used, Caster.toDouble(used)); 862 sct.setEL(KeyConstants._max, Caster.toDouble(max)); 863 sct.setEL(KeyConstants._init, Caster.toDouble(init)); 864 sct.setEL(KeyImpl.init("available"), Caster.toDouble(max-used)); 865 return sct; 866 } 867 868 869 public static Struct getMemoryUsageCompact(int type) { 870 java.util.List<MemoryPoolMXBean> manager = ManagementFactory.getMemoryPoolMXBeans(); 871 Iterator<MemoryPoolMXBean> it = manager.iterator(); 872 873 MemoryPoolMXBean bean; 874 MemoryUsage usage; 875 MemoryType _type; 876 Struct sct=new StructImpl(); 877 while(it.hasNext()){ 878 bean = it.next(); 879 usage = bean.getUsage(); 880 _type = bean.getType(); 881 if(type==MEMORY_TYPE_HEAP && _type!=MemoryType.HEAP)continue; 882 if(type==MEMORY_TYPE_NON_HEAP && _type!=MemoryType.NON_HEAP)continue; 883 884 double d=((int)(100D/usage.getMax()*usage.getUsed()))/100D; 885 sct.setEL(KeyImpl.init(bean.getName()), Caster.toDouble(d)); 886 } 887 return sct; 888 } 889 890 public static String getPropertyEL(String key) { 891 try{ 892 String str = System.getProperty(key); 893 if(!StringUtil.isEmpty(str,true)) return str; 894 895 Iterator<Entry<Object, Object>> it = System.getProperties().entrySet().iterator(); 896 Entry<Object, Object> e; 897 String n; 898 while(it.hasNext()){ 899 e = it.next(); 900 n=(String) e.getKey(); 901 if(key.equalsIgnoreCase(n)) return (String) e.getValue(); 902 } 903 904 } 905 catch(Throwable t){ 906 ExceptionUtil.rethrowIfNecessary(t); 907 } 908 return null; 909 } 910 public static long microTime() { 911 return System.nanoTime()/1000L; 912 } 913 914 public static TemplateLine getCurrentContext() { 915 StackTraceElement[] traces = Thread.currentThread().getStackTrace(); 916 917 int line=0; 918 String template; 919 920 StackTraceElement trace=null; 921 for(int i=0;i<traces.length;i++) { 922 trace=traces[i]; 923 template=trace.getFileName(); 924 if(trace.getLineNumber()<=0 || template==null || ResourceUtil.getExtension(template,"").equals("java")) continue; 925 line=trace.getLineNumber(); 926 return new TemplateLine(template,line); 927 } 928 return null; 929 } 930 931 public static class TemplateLine implements Serializable { 932 933 private static final long serialVersionUID = 6610978291828389799L; 934 935 public final String template; 936 public final int line; 937 938 public TemplateLine(String template, int line) { 939 this.template=template; 940 this.line=line; 941 } 942 public String toString(){ 943 return template+":"+line; 944 } 945 } 946 947 public static long getFreeBytes() throws ApplicationException { 948 return physical().getFreeBytes(); 949 } 950 951 public static long getTotalBytes() throws ApplicationException { 952 return physical().getTotalBytes(); 953 } 954 955 public static double getCpuUsage(long time) throws ApplicationException { 956 if(time<1) throw new ApplicationException("time has to be bigger than 0"); 957 if(jsm==null) jsm=new JavaSysMon(); 958 CpuTimes cput = jsm.cpuTimes(); 959 if(cput==null) throw new ApplicationException("CPU information are not available for this OS"); 960 CpuTimes previous = new CpuTimes(cput.getUserMillis(),cput.getSystemMillis(),cput.getIdleMillis()); 961 sleep(time); 962 963 return jsm.cpuTimes().getCpuUsage(previous)*100D; 964 } 965 966 967 private synchronized static MemoryStats physical() throws ApplicationException { 968 if(jsm==null) jsm=new JavaSysMon(); 969 MemoryStats p = jsm.physical(); 970 if(p==null) throw new ApplicationException("Memory information are not available for this OS"); 971 return p; 972 } 973 public static void setPrintWriter(int type,PrintWriter pw) { 974 printWriter[type]=pw; 975 } 976 public static PrintWriter getPrintWriter(int type) { 977 if(printWriter[type]==null) { 978 if(type==OUT) printWriter[OUT]=PRINTWRITER_OUT; 979 else printWriter[ERR]=PRINTWRITER_ERR; 980 } 981 return printWriter[type]; 982 } 983 public static boolean isCLICall() { 984 if(isCLI==null){ 985 isCLI=Caster.toBoolean(System.getProperty("lucee.cli.call"),Boolean.FALSE); 986 } 987 return isCLI.booleanValue(); 988 } 989 990 public static double getLoaderVersion() { 991 // this is done via reflection to make it work in older version, where the class lucee.loader.Version does not exist 992 if(loaderVersion==0D) { 993 loaderVersion=4D; 994 Class cVersion = ClassUtil.loadClass(TP.class.getClassLoader(),"lucee.loader.Version",null); 995 if(cVersion!=null) { 996 try { 997 Field f = cVersion.getField("VERSION"); 998 loaderVersion=f.getDouble(null); 999 } 1000 catch (Throwable t) { 1001 ExceptionUtil.rethrowIfNecessary(t); 1002 t.printStackTrace(); 1003 } 1004 } 1005 } 1006 return loaderVersion; 1007 } 1008 public static String getMacAddress() { 1009 if(macAddress==null) { 1010 try{ 1011 InetAddress ip = InetAddress.getLocalHost(); 1012 NetworkInterface network = NetworkInterface.getByInetAddress(ip); 1013 byte[] mac = network.getHardwareAddress(); 1014 1015 StringBuilder sb = new StringBuilder(); 1016 for (int i = 0; i < mac.length; i++) { 1017 sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : "")); 1018 } 1019 macAddress= sb.toString(); 1020 } 1021 catch(Throwable t){ 1022 ExceptionUtil.rethrowIfNecessary(t); 1023 } 1024 1025 } 1026 return macAddress; 1027 } 1028 1029 @Deprecated 1030 public static void stop(Thread thread,Log log) { 1031 new StopThread(thread,new StopException(thread),null).start(); 1032 } 1033 1034 public static void stop(PageContext pc,Log log) { 1035 stop(pc,new StopException(pc.getThread()),log); 1036 } 1037 1038 public static void stop(PageContext pc, Throwable t,Log log) { 1039 new StopThread(pc,t,log).start(); 1040 } 1041} 1042 1043class StopThread extends Thread { 1044 1045 private final PageContext pc; 1046 private final Throwable t; 1047 private final Log log; 1048 private final Thread thread; 1049 1050 public StopThread(PageContext pc, Throwable t, Log log) { 1051 this.pc=pc; 1052 this.t=t; 1053 this.log=log; 1054 this.thread=pc.getThread(); 1055 } 1056 1057 public StopThread(Thread thread, Throwable t, Log log) { 1058 this.pc=null; 1059 this.t=t; 1060 this.log=log; 1061 this.thread=thread; 1062 } 1063 1064 public void run(){ 1065 if(pc!=null){ 1066 PageContextImpl pci=(PageContextImpl) pc; 1067 pci.stop(t); 1068 } 1069 int count=0; 1070 if(thread!=null && thread.isAlive()) { 1071 ////do{ 1072 try{ 1073 if(count>0 && log!=null) { 1074 LogUtil.log(log, Log.LEVEL_ERROR, "", "could not stop the thread on the "+count+" approach", thread.getStackTrace()); 1075 } 1076 if(count++>4) { 1077 if(log!=null)LogUtil.log(log, Log.LEVEL_ERROR, "", "could not terminate the thread", thread.getStackTrace()); 1078 aprint.e(thread.getStackTrace()); 1079 ////break; // should never happen 1080 } 1081 try{ 1082 thread.stop(t); 1083 } 1084 catch(UnsupportedOperationException uoe) { 1085 LogUtil.log(log, Log.LEVEL_INFO, "", "Thread.stop(Throwable) is not supported by this JVM and failed with UnsupportedOperationException", thread.getStackTrace()); 1086 try { 1087 Method m = thread.getClass().getMethod("stop0", new Class[]{Object.class}); 1088 m.setAccessible(true); // allow to access private method 1089 m.invoke(thread, new Object[]{t}); 1090 } 1091 catch (Exception e) { 1092 if( 1093 e instanceof IllegalAccessException || 1094 e instanceof IllegalArgumentException || 1095 e instanceof InvocationTargetException || 1096 e instanceof NoSuchMethodException || 1097 e instanceof SecurityException) { 1098 thread.stop(); 1099 } 1100 else throw e; 1101 } 1102 } 1103 } 1104 // catch any exception 1105 catch(Exception e){ 1106 LogUtil.log(log, Log.LEVEL_ERROR, "", e); 1107 } 1108 1109 /*if(!(thread.isAlive() && (pc==null || ((PageContextImpl)pc).isInitialized()))) break; 1110 print.e("sleep-10:"+thread.isAlive()); 1111 SystemUtil.sleep(10); 1112 1113 if(!(thread.isAlive() && (pc==null || ((PageContextImpl)pc).isInitialized()))) break; 1114 print.e("sleep-100"); 1115 SystemUtil.sleep(100);*/ 1116 ////}while(thread.isAlive() && (pc==null || ((PageContextImpl)pc).isInitialized())); 1117 } 1118 1119 } 1120 1121}