KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > servicemix > components > mps > MessagePropertySetterXML


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.servicemix.components.mps;
18
19 import java.io.IOException JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.Map JavaDoc;
22
23 import javax.jbi.JBIException;
24 import javax.jbi.component.ComponentContext;
25 import javax.jbi.messaging.MessageExchange;
26 import javax.jbi.messaging.MessagingException;
27 import javax.jbi.messaging.NormalizedMessage;
28 import javax.xml.parsers.DocumentBuilder JavaDoc;
29 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
30 import javax.xml.parsers.ParserConfigurationException JavaDoc;
31 import javax.xml.transform.TransformerException JavaDoc;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.servicemix.components.util.TransformComponentSupport;
36 import org.apache.servicemix.jbi.jaxp.SourceTransformer;
37 import org.apache.xpath.CachedXPathAPI;
38 import org.apache.xpath.objects.XObject;
39 import org.springframework.core.io.Resource;
40 import org.springframework.util.Assert;
41 import org.w3c.dom.Document JavaDoc;
42 import org.w3c.dom.Element JavaDoc;
43 import org.w3c.dom.Node JavaDoc;
44 import org.xml.sax.SAXException JavaDoc;
45
46
47
48 /**
49  * Sets properties on the message, loaded from an XML MPS file
50  * where the properties to set are located in a <property-set ..>
51  * inside the XML config file.
52  *
53  * There can be more than one propertySet to "load".
54  *
55  * The property values are derived from 3 types of config.
56  * The first config that can return a value as a String to
57  * set onto the message, will be the "value" that is set
58  * as the property.
59  *
60  * <static-value>
61  * As it's name suggests, the "value" of this element
62  * will be the value of the JBI property.
63  *
64  * This is helpful as a default value, or as a static value.
65  *
66  * <exisiting-property> and <existint-property name="..."/>
67  * This will obtain the value of an existing property (itself)
68  * or another property on the same message.
69  *
70  * This can be helpful when you want the to "ONLY" change the
71  * the value of the property if there is some "xpath" expression
72  * that could not be derived.
73  *
74  * name=".." form will copy the string value of the other JBI property
75  * onto this one, (duping it). This may be handy when you have a component
76  * which expects a new property, but you have it as a different name at the moment.
77  *
78  * <xpath-expression>
79  * As it's name suggests, will locate a value in the inMessage source
80  * and set the resulting XPath String as the value of the JBI property.
81  *
82  * So given the three types, they can be arranged in any order. and the first
83  * PropertyValue Type that returns a value, will become the "value" of the JBI property.
84  *
85  *
86  * <!--
87  * <mps>
88  * <property-set name="someSetNameForASetOfProperties">
89  * <property name="some.property.name1">
90  * <static-value><![CDATA[value for the property]]></static-value>
91  * </property>
92  * <property name="some.property.name2">
93  * <xpath-expression>
94  * <![CDATA[/someexpath/statement/to/be/applied/to/message/source]]>
95  * </xpath-expression>
96  * <existing-property name="someproperty"/>
97  * <static-value><![CDATA[a value in the raw]]></static-value>
98  * </property>
99  * <property name="prop.xpath.with.static.default">
100  * <xpath-expression>
101  * <![CDATA[/someexpath/statement]]>
102  * </xpath-expression>
103  * <static-value><![CDATA[some default if xpath does not resolve]]></static-value>
104  * </property>
105  * <property name="prop.xpath.or.keep.existing">
106  * <xpath-expression>
107  * <![CDATA[/someexpath/statement]]>
108  * </xpath-expression>
109  * <existing-property/>
110  * </property>
111  * <property name="new.prop.name">
112  * <existing-property name="other.property"/>
113  * </property>
114  * <property name="...">
115  * ...
116  * </property>
117  * </property-set>
118  * <property-set name="...">
119  * ...
120  * </property-set>
121  * </mps>
122  * -->
123  *
124  *
125  * @author rbuckland
126  *
127  */

