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/11/05 16:58:35 UTC

cvs commit: jakarta-hivemind/framework/src/java/org/apache/hivemind/order Orderer.java

hlship      2004/11/05 07:58:35

  Modified:    src/documentation/content/xdocs index.xml site.xml
               library/src/documentation/content/xdocs/hivemind-lib
                        PipelineFactory.xml
               .        status.xml
               framework/src/java/org/apache/hivemind/impl
                        ServiceImplementationFactoryParametersImpl.java
               framework/src/java/org/apache/hivemind
                        ServiceImplementationFactoryParameters.java
               framework/src/java/org/apache/hivemind/service
                        ClassFabUtils.java
               library/src/descriptor/META-INF hivemodule.xml
               framework/src/test/org/apache/hivemind/service/impl
                        TestClassFabUtils.java
               library/src/java/org/apache/hivemind/lib/impl
                        DefaultImplementationBuilderImpl.java
               framework/src/java/org/apache/hivemind/order Orderer.java
  Added:       library/src/test/org/apache/hivemind/lib/util
                        TestAdaptorRegistry.java
               library/src/java/org/apache/hivemind/lib/adaptor
                        AdaptorRegistryFactory.java
                        AdaptorRegistryParameter.java AdaptorMessages.java
                        AdaptorStrings.properties
                        AdaptorRegistryContribution.java
               library/src/test/org/apache/hivemind/lib/adaptor
                        ToStringAdaptor.java CatchAllToStringAdaptor.java
                        AdaptorFactoryIntegration.xml
                        TestAdaptorRegistryFactory.java
               library/src/java/org/apache/hivemind/lib/util
                        AdaptorRegistryImpl.java AdaptorRegistry.java
                        UtilMessages.java UtilStrings.properties
               library/src/documentation/content/xdocs/hivemind-lib
                        AdaptorRegistryFactory.xml
               framework/src/java/org/apache/hivemind/test
                        ArrayMatcher.java
               framework/src/test/org/apache/hivemind/test
                        TestArrayMatcher.java
  Log:
  Add AdaptorRegistryFactory service implementation factory.
  
  Revision  Changes    Path
  1.1                  jakarta-hivemind/library/src/test/org/apache/hivemind/lib/util/TestAdaptorRegistry.java
  
  Index: TestAdaptorRegistry.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.util;
  
  import java.io.Serializable;
  import java.util.List;
  import java.util.Map;
  
  import org.apache.hivemind.lib.util.AdaptorRegistry;
  import org.apache.hivemind.lib.util.AdaptorRegistryImpl;
  import org.apache.hivemind.test.HiveMindTestCase;
  
  /**
   * Tests the {@link org.apache.hivemind.lib.util.AdaptorRegistryImpl}class.
   * 
   * @author Howard Lewis Ship
   * @since 1.1
   */
  
  public class TestAdaptorRegistry extends HiveMindTestCase
  {
  
      private AdaptorRegistry build()
      {
          AdaptorRegistry result = new AdaptorRegistryImpl();
  
          result.register(Object.class, "OBJECT");
          result.register(Object[].class, "OBJECT[]");
          result.register(String.class, "STRING");
          result.register(List.class, "LIST");
          result.register(Map.class, "MAP");
          result.register(Serializable.class, "SERIALIZABLE");
          result.register(int[].class, "INT[]");
          result.register(double.class, "DOUBLE");
          result.register(Number[].class, "NUMBER[]");
  
          return result;
      }
  
      private void expect(String expected, Class subjectClass)
      {
          Object actual = build().getAdaptor(subjectClass);
  
          assertEquals(expected, actual);
      }
  
      public void testDefaultMatch()
      {
          expect("OBJECT", TestAdaptorRegistry.class);
      }
  
      public void testClassBeforeInterface()
      {
          expect("STRING", String.class);
      }
  
      public void testInterfaceMatch()
      {
          expect("SERIALIZABLE", Boolean.class);
      }
  
      public void testObjectArrayMatch()
      {
          expect("OBJECT[]", Object[].class);
      }
  
      public void testObjectSubclassArray()
      {
          expect("OBJECT[]", String[].class);
      }
  
      public void testRegisteredSubclassArray()
      {
          expect("NUMBER[]", Number[].class);
      }
  
      public void testScalarArrayMatch()
      {
          expect("INT[]", int[].class);
      }
  
      public void testScalarArrayDefault()
      {
          // This won't change, scalar arrays can't be cast to Object[].
  
          expect("SERIALIZABLE", short[].class);
      }
  
      public void testScalar()
      {
          expect("DOUBLE", double.class);
      }
  
      public void testScalarDefault()
      {
          expect("OBJECT", float.class);
      }
  
      public void testSearchNoInterfaces()
      {
          expect("OBJECT", Object.class);
      }
  
      public void testNoMatch()
      {
          AdaptorRegistry r = new AdaptorRegistryImpl();
  
          r.register(String.class, "STRING");
  
          try
          {
              r.getAdaptor(Boolean.class);
  
              unreachable();
          }
          catch (IllegalArgumentException ex)
          {
              assertEquals(UtilMessages.adaptorNotFound(Boolean.class), ex.getMessage());
          }
      }
  
      public void testToString()
      {
          AdaptorRegistry r = new AdaptorRegistryImpl();
  
          r.register(String.class, "STRING");
  
          assertEquals("AdaptorRegistry[java.lang.String=STRING]", r.toString());
      }
  
      public void testDuplicateRegistration()
      {
          AdaptorRegistry r = new AdaptorRegistryImpl();
  
          r.register(String.class, "STRING");
  
          try
          {
              r.register(String.class, "STRING2");
  
              unreachable();
          }
          catch (IllegalArgumentException ex)
          {
              assertEquals(UtilMessages.duplicateRegistration(String.class), ex.getMessage());
          }
      }
  }
  
  
  1.1                  jakarta-hivemind/library/src/java/org/apache/hivemind/lib/adaptor/AdaptorRegistryFactory.java
  
  Index: AdaptorRegistryFactory.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.adaptor;
  
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Modifier;
  import java.util.Iterator;
  import java.util.List;
  
  import org.apache.hivemind.ApplicationRuntimeException;
  import org.apache.hivemind.HiveMind;
  import org.apache.hivemind.ServiceImplementationFactory;
  import org.apache.hivemind.ServiceImplementationFactoryParameters;
  import org.apache.hivemind.lib.util.AdaptorRegistry;
  import org.apache.hivemind.lib.util.AdaptorRegistryImpl;
  import org.apache.hivemind.service.ClassFab;
  import org.apache.hivemind.service.ClassFabUtils;
  import org.apache.hivemind.service.ClassFactory;
  import org.apache.hivemind.service.MethodIterator;
  import org.apache.hivemind.service.MethodSignature;
  
  /**
   * Constructs a service where the first parameter of each method is used to selected an adaptor from
   * an {@link org.apache.hivemind.lib.util.AdaptorRegistry}. The method invocation is then delegated
   * to the adaptor.
   * <p>
   * The service factory parameter defines a configuration (of
   * {@link org.apache.hivemind.lib.adaptor.AdaptorRegistryContribution}that provide the mapping from
   * Java classes (or interfaces) to adaptor instances.
   * 
   * @author Howard M. Lewis Ship
   * @since 1.1
   */
  public class AdaptorRegistryFactory implements ServiceImplementationFactory
  {
      private ClassFactory _classFactory;
  
      public Object createCoreServiceImplementation(
              ServiceImplementationFactoryParameters factoryParameters)
      {
          AdaptorRegistry ar = new AdaptorRegistryImpl();
  
          buildAdaptorRegistry(factoryParameters, ar);
  
          Class implClass = buildImplementationClass(factoryParameters);
  
          try
          {
              Constructor c = implClass.getConstructors()[0];
  
              return c.newInstance(new Object[]
              { ar });
          }
          catch (Exception ex)
          {
              throw new ApplicationRuntimeException(ex.getMessage(), HiveMind
                      .getLocation(factoryParameters.getFirstParameter()), ex);
          }
  
      }
  
      // package private for testing purposes
  
      void buildAdaptorRegistry(ServiceImplementationFactoryParameters factoryParameters,
              AdaptorRegistry ar)
      {
          Class serviceInterface = factoryParameters.getServiceInterface();
  
          AdaptorRegistryParameter p = (AdaptorRegistryParameter) factoryParameters
                  .getFirstParameter();
  
          List contributions = p.getContributions();
  
          Iterator i = contributions.iterator();
  
          while (i.hasNext())
          {
              AdaptorRegistryContribution c = (AdaptorRegistryContribution) i.next();
  
              try
              {
                  Object adaptor = c.getAdaptor();
  
                  if (!serviceInterface.isAssignableFrom(adaptor.getClass()))
                      throw new ClassCastException(AdaptorMessages.adaptorWrongInterface(adaptor, c
                              .getRegisterClass(), serviceInterface));
  
                  ar.register(c.getRegisterClass(), adaptor);
              }
              catch (Exception ex)
              {
                  factoryParameters.getErrorLog().error(ex.getMessage(), c.getLocation(), ex);
              }
  
          }
  
      }
  
      // package private for testing purposes
  
      private Class buildImplementationClass(ServiceImplementationFactoryParameters factoryParameters)
      {
          String name = ClassFabUtils.generateClassName("AdaptorRegistry");
          ClassLoader loader = factoryParameters.getInvokingModule().getClassResolver()
                  .getClassLoader();
  
          return buildImplementationClass(factoryParameters, name, loader);
      }
  
      // package private for testing purposes
  
      Class buildImplementationClass(ServiceImplementationFactoryParameters factoryParameters,
              String name, ClassLoader loader)
      {
          Class serviceInterface = factoryParameters.getServiceInterface();
  
          ClassFab cf = _classFactory.newClass(name, Object.class, loader);
  
          cf.addInterface(serviceInterface);
  
          cf.addField("_adaptorRegistry", AdaptorRegistry.class);
  
          cf.addConstructor(new Class[]
          { AdaptorRegistry.class }, null, "_adaptorRegistry = $1;");
  
          // TODO: Should we add a check for $1 == null?
          
          cf.addMethod(Modifier.PRIVATE, new MethodSignature(serviceInterface, "_getAdaptor",
                  new Class[]
                  { Object.class }, null), "return (" + serviceInterface.getName()
                  + ") _adaptorRegistry.getAdaptor($1.getClass());");
  
          MethodIterator i = new MethodIterator(serviceInterface);
  
          while (i.hasNext())
          {
              MethodSignature sig = i.next();
  
              if (proper(sig))
              {
                  addAdaptedMethod(cf, sig);
              }
              else
              {
                  ClassFabUtils.addNoOpMethod(cf, sig);
  
                  factoryParameters.getErrorLog().error(
                          AdaptorMessages.improperServiceMethod(sig),
                          HiveMind.getLocation(factoryParameters.getFirstParameter()),
                          null);
              }
  
          }
  
          if (!i.getToString())
              ClassFabUtils.addToStringMethod(cf, AdaptorMessages.toString(factoryParameters
                      .getServiceId(), serviceInterface));
  
          return cf.createClass();
      }
  
      private void addAdaptedMethod(ClassFab cf, MethodSignature sig)
      {
          String body = "return ($r) _getAdaptor($1)." + sig.getName() + "($$);";
  
          cf.addMethod(Modifier.PUBLIC, sig, body);
      }
  
      /**
       * A "proper" method is one with at least one parameter and whose first parameter is an object
       * (not primitive) type.
       */
  
      private boolean proper(MethodSignature sig)
      {
          Class[] parameterTypes = sig.getParameterTypes();
  
          return parameterTypes != null && parameterTypes.length > 0
                  && !parameterTypes[0].isPrimitive();
      }
  
      public void setClassFactory(ClassFactory classFactory)
      {
          _classFactory = classFactory;
      }
  }
  
  
  1.1                  jakarta-hivemind/library/src/java/org/apache/hivemind/lib/adaptor/AdaptorRegistryParameter.java
  
  Index: AdaptorRegistryParameter.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.adaptor;
  
  import java.util.List;
  
  import org.apache.hivemind.impl.BaseLocatable;
  
  /**
   * Parameter value passed to the <code>hivemind.lib.AdaptorRegistryFactory</code> service factory.
   * 
   * @author Howard M. Lewis Ship
   * @since 1.1
   */
  public class AdaptorRegistryParameter extends BaseLocatable
  {
      private List _contributions;
  
      /**
       * List of {@link org.apache.hivemind.lib.adaptor.AdaptorRegistryContribution}.
       */
      public List getContributions()
      {
          return _contributions;
      }
  
      public void setContributions(List configuration)
      {
          _contributions = configuration;
      }
  }
  
  
  1.1                  jakarta-hivemind/library/src/java/org/apache/hivemind/lib/adaptor/AdaptorMessages.java
  
  Index: AdaptorMessages.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.adaptor;
  
  import org.apache.hivemind.impl.MessageFormatter;
  import org.apache.hivemind.service.ClassFabUtils;
  import org.apache.hivemind.service.MethodSignature;
  
  /**
   * @author Howard M. Lewis Ship
   * @since 1.1
   */
  public class AdaptorMessages
  {
      private static final MessageFormatter _formatter = new MessageFormatter(AdaptorMessages.class,
              "AdaptorStrings");
  
      public static String adaptorWrongInterface(Object adaptor, Class registerClass,
              Class serviceInterface)
      {
          return _formatter.format("adaptor-wrong-interface", adaptor, ClassFabUtils
                  .getJavaClassName(registerClass), serviceInterface.getName());
      }
  
      public static String improperServiceMethod(MethodSignature sig)
      {
          return _formatter.format("improper-service-method", sig);
      }
  
      public static String toString(String serviceId, Class serviceInterface)
      {
          return _formatter.format("to-string", serviceId, serviceInterface.getName());
      }
  }
  
  
  1.1                  jakarta-hivemind/library/src/java/org/apache/hivemind/lib/adaptor/AdaptorStrings.properties
  
  Index: AdaptorStrings.properties
  ===================================================================
  #
  # 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.
  
  adaptor-wrong-interface=Adaptor {0} (for class {1}) does not implement the {2} interface.
  improper-service-method=Method ''{0}'' is not suitable for use with the AdaptorRegistryFactory; the first parameter should be an object type (used to select the adaptor).
  to-string=<AdaptorRegistry for service {0}({1})>
  
  
  
  
  1.1                  jakarta-hivemind/library/src/java/org/apache/hivemind/lib/adaptor/AdaptorRegistryContribution.java
  
  Index: AdaptorRegistryContribution.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.adaptor;
  
  import org.apache.hivemind.impl.BaseLocatable;
  
  /**
   * @author Howard M. Lewis Ship
   * @since 1.1
   */
  public class AdaptorRegistryContribution extends BaseLocatable
  {
      private Class _registerClass;
  
      private Object _adaptor;
  
      public Object getAdaptor()
      {
          return _adaptor;
      }
  
      public void setAdaptor(Object adaptor)
      {
          _adaptor = adaptor;
      }
  
      public Class getRegisterClass()
      {
          return _registerClass;
      }
  
      public void setRegisterClass(Class registerClass)
      {
          _registerClass = registerClass;
      }
  }
  
  
  1.21      +2 -0      jakarta-hivemind/src/documentation/content/xdocs/index.xml
  
  Index: index.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/src/documentation/content/xdocs/index.xml,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- index.xml	2 Nov 2004 17:46:11 -0000	1.20
  +++ index.xml	5 Nov 2004 15:58:34 -0000	1.21
  @@ -93,6 +93,8 @@
           <p>Release 1.1 has introduced an incompatible change to the &api.ServiceImplementationFactory; interface. This 
             change should not affect the vast majority of HiveMind users, only those who have created their
             own service implementation factory services.</p>
  +        <p>Added the <link href="site:hivemind.lib.AdaptorRegistryFactory">AdaptorRegistryFactory</link> service implementation
  +          factory.</p>
   		</section>
   		<section>
   			<title>Acknowledgments</title>
  
  
  
  1.31      +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.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- site.xml	27 Oct 2004 19:29:35 -0000	1.30
  +++ site.xml	5 Nov 2004 15:58:34 -0000	1.31
  @@ -107,6 +107,7 @@
   		<index href="hivemind-lib/index.html" tab="hivemind-lib"/>
   		
   		<services label="Services" tab="hivemind-lib">
  +      <hivemind.lib.AdaptorRegistryFactory label="AdaptorRegistryFactory" href="hivemind-lib/AdaptorRegistryFactory.html"/>
         <hivemind.lib.BeanFactoryBuilder label="BeanFactoryBuilder" href="hivemind-lib/BeanFactoryBuilder.html"/>
         <hivemind.lib.DefaultImplementationBuilder label="DefaultImplementationBuilder" href="hivemind-lib/DefaultImplementationBuilder.html"/>
   			<hivemind.lib.EJBProxyFactory label="EJBProxyFactory" href="hivemind-lib/EJBProxyFactory.html"/>
  
  
  
  1.1                  jakarta-hivemind/library/src/test/org/apache/hivemind/lib/adaptor/ToStringAdaptor.java
  
  Index: ToStringAdaptor.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.adaptor;
  
  /**
   * Used by {@link org.apache.hivemind.lib.adaptor.TestAdaptorRegistryFactory}.
   * 
   * @author Howard M. Lewis Ship
   * @since 1.1
   */
  public interface ToStringAdaptor
  {
      public String toString(Object o);
  }
  
  
  1.1                  jakarta-hivemind/library/src/test/org/apache/hivemind/lib/adaptor/CatchAllToStringAdaptor.java
  
  Index: CatchAllToStringAdaptor.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.adaptor;
  
  /**
   * Used by {@link org.apache.hivemind.lib.util.TestAdaptorRegistry}'s integration test.
   * 
   * @author Howard M. Lewis Ship
   * @since 1.1
   */
  public class CatchAllToStringAdaptor implements ToStringAdaptor
  {
  
      /**
       * Invokes {@link java.lang.Object#toString()}.
       */
  
      public String toString(Object o)
      {
          return o.toString();
      }
  
  }
  
  
  1.1                  jakarta-hivemind/library/src/test/org/apache/hivemind/lib/adaptor/AdaptorFactoryIntegration.xml
  
  Index: AdaptorFactoryIntegration.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">
    
    <configuration-point id="ToStringAdaptors" schema-id="hivemind.lib.AdaptorRegistry"/>
    
    <contribution configuration-id="ToStringAdaptors">
      
      <adaptor class="java.lang.Object" object="instance:org.apache.hivemind.lib.adaptor.CatchAllToStringAdaptor"/>
      
    </contribution>
    
    <service-point id="ToStringAdaptor" interface="org.apache.hivemind.lib.adaptor.ToStringAdaptor">
      <invoke-factory service-id="hivemind.lib.AdaptorRegistryFactory">
        <construct configuration-id="ToStringAdaptors"/>
      </invoke-factory>
    </service-point>
    
  </module>
  
  
  1.1                  jakarta-hivemind/library/src/test/org/apache/hivemind/lib/adaptor/TestAdaptorRegistryFactory.java
  
  Index: TestAdaptorRegistryFactory.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.adaptor;
  
  import java.lang.reflect.Modifier;
  import java.util.Collections;
  import java.util.List;
  
  import org.apache.hivemind.ErrorLog;
  import org.apache.hivemind.Location;
  import org.apache.hivemind.Registry;
  import org.apache.hivemind.ServiceImplementationFactoryParameters;
  import org.apache.hivemind.lib.util.AdaptorRegistry;
  import org.apache.hivemind.service.ClassFab;
  import org.apache.hivemind.service.ClassFabUtils;
  import org.apache.hivemind.service.ClassFactory;
  import org.apache.hivemind.service.MethodFab;
  import org.apache.hivemind.service.MethodSignature;
  import org.apache.hivemind.test.AggregateArgumentsMatcher;
  import org.apache.hivemind.test.ArgumentMatcher;
  import org.apache.hivemind.test.ArrayMatcher;
  import org.apache.hivemind.test.HiveMindTestCase;
  import org.apache.hivemind.test.TypeMatcher;
  import org.easymock.MockControl;
  
  /**
   * Test for the {@link org.apache.hivemind.lib.adaptor.AdaptorRegistryFactory}service
   * implementation factory.
   * 
   * @author Howard M. Lewis Ship
   * @since 1.1
   */
  public class TestAdaptorRegistryFactory extends HiveMindTestCase
  {
      private List buildContributions(Class registerClass, Object adaptor, Location location)
      {
          AdaptorRegistryContribution c = new AdaptorRegistryContribution();
  
          c.setRegisterClass(registerClass);
          c.setAdaptor(adaptor);
          c.setLocation(location);
  
          return Collections.singletonList(c);
      }
  
      private AdaptorRegistryParameter buildParameter(Class registerClass, Object adaptor,
              Location contributionLocation, Location parameterLocation)
      {
          AdaptorRegistryParameter result = new AdaptorRegistryParameter();
  
          result.setContributions(buildContributions(registerClass, adaptor, contributionLocation));
          result.setLocation(parameterLocation);
  
          return result;
      }
  
      private AdaptorRegistryParameter buildParameter(Class registerClass, Object adaptor)
      {
          return buildParameter(registerClass, adaptor, null, null);
      }
  
      public void testBuildRegistry()
      {
          AdaptorRegistry ar = (AdaptorRegistry) newMock(AdaptorRegistry.class);
          ToStringAdaptor adaptor = (ToStringAdaptor) newMock(ToStringAdaptor.class);
  
          MockControl fpc = newControl(ServiceImplementationFactoryParameters.class);
          ServiceImplementationFactoryParameters fp = (ServiceImplementationFactoryParameters) fpc
                  .getMock();
  
          fp.getServiceInterface();
          fpc.setReturnValue(ToStringAdaptor.class);
  
          AdaptorRegistryParameter p = buildParameter(Number.class, adaptor);
  
          fp.getFirstParameter();
          fpc.setReturnValue(p);
  
          ar.register(Number.class, adaptor);
  
          replayControls();
  
          new AdaptorRegistryFactory().buildAdaptorRegistry(fp, ar);
  
          verifyControls();
      }
  
      public void testBuildRegistryWrongAdaptorType()
      {
          Location l = fabricateLocation(3);
  
          AdaptorRegistry ar = (AdaptorRegistry) newMock(AdaptorRegistry.class);
          ToStringAdaptor adaptor = (ToStringAdaptor) newMock(ToStringAdaptor.class);
  
          MockControl fpc = newControl(ServiceImplementationFactoryParameters.class);
          ServiceImplementationFactoryParameters fp = (ServiceImplementationFactoryParameters) fpc
                  .getMock();
  
          MockControl logc = newControl(ErrorLog.class);
          ErrorLog log = (ErrorLog) logc.getMock();
  
          fp.getServiceInterface();
          fpc.setReturnValue(Runnable.class);
  
          AdaptorRegistryParameter p = buildParameter(Number.class, adaptor, l, null);
  
          fp.getFirstParameter();
          fpc.setReturnValue(p);
  
          fp.getErrorLog();
          fpc.setReturnValue(log);
  
          log.error(
                  AdaptorMessages.adaptorWrongInterface(adaptor, Number.class, Runnable.class),
                  l,
                  new ClassCastException());
          logc.setMatcher(new AggregateArgumentsMatcher(new ArgumentMatcher[]
          { null, null, new TypeMatcher() }));
  
          replayControls();
  
          new AdaptorRegistryFactory().buildAdaptorRegistry(fp, ar);
  
          verifyControls();
      }
  
      public void testBuildImplementationClass()
      {
          MockControl factoryControl = newControl(ClassFactory.class);
          ClassFactory factory = (ClassFactory) factoryControl.getMock();
  
          MockControl cfc = newControl(ClassFab.class);
          ClassFab cf = (ClassFab) cfc.getMock();
  
          MethodFab mf = (MethodFab) newMock(MethodFab.class);
  
          ClassLoader loader = Thread.currentThread().getContextClassLoader();
  
          MockControl fpc = newControl(ServiceImplementationFactoryParameters.class);
          ServiceImplementationFactoryParameters fp = (ServiceImplementationFactoryParameters) fpc
                  .getMock();
  
          fp.getServiceInterface();
          fpc.setReturnValue(ToStringAdaptor.class);
  
          factory.newClass("NewClass", Object.class, loader);
          factoryControl.setReturnValue(cf);
  
          cf.addInterface(ToStringAdaptor.class);
          cf.addField("_adaptorRegistry", AdaptorRegistry.class);
  
          cf.addConstructor(new Class[]
          { AdaptorRegistry.class }, null, "_adaptorRegistry = $1;");
          cfc.setMatcher(new AggregateArgumentsMatcher(new ArrayMatcher()));
  
          cf
                  .addMethod(
                          Modifier.PRIVATE,
                          new MethodSignature(ToStringAdaptor.class, "_getAdaptor", new Class[]
                          { Object.class }, null),
                          "return (org.apache.hivemind.lib.adaptor.ToStringAdaptor) _adaptorRegistry.getAdaptor($1.getClass());");
          cfc.setReturnValue(mf);
  
          cf.addMethod(Modifier.PUBLIC, new MethodSignature(String.class, "toString", new Class[]
          { Object.class }, null), "return ($r) _getAdaptor($1).toString($$);");
          cfc.setReturnValue(mf);
  
          fp.getServiceId();
          fpc.setReturnValue("foo.Bar");
  
          ClassFabUtils.addToStringMethod(cf, AdaptorMessages.toString(
                  "foo.Bar",
                  ToStringAdaptor.class));
          cfc.setReturnValue(mf);
  
          cf.createClass();
          cfc.setReturnValue(String.class);
  
          replayControls();
  
          AdaptorRegistryFactory f = new AdaptorRegistryFactory();
          f.setClassFactory(factory);
  
          f.buildImplementationClass(fp, "NewClass", loader);
  
          verifyControls();
      }
  
      public void testBuildImplementationClassImproperMethod()
      {
          Location l = fabricateLocation(31);
  
          MockControl factoryControl = newControl(ClassFactory.class);
          ClassFactory factory = (ClassFactory) factoryControl.getMock();
  
          MockControl cfc = newControl(ClassFab.class);
          ClassFab cf = (ClassFab) cfc.getMock();
  
          MethodFab mf = (MethodFab) newMock(MethodFab.class);
  
          ClassLoader loader = Thread.currentThread().getContextClassLoader();
  
          MockControl fpc = newControl(ServiceImplementationFactoryParameters.class);
          ServiceImplementationFactoryParameters fp = (ServiceImplementationFactoryParameters) fpc
                  .getMock();
  
          ErrorLog log = (ErrorLog) newMock(ErrorLog.class);
  
          fp.getServiceInterface();
          fpc.setReturnValue(Runnable.class);
  
          factory.newClass("NewClass", Object.class, loader);
          factoryControl.setReturnValue(cf);
  
          cf.addInterface(Runnable.class);
          cf.addField("_adaptorRegistry", AdaptorRegistry.class);
  
          cf.addConstructor(new Class[]
          { AdaptorRegistry.class }, null, "_adaptorRegistry = $1;");
          cfc.setMatcher(new AggregateArgumentsMatcher(new ArrayMatcher()));
  
          cf.addMethod(
                  Modifier.PRIVATE,
                  new MethodSignature(Runnable.class, "_getAdaptor", new Class[]
                  { Object.class }, null),
                  "return (java.lang.Runnable) _adaptorRegistry.getAdaptor($1.getClass());");
          cfc.setReturnValue(mf);
  
          MethodSignature sig = new MethodSignature(void.class, "run", null, null);
  
          cf.addMethod(Modifier.PUBLIC, sig, "{  }");
          cfc.setReturnValue(mf);
  
          fp.getErrorLog();
          fpc.setReturnValue(log);
  
          fp.getFirstParameter();
          // Slight fudge: we return the location itself when we should return
          // an object with this location.
          fpc.setReturnValue(l);
  
          log.error(AdaptorMessages.improperServiceMethod(sig), l, null);
  
          fp.getServiceId();
          fpc.setReturnValue("foo.Bar");
  
          ClassFabUtils.addToStringMethod(cf, AdaptorMessages.toString("foo.Bar", Runnable.class));
          cfc.setReturnValue(mf);
  
          cf.createClass();
  
          cfc.setReturnValue(String.class);
  
          replayControls();
  
          AdaptorRegistryFactory f = new AdaptorRegistryFactory();
          f.setClassFactory(factory);
  
          f.buildImplementationClass(fp, "NewClass", loader);
  
          verifyControls();
      }
  
      public void testIntegration() throws Exception
      {
          Registry r = buildFrameworkRegistry("AdaptorFactoryIntegration.xml");
  
          ToStringAdaptor ts = (ToStringAdaptor) r.getService(ToStringAdaptor.class);
  
          assertEquals("5150", ts.toString(new Integer(5150)));
      }
  }
  
  
  1.1                  jakarta-hivemind/library/src/java/org/apache/hivemind/lib/util/AdaptorRegistryImpl.java
  
  Index: AdaptorRegistryImpl.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.util;
  
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.Map;
  import java.util.WeakHashMap;
  
  import org.apache.hivemind.Defense;
  import org.apache.hivemind.service.ClassFabUtils;
  
  /**
   * Thread-safe implementation of {@link org.apache.hivemind.lib.util.AdaptorRegistry}.
   * 
   * @author Howard Lewis Ship
   * @since 1.1
   */
  
  public class AdaptorRegistryImpl implements AdaptorRegistry
  {
      /**
       * A Map of adaptor objects, keyed on registration Class.
       */
  
      private Map _registrations = new HashMap();
  
      /**
       * A Map of adaptor objects, keyed on subject Class.
       */
  
      private Map _cache = new WeakHashMap();
  
      public synchronized void register(Class registrationClass, Object adaptor)
      {
          Defense.notNull(registrationClass, "registrationClass");
          Defense.notNull(adaptor, "adaptor");
  
          if (_registrations.containsKey(registrationClass))
              throw new IllegalArgumentException(UtilMessages
                      .duplicateRegistration(registrationClass));
  
          _registrations.put(registrationClass, adaptor);
  
          // Can't tell what is and isn't valid in the cache.
          // Also, normally all registrations occur before any adaptors
          // are searched for, so this is not a big deal.
  
          _cache.clear();
      }
  
      public synchronized Object getAdaptor(Class subjectClass)
      {
          Defense.notNull(subjectClass, "subjectClass");
  
          Object result = _cache.get(subjectClass);
  
          if (result != null)
              return result;
  
          result = searchForAdaptor(subjectClass);
  
          // Record the result in the cache
  
          _cache.put(subjectClass, result);
  
          return result;
      }
  
      /**
       * Searches the registration Map for a match, based on inheritance.
       * <p>
       * Searches class inheritance first, then interfaces (in a rather vague order). Really should
       * match the order from the JVM spec.
       * <p>
       * There's a degenerate case where we may check the same interface more than once:
       * <ul>
       * <li>Two interfaces, I1 and I2
       * <li>Two classes, C1 and C2
       * <li>I2 extends I1
       * <li>C2 extends C1
       * <li>C1 implements I1
       * <li>C2 implements I2
       * <li>The search will be: C2, C1, I2, I1, I1
       * <li>I1 is searched twice, because C1 implements it, and I2 extends it
       * <li>There are other such cases, but none of them cause infinite loops and most are rare (we
       * could guard against it, but its relatively expensive).
       * <li>Multiple checks only occur if we don't find a registration
       * </ul>
       * <p>
       * This method is only called from a synchronized block, so it is implicitly synchronized.
       */
  
      private Object searchForAdaptor(Class subjectClass)
      {
          LinkedList queue = null;
          Object result = null;
  
          // Step one: work up through the class inheritance.
  
          Class searchClass = subjectClass;
  
          // Primitive types have null, not Object, as their parent
          // class.
  
          while (searchClass != Object.class && searchClass != null)
          {
              result = _registrations.get(searchClass);
              if (result != null)
                  return result;
  
              // Not an exact match. If the search class
              // implements any interfaces, add them to the queue.
  
              Class[] interfaces = searchClass.getInterfaces();
              int length = interfaces.length;
  
              if (queue == null && length > 0)
                  queue = new LinkedList();
  
              for (int i = 0; i < length; i++)
                  queue.addLast(interfaces[i]);
  
              // Advance up to the next superclass
  
              searchClass = getSuperclass(searchClass);
  
          }
  
          // Ok, the easy part failed, lets start searching
          // interfaces.
  
          if (queue != null)
          {
              while (!queue.isEmpty())
              {
                  searchClass = (Class) queue.removeFirst();
  
                  result = _registrations.get(searchClass);
                  if (result != null)
                      return result;
  
                  // Interfaces can extend other interfaces; add them
                  // to the queue.
  
                  Class[] interfaces = searchClass.getInterfaces();
                  int length = interfaces.length;
  
                  for (int i = 0; i < length; i++)
                      queue.addLast(interfaces[i]);
              }
          }
  
          // Not a match on interface; our last gasp is to check
          // for a registration for java.lang.Object
  
          result = _registrations.get(Object.class);
          if (result != null)
              return result;
  
          // No match? That's rare ... and an error.
  
          throw new IllegalArgumentException(UtilMessages.adaptorNotFound(subjectClass));
      }
  
      /**
       * Returns the superclass of the given class, with a single tweak: If the search class is an
       * array class, and the component type is an object class (but not Object), then the simple
       * Object array class is returned. This reflects the fact that an array of any class may be
       * assignable to <code>Object[]</code>, even though the superclass of an array is always
       * simply <code>Object</code>.
       */
  
      private Class getSuperclass(Class searchClass)
      {
          if (searchClass.isArray())
          {
              Class componentType = searchClass.getComponentType();
  
              if (!componentType.isPrimitive() && componentType != Object.class)
                  return Object[].class;
          }
  
          return searchClass.getSuperclass();
      }
  
      public synchronized String toString()
      {
          StringBuffer buffer = new StringBuffer();
          buffer.append("AdaptorRegistry[");
  
          Iterator i = _registrations.entrySet().iterator();
          boolean showSep = false;
  
          while (i.hasNext())
          {
              if (showSep)
                  buffer.append(' ');
  
              Map.Entry entry = (Map.Entry) i.next();
  
              Class registeredClass = (Class) entry.getKey();
  
              buffer.append(ClassFabUtils.getJavaClassName(registeredClass));
              buffer.append("=");
              buffer.append(entry.getValue());
  
              showSep = true;
          }
  
          buffer.append("]");
  
          return buffer.toString();
      }
  }
  
  
  1.1                  jakarta-hivemind/library/src/java/org/apache/hivemind/lib/util/AdaptorRegistry.java
  
  Index: AdaptorRegistry.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.util;
  
  /**
   * An implementation of the <b>Adaptor </b> pattern. The adaptor pattern allows new functionality to
   * be assigned to an existing class. As implemented here, this is a smart lookup between a
   * particular class (the class to be adapted, called the <em>subject class</em>) and some object
   * instance that can provide the extra functionality (called the <em>adaptor</em>). The
   * implementation of the adaptor is not relevant to the AdaptorRegistry class.
   * <p>
   * Adaptors are registered before they can be used; the registration maps a particular class to an
   * adaptor instance. The adaptor instance will be used when the subject class matches the registered
   * class, or the subject class inherits from the registered class.
   * <p>
   * This means that a search must be made that walks the inheritance tree (upwards from the subject
   * class) to find a registered mapping.
   * <p>
   * In addition, adaptors can be registered against <em>interfaces</em>. Searching of interfaces
   * occurs after searching of classes. The exact order is:
   * <ul>
   * <li>Search for the subject class, then each super-class of the subject class (excluding
   * java.lang.Object)
   * <li>Search interfaces, starting with interfaces implemented by the subject class, continuing
   * with interfaces implemented by the super-classes, then interfaces extended by earlier interfaces
   * (the exact order is a bit fuzzy)
   * <li>Search for a match for java.lang.Object, if any
   * </ul>
   * <p>
   * The first match terminates the search.
   * <p>
   * The AdaptorRegistry caches the results of search; a subsequent search for the same subject class
   * will be resolved immediately.
   * <p>
   * AdaptorRegistry does a minor tweak of the "natural" inheritance. Normally, the parent class of an
   * object array (i.e., <code>Foo[]</code>) is simply <code>Object</code>, even though you may
   * assign <code>Foo[]</code> to a variable of type <code>Object[]</code>. AdaptorRegistry
   * "fixes" this by searching for <code>Object[]</code> as if it was the superclass of any object
   * array. This means that the search path for <code>Foo[]</code> is <code>Foo[]</code>,
   * <code>Object[]</code>, then a couple of interfaces {@link java.lang.Cloneable},
   * {@link java.io.Serializable}, etc. that are implicitily implemented by arrays), and then,
   * finally, <code>Object</code>
   * <p>
   * This tweak doesn't apply to arrays of primitives, since such arrays may <em>not</em> be
   * assigned to <code>Object[]</code>.
   * 
   * @author Howard M. Lewis Ship
   * @see org.apache.hivemind.lib.util.AdaptorRegistryImpl
   * @since 1.1
   */
  public interface AdaptorRegistry
  {
      /**
       * Registers an adaptor for a registration class.
       * 
       * @throws IllegalArgumentException
       *             if an adaptor has already been registered for the given class.
       */
      public void register(Class registrationClass, Object adaptor);
  
      /**
       * Gets the adaptor for the specified subjectClass.
       * 
       * @throws IllegalArgumentException
       *             if no adaptor could be found.
       */
      public Object getAdaptor(Class subjectClass);
  }
  
  
  1.1                  jakarta-hivemind/library/src/java/org/apache/hivemind/lib/util/UtilMessages.java
  
  Index: UtilMessages.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.util;
  
  import org.apache.hivemind.impl.MessageFormatter;
  import org.apache.hivemind.service.ClassFabUtils;
  
  /**
   * @author Howard M. Lewis Ship
   * @since 1.1
   */
  class UtilMessages
  {
      private static final MessageFormatter _formatter = new MessageFormatter(UtilMessages.class,
              "UtilStrings");
  
      public static String duplicateRegistration(Class subjectClass)
      {
          return _formatter.format("duplicate-registration", ClassFabUtils
                  .getJavaClassName(subjectClass));
      }
  
      public static String adaptorNotFound(Class subjectClass)
      {
          return _formatter.format("adaptor-not-found", ClassFabUtils.getJavaClassName(subjectClass));
      }
  }
  
  
  1.1                  jakarta-hivemind/library/src/java/org/apache/hivemind/lib/util/UtilStrings.properties
  
  Index: UtilStrings.properties
  ===================================================================
  #
  # 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.
  
  duplicate-registration=A registration for class {0} already exists.
  adaptor-not-found=Could not find an adaptor for class {0}.
  
  
  1.7       +1 -1      jakarta-hivemind/library/src/documentation/content/xdocs/hivemind-lib/PipelineFactory.xml
  
  Index: PipelineFactory.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/library/src/documentation/content/xdocs/hivemind-lib/PipelineFactory.xml,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- PipelineFactory.xml	21 Oct 2004 12:35:56 -0000	1.6
  +++ PipelineFactory.xml	5 Nov 2004 15:58:34 -0000	1.7
  @@ -26,7 +26,7 @@
     </header>
     <body>
       <p>The <link href="&hivedoc;/service/hivemind.lib.PipelineFactory.html"> 
  -      PipelineFactory</link> services is used to construct a <em>pipeline</em> 
  +      PipelineFactory</link> service is used to construct a <em>pipeline</em> 
         consisting of a series of filters. The filters implement an interface 
         related to the service interface.</p>
       <p> Each method of the service interface has a corresponding method in the 
  
  
  
  1.1                  jakarta-hivemind/library/src/documentation/content/xdocs/hivemind-lib/AdaptorRegistryFactory.xml
  
  Index: AdaptorRegistryFactory.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.3//EN" 
    "http://xml.apache.org/forrest/dtd/document-v13.dtd" [
    <!ENTITY projectroot '../'>
    <!ENTITY % common-links SYSTEM "../links.ent">
    %common-links;
    ]>
  <document>
    <header>
      <title>hivemind.lib.AdaptorRegistryFactory Service</title>
    </header>
    <body>
      <p>The <link href="&hivedoc;/service/hivemind.lib.AdaptorRegistryFactory.html"> 
        AdaptorRegistryFactory</link> service is used to create a service implementation
        based on a service interface and a number of <em>adaptors</em> implementing that interface.</p>
        <p>
          The class of the first parameter of each method is used to select the correct adaptor to
          delegate the method invocation to.  
        </p>
        <p>
          The class-to-adaptor lookup understands inheritance. If an exact match for a class is not found,
          then the search works up the inheritance chain.  First, it checks all the super-classes, working upwards,
          but skipping java.lang.Object. It then searches all the interfaces directly or indirectly implemented by
          the search class.  Finally, java.lang.Object is checked.  It is an exception if no match is found (so you should
          almost always include an adaptor for java.lang.Object).
        </p>
        
        
      <section>
        <title>Usage</title>
        <p> The factory expects a single parameter element: </p>
        <source><![CDATA[
  <construct configuration-id="..."/>]]></source>
        <p>The <code>configuration-id</code> is the id of the companion 
          configuration (used to define classes and adaptors).</p>
      </section>
      <section>
        <title>Configuration</title>
        <p>Each AdaptorRegistry service must have a configuration, into which adaptors 
          are contributed:</p>
        <source><![CDATA[
  <configuration-point id="..." schema-id="hivemind.lib.AdaptorRegistry"/>]]></source>
      </section>
      <section>
        <title>Contributions</title>
        <p>Contributions into the configuration are used to specify classes to match, and the adaptors to use.</p>
        <section>
          <title>adaptor</title>
          <source><![CDATA[
  <adaptor class="..." object="..."/>]]> </source>
          <p>Contributes an adaptor. The <code>class</code> attribute defines the class to match against, the 
            <code>object</code> attribute provides the actual adaptor object (which must implement the service 
            interface). </p>
        </section>
      </section>
    </body>
  </document>
  
  
  1.1                  jakarta-hivemind/framework/src/java/org/apache/hivemind/test/ArrayMatcher.java
  
  Index: ArrayMatcher.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.test;
  
  /**
   * Used when the arguments to compare are a non-primitive array type.
   * 
   * @author Howard M. Lewis Ship
   * @since 1.1
   */
  public class ArrayMatcher implements ArgumentMatcher
  {
  
      public boolean matches(Object expected, Object actual)
      {
          Object[] e = (Object[]) expected;
          Object[] a = (Object[]) actual;
  
          if (a == null)
              return false;
  
          if (e.length != a.length)
              return false;
  
          for (int i = 0; i < e.length; i++)
          {
              if (!e[i].equals(a[i]))
                  return false;
          }
  
          return true;
      }
  
  }
  
  
  1.76      +3 -0      jakarta-hivemind/status.xml
  
  Index: status.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/status.xml,v
  retrieving revision 1.75
  retrieving revision 1.76
  diff -u -r1.75 -r1.76
  --- status.xml	4 Nov 2004 03:19:20 -0000	1.75
  +++ status.xml	5 Nov 2004 15:58:35 -0000	1.76
  @@ -85,6 +85,9 @@
         <action type="add" dev="HLS">
           Add toString() support to ClassFab and MethodFab.
         </action>
  +      <action type="add" dev="HLS">
  +        Add the hivemind.lib.AdaptorRegistryFactory service implementation factory.
  +      </action>
       </release>
   
      <release version="1.0" date="Sep 22 2004">
  
  
  
  1.3       +5 -0      jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ServiceImplementationFactoryParametersImpl.java
  
  Index: ServiceImplementationFactoryParametersImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ServiceImplementationFactoryParametersImpl.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ServiceImplementationFactoryParametersImpl.java	4 Nov 2004 14:32:32 -0000	1.2
  +++ ServiceImplementationFactoryParametersImpl.java	5 Nov 2004 15:58:35 -0000	1.3
  @@ -92,4 +92,9 @@
       {
           return _parameters;
       }
  +
  +    public Object getFirstParameter()
  +    {
  +        return _parameters.get(0);
  +    }
   }
  
  
  
  1.3       +7 -0      jakarta-hivemind/framework/src/java/org/apache/hivemind/ServiceImplementationFactoryParameters.java
  
  Index: ServiceImplementationFactoryParameters.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/ServiceImplementationFactoryParameters.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ServiceImplementationFactoryParameters.java	4 Nov 2004 14:32:33 -0000	1.2
  +++ ServiceImplementationFactoryParameters.java	5 Nov 2004 15:58:35 -0000	1.3
  @@ -62,5 +62,12 @@
        * there will only be a single element in the list.
        */
       public List getParameters();
  +    
  +    /**
  +     * Returns the first parameter passed to the factory (since most factories
  +     * take exactly one parameter, this is the most common usage).
  +     */
  +    
  +    public Object getFirstParameter();
   
   }
  
  
  
  1.5       +47 -14    jakarta-hivemind/framework/src/java/org/apache/hivemind/service/ClassFabUtils.java
  
  Index: ClassFabUtils.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/service/ClassFabUtils.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ClassFabUtils.java	14 Sep 2004 17:56:51 -0000	1.4
  +++ ClassFabUtils.java	5 Nov 2004 15:58:35 -0000	1.5
  @@ -43,10 +43,9 @@
       }
   
       /**
  -     * Javassist needs the class name to be as it appears in source code, even
  -     * for arrays. Invoking getName() on a Class instance representing an array
  -     * returns the internal format (i.e, "[...;" or something). This returns it
  -     * as it would appear in Java code.
  +     * Javassist needs the class name to be as it appears in source code, even for arrays. Invoking
  +     * getName() on a Class instance representing an array returns the internal format (i.e, "[...;"
  +     * or something). This returns it as it would appear in Java code.
        */
       public static String getJavaClassName(Class inputClass)
       {
  @@ -57,9 +56,8 @@
       }
   
       /**
  -     * Returns true if the method is the standard toString() method. Very few
  -     * interfaces will ever include this method as part of the interface, but we
  -     * have to be sure.
  +     * Returns true if the method is the standard toString() method. Very few interfaces will ever
  +     * include this method as part of the interface, but we have to be sure.
        */
       public static boolean isToString(Method method)
       {
  @@ -73,8 +71,7 @@
       }
   
       /**
  -     * Adds a <code>toString()</code> method to a class that returns a fixed,
  -     * pre-computed value.
  +     * Adds a <code>toString()</code> method to a class that returns a fixed, pre-computed value.
        * 
        * @param classFab
        *            ClassFab used to construct the new class.
  @@ -89,14 +86,13 @@
           buffer.append(QUOTE);
           buffer.append(";");
   
  -        classFab.addMethod(Modifier.PUBLIC, new MethodSignature(String.class, "toString", null, null), buffer
  -                .toString());
  +        classFab.addMethod(Modifier.PUBLIC, new MethodSignature(String.class, "toString", null,
  +                null), buffer.toString());
       }
   
       /**
  -     * Returns the class of an instance. However, if the instance is, in fact, a
  -     * JDK proxy, returns the interfaceClass (because JDK proxies do not work
  -     * with Javassist).
  +     * Returns the class of an instance. However, if the instance is, in fact, a JDK proxy, returns
  +     * the interfaceClass (because JDK proxies do not work with Javassist).
        * 
        * @param instance
        *            the object instance to obtain a class from
  @@ -111,5 +107,42 @@
               return interfaceClass;
   
           return instanceClass;
  +    }
  +
  +    /**
  +     * Adds a method that does nothing. If the method returns a value, it will return null, 0 or
  +     * false (depending on the type).
  +     * 
  +     * @since 1.1
  +     */
  +
  +    public static void addNoOpMethod(ClassFab cf, MethodSignature m)
  +    {
  +        StringBuffer body = new StringBuffer("{ ");
  +
  +        Class returnType = m.getReturnType();
  +
  +        if (returnType != void.class)
  +        {
  +            body.append("return");
  +
  +            if (returnType.isPrimitive())
  +            {
  +                if (returnType == boolean.class)
  +                    body.append(" false");
  +                else
  +                    body.append(" 0");
  +            }
  +            else
  +            {
  +                body.append(" null");
  +            }
  +
  +            body.append(";");
  +        }
  +
  +        body.append(" }");
  +
  +        cf.addMethod(Modifier.PUBLIC, m, body.toString());
       }
   }
  
  
  
  1.15      +53 -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.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- hivemodule.xml	27 Sep 2004 14:38:01 -0000	1.14
  +++ hivemodule.xml	5 Nov 2004 15:58:35 -0000	1.15
  @@ -290,4 +290,57 @@
       </parameters-schema>
       
     </service-point>
  +  
  +  
  +  <schema id="AdaptorRegistry">
  +    
  +    Used with the hivemind.lib.AdaptorRegistryFactory to define a set of classes and corresponding
  +    adaptors.
  +    
  +    <element name="adaptor">
  +      
  +      <attribute name="class" translator="class" required="true">
  +        The class (or interface) to register the adaptor against.
  +      </attribute>
  +      
  +      <attribute name="object" translator="object" required="true">
  +        The adaptor that corresponds to objects of the given class.
  +      </attribute>
  +      
  +      <conversion class="org.apache.hivemind.lib.adaptor.AdaptorRegistryContribution">
  +        <map attribute="class" property="registerClass"/>
  +        <map attribute="object" property="adaptor"/>
  +      </conversion>
  +      
  +    </element>
  +    
  +  </schema>
  +  
  +  <service-point id="AdaptorRegistryFactory" interface="org.apache.hivemind.ServiceImplementationFactory">
  +    
  +    Creates a service as a wrapper around an AdaptorRegistry.  The first parameter to
  +    each method of the service interface is used to select an adaptor, and then
  +    the method implementation delegates to that adaptor.
  +    
  +    <invoke-factory>
  +      <construct class="org.apache.hivemind.lib.adaptor.AdaptorRegistryFactory">
  +        <set-service property="classFactory" service-id="hivemind.ClassFactory"/>
  +      </construct>
  +    </invoke-factory>
  +    
  +    <parameters-schema>
  +      <element name="construct">
  +        <attribute name="configuration-id" translator="configuration" required="true">
  +          A configuration utilizing the hivemind.lib.AdaptorRegistry schema, which
  +          defines the classes and matching adaptors.
  +        </attribute>
  +        
  +        <conversion class="org.apache.hivemind.lib.adaptor.AdaptorRegistryParameter">
  +          <map attribute="configuration-id" property="contributions"/>
  +        </conversion>
  +      </element>
  +    </parameters-schema>
  +    
  +  </service-point>
  +  
   </module>
  
  
  
  1.3       +34 -0     jakarta-hivemind/framework/src/test/org/apache/hivemind/service/impl/TestClassFabUtils.java
  
  Index: TestClassFabUtils.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/framework/src/test/org/apache/hivemind/service/impl/TestClassFabUtils.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- TestClassFabUtils.java	14 Sep 2004 17:56:50 -0000	1.2
  +++ TestClassFabUtils.java	5 Nov 2004 15:58:35 -0000	1.3
  @@ -14,8 +14,14 @@
   
   package org.apache.hivemind.service.impl;
   
  +import java.lang.reflect.Modifier;
  +
  +import org.apache.hivemind.service.ClassFab;
   import org.apache.hivemind.service.ClassFabUtils;
  +import org.apache.hivemind.service.MethodFab;
  +import org.apache.hivemind.service.MethodSignature;
   import org.apache.hivemind.test.HiveMindTestCase;
  +import org.easymock.MockControl;
   
   /**
    * Tests for {@link org.apache.hivemind.service.ClassFabUtils}
  @@ -38,5 +44,33 @@
           Runnable mock = (Runnable) newMock(Runnable.class);
   
           assertSame(Runnable.class, ClassFabUtils.getInstanceClass(mock, Runnable.class));
  +    }
  +
  +    /** @since 1.1 */
  +    public void testAddNoOpMethod()
  +    {
  +        tryAddNoOpMethod(void.class, "{  }");
  +        tryAddNoOpMethod(String.class, "{ return null; }");
  +        tryAddNoOpMethod(int.class, "{ return 0; }");
  +        tryAddNoOpMethod(boolean.class, "{ return false; }");
  +    }
  +
  +    /** @since 1.1 */
  +    private void tryAddNoOpMethod(Class returnClass, String expectedBody)
  +    {
  +        MethodSignature sig = new MethodSignature(returnClass, "run", null, null);
  +
  +        MockControl control = newControl(ClassFab.class);
  +        ClassFab cf = (ClassFab) control.getMock();
  +        MethodFab mf = (MethodFab) newMock(MethodFab.class);
  +
  +        cf.addMethod(Modifier.PUBLIC, sig, expectedBody);
  +        control.setReturnValue(mf);
  +
  +        replayControls();
  +
  +        ClassFabUtils.addNoOpMethod(cf, sig);
  +
  +        verifyControls();
       }
   }
  
  
  
  1.5       +1 -33     jakarta-hivemind/library/src/java/org/apache/hivemind/lib/impl/DefaultImplementationBuilderImpl.java
  
  Index: DefaultImplementationBuilderImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/library/src/java/org/apache/hivemind/lib/impl/DefaultImplementationBuilderImpl.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DefaultImplementationBuilderImpl.java	13 Sep 2004 14:48:16 -0000	1.4
  +++ DefaultImplementationBuilderImpl.java	5 Nov 2004 15:58:35 -0000	1.5
  @@ -14,7 +14,6 @@
   
   package org.apache.hivemind.lib.impl;
   
  -import java.lang.reflect.Modifier;
   import java.util.Collections;
   import java.util.HashMap;
   import java.util.Map;
  @@ -27,7 +26,6 @@
   import org.apache.hivemind.service.ClassFabUtils;
   import org.apache.hivemind.service.ClassFactory;
   import org.apache.hivemind.service.MethodIterator;
  -import org.apache.hivemind.service.MethodSignature;
   
   /**
    * Implemenation of {@link org.apache.hivemind.lib.DefaultImplementationBuilder}.
  @@ -87,7 +85,7 @@
   
           while (mi.hasNext())
           {
  -            addMethod(cf, mi.next());
  +            ClassFabUtils.addNoOpMethod(cf, mi.next());
           }
   
           if (!mi.getToString())
  @@ -96,36 +94,6 @@
                   ImplMessages.defaultImplementationDescription(interfaceType));
   
           return cf.createClass();
  -    }
  -
  -    private void addMethod(ClassFab cf, MethodSignature m)
  -    {
  -        StringBuffer body = new StringBuffer("{ ");
  -
  -        Class returnType = m.getReturnType();
  -
  -        if (returnType != void.class)
  -        {
  -            body.append("return");
  -
  -            if (returnType.isPrimitive())
  -            {
  -                if (returnType == boolean.class)
  -                    body.append(" false");
  -                else
  -                    body.append(" 0");
  -            }
  -            else
  -            {
  -                body.append(" null");
  -            }
  -
  -            body.append(";");
  -        }
  -
  -        body.append(" }");
  -
  -        cf.addMethod(Modifier.PUBLIC, m, body.toString());
       }
   
       public void setClassFactory(ClassFactory factory)
  
  
  
  1.1                  jakarta-hivemind/framework/src/test/org/apache/hivemind/test/TestArrayMatcher.java
  
  Index: TestArrayMatcher.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.test;
  
  /**
   * Tests for {@link org.apache.hivemind.test.ArrayMatcher}.
   * 
   * @author Howard M. Lewis Ship
   * @since 1.1
   */
  public class TestArrayMatcher extends HiveMindTestCase
  {
      private Object[] _expected = new String[]
      { "fred" };
  
      private ArrayMatcher _matcher = new ArrayMatcher();
  
      public void testActualIsNull()
      {
          assertEquals(false, _matcher.matches(_expected, null));
      }
  
      public void testWrongElementCount()
      {
          assertEquals(false, _matcher.matches(_expected, new Object[]
          { "barney", "wilma" }));
      }
  
      public void testMismatch()
      {
          assertEquals(false, _matcher.matches(_expected, new Object[]
          { "barney" }));
      }
  
      public void testMatch()
      {
          assertEquals(true, _matcher.matches(_expected, new Object[]
          { "fred" }));
      }
  }
  
  
  1.11      +11 -13    jakarta-hivemind/framework/src/java/org/apache/hivemind/order/Orderer.java
  
  Index: Orderer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/order/Orderer.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- Orderer.java	2 Nov 2004 17:46:11 -0000	1.10
  +++ Orderer.java	5 Nov 2004 15:58:35 -0000	1.11
  @@ -83,7 +83,6 @@
        * @param objectType
        *            user presentable name for the type of object to be ordered; used in some error
        *            messages
  -     * @deprecated To be removed in 1.2, use {@link #Orderer(ErrorLog, String) instead.
        */
       public Orderer(ErrorLog errorLog, String objectType)
       {
  @@ -280,20 +279,19 @@
                           null);
                   continue;
               }
  -            else
  +
  +            try
               {
  -                try
  -                {
  -                    node.addDependency(prenode);
  -                }
  -                catch (ApplicationRuntimeException ex)
  -                {
  -                    _errorLog.error(
  -                            OrdererMessages.dependencyCycle(_objectType, ordering, ex),
  -                            HiveMind.getLocation(ordering.getObject()),
  -                            ex);
  -                }
  +                node.addDependency(prenode);
               }
  +            catch (ApplicationRuntimeException ex)
  +            {
  +                _errorLog.error(
  +                        OrdererMessages.dependencyCycle(_objectType, ordering, ex),
  +                        HiveMind.getLocation(ordering.getObject()),
  +                        ex);
  +            }
  +
           }
       }
   
  
  
  

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