1 package org.apache.beehive.controls.runtime.bean; 2 19 20 import java.beans.beancontext.BeanContext ; 21 import java.beans.beancontext.BeanContextServices ; 22 import java.beans.PropertyChangeSupport ; 23 import java.beans.VetoableChangeSupport ; 24 import java.io.IOException ; 25 import java.io.ObjectOutputStream ; 26 import java.lang.reflect.AnnotatedElement ; 27 import java.lang.reflect.InvocationTargetException ; 28 import java.lang.reflect.Method ; 29 import java.util.*; 30 import java.util.concurrent.Semaphore ; 31 32 import org.apache.beehive.controls.api.ControlException; 33 import org.apache.beehive.controls.api.versioning.VersionRequired; 34 import org.apache.beehive.controls.api.versioning.Version; 35 import org.apache.beehive.controls.api.bean.Threading; 36 import org.apache.beehive.controls.api.bean.ThreadingPolicy; 37 import org.apache.beehive.controls.api.bean.ControlImplementation; 38 import org.apache.beehive.controls.api.bean.ControlExtension; 39 import org.apache.beehive.controls.api.bean.ControlInterface; 40 import org.apache.beehive.controls.api.context.ControlThreadContext; 41 import org.apache.beehive.controls.api.events.EventRef; 42 import org.apache.beehive.controls.api.events.EventSet; 43 import org.apache.beehive.controls.api.properties.*; 44 import org.apache.beehive.controls.spi.svc.Interceptor; 45 import org.apache.beehive.controls.spi.svc.InterceptorPivotException; 46 47 62 abstract public class ControlBean 63 implements org.apache.beehive.controls.api.bean.ControlBean 64 { 65 73 protected ControlBean(org.apache.beehive.controls.api.context.ControlBeanContext context, 74 String id, PropertyMap initProperties, Class controlIntf) 75 { 76 super(); 77 78 _localID = id; 79 _controlIntf = controlIntf; 80 81 _cbc = new ControlBeanContext( this ); 83 84 if (context == null) 89 context = ControlThreadContext.getContext(); 90 91 if (context != null) 97 context.add(this); 98 else 99 setBeanContext(null); 100 101 PropertyMap classMap = getAnnotationMap(controlIntf); 106 if (initProperties != null) 107 { 108 AnnotatedElement annotElem = null; 114 if (initProperties instanceof AnnotatedElementMap) 115 { 116 annotElem = ((AnnotatedElementMap)initProperties).getAnnotatedElement(); 117 initProperties = getAnnotationMap(annotElem); 118 } 119 120 if (annotElem != controlIntf) 126 initProperties.setDelegateMap(classMap); 127 _properties = new BeanPropertyMap(initProperties); 128 } 129 else 130 { 131 _properties = new BeanPropertyMap(classMap); 136 } 137 138 } 139 140 144 private void ensureThreadingBehaviour() 145 { 146 if (hasSingleThreadedImpl() && ! _cbc.hasSingleThreadedParent()) 152 _invokeLock = new Semaphore (1, true); 153 else 154 _invokeLock = null; 155 } 156 159 final public ControlBeanContext getBeanContextProxy() 160 { 161 return _cbc; 162 } 163 164 168 final public BeanContext getBeanContext() 169 { 170 return getBeanContextProxy().getBeanContext(); 176 } 177 178 188 final public synchronized void setBeanContext(BeanContext bc) 189 { 190 ensureThreadingBehaviour(); 191 } 192 193 196 final public String getControlID() 197 { 198 return _cbc.getControlID(); 199 } 200 201 204 final public Class getControlInterface() 205 { 206 return _controlIntf; 207 } 208 209 213 boolean hasSingleThreadedImpl() 214 { 215 return _threadingPolicy == ThreadingPolicy.SINGLE_THREADED; 216 } 217 218 221 protected synchronized ImplInitializer getImplInitializer() 222 { 223 if (_implInitializer == null) 224 { 225 try 226 { 227 Class initClass = _implClass.getClassLoader().loadClass( 228 _implClass.getName() + "Initializer"); 229 _implInitializer = (ImplInitializer)initClass.newInstance(); 230 } 231 catch (Exception e) 232 { 233 throw new ControlException("Control initialization failure", e); 234 } 235 } 236 return _implInitializer; 237 } 238 239 246 public synchronized Object ensureControl() 247 { 248 if (_control == null) 249 { 250 255 String implBinding = null; 256 BaseProperties bp = _properties.getPropertySet( BaseProperties.class ); 257 if ( bp != null ) 258 implBinding = bp.controlImplementation(); 259 else 260 implBinding = ControlBeanContext.getDefaultControlBinding(_controlIntf); 261 262 try 263 { 264 _implClass = _controlIntf.getClassLoader().loadClass(implBinding); 265 266 if (_implClass.getAnnotation(ControlImplementation.class) == null) 272 { 273 throw new ControlException("@org.apache.beehive.controls.api.bean.ControlImplementation annotation is missing from control implementation class: " + _implClass.getName()); 274 } 275 } 276 catch (ClassNotFoundException cnfe) 277 { 278 throw new ControlException("Unable to load control implementation: " + implBinding, cnfe); 279 } 280 281 Threading thr = (Threading)_implClass.getAnnotation(Threading.class); 285 if ( thr != null ) 286 _threadingPolicy = thr.value(); 287 else 288 _threadingPolicy = ThreadingPolicy.SINGLE_THREADED; 290 ensureThreadingBehaviour(); 291 292 try 293 { 294 _control = _implClass.newInstance(); 298 299 try 300 { 301 getImplInitializer().initialize(this, _control); 302 _hasServices = true; 303 } 304 catch (Exception e) 305 { 306 throw new ControlException("Control initialization failure", e); 307 } 308 309 ControlBeanContext cbcs = (ControlBeanContext)getBeanContextProxy(); 314 cbcs.initializeControl(); 315 } 316 catch (RuntimeException re) { throw re; } catch (Exception e) 318 { 319 throw new ControlException("Unable to create control instance", e); 320 } 321 } 322 323 if (!_hasServices) 328 { 329 getImplInitializer().initServices(this, _control); 330 _hasServices = true; 331 } 332 333 return _control; 334 } 335 336 339 Object getImplementation() { return _control; } 340 341 346 protected void preInvoke(Method m, Object [] args, String [] interceptorNames) 347 throws InterceptorPivotException 348 { 349 if (_invokeLock != null) 354 { 355 try { _invokeLock.acquire(); } catch (InterruptedException ie) { } 356 } 357 358 if ( interceptorNames != null ) 362 { 363 ControlBeanContext cbc = getControlBeanContext(); 364 365 for ( String n : interceptorNames ) 366 { 367 Interceptor i = ensureInterceptor( n ); 368 try 369 { 370 i.preInvoke( this, m, args ); 371 } 372 catch (InterceptorPivotException ipe) 373 { 374 ipe.setInterceptorName(n); 375 throw ipe; 376 } 377 } 378 } 379 380 Vector<InvokeListener> invokeListeners = getInvokeListeners(); 381 if (invokeListeners.size() > 0) 382 { 383 for (InvokeListener listener : invokeListeners) 384 listener.preInvoke(m, args); 385 } 386 } 387 388 393 protected void preInvoke(Method m, Object [] args) 394 { 395 try 396 { 397 preInvoke(m, args, null); 398 } 399 catch (InterceptorPivotException ipe) 400 { 401 } 403 } 404 405 420 protected void postInvoke(Method m, Object [] args, Object retval, Throwable t, String [] interceptorNames, String pivotedInterceptor) 421 { 422 try 423 { 424 if ( interceptorNames != null ) 428 { 429 ControlBeanContext cbc = getControlBeanContext(); 430 431 for (int cnt = interceptorNames.length-1; cnt >= 0; cnt-- ) 432 { 433 String n = interceptorNames[cnt]; 434 if (pivotedInterceptor == null || n.equals(pivotedInterceptor)) 435 { 436 pivotedInterceptor = null; 437 Interceptor i = ensureInterceptor( n ); 438 i.postInvoke( this, m, args, retval, t ); 439 } 440 } 441 } 442 443 Vector<InvokeListener> invokeListeners = getInvokeListeners(); 444 if (invokeListeners.size() > 0) 445 { 446 for (InvokeListener listener : invokeListeners) 447 listener.postInvoke(retval, t); 448 } 449 } 450 finally 451 { 452 if (_invokeLock != null) 456 _invokeLock.release(); 457 } 458 } 459 460 465 protected void postInvoke(Method m, Object [] args, Object retval, Throwable t) 466 { 467 postInvoke(m, args, retval, t, null, null); 468 } 469 470 471 474 protected <T> void setEventNotifier(Class <T> eventSet, T notifier) 475 { 476 _notifiers.put(eventSet,notifier); 477 478 List<Class > superEventSets = new ArrayList<Class >(); 483 getSuperEventSets(eventSet, superEventSets); 484 Iterator<Class > i = superEventSets.iterator(); 485 while (i.hasNext()) 486 { 487 Class superEventSet = i.next(); 488 _notifiers.put(superEventSet,notifier); 489 } 490 } 491 492 498 private void getSuperEventSets(Class eventSet, List<Class > superEventSets) 499 { 500 Class [] superInterfaces = eventSet.getInterfaces(); 501 if (superInterfaces != null) 502 { 503 for (int i=0; i < superInterfaces.length; i++) 504 { 505 Class superInterface = superInterfaces[i]; 506 if (superInterface.isAnnotationPresent(EventSet.class)) 507 { 508 superEventSets.add(superInterface); 509 510 getSuperEventSets(superInterface, superEventSets); 512 } 513 } 514 } 515 } 516 517 520 protected <T> T getEventNotifier(Class <T> eventSet) 521 { 522 return (T)_notifiers.get(eventSet); 523 } 524 525 528 Vector<InvokeListener> getInvokeListeners() 529 { 530 if (_invokeListeners == null) 531 _invokeListeners = new Vector<InvokeListener>(); 532 return _invokeListeners; 533 } 534 535 538 void addInvokeListener(InvokeListener invokeListener) 539 { 540 getInvokeListeners().addElement(invokeListener); 541 } 542 543 546 void removeInvokeListener(InvokeListener invokeListener) 547 { 548 getInvokeListeners().removeElement(invokeListener); 549 } 550 551 554 protected String getLocalID() 555 { 556 return _localID; 557 } 558 559 564 void setLocalID(String localID) 565 { 566 assert _localID == null; _localID = localID; 568 } 569 570 571 575 public ControlBeanContext getControlBeanContext() 576 { 577 return (ControlBeanContext)getBeanContextProxy(); 581 } 582 583 590 protected Object getControlService(Class serviceClass, Object selector) 591 throws TooManyListenersException 592 593 { 594 ControlBeanContext cbc = getControlBeanContext(); 599 BeanContext bc = cbc.getBeanContext(); 600 if (bc == null || !(bc instanceof BeanContextServices )) 601 throw new ControlException("Can't locate service context: " + bc); 602 603 return ((BeanContextServices )bc).getService(cbc, this, serviceClass, selector, cbc); 608 } 609 610 614 protected void setControlProperty(PropertyKey key, Object o) 615 { 616 AnnotationConstraintValidator.validate(key, o); 617 _properties.setProperty(key, o); 618 } 619 620 624 Object dispatchEvent(EventRef event, Object [] args) 625 throws IllegalAccessException ,IllegalArgumentException , 626 InvocationTargetException 627 { 628 ensureControl(); 629 630 Class controlInterface = getControlInterface(); 634 Method method = event.getEventMethod(controlInterface); 635 636 Object eventTarget = null; 640 if (method.getDeclaringClass().isAssignableFrom(_control.getClass())) 641 { 642 eventTarget = _control; 649 } 650 else 651 { 652 eventTarget = _notifiers.get(method.getDeclaringClass()); 658 if (eventTarget == null) 659 throw new IllegalArgumentException ("No event notifier found for " + event); 660 } 661 662 return method.invoke(eventTarget, args); 666 } 667 668 673 protected Object getRawControlProperty(PropertyKey key) 674 { 675 return _properties.getProperty(key); 676 } 677 678 682 protected Object getControlProperty(PropertyKey key) 683 { 684 Object value = getRawControlProperty(key); 685 686 if (value instanceof PropertyMap) 689 { 690 PropertyMap map = (PropertyMap)value; 691 value = PropertySetProxy.getProxy(map.getMapClass(), map); 692 } 693 694 return value; 695 } 696 697 700 abstract protected Map getPropertyMapCache(); 701 702 706 protected PropertyMap getAnnotationMap(AnnotatedElement annotElem) 707 { 708 Map annotCache = getPropertyMapCache(); 709 710 if (annotCache.containsKey(annotElem)) 712 return (PropertyMap)annotCache.get(annotElem); 713 714 PropertyMap map = getControlBeanContext().getAnnotationMap(annotElem); 719 annotCache.put(annotElem, map); 720 721 return map; 722 } 723 724 727 BeanPropertyMap getPropertyMap() 728 { 729 return _properties; 730 } 731 732 738 synchronized protected PropertyChangeSupport getPropertyChangeSupport() 739 { 740 if (_changeSupport == null) 741 _changeSupport = new PropertyChangeSupport (this); 742 743 return _changeSupport; 744 } 745 746 753 protected void firePropertyChange(PropertyKey propertyKey, Object oldValue, Object newValue) 754 { 755 if (_changeSupport == null) 757 return; 758 759 _changeSupport.firePropertyChange(propertyKey.getPropertyName(), oldValue, newValue); 760 } 761 762 768 synchronized protected VetoableChangeSupport getVetoableChangeSupport() 769 { 770 if (_vetoSupport == null) 771 _vetoSupport = new VetoableChangeSupport (this); 772 773 return _vetoSupport; 774 } 775 776 783 protected void fireVetoableChange(PropertyKey propertyKey, Object oldValue, Object newValue) 784 throws java.beans.PropertyVetoException 785 { 786 if (_vetoSupport == null) 788 return; 789 790 _vetoSupport.fireVetoableChange(propertyKey.getPropertyName(), oldValue, newValue); 791 } 792 793 798 protected String [] getParameterNames(Method m) 799 { 800 throw new IllegalArgumentException ("No parameter name data for " + m); 801 } 802 803 808 public static Class getMostDerivedInterface(Class controlIntf) 809 { 810 while (controlIntf.isAnnotationPresent(ControlExtension.class)) 811 { 812 Class [] intfs = controlIntf.getInterfaces(); 813 boolean found = false; 814 for (int i = 0; i < intfs.length; i++) 815 { 816 if (intfs[i].isAnnotationPresent(ControlExtension.class) || 817 intfs[i].isAnnotationPresent(ControlInterface.class)) 818 { 819 controlIntf = intfs[i]; 820 found = true; 821 break; 822 } 823 } 824 if (!found) 825 { 826 throw new ControlException("Can't find base control interface for " + controlIntf); 827 } 828 } 829 return controlIntf; 830 } 831 832 838 protected static void enforceVersionRequired(String intfName, Version version, VersionRequired versionRequired) 839 { 840 if ( versionRequired != null ) 841 { 842 int majorRequired = versionRequired.major(); 843 int minorRequired = versionRequired.minor(); 844 845 if ( majorRequired < 0 ) return; 847 848 int majorPresent = -1; 849 int minorPresent = -1; 850 if ( version != null ) 851 { 852 majorPresent = version.major(); 853 minorPresent = version.minor(); 854 855 if ( majorRequired <= majorPresent && 856 (minorRequired < 0 || minorRequired <= minorPresent) ) 857 { 858 return; 860 } 861 } 862 863 throw new ControlException( "Control extension " + intfName + " fails version requirement: requires interface version " + 867 majorRequired + "." + minorRequired + ", found interface version " + 868 majorPresent + "." + minorPresent + "." ); 869 } 870 } 871 872 873 876 private synchronized void writeObject(ObjectOutputStream oos) 877 throws IOException 878 { 879 if (_control != null) 880 { 881 ControlImplementation implAnnot = (ControlImplementation)_implClass.getAnnotation(ControlImplementation.class); 891 assert implAnnot != null; 892 if (implAnnot.isTransient()) 893 { 894 _control = null; 895 } 896 else 897 { 898 getImplInitializer().resetServices(this, _control); 899 _hasServices = false; 900 } 901 } 902 903 oos.defaultWriteObject(); 904 } 905 906 909 public void decodeImpl(Object impl) 910 { 911 if (impl != _control) 912 throw new ControlException("Cannot change implementation"); 913 }; 914 915 918 protected Interceptor ensureInterceptor( String n ) 919 { 920 Interceptor i = null; 921 if ( _interceptors == null ) 922 { 923 _interceptors = new HashMap<String ,Interceptor>(); 924 } 925 else 926 { 927 i = _interceptors.get( n ); 928 } 929 930 if ( i == null ) 931 { 932 try 933 { 934 i = (Interceptor) getControlService( getControlBeanContext().getClassLoader().loadClass( n ), null ); 935 } 936 catch ( Exception e ) 937 { 938 942 } 944 finally 945 { 946 if ( i == null) 949 i = new NullInterceptor(); 950 951 _interceptors.put( n, i ); 952 } 953 } 954 return i; 955 } 956 957 961 static private class NullInterceptor implements Interceptor 962 { 963 public void preInvoke( org.apache.beehive.controls.api.bean.ControlBean cb, Method m, Object [] args ) {} 964 public void postInvoke( org.apache.beehive.controls.api.bean.ControlBean cb, Method m, Object [] args, Object retval, Throwable t) {} 965 public void preEvent( org.apache.beehive.controls.api.bean.ControlBean cb, Class eventSet, Method m, Object [] args) {} 966 public void postEvent( org.apache.beehive.controls.api.bean.ControlBean cb, Class eventSet, Method m, Object [] args ) {} 967 } 968 969 970 971 975 976 979 protected Class _implClass; 980 981 986 transient private ThreadingPolicy _threadingPolicy = ThreadingPolicy.MULTI_THREADED; 987 988 991 private BeanPropertyMap _properties; 992 993 994 995 996 997 1003 1004 1007 private Object _control; 1008 1009 1012 private ControlBeanContext _cbc; 1013 1014 1018 transient private ImplInitializer _implInitializer; 1019 1020 1024 transient private boolean _hasServices = false; 1025 1026 1031 transient private Semaphore _invokeLock; 1032 1033 1036 private PropertyChangeSupport _changeSupport; 1037 1038 1041 private VetoableChangeSupport _vetoSupport; 1042 1043 1044 1045 1048 private String _localID; 1049 1050 1053 private Class _controlIntf; 1054 1055 1061 private HashMap<Class , Object > _notifiers = new HashMap<Class ,Object >(); 1062 1063 1066 transient private Vector<InvokeListener> _invokeListeners; 1067 1068 1072 transient private HashMap<String ,Interceptor> _interceptors; 1073} 1074 | Popular Tags |