View Javadoc

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