You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hivemind.apache.org by hl...@apache.org on 2004/08/06 19:03:32 UTC

cvs commit: jakarta-hivemind/library/src/descriptor/META-INF hivemodule.xml

hlship      2004/08/06 10:03:32

  Modified:    library/src/java/org/apache/hivemind/lib/impl
                        ImplStrings.properties ImplMessages.java
               framework/src/java/org/apache/hivemind/util
                        ClassAdaptor.java PropertyUtils.java
                        PropertyAdaptor.java
               src/documentation/content/xdocs site.xml
               framework/src/test/org/apache/hivemind/util
                        TestPropertyUtils.java
               library/src/descriptor/META-INF hivemodule.xml
  Added:       library/src/java/org/apache/hivemind/lib/impl
                        ServicePropertyFactoryParameter.java
                        ServicePropertyFactory.java
               library/src/test/org/apache/hivemind/lib/impl
                        WonkHolder.java TestServicePropertyFactory.java
                        ServicePropertyFactory.xml WonkSource.java
                        Wonk.java
               library/src/documentation/content/xdocs/hivemind-lib
                        ServicePropertyFactory.xml
  Log:
  Add ServicePropertyFactory.
  
  Revision  Changes    Path
  1.2       +5 -0      jakarta-hivemind/library/src/java/org/apache/hivemind/lib/impl/ImplStrings.properties
  
  Index: ImplStrings.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/library/src/java/org/apache/hivemind/lib/impl/ImplStrings.properties,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ImplStrings.properties	9 Jun 2004 14:57:15 -0000	1.1
  +++ ImplStrings.properties	6 Aug 2004 17:03:31 -0000	1.2
  @@ -26,3 +26,8 @@
   wrong-type=JNDI object ''{0}'' ({1}) is not assignable to {2}.
   
   coordinator-locked=RemoteExceptionCoordinator method {0} was invoked during a notification.
  +
  +service-property-not-readable=Property ''{0}'' of {1} is not readable.
  +service-property-wrong-type=Property ''{0}'' of {1} is type {2}, which does not match the expected interface {3}.
  +service-property-was-null=Property ''{0}'' of {1} is null.
  +service-property-to-string=<ServicePropertyProxy {0}({1}) for property ''{2}'' of {3}>
  
  
  
  1.3       +45 -11    jakarta-hivemind/library/src/java/org/apache/hivemind/lib/impl/ImplMessages.java
  
  Index: ImplMessages.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/library/src/java/org/apache/hivemind/lib/impl/ImplMessages.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ImplMessages.java	29 Jul 2004 13:18:50 -0000	1.2
  +++ ImplMessages.java	6 Aug 2004 17:03:31 -0000	1.3
  @@ -19,6 +19,7 @@
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
   import org.apache.hivemind.impl.MessageFormatter;
  +import org.apache.hivemind.service.ClassFabUtils;
   
   /**
    * Messages for the lib.impl package.
  @@ -32,7 +33,7 @@
       private static final MessageFormatter _formatter =
           new MessageFormatter(LOG, ImplMessages.class, "ImplStrings");
   
  -    public static String unableToCreateDefaultImplementation(Class interfaceType, Throwable cause)
  +    static String unableToCreateDefaultImplementation(Class interfaceType, Throwable cause)
       {
           return _formatter.format(
               "unable-to-create-default-implementation",
  @@ -40,20 +41,17 @@
               cause.getMessage());
       }
   
  -    public static String notAnInterface(Class interfaceType)
  +    static String notAnInterface(Class interfaceType)
       {
           return _formatter.format("not-an-interface", interfaceType.getName());
       }
   
  -    public static String defaultImplementationDescription(Class interfaceType)
  +    static String defaultImplementationDescription(Class interfaceType)
       {
           return _formatter.format("default-implementation-description", interfaceType.getName());
       }
   
  -    public static String ejbProxyDescription(
  -        String serviceId,
  -        Class serviceInterface,
  -        String jndiName)
  +    static String ejbProxyDescription(String serviceId, Class serviceInterface, String jndiName)
       {
           return _formatter.format(
               "ejb-proxy-description",
  @@ -62,23 +60,59 @@
               jndiName);
       }
   
  -    public static String unableToLookup(String name, Context context)
  +    static String unableToLookup(String name, Context context)
       {
           return _formatter.format("unable-to-lookup", name, context);
       }
   
  -    public static String noObject(String name, Class expectedType)
  +    static String noObject(String name, Class expectedType)
       {
           return _formatter.format("no-object", name, expectedType);
       }
   
  -    public static String wrongType(String name, Object object, Class expectedType)
  +    static String wrongType(String name, Object object, Class expectedType)
       {
           return _formatter.format("wrong-type", name, object, expectedType);
       }
   
  -    public static String coordinatorLocked(String methodName)
  +    static String coordinatorLocked(String methodName)
       {
           return _formatter.format("coordinator-locked", methodName);
  +    }
  +
  +    static String servicePropertyNotReadable(String propertyName, Object service)
  +    {
  +        return _formatter.format("service-property-not-readable", propertyName, service);
  +    }
  +
  +    static String servicePropertyWrongType(
  +        String propertyName,
  +        Object service,
  +        Class actualType,
  +        Class expectedType)
  +    {
  +        return _formatter.format(
  +            "service-property-wrong-type",
  +            new Object[] {
  +                propertyName,
  +                service,
  +                ClassFabUtils.getJavaClassName(actualType),
  +                expectedType.getName()});
  +    }
  +
  +    static String servicePropertyWasNull(String propertyName, Object service)
  +    {
  +        return _formatter.format("service-property-was-null", propertyName, service);
  +    }
  +
  +    static String servicePropertyToString(
  +        String serviceId,
  +        Class serviceInterface,
  +        String propertyName,
  +        Object service)
  +    {
  +        return _formatter.format(
  +            "service-property-to-string",
  +            new Object[] { serviceId, serviceInterface.getName(), propertyName, service });
       }
   }
  
  
  
  1.1                  jakarta-hivemind/library/src/java/org/apache/hivemind/lib/impl/ServicePropertyFactoryParameter.java
  
  Index: ServicePropertyFactoryParameter.java
  ===================================================================
  //  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.
  
  package org.apache.hivemind.lib.impl;
  
  import org.apache.hivemind.impl.BaseLocatable;
  
  /**
   * Parameter object used with {@link ServicePropertyFactory}.
   *
   * @author Howard Lewis Ship
   */
  public class ServicePropertyFactoryParameter extends BaseLocatable
  {
      private Object _service;
      private String _propertyName;
  
      public String getPropertyName()
      {
          return _propertyName;
      }
  
      public Object getService()
      {
          return _service;
      }
  
      public void setPropertyName(String string)
      {
          _propertyName = string;
      }
  
      public void setService(Object object)
      {
          _service = object;
      }
  
  }
  
  
  
  1.1                  jakarta-hivemind/library/src/java/org/apache/hivemind/lib/impl/ServicePropertyFactory.java
  
  Index: ServicePropertyFactory.java
  ===================================================================
  //  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.
  
  package org.apache.hivemind.lib.impl;
  
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.util.List;
  
  import org.apache.hivemind.ApplicationRuntimeException;
  import org.apache.hivemind.HiveMind;
  import org.apache.hivemind.ServiceImplementationFactory;
  import org.apache.hivemind.internal.Module;
  import org.apache.hivemind.service.BodyBuilder;
  import org.apache.hivemind.service.ClassFab;
  import org.apache.hivemind.service.ClassFabUtils;
  import org.apache.hivemind.service.ClassFactory;
  import org.apache.hivemind.service.MethodSignature;
  import org.apache.hivemind.util.ConstructorUtils;
  import org.apache.hivemind.util.PropertyAdaptor;
  import org.apache.hivemind.util.PropertyUtils;
  
  /**
   * Factory that dynamically exposes a property of another service. A proxy
   * is constructed that accesses the target service and obtains a property from that.
   * The service interface of the constructed service must match the
   * type of the exposed property.
   *
   * @author Howard Lewis Ship
   */
  public class ServicePropertyFactory implements ServiceImplementationFactory
  {
      private String _serviceId;
      private ClassFactory _classFactory;
  
      public Object createCoreServiceImplementation(
          String serviceId,
          Class serviceInterface,
          Module invokingModule,
          List parameters)
      {
          HiveMind.checkFactoryParameterCount(_serviceId, parameters, 1);
  
          ServicePropertyFactoryParameter p = (ServicePropertyFactoryParameter) parameters.get(0);
  
          Object targetService = p.getService();
          String propertyName = p.getPropertyName();
  
          PropertyAdaptor pa = PropertyUtils.getPropertyAdaptor(targetService, propertyName);
  
          String readMethodName = pa.getReadMethodName();
  
          if (readMethodName == null)
              throw new ApplicationRuntimeException(
                  ImplMessages.servicePropertyNotReadable(propertyName, targetService),
                  null,
                  p.getLocation(),
                  null);
  
          if (!(serviceInterface.isAssignableFrom(pa.getPropertyType())))
              throw new ApplicationRuntimeException(
                  ImplMessages.servicePropertyWrongType(
                      propertyName,
                      targetService,
                      pa.getPropertyType(),
                      serviceInterface),
                  p.getLocation(),
                  null);
  
          // Now we're good to go.
  
          String name = ClassFabUtils.generateClassName("ServicePropertyProxy");
  
          ClassFab cf = _classFactory.newClass(name, Object.class, invokingModule);
  
          addInfrastructure(cf, targetService, serviceInterface, propertyName, readMethodName);
  
          addMethods(cf, serviceId, serviceInterface, propertyName, targetService);
  
          Class proxyClass = cf.createClass();
  
          try
          {
              return ConstructorUtils.invokeConstructor(proxyClass, new Object[] { targetService });
          }
          catch (ApplicationRuntimeException ex)
          {
              throw new ApplicationRuntimeException(ex.getMessage(), p.getLocation(), ex);
          }
      }
  
      private void addInfrastructure(
          ClassFab cf,
          Object targetService,
          Class serviceInterface,
          String propertyName,
          String readPropertyMethodName)
      {
          cf.addInterface(serviceInterface);
  
          Class targetServiceClass = targetService.getClass();
  
          cf.addField("_targetService", targetServiceClass);
  
          cf.addConstructor(
              new Class[] { targetServiceClass },
              null,
              "{ super(); _targetService = $1; }");
  
          BodyBuilder b = new BodyBuilder();
  
          b.begin();
          b.addln(
              "{0} property = _targetService.{1}();",
              serviceInterface.getName(),
              readPropertyMethodName);
  
          b.addln("if (property == null)");
          b.add("  throw new java.lang.NullPointerException(");
          b.addQuoted(ImplMessages.servicePropertyWasNull(propertyName, targetService));
          b.addln(");");
  
          b.addln("return property;");
  
          b.end();
  
          MethodSignature sig =
              new MethodSignature(serviceInterface, "_targetServiceProperty", null, null);
          cf.addMethod(Modifier.FINAL | Modifier.PRIVATE, sig, b.toString());
      }
  
      private void addMethods(
          ClassFab cf,
          String serviceId,
          Class serviceInterface,
          String propertyName,
          Object targetService)
      {
          boolean toString = false;
  
          Method[] methods = serviceInterface.getMethods();
  
          for (int i = 0; i < methods.length; i++)
          {
              Method method = methods[i];
  
              toString |= ClassFabUtils.isToString(method);
  
              String body = "return ($r) _targetServiceProperty()." + method.getName() + "($$);";
  
              cf.addMethod(Modifier.PUBLIC, new MethodSignature(method), body);
          }
  
          if (!toString)
              ClassFabUtils.addToStringMethod(
                  cf,
                  ImplMessages.servicePropertyToString(
                      serviceId,
                      serviceInterface,
                      propertyName,
                      targetService));
      }
  
      public void setClassFactory(ClassFactory factory)
      {
          _classFactory = factory;
      }
  
      public void setServiceId(String string)
      {
          _serviceId = string;
      }
  
  }
  
  
  
  1.7       +5 -5      jakarta-hivemind/framework/src/java/org/apache/hivemind/util/ClassAdaptor.java
  
  Index: ClassAdaptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/util/ClassAdaptor.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- ClassAdaptor.java	18 Jul 2004 14:43:11 -0000	1.6
  +++ ClassAdaptor.java	6 Aug 2004 17:03:31 -0000	1.7
  @@ -33,7 +33,7 @@
   {
       private final Map _propertyAdaptorMap = new HashMap();
   
  -    public ClassAdaptor(PropertyDescriptor[] properties)
  +    ClassAdaptor(PropertyDescriptor[] properties)
       {
           for (int i = 0; i < properties.length; i++)
           {
  @@ -59,7 +59,7 @@
        */
       public void write(Object target, String propertyName, Object value)
       {
  -        PropertyAdaptor a = getAdaptor(target, propertyName);
  +        PropertyAdaptor a = getPropertyAdaptor(target, propertyName);
   
           a.write(target, value);
       }
  @@ -72,7 +72,7 @@
        */
       public Object read(Object target, String propertyName)
       {
  -        PropertyAdaptor a = getAdaptor(target, propertyName);
  +        PropertyAdaptor a = getPropertyAdaptor(target, propertyName);
   
           return a.read(target);
       }
  @@ -85,7 +85,7 @@
        */
       public Class getPropertyType(Object target, String propertyName)
       {
  -        PropertyAdaptor a = getAdaptor(target, propertyName);
  +        PropertyAdaptor a = getPropertyAdaptor(target, propertyName);
   
           return a.getPropertyType();
       }
  @@ -112,7 +112,7 @@
           return result != null && result.isWritable();
       }
   
  -    private PropertyAdaptor getAdaptor(Object target, String propertyName)
  +    PropertyAdaptor getPropertyAdaptor(Object target, String propertyName)
       {
           PropertyAdaptor result = (PropertyAdaptor) _propertyAdaptorMap.get(propertyName);
   
  
  
  
  1.7       +12 -0     jakarta-hivemind/framework/src/java/org/apache/hivemind/util/PropertyUtils.java
  
  Index: PropertyUtils.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/util/PropertyUtils.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- PropertyUtils.java	18 Jul 2004 14:43:11 -0000	1.6
  +++ PropertyUtils.java	6 Aug 2004 17:03:31 -0000	1.7
  @@ -93,6 +93,18 @@
           return a.getPropertyType(target, propertyName);
       }
   
  +	/**
  +	 * Returns the {@link PropertyAdaptor} for the given target object and property name.
  +	 * 
  +	 * @throws ApplicationRuntimeException if the property does not exist.
  +	 */
  +    public static PropertyAdaptor getPropertyAdaptor(Object target, String propertyName)
  +    {
  +        ClassAdaptor a = getAdaptor(target);
  +
  +        return a.getPropertyAdaptor(target, propertyName);
  +    }
  +
       /**
        * Returns an unordered List of the names of all readable properties
        * of the target.
  
  
  
  1.7       +24 -6     jakarta-hivemind/framework/src/java/org/apache/hivemind/util/PropertyAdaptor.java
  
  Index: PropertyAdaptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/util/PropertyAdaptor.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- PropertyAdaptor.java	18 Jul 2004 14:43:11 -0000	1.6
  +++ PropertyAdaptor.java	6 Aug 2004 17:03:31 -0000	1.7
  @@ -23,7 +23,7 @@
    *
    * @author Howard Lewis Ship
    */
  -class PropertyAdaptor
  +public class PropertyAdaptor
   {
       private String _propertyName;
       private Class _propertyType;
  @@ -39,11 +39,29 @@
           _writeMethod = writeMethod;
       }
   
  -	public String getPropertyName()
  -	{
  -		return _propertyName;
  -	}
  -	
  +    /**
  +     * Returns the name of the method used to read the property, or null if the property is
  +     * not readable.
  +     */
  +    public String getReadMethodName()
  +    {
  +        return _readMethod == null ? null : _readMethod.getName();
  +    }
  +
  +    /**
  +     * Returns the name of the method used to write the property, or null if the property
  +     * is not writable.
  +     */
  +    public String getWriteMethodName()
  +    {
  +        return _writeMethod == null ? null : _writeMethod.getName();
  +    }
  +
  +    public String getPropertyName()
  +    {
  +        return _propertyName;
  +    }
  +
       public Class getPropertyType()
       {
           return _propertyType;
  
  
  
  1.1                  jakarta-hivemind/library/src/test/org/apache/hivemind/lib/impl/WonkHolder.java
  
  Index: WonkHolder.java
  ===================================================================
  //  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.
  
  package org.apache.hivemind.lib.impl;
  
  /**
   * Takes the place of a HiveMind service when testing
   * the {@link org.apache.hivemind.lib.impl.ServicePropertyFactory}.
   *
   * @author Howard Lewis Ship
   */
  public class WonkHolder implements WonkSource
  {
      private Wonk _wonk;
  
      public WonkHolder()
      {
      }
      
      public WonkHolder(Wonk wonk)
      {
          _wonk = wonk;
      }
  
      public Wonk getWonk()
      {
          return _wonk;
      }
  
      public String toString()
      {
          return "<WonkHolder>";
      }
  
      public void setWriteOnly(String value)
      {
  
      }
      public void setWonk(Wonk wonk)
      {
          _wonk = wonk;
      }
  
  }
  
  
  
  1.1                  jakarta-hivemind/library/src/test/org/apache/hivemind/lib/impl/TestServicePropertyFactory.java
  
  Index: TestServicePropertyFactory.java
  ===================================================================
  //  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.
  
  package org.apache.hivemind.lib.impl;
  
  import java.util.Collections;
  import java.util.List;
  
  import org.apache.hivemind.ApplicationRuntimeException;
  import org.apache.hivemind.HiveMind;
  import org.apache.hivemind.Registry;
  import org.apache.hivemind.impl.DefaultClassResolver;
  import org.apache.hivemind.internal.Module;
  import org.apache.hivemind.service.impl.ClassFactoryImpl;
  import org.apache.hivemind.test.HiveMindTestCase;
  import org.easymock.MockControl;
  
  /**
   * Tests for {@link org.apache.hivemind.lib.impl.ServicePropertyFactory}.
   *
   * @author Howard Lewis Ship
   */
  public class TestServicePropertyFactory extends HiveMindTestCase
  {
      private ServicePropertyFactory newFactory()
      {
          ServicePropertyFactory result = new ServicePropertyFactory();
  
          result.setServiceId("test.factory");
          result.setClassFactory(new ClassFactoryImpl());
  
          return result;
      }
  
      private Module newModule()
      {
          MockControl c = newControl(Module.class);
          Module result = (Module) c.getMock();
  
          result.getModuleId();
          c.setReturnValue("test.module");
  
          result.getClassResolver();
          c.setReturnValue(new DefaultClassResolver());
  
          return result;
      }
  
      private List newParameters(Object service, String propertyName)
      {
          ServicePropertyFactoryParameter p = new ServicePropertyFactoryParameter();
  
          p.setService(service);
          p.setPropertyName(propertyName);
          p.setLocation(fabricateLocation(99));
  
          return Collections.singletonList(p);
      }
  
      public void testSuccess()
      {
          ServicePropertyFactory f = newFactory();
  
          MockControl wonkControl = newControl(Wonk.class);
          Wonk wonk = (Wonk) wonkControl.getMock();
  
          List parameters = newParameters(new WonkHolder(wonk), "wonk");
  
          wonk.wonkVoid();
          wonk.wonkString("zebra");
          wonkControl.setReturnValue("stripes");
  
          Module m = newModule();
  
          replayControls();
  
          Wonk proxy = (Wonk) f.createCoreServiceImplementation("foo.bar", Wonk.class, m, parameters);
  
          proxy.wonkVoid();
          assertEquals("stripes", proxy.wonkString("zebra"));
  
          assertEquals(
              "<ServicePropertyProxy foo.bar(org.apache.hivemind.lib.impl.Wonk) for property 'wonk' of <WonkHolder>>",
              proxy.toString());
  
          verifyControls();
      }
  
      public void testPropertyNull()
      {
          ServicePropertyFactory f = newFactory();
  
          List parameters = newParameters(new WonkHolder(null), "wonk");
  
          Module m = newModule();
  
          replayControls();
  
          Wonk proxy = (Wonk) f.createCoreServiceImplementation("foo.bar", Wonk.class, m, parameters);
  
          try
          {
              proxy.wonkVoid();
              unreachable();
          }
          catch (NullPointerException ex)
          {
              assertEquals("Property 'wonk' of <WonkHolder> is null.", ex.getMessage());
          }
  
          verifyControls();
      }
  
      public void testWriteOnlyProperty()
      {
          ServicePropertyFactory f = newFactory();
  
          List parameters = newParameters(new WonkHolder(null), "writeOnly");
  
          try
          {
              f.createCoreServiceImplementation("foo.bar", Wonk.class, null, parameters);
              unreachable();
          }
          catch (ApplicationRuntimeException ex)
          {
              assertEquals("Property 'writeOnly' of <WonkHolder> is not readable.", ex.getMessage());
              assertEquals(HiveMind.getLocation(parameters.get(0)), ex.getLocation());
          }
      }
  
      public void testPropertyTypeMismatch()
      {
          ServicePropertyFactory f = newFactory();
  
          List parameters = newParameters(new WonkHolder(null), "class");
  
          try
          {
              f.createCoreServiceImplementation("foo.bar", Wonk.class, null, parameters);
              unreachable();
          }
          catch (ApplicationRuntimeException ex)
          {
              assertEquals(
                  "Property 'class' of <WonkHolder> is type java.lang.Class, which does not match the expected interface org.apache.hivemind.lib.impl.Wonk.",
                  ex.getMessage());
              assertEquals(HiveMind.getLocation(parameters.get(0)), ex.getLocation());
          }
      }
  
      public void testIntegrated() throws Exception
      {
          Registry r = buildFrameworkRegistry("ServicePropertyFactory.xml");
  
          WonkSource source = (WonkSource) r.getService(WonkSource.class);
          Wonk wonkService = (Wonk) r.getService(Wonk.class);
  
          Wonk wonk = (Wonk) newMock(Wonk.class);
          
          source.setWonk(wonk);
  
          wonk.wonkVoid();
  
          replayControls();
  
  		// Invoking this (on the proxy) will cause the corresponding
  		// method (on the mock) to be invoked.
  		
          wonkService.wonkVoid();
  
          verifyControls();
      }
  }
  
  
  
  1.1                  jakarta-hivemind/library/src/test/org/apache/hivemind/lib/impl/ServicePropertyFactory.xml
  
  Index: ServicePropertyFactory.xml
  ===================================================================
  <?xml version="1.0"?>
  <!-- 
     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.
  -->
  
  <module id="hivemind.lib.test" version="1.0.0">
    
    <service-point id="WonkSource" interface="org.apache.hivemind.lib.impl.WonkSource">
      <create-instance class="org.apache.hivemind.lib.impl.WonkHolder"/>
    </service-point>
    
    <service-point id="Wonk" interface="org.apache.hivemind.lib.impl.Wonk">
      <invoke-factory service-id="hivemind.lib.ServicePropertyFactory">
        <construct service-id="WonkSource" property="wonk"/>
      </invoke-factory>
    </service-point>
    
  </module>
  
  
  1.1                  jakarta-hivemind/library/src/test/org/apache/hivemind/lib/impl/WonkSource.java
  
  Index: WonkSource.java
  ===================================================================
  //  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.
  
  package org.apache.hivemind.lib.impl;
  
  /**
   * Used by {@link org.apache.hivemind.lib.impl.TestServicePropertyFactory}.
   *
   * @author Howard Lewis Ship
   */
  public interface WonkSource
  {
  	public void setWonk(Wonk wonk);
  	
      public Wonk getWonk();
  }
  
  
  
  1.1                  jakarta-hivemind/library/src/test/org/apache/hivemind/lib/impl/Wonk.java
  
  Index: Wonk.java
  ===================================================================
  //  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.
  
  package org.apache.hivemind.lib.impl;
  
  /**
   * Used by {@link org.apache.hivemind.lib.impl.TestServicePropertyFactory}.
   *
   * @author Howard Lewis Ship
   */
  public interface Wonk
  {
      public void wonkVoid();
  
      public String wonkString(String parameter);
  }
  
  
  
  1.24      +1 -0      jakarta-hivemind/src/documentation/content/xdocs/site.xml
  
  Index: site.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/src/documentation/content/xdocs/site.xml,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- site.xml	3 Aug 2004 14:02:13 -0000	1.23
  +++ site.xml	6 Aug 2004 17:03:31 -0000	1.24
  @@ -116,6 +116,7 @@
         <hivemind.lib.PlaceholderFactory label="PlaceholderFactory" href="PlaceholderFactory.html"/> 
         <hivemind.lib.PipelineFactory label="PipelineFactory" href="PipelineFactory.html"/>     
   			<hivemind.lib.RemoteExceptionCoordinator label="RemoteExceptionCoordinator" href="RemoteExceptionCoordinator.html"/>
  +      <hivemind.lib.ServicePropertyFactory label="ServicePropertyFactory" href="ServicePropertyFactory.html"/>
   			<hivemind.lib.SpringLookupFactory label="SpringLookupFactory" href="SpringLookupFactory.html"/>
   		</services>	
   		
  
  
  
  1.1                  jakarta-hivemind/library/src/documentation/content/xdocs/hivemind-lib/ServicePropertyFactory.xml
  
  Index: ServicePropertyFactory.xml
  ===================================================================
  <?xml version="1.0"?>
  <!-- 
     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.
  -->
  <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.2//EN"
  	"./dtd/document-v12.dtd" [
  	<!ENTITY projectroot '../'>
  	<!ENTITY % common-links SYSTEM "../links.ent">
  	%common-links;
  	]>
  <document>
  	<header>
  		<title>hivemind.lib.ServicePropertyFactory Service</title>
  	</header>
  	<body>
  		<p>The <link href="&hivedoc;/service/hivemind.lib.ServicePropertyFactory.html">
  			ServicePropertyFactory</link> exposes a property of a service as a new service.
        The property's type must the same as (or assignable to) the service interface.
        </p>
        
        <p>On each invocation of a service method, the property is re-acquired from
          the property source service, and the method reinvoked on the active value.
        This is useful when the value of the property can change at different times ...
        by using this factory,
        and not the <code>service-property</code>  <link href="site:hivemind.ObjectProviders">object provider</link>,
        your code will always access the current value.
        </p>
        
        <p>
          This can invaluable when a small number of services use the threaded or pooled service models.
          Other services can access information in those services transparently, without themselves having
          to be threaded or pooled.
        </p>
        
        <p>
          A single parameter element is expected:
        </p>
        
        <source>
  <![CDATA[<construct service-id="..." property="..."/>]]>      
        </source>
        
        <p>
          Both attributes are required. 
        </p>
  	</body>
  </document>
  
  
  
  1.6       +15 -0     jakarta-hivemind/framework/src/test/org/apache/hivemind/util/TestPropertyUtils.java
  
  Index: TestPropertyUtils.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/framework/src/test/org/apache/hivemind/util/TestPropertyUtils.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- TestPropertyUtils.java	18 Jul 2004 14:43:12 -0000	1.5
  +++ TestPropertyUtils.java	6 Aug 2004 17:03:31 -0000	1.6
  @@ -326,4 +326,19 @@
   
           assertListsEqual(new String[] { "value", "writeOnly" }, actual);
       }
  +
  +    public void testGetPropertyAdaptor()
  +    {
  +        Bean b = new Bean();
  +
  +        PropertyAdaptor a = PropertyUtils.getPropertyAdaptor(b, "writeOnly");
  +
  +        assertEquals("setWriteOnly", a.getWriteMethodName());
  +        assertNull(a.getReadMethodName());
  +
  +        a = PropertyUtils.getPropertyAdaptor(b, "class");
  +
  +        assertEquals("getClass", a.getReadMethodName());
  +        assertNull(a.getWriteMethodName());
  +    }
   }
  
  
  
  1.8       +41 -0     jakarta-hivemind/library/src/descriptor/META-INF/hivemodule.xml
  
  Index: hivemodule.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/library/src/descriptor/META-INF/hivemodule.xml,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- hivemodule.xml	3 Aug 2004 14:02:19 -0000	1.7
  +++ hivemodule.xml	6 Aug 2004 17:03:31 -0000	1.8
  @@ -181,4 +181,45 @@
               </conversion>
           </element>
       </schema>
  +    
  +    <service-point id="ServicePropertyFactory" interface="org.apache.hivemind.ServiceImplementationFactory">
  +      
  +      Creates a service that dynamically (i.e., on each service method invocation) obtains a property
  +      from another service and forwards the invocation to the property.  The property must be
  +      the same type (or assignable to) the constructed service's interface. Typically,
  +      the targeted service uses a threaded (or similar) service model, thus requiring dynamic,
  +      rather than static, access.
  +      
  +      <invoke-factory service-id="hivemind.BuilderFactory">
  +        <construct class="org.apache.hivemind.lib.impl.ServicePropertyFactory">
  +          
  +          <set-service property="classFactory" service-id="hivemind.ClassFactory"/>
  +          
  +        </construct>
  +        
  +      </invoke-factory>
  +      
  +      <parameters-schema>
  +        <element name="construct">
  +          
  +          <attribute name="service-id" required="true" translator="service">
  +            
  +            The service which contains the property.
  +            
  +          </attribute>
  +          
  +          <attribute name="property" required="true">
  +            
  +            The name of the property of the target service to expose.
  +          </attribute>
  +          
  +          <conversion class="org.apache.hivemind.lib.impl.ServicePropertyFactoryParameter">
  +            <map attribute="service-id" property="service"/>
  +            <map attribute="property" property="propertyName"/>
  +          </conversion>
  +          
  +        </element>
  +      </parameters-schema>
  +      
  +    </service-point>
   </module>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: hivemind-cvs-unsubscribe@jakarta.apache.org
For additional commands, e-mail: hivemind-cvs-help@jakarta.apache.org