View Javadoc

1   /*
2    * $Id: ComponentDelegatingDefinitionParser.java 11379 2008-03-17 02:46:56Z dfeist $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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      protected MuleDefinitionParser getDelegate(Element element, ParserContext parserContext)
61      {
62          if (StringUtils.isEmpty(element.getAttribute(AbstractMuleBeanDefinitionParser.ATTRIBUTE_CLASS)))
63          {
64              return normalConfig;
65          }
66          else
67          {
68              return shortcutConfig;
69          }
70      }
71  
72      /**
73       * Given that the service object-factory is extensible and new object factory
74       * types can be implemented and used by substitution, the only extensible way of
75       * checking for the existence of an object-factory child element is by exclusion.<br>
76       * This pre-processor checks for the existence of a <i>"class"</i> attribute on
77       * the service, and throws an exception if the service has any child elements
78       * that are not binding's.
79       */
80      class CheckExclusiveClassAttributeObjectFactory implements PreProcessor
81      {
82  
83          private static final String BINDING_CHILD_ELEMENT = "binding";
84          private static final String POOLING_PROFILE_CHILD_ELEMENT = "pooling-profile";
85          private static final String LIFECYCLE_ADAPTER_FACTORT_CHILD_ELEMENT = "lifecycle-adapter-factory";
86          private static final String ENTRY_POINT_RESOLVER_CHILD_ELEMENT = "entry-point-resolver";
87          private static final String ENTRY_POINT_RESOLVER_SET_CHILD_ELEMENT = "entry-point-resolver-set";
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().equals(BINDING_CHILD_ELEMENT)
102                                  || child.getLocalName().equals(POOLING_PROFILE_CHILD_ELEMENT)
103                                  || child.getLocalName().equals(ENTRY_POINT_RESOLVER_CHILD_ELEMENT)
104                                  || child.getLocalName().equals(ENTRY_POINT_RESOLVER_SET_CHILD_ELEMENT) || child.getLocalName()
105                                 .endsWith(LIFECYCLE_ADAPTER_FACTORT_CHILD_ELEMENT)))
106                         {
107                             StringBuffer message = new StringBuffer("The child element '");
108                             message.append(child.getLocalName());
109                             message.append("' cannot appear with the 'class' attribute");
110                             message.append(" in element ");
111                             message.append(SpringXMLUtils.elementToString(element));
112                             message.append(".");
113                             throw new CheckExclusiveClassAttributeObjectFactoryException(message.toString());
114                         }
115                     }
116 
117                 }
118             }
119         }
120     }
121 
122     class CheckExclusiveClassAttributeObjectFactoryException extends IllegalStateException
123     {
124         private static final long serialVersionUID = 4625276914151932111L;
125 
126         private CheckExclusiveClassAttributeObjectFactoryException(String message)
127         {
128             super(message);
129         }
130     }
131 
132 }