[jboss-cvs] JBossAS SVN: r98906 - in projects/kernel/trunk/kernel/src: main/java/org/jboss/beans/metadata/plugins/builder and 10 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Dec 23 09:38:25 EST 2009


Author: kabir.khan at jboss.com
Date: 2009-12-23 09:38:24 -0500 (Wed, 23 Dec 2009)
New Revision: 98906

Added:
   projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/
   projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/AnnotationQualiferParser.java
   projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/DefaultEqualsMatcher.java
   projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/StringQualifierParser.java
   projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierMatcher.java
   projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierParser.java
   projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/support/TestMatcherAndParser.java
   projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/deployment/xml/test/QualifierBeanNonStandardContent.xml
   projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/deployment/xml/test/QualifierInjectNonStandardContent.xml
   projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomBeanQualifiers_Not_Automatic.xml
   projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomConstructorQualifiers_Not_Automatic.xml
   projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomMethodQualifiers_Not_Automatic.xml
   projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomPropertyQualifiers_Not_Automatic.xml
Removed:
   projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/Matcher.java
Modified:
   projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractBeanQualifierMetaData.java
   projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractInjectQualifierMetaData.java
   projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractQualifierMetaData.java
   projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/builder/BeanMetaDataBuilderImpl.java
   projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/spi/builder/BeanMetaDataBuilder.java
   projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/dependency/QualifiersMdrUtil.java
   projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierMatchers.java
   projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/deployment/xml/test/QualifierTestCase.java
   projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/BeanQualifiersTestCase.java
   projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/InjectionPointQualifiersTestCase.java
   projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase.java
Log:
[JBKERNEL-70] Support adding new qualifier contents, parsing them via a QualifierParser and matching using a QualfierMatcher. Get rid of all the new BeanMetaDataBuilder.createContextualInject() methods involving qualifiers since the number of overloaded methods got too confusing, and add BMDB.addQualifiersToContextualInject() instead

Modified: projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractBeanQualifierMetaData.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractBeanQualifierMetaData.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractBeanQualifierMetaData.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -29,6 +29,7 @@
 import org.jboss.beans.metadata.api.model.QualifierPoint;
 import org.jboss.beans.metadata.api.model.QualifierType;
 import org.jboss.kernel.plugins.dependency.QualifiersMdrUtil;
+import org.jboss.kernel.spi.qualifier.QualifierParser;
 
 /**
  * Qualifier Metadata for a bean's qualifiers
@@ -95,5 +96,13 @@
    {
       return points;
    }
-   
+
+   @Override
+   protected Object parse(ClassLoader cl, QualifierParser parser, Object enabled)
+   {
+      if (getType() == QualifierType.SUPPLIED)
+         return parser.parseSupplied(cl, enabled);
+      else
+         return parser.parseWanted(cl, enabled);
+   }
 }

Modified: projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractInjectQualifierMetaData.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractInjectQualifierMetaData.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractInjectQualifierMetaData.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -26,6 +26,7 @@
 import javax.xml.bind.annotation.XmlType;
 
 import org.jboss.kernel.plugins.dependency.QualifiersMdrUtil;
+import org.jboss.kernel.spi.qualifier.QualifierParser;
 
 /**
  * Qualifier Metadata for an injection point's qualifiers
@@ -49,4 +50,9 @@
       setEnabled(qualifiers);
    }
 
+   @Override
+   protected Object parse(ClassLoader cl, QualifierParser parser, Object enabled)
+   {
+      return parser.parseWanted(cl, enabled);
+   }
 }

Modified: projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractQualifierMetaData.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractQualifierMetaData.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/AbstractQualifierMetaData.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -21,14 +21,14 @@
 */ 
 package org.jboss.beans.metadata.plugins;
 
-import java.lang.annotation.Annotation;
 import java.util.HashSet;
 import java.util.Set;
 
 import javax.xml.bind.annotation.XmlAttribute;
 
-import org.jboss.annotation.factory.AnnotationCreator;
 import org.jboss.beans.metadata.api.model.QualifierContent;
+import org.jboss.kernel.spi.qualifier.QualifierMatchers;
+import org.jboss.kernel.spi.qualifier.QualifierParser;
 
 /**
  * Abstract Qualifier MetaData. Qualifiers are used to narrow down what is injected
@@ -43,7 +43,7 @@
    
    private volatile QualifierContent content = QualifierContent.STRING;
    
-   private volatile Set<Object> annotations;
+   private volatile Set<Object> parsedQualifiers;
    
    public AbstractQualifierMetaData()
    {
@@ -87,48 +87,26 @@
    {
       return getEnabled((ClassLoader)null);
    }
-
+   
    public Set<Object> getEnabled(ClassLoader cl)
    {
-      if (content == QualifierContent.STRING)
-         return super.getEnabled();
+      Set<Object> enableds = super.getEnabled();
+      if (enableds == null || enableds.size() == 0)
+         return enableds;
       
-      if (content == QualifierContent.ANNOTATION)
+      QualifierParser parser = QualifierMatchers.getInstance().getParser(content);
+
+      if (parsedQualifiers == null)
       {
-         if (annotations == null)
+         Set<Object> qualifiers = new HashSet<Object>();
+         for(Object enabled : enableds)
          {
-            Set<Object> anns = new HashSet<Object>();
-            for (Object enabled : super.getEnabled())
-            {
-               anns.add(parseAnnotation(cl, enabled));
-            }
-            annotations = anns;
+            qualifiers.add(parse(cl, parser, enabled));
          }
-         return annotations;
+         parsedQualifiers = qualifiers;
       }
-      
-      throw new IllegalStateException("Unknown content type " + content);
+      return parsedQualifiers;
    }
    
-   private Annotation parseAnnotation(ClassLoader cl, Object enabled)
-   {
-      if (enabled instanceof Annotation)
-         return (Annotation)enabled;
-      if (enabled instanceof String == false)
-         throw new IllegalStateException(enabled + " is neither an annotation nor a string");
-         
-      String annString = (String)enabled;
-      try
-      {
-         if (cl == null) 
-         {
-            cl = Thread.currentThread().getContextClassLoader();
-         }
-         return (Annotation)AnnotationCreator.createAnnotation(annString, cl);
-      }
-      catch (Throwable e)
-      {
-         throw new RuntimeException("Error creating annotation for " + enabled, e);
-      }
-   }
+   protected abstract Object parse(ClassLoader cl, QualifierParser parser, Object enabled);
 }

Modified: projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/builder/BeanMetaDataBuilderImpl.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/builder/BeanMetaDataBuilderImpl.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/plugins/builder/BeanMetaDataBuilderImpl.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -35,6 +35,7 @@
 import org.jboss.beans.metadata.api.model.AutowireType;
 import org.jboss.beans.metadata.api.model.FromContext;
 import org.jboss.beans.metadata.api.model.InjectOption;
+import org.jboss.beans.metadata.api.model.QualifierContent;
 import org.jboss.beans.metadata.api.model.QualifierPoint;
 import org.jboss.beans.metadata.api.model.QualifierType;
 import org.jboss.beans.metadata.plugins.AbstractAnnotationMetaData;
@@ -1103,7 +1104,7 @@
       return new AbstractInjectionValueMetaData(name);
    }
 
-   public ValueMetaData createContextualInject(ControllerState whenRequired, ControllerState dependentState, AutowireType autowire, InjectOption option, SearchInfo search, boolean ignoreBeanQualifiers, Object...qualifiers)
+   public ValueMetaData createContextualInject(ControllerState whenRequired, ControllerState dependentState, AutowireType autowire, InjectOption option, SearchInfo search)
    {
       AbstractInjectionValueMetaData result = createAbstractInjectionValueMetaData();
       if (whenRequired != null)
@@ -1116,22 +1117,40 @@
          result.setInjectionOption(option);
       if (search != null)
          result.setSearch(search);
+
+      return result;
+   }
+
+   public ValueMetaData addQualifiersToContextualInject(ValueMetaData inject, QualifierContent content, boolean ignoreBeanQualifiers, Object...qualifiers)
+   {
+      if (inject instanceof AbstractInjectionValueMetaData == false)
+         throw new IllegalArgumentException("inject is not ValueMetaData for a contextual injection");
+
+      AbstractInjectionValueMetaData injection = (AbstractInjectionValueMetaData)inject;
+      injection.setIgnoreBeanQualifiers(ignoreBeanQualifiers);
       if (qualifiers != null && qualifiers.length > 0)
       {
-         HashSet<RelatedClassMetaData> qualifierSet = new HashSet<RelatedClassMetaData>();
+         Set<RelatedClassMetaData> qualifierSet = injection.getQualifiers();
+         if (qualifierSet == null)
+         {
+            qualifierSet = new HashSet<RelatedClassMetaData>();
+            injection.setQualifiers(qualifierSet);
+         }
          
          for (Object qualifier : qualifiers)
          {
             AbstractInjectQualifierMetaData qmd = new AbstractInjectQualifierMetaData();
             qmd.setEnabled(Collections.singleton(qualifier));
             qualifierSet.add(qmd);
+            if (content != null)
+               qmd.setContent(content);
          }
-         result.setQualifiers(qualifierSet);
-         result.setIgnoreBeanQualifiers(ignoreBeanQualifiers);
       }
-      return result;
+
+      
+      return inject;
    }
-
+   
    public ValueMetaData createFromContextInject(FromContext fromContext, Object contextName, ControllerState dependentState, SearchInfo search)
    {
       AbstractInjectionValueMetaData result = createAbstractInjectionValueMetaData(contextName);
@@ -1200,7 +1219,7 @@
       return (Map) map;
    }
 
-   public BeanMetaDataBuilder addQualifiers(QualifierType type, List<QualifierPoint> points, Object...qualifiers)
+   public BeanMetaDataBuilder addQualifiers(QualifierType type, QualifierContent content, List<QualifierPoint> points, Object...qualifiers)
    {
       if (type == QualifierType.SUPPLIED && points != null)
          throw new IllegalArgumentException("Can not specify SUPPLIED and a list of qualifier points");
@@ -1212,6 +1231,8 @@
          beanMetaData.setRelated(relatedClassMetaDatas);
       }
       AbstractBeanQualifierMetaData metaData = new AbstractBeanQualifierMetaData();
+      if (content != null)
+         metaData.setContent(content);
       metaData.setType(type);
       metaData.setEnabled(new HashSet<Object>(Arrays.asList(qualifiers)));
       metaData.setPoints(points);

Modified: projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/spi/builder/BeanMetaDataBuilder.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/spi/builder/BeanMetaDataBuilder.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/beans/metadata/spi/builder/BeanMetaDataBuilder.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -32,6 +32,7 @@
 import org.jboss.beans.metadata.api.model.AutowireType;
 import org.jboss.beans.metadata.api.model.FromContext;
 import org.jboss.beans.metadata.api.model.InjectOption;
+import org.jboss.beans.metadata.api.model.QualifierContent;
 import org.jboss.beans.metadata.api.model.QualifierPoint;
 import org.jboss.beans.metadata.api.model.QualifierType;
 import org.jboss.beans.metadata.plugins.AbstractBeanMetaData;
@@ -1905,7 +1906,26 @@
     * @param qualifiers the qualifiers we want to apply to this bean
     * @return this builder
     */
