1 package org.tanukisoftware.wrapper; 2 3 45 46 import java.io.DataInputStream ; 47 import java.io.File ; 48 import java.io.InputStream ; 49 import java.io.InterruptedIOException ; 50 import java.io.IOException ; 51 import java.io.OutputStream ; 52 import java.io.PrintStream ; 53 import java.lang.reflect.Constructor ; 54 import java.lang.reflect.InvocationTargetException ; 55 import java.lang.reflect.Method ; 56 import java.net.BindException ; 57 import java.net.ConnectException ; 58 import java.net.InetAddress ; 59 import java.net.ServerSocket ; 60 import java.net.Socket ; 61 import java.net.SocketException ; 62 import java.net.UnknownHostException ; 63 import java.security.AccessControlException ; 64 import java.security.AccessController ; 65 import java.security.PrivilegedAction ; 66 import java.util.ArrayList ; 67 import java.util.Iterator ; 68 import java.util.List ; 69 import java.util.Properties ; 70 import java.util.StringTokenizer ; 71 72 import org.tanukisoftware.wrapper.event.WrapperControlEvent; 73 import org.tanukisoftware.wrapper.event.WrapperEvent; 74 import org.tanukisoftware.wrapper.event.WrapperEventListener; 75 import org.tanukisoftware.wrapper.event.WrapperPingEvent; 76 import org.tanukisoftware.wrapper.event.WrapperServiceControlEvent; 77 import org.tanukisoftware.wrapper.event.WrapperTickEvent; 78 import org.tanukisoftware.wrapper.resources.ResourceManager; 79 import org.tanukisoftware.wrapper.security.WrapperEventPermission; 80 import org.tanukisoftware.wrapper.security.WrapperPermission; 81 import org.tanukisoftware.wrapper.security.WrapperServicePermission; 82 83 103 public final class WrapperManager 104 implements Runnable 105 { 106 private static final String WRAPPER_CONNECTION_THREAD_NAME = "Wrapper-Connection"; 107 108 private static final int DEFAULT_PORT = 15003; 109 private static final int DEFAULT_SO_TIMEOUT = 10000; 110 private static final int DEFAULT_CPU_TIMEOUT = 10000; 111 112 114 private static final int TICK_MS = 100; 115 private static final int TIMER_FAST_THRESHOLD = 2 * 24 * 3600 * 1000 / TICK_MS; private static final int TIMER_SLOW_THRESHOLD = 2 * 24 * 3600 * 1000 / TICK_MS; 118 private static final byte WRAPPER_MSG_START = (byte)100; 119 private static final byte WRAPPER_MSG_STOP = (byte)101; 120 private static final byte WRAPPER_MSG_RESTART = (byte)102; 121 private static final byte WRAPPER_MSG_PING = (byte)103; 122 private static final byte WRAPPER_MSG_STOP_PENDING = (byte)104; 123 private static final byte WRAPPER_MSG_START_PENDING = (byte)105; 124 private static final byte WRAPPER_MSG_STARTED = (byte)106; 125 private static final byte WRAPPER_MSG_STOPPED = (byte)107; 126 private static final byte WRAPPER_MSG_KEY = (byte)110; 127 private static final byte WRAPPER_MSG_BADKEY = (byte)111; 128 private static final byte WRAPPER_MSG_LOW_LOG_LEVEL = (byte)112; 129 private static final byte WRAPPER_MSG_PING_TIMEOUT = (byte)113; 130 private static final byte WRAPPER_MSG_SERVICE_CONTROL_CODE = (byte)114; 131 private static final byte WRAPPER_MSG_PROPERTIES = (byte)115; 132 133 134 private static final byte WRAPPER_MSG_LOG = (byte)116; 135 136 137 public static final int WRAPPER_CTRL_C_EVENT = 200; 138 139 140 public static final int WRAPPER_CTRL_CLOSE_EVENT = 201; 141 142 143 public static final int WRAPPER_CTRL_LOGOFF_EVENT = 202; 144 145 146 public static final int WRAPPER_CTRL_SHUTDOWN_EVENT = 203; 147 148 149 public static final int WRAPPER_CTRL_TERM_EVENT = 204; 150 151 152 public static final int WRAPPER_CTRL_HUP_EVENT = 205; 153 154 155 public static final int WRAPPER_LOG_LEVEL_DEBUG = 1; 156 157 public static final int WRAPPER_LOG_LEVEL_INFO = 2; 158 159 public static final int WRAPPER_LOG_LEVEL_STATUS = 3; 160 161 public static final int WRAPPER_LOG_LEVEL_WARN = 4; 162 163 public static final int WRAPPER_LOG_LEVEL_ERROR = 5; 164 165 public static final int WRAPPER_LOG_LEVEL_FATAL = 6; 166 167 public static final int WRAPPER_LOG_LEVEL_ADVICE = 7; 168 169 170 public static final int SERVICE_CONTROL_CODE_START = 0x10000; 171 172 173 public static final int SERVICE_CONTROL_CODE_STOP = 1; 174 175 176 public static final int SERVICE_CONTROL_CODE_PAUSE = 2; 177 178 179 public static final int SERVICE_CONTROL_CODE_CONTINUE = 3; 180 181 182 public static final int SERVICE_CONTROL_CODE_INTERROGATE = 4; 183 184 185 public static final int SERVICE_CONTROL_CODE_SHUTDOWN = 5; 186 187 188 private static PrintStream m_out; 189 190 191 private static PrintStream m_err; 192 193 194 private static boolean m_securityManagerChecked = false; 195 196 private static boolean m_disposed = false; 197 private static boolean m_started = false; 198 private static WrapperManager m_instance = null; 199 private static Thread m_hook = null; 200 private static boolean m_hookTriggered = false; 201 202 203 private static boolean m_shutdownJVMComplete = false; 204 205 private static String [] m_args; 206 private static int m_port = DEFAULT_PORT; 207 private static int m_jvmPort; 208 private static int m_jvmPortMin; 209 private static int m_jvmPortMax; 210 private static String m_key; 211 private static int m_soTimeout = DEFAULT_SO_TIMEOUT; 212 private static long m_cpuTimeout = DEFAULT_CPU_TIMEOUT; 213 214 215 private static int m_startedTicks; 216 217 220 private static int m_lowLogLevel = WRAPPER_LOG_LEVEL_ADVICE + 1; 221 222 224 private static int m_pingTimeout = 30000; 225 226 228 private static boolean m_ignoreSignals = false; 229 230 231 private static Thread m_commRunner; 232 private static boolean m_commRunnerStarted = false; 233 private static Thread m_eventRunner; 234 private static int m_eventRunnerTicks; 235 private static Thread m_startupRunner; 236 237 238 private static boolean m_useSystemTime; 239 240 242 private static int m_timerFastThreshold; 243 244 246 private static int m_timerSlowThreshold; 247 248 253 private static int m_jvmBits; 254 255 259 private static volatile int m_ticks; 260 261 private static WrapperListener m_listener; 262 263 private static int m_lastPingTicks; 264 private static ServerSocket m_serverSocket; 265 private static Socket m_socket; 266 private static boolean m_shuttingDown = false; 267 private static boolean m_appearHung = false; 268 269 private static Method m_addShutdownHookMethod = null; 270 private static Method m_removeShutdownHookMethod = null; 271 272 private static boolean m_service = false; 273 private static boolean m_debug = false; 274 private static int m_jvmId = 0; 275 private static boolean m_stopping = false; 276 private static Thread m_stoppingThread; 277 private static int m_exitCode; 278 private static boolean m_libraryOK = false; 279 private static byte[] m_commandBuffer = new byte[512]; 280 281 282 private static WrapperProperties m_properties; 283 284 285 private static List m_wrapperEventListenerMaskList = new ArrayList (); 286 287 290 private static WrapperEventListenerMask[] m_wrapperEventListenerMasks = null; 291 292 293 private static boolean m_produceCoreEvents = false; 294 295 private static ResourceManager m_res = ResourceManager.getResourceManager(); 297 private static ResourceManager m_error = m_res; 298 private static ResourceManager m_warning = m_res; 299 private static ResourceManager m_info = m_res; 300 301 304 313 static 314 { 315 AccessController.doPrivileged( 326 new PrivilegedAction () { 327 public Object run() { 328 privilegedClassInit(); 329 return null; 330 } 331 } 332 ); 333 } 334 335 339 private static void privilegedClassInit() 340 { 341 m_out = System.out; 349 m_err = System.err; 350 351 m_properties = new WrapperProperties(); 354 m_properties.lock(); 355 356 checkSecurityManager(); 359 360 m_debug = WrapperSystemPropertyUtil.getBooleanProperty( "wrapper.debug", false ); 362 363 if ( m_debug ) 364 { 365 m_out.println( "WrapperManager class initialized by thread: " 366 + Thread.currentThread().getName() 367 + " Using classloader: " + WrapperManager.class.getClassLoader() ); 368 } 369 370 m_out.println( "Wrapper (Version " + getVersion() + ") http://wrapper.tanukisoftware.org" ); 379 m_out.println( " Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved." ); 380 m_out.println(); 381 382 m_jvmId = WrapperSystemPropertyUtil.getIntProperty( "wrapper.jvmid", 1 ); 384 if ( m_debug ) 385 { 386 m_out.println( "Wrapper Manager: JVM #" + m_jvmId ); 387 } 388 389 m_jvmBits = Integer.getInteger( "sun.arch.data.model", -1 ).intValue(); 391 if ( m_debug ) 392 { 393 if ( m_jvmBits > 0 ) 394 { 395 m_out.println( "Running a " + m_jvmBits + "-bit JVM." ); 396 } 397 else 398 { 399 m_out.println( "The bit depth of this JVM could not be determined." ); 400 } 401 } 402 403 m_ticks = Integer.MAX_VALUE - 200; 408 409 m_useSystemTime = WrapperSystemPropertyUtil.getBooleanProperty( 410 "wrapper.use_system_time", false ); 411 m_timerFastThreshold = WrapperSystemPropertyUtil.getIntProperty( 412 "wrapper.timer_fast_threshold", TIMER_FAST_THRESHOLD ) * 1000 / TICK_MS; 413 m_timerSlowThreshold = WrapperSystemPropertyUtil.getIntProperty( 414 "wrapper.timer_slow_threshold", TIMER_SLOW_THRESHOLD ) * 1000 / TICK_MS; 415 416 boolean disableShutdownHook = WrapperSystemPropertyUtil.getBooleanProperty( 418 "wrapper.disable_shutdown_hook", false ); 419 420 try 423 { 424 m_addShutdownHookMethod = 425 Runtime .class.getMethod( "addShutdownHook", new Class [] { Thread .class } ); 426 m_removeShutdownHookMethod = 427 Runtime .class.getMethod( "removeShutdownHook", new Class [] { Thread .class } ); 428 } 429 catch ( NoSuchMethodException e ) 430 { 431 if ( m_debug ) 432 { 433 m_out.println( 434 "Wrapper Manager: Shutdown hooks not supported by current JVM." ); 435 } 436 m_addShutdownHookMethod = null; 437 m_removeShutdownHookMethod = null; 438 disableShutdownHook = true; 439 } 440 441 if ( !disableShutdownHook ) 443 { 444 if ( m_debug ) 445 { 446 m_out.println( "Wrapper Manager: Registering shutdown hook" ); 447 } 448 m_hook = new Thread ( "Wrapper-Shutdown-Hook" ) 449 { 450 453 public void run() 454 { 455 m_hookTriggered = true; 457 458 if ( m_debug ) 459 { 460 m_out.println( "Wrapper Manager: ShutdownHook started" ); 461 } 462 463 m_startupRunner = null; 465 466 WrapperManager.stop( 0 ); 468 469 if ( m_debug ) 470 { 471 m_out.println( "Wrapper Manager: ShutdownHook complete" ); 472 } 473 } 474 }; 475 476 try 478 { 479 m_addShutdownHookMethod.invoke( Runtime.getRuntime(), new Object [] { m_hook } ); 480 } 481 catch ( IllegalAccessException e ) 482 { 483 m_out.println( "Wrapper Manager: Unable to register shutdown hook: " + e ); 484 } 485 catch ( InvocationTargetException e ) 486 { 487 Throwable t = e.getTargetException(); 488 if ( t == null ) 489 { 490 t = e; 491 } 492 493 m_out.println( "Wrapper Manager: Unable to register shutdown hook: " + t ); 494 } 495 } 496 497 if ( ( m_key = System.getProperty( "wrapper.key" ) ) == null ) 501 { 502 if ( m_debug ) 503 { 504 m_out.println( "Wrapper Manager: Not using wrapper. (key not specified)" ); 505 } 506 507 m_port = 0; 509 m_jvmPort = 0; 510 m_jvmPortMin = 0; 511 m_jvmPortMax = 0; 512 m_service = false; 513 m_cpuTimeout = 31557600000L; } 515 else 516 { 517 if ( m_debug ) 518 { 519 m_out.println( "Wrapper Manager: Using wrapper" ); 520 } 521 522 String sPort; 524 if ( ( sPort = System.getProperty( "wrapper.port" ) ) == null ) 525 { 526 String msg = m_res.format( "MISSING_PORT" ); 527 m_out.println( msg ); 528 throw new ExceptionInInitializerError ( msg ); 529 } 530 try 531 { 532 m_port = Integer.parseInt( sPort ); 533 } 534 catch ( NumberFormatException e ) 535 { 536 String msg = m_res.format( "BAD_PORT", sPort ); 537 m_out.println( msg ); 538 throw new ExceptionInInitializerError ( msg ); 539 } 540 541 m_jvmPort = 542 WrapperSystemPropertyUtil.getIntProperty( "wrapper.jvm.port", 0 ); 543 m_jvmPortMin = 544 WrapperSystemPropertyUtil.getIntProperty( "wrapper.jvm.port.min", 31000 ); 545 m_jvmPortMax = 546 WrapperSystemPropertyUtil.getIntProperty( "wrapper.jvm.port.max", 31999 ); 547 548 m_ignoreSignals = WrapperSystemPropertyUtil.getBooleanProperty( 550 "wrapper.ignore_signals", false ); 551 552 m_service = WrapperSystemPropertyUtil.getBooleanProperty( "wrapper.service", false ); 554 555 String sCPUTimeout = System.getProperty( "wrapper.cpu.timeout" ); 557 if ( sCPUTimeout == null ) 558 { 559 m_cpuTimeout = DEFAULT_CPU_TIMEOUT; 560 } 561 else 562 { 563 try 564 { 565 m_cpuTimeout = Integer.parseInt( sCPUTimeout ) * 1000L; 566 } 567 catch ( NumberFormatException e ) 568 { 569 String msg = m_res.format( "BAD_CPU_TIMEOUT", sCPUTimeout ); 570 m_out.println( msg ); 571 throw new ExceptionInInitializerError ( msg ); 572 } 573 } 574 } 575 576 verifyWrapperVersion(); 578 579 if ( WrapperSystemPropertyUtil.getBooleanProperty( 581 WrapperManager.class.getName() + ".mbean", true ) ) 582 { 583 registerMBean( new org.tanukisoftware.wrapper.jmx.WrapperManager(), 584 "org.tanukisoftware.wrapper:type=WrapperManager" ); 585 } 586 if ( WrapperSystemPropertyUtil.getBooleanProperty( 587 WrapperManager.class.getName() + ".mbean.testing", false ) ) 588 { 589 registerMBean( new org.tanukisoftware.wrapper.jmx.WrapperManagerTesting(), 590 "org.tanukisoftware.wrapper:type=WrapperManagerTesting" ); 591 } 592 593 initializeNativeLibrary(); 595 596 if ( m_libraryOK ) 597 { 598 verifyNativeLibraryVersion(); 600 601 try 604 { 605 System.setProperty( "wrapper.java.pid", Integer.toString( nativeGetJavaPID() ) ); 606 } 607 catch ( Throwable e ) 608 { 609 if ( m_debug ) 610 { 611 m_out.println( "Call to nativeGetJavaPID() failed: " + e ); 612 } 613 } 614 } 615 616 m_eventRunnerTicks = getTicks(); 621 m_eventRunner = new Thread ( "Wrapper-Control-Event-Monitor" ) 622 { 623 public void run() 624 { 625 if ( m_debug ) 626 { 627 m_out.println( "Control event monitor thread started." ); 628 } 629 630 try 631 { 632 WrapperTickEventImpl tickEvent = new WrapperTickEventImpl(); 633 int lastTickOffset = 0; 634 boolean first = true; 635 636 while ( !m_shuttingDown ) 637 { 638 int offsetDiff; 639 if ( !m_useSystemTime ) 640 { 641 int sysTicks = getSystemTicks(); 643 644 m_ticks++; 655 656 int tickOffset = sysTicks - m_ticks; 659 660 offsetDiff = tickOffset - lastTickOffset; 663 664 if ( first ) 665 { 666 first = false; 667 } 668 else 669 { 670 if ( offsetDiff > m_timerSlowThreshold ) 671 { 672 m_out.println( "The timer fell behind the system clock by " 673 + ( offsetDiff * TICK_MS ) + "ms." ); 674 } 675 else if ( offsetDiff < - m_timerFastThreshold ) 676 { 677 m_out.println( "The system clock fell behind the timer by " 678 + ( -1 * offsetDiff * TICK_MS ) + "ms." ); 679 } 680 } 681 682 lastTickOffset = tickOffset; 684 } 685 else 686 { 687 offsetDiff = 0; 688 } 689 690 694 int nowTicks = getTicks(); 698 long age = getTickAge( m_eventRunnerTicks, nowTicks ); 699 if ( ( m_cpuTimeout > 0 ) && ( age > m_cpuTimeout ) ) 700 { 701 m_out.println( "JVM Process has not received any CPU time for " 702 + ( age / 1000 ) + " seconds. Extending timeouts." ); 703 704 m_lastPingTicks = nowTicks; 706 } 707 m_eventRunnerTicks = nowTicks; 708 709 if ( m_produceCoreEvents ) 712 { 713 tickEvent.m_ticks = nowTicks; 714 tickEvent.m_tickOffset = offsetDiff; 715 fireWrapperEvent( tickEvent ); 716 } 717 718 if ( m_libraryOK ) 719 { 720 int event = WrapperManager.nativeGetControlEvent(); 722 if ( event != 0 ) 723 { 724 WrapperManager.controlEvent( event ); 725 } 726 } 727 728 try 730 { 731 Thread.sleep( TICK_MS ); 732 } 733 catch ( InterruptedException e ) 734 { 735 } 736 } 737 } 738 finally 739 { 740 if ( m_debug ) 741 { 742 m_out.println( "Control event monitor thread stopped." ); 743 } 744 } 745 } 746 }; 747 m_eventRunner.setDaemon( true ); 748 m_eventRunner.start(); 749 750 String fullVersion = System.getProperty( "java.fullversion" ); 752 String vendor = System.getProperty( "java.vm.vendor", "" ); 753 String os = System.getProperty( "os.name", "" ).toLowerCase(); 754 if ( fullVersion == null ) 755 { 756 fullVersion = System.getProperty( "java.runtime.version" ) + " " 757 + System.getProperty( "java.vm.name" ); 758 } 759 760 if ( m_debug ) 761 { 762 m_out.println( "Java Version : " + fullVersion ); 764 m_out.println( "Java VM Vendor : " + vendor ); 765 m_out.println(); 766 } 767 768 m_startupRunner = new Thread ( "Wrapper-Startup-Runner" ) 778 { 779 public void run() 780 { 781 if ( m_debug ) 782 { 783 m_out.println( "Startup runner thread started." ); 784 } 785 786 try 787 { 788 while ( m_startupRunner != null ) 789 { 790 try 791 { 792 Thread.sleep( 100 ); 793 } 794 catch ( InterruptedException e ) 795 { 796 } 798 } 799 } 800 finally 801 { 802 if ( m_debug ) 803 { 804 m_out.println( "Startup runner thread stopped." ); 805 } 806 } 807 } 808 }; 809 m_startupRunner.setDaemon( false ); 811 m_startupRunner.start(); 812 813 m_instance = new WrapperManager(); 815 } 816 817 820 private static native void nativeInit( boolean debug ); 821 private static native String nativeGetLibraryVersion(); 822 private static native int nativeGetJavaPID(); 823 private static native int nativeGetControlEvent(); 824 private static native void nativeRequestThreadDump(); 825 private static native void accessViolationInner(); 826 private static native void nativeSetConsoleTitle( byte[] titleBytes ); 827 private static native WrapperUser nativeGetUser( boolean groups ); 828 private static native WrapperUser nativeGetInteractiveUser( boolean groups ); 829 private static native WrapperWin32Service[] nativeListServices(); 830 private static native WrapperWin32Service nativeSendServiceControlCode( byte[] serviceName, int controlCode ); 831 832 835 838 private static int getSystemTicks() 839 { 840 return (int)( System.currentTimeMillis() / TICK_MS ); 845 } 846 847 861 private static int getTicks() 862 { 863 if ( m_useSystemTime ) 864 { 865 return getSystemTicks(); 866 } 867 else 868 { 869 return m_ticks; 870 } 871 } 872 873 885 private static long getTickAge( int start, int end ) 886 { 887 return (long)( end - start ) * TICK_MS; 890 } 891 892 901 private static String loadNativeLibrary( String name, String file ) 902 { 903 try 904 { 905 System.loadLibrary( name ); 906 907 if ( m_debug ) 908 { 909 m_out.println( "Loaded native library: " + file ); 910 } 911 912 return null; 913 } 914 catch ( UnsatisfiedLinkError e ) 915 { 916 if ( m_debug ) 917 { 918 m_out.println( "Loading native library failed: " + file + " Cause: " + e ); 919 } 920 String error = e.getMessage(); 921 if ( error == null ) 922 { 923 error = e.toString(); 924 } 925 return error; 926 } 927 catch ( Throwable e ) 928 { 929 if ( m_debug ) 930 { 931 m_out.println( "Loading native library failed: " + file + " Cause: " + e ); 932 } 933 String error = e.toString(); 934 return error; 935 } 936 } 937 938 942 private static void registerMBean( Object mbean, String name ) 943 { 944 Class classManagementFactory; 945 try 946 { 947 classManagementFactory = Class.forName( "java.lang.management.ManagementFactory" ); 948 } 949 catch ( ClassNotFoundException e ) 950 { 951 if ( m_debug ) 952 { 953 m_out.println( "Registering MBeans not supported by current JVM: " + name ); 954 } 955 return; 956 } 957 958 try 959 { 960 967 Class classMBeanServer = Class.forName( "javax.management.MBeanServer" ); 969 Class classObjectName = Class.forName( "javax.management.ObjectName" ); 970 Method methodGetPlatformMBeanServer = 971 classManagementFactory.getMethod( "getPlatformMBeanServer", null ); 972 Constructor constructorObjectName = 973 classObjectName.getConstructor( new Class [] {String .class} ); 974 Method methodRegisterMBean = classMBeanServer.getMethod( 975 "registerMBean", new Class [] {Object .class, classObjectName} ); 976 Object mbs = methodGetPlatformMBeanServer.invoke( null, null ); 977 Object oName = constructorObjectName.newInstance( new Object [] {name} ); 978 methodRegisterMBean.invoke( mbs, new Object [] {mbean, oName} ); 979 980 if ( m_debug ) 981 { 982 m_out.println( "Registered MBean with Platform MBean Server: " + name ); 983 } 984 } 985 catch ( Throwable t ) 986 { 987 m_err.println( "Unable to register the " + name + " MBean." ); 988 t.printStackTrace(); 989 } 990 } 991 992 1000 private static File locateFileOnPath( String file, String path ) 1001 { 1002 String pathSep = System.getProperty( "path.separator" ); 1004 1005 StringTokenizer st = new StringTokenizer ( path, pathSep ); 1008 while( st.hasMoreTokens() ) 1009 { 1010 File libFile = new File ( new File ( st.nextToken() ), file ); 1011 if ( libFile.exists() ) 1012 { 1013 return libFile; 1014 } 1015 } 1016 1017 return null; 1018 } 1019 1020 1027 private static String generateDetailedNativeLibraryBaseName( String baseName, 1028 int jvmBits, 1029 boolean universal ) 1030 { 1031 String os = System.getProperty( "os.name", "" ).toLowerCase(); 1033 if ( os.startsWith( "windows" ) ) 1034 { 1035 os = "windows"; 1036 } 1037 else if ( os.equals( "sunos" ) ) 1038 { 1039 os = "solaris"; 1040 } 1041 else if ( os.equals( "hp-ux" ) || os.equals( "hp-ux64" ) ) 1042 { 1043 os = "hpux"; 1044 } 1045 else if ( os.equals( "mac os x" ) ) 1046 { 1047 os = "macosx"; 1048 } 1049 else if ( os.equals( "unix_sv" ) ) 1050 { 1051 os = "unixware"; 1052 } 1053 1054 String arch = System.getProperty( "os.arch", "" ).toLowerCase(); 1056 if ( universal ) 1057 { 1058 arch = "universal"; 1059 } 1060 else 1061 { 1062 if ( arch.equals( "amd64" ) || arch.equals( "athlon" ) || arch.equals( "ia32" ) || 1063 arch.equals( "ia64" ) || arch.equals( "x86_64" ) || arch.equals( "i686" ) || 1064 arch.equals( "i586" ) || arch.equals( "i486" ) || arch.equals( "i386" ) ) 1065 { 1066 arch = "x86"; 1067 } 1068 else if ( arch.startsWith( "sparc" ) ) 1069 { 1070 arch = "sparc"; 1071 } 1072 else if ( arch.equals( "power" ) || arch.equals( "powerpc" ) || arch.equals( "ppc64" ) ) 1073 { 1074 arch = "ppc"; 1075 } 1076 else if ( arch.equals( "pa_risc" ) || arch.equals( "pa-risc" ) ) 1077 { 1078 arch = "parisc"; 1079 } 1080 } 1081 1082 return baseName + "-" + os + "-" + arch + "-" + jvmBits; 1083 } 1084 1085 1089 private static void initializeNativeLibrary() 1090 { 1091 String osName = System.getProperty( "os.name" ).toLowerCase(); 1093 1094 String baseName = System.getProperty( "wrapper.native_library" ); 1096 if ( baseName == null ) 1097 { 1098 m_out.println( "WARNING - The wrapper.native_library system property was not" ); 1100 m_out.println( " set. Using the default value, 'wrapper'." ); 1101 baseName = "wrapper"; 1102 } 1103 String [] detailedNames = new String [4]; 1104 if ( m_jvmBits > 0 ) 1105 { 1106 detailedNames[0] = generateDetailedNativeLibraryBaseName( baseName, m_jvmBits, false ); 1107 if ( osName.startsWith( "mac" ) ) 1108 { 1109 detailedNames[1] = generateDetailedNativeLibraryBaseName( baseName, m_jvmBits, true ); 1110 } 1111 } 1112 else 1113 { 1114 detailedNames[0] = generateDetailedNativeLibraryBaseName( baseName, 32, false ); 1115 detailedNames[1] = generateDetailedNativeLibraryBaseName( baseName, 64, false ); 1116 if ( osName.startsWith( "mac" ) ) 1117 { 1118 detailedNames[2] = generateDetailedNativeLibraryBaseName( baseName, 32, true ); 1119 detailedNames[3] = generateDetailedNativeLibraryBaseName( baseName, 64, true ); 1120 } 1121 } 1122 1123 String file = System.mapLibraryName( baseName ); 1125 String [] detailedFiles = new String [detailedNames.length]; 1126 for ( int i = 0; i < detailedNames.length; i++ ) 1127 { 1128 if ( detailedNames[i] != null ) 1129 { 1130 detailedFiles[i] = System.mapLibraryName( detailedNames[i] ); 1131 } 1132 } 1133 1134 String [] detailedErrors = new String [detailedNames.length]; 1135 String baseError = null; 1136 1137 if ( m_debug ) 1140 { 1141 m_out.println( "Load native library. One or more attempts may fail if platform " 1142 + "specific libraries do not exist." ); 1143 } 1144 m_libraryOK = false; 1145 for ( int i = 0; i < detailedNames.length; i++ ) 1146 { 1147 if ( detailedNames[i] != null ) 1148 { 1149 detailedErrors[i] = loadNativeLibrary( detailedNames[i], detailedFiles[i] ); 1150 if ( detailedErrors[i] == null ) 1151 { 1152 m_libraryOK = true; 1153 break; 1154 } 1155 } 1156 } 1157 if ( ( !m_libraryOK ) && ( ( baseError = loadNativeLibrary( baseName, file ) ) == null ) ) 1158 { 1159 m_libraryOK = true; 1160 } 1161 if ( m_libraryOK ) 1162 { 1163 if ( m_debug ) 1165 { 1166 m_out.println( "Calling native initialization method." ); 1167 } 1168 nativeInit( m_debug ); 1169 } 1170 else 1171 { 1172 String libPath = System.getProperty( "java.library.path" ); 1175 m_out.println(); 1176 if ( libPath.equals( "" ) ) 1177 { 1178 m_out.println( 1180 "WARNING - Unable to load the Wrapper's native library because the" ); 1181 m_out.println( 1182 " java.library.path was set to ''. Please see the" ); 1183 m_out.println( 1184 " documentation for the wrapper.java.library.path " ); 1185 m_out.println( 1186 " configuration property."); 1187 } 1188 else 1189 { 1190 String error = null; 1192 File libFile = null; 1193 for ( int i = 0; i < detailedNames.length; i++ ) 1194 { 1195 if ( detailedFiles[i] != null ) 1196 { 1197 libFile = locateFileOnPath( detailedFiles[i], libPath ); 1198 if ( libFile != null ) 1199 { 1200 error = detailedErrors[i]; 1201 break; 1202 } 1203 } 1204 } 1205 if ( libFile == null ) 1206 { 1207 libFile = locateFileOnPath( file, libPath ); 1208 if ( libFile != null ) 1209 { 1210 error = baseError; 1211 } 1212 } 1213 if ( libFile == null ) 1214 { 1215 m_out.println( 1217 "WARNING - Unable to load the Wrapper's native library because none of the" ); 1218 m_out.println( 1219 " following files:" ); 1220 for ( int i = 0; i < detailedNames.length; i++ ) 1221 { 1222 if ( detailedFiles[i] != null ) 1223 { 1224 m_out.println( 1225 " " + detailedFiles[i] ); 1226 } 1227 } 1228 m_out.println( 1229 " " + file ); 1230 m_out.println( 1231 " could be located on the following java.library.path:" ); 1232 1233 String pathSep = System.getProperty( "path.separator" ); 1234 StringTokenizer st = new StringTokenizer ( libPath, pathSep ); 1235 while ( st.hasMoreTokens() ) 1236 { 1237 File pathElement = new File ( st.nextToken() ); 1238 m_out.println( " " + pathElement.getAbsolutePath() ); 1239 } 1240 m_out.println( 1241 " Please see the documentation for the " 1242 + "wrapper.java.library.path" ); 1243 m_out.println( 1244 " configuration property." ); 1245 } 1246 else 1247 { 1248 m_out.println( 1250 "WARNING - Unable to load the Wrapper's native library '" + libFile.getName() + "'." ); 1251 m_out.println( 1252 " The file is located on the path at the following location but" ); 1253 m_out.println( 1254 " could not be loaded:" ); 1255 m_out.println( 1256 " " + libFile.getAbsolutePath() ); 1257 m_out.println( 1258 " Please verify that the file is readable by the current user" ); 1259 m_out.println( 1260 " and that the file has not been corrupted in any way." ); 1261 m_out.println( 1262 " One common cause of this problem is running a 32-bit version" ); 1263 m_out.println( 1264 " of the Wrapper with a 64-bit version of Java, or vica versa." ); 1265 if ( m_jvmBits > 0 ) 1266 { 1267 m_out.println( 1268 " This is a " + m_jvmBits + "-bit JVM." ); 1269 } 1270 else 1271 { 1272 m_out.println( 1273 " The bit depth of this JVM could not be determined." ); 1274 } 1275 m_out.println( 1276 " Reported cause:" ); 1277 m_out.println( 1278 " " + error ); 1279 } 1280 } 1281 m_out.println( " System signals will not be handled correctly." ); 1282 m_out.println(); 1283 } 1284 } 1285 1286 1291 private static void verifyWrapperVersion() 1292 { 1293 if ( !WrapperManager.isControlledByNativeWrapper() ) 1295 { 1296 return; 1297 } 1298 1299 String wrapperVersion = System.getProperty( "wrapper.version" ); 1302 if ( wrapperVersion == null ) 1303 { 1304 wrapperVersion = "unknown"; 1305 } 1306 1307 if ( !WrapperInfo.getVersion().equals( wrapperVersion ) ) 1308 { 1309 m_out.println( 1310 "WARNING - The Wrapper jar file currently in use is version \"" 1311 + WrapperInfo.getVersion() + "\"" ); 1312 m_out.println( 1313 " while the version of the Wrapper which launched this JVM is " ); 1314 m_out.println( 1315 " \"" + wrapperVersion + "\"." ); 1316 m_out.println( 1317 " The Wrapper may appear to work correctly but some features may" ); 1318 m_out.println( 1319 " not function correctly. This configuration has not been tested" ); 1320 m_out.println( 1321 " and is not supported." ); 1322 m_out.println(); 1323 } 1324 } 1325 1326 1331 private static void verifyNativeLibraryVersion() 1332 { 1333 String jniVersion; 1336 try 1337 { 1338 jniVersion = nativeGetLibraryVersion(); 1339 } 1340 catch ( Throwable e ) 1341 { 1342 if ( m_debug ) 1343 { 1344 m_out.println( "Call to nativeGetLibraryVersion() failed: " + e ); 1345 } 1346 jniVersion = "unknown"; 1347 } 1348 1349 if ( !WrapperInfo.getVersion().equals( jniVersion ) ) 1350 { 1351 m_out.println( 1352 "WARNING - The Wrapper jar file currently in use is version \"" 1353 + WrapperInfo.getVersion() + "\"" ); 1354 m_out.println( 1355 " while the version of the native library is \"" + jniVersion + "\"." ); 1356 m_out.println( 1357 " The Wrapper may appear to work correctly but some features may" ); 1358 m_out.println( 1359 " not function correctly. This configuration has not been tested" ); 1360 m_out.println( 1361 " and is not supported." ); 1362 m_out.println(); 1363 } 1364 } 1365 1366 1371 public static String getVersion() 1372 { 1373 return WrapperInfo.getVersion(); 1374 } 1375 1376 1381 public static String getBuildTime() 1382 { 1383 return WrapperInfo.getBuildTime(); 1384 } 1385 1386 1392 public static int getJVMId() 1393 { 1394 return m_jvmId; 1395 } 1396 1397 1408 public static void setConsoleTitle( String title ) 1409 { 1410 SecurityManager sm = System.getSecurityManager(); 1411 if ( sm != null ) 1412 { 1413 sm.checkPermission( new WrapperPermission( "setConsoleTitle" ) ); 1414 } 1415 1416 if ( m_libraryOK ) 1417 { 1418 byte[] titleBytes = title.getBytes(); 1421 1422 byte[] nullTermBytes = new byte[titleBytes.length + 1]; 1424 System.arraycopy( titleBytes, 0, nullTermBytes, 0, titleBytes.length ); 1425 nullTermBytes[titleBytes.length] = 0; 1426 1427 nativeSetConsoleTitle( nullTermBytes ); 1428 } 1429 } 1430 1431 1443 public static WrapperUser getUser( boolean groups ) 1444 { 1445 SecurityManager sm = System.getSecurityManager(); 1446 if ( sm != null ) 1447 { 1448 sm.checkPermission( new WrapperPermission( "getUser" ) ); 1449 } 1450 1451 WrapperUser user = null; 1452 if ( m_libraryOK ) 1453 { 1454 user = nativeGetUser( groups ); 1455 } 1456 return user; 1457 } 1458 1459 1493 public static WrapperUser getInteractiveUser( boolean groups ) 1494 { 1495 SecurityManager sm = System.getSecurityManager(); 1496 if ( sm != null ) 1497 { 1498 sm.checkPermission( new WrapperPermission( "getInteractiveUser" ) ); 1499 } 1500 1501 WrapperUser user = null; 1502 if ( m_libraryOK ) 1503 { 1504 user = nativeGetInteractiveUser( groups ); 1505 } 1506 return user; 1507 } 1508 1509 1519 public static Properties getProperties() 1520 { 1521 SecurityManager sm = System.getSecurityManager(); 1522 if ( sm != null ) 1523 { 1524 sm.checkPermission( new WrapperPermission( "getProperties" ) ); 1525 } 1526 1527 return m_properties; 1528 } 1529 1530 1539 public static int getWrapperPID() 1540 { 1541 SecurityManager sm = System.getSecurityManager(); 1542 if ( sm != null ) 1543 { 1544 sm.checkPermission( new WrapperPermission( "getWrapperPID" ) ); 1545 } 1546 1547 return WrapperSystemPropertyUtil.getIntProperty( "wrapper.pid", 0 ); 1548 } 1549 1550 1559 public static int getJavaPID() 1560 { 1561 SecurityManager sm = System.getSecurityManager(); 1562 if ( sm != null ) 1563 { 1564 sm.checkPermission( new WrapperPermission( "getJavaPID" ) ); 1565 } 1566 1567 return WrapperSystemPropertyUtil.getIntProperty( "wrapper.java.pid", 0 ); 1568 } 1569 1570 1576 public static void requestThreadDump() 1577 { 1578 SecurityManager sm = System.getSecurityManager(); 1579 if ( sm != null ) 1580 { 1581 sm.checkPermission( new WrapperPermission( "requestThreadDump" ) ); 1582 } 1583 1584 if ( m_libraryOK ) 1585 { 1586 nativeRequestThreadDump(); 1587 } 1588 else 1589 { 1590 m_out.println( " wrapper library not loaded." ); 1591 } 1592 } 1593 1594 1600 public static void appearHung() 1601 { 1602 SecurityManager sm = System.getSecurityManager(); 1603 if ( sm != null ) 1604 { 1605 sm.checkPermission( new WrapperPermission( "test.appearHung" ) ); 1606 } 1607 1608 m_out.println( "WARNING: Making JVM appear to be hung..." ); 1609 m_appearHung = true; 1610 } 1611 1612 1618 public static void accessViolation() 1619 { 1620 SecurityManager sm = System.getSecurityManager(); 1621 if ( sm != null ) 1622 { 1623 sm.checkPermission( new WrapperPermission( "test.accessViolation" ) ); 1624 } 1625 1626 m_out.println( "WARNING: Attempting to cause an access violation..." ); 1627 1628 try 1629 { 1630 Class c = Class.forName( "java.lang.String" ); 1631 java.lang.reflect.Method m = c.getDeclaredMethod( null, null ); 1632 } 1633 catch( NoSuchMethodException ex ) 1634 { 1635 } 1637 catch( Exception ex ) 1638 { 1639 if ( ex instanceof NoSuchFieldException ) 1640 { 1641 } 1645 else 1646 { 1647 ex.printStackTrace(); 1649 } 1650 } 1651 1652 m_out.println( " Attempt to cause access violation failed. JVM is still alive." ); 1653 } 1654 1655 1660 public static void accessViolationNative() 1661 { 1662 SecurityManager sm = System.getSecurityManager(); 1663 if ( sm != null ) 1664 { 1665 sm.checkPermission( new WrapperPermission( "test.accessViolationNative" ) ); 1666 } 1667 1668 m_out.println( "WARNING: Attempting to cause an access violation..." ); 1669 if ( m_libraryOK ) 1670 { 1671 accessViolationInner(); 1672 1673 m_out.println( " Attempt to cause access violation failed. " 1674 + "JVM is still alive." ); 1675 } 1676 else 1677 { 1678 m_out.println( " wrapper library not loaded." ); 1679 } 1680 } 1681 1682 1688 public static boolean isControlledByNativeWrapper() 1689 { 1690 return m_key != null; 1691 } 1692 1693 1703 public static boolean isLaunchedAsService() 1704 { 1705 return m_service; 1706 } 1707 1708 1716 public static boolean isDebugEnabled() 1717 { 1718 return m_debug; 1719 } 1720 1721 1733 public static synchronized void start( final WrapperListener listener, final String [] args ) 1734 { 1735 AccessController.doPrivileged( 1741 new PrivilegedAction () { 1742 public Object run() { 1743 privilegedStart( listener, args ); 1744 return null; 1745 } 1746 } 1747 ); 1748 } 1749 1750 1757 private static void privilegedStart( WrapperListener listener, String [] args ) 1758 { 1759 checkSecurityManager(); 1761 1762 if ( args == null ) 1765 { 1766 args = new String [0]; 1767 } 1768 1769 if ( m_debug ) 1770 { 1771 StringBuffer sb = new StringBuffer (); 1772 sb.append( "args[" ); 1773 for ( int i = 0; i < args.length; i++ ) 1774 { 1775 if ( i > 0 ) 1776 { 1777 sb.append( ", " ); 1778 } 1779 sb.append( "\"" ); 1780 sb.append( args[i] ); 1781 sb.append( "\"" ); 1782 } 1783 sb.append( "]" ); 1784 1785 m_out.println( "WrapperManager.start(" + listener + ", " + sb.toString() + ") " 1786 + "called by thread: " + Thread.currentThread().getName() ); 1787 } 1788 1789 if ( m_disposed) 1791 { 1792 throw new IllegalStateException ( "WrapperManager has already been disposed." ); 1793 } 1794 1795 if ( m_listener != null ) 1796 { 1797 throw new IllegalStateException ( 1798 "WrapperManager has already been started with a WrapperListener." ); 1799 } 1800 if ( listener == null ) 1801 { 1802 throw new IllegalStateException ( "A WrapperListener must be specified." ); 1803 } 1804 m_listener = listener; 1805 1806 m_args = args; 1807 1808 startRunner(); 1809 1810 if ( !isControlledByNativeWrapper() ) 1814 { 1815 startInner(); 1816 } 1817 } 1818 1819 1831 public static void restart() 1832 throws SecurityException 1833 { 1834 SecurityManager sm = System.getSecurityManager(); 1835 if ( sm != null ) 1836 { 1837 sm.checkPermission( new WrapperPermission( "restart" ) ); 1838 } 1839 1840 if ( m_debug ) 1841 { 1842 m_out.println( "WrapperManager.restart() called by thread: " 1843 + Thread.currentThread().getName() ); 1844 } 1845 1846 restartInner(); 1847 } 1848 1849 1865 public static void restartAndReturn() 1866 throws SecurityException 1867 { 1868 SecurityManager sm = System.getSecurityManager(); 1869 if ( sm != null ) 1870 { 1871 sm.checkPermission( new WrapperPermission( "restart" ) ); 1872 } 1873 1874 synchronized( WrapperManager.class ) 1875 { 1876 if ( m_stopping ) 1877 { 1878 if ( m_debug ) 1879 { 1880 m_out.println( "WrapperManager.restartAndReturn() called by thread: " 1881 + Thread.currentThread().getName() + " already stopping." ); 1882 } 1883 return; 1884 } 1885 else 1886 { 1887 if ( m_debug ) 1888 { 1889 m_out.println( "WrapperManager.restartAndReturn() called by thread: " 1890 + Thread.currentThread().getName() ); 1891 } 1892 } 1893 } 1894 1895 1896 Thread restarter = new Thread ( "Wrapper-Restarter" ) 1898 { 1899 public void run() 1900 { 1901 restartInner(); 1902 } 1903 }; 1904 restarter.setDaemon( false ); 1905 restarter.start(); 1906 } 1907 1908 1912 private static void restartInner() 1913 { 1914 boolean stopping; 1915 synchronized( WrapperManager.class ) 1916 { 1917 stopping = m_stopping; 1918 if ( !stopping ) 1919 { 1920 m_stopping = true; 1921 } 1922 } 1923 1924 if ( !stopping ) 1925 { 1926 if ( !m_commRunnerStarted ) 1927 { 1928 startRunner(); 1929 } 1930 1931 sendCommand( WRAPPER_MSG_RESTART, "restart" ); 1933 } 1934 1935 try 1939 { 1940 Thread.sleep( 1000 ); 1941 } 1942 catch ( InterruptedException e ) 1943 { 1944 } 1945 1946 AccessController.doPrivileged( 1950 new PrivilegedAction () { 1951 public Object run() { 1952 privilegedStopInner( 0 ); 1953 return null; 1954 } 1955 } 1956 ); 1957 } 1958 1959 1973 public static void stop( final int exitCode ) 1974 { 1975 SecurityManager sm = System.getSecurityManager(); 1976 if ( sm != null ) 1977 { 1978 sm.checkPermission( new WrapperPermission( "stop" ) ); 1979 } 1980 1981 if ( m_debug ) 1982 { 1983 m_out.println( "WrapperManager.stop(" + exitCode + ") called by thread: " 1984 + Thread.currentThread().getName() ); 1985 } 1986 1987 stopCommon( exitCode, 1000 ); 1988 1989 AccessController.doPrivileged( 1993 new PrivilegedAction () { 1994 public Object run() { 1995 privilegedStopInner( exitCode ); 1996 return null; 1997 } 1998 } 1999 ); 2000 } 2001 2002 2020 public static void stopAndReturn( final int exitCode ) 2021 { 2022 SecurityManager sm = System.getSecurityManager(); 2023 if ( sm != null ) 2024 { 2025 sm.checkPermission( new WrapperPermission( "stop" ) ); 2026 } 2027 2028 synchronized( WrapperManager.class ) 2029 { 2030 if ( m_stopping ) 2031 { 2032 if ( m_debug ) 2033 { 2034 m_out.println( "WrapperManager.stopAndReturn(" + exitCode + ") called by thread: " 2035 + Thread.currentThread().getName() + " already stopping." ); 2036 } 2037 return; 2038 } 2039 else 2040 { 2041 if ( m_debug ) 2042 { 2043 m_out.println( "WrapperManager.stopAndReturn(" + exitCode + ") called by thread: " 2044 + Thread.currentThread().getName() ); 2045 } 2046 } 2047 } 2048 2049 Thread stopper = new Thread ( "Wrapper-Stopper" ) 2051 { 2052 public void run() 2053 { 2054 stopCommon( exitCode, 1000 ); 2055 2056 AccessController.doPrivileged( 2060 new PrivilegedAction () { 2061 public Object run() { 2062 privilegedStopInner( exitCode ); 2063 return null; 2064 } 2065 } 2066 ); 2067 } 2068 }; 2069 stopper.setDaemon( false ); 2070 stopper.start(); 2071 } 2072 2073 2086 public static void stopImmediate( final int exitCode ) 2087 { 2088 SecurityManager sm = System.getSecurityManager(); 2089 if ( sm != null ) 2090 { 2091 sm.checkPermission( new WrapperPermission( "stopImmediate" ) ); 2092 } 2093 2094 if ( m_debug ) 2095 { 2096 m_out.println( "WrapperManager.stopImmediate(" + exitCode + ") called by thread: " 2097 + Thread.currentThread().getName() ); 2098 } 2099 2100 stopCommon( exitCode, 250 ); 2101 2102 signalStopped( exitCode ); 2103 2104 Method haltMethod; 2107 try 2108 { 2109 haltMethod = 2110 Runtime .class.getMethod( "halt", new Class [] { Integer.TYPE } ); 2111 } 2112 catch ( NoSuchMethodException e ) 2113 { 2114 m_out.println( "halt not supported by current JVM." ); 2115 haltMethod = null; 2116 } 2117 2118 if ( haltMethod != null ) 2119 { 2120 Runtime runtime = Runtime.getRuntime(); 2121 try 2122 { 2123 haltMethod.invoke( runtime, new Object [] { new Integer ( exitCode ) } ); 2124 } 2125 catch ( IllegalAccessException e ) 2126 { 2127 m_out.println( "Unable to call runtime.halt: " + e ); 2128 } 2129 catch ( InvocationTargetException e ) 2130 { 2131 Throwable t = e.getTargetException(); 2132 if ( t == null ) 2133 { 2134 t = e; 2135 } 2136 2137 m_out.println( "Unable to call runtime.halt: " + t ); 2138 } 2139 } 2140 else 2141 { 2142 2144 AccessController.doPrivileged( 2148 new PrivilegedAction () { 2149 public Object run() { 2150 privilegedStopInner( exitCode ); 2151 return null; 2152 } 2153 } 2154 ); 2155 } 2156 } 2157 2158 2171 public static void signalStarting( int waitHint ) 2172 { 2173 SecurityManager sm = System.getSecurityManager(); 2174 if ( sm != null ) 2175 { 2176 sm.checkPermission( new WrapperPermission( "signalStarting" ) ); 2177 } 2178 2179 sendCommand( WRAPPER_MSG_START_PENDING, Integer.toString( waitHint ) ); 2180 } 2181 2182 2195 public static void signalStopping( int waitHint ) 2196 { 2197 SecurityManager sm = System.getSecurityManager(); 2198 if ( sm != null ) 2199 { 2200 sm.checkPermission( new WrapperPermission( "signalStopping" ) ); 2201 } 2202 2203 m_stopping = true; 2204 sendCommand( WRAPPER_MSG_STOP_PENDING, Integer.toString( waitHint ) ); 2205 } 2206 2207 2219 public static void signalStopped( int exitCode ) 2220 { 2221 SecurityManager sm = System.getSecurityManager(); 2222 if ( sm != null ) 2223 { 2224 sm.checkPermission( new WrapperPermission( "signalStopped" ) ); 2225 } 2226 2227 m_stopping = true; 2228 sendCommand( WRAPPER_MSG_STOPPED, Integer.toString( exitCode ) ); 2229 2230 try 2233 { 2234 Thread.sleep( 250 ); 2235 } 2236 catch ( InterruptedException e ) 2237 { 2238 } 2240 } 2241 2242 2248 public static boolean hasShutdownHookBeenTriggered() 2249 { 2250 return m_hookTriggered; 2251 } 2252 2253 2284 public static void log( int logLevel, String message ) 2285 { 2286 SecurityManager sm = System.getSecurityManager(); 2287 if ( sm != null ) 2288 { 2289 sm.checkPermission( new WrapperPermission( "log" ) ); 2290 } 2291 2292 2295 if ( ( logLevel < WRAPPER_LOG_LEVEL_DEBUG ) || ( logLevel > WRAPPER_LOG_LEVEL_ADVICE ) ) 2296 { 2297 throw new IllegalArgumentException ( "The specified logLevel is not valid." ); 2298 } 2299 if ( message == null ) 2300 { 2301 throw new IllegalArgumentException ( "The message parameter can not be null." ); 2302 } 2303 2304 if ( m_lowLogLevel <= logLevel ) 2305 { 2306 sendCommand( (byte)( WRAPPER_MSG_LOG + logLevel ), message ); 2307 } 2308 } 2309 2310 2325 public static WrapperWin32Service[] listServices() 2326 throws SecurityException 2327 { 2328 SecurityManager sm = System.getSecurityManager(); 2329 if ( sm == null ) 2330 { 2331 throw new SecurityException ( "A SecurityManager has not yet been set." ); 2332 } 2333 else 2334 { 2335 sm.checkPermission( new WrapperPermission( "listServices" ) ); 2336 } 2337 2338 if ( m_libraryOK ) 2339 { 2340 return nativeListServices(); 2341 } 2342 else 2343 { 2344 return null; 2345 } 2346 } 2347 2348 2382 public static WrapperWin32Service sendServiceControlCode( String serviceName, int controlCode ) 2383 throws WrapperServiceException, SecurityException 2384 { 2385 SecurityManager sm = System.getSecurityManager(); 2386 if ( sm == null ) 2387 { 2388 throw new SecurityException ( "A SecurityManager has not yet been set." ); 2389 } 2390 else 2391 { 2392 String action; 2393 switch( controlCode ) 2394 { 2395 case SERVICE_CONTROL_CODE_START: 2396 action = WrapperServicePermission.ACTION_START; 2397 break; 2398 2399 case SERVICE_CONTROL_CODE_STOP: 2400 action = WrapperServicePermission.ACTION_STOP; 2401 break; 2402 2403 case SERVICE_CONTROL_CODE_PAUSE: 2404 action = WrapperServicePermission.ACTION_PAUSE; 2405 break; 2406 2407 case SERVICE_CONTROL_CODE_CONTINUE: 2408 action = WrapperServicePermission.ACTION_CONTINUE; 2409 break; 2410 2411 case SERVICE_CONTROL_CODE_INTERROGATE: 2412 action = WrapperServicePermission.ACTION_INTERROGATE; 2413 break; 2414 2415 default: 2416 action = WrapperServicePermission.ACTION_USER_CODE; 2417 break; 2418 } 2419 2420 sm.checkPermission( new WrapperServicePermission( serviceName, action ) ); 2421 } 2422 2423 WrapperWin32Service service = null; 2424 if ( m_libraryOK ) 2425 { 2426 service = nativeSendServiceControlCode( serviceName.getBytes(), controlCode ); 2427 } 2428 return service; 2429 } 2430 2431 2450 public static void addWrapperEventListener( WrapperEventListener listener, long mask ) 2451 { 2452 SecurityManager sm = System.getSecurityManager(); 2453 if ( sm != null ) 2454 { 2455 StringBuffer sb = new StringBuffer (); 2456 boolean first = true; 2457 if ( ( mask & WrapperEventListener.EVENT_FLAG_SERVICE ) != 0 ) 2458 { 2459 first = false; 2460 sb.append( WrapperEventPermission.EVENT_TYPE_SERVICE ); 2461 } 2462 if ( ( mask & WrapperEventListener.EVENT_FLAG_CONTROL ) != 0 ) 2463 { 2464 if ( first ) 2465 { 2466 first = false; 2467 } 2468 else 2469 { 2470 sb.append( "," ); 2471 } 2472 sb.append( WrapperEventPermission.EVENT_TYPE_CONTROL ); 2473 } 2474 if ( ( mask & WrapperEventListener.EVENT_FLAG_CORE ) != 0 ) 2475 { 2476 if ( first ) 2477 { 2478 first = false; 2479 } 2480 else 2481 { 2482 sb.append( "," ); 2483 } 2484 sb.append( WrapperEventPermission.EVENT_TYPE_CORE ); 2485 } 2486 sm.checkPermission( new WrapperEventPermission( sb.toString() ) ); 2487 } 2488 2489 synchronized( WrapperManager.class ) 2490 { 2491 WrapperEventListenerMask listenerMask = new WrapperEventListenerMask(); 2492 listenerMask.m_listener = listener; 2493 listenerMask.m_mask = mask; 2494 2495 m_wrapperEventListenerMaskList.add( listenerMask ); 2496 m_wrapperEventListenerMasks = null; 2497 } 2498 2499 updateWrapperEventListenerFlags(); 2500 } 2501 2502 2507 public static void removeWrapperEventListener( WrapperEventListener listener ) 2508 { 2509 SecurityManager sm = System.getSecurityManager(); 2510 if ( sm != null ) 2511 { 2512 sm.checkPermission( new WrapperPermission( "removeWrapperEventListener" ) ); 2513 } 2514 2515 synchronized( WrapperManager.class ) 2516 { 2517 for ( Iterator iter = m_wrapperEventListenerMaskList.iterator(); iter.hasNext(); ) 2519 { 2520 WrapperEventListenerMask listenerMask = (WrapperEventListenerMask)iter.next(); 2521 if ( listenerMask.m_listener == listener ) 2522 { 2523 iter.remove(); 2524 m_wrapperEventListenerMasks = null; 2525 break; 2526 } 2527 } 2528 } 2529 2530 updateWrapperEventListenerFlags(); 2531 } 2532 2533 2536 2539 private WrapperManager() 2540 { 2541 } 2542 2543 2546 2557 private static void checkSecurityManager() 2558 { 2559 if ( m_securityManagerChecked ) 2560 { 2561 return; 2562 } 2563 2564 SecurityManager securityManager = System.getSecurityManager(); 2565 if ( securityManager != null ) 2566 { 2567 if ( m_debug ) 2568 { 2569 m_out.println( 2570 "Detected a SecurityManager: " + securityManager.getClass().getName() ); 2571 } 2572 2573 try 2574 { 2575 securityManager.checkPermission( new java.security.AllPermission () ); 2576 } 2577 catch ( SecurityException e ) 2578 { 2579 m_out.println(); 2580 m_out.println( 2581 "WARNING - Detected that a SecurityManager has been installed but the " ); 2582 m_out.println( 2583 " wrapper.jar has not been granted the java.security.AllPermission" ); 2584 m_out.println( 2585 " permission. This will most likely result in SecurityExceptions" ); 2586 m_out.println( 2587 " being thrown by the Wrapper." ); 2588 m_out.println(); 2589 } 2590 2591 m_securityManagerChecked = true; 2593 } 2594 } 2595 2596 2602 private static WrapperEventListenerMask[] getWrapperEventListenerMasks() 2603 { 2604 WrapperEventListenerMask[] listenerMasks = m_wrapperEventListenerMasks; 2605 if ( listenerMasks == null ) 2606 { 2607 synchronized( WrapperManager.class ) 2608 { 2609 if ( listenerMasks == null ) 2610 { 2611 listenerMasks = 2612 new WrapperEventListenerMask[m_wrapperEventListenerMaskList.size()]; 2613 m_wrapperEventListenerMaskList.toArray( listenerMasks ); 2614 m_wrapperEventListenerMasks = listenerMasks; 2615 } 2616 } 2617 } 2618 2619 return listenerMasks; 2620 } 2621 2622 2626 private static void updateWrapperEventListenerFlags() 2627 { 2628 boolean core = false; 2629 2630 WrapperEventListenerMask[] listenerMasks = getWrapperEventListenerMasks(); 2631 for ( int i = 0; i < listenerMasks.length; i++ ) 2632 { 2633 long mask = listenerMasks[i].m_mask; 2634 2635 core = core | ( ( mask & WrapperEventListener.EVENT_FLAG_CORE ) != 0 ); 2637 } 2638 2639 m_produceCoreEvents = core; 2640 } 2641 2642 2647 private static void fireWrapperEvent( WrapperEvent event ) 2648 { 2649 long eventMask = event.getFlags(); 2650 2651 WrapperEventListenerMask[] listenerMasks = getWrapperEventListenerMasks(); 2652 for ( int i = 0; i < listenerMasks.length; i++ ) 2653 { 2654 long listenerMask = listenerMasks[i].m_mask; 2655 2656 if ( ( listenerMask & eventMask ) != 0 ) 2658 { 2659 WrapperEventListener listener = listenerMasks[i].m_listener; 2661 try 2662 { 2663 listener.fired( event ); 2664 } 2665 catch ( Throwable t ) 2666 { 2667 m_out.println( "Encountered an uncaught exception while notifying " 2668 + "WrapperEventListener of an event:" ); 2669 t.printStackTrace( m_out ); 2670 } 2671 } 2672 } 2673 } 2674 2675 2678 private static void stopCommon( int exitCode, int delay ) 2679 { 2680 boolean stopping; 2681 synchronized( WrapperManager.class ) 2682 { 2683 stopping = m_stopping; 2684 if ( !stopping ) 2685 { 2686 m_stopping = true; 2687 } 2688 } 2689 2690 if ( !stopping ) 2691 { 2692 if ( !m_commRunnerStarted ) 2693 { 2694 startRunner(); 2695 } 2696 2697 sendCommand( WRAPPER_MSG_STOP, Integer.toString( exitCode ) ); 2699 2700 try 2704 { 2705 Thread.sleep( delay ); 2706 } 2707 catch ( InterruptedException e ) 2708 { 2709 } 2710 } 2711 } 2712 2713 2717 private static void dispose() 2718 { 2719 synchronized( WrapperManager.class ) 2720 { 2721 m_disposed = true; 2722 2723 closeSocket(); 2725 2726 try 2728 { 2729 Thread.sleep( 500 ); 2730 } 2731 catch ( InterruptedException e ) 2732 { 2733 } 2734 } 2735 } 2736 2737 2740 private static void startInner() 2741 { 2742 int oldPriority = Thread.currentThread().getPriority(); 2745 Thread.currentThread().setPriority( Thread.NORM_PRIORITY ); 2746 2747 if ( m_listener == null ) 2753 { 2754 if ( m_debug ) 2755 { 2756 m_out.println( "No WrapperListener has been set. Nothing to start." ); 2757 } 2758 } 2759 else 2760 { 2761 if ( m_debug ) 2762 { 2763 m_out.println( "calling WrapperListener.start()" ); 2764 } 2765 2766 final Integer [] resultF = new Integer [1]; 2769 final Throwable [] tF = new Throwable [1]; 2770 2771 if ( Thread.currentThread().isDaemon() ) 2772 { 2773 Thread startRunner = new Thread ( "WrapperListener_start_runner" ) 2775 { 2776 public void run() 2777 { 2778 if ( m_debug ) 2779 { 2780 m_out.println( "WrapperListener.start runner thread started." ); 2781 } 2782 2783 try 2784 { 2785 try 2787 { 2788 resultF[0] = m_listener.start( m_args ); 2789 } 2790 catch ( Throwable t ) 2791 { 2792 tF[0] = t; 2793 } 2794 } 2795 finally 2796 { 2797 if ( m_debug ) 2798 { 2799 m_out.println( "WrapperListener.start runner thread stopped." ); 2800 } 2801 } 2802 } 2803 }; 2804 startRunner.setDaemon( false ); 2805 startRunner.start(); 2806 2807 if ( m_debug ) 2809 { 2810 m_out.println( "Waiting for WrapperListener.start runner thread to complete." ); 2811 } 2812 while ( ( startRunner != null ) && ( startRunner.isAlive() ) ) 2813 { 2814 try 2815 { 2816 startRunner.join(); 2817 startRunner = null; 2818 } 2819 catch ( InterruptedException e ) 2820 { 2821 } 2823 } 2824 } 2825 else 2826 { 2827 try 2830 { 2831 resultF[0] = m_listener.start( m_args ); 2832 } 2833 catch ( Throwable t ) 2834 { 2835 tF[0] = t; 2836 } 2837 } 2838 2839 if ( tF[0] != null ) 2841 { 2842 m_out.println( "Error in WrapperListener.start callback. " + tF[0] ); 2843 tF[0].printStackTrace(); 2844 privilegedStopInner( 1 ); 2847 return; 2849 } 2850 2851 if ( m_debug ) 2852 { 2853 m_out.println( "returned from WrapperListener.start()" ); 2854 } 2855 if ( resultF[0] != null ) 2856 { 2857 int exitCode = resultF[0].intValue(); 2858 if ( m_debug ) 2859 { 2860 m_out.println( 2861 "WrapperListener.start() returned an exit code of " + exitCode + "." ); 2862 } 2863 2864 stop( exitCode ); 2866 return; 2868 } 2869 } 2870 m_startedTicks = getTicks(); 2871 2872 m_startupRunner = null; 2874 2875 checkSecurityManager(); 2878 2879 Thread.currentThread().setPriority( oldPriority ); 2881 2882 signalStarted(); 2884 } 2885 2886 private static void shutdownJVM( int exitCode ) 2887 { 2888 if ( m_debug ) 2889 { 2890 m_out.println( "shutdownJVM(" + exitCode + ") Thread:" + Thread.currentThread().getName() ); 2891 } 2892 2893 if ( Thread.currentThread() == m_hook ) 2895 { 2896 signalStopped( exitCode ); 2898 2899 dispose(); 2901 2902 2905 m_shutdownJVMComplete = true; 2906 } 2907 else 2908 { 2909 if ( ( !m_hookTriggered ) && ( m_hook != null ) ) 2914 { 2915 try 2917 { 2918 m_removeShutdownHookMethod.invoke( 2919 Runtime.getRuntime(), new Object [] { m_hook } ); 2920 } 2921 catch ( IllegalAccessException e ) 2922 { 2923 m_out.println( "Wrapper Manager: Unable to unregister shutdown hook: " + e ); 2924 } 2925 catch ( InvocationTargetException e ) 2926 { 2927 Throwable t = e.getTargetException(); 2928 if ( t == null ) 2929 { 2930 t = e; 2931 } 2932 2933 m_out.println( "Wrapper Manager: Unable to unregister shutdown hook: " + t ); 2934 } 2935 } 2936 signalStopped( exitCode ); 2938 2939 dispose(); 2941 2942 if ( m_debug ) 2943 { 2944 m_out.println( "calling System.exit(" + exitCode + ")" ); 2945 } 2946 m_shutdownJVMComplete = true; 2947 safeSystemExit( exitCode ); 2948 } 2949 } 2950 2951 2957 private static void safeSystemExit( int exitCode ) 2958 { 2959 try 2960 { 2961 System.exit( exitCode ); 2962 } 2963 catch ( IllegalThreadStateException e ) 2964 { 2965 m_out.println( "Wrapper Manager: Attempted System.exit(" + exitCode + ") call failed: " + e.toString() ); 2966 m_out.println( " Trying Runtime.halt(" + exitCode + ")" ); 2967 Runtime.getRuntime().halt( exitCode ); 2968 } 2969 } 2970 2971 2977 private static void privilegedStopInner( int exitCode ) 2978 { 2979 boolean block; 2980 synchronized( WrapperManager.class ) 2981 { 2982 m_stopping = true; 2984 2985 if ( m_stoppingThread == null ) 2987 { 2988 m_stoppingThread = Thread.currentThread(); 2989 block = false; 2990 } 2991 else 2992 { 2993 if ( Thread.currentThread() == m_stoppingThread ) 2994 { 2995 throw new IllegalStateException ( 2996 "WrapperManager.stop() can not be called recursively." ); 2997 } 2998 2999 block = true; 3000 } 3001 } 3002 3003 if ( block ) 3004 { 3005 if ( m_debug ) 3006 { 3007 m_out.println( "Thread, " + Thread.currentThread().getName() 3008 + ", waiting for the JVM to exit." ); 3009 3010 if ( Thread.currentThread() == m_hook ) 3011 { 3012 m_out.println( "System.exit appears to have been called from within the" ); 3013 m_out.println( " WrapperListener.stop() method. If possible the application" ); 3014 m_out.println( " should be modified to avoid this behavior." ); 3015 m_out.println( " To avoid a deadlock, this thread will only wait 5 seconds" ); 3016 m_out.println( " for the application to shutdown. This may result in the" ); 3017 m_out.println( " application failing to shutdown completely before the JVM" ); 3018 m_out.println( " exists. Removing the offending System.exit call will" ); 3019 m_out.println( " resolve this." ); 3020 } 3021 } 3022 3023 int loops = 0; 3028 int wait = 50; 3029 while( true ) 3030 { 3031 try 3032 { 3033 Thread.sleep( wait ); 3034 } 3035 catch ( InterruptedException e ) 3036 { 3037 } 3038 3039 if ( Thread.currentThread() == m_hook ) 3047 { 3048 if ( m_shutdownJVMComplete || ( loops > 5000 / wait ) ) 3049 { 3050 if ( !m_shutdownJVMComplete ) 3051 { 3052 if ( m_debug ) 3053 { 3054 m_out.println( "Thread, " + Thread.currentThread().getName() 3055 + ", continuing after 5 seconds." ); 3056 } 3057 } 3058 3059 signalStopped( m_exitCode ); 3069 3070 return; 3071 } 3072 } 3073 3074 loops++; 3075 } 3076 } 3077 3078 if ( m_debug ) 3079 { 3080 m_out.println( "Thread, " + Thread.currentThread().getName() 3081 + ", handling the shutdown process." ); 3082 } 3083 m_exitCode = exitCode; 3084 3085 int code = exitCode; 3087 if ( m_started ) 3088 { 3089 int oldPriority = Thread.currentThread().getPriority(); 3092 Thread.currentThread().setPriority( Thread.NORM_PRIORITY ); 3093 3094 if ( m_listener == null ) 3100 { 3101 if ( m_debug ) 3102 { 3103 m_out.println( "No WrapperListener has been set. Nothing to stop." ); 3104 } 3105 } 3106 else 3107 { 3108 if ( m_debug ) 3109 { 3110 m_out.println( "calling listener.stop()" ); 3111 } 3112 3113 if ( Thread.currentThread().isDaemon() ) 3114 { 3115 final Integer [] codeF = new Integer [] {new Integer (code)}; 3118 3119 Thread stopRunner = new Thread ( "WrapperListener_stop_runner" ) 3121 { 3122 public void run() 3123 { 3124 if ( m_debug ) 3125 { 3126 m_out.println( "WrapperListener.stop runner thread started." ); 3127 } 3128 3129 try 3130 { 3131 try 3133 { 3134 codeF[0] = new Integer ( m_listener.stop( codeF[0].intValue() ) ); 3135 } 3136 catch ( Throwable t ) 3137 { 3138 m_out.println( "Error in WrapperListener.stop callback. " + t ); 3139 t.printStackTrace(); 3140 } 3141 } 3142 finally 3143 { 3144 if ( m_debug ) 3145 { 3146 m_out.println( "WrapperListener.stop runner thread stopped." ); 3147 } 3148 } 3149 } 3150 }; 3151 stopRunner.setDaemon( false ); 3152 stopRunner.start(); 3153 3154 if ( m_debug ) 3156 { 3157 m_out.println( "Waiting for WrapperListener.stop runner thread to complete." ); 3158 } 3159 while ( ( stopRunner != null ) && ( stopRunner.isAlive() ) ) 3160 { 3161 try 3162 { 3163 stopRunner.join(); 3164 stopRunner = null; 3165 } 3166 catch ( InterruptedException e ) 3167 { 3168 } 3170 } 3171 3172 code = codeF[0].intValue(); 3174 } 3175 else 3176 { 3177 try 3179 { 3180 code = m_listener.stop( code ); 3181 } 3182 catch ( Throwable t ) 3183 { 3184 m_out.println( "Error in WrapperListener.stop callback. " + t ); 3185 t.printStackTrace(); 3186 } 3187 } 3188 if ( m_debug ) 3189 { 3190 m_out.println( "returned from listener.stop() -> " + code ); 3191 } 3192 } 3193 3194 Thread.currentThread().setPriority( oldPriority ); 3196 } 3197 3198 shutdownJVM( code ); 3199 } 3200 3201 private static void signalStarted() 3202 { 3203 sendCommand( WRAPPER_MSG_STARTED, "" ); 3204 m_started = true; 3205 } 3206 3207 3213 private static void controlEvent( int event ) 3214 { 3215 String eventName; 3216 boolean ignore; 3217 switch( event ) 3218 { 3219 case WRAPPER_CTRL_C_EVENT: 3220 eventName = "WRAPPER_CTRL_C_EVENT"; 3221 ignore = m_ignoreSignals; 3222 break; 3223 case WRAPPER_CTRL_CLOSE_EVENT: 3224 eventName = "WRAPPER_CTRL_CLOSE_EVENT"; 3225 ignore = m_ignoreSignals; 3226 break; 3227 case WRAPPER_CTRL_LOGOFF_EVENT: 3228 eventName = "WRAPPER_CTRL_LOGOFF_EVENT"; 3229 ignore = false; 3230 break; 3231 case WRAPPER_CTRL_SHUTDOWN_EVENT: 3232 eventName = "WRAPPER_CTRL_SHUTDOWN_EVENT"; 3233 ignore = false; 3234 break; 3235 case WRAPPER_CTRL_TERM_EVENT: 3236 eventName = "WRAPPER_CTRL_TERM_EVENT"; 3237 ignore = m_ignoreSignals; 3238 break; 3239 case WRAPPER_CTRL_HUP_EVENT: 3240 eventName = "WRAPPER_CTRL_HUP_EVENT"; 3241 ignore = m_ignoreSignals; 3242 break; 3243 default: 3244 eventName = "Unexpected event: " + event; 3245 ignore = false; 3246 break; 3247 } 3248 3249 WrapperControlEvent controlEvent = new WrapperControlEvent( event, eventName ); 3250 if ( ignore ) 3251 { 3252 controlEvent.consume(); 3255 } 3256 fireWrapperEvent( controlEvent ); 3257 3258 if ( !controlEvent.isConsumed() ) 3259 { 3260 if ( ignore ) 3261 { 3262 if ( m_debug ) 3263 { 3264 m_out.println( "Ignoring control event(" + eventName + ")" ); 3265 } 3266 } 3267 else 3268 { 3269 if ( m_debug ) 3270 { 3271 m_out.println( "Processing control event(" + eventName + ")" ); 3272 } 3273 3274 if ( m_listener != null ) 3276 { 3277 try 3278 { 3279 m_listener.controlEvent( event ); 3280 } 3281 catch ( Throwable t ) 3282 { 3283 m_out.println( "Error in WrapperListener.controlEvent callback. " + t ); 3284 t.printStackTrace(); 3285 } 3286 } 3287 else 3288 { 3289 stop( 0 ); 3292 } 3293 } 3294 } 3295 } 3296 3297 3301 private static char PROPERTY_SEPARATOR = '\t'; 3302 private static void readProperties( String rawProps ) 3303 { 3304 WrapperProperties properties = new WrapperProperties(); 3305 3306 int len = rawProps.length(); 3307 int first = 0; 3308 while ( first < len ) 3309 { 3310 StringBuffer sb = new StringBuffer (); 3311 boolean foundEnd = false; 3312 do 3313 { 3314 int pos = rawProps.indexOf( PROPERTY_SEPARATOR, first ); 3315 if ( pos >= 0 ) 3316 { 3317 if ( pos > 0 ) 3318 { 3319 sb.append( rawProps.substring( first, pos ) ); 3320 } 3321 if ( pos < len - 1 ) 3322 { 3323 if ( rawProps.charAt( pos + 1 ) == PROPERTY_SEPARATOR ) 3324 { 3325 sb.append( PROPERTY_SEPARATOR ); 3327 first = pos + 2; 3328 } 3329 else 3330 { 3331 foundEnd = true; 3332 first = pos + 1; 3333 } 3334 } 3335 else 3336 { 3337 foundEnd = true; 3338 first = pos + 1; 3339 } 3340 } 3341 else 3342 { 3343 sb.append( rawProps.substring( first ) ); 3345 foundEnd = true; 3346 first = len; 3347 } 3348 } 3349 while ( !foundEnd ); 3350 3351 String property = sb.toString(); 3352 3353 int pos = property.indexOf( '=' ); 3355 if ( pos > 0 ) 3356 { 3357 String key = property.substring( 0, pos ); 3358 String value; 3359 if ( pos < property.length() - 1 ) 3360 { 3361 value = property.substring( pos + 1 ); 3362 } 3363 else 3364 { 3365 value = ""; 3366 } 3367 3368 properties.setProperty( key, value ); 3369 } 3370 } 3371 3372 properties.lock(); 3374 3375 m_properties = properties; 3376 } 3377 3378 private static synchronized Socket openSocket() 3379 { 3380 if ( m_debug ) 3381 { 3382 m_out.println( "Open socket to wrapper..." + Thread.currentThread().getName() ); 3383 } 3384 3385 InetAddress iNetAddress; 3386 try 3387 { 3388 iNetAddress = InetAddress.getByName( "127.0.0.1" ); 3389 } 3390 catch ( UnknownHostException e ) 3391 { 3392 m_out.println( e ); 3394 stop( 1 ); 3395 return null; } 3397 3398 boolean connected = false; 3400 int tryPort; 3401 boolean fixedPort; 3402 if ( m_jvmPort > 0 ) 3403 { 3404 tryPort = m_jvmPort; 3405 fixedPort = true; 3406 } 3407 else 3408 { 3409 tryPort = m_jvmPortMin; 3410 fixedPort = false; 3411 } 3412 3413 do 3415 { 3416 try 3417 { 3418 m_socket = new Socket ( iNetAddress, m_port, iNetAddress, tryPort ); 3419 if ( m_debug ) 3420 { 3421 m_out.println( "Opened Socket from " + tryPort + " to " + m_port ); 3422 } 3423 connected = true; 3424 break; 3425 } 3426 catch ( SocketException e ) 3427 { 3428 String eMessage = e.getMessage(); 3429 3430 if ( e instanceof ConnectException ) 3431 { 3432 m_out.println( "Failed to connect to the Wrapper at port " + m_port + "." ); 3433 m_out.println( e ); 3434 m_out.println( "Exiting JVM..." ); 3436 stopImmediate( 1 ); 3437 } 3438 else if ( ( e instanceof BindException ) || 3439 ( ( eMessage != null ) && ( eMessage.indexOf( "errno: 48" ) >= 0 ) ) ) 3440 { 3441 3444 if ( m_debug ) 3447 { 3448 m_out.println( "Failed attempt to bind using local port " + tryPort ); 3449 } 3450 3451 if ( fixedPort ) 3452 { 3453 tryPort = m_jvmPortMin; 3455 fixedPort = false; 3456 } 3457 else 3458 { 3459 tryPort++; 3460 } 3461 } 3462 else 3463 { 3464 m_out.println( e ); 3466 m_socket = null; 3467 return null; 3468 } 3469 } 3470 catch ( IOException e ) 3471 { 3472 m_out.println( e ); 3473 m_socket = null; 3474 return null; 3475 } 3476 } 3477 while ( tryPort <= m_jvmPortMax ); 3478 3479 if ( connected ) 3480 { 3481 if ( ( m_jvmPort > 0 ) && ( m_jvmPort != tryPort ) ) 3482 { 3483 m_out.println( 3484 "Port " + m_jvmPort + " already in use, using port " + tryPort + " instead." ); 3485 } 3486 } 3487 else 3488 { 3489 if ( m_jvmPortMax > m_jvmPortMin ) 3490 { 3491 m_out.println( 3492 "Failed to connect to the Wrapper at port " + m_port + " by binding to any " 3493 + "ports in the range " + m_jvmPortMin + " to " + m_jvmPortMax + "." ); 3494 } 3495 else 3496 { 3497 m_out.println( 3498 "Failed to connect to the Wrapper at port " + m_port + " by binding to port " 3499 + m_jvmPortMin + "." ); 3500 } 3501 m_out.println( "Exiting JVM..." ); 3503 stopImmediate( 1 ); 3504 } 3505 3506 try 3508 { 3509 m_socket.setTcpNoDelay( true ); 3511 3512 if ( m_soTimeout > 0 ) 3514 { 3515 m_socket.setSoTimeout( m_soTimeout ); 3516 } 3517 } 3518 catch ( IOException e ) 3519 { 3520 m_out.println( e ); 3521 } 3522 3523 sendCommand( WRAPPER_MSG_KEY, m_key ); 3526 3527 return m_socket; 3528 } 3529 3530 private static synchronized void closeSocket() 3531 { 3532 if ( m_socket != null ) 3533 { 3534 if ( m_debug ) 3535 { 3536 m_out.println( "Closing socket." ); 3537 } 3538 3539 try 3540 { 3541 m_socket.close(); 3542 } 3543 catch ( IOException e ) 3544 { 3545 } 3546 finally 3547 { 3548 m_socket = null; 3549 } 3550 } 3551 } 3552 3553 private static String getPacketCodeName(byte code) 3554 { 3555 String name; 3556 3557 switch (code) 3558 { 3559 case WRAPPER_MSG_START: 3560 name ="START"; 3561 break; 3562 3563 case WRAPPER_MSG_STOP: 3564 name ="STOP"; 3565 break; 3566 3567 case WRAPPER_MSG_RESTART: 3568 name ="RESTART"; 3569 break; 3570 3571 case WRAPPER_MSG_PING: 3572 name ="PING"; 3573 break; 3574 3575 case WRAPPER_MSG_STOP_PENDING: 3576 name ="STOP_PENDING"; 3577 break; 3578 3579 case WRAPPER_MSG_START_PENDING: 3580 name ="START_PENDING"; 3581 break; 3582 3583 case WRAPPER_MSG_STARTED: 3584 name ="STARTED"; 3585 break; 3586 3587 case WRAPPER_MSG_STOPPED: 3588 name ="STOPPED"; 3589 break; 3590 3591 case WRAPPER_MSG_KEY: 3592 name ="KEY"; 3593 break; 3594 3595 case WRAPPER_MSG_BADKEY: 3596 name ="BADKEY"; 3597 break; 3598 3599 case WRAPPER_MSG_LOW_LOG_LEVEL: 3600 name ="LOW_LOG_LEVEL"; 3601 break; 3602 3603 case WRAPPER_MSG_PING_TIMEOUT: 3604 name ="PING_TIMEOUT"; 3605 break; 3606 3607 case WRAPPER_MSG_SERVICE_CONTROL_CODE: 3608 name ="SERVICE_CONTROL_CODE"; 3609 break; 3610 3611 case WRAPPER_MSG_PROPERTIES: 3612 name ="PROPERTIES"; 3613 break; 3614 3615 case WRAPPER_MSG_LOG + WRAPPER_LOG_LEVEL_DEBUG: 3616 name ="LOG(DEBUG)"; 3617 break; 3618 3619 case WRAPPER_MSG_LOG + WRAPPER_LOG_LEVEL_INFO: 3620 name ="LOG(INFO)"; 3621 break; 3622 3623 case WRAPPER_MSG_LOG + WRAPPER_LOG_LEVEL_STATUS: 3624 name ="LOG(STATUS)"; 3625 break; 3626 3627 case WRAPPER_MSG_LOG + WRAPPER_LOG_LEVEL_WARN: 3628 name ="LOG(WARN)"; 3629 break; 3630 3631 case WRAPPER_MSG_LOG + WRAPPER_LOG_LEVEL_ERROR: 3632 name ="LOG(ERROR)"; 3633 break; 3634 3635 case WRAPPER_MSG_LOG + WRAPPER_LOG_LEVEL_FATAL: 3636 name ="LOG(FATAL)"; 3637 break; 3638 3639 case WRAPPER_MSG_LOG + WRAPPER_LOG_LEVEL_ADVICE: 3640 name ="LOG(ADVICE)"; 3641 break; 3642 3643 default: 3644 name = "UNKNOWN(" + code + ")"; 3645 break; 3646 } 3647 return name; 3648 } 3649 3650 private static synchronized void sendCommand( byte code, String message ) 3651 { 3652 if ( m_debug ) 3653 { 3654 m_out.println( "Send a packet " + getPacketCodeName( code ) + " : " + message ); 3655 } 3656 if ( m_appearHung ) 3657 { 3658 } 3660 else 3661 { 3662 Socket socket = m_socket; 3664 if ( socket == null && isControlledByNativeWrapper() && ( !m_stopping ) ) 3665 { 3666 socket = openSocket(); 3668 } 3669 3670 if ( ( code == WRAPPER_MSG_START_PENDING ) || ( code == WRAPPER_MSG_STARTED ) ) 3671 { 3672 m_lastPingTicks = getTicks(); 3675 } 3676 3677 if ( socket != null ) 3679 { 3680 try 3681 { 3682 byte[] messageBytes = message.getBytes(); 3686 if ( m_commandBuffer.length < messageBytes.length + 2 ) 3687 { 3688 m_commandBuffer = new byte[messageBytes.length + 2]; 3689 } 3690 3691 m_commandBuffer[0] = code; 3695 System.arraycopy( messageBytes, 0, m_commandBuffer, 1, messageBytes.length ); 3696 int len = messageBytes.length + 2; 3697 m_commandBuffer[len - 1] = 0; 3698 3699 OutputStream os = socket.getOutputStream(); 3700 os.write( m_commandBuffer, 0, len ); 3701 os.flush(); 3702 } 3703 catch ( IOException e ) 3704 { 3705 m_out.println( e ); 3706 e.printStackTrace(); 3707 closeSocket(); 3708 } 3709 } 3710 } 3711 } 3712 3713 3721 private static byte[] m_socketReadBuffer = new byte[256]; 3722 private static void handleSocket() 3723 { 3724 WrapperPingEvent pingEvent = new WrapperPingEvent(); 3725 try 3726 { 3727 if ( m_debug ) 3728 { 3729 m_out.println( "handleSocket(" + m_socket + ")" ); 3730 } 3731 DataInputStream is = new DataInputStream ( m_socket.getInputStream() ); 3732 while ( !m_disposed ) 3733 { 3734 try 3735 { 3736 byte code = is.readByte(); 3738 3739 byte b; 3741 int i = 0; 3742 do 3743 { 3744 b = is.readByte(); 3745 if ( b != 0 ) 3746 { 3747 if ( i >= m_socketReadBuffer.length ) 3748 { 3749 byte[] tmp = m_socketReadBuffer; 3750 m_socketReadBuffer = new byte[tmp.length + 256]; 3751 System.arraycopy( tmp, 0, m_socketReadBuffer, 0, tmp.length ); 3752 } 3753 m_socketReadBuffer[i] = b; 3754 i++; 3755 } 3756 } 3757 while ( b != 0 ); 3758 3759 String msg = new String ( m_socketReadBuffer, 0, i ); 3760 3761 if ( m_appearHung ) 3762 { 3763 } 3766 else 3767 { 3768 if ( m_debug ) 3769 { 3770 String logMsg; 3771 if ( code == WRAPPER_MSG_PROPERTIES ) 3772 { 3773 logMsg = "(Property Values)"; 3777 } 3778 else 3779 { 3780 logMsg = msg; 3781 } 3782 m_out.println( "Received a packet " + getPacketCodeName( code ) 3783 + " : " + logMsg ); 3784 } 3785 3786 switch( code ) 3788 { 3789 case WRAPPER_MSG_START: 3790 startInner(); 3791 break; 3792 3793 case WRAPPER_MSG_STOP: 3794 if ( !m_stopping ) 3796 { 3797 privilegedStopInner( 0 ); 3798 } 3800 break; 3801 3802 case WRAPPER_MSG_PING: 3803 m_lastPingTicks = getTicks(); 3804 sendCommand( WRAPPER_MSG_PING, "ok" ); 3805 3806 if ( m_produceCoreEvents ) 3807 { 3808 fireWrapperEvent( pingEvent ); 3809 } 3810 3811 break; 3812 3813 case WRAPPER_MSG_BADKEY: 3814 m_out.println( 3816 "Authorization key rejected by Wrapper. Exiting JVM." ); 3817 closeSocket(); 3818 privilegedStopInner( 1 ); 3819 break; 3820 3821 case WRAPPER_MSG_LOW_LOG_LEVEL: 3822 try 3823 { 3824 m_lowLogLevel = Integer.parseInt( msg ); 3825 m_debug = ( m_lowLogLevel <= WRAPPER_LOG_LEVEL_DEBUG ); 3826 if ( m_debug ) 3827 { 3828 m_out.println( "Wrapper Manager: LowLogLevel from Wrapper " 3829 + "is " + m_lowLogLevel ); 3830 } 3831 } 3832 catch ( NumberFormatException e ) 3833 { 3834 m_out.println( "Encountered an Illegal LowLogLevel from the " 3835 + "Wrapper: " + msg ); 3836 } 3837 break; 3838 3839 case WRAPPER_MSG_PING_TIMEOUT: 3840 try 3841 { 3842 m_pingTimeout = Integer.parseInt( msg ) * 1000; 3843 if ( m_debug ) 3844 { 3845 m_out.println( "PingTimeout from Wrapper is " + m_pingTimeout ); 3846 } 3847 } 3848 catch ( NumberFormatException e ) 3849 { 3850 m_out.println( "Encountered an Illegal PingTimeout from the " 3851 + "Wrapper: " + msg ); 3852 } 3853 3854 if ( m_pingTimeout <= 0 ) 3856 { 3857 m_socket.setSoTimeout( 0 ); 3858 } 3859 else if ( m_soTimeout < m_pingTimeout ) 3860 { 3861 m_socket.setSoTimeout( m_pingTimeout ); 3862 } 3863 3864 break; 3865 3866 case WRAPPER_MSG_SERVICE_CONTROL_CODE: 3867 try 3868 { 3869 int serviceControlCode = Integer.parseInt( msg ); 3870 if ( m_debug ) 3871 { 3872 m_out.println( "ServiceControlCode from Wrapper with code " 3873 + serviceControlCode ); 3874 } 3875 WrapperServiceControlEvent event = 3876 new WrapperServiceControlEvent( serviceControlCode ); 3877 fireWrapperEvent( event ); 3878 } 3879 catch ( NumberFormatException e ) 3880 { 3881 m_out.println( "Encountered an Illegal ServiceControlCode from " 3882 + "the Wrapper: " + msg ); 3883 } 3884 break; 3885 3886 case WRAPPER_MSG_PROPERTIES: 3887 readProperties( msg ); 3888 break; 3889 3890 default: 3891 m_out.println( "Wrapper code received an unknown packet type: " 3893 + code ); 3894 break; 3895 } 3896 } 3897 } 3898 catch ( InterruptedIOException e ) 3899 { 3900 int nowTicks = getTicks(); 3901 3902 if ( ( m_started ) && ( !m_stopping ) ) 3904 { 3905 if ( m_debug ) 3906 { 3907 m_out.println( "Read Timed out. (Last Ping was " 3908 + getTickAge( m_lastPingTicks, nowTicks ) + " milliseconds ago)" ); 3909 } 3910 3911 if ( !m_appearHung ) 3912 { 3913 long lastPingAge = getTickAge( m_lastPingTicks, nowTicks ); 3914 long eventRunnerAge = getTickAge( m_eventRunnerTicks, nowTicks ); 3915 3916 if ( eventRunnerAge < 10000 ) 3920 { 3921 if ( m_pingTimeout > 0 ) 3923 { 3924 if ( lastPingAge > m_pingTimeout + 90000 ) 3927 { 3928 m_out.println( 3931 "Wrapper Manager: JVM did not exit. Give up." ); 3932 safeSystemExit(1); 3933 } 3934 else if ( lastPingAge > m_pingTimeout ) 3935 { 3936 m_out.println( 3939 "Wrapper Manager: The Wrapper code did not ping the " 3940 + "JVM for " + (lastPingAge / 1000) + " seconds. " 3941 + "Quit and let the Wrapper resynch."); 3942 3943 if ( !m_stopping ) 3945 { 3946 sendCommand( WRAPPER_MSG_RESTART, "restart" ); 3948 3949 try 3954 { 3955 Thread.sleep( 1000 ); 3956 } 3957 catch ( InterruptedException e2 ) 3958 { 3959 } 3960 3961 privilegedStopInner( 1 ); 3962 } 3963 } 3964 } 3965 } 3966 } 3967 } 3968 } 3969 } 3970 return; 3971 3972 } 3973 catch ( SocketException e ) 3974 { 3975 if ( m_debug ) 3976 { 3977 if ( m_socket == null ) 3978 { 3979 } 3983 else 3984 { 3985 m_out.println( "Closed socket: " + e ); 3986 } 3987 } 3988 return; 3989 } 3990 catch ( IOException e ) 3991 { 3992 return; 3996 } 3997 } 3998 3999 private static void startRunner() 4000 { 4001 if ( isControlledByNativeWrapper() ) 4002 { 4003 if ( m_commRunner == null ) 4004 { 4005 m_commRunner = new Thread ( m_instance, WRAPPER_CONNECTION_THREAD_NAME ); 4007 m_commRunner.setDaemon( true ); 4008 m_commRunner.start(); 4009 } 4010 4011 synchronized( WrapperManager.class ) 4013 { 4014 while ( !m_commRunnerStarted ) 4015 { 4016 try 4017 { 4018 WrapperManager.class.wait( 100 ); 4019 } 4020 catch ( InterruptedException e ) 4021 { 4022 } 4023 } 4024 } 4025 } 4026 else 4027 { 4028 synchronized( WrapperManager.class ) 4030 { 4031 m_commRunnerStarted = true; 4032 WrapperManager.class.notifyAll(); 4033 } 4034 } 4035 } 4036 4037 4040 public void run() 4041 { 4042 if ( Thread.currentThread() != m_commRunner ) 4044 { 4045 throw new IllegalStateException ( 4046 "Only the comm runner thread is allowed to call this method." ); 4047 } 4048 4049 if ( m_debug ) 4050 { 4051 m_out.println( "Communications runner thread started." ); 4052 } 4053 4054 Thread.currentThread().setPriority( Thread.MAX_PRIORITY ); 4057 4058 m_lastPingTicks = getTicks(); 4060 4061 boolean gotPortOnce = false; 4062 while ( !m_disposed ) 4063 { 4064 try 4065 { 4066 try 4067 { 4068 openSocket(); 4069 4070 if ( !m_commRunnerStarted ) 4074 { 4075 synchronized( WrapperManager.class ) 4076 { 4077 m_commRunnerStarted = true; 4078 WrapperManager.class.notifyAll(); 4079 } 4080 } 4081 4082 if ( m_socket != null ) 4083 { 4084 handleSocket(); 4085 } 4086 else 4087 { 4088 try 4090 { 4091 Thread.sleep( 100 ); 4092 } 4093 catch ( InterruptedException e ) 4094 { 4095 } 4096 } 4097 } 4098 finally 4099 { 4100 closeSocket(); 4102 } 4103 } 4104 catch ( ThreadDeath td ) 4105 { 4106 m_out.println( m_warning.format( "SERVER_DAEMON_KILLED" ) ); 4107 } 4108 catch ( Throwable t ) 4109 { 4110 if ( !m_shuttingDown ) 4111 { 4112 m_out.println( m_error.format( "SERVER_DAEMON_DIED" ) ); 4114 t.printStackTrace(); 4115 } 4116 } 4117 } 4118 4119 synchronized( WrapperManager.class ) 4121 { 4122 if ( !m_commRunnerStarted ) 4123 { 4124 m_commRunnerStarted = true; 4125 WrapperManager.class.notifyAll(); 4126 } 4127 } 4128 4129 if ( m_debug ) 4130 { 4131 m_out.println( m_info.format( "SERVER_DAEMON_SHUT_DOWN" ) ); 4132 } 4133 } 4134 4135 4138 4144 private static class WrapperEventListenerMask 4145 { 4146 private WrapperEventListener m_listener; 4147 private long m_mask; 4148 } 4149 4150 private static class WrapperTickEventImpl 4151 extends WrapperTickEvent 4152 { 4153 private int m_ticks; 4154 private int m_tickOffset; 4155 4156 4161 public int getTicks() 4162 { 4163 return m_ticks; 4164 } 4165 4166 4179 public int getTickOffset() 4180 { 4181 return m_tickOffset; 4182 } 4183 } 4184} 4185 4186 | Popular Tags |