View Javadoc
1   /**
2    * This Source Code Form is subject to the terms of the Mozilla Public
3    * License, v. 2.0. If a copy of the MPL was not distributed with this
4    * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5    *
6    * If it is not possible or desirable to put the notice in a particular
7    * file, then You may include the notice in a location (such as a LICENSE
8    * file in a relevant directory) where a recipient would be likely to look
9    * for such a notice.
10   *
11   *
12   */
13  /*  ---------------------------------------------------------------------------
14   *  U.S. Government, Department of the Army
15   *  Army Materiel Command
16   *  Research Development Engineering Command
17   *  Communications Electronics Research Development and Engineering Center
18   *  ---------------------------------------------------------------------------
19   */
20  package org.miloss.fgsms.agents;
21  
22  import com.sun.net.httpserver.HttpExchange;
23  import java.io.ByteArrayOutputStream;
24  import java.io.IOException;
25  import java.net.InetAddress;
26  import java.net.UnknownHostException;
27  import java.util.*;
28  import javax.servlet.http.HttpServletRequest;
29  import javax.xml.soap.SOAPMessage;
30  import javax.xml.ws.handler.soap.SOAPMessageContext;
31  import org.miloss.fgsms.agentcore.DependencyHelper;
32  import org.miloss.fgsms.agentcore.MessageProcessor;
33  import org.miloss.fgsms.common.Utility;
34  import org.apache.log4j.Level;
35  import org.miloss.fgsms.agentcore.IMessageProcessor;
36  import org.miloss.fgsms.common.Logger;
37  ;
38  import org.miloss.fgsms.common.Constants;
39  
40  /**
41   * This class covers all JAXWS based handler traffic, client and service side
42   *
43   * @author AO
44   */
45  
46  
47  public class JAXWSGenericCommonMessageHandler {
48  
49      static final Logger log = Logger.getLogger(org.miloss.fgsms.common.Constants.LoggerName);
50  
51      public static void processRequest(SOAPMessageContext messageContext, boolean client, String classname) {
52          log.log(Level.DEBUG, "Current VM Memory : total = " + Runtime.getRuntime().totalMemory() + " free = " + Runtime.getRuntime().freeMemory());
53          long start = System.currentTimeMillis();
54          UUID id = UUID.randomUUID();
55          messageContext.put(org.miloss.fgsms.common.Constants.key, id);
56          SOAPMessage msg = messageContext.getMessage();
57          try {
58              IMessageProcessor mp = MessageProcessor.getSingletonObject();
59          } catch (Exception ex) {
60              log.log(Level.ERROR, "Unable to get a reference to the Message Processor singleton object", ex);
61          }
62          String transactionthreadid = "";
63  
64          log.log(Level.DEBUG, "fgsms message context is of type " + messageContext.getClass().getName());
65          //log.log(Level.WARN, "fgsms Timer, inbound setup3 " + (System.currentTimeMillis() - start));
66          HttpServletRequest ctx = null;
67  
68          try {
69              ctx = (HttpServletRequest) messageContext.get(messageContext.SERVLET_REQUEST);
70          } catch (Exception ex) {
71          }
72  
73          String action = org.miloss.fgsms.common.Constants.Undetermineable;
74          java.util.Map<java.lang.String, java.util.List<java.lang.String>> headers = null;
75          try {
76  
77              headers = (Map<String, List<String>>) messageContext.get(messageContext.HTTP_REQUEST_HEADERS);
78              if (headers != null) {
79                  List l = headers.get("SOAPAction");
80                  if (l != null && !l.isEmpty()) {
81                      action = (String) l.get(0);
82                  }
83              }
84          } catch (Exception ex) {
85              log.log(Level.WARN, "error getting outbound soap action", ex);
86          }
87  
88          if (action.equals(org.miloss.fgsms.common.Constants.Undetermineable) && ctx != null) {
89              try {
90                  //ctx = (HttpServletRequest) messageContext.get(messageContext.SERVLET_REQUEST);
91                  action = ctx.getHeader("SOAPAction");
92                  if (Utility.stringIsNullOrEmpty(action)) {
93                      action = org.miloss.fgsms.common.Constants.Undetermineable;
94                  }
95                  action = action.replace("\"", "");
96                  action = action.replace("'", "");
97                  if (Utility.stringIsNullOrEmpty(action)) {
98                      action = org.miloss.fgsms.common.Constants.Undetermineable;
99                  }
100                 //  if (!Utility.stringIsNullOrEmpty(action)) {
101                 ///  action = action.replace("\"", "");
102                 //  action = action.replace("\'", "");
103                 //  }
104             } catch (Exception ex) {
105                 log.log(Level.WARN, "fgsms error getting context object " + ex.getLocalizedMessage());
106             }
107         }
108         if (action.equals(org.miloss.fgsms.common.Constants.Undetermineable)) {
109             try {
110                 action = (String) messageContext.get(messageContext.WSDL_OPERATION);
111                 action = action.replace("\"", "");
112                 action = action.replace("'", "");
113                 if (Utility.stringIsNullOrEmpty(action)) {
114                     action = org.miloss.fgsms.common.Constants.Undetermineable;
115                 }
116             } catch (Exception ex) {
117             }
118         }
119         if (Utility.stringIsNullOrEmpty(action)) {
120             action = org.miloss.fgsms.common.Constants.Undetermineable;
121         }
122         action = action.replace("\"", "");
123         action = action.replace("'", "");
124 
125         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.DCSaction3.toLowerCase().trim())) {
126             log.log(Level.DEBUG, "fgsms, skipping the request for DCS AddData to prevent recursive looping. This is normal and no action is required.");
127             return;     //prevent recursive loops
128         }
129         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.DCSaction4.toLowerCase().trim())) {
130             log.log(Level.DEBUG, "fgsms, skipping the request for DCS AddData to prevent recursive looping. This is normal and no action is required.");
131             return;     //prevent recursive loops
132         }
133 
134         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.DCSaction.toLowerCase().trim())) {
135             log.log(Level.DEBUG, "fgsms, skipping the request for DCS AddData to prevent recursive looping. This is normal and no action is required.");
136             return;     //prevent recursive loops
137         }
138         //if (action.equalsIgnoreCase("urn:org:miloss:fgsms:services:interfaces:policyConfiguration/policyConfigurationService/GetServicePolicy")) {
139         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.PCSaction.toLowerCase().trim())) {
140             log.log(Level.DEBUG, "fgsms, skipping the request for PCS GetServicePolicy to prevent recursive looping. This is normal and no action is required.");
141             return;     //prevent recursive loops
142         }
143 
144         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.DCSaction2.toLowerCase().trim())) {
145             log.log(Level.DEBUG, "fgsms, skipping the request for DCS AddData to prevent recursive looping. This is normal and no action is required.");
146             return;     //prevent recursive loops
147         }
148         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.PCSaction2.toLowerCase().trim())) {
149             log.log(Level.DEBUG, "fgsms, skipping the request for PCS GetServicePolicy to prevent recursive looping. This is normal and no action is required.");
150             return;     //prevent recursive loops
151         }
152 
153         String requestURL = "";
154         if (ctx != null) {
155             try {
156                 StringBuffer buff = ctx.getRequestURL();
157                 requestURL = buff.toString();
158             } catch (Exception ex) {
159                 log.log(Level.WARN, "fgsms error getting request url " + ex.getLocalizedMessage());
160                 requestURL = "";
161             }
162 
163         }
164         if (Utility.stringIsNullOrEmpty(requestURL)) {
165             try {
166 
167                 requestURL = (String) messageContext.get("javax.xml.ws.service.endpoint.address");
168             } catch (Exception ex) {
169                 log.log(Level.WARN, "fgsms error getting request url " + ex.getLocalizedMessage());
170                 requestURL = "";
171             }
172         }
173         if ((Utility.stringIsNullOrEmpty(requestURL)) && ctx != null) {
174             try {
175                 StringBuffer buff = ctx.getRequestURL();
176                 requestURL = buff.toString();
177             } catch (Exception ex) {
178                 log.log(Level.WARN, "fgsms error getting request url " + ex.getLocalizedMessage());
179                 requestURL = "";
180 
181             }
182         }
183 
184         //fix for standalone web services using the Endpoint API
185         if (Utility.stringIsNullOrEmpty(requestURL) && messageContext.containsKey("com.sun.xml.internal.ws.http.exchange")) {
186             try {
187                 HttpExchange exchg = (HttpExchange) messageContext.get("com.sun.xml.internal.ws.http.exchange");
188                 requestURL = ((exchg.getProtocol().toLowerCase().startsWith("https")) ? "https:/" : "http:/") + exchg.getLocalAddress().toString() + exchg.getRequestURI().toString();
189                 // HTTP/1.1://192.168.1.1:4444/Service1
190             } catch (Exception ex) {
191             }
192         }
193 
194         if (Utility.stringIsNullOrEmpty(requestURL)) {
195             requestURL = "urn:" + MessageProcessor.getSingletonObject().getHostName() + ":undeterminable";
196         }
197 
198         ByteArrayOutputStream b = new ByteArrayOutputStream();
199         String messagexml = "";
200         //if (MessageProcessor.shouldAgentRecordRequestContent(requestURL))
201         {
202             try {
203                 msg.writeTo(b);
204                 messagexml = b.toString(Constants.CHARSET);
205             } catch (Exception ex) {
206                 log.log(Level.WARN, "fgsms, error obtaining request message.", ex);
207                 messagexml = "fgsms was unable to obtain the request message.";
208             }
209         }
210 
211         if (action.equals(org.miloss.fgsms.common.Constants.Undetermineable)) {
212             action = Utility.getActionNameFromXML(messagexml);
213             if (Utility.stringIsNullOrEmpty(action)) {
214                 action = org.miloss.fgsms.common.Constants.Undetermineable;
215             }
216             action = action.replace("\"", "");
217             action = action.replace("'", "");
218             if (Utility.stringIsNullOrEmpty(action)) {
219                 action = org.miloss.fgsms.common.Constants.Undetermineable;
220             }
221         }
222         if (action.equals(org.miloss.fgsms.common.Constants.Undetermineable)) {
223             action = (String) messageContext.get(messageContext.HTTP_REQUEST_METHOD);
224             if (Utility.stringIsNullOrEmpty(action)) {
225                 action = org.miloss.fgsms.common.Constants.Undetermineable;
226             }
227             action = action.replace("\"", "");
228             action = action.replace("'", "");
229             if (Utility.stringIsNullOrEmpty(action)) {
230                 action = org.miloss.fgsms.common.Constants.Undetermineable;
231             }
232         }
233 
234         log.log(Level.DEBUG, "fgsms Agent for JAXWS, inbound message for " + requestURL + " action " + action);
235         //log.log(Level.WARN, "fgsms Timer, inbound setup4 " + (System.currentTimeMillis() - start));
236         //special case
237 
238         String user = "";
239 
240         try {
241             if (ctx != null) {
242                 user = ctx.getRemoteUser();
243             }
244             if (ctx != null && ctx.getAuthType() != null && ctx.getUserPrincipal() != null) {
245                 String u = ctx.getUserPrincipal().getName();
246                 if (!u.equals(user)) {
247                     user += " " + ctx.getUserPrincipal().getName();
248                 }
249             }
250         } catch (Exception ex) {
251             log.log(Level.WARN, "fgsms error getting user principal " + ex.getLocalizedMessage());
252         }
253 
254         //ctx2.getOperationMetaData().isOneWay();
255         String ipaddress = "";
256         if (client) {
257 
258             transactionthreadid = MessageProcessor.getSingletonObject().getTransactionThreadId(Thread.currentThread().getId());
259             if (Utility.stringIsNullOrEmpty(transactionthreadid)) {
260                 //if not, create a new one
261                 try {
262                     transactionthreadid = UUID.randomUUID().toString();
263                 } catch (Exception ex) {
264                     log.log(Level.WARN, "error caught build transaction thread id", ex);
265                 }
266 
267             }
268 
269             if (headers == null) {
270                 headers = new HashMap<String, List<String>>();
271             }
272             if (MessageProcessor.getSingletonObject().isDependencyInjectionEnabled()) {
273                 DependencyHelper.insertThreadIdHeader(transactionthreadid, messageContext);
274                 DependencyHelper.insertRelatedMessageHeader(id.toString(), messageContext);
275                 ArrayList t = new ArrayList();
276                 t.add(transactionthreadid);
277                 headers.put(org.miloss.fgsms.common.Constants.transactionthreadKey, t);
278                 t = new ArrayList();
279                 t.add(id.toString());
280                 headers.put(org.miloss.fgsms.common.Constants.relatedtransactionKey, t);
281                 //append to http header, transactionthreadid
282                 //append to http header, id
283                 messageContext.remove(messageContext.HTTP_REQUEST_HEADERS);
284                 messageContext.put(messageContext.HTTP_REQUEST_HEADERS, headers);
285             }
286 
287             try {
288                 InetAddress addr = InetAddress.getLocalHost();
289                 ipaddress = addr.getHostAddress();
290             } catch (UnknownHostException ex) {
291                 log.log(Level.ERROR, "error obtaining local ip address", ex);
292             }
293         } else {
294             if (ctx != null) {
295                 ipaddress = ctx.getRemoteAddr();
296             }
297 
298         }
299         String relatedTransaction = null;
300         //String threadid = null;
301         if (!client) {
302             //inbound request to a service
303             //check for thread id
304             //if not null, MP.setthreadid
305             //check for related message id
306             if (headers == null) {
307                 headers = new HashMap<String, List<String>>();
308             }
309             if (headers.containsKey(org.miloss.fgsms.common.Constants.MessageId)) {
310                 relatedTransaction = ((List<String>) headers.get(org.miloss.fgsms.common.Constants.relatedtransactionKey)).get(0);
311             }
312             if (Utility.stringIsNullOrEmpty(relatedTransaction)) {
313                 relatedTransaction = org.miloss.fgsms.agentcore.DependencyHelper.getRelatedMessageIdFromSoapHeader(messageContext);
314             }
315             if (headers.containsKey(org.miloss.fgsms.common.Constants.transactionthreadKey)) {
316                 transactionthreadid = ((List<String>) headers.get(org.miloss.fgsms.common.Constants.transactionthreadKey)).get(0);
317             }
318             if (Utility.stringIsNullOrEmpty(transactionthreadid)) {
319                 transactionthreadid = org.miloss.fgsms.agentcore.DependencyHelper.getThreadIdFromSoapHeader(messageContext);
320             }
321 
322             if (Utility.stringIsNullOrEmpty(transactionthreadid)) {
323                 transactionthreadid = UUID.randomUUID().toString();
324             }
325             try {
326                 MessageProcessor.getSingletonObject().setTransactionThreadId(Thread.currentThread().getId(), transactionthreadid);
327             } catch (Exception ex) {
328             }
329         }
330 
331         HashMap headervalues = new HashMap();
332         if (ctx != null) {
333             try {
334                 Enumeration<String> headersnames = ctx.getHeaderNames();
335 
336                 while (headersnames.hasMoreElements()) {
337                     String s = headersnames.nextElement();
338                     headervalues.put(s, ctx.getHeader(s));
339                     //   log.log(Level.INFO, "fgsms, Http header key: " + s + " value " + ctx.getHeader(s));
340                 }
341             } catch (Exception ex) {
342                 log.log(Level.WARN, "fgsms error getting http headers " + ex.getLocalizedMessage());
343             }
344         }
345 
346         if (ctx != null) {
347             try {
348                 String query = ctx.getQueryString();
349                 if (query != null && (query == null ? "null" != null : !query.equals("null"))) {
350                     requestURL += "?" + query;
351                 }
352             } catch (Exception ex) {
353                 log.log(Level.WARN, "fgsms error getting request query string " + ex.getLocalizedMessage());
354             }
355         }
356 
357         messageContext.put(org.miloss.fgsms.common.Constants.urlKEY, requestURL);
358         log.log(Level.DEBUG, "fgsms Message intercepted, this is a request message to " + requestURL + " with the SOAPAction of " + action + ". Assigning message id:" + id.toString());
359 
360         try {
361             MessageProcessor.getSingletonObject().processMessageInput(messagexml, messagexml.length(), requestURL, action, user, id.toString(), headervalues, ipaddress, classname, relatedTransaction, transactionthreadid);
362         } catch (Exception ex) {
363             log.log(Level.ERROR, "Unable to get a reference to the MessageProcessor.processMessageInput", ex);
364         }
365         log.log(Level.DEBUG, "estimated additional latency " + (System.currentTimeMillis() - start));
366     }
367 
368     public static void processResponse(SOAPMessageContext messageContext, boolean fault, boolean client, String classname) {
369         log.log(Level.DEBUG, "Current VM Memory : total = " + Runtime.getRuntime().totalMemory() + " free = " + Runtime.getRuntime().freeMemory());
370         long start = System.currentTimeMillis();
371         UUID id = (UUID) messageContext.get(org.miloss.fgsms.common.Constants.key);
372         String requrl = (String) messageContext.get(org.miloss.fgsms.common.Constants.urlKEY);
373         boolean ok = true;
374         if (id == null) {
375             log.log(Level.DEBUG, "fgsms reply message did not have context variable " + org.miloss.fgsms.common.Constants.key + " added. This transaction will be ignored.");
376             ok = false;
377         }
378         if (Utility.stringIsNullOrEmpty(requrl)) {
379             log.log(Level.DEBUG, "fgsms reply message did not have context variable " + org.miloss.fgsms.common.Constants.urlKEY + " added. This transaction will be ignored.");
380             ok = false;
381         }
382 
383         if (!ok) {
384             if (id != null) {
385                 MessageProcessor.getSingletonObject().removeFromQueue(id);
386             }
387             return;
388         }
389 
390         HashMap headervalues = new HashMap();
391         String relatedtransaction = null;
392         if (client) {
393             relatedtransaction = DependencyHelper.getRelatedMessageIdFromSoapHeader(messageContext);
394             try {
395                 Map headers = (Map) messageContext.get(messageContext.HTTP_RESPONSE_HEADERS);
396                 if (headers != null) {
397                     log.log(Level.DEBUG, "client received " + headers.size() + " transaction " + id.toString());
398                     Iterator it = headers.keySet().iterator();
399                     while (it.hasNext()) {
400                         String s = (String) it.next();
401                         log.log(Level.DEBUG, " client header " + s + " = " + headers.get(s).toString());
402                         headervalues.put(s, headers.get(s).toString());
403                     }
404 
405                 }
406 
407             } catch (Exception ex) {
408                 log.log(Level.ERROR, "Unexpected error caught when searching for fgsms soap header", ex);
409             }
410         }
411 
412         if (!client) {
413             //service response, insert fgsms headers
414             ArrayList<String> l = new ArrayList<String>();
415             l.add(id.toString());
416             ArrayList<String> threadlist = new ArrayList<String>();
417             threadlist.add(MessageProcessor.getSingletonObject().getTransactionThreadId(Thread.currentThread().getId()));
418             java.util.Map<java.lang.String, java.util.List<java.lang.String>> headers = (Map<String, List<String>>) messageContext.get(messageContext.HTTP_RESPONSE_HEADERS);
419             if (MessageProcessor.getSingletonObject().isDependencyInjectionEnabled()) {
420                 DependencyHelper.insertRelatedMessageHeader(id.toString(), messageContext);
421                 DependencyHelper.insertThreadIdHeader(threadlist.get(0), messageContext);
422                 if (headers != null) {
423                     headers.put(org.miloss.fgsms.common.Constants.relatedtransactionKey, l);
424                 } else {
425                     headers = new HashMap<String, List<String>>();
426                     headers.put(org.miloss.fgsms.common.Constants.relatedtransactionKey, l);
427                     headers.put(org.miloss.fgsms.common.Constants.transactionthreadKey, threadlist);
428                     messageContext.put(messageContext.HTTP_RESPONSE_HEADERS, headers);
429                     //log.log(Level.WARN, "fgsms response header map is null");
430                 }
431             }
432             if (headers != null) {
433                 Iterator it = headers.keySet().iterator();
434                 while (it.hasNext()) {
435                     String s = (String) it.next();
436                     log.log(Level.DEBUG, " service response header " + s + " = " + headers.get(s).toString());
437                     headervalues.put(s, headers.get(s).toString());
438                 }
439             }
440             /*
441              * try {
442              * messageContext.getMessage().getSOAPHeader().addHeaderElement(new
443              * QName("org.miloss.fgsms.agent", "fgsmsAgent")); } catch
444              * (SOAPException ex) {
445              * Logger.getLogger(JbossWSCommonMessageHandler.class.getName()).log(Level.ERROR,
446              * "Error adding fgsms soap header to response message", ex); }
447              */
448         }
449 
450         SOAPMessage msg = messageContext.getMessage();
451         ByteArrayOutputStream b = new ByteArrayOutputStream();
452         String messagexml = "";
453         try {
454             msg.writeTo(b);
455             messagexml = b.toString(Constants.CHARSET);
456         } catch (Exception ex) {
457             log.log(Level.WARN, "fgsms, error obtaining response message.", ex);
458             messagexml = "fgsms was unable to obtain response message.";
459             //MessageProcessor.removeFromQueue(id);
460             //return;
461         } finally {
462             try {
463                 b.close();
464             } catch (IOException ex) {
465                 
466             }
467         }
468 
469         String code2 = "200";
470         //  boolean fault = false;
471         try {
472             Object j = messageContext.get(messageContext.HTTP_RESPONSE_CODE).toString();
473             if (j != null) {
474                 code2 = j.toString();
475                 if (!code2.equalsIgnoreCase("200")) {
476                     fault = true;
477                 }
478                 headervalues.put("RESPONSE_CODE", code2);
479             }
480         } catch (Exception ex) {
481             //log.log(Level.WARN, "fgsms error caught attempting to pull the http status code from the current context.");
482         }
483 
484         log.log(Level.DEBUG, "fgsms Message intercepted, this is a response message transaction id:" + id.toString() + " fault=" + fault + " " + classname);
485 
486         MessageProcessor.getSingletonObject().processMessageOutput(id.toString(), messagexml, messagexml.length(), fault, Long.valueOf(System.currentTimeMillis()), headervalues, relatedtransaction);
487         //log.log(Level.WARN, "fgsms Timer, outbound final" + (System.currentTimeMillis() - start));
488         if (!client) {
489             MessageProcessor.getSingletonObject().clearTransactionThreadId(Thread.currentThread().getId());
490         }
491         log.log(Level.DEBUG, "estimated additional latency " + (System.currentTimeMillis() - start));
492     }
493 }