View Javadoc

1   /*
2    * $Id: ComponentDelegatingDefinitionParser.java 19191 2010-08-25 21:05:23Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.config.spring.parsers.specific;
12  
13  import org.mule.config.spring.parsers.AbstractMuleBeanDefinitionParser;
14  import org.mule.config.spring.parsers.MuleDefinitionParser;
15  import org.mule.config.spring.parsers.PreProcessor;
16  import org.mule.config.spring.parsers.assembly.configuration.PropertyConfiguration;
17  import org.mule.config.spring.parsers.delegate.AbstractParallelDelegatingDefinitionParser;
18  import org.mule.config.spring.util.SpringXMLUtils;
19  import org.mule.util.StringUtils;
20  
21  import org.springframework.beans.factory.xml.ParserContext;
22  import org.w3c.dom.Attr;
23  import org.w3c.dom.Element;
24  import org.w3c.dom.NamedNodeMap;
25  import org.w3c.dom.Node;
26  
27  /**
28   * Allows for parsing either a shortcut component configuration by delegating to two
29   * different component parses depending on the existence of the class attribute. If
30   * the class attribute is used then an embedded object factory element cannot be
31   * used.
32   * 
33   * <pre>
34   * &lt;component class=&quot;&quot;&gt;
35   * </pre>
36   * 
37   * or one with an embedded object factory element.
38   * 
39   * <pre>
40   * &lt;component&gt;
41   *     &lt;singleon-object class=&quot;..&quot;/&gt;
42   * &lt;/component&gt;
43   * </pre>
44   */
45  public class ComponentDelegatingDefinitionParser extends AbstractParallelDelegatingDefinitionParser
46  {
47  
48      private MuleDefinitionParser normalConfig;
49      private MuleDefinitionParser shortcutConfig;
50  
51      public ComponentDelegatingDefinitionParser(Class clazz)
52      {
53          normalConfig = new ComponentDefinitionParser(clazz);
54          shortcutConfig = new ShortcutComponentDefinitionParser(clazz);
55          addDelegate(normalConfig);
56          addDelegate(shortcutConfig);
57          registerPreProcessor(new CheckExclusiveClassAttributeObjectFactory());
58      }
59  
60      @Override
61      protected MuleDefinitionParser getDelegate(Element element, ParserContext parserContext)
62      {
63          if (StringUtils.isEmpty(element.getAttribute(AbstractMuleBeanDefinitionParser.ATTRIBUTE_CLASS)))
64          {
65              return normalConfig;
66          }
67          else
68          {
69              return shortcutConfig;
70          }
71      }
72  
73      /**
74       * Given that the service object-factory is extensible and new object factory
75       * types can be implemented and used by substitution, the only way of checking
76       * for the existence of an object-factory if by object factory element
77       * convention.<br>
78       * This pre-processor checks for the existence of a <i>"class"</i> attribute on
79       * the service, and throws an exception if the service has any elements that
80       * match the object factory element convention (i.e. that end in "object"). NOTE:
81       * We used to test by exclusion here allowing all other elements, but that no
82       * longer works now extensible interceptors elements can be used.
83       */
84      class CheckExclusiveClassAttributeObjectFactory implements PreProcessor
85      {
86  
87          private static final String OBJECT_FACTORY_ELEMENT_CONVENTION_SUFFIX = "object";
88  
89          public void preProcess(PropertyConfiguration config, Element element)
90          {
91              NamedNodeMap attributes = element.getAttributes();
92              for (int i = 0; i < attributes.getLength(); i++)
93              {
94                  String alias = SpringXMLUtils.attributeName((Attr) attributes.item(i));
95                  if (alias.equals(AbstractMuleBeanDefinitionParser.ATTRIBUTE_CLASS))
96                  {
97                      for (int j = 0; j < element.getChildNodes().getLength(); j++)
98                      {
99                          Node child = element.getChildNodes().item(j);
100                         if (child instanceof Element
101                             && child.getLocalName().endsWith(OBJECT_FACTORY_ELEMENT_CONVENTION_SUFFIX))
102                         {
103                             StringBuffer message = new StringBuffer("The child element '");
104                             message.append(child.getLocalName());
105                             message.append("' cannot appear with the 'class' attribute");
106                             message.append(" in element ");
107                             message.append(SpringXMLUtils.elementToString(element));
108                             message.append(".");
109                             throw new CheckExclusiveClassAttributeObjectFactoryException(message.toString());
110                         }
111                     }
112                 }
113             }
114         }
115     }
116 
117     class CheckExclusiveClassAttributeObjectFactoryException extends IllegalStateException
118     {
119         private static final long serialVersionUID = 4625276914151932111L;
120 
121         CheckExclusiveClassAttributeObjectFactoryException(String message)
122         {
123             super(message);
124         }
125     }
126 
127 }