PicoContainer
  1. PicoContainer
  2. PICO-130

ComponentParameter does not respect expectedType and behaves different from ConstantParameter

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 1.0-beta-5
    • Component/s: PicoContainer (Java)
    • Labels:
      None
    • Number of attachments :
      3

      Description

      The current implementation of ComponentParameter.resolve(PicoContainer pico, Class expectedType) does not respect the expected type. The Parameter will either return the component mapped to the key or a component of the class type given in the ctor, but will not ensure that the component is compatible to the type.

      === snip ===
      MutablePicoContainer picoContainer = new DefaultPicoContainer();
      Parameter parameter = new ComponentParameter(Touchable.class);
      picoContainer.registerComponentImplementation(Touchable.class, SimpleTouchable.class);
      assertNull(parameter.resolveAdapter(picoContainer, TestCase.class));
      === snap ===

      ConstantParameter instead will throw an AssignabilityRegistrationException.

      Both versions create big problems, if a component is registered with incompatible parameters, because the implementation will normally just try to resolve the parameter and check for a returned null. To support the best fitting ctor respecting a component's parameters from the registration, the returning-null-behaviour is mandatory.

      1. ComponentParameter.java.diff
        0.8 kB
        Jörg Schaible
      2. ConstantParameter.java.diff
        1 kB
        Jörg Schaible
      3. ParameterTestCase.java.diff
        3 kB
        Jörg Schaible

        Activity

        Hide
        Jörg Schaible added a comment -

        src/java/org/picocontainer/defaults/ConstantParameter.java

        With this patch resolveAdapter returns null in case of an AssignabilityRegistrationException.

        Show
        Jörg Schaible added a comment - src/java/org/picocontainer/defaults/ConstantParameter.java With this patch resolveAdapter returns null in case of an AssignabilityRegistrationException.
        Jörg Schaible made changes -
        Field Original Value New Value
        Attachment ConstantParameter.java.diff [ 11378 ]
        Hide
        Jörg Schaible added a comment -

        src/java/org/picocontainer/defaults/ComponentParameter.java

        With this patch resolveAdapter returns null if the parameter references an adapter not compatible to the expected type.

        Show
        Jörg Schaible added a comment - src/java/org/picocontainer/defaults/ComponentParameter.java With this patch resolveAdapter returns null if the parameter references an adapter not compatible to the expected type.
        Jörg Schaible made changes -
        Attachment ComponentParameter.java.diff [ 11379 ]
        Hide
        Jörg Schaible added a comment -

        src/test/org/picocontainer/defaults/ParameterTestCase.java

        Test case for incompatible parameter types.

        Additional test case for native types in ConstantParameter, since I broke this with an interim version unintentionally.

        Show
        Jörg Schaible added a comment - src/test/org/picocontainer/defaults/ParameterTestCase.java Test case for incompatible parameter types. Additional test case for native types in ConstantParameter, since I broke this with an interim version unintentionally.
        Jörg Schaible made changes -
        Attachment ParameterTestCase.java.diff [ 11380 ]
        Hide
        Jörg Schaible added a comment -

        Sorry, missed to set the issue details right:
        This is an enhancement and probably not major.

        Show
        Jörg Schaible added a comment - Sorry, missed to set the issue details right: This is an enhancement and probably not major.
        Hide
        Aslak Hellesøy added a comment -

        Fixed - with a slightly different implementation. Both ComponentParameter and ConstantParameter should follow the same contract now.

        Show
        Aslak Hellesøy added a comment - Fixed - with a slightly different implementation. Both ComponentParameter and ConstantParameter should follow the same contract now.
        Aslak Hellesøy made changes -
        Status Open [ 1 ] Closed [ 6 ]
        Assignee Aslak Hellesoy [ rinkrank ]
        Resolution Fixed [ 1 ]
        Fix Version/s 1.0-beta-5 [ 10145 ]
        Hide
        Jörg Schaible added a comment -

        Hi Aslak,

        sorry causing you work. I noticed this problem for ConstantParameter meanwhile too and had another implementation using reflection. Because I cannot create attachments to closed issues, I just post it here. This one will also succeed your new tests. So, take it or leave it. I do not know which implementation is really more efficient.

        ======= snip ========
        Index: src/java/org/picocontainer/defaults/ConstantParameter.java
        ===================================================================
        RCS file: /cvsroot/picocontainer/java/picocontainer/src/java/org/picocontainer/defaults/ConstantParameter.java,v
        retrieving revision 1.15
        diff -u -r1.15 ConstantParameter.java
        — src/java/org/picocontainer/defaults/ConstantParameter.java 10 Feb 2004 02:36:54 -0000 1.15
        +++ src/java/org/picocontainer/defaults/ConstantParameter.java 10 Feb 2004 03:19:35 -0000
        @@ -10,6 +10,8 @@

        package org.picocontainer.defaults;

        +import java.lang.reflect.Field;
        +
        import org.picocontainer.ComponentAdapter;
        import org.picocontainer.Parameter;
        import org.picocontainer.PicoContainer;
        @@ -21,7 +23,7 @@
        *

        • @author Jon Tirsén
        • @author Aslak Hellesøy
        • * @version $Revision: 1.15 $
          + * @version $Revision: 1.13 $
          */
          public class ConstantParameter implements Parameter { private final Object value; @@ -30,44 +32,30 @@ this.value = value; }
        • public ComponentAdapter resolveAdapter(PicoContainer picoContainer, Class expectedType) throws NotConcreteRegistrationException {
        • if(!expectedType.isAssignableFrom(value.getClass())) {
        • if (expectedType.isPrimitive()) {
        • if(!primitiveMatches(expectedType, value.getClass())) { - return null; - }
        • } else {
        • return null;
          + public ComponentAdapter resolveAdapter(PicoContainer picoContainer, Class expectedType) throws AssignabilityRegistrationException, NotConcreteRegistrationException {
          + ComponentAdapter result = null;
          + if(expectedType.isAssignableFrom(value.getClass())) { + result = new InstanceComponentAdapter(value, value); + }

          else if (expectedType.isPrimitive()) {
          + try

          Unknown macro: {+ Field field = value.getClass().getField("TYPE");+ Class type = (Class)field.get(value);+ if (expectedType.isAssignableFrom(type)) { + result = new InstanceComponentAdapter(value, value); + } else { + result = null; + }+ + }

          catch (NoSuchFieldException e)

          { + result = null; + } catch (IllegalArgumentException e) { + result = null; + }

          catch (IllegalAccessException e)

          { + result = null; + }

          catch (ClassCastException e)

          { + result = null; }

          }

        • return new InstanceComponentAdapter(value, value);
        • }
          -
        • private boolean primitiveMatches(Class expectedPrimitiveType, Class constantClass) {
        • if(expectedPrimitiveType.equals(Byte.class) || expectedPrimitiveType.equals(Byte.TYPE)) { - return constantClass.equals(Byte.class) || constantClass.equals(Byte.TYPE); - }
        • if(expectedPrimitiveType.equals(Short.class) || expectedPrimitiveType.equals(Short.TYPE)) { - return constantClass.equals(Short.class) || constantClass.equals(Short.TYPE); - }
        • if(expectedPrimitiveType.equals(Integer.class) || expectedPrimitiveType.equals(Integer.TYPE)) { - return constantClass.equals(Integer.class) || constantClass.equals(Integer.TYPE); - }
        • if(expectedPrimitiveType.equals(Long.class) || expectedPrimitiveType.equals(Long.TYPE)) { - return constantClass.equals(Long.class) || constantClass.equals(Long.TYPE); - }
        • if(expectedPrimitiveType.equals(Float.class) || expectedPrimitiveType.equals(Float.TYPE)) { - return constantClass.equals(Float.class) || constantClass.equals(Float.TYPE); - }
        • if(expectedPrimitiveType.equals(Double.class) || expectedPrimitiveType.equals(Double.TYPE)) { - return constantClass.equals(Double.class) || constantClass.equals(Double.TYPE); - }
        • if(expectedPrimitiveType.equals(Boolean.class) || expectedPrimitiveType.equals(Boolean.TYPE)) { - return constantClass.equals(Boolean.class) || constantClass.equals(Boolean.TYPE); - }
        • if(expectedPrimitiveType.equals(Character.class) || expectedPrimitiveType.equals(Character.TYPE)) { - return constantClass.equals(Character.class) || constantClass.equals(Character.TYPE); - }
        • return false;
          + return result;
          }
          }
          ======= snap ========
        Show
        Jörg Schaible added a comment - Hi Aslak, sorry causing you work. I noticed this problem for ConstantParameter meanwhile too and had another implementation using reflection. Because I cannot create attachments to closed issues, I just post it here. This one will also succeed your new tests. So, take it or leave it. I do not know which implementation is really more efficient. ======= snip ======== Index: src/java/org/picocontainer/defaults/ConstantParameter.java =================================================================== RCS file: /cvsroot/picocontainer/java/picocontainer/src/java/org/picocontainer/defaults/ConstantParameter.java,v retrieving revision 1.15 diff -u -r1.15 ConstantParameter.java — src/java/org/picocontainer/defaults/ConstantParameter.java 10 Feb 2004 02:36:54 -0000 1.15 +++ src/java/org/picocontainer/defaults/ConstantParameter.java 10 Feb 2004 03:19:35 -0000 @@ -10,6 +10,8 @@ package org.picocontainer.defaults; +import java.lang.reflect.Field; + import org.picocontainer.ComponentAdapter; import org.picocontainer.Parameter; import org.picocontainer.PicoContainer; @@ -21,7 +23,7 @@ * @author Jon Tirsén @author Aslak Hellesøy * @version $Revision: 1.15 $ + * @version $Revision: 1.13 $ */ public class ConstantParameter implements Parameter { private final Object value; @@ -30,44 +32,30 @@ this.value = value; } public ComponentAdapter resolveAdapter(PicoContainer picoContainer, Class expectedType) throws NotConcreteRegistrationException { if(!expectedType.isAssignableFrom(value.getClass())) { if (expectedType.isPrimitive()) { if(!primitiveMatches(expectedType, value.getClass())) { - return null; - } } else { return null; + public ComponentAdapter resolveAdapter(PicoContainer picoContainer, Class expectedType) throws AssignabilityRegistrationException, NotConcreteRegistrationException { + ComponentAdapter result = null; + if(expectedType.isAssignableFrom(value.getClass())) { + result = new InstanceComponentAdapter(value, value); + } else if (expectedType.isPrimitive()) { + try Unknown macro: {+ Field field = value.getClass().getField("TYPE");+ Class type = (Class)field.get(value);+ if (expectedType.isAssignableFrom(type)) { + result = new InstanceComponentAdapter(value, value); + } else { + result = null; + }+ + } catch (NoSuchFieldException e) { + result = null; + } catch (IllegalArgumentException e) { + result = null; + } catch (IllegalAccessException e) { + result = null; + } catch (ClassCastException e) { + result = null; } } return new InstanceComponentAdapter(value, value); } - private boolean primitiveMatches(Class expectedPrimitiveType, Class constantClass) { if(expectedPrimitiveType.equals(Byte.class) || expectedPrimitiveType.equals(Byte.TYPE)) { - return constantClass.equals(Byte.class) || constantClass.equals(Byte.TYPE); - } if(expectedPrimitiveType.equals(Short.class) || expectedPrimitiveType.equals(Short.TYPE)) { - return constantClass.equals(Short.class) || constantClass.equals(Short.TYPE); - } if(expectedPrimitiveType.equals(Integer.class) || expectedPrimitiveType.equals(Integer.TYPE)) { - return constantClass.equals(Integer.class) || constantClass.equals(Integer.TYPE); - } if(expectedPrimitiveType.equals(Long.class) || expectedPrimitiveType.equals(Long.TYPE)) { - return constantClass.equals(Long.class) || constantClass.equals(Long.TYPE); - } if(expectedPrimitiveType.equals(Float.class) || expectedPrimitiveType.equals(Float.TYPE)) { - return constantClass.equals(Float.class) || constantClass.equals(Float.TYPE); - } if(expectedPrimitiveType.equals(Double.class) || expectedPrimitiveType.equals(Double.TYPE)) { - return constantClass.equals(Double.class) || constantClass.equals(Double.TYPE); - } if(expectedPrimitiveType.equals(Boolean.class) || expectedPrimitiveType.equals(Boolean.TYPE)) { - return constantClass.equals(Boolean.class) || constantClass.equals(Boolean.TYPE); - } if(expectedPrimitiveType.equals(Character.class) || expectedPrimitiveType.equals(Character.TYPE)) { - return constantClass.equals(Character.class) || constantClass.equals(Character.TYPE); - } return false; + return result; } } ======= snap ========

          People

          • Assignee:
            Aslak Hellesøy
            Reporter:
            Jörg Schaible
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Time Tracking

              Estimated:
              Original Estimate - 10 minutes
              10m
              Remaining:
              Remaining Estimate - 10 minutes
              10m
              Logged:
              Time Spent - Not Specified
              Not Specified