128 public class MessagePropertySetterXML extends TransformComponentSupport {
129     
130     /**
131      * Apache commons logger
132      */

133     private final transient Log logger = LogFactory.getLog(getClass());
134
135     /**
136      * The name of our JBI property we may have to interrogate to
137      * use as the "xpath" for the set of config.
138      */

139     public static final String JavaDoc MPS_PROP_NAME_PROPERTYSET = "org.apache.servicemix.components.mps.propertyset";
140     
141     /**
142      * The XML Element name "property-set"
143      */

144     public static final String JavaDoc XML_ELEMENT_NAME = "property-set";
145     
146     /**
147      * This is our XML file
148      */

149     private Resource xmlConfiguration = null;
150     
151     /**
152      * Our XML config MPS.
153      */

154     private Document JavaDoc xmlMPSdom = null;
155     
156     /**
157      * Holds the propertyValueResolver objects.
158      * if propertySet is not null, this holds one.
159      * if propertySet is null, this will hold
160      * one for each propertyvalue entry used during the time
161      * we are "active".
162      */

163     private Map JavaDoc propertSets = new HashMap JavaDoc();
164
165     /**
166      * If this is set, it is hardcoded as the fixed value.
167      *
168      * If this is null
169      * we will look for a propery MPS_PROP_NAME_PROPERTYSET
170      * as the "name" of the property set we will work with.
171      * So the message incoming, seeds the set of properties to load, just by
172      * the JBI property itself.
173      */

174     private String JavaDoc propertySet = null;
175     
176     
177     /**
178      * If the XPath for a propertySet is not null
179      * we will try and locate the propertySet to use by
180      * pulling a String from the inMessage content using this
181      * XPath.
182      */

183     private String JavaDoc xpathForPropertySet = null;
184     
185     /**
186      * Here is the transform of the message
187      * We will locate the propertySetName to use
188      * and the load up our propertySet magic wand and apply all the properties
189      * we can to the outgoing NormalizedMessage
190      */

191     protected boolean transform(MessageExchange arg0, NormalizedMessage in, NormalizedMessage out) throws MessagingException {
192         try {
193             copyPropertiesAndAttachments(arg0,in,out);
194             out.setContent(in.getContent());
195             
196             String JavaDoc propertySetName = "";
197             if (xpathForPropertySet != null) {
198                 try {
199                     CachedXPathAPI xpathApi = new org.apache.xpath.CachedXPathAPI();
200                     Document JavaDoc doc = new SourceTransformer().toDOMDocument(in);
201                     XObject propSetXO = xpathApi.eval(doc.getDocumentElement(),xpathForPropertySet);
202                     propertySetName = propSetXO.str();
203                 } catch (Exception JavaDoc e) {
204                     throw new MessagingException("Problem getting the propertySet using XPath", e);
205                 }
206             } else if (this.propertySet != null) {
207                 propertySetName = this.propertySet;
208             } else if (in.getProperty(MPS_PROP_NAME_PROPERTYSET) != null) {
209                 propertySetName = in.getProperty(MPS_PROP_NAME_PROPERTYSET).toString();
210             } else {
211                 return false;
212             }
213             logger.info("Applying properties from property-set [" + propertySetName + "]");
214             getPropertySetByName(propertySetName).applyProperties(in,out);
215             return true;
216         } catch (JBIException e) {
217             throw new MessagingException("Problem setting properties",e);
218         } catch (PropertySetNotFoundException e) {
219             logger.warn(e.getLocalizedMessage());
220             return false;
221         }
222     }
223
224     /**
225      * Initialise by loading the mps.xml file up into an internal DOM.
226      *
227      * @throws JBIException
228      */

229     private void initConfig() throws JBIException {
230         Assert.notNull(this.xmlConfiguration);
231         DocumentBuilderFactory JavaDoc domFactory = DocumentBuilderFactory.newInstance();
232         domFactory.setIgnoringElementContentWhitespace(true);
233         domFactory.setIgnoringComments(true);
234         domFactory.setCoalescing(true); // convert CDATA to test nodes
235
DocumentBuilder JavaDoc domBuilder;
236         try {
237             logger.info("Intialising MessagePropertySetterXML, loading settings from " + this.xmlConfiguration.getFile().getAbsolutePath());
238             domBuilder = domFactory.newDocumentBuilder();
239             xmlMPSdom = domBuilder.parse(this.xmlConfiguration.getInputStream());
240         } catch (ParserConfigurationException JavaDoc e) {
241             throw new JBIException("Problem parsing the XML config file for MPS",e);
242         } catch (SAXException JavaDoc e) {
243             throw new JBIException("Problem loading the XML config file for MPS",e);
244         } catch (IOException JavaDoc e) {
245             throw new JBIException("Problem loading the XML config file for MPS",e);
246         }
247         
248     }
249
250     /**
251      * We are only interested in loading the XML onfig, nothing else
252      */

253     public void init(ComponentContext context) throws JBIException {
254         super.init(context);
255         initConfig();
256     }
257
258     /**
259      * Create a propertyset (loading up the Object config based on the XML config)
260      *
261      * @param propertySetName
262      * @return
263      * @throws JBIException
264      * @throws PropertySetNotFoundException
265      */

266     private PropertySet createPropertySet(String JavaDoc propertySetName) throws JBIException , PropertySetNotFoundException{
267         PropertySet ps;
268         CachedXPathAPI xpath = new CachedXPathAPI();
269         StringBuffer JavaDoc xpathSB = new StringBuffer JavaDoc("//")
270                                     .append(XML_ELEMENT_NAME)
271                                     .append("[@name='")
272                                     .append(propertySetName)
273                                     .append("']");
274         try {
275             Node JavaDoc propertySetNode = xpath.selectSingleNode(xmlMPSdom,xpathSB.toString());
276             if (propertySetNode == null) {
277                 throw new PropertySetNotFoundException("Could not find a property-set for [" + propertySetName + "] in " + xmlConfiguration.getFilename());
278             }
279             ps = new PropertySet(propertySetName,(Element JavaDoc) propertySetNode);
280             this.propertSets.put(propertySetName, ps);
281         } catch (TransformerException JavaDoc e) {
282             throw new JBIException("Could not load the PropertySet for " + propertySet,e);
283         } catch (ConfigNotSupportedException e) {
284             throw new JBIException("Could not load the PropertySet for. XMLConfig is not good for " + propertySet,e);
285         }
286         return ps;
287
288     }
289     
290     /**
291      * Get a property set from ou
292      * @param name
293      * @return
294      * @throws JBIException
295      */

296     private PropertySet getPropertySetByName(String JavaDoc name) throws JBIException, PropertySetNotFoundException {
297         // find a pre "created" one
298
if (this.propertSets.containsKey(name)) {
299             return (PropertySet)this.propertSets.get(name);
300         } else {
301             return this.createPropertySet(name);
302         }
303         
304     }
305
306     /**
307      * @param propertySet The propertySet to set.
308      */

309     public void setPropertySet(String JavaDoc propertySet) {
310         this.propertySet = propertySet;
311     }
312
313     /**
314      * @param xmlConfiguration The xmlConfiguration to set.
315      */

316     public void setXmlConfiguration(Resource xmlConfiguration) {
317         this.xmlConfiguration = xmlConfiguration;
318     }
319
320     /**
321      * @param xpathForPropertySet xpath to apply to a message to derive the name of the property-set we want to load
322      */

323     public void setXpathForPropertySet(String JavaDoc xpathForPropertySet) {
324         this.xpathForPropertySet = xpathForPropertySet;
325     }
326
327 }
328
Popular Tags