-   public abstract BeanMetaDataBuilder addQualifiers(QualifierType type, List<QualifierPoint> points, Object...qualifiers);
+   public BeanMetaDataBuilder addQualifiers(QualifierType type, List<QualifierPoint> points, Object...qualifiers)
+   {
+      return addQualifiers(type, null, points, qualifiers);
+   }
+   
+   /**
+    * Create qualifiers for the bean to narrow down the set of candidate contexts of the required when doing contextual injection.
+    * Note that these qualifiers are stored in the set of related classes so take care not to call {@link #setRelated(Set)}
+    * after calling this method.
+    * 
+    * @see BeanMetaData#getRelated()
+    * @param type the type of qualifier to add
+    * @param content how to parse the qualifier content, if null {@link QualifierContent#STRING} is used
+    * @param points the list of injection point types this qualifier applies to. Should be null if {@link QualifierType#SUPPLIED}
+    * was passed in for the 'type' parameter. If null and used with {@link QualifierType#REQUIRED} or {@link QualifierType#OPTIONAL}
+    * it will be applied to all the bean's injection points.
+    * @param qualifiers the qualifiers we want to apply to this bean
+    * @return this builder
+    */
+   public abstract BeanMetaDataBuilder addQualifiers(QualifierType type, QualifierContent content, List<QualifierPoint> points, Object...qualifiers);
 
    /**
     * Create a null value
@@ -2099,42 +2119,6 @@
    }
 
    /**
-    * Create contextual injection, using the default
-    * whenRequired state of {@link ControllerState#CONFIGURED} and the default dependentState of
-    * {@link ControllerState#INSTANTIATED}. This does not need to specify the name of the bean, 
-    * but looks at the target property/parameter type for autowiring
-    *
-    * @see BeanMetaData#isAutowireCandidate()
-    * @param the qualifiers to use to narrow down beans of the matching type. These will come in addition to the bean level ones 
-    * specified in {@link #addRequiredQualifiers(Object...)} and {@link #addOptionalQualifiers(Object...)} and to the ones from higher 
-    * level in the MDR 
-    * @return the contextual injection
-    */
-   public ValueMetaData createContextualInject(Object...qualifiers)
-   {
-      return createContextualInject(null, null, qualifiers);
-   }
-
-   /**
-    * Create contextual injection, using the default
-    * whenRequired state of {@link ControllerState#CONFIGURED} and the default dependentState of
-    * {@link ControllerState#INSTANTIATED}. This does not need to specify the name of the bean, 
-    * but looks at the target property/parameter type for autowiring
-    *
-    * @see BeanMetaData#isAutowireCandidate()
-    * 
-    * @param ignoreBeanQualifiers Whether we should ignore bean level qualifiers and only use the ones specified here. Default is false
-    * @param the qualifiers to use to narrow down beans of the matching type. These will override or come in addition to the bean level ones
-    * specified in {@link #addRequiredQualifiers(Object...)} and {@link #addOptionalQualifiers(Object...)}and to the ones from higher 
-    * levels in the MDR, depending on the value of ignoreBeanQualifiers
-    * @return the contextual injection
-    */
-   public ValueMetaData createContextualInject(boolean ignoreBeanQualifiers, Object...qualifiers)
-   {
-      return createContextualInject(null, null, ignoreBeanQualifiers, qualifiers);
-   }
-
-   /**
     * Create contextual injection. This does not need to specify the name of the bean, 
     * but looks at the target property/parameter type for autowiring
     *
@@ -2153,41 +2137,6 @@
     * but looks at the target property/parameter type for autowiring
     *
     * @see BeanMetaData#isAutowireCandidate()
-    * @param whenRequired when the injection is required. If null {@link ControllerState#CONFIGURED} is used.
-    * @param dependentState the required state of the injected bean. If null {@link ControllerState#INSTALLED} is used.
-    * @param the qualifiers to use to narrow down beans of the matching type. These will come in addition to the ones 
-    * in {@link #addRequiredQualifiers(Object...)} and {@link #addOptionalQualifiers(Object...)} and to the ones from higher 
-    * levels in the MDR 
-    * @return the contextual injection
-    */
-   public ValueMetaData createContextualInject(ControllerState whenRequired, ControllerState dependentState, Object...qualifiers)
-   {
-      return createContextualInject(whenRequired, dependentState, null, null, qualifiers);
-   }
-
-   /**
-    * Create contextual injection. This does not need to specify the name of the bean, 
-    * but looks at the target property/parameter type for autowiring
-    *
-    * @see BeanMetaData#isAutowireCandidate()
-    * @param whenRequired when the injection is required. If null {@link ControllerState#CONFIGURED} is used.
-    * @param dependentState the required state of the injected bean. If null {@link ControllerState#INSTALLED} is used.
-    * @param ignoreBeanQualifiers Whether we should ignore bean level qualifiers and only use the ones specified here. Default is false
-    * @param the qualifiers to use to narrow down beans of the matching type. These will override or come in addition to the bean level ones
-    * specified in {@link #addRequiredQualifiers(Object...)} and {@link #addOptionalQualifiers(Object...)} and to the ones from higher 
-    * levels in the MDR  depending on the value of ignoreBeanQualifiers
-    * @return the contextual injection
-    */
-   public ValueMetaData createContextualInject(ControllerState whenRequired, ControllerState dependentState, boolean ignoreBeanQualifiers, Object...qualifiers)
-   {
-      return createContextualInject(whenRequired, dependentState, null, null, ignoreBeanQualifiers, qualifiers);
-   }
-
-   /**
-    * Create contextual injection. This does not need to specify the name of the bean, 
-    * but looks at the target property/parameter type for autowiring
-    *
-    * @see BeanMetaData#isAutowireCandidate()
     * @see BeanMetaData#getAutowireType()
     * @param whenRequired when the injection is required. If null {@link ControllerState#CONFIGURED} is used.
     * @param dependentState the required state of the injected bean. If null {@link ControllerState#INSTALLED} is used.
@@ -2197,88 +2146,53 @@
     */
    public ValueMetaData createContextualInject(ControllerState whenRequired, ControllerState dependentState, AutowireType autowire, InjectOption option)
    {
-      return createContextualInject(whenRequired, dependentState, autowire, option, null, false, (Object[])null);
+      return createContextualInject(whenRequired, dependentState, autowire, option, null);
    }
 
    /**
     * Create contextual injection. This does not need to specify the name of the bean, 
     * but looks at the target property/parameter type for autowiring
     *
-    * @see BeanMetaData#isAutowireCandidate()
-    * @see BeanMetaData#getAutowireType()
     * @param whenRequired when the injection is required. If null {@link ControllerState#CONFIGURED} is used.
     * @param dependentState the required state of the injected bean. If null {@link ControllerState#INSTALLED} is used.
-    * @param autowire the autowire type. If null, the type is {@link AutowireType#BY_CLASS} 
+    * @param autowire the autowire type
     * @param option the inject option
-    * @param the qualifiers to use to narrow down beans of the matching type. These will come in addition to the ones 
-    * in {@link #addRequiredQualifiers(Object...)} and {@link #addOptionalQualifiers(Object...)} and to the ones from higher 
-    * levels in the MDR  
+    * @param search the search info describing how to search for the injected bean if we have a hierarchy of 
+    * {@link org.jboss.dependency.spi.Controller}s
     * @return the contextual injection
     */
-   public ValueMetaData createContextualInject(ControllerState whenRequired, ControllerState dependentState, AutowireType autowire, InjectOption option, Object...qualifiers)
-   {
-      return createContextualInject(whenRequired, dependentState, autowire, option, null, qualifiers);
-   }
+   public abstract ValueMetaData createContextualInject(ControllerState whenRequired, ControllerState dependentState, AutowireType autowire, InjectOption option, SearchInfo search);
 
