Source Code Cross Referenced for ControlBean.java in  » Library » Apache-beehive-1.0.2-src » org » apache » beehive » controls » runtime » bean » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache beehive 1.0.2 src » org.apache.beehive.controls.runtime.bean 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         *
0017:         * $Header:$
0018:         */
0019:        package org.apache.beehive.controls.runtime.bean;
0020:
0021:        import java.beans.beancontext.BeanContext;
0022:        import java.beans.beancontext.BeanContextServices;
0023:        import java.beans.PropertyChangeSupport;
0024:        import java.beans.VetoableChangeSupport;
0025:        import java.io.IOException;
0026:        import java.io.ObjectOutputStream;
0027:        import java.lang.reflect.AnnotatedElement;
0028:        import java.lang.reflect.InvocationTargetException;
0029:        import java.lang.reflect.Method;
0030:        import java.util.concurrent.Semaphore;
0031:        import java.util.ArrayList;
0032:        import java.util.HashMap;
0033:        import java.util.Iterator;
0034:        import java.util.List;
0035:        import java.util.Map;
0036:        import java.util.TooManyListenersException;
0037:        import java.util.Vector;
0038:
0039:        import org.apache.beehive.controls.api.ControlException;
0040:        import org.apache.beehive.controls.api.properties.BaseProperties;
0041:        import org.apache.beehive.controls.api.properties.AnnotatedElementMap;
0042:        import org.apache.beehive.controls.api.properties.PropertyMap;
0043:        import org.apache.beehive.controls.api.properties.BeanPropertyMap;
0044:        import org.apache.beehive.controls.api.properties.PropertyKey;
0045:        import org.apache.beehive.controls.api.properties.PropertySetProxy;
0046:        import org.apache.beehive.controls.api.versioning.VersionRequired;
0047:        import org.apache.beehive.controls.api.versioning.Version;
0048:        import org.apache.beehive.controls.api.bean.Threading;
0049:        import org.apache.beehive.controls.api.bean.ThreadingPolicy;
0050:        import org.apache.beehive.controls.api.bean.ControlImplementation;
0051:        import org.apache.beehive.controls.api.context.ControlThreadContext;
0052:        import org.apache.beehive.controls.api.events.EventRef;
0053:        import org.apache.beehive.controls.api.events.EventSet;
0054:        import org.apache.beehive.controls.spi.context.ControlBeanContextFactory;
0055:        import org.apache.beehive.controls.spi.svc.Interceptor;
0056:        import org.apache.beehive.controls.spi.svc.InterceptorPivotException;
0057:        import org.apache.commons.discovery.tools.DiscoverClass;
0058:
0059:        /**
0060:         * The ControlBean class is an abstract base class for the JavaBean classes generated to support
0061:         * Beehive Controls.
0062:         * <p>
0063:         * The ControlBean class indirectly implements BeanContextProxy; the
0064:         * {@link org.apache.beehive.controls.api.context.ControlBeanContext} that it contains/scopes acts as that proxy.
0065:         * <p>
0066:         * All support APIs (which may be called from derived subclasses or contextual services)
0067:         * are generally marked as protected and have names that start with an underscore.  This avoids the
0068:         * possibility that the name might conflict with a user-defined method on a control's public or
0069:         * extended Control interfaces.
0070:         * <p>
0071:         * NOTE: Adding public methods should be done with great care; any such method becomes part of the
0072:         * public API, and occupies the method namespace for all controls.
0073:         */
0074:        abstract public class ControlBean implements 
0075:                org.apache.beehive.controls.api.bean.ControlBean {
0076:            /**
0077:             *
0078:             * @param context        the containing ControlBeanContext.  May be null, in which case the bean will attempt to
0079:             *                       associate with an active context at runtime (via thread-locals).   
0080:             * @param id             the local ID for the control, scoped to the control bean context.
0081:             * @param initProperties a PropertyMap containing initial properties for the control
0082:             * @param controlIntf    the control interface or extension directly implemented by the control bean
0083:             */
0084:            protected ControlBean(
0085:                    org.apache.beehive.controls.api.context.ControlBeanContext context,
0086:                    String id, PropertyMap initProperties, Class controlIntf) {
0087:                super ();
0088:
0089:                _localID = id;
0090:                _controlIntf = controlIntf;
0091:
0092:                //
0093:                // If no containing context was specified during construction, see if there is a current
0094:                // active container context and implicitly associated the control with it.
0095:                //
0096:                if (context == null)
0097:                    context = ControlThreadContext.getContext();
0098:
0099:                ControlBeanContextFactory cbcFactory = lookupControlBeanContextFactory(context);
0100:                _cbc = cbcFactory.instantiate(this );
0101:
0102:                //
0103:                // Associate this bean with the context.  Beans may run without a context!
0104:                // Note that the add() call has the side-effect of calling ControlBean.setBeanContext(), which does
0105:                // additional setup work, so we make sure we always call that anyways!
0106:                //
0107:                if (context != null)
0108:                    context.add(this );
0109:                else
0110:                    setBeanContext(null);
0111:
0112:                //
0113:                // Get the default map for the control class.  This contains the default property
0114:                // values for all beans of the class.
0115:                //
0116:                PropertyMap classMap = getAnnotationMap(controlIntf);
0117:                if (initProperties != null) {
0118:                    //
0119:                    // If the initialization map derives its values from a Java annotated element,
0120:                    // then allow container overrides on this element to be applied.  This will also
0121:                    // coelesce maps referencing the same element.
0122:                    //
0123:                    AnnotatedElement annotElem = null;
0124:                    if (initProperties instanceof  AnnotatedElementMap) {
0125:                        annotElem = ((AnnotatedElementMap) initProperties)
0126:                                .getAnnotatedElement();
0127:                        initProperties = getAnnotationMap(annotElem);
0128:                    }
0129:
0130:                    //
0131:                    // If an initial property map was provided, set it to delegate to the default
0132:                    // map, and then create a wrapper map around it for storing per instance
0133:                    // properties.
0134:                    //
0135:                    if (annotElem != controlIntf)
0136:                        initProperties.setDelegateMap(classMap);
0137:                    _properties = new BeanPropertyMap(initProperties);
0138:                } else {
0139:                    //
0140:                    // If no initial map was provided, simply create an empty map wrapping the
0141:                    // control class default.
0142:                    //
0143:                    _properties = new BeanPropertyMap(classMap);
0144:                }
0145:
0146:            }
0147:
0148:            /**
0149:             * Configure this bean to be thread-safe given the threading settings of the impl class and
0150:             * the outer container.
0151:             */
0152:            private void ensureThreadingBehaviour() {
0153:                //
0154:                // If the implementation class requires a guarantee of single-threaded behavior and the
0155:                // outer container does not guarantee it, then enable invocation locking on this
0156:                // bean instance.
0157:                //
0158:                if (hasSingleThreadedImpl() && !_cbc.hasSingleThreadedParent())
0159:                    _invokeLock = new Semaphore(1, true);
0160:                else
0161:                    _invokeLock = null;
0162:            }
0163:
0164:            /**
0165:             * Return the BeanContextService proxy associated with this bean instance
0166:             */
0167:            final public ControlBeanContext getBeanContextProxy() {
0168:                return _cbc;
0169:            }
0170:
0171:            /**
0172:             * Returns the nesting BeanContext for this ControlBean.  This is thread-safe even though it
0173:             * is not synchronized.
0174:             */
0175:            final public BeanContext getBeanContext() {
0176:                //
0177:                // Indirect through the bean proxy for this control bean and up to its parent nesting
0178:                // context.  Both these calls (getBeanContextProxy() and getBeanContext()) are, and must
0179:                // remain, thread-safe.
0180:                //
0181:                return getBeanContextProxy().getBeanContext();
0182:            }
0183:
0184:            /**
0185:             * Called by the BeanContextProxy (_cbc) whenever the _parent_ context containing this control bean is
0186:             * changed.  This is the place to do any initialization (or reinitialization) that is dependent
0187:             * upon attributes of the container for the ControlBean.
0188:             *
0189:             * Note: this is called in the ControlBean ctor, when a parent context calls add() on the nascent
0190:             * bean.
0191:             *
0192:             * @param bc the new parent context containing this control bean (not _cbc)
0193:             */
0194:            final public synchronized void setBeanContext(BeanContext bc) {
0195:                ensureThreadingBehaviour();
0196:            }
0197:
0198:            /**
0199:             * Returns the control ID for this control
0200:             */
0201:            final public String getControlID() {
0202:                return _cbc.getControlID();
0203:            }
0204:
0205:            /**
0206:             * Returns the public interface for this control.
0207:             */
0208:            final public Class getControlInterface() {
0209:                return _controlIntf;
0210:            }
0211:
0212:            /**
0213:             * Returns true if the implementation class for this ControlBean requires the framework
0214:             * to ensure thread-safety for it.
0215:             */
0216:            /*package*/boolean hasSingleThreadedImpl() {
0217:                return _threadingPolicy == ThreadingPolicy.SINGLE_THREADED;
0218:            }
0219:
0220:            /**
0221:             * Obtains an instance of the appropriate ImplInitializer class
0222:             */
0223:            protected synchronized ImplInitializer getImplInitializer() {
0224:                if (_implInitializer == null) {
0225:                    try {
0226:                        Class initClass = _implClass
0227:                                .getClassLoader()
0228:                                .loadClass(_implClass.getName() + "Initializer");
0229:                        _implInitializer = (ImplInitializer) initClass
0230:                                .newInstance();
0231:                    } catch (Exception e) {
0232:                        throw new ControlException(
0233:                                "Control initialization failure", e);
0234:                    }
0235:                }
0236:                return _implInitializer;
0237:            }
0238:
0239:            /**
0240:             * Returns the target control instance associated with this ControlBean, performing lazy
0241:             * instantiation and initialization of the instance.
0242:             *
0243:             * REVIEW: could probably improve the granularity of locking here, but start w/ just
0244:             * synchronizing the entire fn.
0245:             */
0246:            public synchronized Object ensureControl() {
0247:                if (_control == null) {
0248:                    //
0249:                    // See if the property map specifies an implementation class for the control; 
0250:                    // if not, use default binding.
0251:                    //
0252:
0253:                    String implBinding = null;
0254:                    BaseProperties bp = _properties
0255:                            .getPropertySet(BaseProperties.class);
0256:                    if (bp != null)
0257:                        implBinding = bp.controlImplementation();
0258:                    else
0259:                        implBinding = ControlUtils
0260:                                .getDefaultControlBinding(_controlIntf);
0261:
0262:                    try {
0263:                        _implClass = _controlIntf.getClassLoader().loadClass(
0264:                                implBinding);
0265:
0266:                        //
0267:                        // Validate that the specified implementation class has an @ControlImplementation
0268:                        // annotation, else downstream requirements (such as having a valid control init
0269:                        // class) will not be met.
0270:                        //
0271:                        if (_implClass
0272:                                .getAnnotation(ControlImplementation.class) == null) {
0273:                            throw new ControlException(
0274:                                    "@"
0275:                                            + ControlImplementation.class
0276:                                                    .getName()
0277:                                            + " annotation is missing from control implementation class: "
0278:                                            + _implClass.getName());
0279:                        }
0280:                    } catch (ClassNotFoundException cnfe) {
0281:                        throw new ControlException(
0282:                                "Unable to load control implementation: "
0283:                                        + implBinding, cnfe);
0284:                    }
0285:
0286:                    //
0287:                    // Cache the threading policy associated with the impl
0288:                    //
0289:                    Threading thr = (Threading) _implClass
0290:                            .getAnnotation(Threading.class);
0291:                    if (thr != null)
0292:                        _threadingPolicy = thr.value();
0293:                    else
0294:                        _threadingPolicy = ThreadingPolicy.SINGLE_THREADED; // default to single-threaded
0295:
0296:                    ensureThreadingBehaviour();
0297:
0298:                    try {
0299:                        //
0300:                        // Create and initialize the new instance
0301:                        //
0302:                        _control = _implClass.newInstance();
0303:
0304:                        try {
0305:                            /*
0306:                            Run the ImplInitializer.  This class is code generated based on metadata from a control
0307:                            implementation.  If a Control implementation declares event handlers for the
0308:                            ControlBeanContext or for the ResourceContext, executing this code generated class
0309:                            will add the appropriate LifeCycle and / or Resource event listeners.
0310:                             */
0311:                            getImplInitializer().initialize(this , _control);
0312:                            _hasServices = true;
0313:                        } catch (Exception e) {
0314:                            throw new ControlException(
0315:                                    "Control initialization failure", e);
0316:                        }
0317:
0318:                        //
0319:                        // Once the control is initialized, then allow the associated context
0320:                        // to do any initialization.
0321:                        //
0322:                        ControlBeanContext cbcs = getBeanContextProxy();
0323:
0324:                        /*
0325:                        Implementation note: this call will run the LifeCycleListener(s) that have
0326:                        been wired-up to the ControlBeanContext object associated with this ControlBean.
0327:                         */
0328:                        cbcs.initializeControl();
0329:                    } catch (RuntimeException re) {
0330:                        // never mask RuntimeExceptions
0331:                        throw re;
0332:                    } catch (Exception e) {
0333:                        throw new ControlException(
0334:                                "Unable to create control instance", e);
0335:                    }
0336:                }
0337:
0338:                //
0339:                // If the implementation instance does not currently have contextual services, they
0340:                // are lazily restored here.
0341:                //
0342:                if (!_hasServices) {
0343:                    getImplInitializer().initServices(this , _control);
0344:                    _hasServices = true;
0345:                }
0346:
0347:                return _control;
0348:            }
0349:
0350:            /**
0351:             * Returns the implementation instance associated with this ControlBean.
0352:             */
0353:            /* package */Object getImplementation() {
0354:                return _control;
0355:            }
0356:
0357:            /**
0358:             * The preinvoke method is called before all operations on the control.  In addition to
0359:             * providing a basic hook for logging, context initialization, resource management, 
0360:             * and other common services, it also provides a hook for interceptors.
0361:             */
0362:            protected void preInvoke(Method m, Object[] args,
0363:                    String[] interceptorNames) throws InterceptorPivotException {
0364:                //
0365:                // If the implementation expects single threaded behavior and our container does
0366:                // not guarantee it, then enforce it locally here
0367:                //
0368:                if (_invokeLock != null) {
0369:                    try {
0370:                        _invokeLock.acquire();
0371:                    } catch (InterruptedException ie) {
0372:                    }
0373:                }
0374:
0375:                //
0376:                // Process interceptors
0377:                //
0378:                if (interceptorNames != null) {
0379:                    for (String n : interceptorNames) {
0380:                        Interceptor i = ensureInterceptor(n);
0381:                        try {
0382:                            i.preInvoke(this , m, args);
0383:                        } catch (InterceptorPivotException ipe) {
0384:                            ipe.setInterceptorName(n);
0385:                            throw ipe;
0386:                        }
0387:                    }
0388:                }
0389:
0390:                Vector<InvokeListener> invokeListeners = getInvokeListeners();
0391:                if (invokeListeners.size() > 0) {
0392:                    for (InvokeListener listener : invokeListeners)
0393:                        listener.preInvoke(m, args);
0394:                }
0395:            }
0396:
0397:            /**
0398:             * The preinvoke method is called before all operations on the control.  It is the basic
0399:             * hook for logging, context initialization, resource management, and other common
0400:             * services
0401:             */
0402:            protected void preInvoke(Method m, Object[] args) {
0403:                try {
0404:                    preInvoke(m, args, null);
0405:                } catch (InterceptorPivotException ipe) {
0406:                    //this will never happen because no interceptor is passed.
0407:                }
0408:            }
0409:
0410:            /**
0411:             * The postInvoke method is called after all operations on the control.  In addition to 
0412:             * providing the basic hook for logging, context initialization, resource management, and other common
0413:             * services, it also provides a hook for interceptors.  During preInvoke, interceptors will be 
0414:             * called in the order that they are in the list.  During postInvoke, they will be called in the
0415:             * reverse order.  Here is an example of the call sequence with I1, I2, and I3 being interceptors in the list:
0416:             * 
0417:             *   I1.preInvoke() -> I2.preInvoke() -> I3.preInvoke() -> invoke method
0418:             *                                                             |
0419:             *   I1.postInvoke() <- I2.postInvoke() <- I3.postInvoke() <--- 
0420:             * 
0421:             * In the event that an interceptor in the list pivoted during preInvoke, the "pivotedInterceptor"
0422:             * parameter indicates the interceptor that had pivoted, and the interceptors succeeding it in the list will
0423:             * not be called during postInvoke. 
0424:             */
0425:            protected void postInvoke(Method m, Object[] args, Object retval,
0426:                    Throwable t, String[] interceptorNames,
0427:                    String pivotedInterceptor) {
0428:                try {
0429:                    Vector<InvokeListener> invokeListeners = getInvokeListeners();
0430:                    if (invokeListeners.size() > 0) {
0431:                        for (InvokeListener listener : invokeListeners)
0432:                            listener.postInvoke(retval, t);
0433:                    }
0434:
0435:                    //
0436:                    // Process interceptors
0437:                    //
0438:                    if (interceptorNames != null) {
0439:                        for (int cnt = interceptorNames.length - 1; cnt >= 0; cnt--) {
0440:                            String n = interceptorNames[cnt];
0441:                            if (pivotedInterceptor == null
0442:                                    || n.equals(pivotedInterceptor)) {
0443:                                pivotedInterceptor = null;
0444:                                Interceptor i = ensureInterceptor(n);
0445:                                i.postInvoke(this , m, args, retval, t);
0446:                            }
0447:                        }
0448:                    }
0449:                } finally {
0450:                    //
0451:                    // Release any lock obtained above in preInvoke
0452:                    //
0453:                    if (_invokeLock != null)
0454:                        _invokeLock.release();
0455:                }
0456:            }
0457:
0458:            /**
0459:             * The postInvoke method is called after all operations on the control.  It is the basic
0460:             * hook for logging, context initialization, resource management, and other common
0461:             * services.
0462:             */
0463:            protected void postInvoke(Method m, Object[] args, Object retval,
0464:                    Throwable t) {
0465:                postInvoke(m, args, retval, t, null, null);
0466:            }
0467:
0468:            /**
0469:             * Sets the EventNotifier for this ControlBean
0470:             */
0471:            protected <T> void setEventNotifier(Class<T> eventSet, T notifier) {
0472:                _notifiers.put(eventSet, notifier);
0473:
0474:                //
0475:                // Register this notifier for all EventSet interfaces up the interface inheritance
0476:                // hiearachy as well
0477:                //
0478:                List<Class> super EventSets = new ArrayList<Class>();
0479:                getSuperEventSets(eventSet, super EventSets);
0480:                Iterator<Class> i = super EventSets.iterator();
0481:                while (i.hasNext()) {
0482:                    Class super EventSet = i.next();
0483:                    _notifiers.put(super EventSet, notifier);
0484:                }
0485:            }
0486:
0487:            /**
0488:             * Finds all of the EventSets extended by the input EventSet, and adds them to
0489:             * the provided list. 
0490:             * @param eventSet
0491:             * @param superEventSets
0492:             */
0493:            private void getSuperEventSets(Class eventSet,
0494:                    List<Class> super EventSets) {
0495:                Class[] super Interfaces = eventSet.getInterfaces();
0496:                if (super Interfaces != null) {
0497:                    for (int i = 0; i < super Interfaces.length; i++) {
0498:                        Class super Interface = super Interfaces[i];
0499:                        if (super Interface.isAnnotationPresent(EventSet.class)) {
0500:                            super EventSets.add(super Interface);
0501:
0502:                            // Continue traversing up the EventSet inheritance hierarchy
0503:                            getSuperEventSets(super Interface, super EventSets);
0504:                        }
0505:                    }
0506:                }
0507:            }
0508:
0509:            /**
0510:             * Returns an EventNotifier/UnicastEventNotifier for this ControlBean for the target event set
0511:             */
0512:            protected <T> T getEventNotifier(Class<T> eventSet) {
0513:                return (T) _notifiers.get(eventSet);
0514:            }
0515:
0516:            /**
0517:             * Returns the list of InvokeListeners for this ControlBean
0518:             */
0519:            /* package */Vector<InvokeListener> getInvokeListeners() {
0520:                if (_invokeListeners == null)
0521:                    _invokeListeners = new Vector<InvokeListener>();
0522:                return _invokeListeners;
0523:            }
0524:
0525:            /**
0526:             * Registers a new InvokeListener for this ControlBean.
0527:             */
0528:            /* package */void addInvokeListener(InvokeListener invokeListener) {
0529:                getInvokeListeners().addElement(invokeListener);
0530:            }
0531:
0532:            /**
0533:             * Deregisters an existing InvokeListener for this ControlBean.
0534:             */
0535:            /* package */void removeInvokeListener(
0536:                    InvokeListener invokeListener) {
0537:                getInvokeListeners().removeElement(invokeListener);
0538:            }
0539:
0540:            /**
0541:             * Returns the local (parent-relative) ID for this ControlBean
0542:             */
0543:            protected String getLocalID() {
0544:                return _localID;
0545:            }
0546:
0547:            /**
0548:             * Set the local (parent-relative) ID for this ControlBean.  It has package access because
0549:             * the local ID should only be set from within the associated context, and only when the
0550:             * bean is currently anonymous (hence the assertion below)
0551:             */
0552:            /* package */void setLocalID(String localID) {
0553:                assert _localID == null; // should only set if not already set!
0554:                _localID = localID;
0555:            }
0556:
0557:            /**
0558:             * Returns the bean context instance associated with the this bean, as opposed to the
0559:             * parent context returned by the public getBeanContext() API.
0560:             */
0561:            public ControlBeanContext getControlBeanContext() {
0562:                //
0563:                // The peer context instance is the context provider for this ControlBean
0564:                //
0565:                return getBeanContextProxy();
0566:            }
0567:
0568:            /**
0569:             * Locates and obtains a context service from the BeanContextServices instance
0570:             * supporting this bean.
0571:             *
0572:             * The base design for the BeanContextServicesSupport is that it will delegate up to peers
0573:             * in a nesting context, so a nested control bean will look 'up' to find a service provider.
0574:             */
0575:            protected Object getControlService(Class serviceClass,
0576:                    Object selector) throws TooManyListenersException
0577:
0578:            {
0579:                //
0580:                // Get the associated context object, then use it to locate the (parent) bean context.
0581:                // Services are always provided by the parent context.
0582:                //
0583:                ControlBeanContext cbc = getControlBeanContext();
0584:                BeanContext bc = cbc.getBeanContext();
0585:                if (bc == null || !(bc instanceof  BeanContextServices))
0586:                    throw new ControlException("Can't locate service context: "
0587:                            + bc);
0588:
0589:                //
0590:                // Call getService on the parent context, using this bean as the requestor and the
0591:                // associated peer context instance as the child and event listener parameters.
0592:                //
0593:                return ((BeanContextServices) bc).getService(cbc, this ,
0594:                        serviceClass, selector, cbc);
0595:            }
0596:
0597:            /**
0598:             * Sets a property on the ControlBean instance.  All generated property setter methods
0599:             * will delegate down to this method.
0600:             */
0601:            protected void setControlProperty(PropertyKey key, Object o) {
0602:                AnnotationConstraintValidator.validate(key, o);
0603:                _properties.setProperty(key, o);
0604:            }
0605:
0606:            /**
0607:             * Dispatches the requested operation event on the ControlBean.
0608:             * @see org.apache.beehive.controls.runtime.bean.ControlContainerContext#dispatchEvent
0609:             */
0610:            /* package */Object dispatchEvent(EventRef event, Object[] args)
0611:                    throws IllegalAccessException, IllegalArgumentException,
0612:                    InvocationTargetException {
0613:                ensureControl();
0614:
0615:                //
0616:                // Translate the EventRef back to an actual event method on the ControlInterface
0617:                //
0618:                Class controlInterface = getControlInterface();
0619:                Method method = event.getEventMethod(controlInterface);
0620:
0621:                //
0622:                // Locate the target of the event
0623:                //
0624:                Object eventTarget = null;
0625:                if (method.getDeclaringClass().isAssignableFrom(
0626:                        _control.getClass())) {
0627:                    //
0628:                    // If the control implementation implements that EventSet interface, then 
0629:                    // dispatch the event directly to it, and allow it do make the decision about 
0630:                    // how/when to dispatch to any external listeners (via a @Client notifier 
0631:                    // instance)
0632:                    //
0633:                    eventTarget = _control;
0634:                } else {
0635:                    //
0636:                    // The associated control implementation does not directly handle the event,
0637:                    // so find the event notifier instance for the EventSet interface associated 
0638:                    // with the method.
0639:                    //
0640:                    eventTarget = _notifiers.get(method.getDeclaringClass());
0641:                    if (eventTarget == null)
0642:                        throw new IllegalArgumentException(
0643:                                "No event notifier found for " + event);
0644:                }
0645:
0646:                //
0647:                // Dispatch the event
0648:                //
0649:                return method.invoke(eventTarget, args);
0650:            }
0651:
0652:            /**
0653:             * Returns a property on the ControlBean instance.   This version does not coerce
0654:             * an annotation type property from a PropertyMap to a proxy instance of the
0655:             * type.
0656:             */
0657:            protected Object getRawControlProperty(PropertyKey key) {
0658:                return _properties.getProperty(key);
0659:            }
0660:
0661:            /**
0662:             * Returns a property on the ControlBean instance.  All generated property getter methods
0663:             * will delegate down to this method
0664:             */
0665:            protected Object getControlProperty(PropertyKey key) {
0666:                Object value = getRawControlProperty(key);
0667:
0668:                // If the held value is a PropertyMap, then wrap it in an annotation proxy of
0669:                // the expected type.
0670:                if (value instanceof  PropertyMap) {
0671:                    PropertyMap map = (PropertyMap) value;
0672:                    value = PropertySetProxy.getProxy(map.getMapClass(), map);
0673:                }
0674:
0675:                return value;
0676:            }
0677:
0678:            /* this method is implemented during code generation by a ControlBean extension */
0679:            /**
0680:             * Returns the local cache for ControlBean property maps.
0681:             */
0682:            abstract protected Map getPropertyMapCache();
0683:
0684:            /**
0685:             * Returns the PropertyMap containing values associated with an AnnotatedElement.  Elements
0686:             * that are associated with the bean's Control interface will be locally cached.
0687:             */
0688:            protected PropertyMap getAnnotationMap(AnnotatedElement annotElem) {
0689:                Map annotCache = getPropertyMapCache();
0690:
0691:                // If in the cache already , just return it
0692:                if (annotCache.containsKey(annotElem))
0693:                    return (PropertyMap) annotCache.get(annotElem);
0694:
0695:                //
0696:                // Ask the associated ControlBeanContext to locate and initialize a PropertyMap, then
0697:                // store it in the local cache.
0698:                //
0699:                PropertyMap map = getControlBeanContext().getAnnotationMap(
0700:                        annotElem);
0701:                annotCache.put(annotElem, map);
0702:
0703:                return map;
0704:            }
0705:
0706:            /**
0707:             * Returns the property map containing the properties for the bean
0708:             */
0709:            /* package */BeanPropertyMap getPropertyMap() {
0710:                return _properties;
0711:            }
0712:
0713:            /**
0714:             * This protected version is only available to concrete subclasses that expose bound
0715:             * property support.   This method is synchronized to enable lazy instantiation, in
0716:             * the belief that it is a bigger win to avoid allocating when there are no listeners
0717:             * than it is to introduce synchronization overhead on access.
0718:             */
0719:            synchronized protected PropertyChangeSupport getPropertyChangeSupport() {
0720:                if (_changeSupport == null)
0721:                    _changeSupport = new PropertyChangeSupport(this );
0722:
0723:                return _changeSupport;
0724:            }
0725:
0726:            /**
0727:             * Delivers a PropertyChangeEvent to any registered PropertyChangeListeners associated
0728:             * with the property referenced by the specified key.
0729:             *
0730:             * This method *should not* be synchronized, as the PropertyChangeSupport has its own
0731:             * built in synchronization mechanisms.
0732:             */
0733:            protected void firePropertyChange(PropertyKey propertyKey,
0734:                    Object oldValue, Object newValue) {
0735:                // No change support instance means no listeners
0736:                if (_changeSupport == null)
0737:                    return;
0738:
0739:                _changeSupport.firePropertyChange(
0740:                        propertyKey.getPropertyName(), oldValue, newValue);
0741:            }
0742:
0743:            /**
0744:             * This protected version is only available to concrete subclasses that expose bound
0745:             * property support.   This method is synchronized to enable lazy instantiation, in
0746:             * the belief that is a bigger win to avoid allocating when there are no listeners
0747:             * than it is to introduce synchronization overhead on access.
0748:             */
0749:            synchronized protected VetoableChangeSupport getVetoableChangeSupport() {
0750:                if (_vetoSupport == null)
0751:                    _vetoSupport = new VetoableChangeSupport(this );
0752:
0753:                return _vetoSupport;
0754:            }
0755:
0756:            /**
0757:             * Delivers a PropertyChangeEvent to any registered VetoableChangeListeners associated
0758:             * with the property referenced by the specified key.
0759:             *
0760:             * This method *should not* be synchronized, as the VetoableChangeSupport has its own
0761:             * built in synchronization mechanisms.
0762:             */
0763:            protected void fireVetoableChange(PropertyKey propertyKey,
0764:                    Object oldValue, Object newValue)
0765:                    throws java.beans.PropertyVetoException {
0766:                // No veto support instance means no listeners
0767:                if (_vetoSupport == null)
0768:                    return;
0769:
0770:                _vetoSupport.fireVetoableChange(propertyKey.getPropertyName(),
0771:                        oldValue, newValue);
0772:            }
0773:
0774:            /**
0775:             * Returns the parameter names for a method on the ControlBean.  Actual mapping is done
0776:             * by generated subclasses, so if we reach the base ControlBean implementation, then
0777:             * no parameter names are available for the target method.
0778:             */
0779:            protected String[] getParameterNames(Method m) {
0780:                throw new IllegalArgumentException(
0781:                        "No parameter name data for " + m);
0782:            }
0783:
0784:            /**
0785:             * Computes the most derived ControlInterface for the specified ControlExtension.
0786:             * @param controlIntf
0787:             * @return the most derived ControlInterface
0788:             * @deprecated Use {@link ControlUtils#getMostDerivedInterface(Class)} instead.  This method will
0789:             *             be removed in the next release.
0790:             */
0791:            public static Class getMostDerivedInterface(Class controlIntf) {
0792:                return ControlUtils.getMostDerivedInterface(controlIntf);
0793:            }
0794:
0795:            /**
0796:             * Enforces the VersionRequired annotation at runtime (called from each ControlBean).
0797:             * @param intfName
0798:             * @param version
0799:             * @param versionRequired
0800:             */
0801:            protected static void enforceVersionRequired(String intfName,
0802:                    Version version, VersionRequired versionRequired) {
0803:                if (versionRequired != null) {
0804:                    int majorRequired = versionRequired.major();
0805:                    int minorRequired = versionRequired.minor();
0806:
0807:                    if (majorRequired < 0) // no real version requirement
0808:                        return;
0809:
0810:                    int majorPresent = -1;
0811:                    int minorPresent = -1;
0812:                    if (version != null) {
0813:                        majorPresent = version.major();
0814:                        minorPresent = version.minor();
0815:
0816:                        if (majorRequired <= majorPresent
0817:                                && (minorRequired < 0 || minorRequired <= minorPresent)) {
0818:                            // Version requirement is satisfied
0819:                            return;
0820:                        }
0821:                    }
0822:
0823:                    //
0824:                    // Version requirement failed
0825:                    //
0826:                    throw new ControlException(
0827:                            "Control extension "
0828:                                    + intfName
0829:                                    + " fails version requirement: requires interface version "
0830:                                    + majorRequired + "." + minorRequired
0831:                                    + ", found interface version "
0832:                                    + majorPresent + "." + minorPresent + ".");
0833:                }
0834:            }
0835:
0836:            /**
0837:             * Implementation of the Java serialization writeObject method
0838:             */
0839:            private synchronized void writeObject(ObjectOutputStream oos)
0840:                    throws IOException {
0841:                if (_control != null) {
0842:                    //
0843:                    // If the implementation class is marked as transient/stateless, then reset the
0844:                    // reference to it prior to serialization.  A new instance will be created by
0845:                    // ensureControl() upon first use after deserialization.
0846:                    // If the implementation class is not transient, then invoke the ImplInitializer
0847:                    // resetServices method to reset all contextual service references to null, as
0848:                    // contextual services should never be serializated and always reassociated on 
0849:                    // deserialization.
0850:                    //
0851:                    ControlImplementation implAnnot = (ControlImplementation) _implClass
0852:                            .getAnnotation(ControlImplementation.class);
0853:                    assert implAnnot != null;
0854:                    if (implAnnot.isTransient()) {
0855:                        _control = null;
0856:                    } else {
0857:                        getImplInitializer().resetServices(this , _control);
0858:                        _hasServices = false;
0859:                    }
0860:                }
0861:
0862:                oos.defaultWriteObject();
0863:            }
0864:
0865:            /**
0866:             * Called during XMLDecoder reconstruction of a ControlBean.
0867:             */
0868:            public void decodeImpl(Object impl) {
0869:                if (impl != _control)
0870:                    throw new ControlException("Cannot change implementation");
0871:            }
0872:
0873:            /**
0874:             * Internal method used to lookup a ControlBeanContextFactory.  This factory is used to create the
0875:             * ControlBeanContext object for this ControlBean.  The factory is discoverable from either the containing
0876:             * ControlBeanContext object or from the environment.  If the containing CBC object exposes a
0877:             * contextual service of type {@link ControlBeanContextFactory}, the factory returned from this will
0878:             * be used to create a ControlBeanContext object.
0879:             *
0880:             * @param context
0881:             * @return the ControlBeanContextFactory discovered in the environment or a default one if no factory is configured
0882:             */
0883:            private ControlBeanContextFactory lookupControlBeanContextFactory(
0884:                    org.apache.beehive.controls.api.context.ControlBeanContext context) {
0885:
0886:                // first, try to find the CBCFactory from the container
0887:                if (context != null) {
0888:                    ControlBeanContextFactory cbcFactory = context.getService(
0889:                            ControlBeanContextFactory.class, null);
0890:
0891:                    if (cbcFactory != null) {
0892:                        return cbcFactory;
0893:                    }
0894:                }
0895:
0896:                // Create the context that acts as the BeanContextProxy for this bean (the context that this bean _defines_).
0897:                try {
0898:                    DiscoverClass discoverer = new DiscoverClass();
0899:                    Class factoryClass = discoverer.find(
0900:                            ControlBeanContextFactory.class,
0901:                            DefaultControlBeanContextFactory.class.getName());
0902:
0903:                    return (ControlBeanContextFactory) factoryClass
0904:                            .newInstance();
0905:                } catch (Exception e) {
0906:                    throw new ControlException(
0907:                            "Exception creating ControlBeanContext", e);
0908:                }
0909:            }
0910:
0911:            /**
0912:             * Retrieves interceptor instances, creates them lazily.
0913:             */
0914:            protected Interceptor ensureInterceptor(String n) {
0915:                Interceptor i = null;
0916:                if (_interceptors == null) {
0917:                    _interceptors = new HashMap<String, Interceptor>();
0918:                } else {
0919:                    i = _interceptors.get(n);
0920:                }
0921:
0922:                if (i == null) {
0923:                    try {
0924:                        i = (Interceptor) getControlService(
0925:                                getControlBeanContext().getClassLoader()
0926:                                        .loadClass(n), null);
0927:                    } catch (Exception e) {
0928:                        // Couldn't instantiate the desired service; usually this is because the service interface itself
0929:                        // isn't present on this system at runtime (ClassNotFoundException), or if the container of the
0930:                        // control didn't registers the service.
0931:
0932:                        /* TODO log a message here to that effect, but just swallow the exception for now. */
0933:                    } finally {
0934:                        // We want to always return an interceptor, so if we can't get the one we want, we'll substitute
0935:                        // a "null" interceptor that does nothing.
0936:                        if (i == null)
0937:                            i = new NullInterceptor();
0938:
0939:                        _interceptors.put(n, i);
0940:                    }
0941:                }
0942:                return i;
0943:            }
0944:
0945:            /**
0946:             * The "null" interceptor that does nothing.  Used when a specific interceptor
0947:             * is unavailable at runtime.
0948:             */
0949:            static private class NullInterceptor implements  Interceptor {
0950:                public void preInvoke(
0951:                        org.apache.beehive.controls.api.bean.ControlBean cb,
0952:                        Method m, Object[] args) {
0953:                }
0954:
0955:                public void postInvoke(
0956:                        org.apache.beehive.controls.api.bean.ControlBean cb,
0957:                        Method m, Object[] args, Object retval, Throwable t) {
0958:                }
0959:
0960:                public void preEvent(
0961:                        org.apache.beehive.controls.api.bean.ControlBean cb,
0962:                        Class eventSet, Method m, Object[] args) {
0963:                }
0964:
0965:                public void postEvent(
0966:                        org.apache.beehive.controls.api.bean.ControlBean cb,
0967:                        Class eventSet, Method m, Object[] args, Object retval,
0968:                        Throwable t) {
0969:                }
0970:            }
0971:
0972:            /** BEGIN unsynchronized fields */
0973:
0974:            /**
0975:             * The following fields are initialized in the constructor and never subsequently changed,
0976:             * so they are safe for unsynchronized read access
0977:             */
0978:
0979:            /**
0980:             * The control implementation class bound to this ControlBean
0981:             */
0982:            protected Class _implClass;
0983:
0984:            /**
0985:             * The threading policy associated with the control implementation wrapped by this
0986:             * ControlBean.  Initialized to MULTI_THREADED in order to assume multi-threadedness
0987:             * until a bean is associated with a specific (potentially single-threaded) implementation.
0988:             */
0989:            transient private ThreadingPolicy _threadingPolicy = ThreadingPolicy.MULTI_THREADED;
0990:
0991:            /**
0992:             *  Contains the per-instance properties set for this ControlBean.
0993:             */
0994:            private BeanPropertyMap _properties;
0995:
0996:            /** END unsynchronized fields */
0997:
0998:            /* BEGIN synchronized fields */
0999:
1000:            /*
1001:             * The following fields must be:
1002:             * 1) only written in synchronized methods or (unsynchronized) constructors
1003:             * 2) only read in synchronized methods or methods that are safe wrt the values changing during
1004:             *    execution.
1005:             */
1006:
1007:            /**
1008:             * The control implementation instance wrapped by this ControlBean
1009:             */
1010:            private Object _control;
1011:
1012:            /**
1013:             * The control bean context instance associated with this ControlBean
1014:             */
1015:            private ControlBeanContext _cbc;
1016:
1017:            /**
1018:             * An ImplInitializer instances used to initialize/reset the state of the associated
1019:             * implementation instance.
1020:             */
1021:            transient private ImplInitializer _implInitializer;
1022:
1023:            /**
1024:             * Indicates whether the contextual services associated with the bean have been
1025:             * fully initialized.
1026:             */
1027:            transient private boolean _hasServices = false;
1028:
1029:            /**
1030:             * Used to guarantee single threaded invocation when required.  If the
1031:             * outer container provides the guarantee or the implementation itself
1032:             * is threadsafe, then the value will be null.
1033:             */
1034:            transient private Semaphore _invokeLock;
1035:
1036:            /**
1037:             * This field manages PropertyChangeListeners (if supporting bound properties).
1038:             */
1039:            private PropertyChangeSupport _changeSupport;
1040:
1041:            /**
1042:             * This field manages VetoabbleChangeListeners (if supporting constrained properties)
1043:             */
1044:            private VetoableChangeSupport _vetoSupport;
1045:
1046:            /** END synchronized fields */
1047:
1048:            /**
1049:             * The (context relative) control ID associated with this instance
1050:             */
1051:            private String _localID;
1052:
1053:            /**
1054:             * The public control interface associated with this ControlBean
1055:             */
1056:            private Class _controlIntf;
1057:
1058:            /**
1059:             * This field manages the register listener list(s) associated with event set interfaces
1060:             * for the ControlBean.  The value objects are either UnicastEventNotifier or EventNotifier
1061:             * instances, depending upon whether the associated EventSet interface is unicast or
1062:             * multicast.
1063:             */
1064:            private HashMap<Class, Object> _notifiers = new HashMap<Class, Object>();
1065:
1066:            /**
1067:             * Maintains the list of callback event listeners (if any) for this ControlBean.
1068:             */
1069:            transient private Vector<InvokeListener> _invokeListeners;
1070:
1071:            /**
1072:             * HashMap to hold interceptor impl instances.
1073:             * Populated lazily.  Maps interceptor interface name to impl.
1074:             */
1075:            transient private HashMap<String, Interceptor> _interceptors;
1076:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.