1 17 18 package org.apache.avalon.fortress.util.test; 19 20 import org.apache.avalon.framework.activity.Disposable; 21 import org.apache.avalon.framework.activity.Initializable; 22 import org.apache.avalon.framework.activity.Startable; 23 import org.apache.avalon.framework.activity.Suspendable; 24 import org.apache.avalon.framework.component.Composable; 25 import org.apache.avalon.framework.component.Recomposable; 26 import org.apache.avalon.framework.configuration.Configurable; 27 import org.apache.avalon.framework.configuration.Reconfigurable; 28 import org.apache.avalon.framework.context.Contextualizable; 29 import org.apache.avalon.framework.context.Recontextualizable; 30 import org.apache.avalon.framework.logger.LogEnabled; 31 import org.apache.avalon.framework.logger.Loggable; 32 import org.apache.avalon.framework.parameters.Parameterizable; 33 import org.apache.avalon.framework.service.Serviceable; 34 35 44 public final class ComponentStateValidator 45 { 46 private static final String WRITE_FAIL = "Value is already bound"; 47 48 private static final long LOG_ENABLED = 0x00000001; 50 private static final long LOGGABLE = 0x00000002; 51 private static final long CONTEXTUALIZABLE = 0x00000004; 52 private static final long COMPOSABLE = 0x00000008; 53 private static final long SERVICEABLE = 0x00000010; 54 private static final long CONFIGURABLE = 0x00000020; 55 private static final long PARAMETERIZABLE = 0x00000040; 56 private static final long INITIALIZABLE = 0x00000080; 57 private static final long STARTABLE = 0x00000100; 58 private static final long SUSPENDABLE = 0x00001000; 59 private static final long RECONTEXTUALIZABLE = 0x00002000; 60 private static final long RECOMPOSABLE = 0x00004000; 61 private static final long RECONFIGURABLE = 0x00008000; 62 private static final long DISPOSABLE = 0x00100000; 63 64 private static final long ENABLE_LOGGING = 0x00000001; 66 private static final long SET_LOGGER = 0x00000002; 67 private static final long CONTEXTUALIZE = 0x00000004; 68 private static final long SERVICE = 0x00000008; 69 private static final long COMPOSE = 0x00000010; 70 private static final long CONFIGURE = 0x00000020; 71 private static final long PARAMETERIZE = 0x00000040; 72 private static final long INITIALIZE = 0x00000080; 73 private static final long START = 0x00000100; 74 private static final long INIT_COMPLETE = 0x00000400; 75 76 private static final long SUSPEND = 0x00001000; 78 private static final long RECONTEXTUALIZE = 0x00002000; 79 private static final long RECOMPOSE = 0x00004000; 80 private static final long RECONFIGURE = 0x00008000; 81 private static final long RESUME = 0x00010000; 82 83 private static final long STOP = 0x00100000; 85 private static final long DISPOSE = 0x00200000; 86 87 private static final long INIT_MASK = ENABLE_LOGGING|SET_LOGGER| 89 CONTEXTUALIZE|COMPOSE|SERVICE|CONFIGURE|PARAMETERIZE|INITIALIZE| 90 START; 91 92 private final long m_interfaces; 93 private final long m_methods; 94 private long m_state; 95 private boolean m_active; 96 private final Object m_object; 97 98 102 public ComponentStateValidator( final Object object ) 103 { 104 m_object = object; 105 106 long methods = 0; 107 long interfaces = 0; 108 109 if ( object instanceof LogEnabled ) 110 { 111 interfaces |= LOG_ENABLED; 112 methods |= ENABLE_LOGGING; 113 } 114 115 if ( object instanceof Loggable ) 116 { 117 interfaces |= LOGGABLE; 118 methods |= SET_LOGGER; 119 } 120 121 if ( object instanceof Contextualizable ) 122 { 123 interfaces |= CONTEXTUALIZABLE; 124 methods |= CONTEXTUALIZE; 125 } 126 127 if ( object instanceof Serviceable ) 128 { 129 interfaces |= SERVICEABLE; 130 methods |= SERVICE; 131 } 132 133 if ( object instanceof Composable ) 134 { 135 if ( ( interfaces&SERVICEABLE ) > 0 ) 136 { 137 throw new IllegalStateException ( "Cannot implement Composable and Serviceable together" ); 138 } 139 140 interfaces |= COMPOSABLE; 141 methods |= COMPOSE; 142 } 143 144 if ( object instanceof Configurable ) 145 { 146 interfaces |= CONFIGURABLE; 147 methods |= CONFIGURE; 148 } 149 150 if ( object instanceof Parameterizable ) 151 { 152 interfaces |= PARAMETERIZABLE; 153 methods |= PARAMETERIZE; 154 } 155 156 if ( object instanceof Initializable ) 157 { 158 interfaces |= INITIALIZABLE; 159 methods |= INITIALIZE; 160 } 161 162 if ( object instanceof Startable ) 163 { 164 interfaces |= STARTABLE; 165 methods |= START|STOP; 166 } 167 168 if ( object instanceof Suspendable ) 169 { 170 interfaces |= SUSPENDABLE; 171 methods |= SUSPEND|RESUME; 172 } 173 174 if ( object instanceof Recontextualizable ) 175 { 176 interfaces |= RECONTEXTUALIZABLE; 177 methods |= RECONTEXTUALIZE; 178 } 179 180 if ( object instanceof Recomposable ) 181 { 182 interfaces |= RECOMPOSABLE; 183 methods |= RECOMPOSE; 184 } 185 186 if ( object instanceof Reconfigurable ) 187 { 188 interfaces |= RECONFIGURABLE; 189 methods |= RECONFIGURE; 190 } 191 192 if ( object instanceof Disposable ) 193 { 194 interfaces |= DISPOSABLE; 195 methods |= DISPOSE; 196 } 197 198 m_methods = methods; 199 m_interfaces = interfaces; 200 201 generalCheckInitComplete(); 202 } 203 204 private String getInterfaceName( long interfaceId ) 205 { 206 if ( interfaceId == LOG_ENABLED ) 207 { 208 return LogEnabled.class.getName(); 209 } 210 else if ( interfaceId == LOGGABLE ) 211 { 212 return Loggable.class.getName(); 213 } 214 else if ( interfaceId == CONTEXTUALIZABLE ) 215 { 216 return Contextualizable.class.getName(); 217 } 218 else if ( interfaceId == SERVICEABLE ) 219 { 220 return Serviceable.class.getName(); 221 } 222 else if ( interfaceId == COMPOSABLE ) 223 { 224 return Composable.class.getName(); 225 } 226 else if ( interfaceId == CONFIGURABLE ) 227 { 228 return Configurable.class.getName(); 229 } 230 else if ( interfaceId == PARAMETERIZABLE ) 231 { 232 return Parameterizable.class.getName(); 233 } 234 else if ( interfaceId == INITIALIZABLE ) 235 { 236 return Initializable.class.getName(); 237 } 238 else if ( interfaceId == STARTABLE ) 239 { 240 return Startable.class.getName(); 241 } 242 else if ( interfaceId == SUSPENDABLE ) 243 { 244 return Suspendable.class.getName(); 245 } 246 else if ( interfaceId == RECONTEXTUALIZABLE ) 247 { 248 return Recontextualizable.class.getName(); 249 } 250 else if ( interfaceId == RECOMPOSABLE ) 251 { 252 return Recomposable.class.getName(); 253 } 254 else if ( interfaceId == RECONFIGURABLE ) 255 { 256 return Reconfigurable.class.getName(); 257 } 258 else if ( interfaceId == DISPOSABLE ) 259 { 260 return Disposable.class.getName(); 261 } 262 else 263 { 264 throw new IllegalStateException ( "Unknown Interface Id " + interfaceId ); 265 } 266 } 267 268 private String getMethodName( long methodId ) 269 { 270 if ( methodId == ENABLE_LOGGING ) 271 { 272 return "enableLogging()"; 273 } 274 else if ( methodId == SET_LOGGER ) 275 { 276 return "setLogger()"; 277 } 278 else if ( methodId == CONTEXTUALIZE ) 279 { 280 return "contextualize()"; 281 } 282 else if ( methodId == SERVICE ) 283 { 284 return "service()"; 285 } 286 else if ( methodId == COMPOSE ) 287 { 288 return "compose()"; 289 } 290 else if ( methodId == CONFIGURE ) 291 { 292 return "configure()"; 293 } 294 else if ( methodId == PARAMETERIZE ) 295 { 296 return "parameterize()"; 297 } 298 else if ( methodId == INITIALIZE ) 299 { 300 return "initialize()"; 301 } 302 else if ( methodId == START ) 303 { 304 return "start()"; 305 } 306 else if ( methodId == SUSPEND ) 307 { 308 return "suspend()"; 309 } 310 else if ( methodId == RECONTEXTUALIZE ) 311 { 312 return "recontextualize()"; 313 } 314 else if ( methodId == RECOMPOSE ) 315 { 316 return "recompose()"; 317 } 318 else if ( methodId == RECONFIGURE ) 319 { 320 return "reconfigure()"; 321 } 322 else if ( methodId == RESUME ) 323 { 324 return "resume()"; 325 } 326 else if ( methodId == STOP ) 327 { 328 return "stop()"; 329 } 330 else if ( methodId == DISPOSE ) 331 { 332 return "dispose()"; 333 } 334 else 335 { 336 throw new IllegalStateException ( "Unknown Method Id " + methodId ); 337 } 338 } 339 340 private String getLastMethod( long state ) 341 { 342 for ( int i = 31; i >= 0; i-- ) 343 { 344 long methodId = 0x1 << i; 345 if ( ( state&methodId ) != 0 ) 346 { 347 return getMethodName( methodId ); 348 } 349 } 350 throw new IllegalStateException ( "No last state method found for state " + state ); 351 } 352 353 356 private void generalCheckInitComplete() 357 { 358 if ( m_state == ( m_methods&INIT_MASK ) ) 359 { 360 m_active = true; 362 } 363 } 364 365 370 private void generalCheckInit( final String message, final long interfaceId, final long methodId ) 371 { 372 if ( ( m_interfaces&interfaceId ) == 0 ) 373 { 374 if ( message == null ) 376 { 377 throw new IllegalStateException ( m_object.getClass().getName() + 378 " does not implement " + getInterfaceName( interfaceId ) + "." ); 379 } 380 else 381 { 382 throw new IllegalStateException ( message ); 383 } 384 } 385 else if ( ( m_state&methodId ) > 0 ) 386 { 387 if ( message == null ) 389 { 390 throw new IllegalStateException ( getMethodName( methodId ) + " already called." ); 391 } 392 else 393 { 394 throw new IllegalStateException ( message ); 395 } 396 } 397 else if ( m_state > methodId ) 398 { 399 if ( message == null ) 401 { 402 throw new IllegalStateException ( getMethodName( methodId ) + 403 " can not be called after " + getLastMethod( m_state ) + "." ); 404 } 405 else 406 { 407 throw new IllegalStateException ( message ); 408 } 409 } 410 else if ( ( m_state&( methodId - 1 ) ) != ( m_methods&( methodId - 1 ) ) ) 411 { 412 if ( message == null ) 415 { 416 throw new IllegalStateException ( getMethodName( methodId ) + 417 " called out of order. " + getLastMethod( m_methods&( methodId - 1 ) ) + 418 " must be called first." ); 419 } 420 else 421 { 422 throw new IllegalStateException ( message ); 423 } 424 } 425 426 m_state |= methodId; 428 429 generalCheckInitComplete(); 431 } 432 433 442 private void generalCheckActive( final String message, final long interfaceId, final long methodId ) 443 { 444 if ( ( m_interfaces&interfaceId ) == 0 ) 445 { 446 if ( message == null ) 448 { 449 throw new IllegalStateException ( m_object.getClass().getName() + 450 " does not implement " + getInterfaceName( interfaceId ) + "." ); 451 } 452 else 453 { 454 throw new IllegalStateException ( message ); 455 } 456 } 457 else if ( !m_active ) 458 { 459 if ( m_state < INIT_COMPLETE ) 461 { 462 if ( message == null ) 464 { 465 throw new IllegalStateException ( getMethodName( methodId ) + 466 " called before component was made active. " + 467 getLastMethod( m_methods&( INIT_COMPLETE - 1 ) ) + 468 " must be called first." ); 469 } 470 else 471 { 472 throw new IllegalStateException ( message ); 473 } 474 } 475 else 476 { 477 if ( message == null ) 479 { 480 throw new IllegalStateException ( getMethodName( methodId ) + 481 " called after component was made inactive. Cannot call after " + 482 getLastMethod( m_state ) + "." ); 483 } 484 else 485 { 486 throw new IllegalStateException ( message ); 487 } 488 } 489 } 490 } 491 492 497 private void generalCheckDest( final String message, final long interfaceId, final long methodId ) 498 { 499 if ( ( m_interfaces&interfaceId ) == 0 ) 500 { 501 if ( message == null ) 503 { 504 throw new IllegalStateException ( m_object.getClass().getName() + 505 " does not implement " + getInterfaceName( interfaceId ) + "." ); 506 } 507 else 508 { 509 throw new IllegalStateException ( message ); 510 } 511 } 512 else if ( m_state > methodId ) 513 { 514 if ( message == null ) 516 { 517 throw new IllegalStateException ( getMethodName( methodId ) + 518 " can not be called after " + getLastMethod( m_state ) + "." ); 519 } 520 else 521 { 522 throw new IllegalStateException ( message ); 523 } 524 } 525 526 m_state |= methodId; 528 529 m_active = false; 531 } 532 533 540 public void checkLogEnabled() 541 { 542 checkLogEnabled( null ); 543 } 544 545 553 public void checkLogEnabled( final String message ) 554 { 555 generalCheckInit( message, LOG_ENABLED, ENABLE_LOGGING ); 556 } 557 558 565 public void checkLoggable() 566 { 567 checkLogEnabled( null ); 568 } 569 570 578 public void checkLoggable( final String message ) 579 { 580 generalCheckInit( message, LOGGABLE, SET_LOGGER ); 581 } 582 583 590 public void checkContextualized() 591 { 592 checkContextualized( null ); 593 } 594 595 603 public void checkContextualized( final String message ) 604 { 605 generalCheckInit( message, CONTEXTUALIZABLE, CONTEXTUALIZE ); 606 } 607 608 615 public void checkServiced() 616 { 617 checkServiced( null ); 618 } 619 620 628 public void checkServiced( final String message ) 629 { 630 generalCheckInit( message, SERVICEABLE, SERVICE ); 631 } 632 633 640 public void checkComposed() 641 { 642 checkComposed( null ); 643 } 644 645 653 public void checkComposed( final String message ) 654 { 655 generalCheckInit( message, COMPOSABLE, COMPOSE ); 656 } 657 658 665 public void checkConfigured() 666 { 667 checkConfigured( null ); 668 } 669 670 678 public void checkConfigured( final String message ) 679 { 680 generalCheckInit( message, CONFIGURABLE, CONFIGURE ); 681 } 682 683 690 public void checkParameterized() 691 { 692 checkParameterized( null ); 693 } 694 695 703 public void checkParameterized( final String message ) 704 { 705 generalCheckInit( message, PARAMETERIZABLE, PARAMETERIZE ); 706 } 707 708 715 public void checkInitialized() 716 { 717 checkInitialized( null ); 718 } 719 720 728 public void checkInitialized( final String message ) 729 { 730 generalCheckInit( message, INITIALIZABLE, INITIALIZE ); 731 } 732 733 740 public void checkStarted() 741 { 742 checkStarted( null ); 743 } 744 745 753 public void checkStarted( final String message ) 754 { 755 generalCheckInit( message, STARTABLE, START ); 756 } 757 758 765 public void checkSuspended() 766 { 767 checkSuspended( null ); 768 } 769 770 778 public void checkSuspended( final String message ) 779 { 780 generalCheckActive( message, SUSPENDABLE, SUSPEND ); 781 } 782 783 790 public void checkResumed() 791 { 792 checkResumed( null ); 793 } 794 795 803 public void checkResumed( final String message ) 804 { 805 generalCheckActive( message, SUSPENDABLE, RESUME ); 806 } 807 808 815 public void checkStopped() 816 { 817 checkStopped( null ); 818 } 819 820 828 public void checkStopped( final String message ) 829 { 830 generalCheckDest( message, STARTABLE, STOP ); 831 } 832 833 840 public void checkDisposed() 841 { 842 checkDisposed( null ); 843 } 844 845 853 public void checkDisposed( final String message ) 854 { 855 generalCheckDest( message, DISPOSABLE, DISPOSE ); 856 } 857 858 863 public void checkActive() 864 { 865 checkActive( null ); 866 } 867 868 874 public void checkActive( final String message ) 875 { 876 if ( isActive() ) 877 { 878 return; 879 } 880 881 if ( m_state < INIT_COMPLETE ) 883 { 884 if ( message == null ) 886 { 887 throw new IllegalStateException ( "Component not in the active state. " + 888 getLastMethod( m_methods&( INIT_COMPLETE - 1 ) ) + 889 " was not called." ); 890 } 891 else 892 { 893 throw new IllegalStateException ( message ); 894 } 895 } 896 else 897 { 898 if ( message == null ) 900 { 901 throw new IllegalStateException ( "Component not in the active state because " + 902 getLastMethod( m_state ) + " was called." ); 903 } 904 else 905 { 906 throw new IllegalStateException ( message ); 907 } 908 } 909 } 910 911 916 public boolean isActive() 917 { 918 return m_active; 919 } 920 921 927 public void checkNotAssigned( final Object object ) 928 { 929 checkNotAssigned( object, WRITE_FAIL ); 930 } 931 932 939 public void checkNotAssigned( final Object object, final String message ) 940 { 941 if ( null != object ) 942 { 943 throw new IllegalStateException ( message ); 944 } 945 } 946 } 947 948 | Popular Tags |