+   
    /**
-    * Create contextual injection. This does not need to specify the name of the bean, 
-    * but looks at the target property/parameter type for autowiring
-    *
-    * @see BeanMetaData#isAutowireCandidate()
-    * @see BeanMetaData#getAutowireType()
-    * @param whenRequired when the injection is required. If null {@link ControllerState#CONFIGURED} is used.
-    * @param dependentState the required state of the injected bean. If null {@link ControllerState#INSTALLED} is used.
-    * @param autowire the autowire type. If null, the type is {@link AutowireType#BY_CLASS} 
-    * @param option the inject option
-    * @param ignoreBeanQualifiers Whether we should ignore bean level qualifiers and only use the ones specified here. Default is false
-    * @param the qualifiers to use to narrow down beans of the matching type. These will override or come in addition to the bean level ones
-    * specified in {@link #addRequiredQualifiers(Object...)} and {@link #addOptionalQualifiers(Object...)}and to the ones from higher 
+    * Adds qualifiers to a ValueMetaData created using one of the createContextualInject() methods.
+    * 
+    * @param inject the ValueMetaData containing the contextual inject
+    * @param qualifiers the qualifiers to use to narrow down beans of the matching type. These will override or come in addition to the bean level ones
+    * specified in {@link #addRequiredQualifiers(Object...)} and {@link #addOptionalQualifiers(Object...)} and to the ones from higher 
     * levels in the MDR, depending on the value of ignoreBeanQualifiers
-    * @return the contextual injection
+    * @return the contextual injection ValueMetaData
+    * @throws IllegalArgumentException if the ValueMetaData was not created using the createContextualInject() methods
     */
-   public ValueMetaData createContextualInject(ControllerState whenRequired, ControllerState dependentState, AutowireType autowire, InjectOption option, boolean ignoreBeanQualifiers, Object...qualifiers)
+   public ValueMetaData addQualifiersToContextualInject(ValueMetaData inject, Object...qualifiers)
    {
-      return createContextualInject(whenRequired, dependentState, autowire, option, null, ignoreBeanQualifiers, qualifiers);
+      return addQualifiersToContextualInject(inject, null, false, qualifiers);
    }
-
-
+   
    /**
-    * Create contextual injection. This does not need to specify the name of the bean, 
-    * but looks at the target property/parameter type for autowiring
-    *
-    * @param whenRequired when the injection is required. If null {@link ControllerState#CONFIGURED} is used.
-    * @param dependentState the required state of the injected bean. If null {@link ControllerState#INSTALLED} is used.
-    * @param autowire the autowire type
-    * @param option the inject option
-    * @param search the search info describing how to search for the injected bean if we have a hierarchy of 
-    * {@link org.jboss.dependency.spi.Controller}s
-    * @param the qualifiers to use to narrow down beans of the matching type. These will come in addition to the ones 
-    * in {@link #addRequiredQualifiers(Object...)} and {@link #addOptionalQualifiers(Object...)} and to the ones from higher 
-    * levels in the MDR  
-    * @return the contextual injection
-    */
-   public ValueMetaData createContextualInject(ControllerState whenRequired, ControllerState dependentState, AutowireType autowire, InjectOption option, SearchInfo search, Object...qualifiers)
-   {
-      return createContextualInject(whenRequired, dependentState, autowire, option, search, false, qualifiers);
-   }
-
-   /**
-    * Create contextual injection. This does not need to specify the name of the bean, 
-    * but looks at the target property/parameter type for autowiring
-    *
-    * @param whenRequired when the injection is required. If null {@link ControllerState#CONFIGURED} is used.
-    * @param dependentState the required state of the injected bean. If null {@link ControllerState#INSTALLED} is used.
-    * @param autowire the autowire type
-    * @param option the inject option
-    * @param search the search info describing how to search for the injected bean if we have a hierarchy of 
-    * {@link org.jboss.dependency.spi.Controller}s
-    * @param ignoreBeanQualifiers Whether we should ignore bean level qualifiers and only use the ones specified here. Default is false
-    * @param the qualifiers to use to narrow down beans of the matching type. These will override or come in addition to the bean level ones
+    * Adds qualifiers to a ValueMetaData created using one of the createContextualInject() methods.
+    * 
+    * @param inject the ValueMetaData containing the contextual inject
+    * @param content how to parse the qualifier content, if null {@link QualifierContent#STRING} is used
+    * @param ignoreBeanQualifiers Whether we should ignore bean level qualifiers and only use the ones specified on the inject. Default is false.
+    * If this method is called numerous times for a contextual inject ValueMetaData, the last ignoreBeanQualifiers value overrides the previous ones
+    * @param qualifiers the qualifiers to use to narrow down beans of the matching type. These will override or come in addition to the bean level ones
     * specified in {@link #addRequiredQualifiers(Object...)} and {@link #addOptionalQualifiers(Object...)} and to the ones from higher 
     * levels in the MDR, depending on the value of ignoreBeanQualifiers
-    * @return the contextual injection
+    * @return the contextual injection ValueMetaData
+    * @throws IllegalArgumentException if the ValueMetaData was not created using the createContextualInject() methods
     */
-   public abstract ValueMetaData createContextualInject(ControllerState whenRequired, ControllerState dependentState, AutowireType autowire, InjectOption option, SearchInfo search, boolean ignoreBeanQualifiers, Object...qualifiers);
+   public abstract ValueMetaData addQualifiersToContextualInject(ValueMetaData inject, QualifierContent content, boolean ignoreBeanQualifiers, Object...qualifiers);
    
    /**
     * Inject values from the context of the bean we are creating, using the default

Modified: projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/dependency/QualifiersMdrUtil.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/dependency/QualifiersMdrUtil.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/dependency/QualifiersMdrUtil.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -646,26 +646,33 @@
       }
       
       @Override
-      void removeQualifiersFromSetInMdr(Set<RelatedClassMetaData> relateds, String keyRoot, MetaDataRetrieval retrieval)
+      void removeQualifiersFromSetInMdr(Set<RelatedClassMetaData> relateds, String keyRoot, MetaDataRetrieval retrieval) 
       {
-         if (relateds == null || relateds.size() == 0)
-            return;
-         
-         if (keyRoot.equals(keyRoot) == false)
-            throw new IllegalArgumentException("Wrong key " + keyRoot);
-         
-         Set<Object> set = getQualifiersSetInMdr(retrieval, keyRoot, false);
-         if (set != null)
+         try
          {
-            for (RelatedClassMetaData rcmd : relateds)
+            if (relateds == null || relateds.size() == 0)
+               return;
+            
+            if (keyRoot.equals(keyRoot) == false)
+               throw new IllegalArgumentException("Wrong key " + keyRoot);
+            
+            Set<Object> set = getQualifiersSetInMdr(retrieval, keyRoot, false);
+            if (set != null)
             {
-               if (rcmd.getEnabled() != null && rcmd.getEnabled().size() > 0)
+               for (RelatedClassMetaData rcmd : relateds)
                {
-                  set.removeAll(rcmd.getEnabled());
+                  if (rcmd.getEnabled() != null && rcmd.getEnabled().size() > 0)
+                  {
+                     set.removeAll(rcmd.getEnabled());
+                  }
                }
             }
+            removeEmptyQualifiersSetFromMdr(set, keyRoot, retrieval, null);
          }
-         removeEmptyQualifiersSetFromMdr(set, keyRoot, retrieval, null);
+         catch(Exception e)
+         {
+            log.warn("Error removing qualifiers", e);
+         }
       }
       
       void removeQualifiersFromMdrRetrieval(MetaDataRetrieval retrieval, QualifierType type, QualifierPoint point, Object...qualifiers)

Added: projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/AnnotationQualiferParser.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/AnnotationQualiferParser.java	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/AnnotationQualiferParser.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,83 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.kernel.plugins.qualifier;
+
+import java.lang.annotation.Annotation;
+
+import org.jboss.annotation.factory.AnnotationCreator;
+import org.jboss.beans.metadata.api.model.QualifierContent;
+import org.jboss.kernel.spi.qualifier.QualifierParser;
+
+/**
+ * Handles {@link QualifierContent#ANNOTATION} and parses raw qualifiers into annotations. 
+ * The raw qualifier values must either be of type:
+ * <ul>
+ *   <li><b>java.lang.Annotation</b> in which case the raw qualifier is returned
+ *   <li><b>java.lang.String</b> in which case the string is parsed into a qualifier
+ * </ul>
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class AnnotationQualiferParser implements QualifierParser
+{
+   public static AnnotationQualiferParser INSTANCE = new AnnotationQualiferParser();
+   
+   private AnnotationQualiferParser() {}
+   
+   public QualifierContent getHandledContent()
+   {
+      return QualifierContent.ANNOTATION;
+   }
+
+   public Object parseSupplied(ClassLoader cl, Object rawQualifier)
+   {
+      return parse(cl, rawQualifier);
+   }
+
+   public Object parseWanted(ClassLoader cl, Object rawQualifier)
+   {
+      return parse(cl, rawQualifier);
+   }
+
+   private Object parse(ClassLoader cl, Object rawQualifier)
+   {
+      if (rawQualifier instanceof Annotation)
+         return rawQualifier;
+      if (rawQualifier instanceof String == false)
+         throw new IllegalArgumentException(rawQualifier + " is neither an annotation nor a string");
+         
+      String annString = (String)rawQualifier;
+      try
+      {
+         if (cl == null) 
+         {
+            cl = Thread.currentThread().getContextClassLoader();
+         }
+         return AnnotationCreator.createAnnotation(annString, cl);
+      }
+      catch (Throwable e)
+      {
+         throw new RuntimeException("Error creating annotation for " + rawQualifier, e);
+      }
+   }
+}
\ No newline at end of file

Added: projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/DefaultEqualsMatcher.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/DefaultEqualsMatcher.java	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/DefaultEqualsMatcher.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,32 @@
+package org.jboss.kernel.plugins.qualifier;
+
+import java.util.Set;
+
+import org.jboss.dependency.spi.ControllerContext;
+import org.jboss.kernel.spi.qualifier.QualifierMatcher;
+
+/**
+ * The default Matcher implementation.
+ * 
+ * It checks if the qualifier exists in the context's standard supplied qualifiers using Object.equals(Object) 
+ * when comparing. 
+ * @see QualifierMatcher#matches(ControllerContext, Set, Object)
+ */
+public class DefaultEqualsMatcher implements QualifierMatcher
+{
+   public static final QualifierMatcher SINGLETON = new DefaultEqualsMatcher();
+   
+   private DefaultEqualsMatcher()
+   {
+   }
+   
+   public boolean matches(ControllerContext context, Set<Object> suppliedQualifiers, Object qualifier)
+   {
+      return suppliedQualifiers.contains(qualifier);
+   }
+
+   public Class<?> getHandledType()
+   {
+      return null;
+   }
+}
\ No newline at end of file

