View Javadoc

1   /*
2      Licensed under the Apache License, Version 2.0 (the "License");
3      you may not use this file except in compliance with the License.
4      You may obtain a copy of the License at
5   
6        http://www.apache.org/licenses/LICENSE-2.0
7   
8      Unless required by applicable law or agreed to in writing, software
9      distributed under the License is distributed on an "AS IS" BASIS,
10     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11     See the License for the specific language governing permissions and
12     limitations under the License.
13  */
14  package uk.nhs.interoperability.util.xml;
15  
16  import javax.xml.namespace.NamespaceContext;
17  import javax.xml.xpath.XPath;
18  import javax.xml.xpath.XPathConstants;
19  import javax.xml.xpath.XPathExpression;
20  import javax.xml.xpath.XPathExpressionException;
21  import javax.xml.xpath.XPathFactory;
22  import javax.xml.xpath.XPathFactoryConfigurationException;
23  
24  import uk.nhs.interoperability.util.Logger;
25  
26  import com.xmlsolutions.annotation.Requirement;
27  
28  /**
29   * The Class XPaths.
30   *
31   * @author Michael Odling-Smee
32   * @author Nicholas Jones
33   * @since 0.1
34   */
35  public class XPaths {
36  	
37  	/** The xpath factory. */
38  	private static XPathFactory xpathFactory;
39  	
40  	static {
41  		try {
42  			xpathFactory = XPathFactory.newInstance(XPathConstants.DOM_OBJECT_MODEL);
43  		} catch (XPathFactoryConfigurationException e) {
44  			Logger.error("Could not create XPath factory", e);
45  		}
46  	}
47  	
48  	/** The Constant ROOT. */
49  	public static final String ROOT = "/";
50      
51      /** The Constant SOAP_BODY. */
52      public static final String SOAP_BODY = ROOT + "SOAP:Envelope/SOAP:Body";
53      
54      /** Obtains the SOAP body contents - typically this will contain the ITK distribution envelope. */
55      public static final String SOAP_BODY_CONTENT = SOAP_BODY + "/*[1]";
56      
57      /** The Constant SOAP_HEADER. */
58      public static final String SOAP_HEADER = ROOT + "SOAP:Envelope/SOAP:Header";
59      
60      /** The Constant WSA_MSG_ID. */
61      public static final String WSA_MSG_ID = SOAP_HEADER + "/wsa:MessageID";
62      
63      /** The Constant WSA_TO. */
64      @Requirement(traceTo={"WS-STD-03"})
65      public static final String WSA_TO = SOAP_HEADER + "/wsa:To";
66      
67      /** The Constant WSA_FROM. */
68      @Requirement(traceTo={"WS-STD-03"})
69      public static final String WSA_FROM = SOAP_HEADER + "/wsa:From/wsa:Address";
70      
71      /** The Constant WSA_REPLY_TO. */
72      @Requirement(traceTo={"WS-STD-03"})
73      public static final String WSA_REPLY_TO = SOAP_HEADER + "/wsa:ReplyTo/wsa:Address";
74      
75      /** The Constant WSA_FAULT_TO. */
76      @Requirement(traceTo={"WS-STD-03"})
77      public static final String WSA_FAULT_TO = SOAP_HEADER + "/wsa:FaultTo/wsa:Address";
78      
79      /** The Constant WSA_ACTION. */
80      @Requirement(traceTo={"WS-STD-03"})
81      public static final String WSA_ACTION = SOAP_HEADER + "/wsa:Action";
82      
83      // Add in Xpaths for security header
84      /** The Constant WSA_SECURITY_TIMESTAMP. */
85      public static final String WSA_SECURITY_TIMESTAMP = SOAP_HEADER + "/wsse:Security/wsu:Timestamp";
86      
87      /** The Constant WSA_SECURITY_CREATED. */
88      public static final String WSA_SECURITY_CREATED = SOAP_HEADER + "/wsse:Security/wsu:Timestamp/wsu:Created";
89      
90      /** The Constant WSA_SECURITY_EXPIRES. */
91      public static final String WSA_SECURITY_EXPIRES = SOAP_HEADER + "/wsse:Security/wsu:Timestamp/wsu:Expires";
92      
93      /** The Constant WSA_SECURITY_USERNAME. */
94      public static final String WSA_SECURITY_USERNAME = SOAP_HEADER + "/wsse:Security/wsse:UsernameToken/wsse:Username";
95      
96      /** Counts the number of payloads present in the message (does not rely on the count provided in the message itself). */
97      public static final String ITK_PAYLOAD_COUNT = "count(itk:DistributionEnvelope/itk:payloads/itk:payload)";
98      
99      /** The Constant ITK_AUDIT_IDENTITY_URI. */
100     public static final String ITK_AUDIT_IDENTITY_URI = "itk:DistributionEnvelope/itk:header/itk:auditIdentity/itk:id/@uri";
101     
102     /** The Constant ITK_AUDIT_IDENTITY_URI. */
103     public static final String ITK_AUDIT_IDENTITY_TYPE = "itk:DistributionEnvelope/itk:header/itk:auditIdentity/itk:id/@type";
104 
105     /** The Constant ITK_FROM_ADDRESS. */
106     public static final String ITK_FROM_ADDRESS = "itk:DistributionEnvelope/itk:header/itk:senderAddress/@uri";
107     
108     /** The Constant ITK_FIRST_TO_ADDRESS. */
109     public static final String ITK_FIRST_TO_ADDRESS = "itk:DistributionEnvelope/itk:header/itk:addresslist/itk:address[1]/@uri";
110     
111     /** The Constant ITK_FIRST_MIMETYPE. */
112     public static final String ITK_FIRST_MIMETYPE = "itk:DistributionEnvelope/itk:header/itk:manifest/itk:manifestitem[1]/@mimetype";
113 
114     /** The Constant ITK_FIRST_BASE64. */
115     public static final String ITK_FIRST_BASE64 = "itk:DistributionEnvelope/itk:header/itk:manifest/itk:manifestitem[1]/@base64";
116     
117     
118     
119     /**
120      * Obtains the profile id. Note this will take the profile id from the manifest for the manifest item. It is not
121      * appropriate for a message containing multiple payloads
122      */
123     public static final String ITK_PROFILE_ID = "itk:DistributionEnvelope/itk:header/itk:manifest/itk:manifestitem[1]/@profileid";
124     
125     /**
126      * The tracking id associated with the message. Used for end-to-end tracing and correlation
127      */
128     public static final String ITK_TRACKING_ID = "itk:DistributionEnvelope/itk:header/@trackingid";
129     
130     /**
131      * XPath to extract the technical service from the message e.g. 
132      * <code>urn:nhs-itk:services:201005:getNHSNumber-v1-0</code>
133      */
134     public static final String ITK_SERVICE = "itk:DistributionEnvelope/itk:header/@service";
135     
136     /** The Constant ITK_BUSINESS_ACK_HANDLING_SPECIFICATIONS. */
137     public static final String ITK_BUSINESS_ACK_HANDLING_SPECIFICATIONS = "itk:DistributionEnvelope/itk:header/itk:handlingSpecification/itk:spec[@key='urn:nhs:itk:ns:201005:ackrequested']/@value";
138     
139     /** The Constant ITK_FIRST_PAYLOAD. */
140     public static final String ITK_FIRST_PAYLOAD = "itk:DistributionEnvelope/itk:payloads/itk:payload[1]/*[1]";
141 
142     /** The Constant ITK_FIRST_PAYLOAD_TEXT. */
143     public static final String ITK_FIRST_PAYLOAD_TEXT = "itk:DistributionEnvelope/itk:payloads/itk:payload[1]/text()";
144     
145     /** The Constant ITK_FIRST_PAYLOAD_ID. */
146     public static final String ITK_FIRST_PAYLOAD_ID = "itk:DistributionEnvelope/itk:payloads/itk:payload[1]/@id";
147     
148     /** The Constant ITK_SIMPLE_MESSAGE_RESPONSE. */
149     public static final String ITK_SIMPLE_MESSAGE_RESPONSE = "itk:SimpleMessageResponse";
150     
151     /** The Constant ITK_SIMPLE_MESSAGE_RESPONSE_CONTENT. */
152     public static final String ITK_SIMPLE_MESSAGE_RESPONSE_CONTENT = "itk:SimpleMessageResponse/* | itk:SimpleMessageResponse/text()";
153     
154     /** The Constant SOAP_WRAPPED_ITK_FIRST_PAYLOAD. */
155     public static final String SOAP_WRAPPED_ITK_FIRST_PAYLOAD = SOAP_BODY + "/" + ITK_FIRST_PAYLOAD;
156     
157     /** The Constant SOAP_WRAPPED_ITK_SIMPLE_MESSAGE_RESPONSE. */
158     public static final String SOAP_WRAPPED_ITK_SIMPLE_MESSAGE_RESPONSE = SOAP_BODY + "/" + ITK_SIMPLE_MESSAGE_RESPONSE;
159     
160     //SOAP Fault XPaths
161     /** The Constant WSA_SOAP_ERROR_DETAIL. */
162     public static final String WSA_SOAP_ERROR_DETAIL = SOAP_BODY + "/SOAP:Fault/SOAP:detail/*[1]";
163     
164     /** The Constant WSA_SOAP_ERROR_DETAIL_ID. */
165     public static final String WSA_SOAP_ERROR_DETAIL_ID = "itk:itkErrorInfo/itk:ErrorID";
166     
167     /** The Constant WSA_SOAP_ERROR_DETAIL_CODE. */
168     public static final String WSA_SOAP_ERROR_DETAIL_CODE = "itk:itkErrorInfo/itk:ErrorCode";
169     
170     /** The Constant WSA_SOAP_ERROR_DETAIL_TEXT. */
171     public static final String WSA_SOAP_ERROR_DETAIL_TEXT = "itk:itkErrorInfo/itk:ErrorText";
172     
173     /** The Constant WSA_SOAP_ERROR_DETAIL_DIAGNOSTIC. */
174     public static final String WSA_SOAP_ERROR_DETAIL_DIAGNOSTIC = "itk:itkErrorInfo/itk:ErrorDiagnosticText";
175     
176     /** The Constant NS_CONTEXT. */
177     public static final NamespaceContext NS_CONTEXT = new XMLNamespaceContext();	
178     
179     
180     /** The Constant ROOT_XPATH. */
181     public static final XPathExpression ROOT_XPATH = compileXPath(ROOT);
182     
183     /** The Constant WSA_MSGID_XPATH. */
184     public static final XPathExpression WSA_MSGID_XPATH = compileXPath(WSA_MSG_ID);
185     
186     /** The Constant WSA_REPLY_TO_XPATH. */
187     public static final XPathExpression WSA_REPLY_TO_XPATH = compileXPath(WSA_REPLY_TO);
188     
189     /** The Constant WSA_FAULT_TO_XPATH. */
190     public static final XPathExpression WSA_FAULT_TO_XPATH = compileXPath(WSA_FAULT_TO);
191     
192     /** The Constant WSA_ACTION_XPATH. */
193     public static final XPathExpression WSA_ACTION_XPATH = compileXPath(WSA_ACTION);
194     
195     /** The Constant WSA_FROM_XPATH. */
196     public static final XPathExpression WSA_FROM_XPATH = compileXPath(WSA_FROM);
197     
198     /** The Constant WSA_TO_XPATH. */
199     public static final XPathExpression WSA_TO_XPATH = compileXPath(WSA_TO);
200     
201     /** The Constant SOAP_HEADER_XPATH. */
202     public static final XPathExpression SOAP_HEADER_XPATH = compileXPath(SOAP_HEADER);
203     
204     /** The Constant SOAP_BODY_XPATH. */
205     public static final XPathExpression SOAP_BODY_XPATH = compileXPath(SOAP_BODY);
206     
207     /** The Constant SOAP_BODY_CONTENT_XPATH. */
208     public static final XPathExpression SOAP_BODY_CONTENT_XPATH = compileXPath(SOAP_BODY_CONTENT);
209     
210     /** The Constant SOAP_WRAPPED_ITK_FIRST_PAYLOAD_XPATH. */
211     public static final XPathExpression SOAP_WRAPPED_ITK_FIRST_PAYLOAD_XPATH = compileXPath(SOAP_WRAPPED_ITK_FIRST_PAYLOAD);
212     
213     /** The Constant SOAP_WRAPPED_ITK_SIMPLE_MESSAGE_RESPONSE_XPATH. */
214     public static final XPathExpression SOAP_WRAPPED_ITK_SIMPLE_MESSAGE_RESPONSE_XPATH = compileXPath(SOAP_WRAPPED_ITK_SIMPLE_MESSAGE_RESPONSE);
215     
216     /** The Constant ITK_SIMPLE_MESSAGE_RESPONSE_CONTENT_XPATH. */
217     public static final XPathExpression ITK_SIMPLE_MESSAGE_RESPONSE_CONTENT_XPATH = compileXPath(ITK_SIMPLE_MESSAGE_RESPONSE_CONTENT);
218 
219     // Security headers
220     /** The Constant WSA_SECURITY_TIMESTAMP_XPATH. */
221     public static final XPathExpression WSA_SECURITY_TIMESTAMP_XPATH = compileXPath(WSA_SECURITY_TIMESTAMP);
222     
223     /** The Constant WSA_SECURITY_CREATED_XPATH. */
224     public static final XPathExpression WSA_SECURITY_CREATED_XPATH = compileXPath(WSA_SECURITY_CREATED);
225     
226     /** The Constant WSA_SECURITY_EXPIRES_XPATH. */
227     public static final XPathExpression WSA_SECURITY_EXPIRES_XPATH = compileXPath(WSA_SECURITY_EXPIRES);
228     
229     /** The Constant WSA_SECURITY_USERNAME_XPATH. */
230     public static final XPathExpression WSA_SECURITY_USERNAME_XPATH = compileXPath(WSA_SECURITY_USERNAME);
231     
232     //The following compiled XPaths need the distribution envelope as the root node / evaluation context    
233     /** The Constant ITK_PAYLOAD_COUNT_XPATH. */
234     public static final XPathExpression ITK_PAYLOAD_COUNT_XPATH = compileXPath(ITK_PAYLOAD_COUNT);
235     
236     /** The Constant ITK_AUDIT_IDENTITY_URI_XPATH. */
237     public static final XPathExpression ITK_AUDIT_IDENTITY_URI_XPATH = compileXPath(ITK_AUDIT_IDENTITY_URI);
238     
239     /** The Constant ITK_AUDIT_IDENTITY_TYPE_XPATH. */
240     public static final XPathExpression ITK_AUDIT_IDENTITY_TYPE_XPATH = compileXPath(ITK_AUDIT_IDENTITY_TYPE);
241     
242     /** The Constant ITK_FROM_ADDRESS_XPATH. */
243     public static final XPathExpression ITK_FROM_ADDRESS_XPATH = compileXPath(ITK_FROM_ADDRESS);
244     
245     /** The Constant ITK_FIRST_TO_ADDRESS_XPATH. */
246     public static final XPathExpression ITK_FIRST_TO_ADDRESS_XPATH = compileXPath(ITK_FIRST_TO_ADDRESS);
247     
248     /** The Constant ITK_PROFILE_ID_XPATH. */
249     public static final XPathExpression ITK_PROFILE_ID_XPATH = compileXPath(ITK_PROFILE_ID);
250     
251     /** The Constant ITK_SERVICE_XPATH. */
252     public static final XPathExpression ITK_SERVICE_XPATH = compileXPath(ITK_SERVICE);
253     
254     /** The Constant ITK_BUSINESS_ACK_HANDLING_SPECIFICATIONS_XPATH. */
255     public static final XPathExpression ITK_BUSINESS_ACK_HANDLING_SPECIFICATIONS_XPATH = compileXPath(ITK_BUSINESS_ACK_HANDLING_SPECIFICATIONS);
256     
257     /** The Constant ITK_TRACKING_ID_XPATH. */
258     public static final XPathExpression ITK_TRACKING_ID_XPATH = compileXPath(ITK_TRACKING_ID);
259     
260     /** The Constant ITK_FIRST_PAYLOAD_XPATH. */
261     public static final XPathExpression ITK_FIRST_PAYLOAD_XPATH = compileXPath(ITK_FIRST_PAYLOAD);
262     
263     /** The Constant ITK_FIRST_PAYLOAD_ID_XPATH. */
264     public static final XPathExpression ITK_FIRST_PAYLOAD_ID_XPATH = compileXPath(ITK_FIRST_PAYLOAD_ID);
265     
266     /** The Constant ITK_FIRST_PAYLOAD_TEXT_XPATH. */
267     public static final XPathExpression ITK_FIRST_PAYLOAD_TEXT_XPATH = compileXPath(ITK_FIRST_PAYLOAD_TEXT);
268 
269     /** The Constant ITK_FIRST_MIMETYPE_XPATH. */
270     public static final XPathExpression ITK_FIRST_MIMETYPE_XPATH = compileXPath(ITK_FIRST_MIMETYPE);
271     
272     /** The Constant ITK_FIRST_BASE64_XPATH. */
273     public static final XPathExpression ITK_FIRST_BASE64_XPATH = compileXPath(ITK_FIRST_BASE64);
274 
275     
276     //The following compiled XPaths work for SOAP faults
277     /** The Constant WSA_SOAP_ERROR_DETAIL_XPATH. */
278     public static final XPathExpression WSA_SOAP_ERROR_DETAIL_XPATH = compileXPath(WSA_SOAP_ERROR_DETAIL);
279     
280     /** The Constant WSA_SOAP_ERROR_DETAIL_ID_XPATH. */
281     public static final XPathExpression WSA_SOAP_ERROR_DETAIL_ID_XPATH = compileXPath(WSA_SOAP_ERROR_DETAIL_ID);
282     
283     /** The Constant WSA_SOAP_ERROR_DETAIL_CODE_XPATH. */
284     public static final XPathExpression WSA_SOAP_ERROR_DETAIL_CODE_XPATH = compileXPath(WSA_SOAP_ERROR_DETAIL_CODE);
285     
286     /** The Constant WSA_SOAP_ERROR_DETAIL_TEXT_XPATH. */
287     public static final XPathExpression WSA_SOAP_ERROR_DETAIL_TEXT_XPATH = compileXPath(WSA_SOAP_ERROR_DETAIL_TEXT);
288     
289     /** The Constant WSA_SOAP_ERROR_DETAIL_DIAGNOSTIC_XPATH. */
290     public static final XPathExpression WSA_SOAP_ERROR_DETAIL_DIAGNOSTIC_XPATH = compileXPath(WSA_SOAP_ERROR_DETAIL_DIAGNOSTIC);
291     
292 	public static XPathExpression getXPathExpression(String xPath) {
293 		XPath xp = xpathFactory.newXPath();
294 		xp.setNamespaceContext(NS_CONTEXT);
295 		try {
296 			return xp.compile(xPath);
297 		} catch (XPathExpressionException e) {
298 			Logger.error("Error compiling XPath \"" + xPath + "\"", e);
299 		}
300 		return null;
301 	}
302     
303 	
304 	/**
305 	 * Compile x path.
306 	 *
307 	 * @param xPath the x path
308 	 * @return the x path expression
309 	 */
310 	private static XPathExpression compileXPath(String xPath) {
311 		XPath xp = xpathFactory.newXPath();
312 		xp.setNamespaceContext(NS_CONTEXT);
313 		try {
314 			return xp.compile(xPath);
315 		} catch (XPathExpressionException e) {
316 			Logger.error("Error compiling XPath \"" + xPath + "\"", e);
317 		}
318 		return null;
319 	}
320 	
321 	
322 
323 }