View Javadoc

1   /*
2    * $Id:AddressedEndpointDefinitionParser.java 8321 2007-09-10 19:22:52Z acooke $
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.endpoint.support;
12  
13  import org.mule.api.config.MuleProperties;
14  import org.mule.config.spring.parsers.AbstractMuleBeanDefinitionParser;
15  import org.mule.config.spring.parsers.MuleChildDefinitionParser;
16  import org.mule.config.spring.parsers.MuleDefinitionParser;
17  import org.mule.config.spring.parsers.delegate.AbstractSingleParentFamilyDefinitionParser;
18  import org.mule.config.spring.parsers.generic.AttributePropertiesDefinitionParser;
19  import org.mule.config.spring.parsers.processors.BlockAttribute;
20  import org.mule.config.spring.parsers.processors.CheckExclusiveAttributes;
21  import org.mule.config.spring.parsers.processors.CheckRequiredAttributes;
22  import org.mule.endpoint.AbstractEndpointBuilder;
23  import org.mule.endpoint.URIBuilder;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  /**
29   * Combine a
30   * {@link org.mule.config.spring.parsers.specific.endpoint.support.ChildAddressDefinitionParser} and
31   * either a
32   * {@link org.mule.config.spring.parsers.specific.endpoint.support.OrphanEndpointDefinitionParser}
33   * or a
34   * {@link org.mule.config.spring.parsers.specific.endpoint.support.ChildEndpointDefinitionParser}
35   * in one parser.  This lets us put the address attributes in the endpoint element.
36   */
37  public class AddressedEndpointDefinitionParser extends AbstractSingleParentFamilyDefinitionParser
38  {
39  
40      protected Log logger = LogFactory.getLog(getClass());
41      public static final boolean META = ChildAddressDefinitionParser.META;
42      public static final boolean PROTOCOL = ChildAddressDefinitionParser.PROTOCOL;
43      public static final String PROPERTIES = "properties";
44      public static final String[] RESTRICTED_ENDPOINT_ATTRIBUTES =
45              new String[]{MuleProperties.EXCHANGE_PATTERN, 
46                      AbstractEndpointBuilder.PROPERTY_RESPONSE_TIMEOUT, "encoding",
47                      "connector", "createConnector", "transformer", "responseTransformer", "disableTransportTransformer", "mimeType"};
48  
49      // this is an example of parsing a single element with several parsers.  in this case
50      // (because we extend AbstractSingleParentFamilyDefinitionParser) the first parser is expected to
51      // create the "parent".  then subsequent parsers will be called as children.
52  
53      // because all are generated from one element we need to be careful to block attributes
54      // that are irrelevant to a particular parser.
55  
56      public AddressedEndpointDefinitionParser(String protocol, MuleDefinitionParser endpointParser)
57      {
58          this(protocol, PROTOCOL, endpointParser);
59      }
60  
61      public AddressedEndpointDefinitionParser(String metaOrProtocol, boolean isMeta, MuleDefinitionParser endpointParser)
62      {
63          this(metaOrProtocol, isMeta, endpointParser, new String[]{}, new String[]{});
64      }
65  
66      public AddressedEndpointDefinitionParser(String metaOrProtocol, boolean isMeta,
67                                               MuleDefinitionParser endpointParser,
68                                               String[] requiredAddressAttributes,
69                                               String[] requiredProperties)
70      {
71          this(metaOrProtocol, isMeta, endpointParser,
72                  RESTRICTED_ENDPOINT_ATTRIBUTES, URIBuilder.ALL_ATTRIBUTES,
73                  new String[][]{requiredAddressAttributes}, new String[][]{requiredProperties});
74      }
75  
76      /**
77       * @param metaOrProtocol The transport metaOrProtocol ("tcp" etc)
78       * @param isMeta Whether transport is "meta" or not (eg cxf)
79       * @param endpointParser The parser for the endpoint
80       * @param endpointAttributes A list of attribute names which will be set as properties on the
81       * endpoint builder
82       * @param addressAttributes A list of attribute names which will be set as properties on the
83       * endpoint URI builder
84       * @param requiredAddressAttributes A list of attribute names that are required if "address"
85       * isn't present
86       * @param requiredProperties A list of property names that are required if "address" isn't present
87       */
88      public AddressedEndpointDefinitionParser(String metaOrProtocol, boolean isMeta,
89                                               MuleDefinitionParser endpointParser,
90                                               String[] endpointAttributes,
91                                               String[] addressAttributes,
92                                               String[][] requiredAddressAttributes,
93                                               String[][] requiredProperties)
94      {
95          // the first delegate, the parent, is an endpoint; we block everything except the endpoint attributes
96          enableAttributes(endpointParser, endpointAttributes);
97          enableAttribute(endpointParser, AbstractMuleBeanDefinitionParser.ATTRIBUTE_NAME);
98          addDelegate(endpointParser);
99  
100         // we handle the address and properties separately, setting the
101         // properties directly on the endpoint (rather than as part of the address)
102         MuleChildDefinitionParser addressParser =
103                 new AddressParser(metaOrProtocol, isMeta, addressAttributes, requiredAddressAttributes);
104 
105         // this handles the exception thrown if a ref is found in the address parser
106         addHandledException(BlockAttribute.BlockAttributeException.class);
107         addChildDelegate(addressParser);
108 
109         MuleChildDefinitionParser propertiesParser =
110                 new PropertiesParser(PROPERTIES, endpointAttributes, requiredAddressAttributes, requiredProperties);
111         addChildDelegate(propertiesParser);
112     }
113 
114     private static class AddressParser extends ChildAddressDefinitionParser
115     {
116 
117         public AddressParser(String metaOrProtocol, boolean isMeta,
118                              String[] addressAttributes, String[][] requiredAddressAttributes)
119         {
120             super(metaOrProtocol, isMeta);
121 
122             // this handles the "ref problem" - we don't want this parsers to be used if a "ref"
123             // defines the address so add a preprocessor to check for that and indicate that the
124             // exception should be handled internally, rather than shown to the user.
125             // we do this before the extra processors below so that this is called last,
126             // allowing other processors to check for conflicts between ref and other attributes
127             registerPreProcessor(new BlockAttribute(AbstractMuleBeanDefinitionParser.ATTRIBUTE_REF));
128 
129             // the address parser sees only the endpoint attributes
130             enableAttributes(this, addressAttributes);
131 
132             // we require either a reference, an address, or the attributes specified
133             // (properties can be used in parallel with "address")
134             String[][] addressAttributeSets =
135             new String[(null != requiredAddressAttributes ? requiredAddressAttributes.length : 0) + 2][];
136             addressAttributeSets[0] = new String[]{URIBuilder.ADDRESS};
137             addressAttributeSets[1] = new String[]{AbstractMuleBeanDefinitionParser.ATTRIBUTE_REF};
138             if (null != requiredAddressAttributes)
139             {
140                 enableAttributes(this, requiredAddressAttributes);
141                 System.arraycopy(requiredAddressAttributes, 0, addressAttributeSets, 2, requiredAddressAttributes.length);
142             }
143             registerPreProcessor(new CheckRequiredAttributes(addressAttributeSets));
144             // and they must be exclusive
145             registerPreProcessor(new CheckExclusiveAttributes(addressAttributeSets));
146         }
147 
148     }
149 
150     private static class PropertiesParser extends AttributePropertiesDefinitionParser
151     {
152 
153         public PropertiesParser(String setter,
154                 String[] endpointAttributes, String[][] requiredAddressAttributes, String[][] requiredProperties)
155         {
156             super(setter);
157 
158             // the properties parser gets to see everything that the other parsers don't - if you
159             // don't want something, don't enable it in the schema!
160             disableAttributes(this, endpointAttributes);
161             disableAttributes(this, URIBuilder.ALL_ATTRIBUTES);
162             disableAttributes(this, requiredAddressAttributes);
163             disableAttribute(this, AbstractMuleBeanDefinitionParser.ATTRIBUTE_NAME);
164             disableAttribute(this, AbstractMuleBeanDefinitionParser.ATTRIBUTE_REF);
165             if (null != requiredProperties && requiredProperties.length > 0 &&
166                     null != requiredProperties[0] && requiredProperties[0].length > 0)
167             {
168                 // if "ref" is present then we don't complain if required properties are missing, since they
169                 // must have been provided on the global endpoint
170                 String[][] requiredPropertiesSets = new String[requiredProperties.length + 1][];
171                 requiredPropertiesSets[0] = new String[]{AbstractMuleBeanDefinitionParser.ATTRIBUTE_REF};
172                 System.arraycopy(requiredProperties, 0, requiredPropertiesSets, 1, requiredProperties.length);
173                 registerPreProcessor(new CheckRequiredAttributes(requiredPropertiesSets));
174             }
175         }
176 
177     }
178 
179 }