Added: projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/StringQualifierParser.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/StringQualifierParser.java	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/qualifier/StringQualifierParser.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,59 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.kernel.plugins.qualifier;
+
+import org.jboss.beans.metadata.api.model.QualifierContent;
+import org.jboss.kernel.spi.qualifier.QualifierParser;
+
+/**
+ * Handles {@link QualifierContent#STRING}, which is a noop, i.e. no transformation is
+ * done on the raw qualifier so the parseXXX() methods return the qualifier in its raw form
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class StringQualifierParser implements QualifierParser
+{
+   public static StringQualifierParser INSTANCE = new StringQualifierParser();
+   
+   private StringQualifierParser() {}
+   
+   public QualifierContent getHandledContent()
+   {
+      return QualifierContent.STRING;
+   }
+
+   public Object parseSupplied(ClassLoader cl, Object rawQualifier)
+   {
+      return parse(cl, rawQualifier);
+   }
+
+   public Object parseWanted(ClassLoader cl, Object rawQualifier)
+   {
+      return parse(cl, rawQualifier);
+   }
+
+   private Object parse(ClassLoader cl, Object rawQualifier)
+   {
+      return rawQualifier;
+   }
+}
\ No newline at end of file

Deleted: projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/Matcher.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/Matcher.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/Matcher.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -1,45 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source.
-* Copyright 2006, Red Hat Middleware LLC, and individual contributors
-* as indicated by the @author tags. See the copyright.txt file in the
-* distribution for a full listing of individual contributors. 
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/ 
-package org.jboss.kernel.spi.qualifier;
-
-import java.util.Set;
-
-import org.jboss.dependency.spi.ControllerContext;
-
-/**
- * Abstraction to check if a qualifier exists in a context's set of supplied qualifiers
- * or other 
- * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
- * @version $Revision: 1.1 $
- */
-public interface Matcher
-{
-   /**
-    * Check whether the passed in qualifier matches the context and/or the context's supplied qualifiers
-    * 
-    * @param context the context to check if matches the passed in qualifier
-    * @param suppliedQualifiers the standard supplied qualifiers for thecontext
-    * @param qualifier the qualifier to check against the context and/or its qualifiers
-    * @return true if there is a match
-    */
-   boolean matches(ControllerContext context, Set<Object> suppliedQualifiers, Object qualifier);
-}

Copied: projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierMatcher.java (from rev 98098, projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/Matcher.java)
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierMatcher.java	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierMatcher.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,54 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.kernel.spi.qualifier;
+
+import java.util.Set;
+
+import org.jboss.dependency.spi.ControllerContext;
+
+/**
+ * Abstraction to check if a qualifier exists in a context's set of supplied qualifiers. A QualifierMatcher
+ * handles a particular class of wanted qualifier and can check a candidate context and/or its supplied qualifiers
+ * to see if the wanted qualifier is satisfied.  
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public interface QualifierMatcher
+{
+   /**
+    * The class of qualifier handled
+    * 
+    * @return the class of qualifier handled
+    */
+   Class<?> getHandledType();
+   
+   /**
+    * Check whether the passed in qualifier matches the context and/or the context's supplied qualifiers
+    * 
+    * @param context the candidate context to check if matches the passed in qualifier
+    * @param suppliedQualifiers the standard supplied qualifiers for thecontext
+    * @param qualifier the qualifier to check against the context and/or its qualifiers
+    * @return true if there is a match
+    */
+   boolean matches(ControllerContext context, Set<Object> suppliedQualifiers, Object qualifier);
+}

Modified: projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierMatchers.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierMatchers.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierMatchers.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -21,14 +21,18 @@
 */ 
 package org.jboss.kernel.spi.qualifier;
 
-import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
+import org.jboss.beans.metadata.api.model.QualifierContent;
 import org.jboss.dependency.spi.ControllerContext;
+import org.jboss.kernel.plugins.qualifier.AnnotationQualiferParser;
+import org.jboss.kernel.plugins.qualifier.DefaultEqualsMatcher;
+import org.jboss.kernel.plugins.qualifier.StringQualifierParser;
 
 /**
- * Singleton registry of qualifier matchers and entry point to the qualifier matcher subsystem
+ * Singleton registry of qualifier matchers and parsers, and the entry point to the qualifier matcher subsystem
  * 
  * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
  * @version $Revision: 1.1 $
@@ -36,12 +40,17 @@
 public class QualifierMatchers
 {
    private final static QualifierMatchers SINGLETON = new QualifierMatchers();
+
+   //Specify concurrency level = 1 since it is very unlikely more than one thread will be adding matchers at any time
+   private ConcurrentMap<Class<?>, QualifierMatcher> matchers = new ConcurrentHashMap<Class<?>, QualifierMatcher>(3, .75f, 1);
    
-   private Map<Class<?>, Matcher> matchers = new ConcurrentHashMap<Class<?>, Matcher>();
+   //Specify concurrency level = 1 since it is very unlikely more than one thread will be adding parsers at any time
+   private ConcurrentMap<QualifierContent, QualifierParser> parsers = new ConcurrentHashMap<QualifierContent, QualifierParser>(3, .75f, 1);
    
    private QualifierMatchers()
    {
-      
+      addParser(StringQualifierParser.INSTANCE);
+      addParser(AnnotationQualiferParser.INSTANCE);
    }
    
    /**
@@ -55,43 +64,85 @@
    }
    
    /**
-    * Check whether the passed in qualifier matches the context and/or the context's supplied qualifiers
+    * Get the qualifier parser to be used for a content type
     * 
+    * @param content the content type
+    * @return the parser
+    */
+   public QualifierParser getParser(QualifierContent content)
+   {
+      QualifierParser parser = parsers.get(content);
+      if (parser == null)
+         throw new IllegalArgumentException("No parser for " + content);
+      
+      return parser;
+   }
+   
+   /**
+    * Check whether the passed in qualifier matches the candidate context and/or the context's supplied qualifiers.
+    * If there is no matcher for the qualifiers type a default implementation is used. The default implementation
+    * iterates over the set of supplied qualifiers and returns true if any of them match the qualifier using Object#equals(Object).
+    * 
     * @param context the context to check if matches the passed in qualifier
-    * @param suppliedQualifiers the standard supplied qualifiers for thecontext
+    * @param suppliedQualifiers the supplied qualifiers for the context
     * @param qualifier the qualifier to check against the context and/or its qualifiers
     * @return true if there is a match
     */
    public boolean matches(ControllerContext context, Set<Object> suppliedQualifiers, Object qualifier)
    {
-      Matcher matcher = getMatcher(qualifier.getClass());
+      QualifierMatcher matcher =  matchers.get(qualifier.getClass());
+      if (matcher == null)
+         matcher = DefaultEqualsMatcher.SINGLETON; 
       return matcher.matches(context, suppliedQualifiers, qualifier);
    }
    
-   private Matcher getMatcher(Class<?> clazz)
+   /**
+    * Add a parser. It will be used to parse qualifiers with the content type {@link QualifierParser#getHandledContent()}
+    * 
+    * @param parser the parser to add
+    * @throws IllegalArgumentException if a parser of a different type already exists for the handled content type
+    */
+   public void addParser(QualifierParser parser)
    {
-      Matcher matcher =  matchers.get(clazz);
-      if (matcher != null)
-         return matcher;
-      return DefaultEqualsMatcherImpl.SINGLETON; 
+      QualifierParser old = parsers.putIfAbsent(parser.getHandledContent(), parser);
+      
+      if (old != null && old.getClass() != parser.getClass())
+         throw new IllegalArgumentException(old + " is already handling " + parser.getHandledContent());
    }
 
    /**
-    * The default Matcher implementation.
-    * It checks if the qualifier exists in the context's standard supplied qualifiers 
+    * Remove a parser for the given qualifier content
     * 
+    * @param content the qualifier content we want to remove a parser for
     */
-   private static class DefaultEqualsMatcherImpl implements Matcher
+   public void removeParser(QualifierContent content)
    {
-      private static final Matcher SINGLETON = new DefaultEqualsMatcherImpl();
+      parsers.remove(content);
+   }
+   
+   /**
+    * Add a matcher. It is used when comparing a wanted qualifier against a candidate
+    * context and its supplied qualifiers. The matcher handles wanted qualifiers of
+    * the type {@link QualifierMatcher#getHandledType()}.
+    * 
+    *  @param matcher the matcher to add
+    *  @throwa IllegalArgumentException if a matcher of a different type already exists for the handled qualifier type
+    */
+   public void addMatcher(QualifierMatcher matcher)
+   {
+      QualifierMatcher old = matchers.putIfAbsent(matcher.getHandledType(), matcher);
       
-      private DefaultEqualsMatcherImpl()
-      {
-      }
-      
-      public boolean matches(ControllerContext context, Set<Object> suppliedQualifiers, Object qualifier)
-      {
-         return suppliedQualifiers.contains(qualifier);
-      }
+      if (old != null && old.getClass() != matcher.getClass())
+         throw new IllegalArgumentException(old + " is already handling " + matcher.getHandledType());
    }
+
+   /**
+    * Remove any matcher for the given qualifier type
+    * 
+    * @param clazz the qualifier type we want to remove the matcher for
+    */
+   public void removeMatcher(Class<?> clazz)
+   {
+      matchers.remove(clazz);
+   }
 }

