View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.config.spring.parsers.delegate;
8   
9   import org.mule.config.spring.MuleHierarchicalBeanDefinitionParserDelegate;
10  import org.mule.config.spring.parsers.AbstractMuleBeanDefinitionParser;
11  import org.mule.config.spring.parsers.MuleDefinitionParser;
12  import org.mule.config.spring.parsers.MuleDefinitionParserConfiguration;
13  import org.mule.config.spring.parsers.PreProcessor;
14  import org.mule.config.spring.parsers.assembly.configuration.PropertyConfiguration;
15  import org.mule.util.StringUtils;
16  
17  import java.util.HashSet;
18  import java.util.Iterator;
19  import java.util.Set;
20  
21  import edu.emory.mathcs.backport.java.util.Arrays;
22  
23  import org.springframework.beans.factory.support.AbstractBeanDefinition;
24  import org.springframework.beans.factory.xml.ParserContext;
25  import org.w3c.dom.Element;
26  
27  /**
28   * This allows a set of definition parsers to be used, one after another, to process
29   * the same element.  This lets multiple beans be generated from a single element.
30   *
31   * <p>Since each bean typically needs a spearate name, this class guarantees that the
32   * name and id attributes are reset before each call.  Delegates can then modify these
33   * on the element without worrying about interfering with other parsers.</p>
34   *
35   * <p>Typically, subclasses will add additional processing with
36   * {@link org.mule.config.spring.parsers.PreProcessor} and
37   * {@link org.mule.config.spring.parsers.PostProcessor} anonymous classes.</p>
38   */
39  public abstract class AbstractSerialDelegatingDefinitionParser extends AbstractDelegatingDefinitionParser
40  {
41  
42      private int index = 0;
43      private boolean first;
44      private boolean doReset;
45      private String originalId;
46      private String originalName;
47      private Set handledExceptions = new HashSet();
48  
49      public AbstractSerialDelegatingDefinitionParser()
50      {
51          this(true); // by default, reset name
52      }
53  
54      /**
55       * @param doReset Should the name be reset after called.  This is typically true (it protects the
56       * parent from changes made by children) unless this is itself nested.
57       */
58      public AbstractSerialDelegatingDefinitionParser(boolean doReset)
59      {
60          this.doReset = doReset;
61      }
62  
63      public AbstractBeanDefinition muleParse(Element element, ParserContext parserContext)
64      {
65          if (index == 0 || index >= size())
66          {
67              first = true;
68              index = 0;
69          }
70          else
71          {
72              first = false;
73          }
74          AbstractBeanDefinition bean = null;
75          while (null == bean && index < size())
76          {
77              try
78              {
79                  MuleDefinitionParser parser = getDelegate(index);
80                  bean = doSingleBean(index++, parser, element, parserContext);
81              }
82              catch (RuntimeException e)
83              {
84                  if (isExceptionHandled(e))
85                  {
86                      bean = null;
87                  }
88                  else
89                  {
90                      throw e;
91                  }
92              }
93          }
94          if (null != bean)
95          {
96              if (index == size())
97              {
98                  bean.removeAttribute(MuleHierarchicalBeanDefinitionParserDelegate.MULE_REPEAT_PARSE);
99              }
100             else
101             {
102                 bean.setAttribute(MuleHierarchicalBeanDefinitionParserDelegate.MULE_REPEAT_PARSE, Boolean.TRUE);
103             }
104         }
105         return bean;
106     }
107 
108     protected boolean isExceptionHandled(Exception e)
109     {
110         return handledExceptions.contains(e.getClass());
111     }
112 
113     protected AbstractBeanDefinition doSingleBean(int index, MuleDefinitionParser parser,
114                                                   Element element, ParserContext parserContext)
115     {
116         return parser.muleParse(element, parserContext);
117     }
118 
119     protected MuleDefinitionParserConfiguration addDelegate(MuleDefinitionParser delegate)
120     {
121         delegate.registerPreProcessor(new PreProcessor()
122         {
123             public void preProcess(PropertyConfiguration config, Element element)
124             {
125                 if (first)
126                 {
127                     originalId = element.getAttribute(AbstractMuleBeanDefinitionParser.ATTRIBUTE_ID);
128                     originalName = element.getAttribute(AbstractMuleBeanDefinitionParser.ATTRIBUTE_NAME);
129                 }
130                 else if (doReset)
131                 {
132                     resetNameAndId(element);
133                 }
134             }
135         });
136         return super.addDelegate(delegate);
137     }
138 
139     protected void resetNameAndId(Element element)
140     {
141         resetAttribute(element, AbstractMuleBeanDefinitionParser.ATTRIBUTE_ID, originalId);
142         resetAttribute(element, AbstractMuleBeanDefinitionParser.ATTRIBUTE_NAME, originalName);
143     }
144 
145     protected void resetAttribute(Element element, String name, String value)
146     {
147         if (StringUtils.isEmpty(value))
148         {
149             if (element.hasAttribute(name))
150             {
151                 element.removeAttribute(name);
152             }
153         }
154         else
155         {
156             element.setAttribute(name, value);
157         }
158     }
159 
160     protected void addHandledException(Class exception)
161     {
162         handledExceptions.add(exception);
163     }
164 
165     /**
166      * A utility class for selecting certain attributes.  If the attributes are enabled,
167      * the default is set to block others; if specific attributes are disabled the default
168      * is set to allow others.
169      *
170      * @param delegate
171      * @param attributes
172      * @param enable
173      */
174     public static void enableAttributes(MuleDefinitionParser delegate, String[] attributes, boolean enable)
175     {
176         // if enabling specific attributes, block globally
177         delegate.setIgnoredDefault(enable);
178 
179         Iterator names = Arrays.asList(attributes).iterator();
180         while (names.hasNext())
181         {
182             String name = (String) names.next();
183             if (enable)
184             {
185                 delegate.removeIgnored(name);
186             }
187             else
188             {
189                 delegate.addIgnored(name);
190             }
191         }
192     }
193 
194     public static void enableAttributes(MuleDefinitionParser delegate, String[][] attributes)
195     {
196         for (int i = 0; i < attributes.length; ++i)
197         {
198             enableAttributes(delegate, attributes[i], true);
199         }
200     }
201 
202     public static void enableAttributes(MuleDefinitionParser delegate, String[] attributes)
203     {
204         enableAttributes(delegate, attributes, true);
205     }
206 
207     public static void enableAttribute(MuleDefinitionParser delegate, String attribute)
208     {
209         enableAttributes(delegate, new String[]{attribute}, true);
210     }
211 
212     public static void disableAttributes(MuleDefinitionParser delegate, String[][] attributes)
213     {
214         for (int i = 0; i < attributes.length; ++i)
215         {
216             enableAttributes(delegate, attributes[i], false);
217         }
218     }
219 
220     public static void disableAttributes(MuleDefinitionParser delegate, String[] attributes)
221     {
222         enableAttributes(delegate, attributes, false);
223     }
224 
225     public static void disableAttribute(MuleDefinitionParser delegate, String attribute)
226     {
227         enableAttributes(delegate, new String[]{attribute}, false);
228     }
229 
230 }