Author: kentam Date: Tue Dec 14 13:57:58 2004 New Revision: 111882 URL: http://svn.apache.org/viewcvs?view=rev&rev=111882 Log: Implemented org.apache.beehive.controls.api.bean.Controls API with helper methods for programmatic and declarative instantiation of controls. See composition/ProgrammaticTest.java and OuterControlImpl.jcs for example usage.
This fixes: http://nagoya.apache.org/jira/browse/BEEHIVE-112 http://nagoya.apache.org/jira/browse/BEEHIVE-113 Also modified performance test to explicitly specify multi-threaded behaviour. DRT: windows Added: incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/bean/Controls.java (contents, props changed) Modified: incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/properties/BaseMap.java incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java incubator/beehive/trunk/controls/test/perf/ctlsrc/org/apache/beehive/controls/perf/controls/custom/StrlenControlImpl.java incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/composition/OuterControlImpl.jcs incubator/beehive/trunk/controls/test/src/units/org/apache/beehive/controls/test/java/composition/ProgrammaticTest.java Added: incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/bean/Controls.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/bean/Controls.java?view=auto&rev=111882 ============================================================================== --- (empty file) +++ incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/bean/Controls.java Tue Dec 14 13:57:58 2004 @@ -0,0 +1,129 @@ +package org.apache.beehive.controls.api.bean; +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Header:$ + */ + +import org.apache.beehive.controls.api.properties.PropertyMap; +import org.apache.beehive.controls.api.context.ControlBeanContext; +import org.apache.beehive.controls.api.ControlException; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +/** + * Helper class for using controls. + */ +public class Controls +{ + /** + * Factory method for instantiating controls. Controls instantiated using this method will be associated with the + * current thread-local ControlBeanContext (possibly none), and have an auto-generated ID. + * + * @param cl the classloader used to load the ControlBean. If null, the system classloader will be used. + * @param beanName the fully qualified name of the ControlBean class. + * @param props an optional PropertyMap containing initial property values for the control. May be null. + * @return an instance of the specified ControlBean. + * @throws ClassNotFoundException + */ + public static Object instantiate( ClassLoader cl, + String beanName, + PropertyMap props ) + throws ClassNotFoundException + { + return instantiate( cl, beanName, props, null, null ); + } + + /** + * Factory method for instantiating controls. + * + * @param cl the classloader used to load the ControlBean. If null, the system classloader will be used. + * @param beanName the fully qualified name of the ControlBean class. + * @param props an optional PropertyMap containing initial property values for the control. May be null. + * @param cbc the ControlBeanContext that will nest the created control. If null, the thread-local context + * (possibly none) will be used. + * @param id a unique ID for the created control. If null, an ID will be auto-generated. + * @return an instance of the specified ControlBean. + * @throws ClassNotFoundException + */ + public static Object instantiate( ClassLoader cl, + String beanName, + PropertyMap props, + ControlBeanContext cbc, + String id ) + throws ClassNotFoundException + { + Class beanClass = beanClass = ( cl == null ) ? Class.forName( beanName ) : cl.loadClass( beanName ); + + Object ret = null; + try + { + Constructor ctor = beanClass.getConstructor( ControlBeanContext.class, String.class, PropertyMap.class ); + ret = ctor.newInstance( cbc, id, props ); + } + catch ( InvocationTargetException ite ) + { + Throwable t = ite.getCause(); + throw new ControlException( "ControlBean constructor exception: " + t.getClass().getName() + ", " + + t.getMessage() ); + } + catch ( Exception e ) + { + throw new ControlException( "Exception creating ControlBean: " + e.getClass().getName() + ", " + + e.getMessage() ); + } + + return ret; + } + + /** + * Helper method for initializing instances of declarative control clients (objects that use controls via @Control + * and @EventHandler annotations). This method runs the client-specific generated ClientInitializer class to do + * its initialization work. + * + * @param cl the classloader used to load the ClientInitializer. If null, defaults to the classloader used to + * load the client object being initialized. + * @param client the client object being initialized. + * @param cbc the ControlBeanContext to be associated with the client object (that will nest the controls the client + * defines). If null, the thread-local context (possibly none) will be used. + * @throws ControlException + * @throws ClassNotFoundException + */ + public static void initializeClient( ClassLoader cl, Object client, ControlBeanContext cbc ) + throws ClassNotFoundException + { + Class clientClass = client.getClass(); + String clientName = clientClass.getName(); + + if ( cl == null ) + cl = clientClass.getClassLoader(); + + String initName = clientName + "ClientInitializer"; + Class initClass = cl.loadClass( initName ); + + try + { + Method m = initClass.getMethod( "initialize", ControlBeanContext.class, clientClass ); + m.invoke(null, cbc, client ); + } + catch ( Exception e ) + { + throw new ControlException( "Exception trying to run client initializer: " + e.getClass().getName() + ", " + + e.getMessage() ); + } + } +} Modified: incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/properties/BaseMap.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/properties/BaseMap.java?view=diff&rev=111882&p1=incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/properties/BaseMap.java&r1=111881&p2=incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/properties/BaseMap.java&r2=111882 ============================================================================== --- incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/properties/BaseMap.java (original) +++ incubator/beehive/trunk/controls/src/api/org/apache/beehive/controls/api/properties/BaseMap.java Tue Dec 14 13:57:58 2004 @@ -18,13 +18,6 @@ */ import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; - import org.apache.beehive.controls.api.bean.ControlBean; import org.apache.beehive.controls.api.bean.ControlExtension; @@ -99,7 +92,21 @@ { Class declaringClass = checkClass.getDeclaringClass(); if (declaringClass != null && - checkClass.getDeclaringClass().isAssignableFrom(_mapClass)) + declaringClass.isAssignableFrom(_mapClass)) + return true; + } + + // + // If the map class is a property set declared by the check class or a super interface + // of the check class, then they are compatible. This is the inverse of the last check, + // and happens e.g. when a programatically instantiated control w/ an initial property + // map needs to delegate to the control interface's property map. + // + if (_mapClass.isAnnotationPresent(PropertySet.class)) + { + Class declaringClass = _mapClass.getDeclaringClass(); + if (declaringClass != null && + declaringClass.isAssignableFrom(checkClass)) return true; } Modified: incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java?view=diff&rev=111882&p1=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java&r1=111881&p2=incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java&r2=111882 ============================================================================== --- incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java (original) +++ incubator/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/ControlBean.java Tue Dec 14 13:57:58 2004 @@ -105,10 +105,12 @@ // // Associate this bean with the context. Beans may run without a context! // Note that the add() call has the side-effect of calling ControlBean.setBeanContext(), which does - // additional setup work! + // additional setup work, so we make sure we always call that anyways! // if (context != null) context.add(this); + else + setBeanContext(null); // // Get the default map for the control class. This contains the default property Modified: incubator/beehive/trunk/controls/test/perf/ctlsrc/org/apache/beehive/controls/perf/controls/custom/StrlenControlImpl.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/perf/ctlsrc/org/apache/beehive/controls/perf/controls/custom/StrlenControlImpl.java?view=diff&rev=111882&p1=incubator/beehive/trunk/controls/test/perf/ctlsrc/org/apache/beehive/controls/perf/controls/custom/StrlenControlImpl.java&r1=111881&p2=incubator/beehive/trunk/controls/test/perf/ctlsrc/org/apache/beehive/controls/perf/controls/custom/StrlenControlImpl.java&r2=111882 ============================================================================== --- incubator/beehive/trunk/controls/test/perf/ctlsrc/org/apache/beehive/controls/perf/controls/custom/StrlenControlImpl.java (original) +++ incubator/beehive/trunk/controls/test/perf/ctlsrc/org/apache/beehive/controls/perf/controls/custom/StrlenControlImpl.java Tue Dec 14 13:57:58 2004 @@ -1,8 +1,11 @@ package org.apache.beehive.controls.perf.controls.custom; import org.apache.beehive.controls.api.bean.ControlImplementation; +import org.apache.beehive.controls.api.bean.Threading; +import org.apache.beehive.controls.api.bean.ThreadingPolicy; @ControlImplementation [EMAIL PROTECTED](ThreadingPolicy.MULTI_THREADED) public class StrlenControlImpl implements StrlenControl { public int stringLength(String input){ return input.length();} Modified: incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/composition/OuterControlImpl.jcs Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/composition/OuterControlImpl.jcs?view=diff&rev=111882&p1=incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/composition/OuterControlImpl.jcs&r1=111881&p2=incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/composition/OuterControlImpl.jcs&r2=111882 ============================================================================== --- incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/composition/OuterControlImpl.jcs (original) +++ incubator/beehive/trunk/controls/test/src/controls/org/apache/beehive/controls/test/controls/composition/OuterControlImpl.jcs Tue Dec 14 13:57:58 2004 @@ -6,6 +6,8 @@ import org.apache.beehive.controls.api.context.ControlBeanContext; import org.apache.beehive.controls.api.events.Client; import org.apache.beehive.controls.api.events.EventHandler; +import org.apache.beehive.controls.api.properties.PropertyMap; +import org.apache.beehive.controls.api.properties.BeanPropertyMap; import org.apache.beehive.controls.test.controls.composition.InnerControlBean; @@ -106,21 +108,36 @@ return innerControl2; } - public InnerControlBean instantiateNestedControlProgrammatically(){ - try{ + public InnerControlBean instantiateNestedControlProgrammatically() + { + try + { InnerControlBean inner=(InnerControlBean)java.beans.Beans.instantiate( - Thread.currentThread().getContextClassLoader() , - "org.apache.beehive.controls.test.controls.composition.InnerControlBean"); - return inner; - } - catch(Exception e){ - return null; - } + Thread.currentThread().getContextClassLoader(), + "org.apache.beehive.controls.test.controls.composition.InnerControlBean"); + return inner; + } + catch ( Exception e ) + { + return null; + } } public InnerControlBean instantiateNestedControlWithProperty(){ - /*BUG:CR190302*/ - return null; + try + { + BeanPropertyMap props = new BeanPropertyMap(InnerControl.Identity.class); + props.setProperty( InnerControlBean.NameKey, "ken" ); + props.setProperty( InnerControlBean.JobKey, "engineer"); + InnerControlBean inner=(InnerControlBean)org.apache.beehive.controls.api.bean.Controls.instantiate( + Thread.currentThread().getContextClassLoader(), + "org.apache.beehive.controls.test.controls.composition.InnerControlBean", props); + return inner; + } + catch(Exception e) + { + throw new RuntimeException("Failed to instantiate nested control", e); + } } public String testActivityWakeup(){ Modified: incubator/beehive/trunk/controls/test/src/units/org/apache/beehive/controls/test/java/composition/ProgrammaticTest.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/src/units/org/apache/beehive/controls/test/java/composition/ProgrammaticTest.java?view=diff&rev=111882&p1=incubator/beehive/trunk/controls/test/src/units/org/apache/beehive/controls/test/java/composition/ProgrammaticTest.java&r1=111881&p2=incubator/beehive/trunk/controls/test/src/units/org/apache/beehive/controls/test/java/composition/ProgrammaticTest.java&r2=111882 ============================================================================== --- incubator/beehive/trunk/controls/test/src/units/org/apache/beehive/controls/test/java/composition/ProgrammaticTest.java (original) +++ incubator/beehive/trunk/controls/test/src/units/org/apache/beehive/controls/test/java/composition/ProgrammaticTest.java Tue Dec 14 13:57:58 2004 @@ -3,9 +3,6 @@ import junit.framework.Assert; import junit.framework.TestCase; -import java.beans.Beans; -import org.apache.beehive.controls.api.bean.Control; -import org.apache.beehive.controls.api.bean.ControlBean; import org.apache.beehive.controls.test.controls.composition.OuterControlBean; import org.apache.beehive.controls.test.controls.composition.InnerControlBean; import org.apache.beehive.test.tools.mantis.annotations.tch.Freq; @@ -26,6 +23,7 @@ * A control that contains a nested control */ private OuterControlBean outerControl; + private OuterControlBean outerControl2; /* Instantiate the outerControl once*/ @@ -33,6 +31,9 @@ outerControl=(OuterControlBean)java.beans.Beans.instantiate( Thread.currentThread().getContextClassLoader() , "org.apache.beehive.controls.test.controls.composition.OuterControlBean"); + + outerControl2=(OuterControlBean)org.apache.beehive.controls.api.bean.Controls.instantiate( Thread.currentThread().getContextClassLoader(), + "org.apache.beehive.controls.test.controls.composition.OuterControlBean", null ); } /** @@ -43,10 +44,13 @@ { Assert.assertNotNull(outerControl); Assert.assertNotNull(outerControl.instantiateNestedControlProgrammatically()); - /* - Commented out for CR190302 - Assert.assertNotNull(outerControl.instantiateNestedControlWithProperty()); - */ + + InnerControlBean innerBean = outerControl.instantiateNestedControlWithProperty(); + Assert.assertNotNull(innerBean); + Assert.assertEquals(innerBean.getName(), "ken"); + Assert.assertEquals(innerBean.getJob(), "engineer"); + + Assert.assertNotNull(outerControl2); } /**