Added: projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierParser.java
===================================================================
--- projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierParser.java	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/spi/qualifier/QualifierParser.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,60 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.kernel.spi.qualifier;
+
+import org.jboss.beans.metadata.api.model.QualifierContent;
+
+/**
+ * Used to parse qualifiers for a given content type.
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public interface QualifierParser
+{
+   /**
+    * The content type handled by this qualifier parser
+    * 
+    * @return the content type
+    */
+   QualifierContent getHandledContent();
+   
+   /**
+    * Parse a supplied qualifier
+    * 
+    * @param cl the classloader to use when parsing the qualifier 
+    * @param rawQualifier the qualifier in it's raw form
+    * @return the parsed qualifier
+    * @throws IllegalArgumentException if the raw qualifier is not in a format that it can be parsed
+    */
+   Object parseSupplied(ClassLoader cl, Object rawQualifier);
+   
+   /**
+    * Parse a wanted qualifier
+    * 
+    * @param cl the classloader to use when parsing the qualifier 
+    * @param rawQualifier the qualifier in it's raw form
+    * @return the parsed qualifier
+    * @throws IllegalArgumentException if the raw qualifier is not in a format that it can be parsed
+    */
+   Object parseWanted(ClassLoader cl, Object rawQualifier);
+}

Modified: projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/deployment/xml/test/QualifierTestCase.java
===================================================================
--- projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/deployment/xml/test/QualifierTestCase.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/deployment/xml/test/QualifierTestCase.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -23,6 +23,7 @@
 
 import java.util.List;
 import java.util.Set;
+import java.util.Stack;
 
 import junit.framework.Test;
 
@@ -35,11 +36,19 @@
 import org.jboss.beans.metadata.plugins.AbstractQualifierMetaData;
 import org.jboss.beans.metadata.spi.ConstructorMetaData;
 import org.jboss.beans.metadata.spi.InstallMetaData;
+import org.jboss.beans.metadata.spi.MetaDataVisitor;
+import org.jboss.beans.metadata.spi.MetaDataVisitorNode;
 import org.jboss.beans.metadata.spi.ParameterMetaData;
 import org.jboss.beans.metadata.spi.PropertyMetaData;
 import org.jboss.beans.metadata.spi.RelatedClassMetaData;
 import org.jboss.beans.metadata.spi.ValueMetaData;
+import org.jboss.dependency.spi.CallbackItem;
+import org.jboss.dependency.spi.ControllerState;
+import org.jboss.dependency.spi.DependencyItem;
 import org.jboss.kernel.plugins.dependency.QualifiersMdrUtil;
+import org.jboss.kernel.spi.dependency.KernelControllerContext;
+import org.jboss.kernel.spi.qualifier.QualifierMatchers;
+import org.jboss.kernel.spi.qualifier.QualifierParser;
 
 /**
  * QualifierTestCase.
@@ -64,21 +73,6 @@
       super(name, useClone);
    }
 
-   protected RelatedClassMetaData getRelated(String name) throws Exception
-   {
-      AbstractBeanMetaData bean = unmarshalBean(name);
-      return checkRelated(bean.getRelated());
-   }
-   
-   protected RelatedClassMetaData checkRelated(Set<RelatedClassMetaData> related)
-   {
-      assertNotNull(related);
-      assertEquals(1, related.size());
-      RelatedClassMetaData rcmd = related.iterator().next();
-      assertNotNull(rcmd);
-      return rcmd;
-   }
-
    public void testBeanQualifierWithEnabled() throws Exception
    {
       RelatedClassMetaData related = getRelated("QualifierBeanWithEnabled.xml");
@@ -317,4 +311,117 @@
       {
       }
    }
+   
+   public void testBeanNonStandardContent() throws Exception
+   {
+      checkBeanNonStandardContent(true);
+      QualifierMatchers.getInstance().addParser(RubbishQualifierParser.INSTANCE);
+      checkBeanNonStandardContent(false);
+      QualifierMatchers.getInstance().removeParser(RubbishQualifierParser.INSTANCE.getHandledContent());
+      checkBeanNonStandardContent(true);
+   }
+   
+   private void checkBeanNonStandardContent(boolean expectFailure) throws Exception
+   {
+      RelatedClassMetaData related = getRelated("QualifierBeanNonStandardContent.xml");
+      assertEquals(QualifiersMdrUtil.SUPPLIED_QUALIFIER_KEY, related.getClassName());
+      assertInstanceOf(related, AbstractQualifierMetaData.class);
+      assertSame(QualifierContent.getOrCreateContent("Rubbish"), ((AbstractQualifierMetaData)related).getContent());
+      Set<Object> enabled = null; 
+      try
+      {
+         enabled = related.getEnabled();
+         if (expectFailure)
+            fail("Expected failure");
+      }
+      catch(Exception possible)
+      {
+         if (!expectFailure)
+            fail("Expected success");
+      }
+      if (expectFailure)
+         return;
+      assertNotNull(enabled);
+      assertEquals(1, enabled.size());
+      assertEquals("!@£123", enabled.iterator().next()); 
+   }
+   
+   public void testInjectNonStandardContent() throws Exception
+   {
+      checkInjectNonStandardContent(true);
+      QualifierMatchers.getInstance().addParser(RubbishQualifierParser.INSTANCE);
+      checkInjectNonStandardContent(false);
+      QualifierMatchers.getInstance().removeParser(RubbishQualifierParser.INSTANCE.getHandledContent());
+      checkInjectNonStandardContent(true);
+   }
+   
+   private void checkInjectNonStandardContent(boolean expectFailure) throws Exception
+   {
+      AbstractBeanMetaData bean = unmarshalBean("QualifierInjectNonStandardContent.xml");
+      List<InstallMetaData> installs = bean.getInstalls();
+      assertEquals(1, installs.size());
+      List<ParameterMetaData> params = installs.get(0).getParameters();
+      assertNotNull(params);
+      assertEquals(1, params.size());
+      ValueMetaData valueMetaData = params.get(0).getValue();
+      assertInstanceOf(valueMetaData, AbstractInjectionValueMetaData.class);
+      RelatedClassMetaData related = checkRelated(((AbstractInjectionValueMetaData)valueMetaData).getQualifiers());
+      assertEquals(QualifiersMdrUtil.REQUIRED_QUALIFIER_KEY, related.getClassName());
+      assertInstanceOf(related, AbstractQualifierMetaData.class);
+      assertSame(QualifierContent.getOrCreateContent("Rubbish"), ((AbstractQualifierMetaData)related).getContent());
+      Set<Object> enabled = null;
+      try
+      {
+         enabled = related.getEnabled();
+         if (expectFailure)
+            fail("Expected failure");
+      }
+      catch (Exception e)
+      {
+         if (!expectFailure)
+            fail("Expected success");
+      }
+      if (expectFailure)
+         return;
+      assertNotNull(enabled);
+      assertEquals(1, enabled.size());
+      assertEquals("abc!@£", enabled.iterator().next());
+  }
+   
+   protected RelatedClassMetaData getRelated(String name) throws Exception
+   {
+      AbstractBeanMetaData bean = unmarshalBean(name);
+      return checkRelated(bean.getRelated());
+   }
+   
+   protected RelatedClassMetaData checkRelated(Set<RelatedClassMetaData> related)
+   {
+      assertNotNull(related);
+      assertEquals(1, related.size());
+      RelatedClassMetaData rcmd = related.iterator().next();
+      assertNotNull(rcmd);
+      return rcmd;
+   }
+   
+   private static class RubbishQualifierParser implements QualifierParser
+   {
+      static RubbishQualifierParser INSTANCE = new RubbishQualifierParser();
+      
+      private RubbishQualifierParser(){}
+
+      public QualifierContent getHandledContent()
+      {
+         return QualifierContent.getOrCreateContent("Rubbish");
+      }
+
+      public Object parseSupplied(ClassLoader cl, Object rawQualifier)
+      {
+         return ((String)rawQualifier) + "123";
+      }
+
+      public Object parseWanted(ClassLoader cl, Object object)
+      {
+         return "abc" + ((String)object);
+      }
+   }
 }
\ No newline at end of file

Added: projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/support/TestMatcherAndParser.java
===================================================================
--- projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/support/TestMatcherAndParser.java	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/support/TestMatcherAndParser.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,113 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.test.kernel.qualifiers.support;
+
+import java.util.Set;
+
+import org.jboss.beans.metadata.api.model.QualifierContent;
+import org.jboss.dependency.spi.ControllerContext;
+import org.jboss.kernel.spi.qualifier.QualifierMatcher;
+import org.jboss.kernel.spi.qualifier.QualifierParser;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class TestMatcherAndParser implements QualifierMatcher, QualifierParser
+{
+   public static TestMatcherAndParser INSTANCE = new TestMatcherAndParser();
+   
+   private TestMatcherAndParser()
+   {
+   }
+   
+   public QualifierContent getHandledContent()
+   {
+      return QualifierContent.getOrCreateContent("Test");
+   }
+
+   public Class<?> getHandledType()
+   {
+      return Wanted.class;
+   }
+   
+   public boolean matches(ControllerContext context, Set<Object> suppliedQualifiers, Object qualifier)
+   {
+      if (qualifier instanceof Wanted)
+      {
+         for (Object supplied : suppliedQualifiers)
+         {
+            if (supplied instanceof Supplied)
+               return ((Wanted)qualifier).getString().equals(((Supplied)supplied).getString());
+         }
+      }
+      return false;
+   }
+
+   public Object parseSupplied(ClassLoader cl, Object rawQualifier)
+   {
+      return new Supplied((String)rawQualifier);
+   }
+
+   public Object parseWanted(ClassLoader cl, Object object)
+   {
+      return new Wanted((String)object);
+   }
+
+   private static class Supplied
+   {
+      String string;
+
+      public Supplied(String string)
+      {
+         int i = string.indexOf("-xxx");
+         if (i >= 0)
+            string = string.substring(0, i);
+         this.string = string;
+      }
+
+      public String getString()
+      {
+         return string;
+      }
+   }
+   
+   private static class Wanted
+   {
+      String string;
+
+      public Wanted(String string)
+      {
+         this.string = string;
+         
+         if (string.startsWith("xxx-"))
+            string = string.substring(4);
+         this.string = string;
+      }
+
+      public String getString()
+      {
+         return string;
+      }
+   }
+}

Modified: projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/BeanQualifiersTestCase.java
===================================================================
--- projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/BeanQualifiersTestCase.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/BeanQualifiersTestCase.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -41,11 +41,13 @@
 import org.jboss.beans.metadata.spi.builder.BeanMetaDataBuilder;
 import org.jboss.kernel.plugins.dependency.QualifiersMdrUtil;
 import org.jboss.kernel.spi.dependency.KernelControllerContext;
+import org.jboss.kernel.spi.qualifier.QualifierMatchers;
 import org.jboss.metadata.plugins.loader.memory.MemoryMetaDataLoader;
 import org.jboss.metadata.spi.scope.ScopeKey;
 import org.jboss.test.kernel.junit.MicrocontainerTest;
 import org.jboss.test.kernel.qualifiers.support.Bean;
 import org.jboss.test.kernel.qualifiers.support.TargetBean;
+import org.jboss.test.kernel.qualifiers.support.TestMatcherAndParser;
 
 /**
  * 
@@ -946,6 +948,83 @@
       }
    }
    
+   public void testCustomMatcherAndParser() throws Throwable
+   {
+      testCustomMatcherAndParser(false, false);
+      
+      QualifierMatchers.getInstance().addParser(TestMatcherAndParser.INSTANCE);
+      testCustomMatcherAndParser(true, false);
+      
+      QualifierMatchers.getInstance().addMatcher(TestMatcherAndParser.INSTANCE);
+      testCustomMatcherAndParser(true, true);
+      
+      QualifierMatchers.getInstance().removeParser(TestMatcherAndParser.INSTANCE.getHandledContent());
+      testCustomMatcherAndParser(false, true);
+      
+      QualifierMatchers.getInstance().removeMatcher(TestMatcherAndParser.INSTANCE.getHandledType());
+      testCustomMatcherAndParser(false, false);
+   }
+   
+   private void testCustomMatcherAndParser(boolean hasParser, boolean hasMatcher) throws Throwable
+   {
+      BeanMetaDataBuilder bean1Builder = BeanMetaDataBuilder.createBuilder("bean1", Bean.class.getName());
+      bean1Builder.addQualifiers(QualifierType.SUPPLIED, "test");
+      bean1Builder.addQualifiers(QualifierType.SUPPLIED, QualifierContent.getOrCreateContent("Test"), null, "Hello-xxx");
+      KernelControllerContext bean1Context = deploy(bean1Builder.getBeanMetaData());
+
+      BeanMetaDataBuilder bean2Builder = BeanMetaDataBuilder.createBuilder("bean2", Bean.class.getName());
+      bean2Builder.addQualifiers(QualifierType.SUPPLIED, "test");
+      KernelControllerContext bean2Context = deploy(bean2Builder.getBeanMetaData());
+
+      BeanMetaDataBuilder bean3Builder = BeanMetaDataBuilder.createBuilder("bean3", Bean.class.getName());
+      bean3Builder.addQualifiers(QualifierType.SUPPLIED, "test");
+      bean3Builder.addQualifiers(QualifierType.SUPPLIED, QualifierContent.getOrCreateContent("Test"), null, "Hola-xxx");
+      KernelControllerContext bean3Context = deploy(bean3Builder.getBeanMetaData());
+
+      BeanMetaDataBuilder targetBuilder = BeanMetaDataBuilder.createBuilder("target", TargetBean.class.getName());
+      targetBuilder.setAutowireType(AutowireType.BY_CLASS);
+      targetBuilder.addQualifiers(QualifierType.REQUIRED, "test");
+      targetBuilder.addQualifiers(QualifierType.REQUIRED, QualifierContent.getOrCreateContent("Test"), null, "xxx-Hola");
+      
+      KernelControllerContext targetContext = deploy(targetBuilder.getBeanMetaData());
+      try
+      {
+            
+         if (hasParser)
+         {
+            assertBean("bean1", Bean.class);
+            assertBean("bean2", Bean.class);
+            Bean bean3 = assertBean("bean3", Bean.class);
+            
+            if (hasMatcher)
+            {
+               TargetBean target = assertBean("target", TargetBean.class);
+               assertNotNull(target.getBean());
+               assertSame(bean3, target.getBean());
+            }
+            else
+            {
+               assertNoBean("target");
+            }
+         }
+         else
+         {
+            assertNoBean("bean1");
+            assertBean("bean2", Bean.class);
+            assertNoBean("bean3");
+            assertNoBean("target");
+         }
+      }
+      finally
+      {
+         undeploy(bean1Context);
+         undeploy(bean2Context);
+         undeploy(bean3Context);
+         undeploy(targetContext);
+         getMetaDataRepository().getMetaDataRepository().removeMetaDataRetrieval(ScopeKey.DEFAULT_SCOPE);
+      }
+   }
+   
    private Annotation getAnnotation(Class<? extends Annotation> clazz) throws Exception
    {
       return (Annotation)AnnotationCreator.createAnnotation("@" + clazz.getName(), clazz);

Modified: projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/InjectionPointQualifiersTestCase.java
===================================================================
--- projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/InjectionPointQualifiersTestCase.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/InjectionPointQualifiersTestCase.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -35,13 +35,12 @@
 import org.jboss.beans.metadata.api.model.QualifierType;
 import org.jboss.beans.metadata.plugins.AbstractBeanMetaData;
 import org.jboss.beans.metadata.plugins.AbstractBeanQualifierMetaData;
-import org.jboss.beans.metadata.plugins.AbstractInjectionValueMetaData;
-import org.jboss.beans.metadata.plugins.AbstractQualifierMetaData;
 import org.jboss.beans.metadata.spi.BeanMetaData;
 import org.jboss.beans.metadata.spi.RelatedClassMetaData;
 import org.jboss.beans.metadata.spi.ValueMetaData;
 import org.jboss.beans.metadata.spi.builder.BeanMetaDataBuilder;
 import org.jboss.kernel.spi.dependency.KernelControllerContext;
+import org.jboss.kernel.spi.qualifier.QualifierMatchers;
 import org.jboss.test.kernel.junit.MicrocontainerTest;
 import org.jboss.test.kernel.qualifiers.support.Bean;
 import org.jboss.test.kernel.qualifiers.support.Target;
@@ -51,6 +50,7 @@
 import org.jboss.test.kernel.qualifiers.support.TargetFieldBean;
 import org.jboss.test.kernel.qualifiers.support.TargetMethodBean;
 import org.jboss.test.kernel.qualifiers.support.TargetPropertyBean;
+import org.jboss.test.kernel.qualifiers.support.TestMatcherAndParser;
 
 /**
  * 
@@ -606,9 +606,9 @@
       KernelControllerContext bean3Context = deploy(bean3Builder.getBeanMetaData());
       
       BeanMetaDataBuilder targetBuilder = BeanMetaDataBuilder.createBuilder("target", TargetAllBean.class.getName());
-      targetBuilder.addPropertyMetaData("fieldBean", targetBuilder.createContextualInject("test"));
-      targetBuilder.addConstructorParameter(Bean.class.getName(), targetBuilder.createContextualInject("test"));
-      targetBuilder.addInstall("installBean", Bean.class.getName(), targetBuilder.createContextualInject("test"));
+      targetBuilder.addPropertyMetaData("fieldBean", targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
+      targetBuilder.addConstructorParameter(Bean.class.getName(), targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
+      targetBuilder.addInstall("installBean", Bean.class.getName(), targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
       targetBuilder.addQualifiers(QualifierType.REQUIRED, "all");
       targetBuilder.addQualifiers(QualifierType.REQUIRED, Arrays.asList(new QualifierPoint[] {QualifierPoint.CONSTRUCTOR}), "constructor");
       targetBuilder.addQualifiers(QualifierType.REQUIRED, Arrays.asList(new QualifierPoint[] {QualifierPoint.METHOD}), "method");
@@ -656,9 +656,9 @@
       
       BeanMetaDataBuilder targetBuilder = BeanMetaDataBuilder.createBuilder("target", TargetAllBeanWithField.class.getName());
       targetBuilder.setAccessMode(BeanAccessMode.ALL);
-      targetBuilder.addPropertyMetaData("fieldBean", targetBuilder.createContextualInject("test"));
-      targetBuilder.addConstructorParameter(Bean.class.getName(), targetBuilder.createContextualInject("test"));
-      targetBuilder.addInstall("installBean", Bean.class.getName(), targetBuilder.createContextualInject("test"));
+      targetBuilder.addPropertyMetaData("fieldBean", targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
+      targetBuilder.addConstructorParameter(Bean.class.getName(), targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
+      targetBuilder.addInstall("installBean", Bean.class.getName(), targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
       targetBuilder.addQualifiers(QualifierType.REQUIRED, "all");
       targetBuilder.addQualifiers(QualifierType.REQUIRED, Arrays.asList(new QualifierPoint[] {QualifierPoint.CONSTRUCTOR}), "constructor");
       targetBuilder.addQualifiers(QualifierType.REQUIRED, Arrays.asList(new QualifierPoint[] {QualifierPoint.METHOD}), "method");
@@ -705,9 +705,9 @@
       KernelControllerContext bean3Context = deploy(bean3Builder.getBeanMetaData());
       
       BeanMetaDataBuilder targetBuilder = BeanMetaDataBuilder.createBuilder("target", TargetAllBean.class.getName());
-      targetBuilder.addPropertyMetaData("fieldBean", targetBuilder.createContextualInject("test"));
-      targetBuilder.addConstructorParameter(Bean.class.getName(), targetBuilder.createContextualInject("test"));
-      targetBuilder.addInstall("installBean", Bean.class.getName(), targetBuilder.createContextualInject("test"));
+      targetBuilder.addPropertyMetaData("fieldBean", targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
+      targetBuilder.addConstructorParameter(Bean.class.getName(), targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
+      targetBuilder.addInstall("installBean", Bean.class.getName(), targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
       targetBuilder.addQualifiers(QualifierType.OPTIONAL, "all");
       targetBuilder.addQualifiers(QualifierType.OPTIONAL, Arrays.asList(new QualifierPoint[] {QualifierPoint.CONSTRUCTOR}), "constructor");
       targetBuilder.addQualifiers(QualifierType.OPTIONAL, Arrays.asList(new QualifierPoint[] {QualifierPoint.METHOD}), "method");
@@ -755,9 +755,9 @@
       
       BeanMetaDataBuilder targetBuilder = BeanMetaDataBuilder.createBuilder("target", TargetAllBeanWithField.class.getName());
       targetBuilder.setAccessMode(BeanAccessMode.ALL);
-      targetBuilder.addPropertyMetaData("fieldBean", targetBuilder.createContextualInject("test"));
-      targetBuilder.addConstructorParameter(Bean.class.getName(), targetBuilder.createContextualInject("test"));
-      targetBuilder.addInstall("installBean", Bean.class.getName(), targetBuilder.createContextualInject("test"));
+      targetBuilder.addPropertyMetaData("fieldBean", targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
+      targetBuilder.addConstructorParameter(Bean.class.getName(), targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
+      targetBuilder.addInstall("installBean", Bean.class.getName(), targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test"));
       targetBuilder.addQualifiers(QualifierType.OPTIONAL, "all");
       targetBuilder.addQualifiers(QualifierType.OPTIONAL, Arrays.asList(new QualifierPoint[] {QualifierPoint.CONSTRUCTOR}), "constructor");
       targetBuilder.addQualifiers(QualifierType.OPTIONAL, Arrays.asList(new QualifierPoint[] {QualifierPoint.METHOD}), "method");
@@ -787,8 +787,106 @@
          undeploy(bean2Context);
          undeploy(bean1Context);
       }
+   }   
+   
+   public void testCustomQualifierContent() throws Throwable
+   {
+      testCustomQualifierContent(false, false);
+      
+      QualifierMatchers.getInstance().addParser(TestMatcherAndParser.INSTANCE);
+      testCustomQualifierContent(true, false);
+
+      QualifierMatchers.getInstance().addMatcher(TestMatcherAndParser.INSTANCE);
+      testCustomQualifierContent(true, true);
+      
+      QualifierMatchers.getInstance().removeParser(TestMatcherAndParser.INSTANCE.getHandledContent());
+      testCustomQualifierContent(false, true);
+      
+      QualifierMatchers.getInstance().removeMatcher(TestMatcherAndParser.INSTANCE.getHandledType());
+      testCustomQualifierContent(false, false);
    }
-
+   
+   private void testCustomQualifierContent(boolean hasParser, boolean hasMatcher) throws Throwable
+   {
+      BeanMetaDataBuilder bean1Builder = BeanMetaDataBuilder.createBuilder("bean1", Bean.class.getName());
+      bean1Builder.addQualifiers(QualifierType.SUPPLIED, "test");
+      bean1Builder.addQualifiers(QualifierType.SUPPLIED, QualifierContent.getOrCreateContent("Test"), null, "Hello-xxx");
+      KernelControllerContext bean1Context = deploy(bean1Builder.getBeanMetaData());
+      
+      BeanMetaDataBuilder bean2Builder = BeanMetaDataBuilder.createBuilder("bean2", Bean.class.getName());
+      bean2Builder.addQualifiers(QualifierType.SUPPLIED, "test");
+      bean2Builder.addQualifiers(QualifierType.SUPPLIED, QualifierContent.getOrCreateContent("Test"), null, "Bonjour-xxx");
+      KernelControllerContext bean2Context = deploy(bean2Builder.getBeanMetaData());
+      
+      BeanMetaDataBuilder bean3Builder = BeanMetaDataBuilder.createBuilder("bean3", Bean.class.getName());
+      bean3Builder.addQualifiers(QualifierType.SUPPLIED, "test");
+      bean3Builder.addQualifiers(QualifierType.SUPPLIED, QualifierContent.getOrCreateContent("Test"), null, "Hola-xxx");
+      KernelControllerContext bean3Context = deploy(bean3Builder.getBeanMetaData());
+      
+      
+      //Need something in builder to handle custom content types at injection points
+      BeanMetaDataBuilder targetBuilder = BeanMetaDataBuilder.createBuilder("target", TargetAllBean.class.getName());
+      
+      ValueMetaData inject = targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test");
+      inject = targetBuilder.addQualifiersToContextualInject(inject, QualifierContent.getOrCreateContent("Test"), false, "xxx-Hola");
+      targetBuilder.addPropertyMetaData("fieldBean", inject);
+      
+      inject = targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test");
+      inject = targetBuilder.addQualifiersToContextualInject(inject, QualifierContent.getOrCreateContent("Test"), false, "xxx-Hello");
+      targetBuilder.addConstructorParameter(Bean.class.getName(), inject);
+      
+      inject = targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), "test");
+      inject = targetBuilder.addQualifiersToContextualInject(inject, QualifierContent.getOrCreateContent("Test"), false, "xxx-Bonjour");      
+      targetBuilder.addInstall("installBean", Bean.class.getName(), inject);
+      
+      targetBuilder.addQualifiers(QualifierType.OPTIONAL, "all");
+      targetBuilder.addQualifiers(QualifierType.OPTIONAL, Arrays.asList(new QualifierPoint[] {QualifierPoint.CONSTRUCTOR}), "constructor");
+      targetBuilder.addQualifiers(QualifierType.OPTIONAL, Arrays.asList(new QualifierPoint[] {QualifierPoint.METHOD}), "method");
+      targetBuilder.addQualifiers(QualifierType.OPTIONAL, Arrays.asList(new QualifierPoint[] {QualifierPoint.PROPERTY}), "property");
+      KernelControllerContext targetContext = deploy(targetBuilder.getBeanMetaData());
+      
+      try
+      {
+         if (hasParser)
+         {
+            Bean bean1 = assertBean("bean1", Bean.class);
+            Bean bean2 = assertBean("bean2", Bean.class);
+            Bean bean3 = assertBean("bean3", Bean.class);
+            
+            if (hasMatcher)
+            {
+               TargetAllBean target = assertBean("target", TargetAllBean.class);
+               assertNotNull(target.getConstructorBean());
+               assertEquals(bean1, target.getConstructorBean());
+               
+               assertNotNull(target.getMethodBean());
+               assertEquals(bean2, target.getMethodBean());
+      
+               assertNotNull(target.getFieldBean());
+               assertEquals(bean3, target.getFieldBean());
+            }
+            else
+            {
+               assertNoBean("target");
+            }
+         }
+         else
+         {
+            assertNoBean("bean1");
+            assertNoBean("bean2");
+            assertNoBean("bean3");
+            assertNoBean("target");
+         }
+      }
+      finally
+      {
+         undeploy(targetContext);
+         undeploy(bean3Context);
+         undeploy(bean2Context);
+         undeploy(bean1Context);
+      }
+   }
+   
    private BeanMetaData addRequiredQualifiers(BeanMetaData bmd, Object...qualifiers)
    {
       BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(bmd);
@@ -822,32 +920,22 @@
          targetBuilder = BeanMetaDataBuilder.createBuilder("target", targetClass.getName());
          if (targetClass == TargetFieldBean.class)
             targetBuilder.setAccessMode(BeanAccessMode.ALL);
-         value = targetBuilder.createContextualInject(ignoreBeanQualifiers, qualifiers);
+         value = targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), content, ignoreBeanQualifiers, qualifiers);
          targetBuilder.addPropertyMetaData("bean", value);
       }
       else if (targetClass == TargetConstructorBean.class)
       {
          targetBuilder = BeanMetaDataBuilder.createBuilder("target", targetClass.getName());
-         value = targetBuilder.createContextualInject(ignoreBeanQualifiers, qualifiers);
+         value = targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), content, ignoreBeanQualifiers, qualifiers);
          targetBuilder.addConstructorParameter(Bean.class.getName(), value);
       }
       else
       {
          targetBuilder = BeanMetaDataBuilder.createBuilder("target", targetClass.getName());
-         value = targetBuilder.createContextualInject(ignoreBeanQualifiers, qualifiers);
+         value = targetBuilder.addQualifiersToContextualInject(targetBuilder.createContextualInject(), content, ignoreBeanQualifiers, qualifiers);
          targetBuilder.addInstall("installBean", Bean.class.getName(), value);
       }
       
-      if (content == QualifierContent.ANNOTATION)
-      {
-         AbstractInjectionValueMetaData inject = (AbstractInjectionValueMetaData)value;
-         for (RelatedClassMetaData qualifier : inject.getQualifiers())
-         {
-            assertInstanceOf(qualifier, AbstractQualifierMetaData.class);
-            ((AbstractQualifierMetaData)qualifier).setContent(QualifierContent.ANNOTATION);
-         }
-      }
-      
       return targetBuilder.getBeanMetaData();
    }
    

Modified: projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase.java
===================================================================
--- projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase.java	2009-12-23 14:32:05 UTC (rev 98905)
+++ projects/kernel/trunk/kernel/src/test/java/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase.java	2009-12-23 14:38:24 UTC (rev 98906)
@@ -23,13 +23,16 @@
 
 import junit.framework.Test;
 
+import org.jboss.kernel.spi.qualifier.QualifierMatchers;
 import org.jboss.test.kernel.junit.MicrocontainerTest;
 import org.jboss.test.kernel.qualifiers.support.Bean;
+import org.jboss.test.kernel.qualifiers.support.Target;
 import org.jboss.test.kernel.qualifiers.support.TargetAllBean;
 import org.jboss.test.kernel.qualifiers.support.TargetBean;
 import org.jboss.test.kernel.qualifiers.support.TargetConstructorBean;
 import org.jboss.test.kernel.qualifiers.support.TargetMethodBean;
 import org.jboss.test.kernel.qualifiers.support.TargetPropertyBean;
+import org.jboss.test.kernel.qualifiers.support.TestMatcherAndParser;
 
 /**
  * 
@@ -196,4 +199,124 @@
       assertNotNull(target.getFieldBean());
       assertEquals(bean2, target.getFieldBean());
    }
+   
+   public void testNonCustomBeanQualifiers() throws Throwable
+   {
+      testNonCustomBeanQualifiers(false, false);
+      
+      QualifierMatchers.getInstance().addParser(TestMatcherAndParser.INSTANCE);
+      testNonCustomBeanQualifiers(true, false);
+      
+      QualifierMatchers.getInstance().addMatcher(TestMatcherAndParser.INSTANCE);
+      testNonCustomBeanQualifiers(true, true);
+      
+      QualifierMatchers.getInstance().removeParser(TestMatcherAndParser.INSTANCE.getHandledContent());
+      testNonCustomBeanQualifiers(false, true);
+      
+      QualifierMatchers.getInstance().removeMatcher(TestMatcherAndParser.INSTANCE.getHandledType());
+      testNonCustomBeanQualifiers(false, false);
+      
+   }
+   
+   private void testNonCustomBeanQualifiers(boolean hasParser, boolean hasMatcher) throws Throwable
+   {
+      deploy("QualifiersXmlTestCase#testCustomBeanQualifiers_Not_Automatic.xml");
+      try
+      {
+         if (hasParser)
+         {
+            assertBean("bean1", Bean.class);
+            assertBean("bean2", Bean.class);
+            Bean bean3 = assertBean("bean3", Bean.class);
+         
+            if (hasMatcher)
+            {
+               TargetBean target = assertBean("target", TargetBean.class);
+               assertNotNull(target.getBean());
+               assertEquals(bean3, target.getBean());
+            }
+            else
+            {
+               assertNoBean("target");
+            }
+         }
+         else
+         {
+            assertNoBean("bean1");
+            assertBean("bean2", Bean.class);
+            assertNoBean("bean3");
+            assertNoBean("target");
+         }
+      }
+      finally
+      {
+         undeploy("QualifiersXmlTestCase#testCustomBeanQualifiers_Not_Automatic.xml");
+      }
+   }
+   
+   public void testNonCustomConstructorQualifiers() throws Throwable
+   {
+      testNonCustomInjectionPointQualifiers("QualifiersXmlTestCase#testCustomConstructorQualifiers_Not_Automatic.xml");
+   }
+   
+   public void testNonCustomMethodQualifiers() throws Throwable
+   {
+      testNonCustomInjectionPointQualifiers("QualifiersXmlTestCase#testCustomMethodQualifiers_Not_Automatic.xml");
+   }
+ 
+   public void testNonCustomPropertyQualifiers() throws Throwable
+   {
+      testNonCustomInjectionPointQualifiers("QualifiersXmlTestCase#testCustomPropertyQualifiers_Not_Automatic.xml");
+   }
+
+   private void testNonCustomInjectionPointQualifiers(String xmlFile) throws Throwable
+   {
+      testNonCustomInjectionPointQualifiers(xmlFile, false, false);
+      
+      QualifierMatchers.getInstance().addParser(TestMatcherAndParser.INSTANCE);
+      testNonCustomInjectionPointQualifiers(xmlFile, true, false);
+      
+      QualifierMatchers.getInstance().addMatcher(TestMatcherAndParser.INSTANCE);
+      testNonCustomInjectionPointQualifiers(xmlFile, true, true);
+      
+      QualifierMatchers.getInstance().removeParser(TestMatcherAndParser.INSTANCE.getHandledContent());
+      testNonCustomInjectionPointQualifiers(xmlFile, false, true);
+      
+      QualifierMatchers.getInstance().removeMatcher(TestMatcherAndParser.INSTANCE.getHandledType());
+      testNonCustomInjectionPointQualifiers(xmlFile, false, false);
+   }
+   
+   private void testNonCustomInjectionPointQualifiers(String xmlFile, boolean hasParser, boolean hasMatcher) throws Throwable
+   {
+      deploy(xmlFile);
+      try
+      {
+         if (hasParser)
+         {
+            assertBean("bean1", Bean.class);
+            Bean bean2 = assertBean("bean2", Bean.class);
+         
+            if (hasMatcher)
+            {
+               Target target = assertBean("target", Target.class);
+               assertNotNull(target.getBean());
+               assertEquals(bean2, target.getBean());
+            }
+            else
+            {
+               assertNoBean("target");
+            }
+         }
+         else
+         {
+            assertNoBean("bean1");
+            assertNoBean("bean2");
+            assertNoBean("target");
+         }
+      }
+      finally
+      {
+         undeploy(xmlFile);
+      }
+   }
 }

Added: projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/deployment/xml/test/QualifierBeanNonStandardContent.xml
===================================================================
--- projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/deployment/xml/test/QualifierBeanNonStandardContent.xml	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/deployment/xml/test/QualifierBeanNonStandardContent.xml	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<bean xmlns="urn:jboss:bean-deployer:2.0" class="Dummy">
+   <qualifier content="Rubbish">!@£</qualifier>
+</bean>

Added: projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/deployment/xml/test/QualifierInjectNonStandardContent.xml
===================================================================
--- projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/deployment/xml/test/QualifierInjectNonStandardContent.xml	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/deployment/xml/test/QualifierInjectNonStandardContent.xml	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<bean xmlns="urn:jboss:bean-deployer:2.0">
+   <install>
+      <parameter>
+         <inject bean="Dummy">
+            <qualifier content="Rubbish">!@£</qualifier>
+         </inject>
+      </parameter>
+   </install>
+</bean>

Added: projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomBeanQualifiers_Not_Automatic.xml
===================================================================
--- projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomBeanQualifiers_Not_Automatic.xml	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomBeanQualifiers_Not_Automatic.xml	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+   
+   <bean name="bean1" class="org.jboss.test.kernel.qualifiers.support.Bean">
+      <qualifier>test</qualifier>
+      <qualifier content="Test">Hello-xxx</qualifier>
+   </bean>
+
+   <bean name="bean2" class="org.jboss.test.kernel.qualifiers.support.Bean">
+      <qualifier>test</qualifier>
+   </bean>
+   
+   <bean name="bean3" class="org.jboss.test.kernel.qualifiers.support.Bean">
+      <qualifier>test</qualifier>
+      <qualifier content="Test">Hola-xxx</qualifier>
+   </bean>
+   
+   <bean name="target" class="org.jboss.test.kernel.qualifiers.support.TargetBean">
+      <qualifier type="Required">test</qualifier>
+      <qualifier type="Required" content="Test">xxx-Hola</qualifier>
+   </bean>
+   
+</deployment>

Added: projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomConstructorQualifiers_Not_Automatic.xml
===================================================================
--- projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomConstructorQualifiers_Not_Automatic.xml	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomConstructorQualifiers_Not_Automatic.xml	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+   
+   <bean name="bean1" class="org.jboss.test.kernel.qualifiers.support.Bean">
+      <qualifier>test</qualifier>
+      <qualifier content="Test">Hello-xxx</qualifier>
+   </bean>
+
+   <bean name="bean2" class="org.jboss.test.kernel.qualifiers.support.Bean">
+      <qualifier>test</qualifier>
+      <qualifier content="Test">Hola-xxx</qualifier>
+   </bean>
+   
+   <bean name="target" class="org.jboss.test.kernel.qualifiers.support.TargetConstructorBean">
+      <constructor>
+         <parameter>
+            <inject>
+               <qualifier>test</qualifier>
+               <qualifier content="Test">xxx-Hola</qualifier>
+            </inject>
+         </parameter>
+      </constructor>
+   </bean>
+   
+</deployment>

Added: projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomMethodQualifiers_Not_Automatic.xml
===================================================================
--- projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomMethodQualifiers_Not_Automatic.xml	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomMethodQualifiers_Not_Automatic.xml	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+   
+   <bean name="bean1" class="org.jboss.test.kernel.qualifiers.support.Bean">
+      <qualifier>test</qualifier>
+      <qualifier content="Test">Hello-xxx</qualifier>
+   </bean>
+
+   <bean name="bean2" class="org.jboss.test.kernel.qualifiers.support.Bean">
+      <qualifier>test</qualifier>
+      <qualifier content="Test">Hola-xxx</qualifier>
+   </bean>
+   
+   <bean name="target" class="org.jboss.test.kernel.qualifiers.support.TargetMethodBean">
+      <install method="installBean">
+         <parameter>
+            <inject>
+               <qualifier>test</qualifier>
+               <qualifier content="Test">xxx-Hola</qualifier>
+            </inject>
+         </parameter>
+      </install>
+   </bean>
+   
+</deployment>

Added: projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomPropertyQualifiers_Not_Automatic.xml
===================================================================
--- projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomPropertyQualifiers_Not_Automatic.xml	                        (rev 0)
+++ projects/kernel/trunk/kernel/src/test/resources/org/jboss/test/kernel/qualifiers/test/QualifiersXmlTestCase#testCustomPropertyQualifiers_Not_Automatic.xml	2009-12-23 14:38:24 UTC (rev 98906)
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+   
+   <bean name="bean1" class="org.jboss.test.kernel.qualifiers.support.Bean">
+      <qualifier>test</qualifier>
+      <qualifier content="Test">Hello-xxx</qualifier>
+   </bean>
+
+   <bean name="bean2" class="org.jboss.test.kernel.qualifiers.support.Bean">
+      <qualifier>test</qualifier>
+      <qualifier content="Test">Hola-xxx</qualifier>
+   </bean>
+   
+   <bean name="target" class="org.jboss.test.kernel.qualifiers.support.TargetPropertyBean">
+      <property name="bean">
+         <inject>
+		      <qualifier>test</qualifier>
+		      <qualifier content="Test">xxx-Hola</qualifier>
+         </inject>
+      </property>
+   </bean>
+   
+</deployment>




More information about the jboss-cvs-commits mailing list