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 java.io.ByteArrayOutputStream;
23  import java.io.IOException;
24  import java.util.Enumeration;
25  import java.util.HashMap;
26  import java.util.Hashtable;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.UUID;
30  import javax.xml.namespace.QName;
31  import javax.xml.soap.MimeHeader;
32  import javax.xml.soap.MimeHeaders;
33  import javax.xml.soap.SOAPException;
34  import org.apache.axis.*;
35  import org.apache.axis.utils.LockableHashtable;
36  import org.apache.log4j.Level;
37  import org.miloss.fgsms.agentcore.IMessageProcessor;
38  import org.miloss.fgsms.common.Logger;
39  ;
40  import org.miloss.fgsms.agentcore.MessageProcessor;
41  import org.miloss.fgsms.common.Utility;
42  import org.w3c.dom.Document;
43  import org.w3c.dom.Element;
44  
45  /**
46   *
47   * @author AO
48   */
49  
50  
51  public class Axis1MonitorInbound implements org.apache.axis.Handler {
52  
53      //<editor-fold defaultstate="collapsed" desc="comment">
54      private Logger log;
55  
56      public Axis1MonitorInbound() {
57          log = Logger.getLogger(org.miloss.fgsms.common.Constants.LoggerName);
58      }
59  
60      public void invoke(org.apache.axis.MessageContext mc) throws AxisFault {
61          log.log(Level.INFO, "Current VM Memory : total = " + Runtime.getRuntime().totalMemory() + " free = " + Runtime.getRuntime().freeMemory());
62  
63          Boolean isRequest = true;
64  
65          /*
66           *
67           * when pivot is false, call is usually null
68           *
69           *
70           * logic, inbound and call is defined, response from external service
71           * inbound and call is NOT defined, request from a client
72           *
73           *
74           * or
75           *
76           *
77           * getPastPivot = true and inbound, reponse from external service
78           * getPastPivor = false and inbound, request from a client
79           */
80          isRequest = !mc.getPastPivot();
81  
82          if (isRequest) {
83  
84              try {
85                  ProcessInboundRequestMessage(mc);
86              } catch (Exception ex) {
87                  log.log(Level.WARN, "fgsms Error processing inbound message", ex);
88              }
89          } else {
90              try {
91                  ProcessInboundResponseMessage(mc, false);
92              } catch (Exception ex) {
93                  log.log(Level.WARN, "fgsms Error processing inbound message", ex);
94              }
95          }
96  
97      }
98      protected boolean makeLockable = false;
99      protected Hashtable options;
100     protected String name;
101 
102     /**
103      * Should this Handler use a LockableHashtable for options? Default is
104      * 'false'.
105      */
106     protected void setOptionsLockable(boolean makeLockable) {
107         this.makeLockable = makeLockable;
108     }
109 
110     protected void initHashtable() {
111         if (makeLockable) {
112             options = new LockableHashtable();
113         } else {
114             options = new Hashtable();
115         }
116     }
117 
118     /**
119      * Stubbed-out methods. Override in your child class to implement any real
120      * behavior. Note that there is NOT a stub for invoke(), since we require
121      * any Handler derivative to implement that.
122      */
123     public void init() {
124     }
125 
126     public void cleanup() {
127     }
128 
129     public boolean canHandleBlock(QName qname) {
130         return false;
131     }
132 
133     public void onFault(MessageContext mc) {
134 
135         //determine if this is a request or response, then process
136         Boolean isRequest = true;
137 
138         isRequest = !mc.getPastPivot();
139         if (isRequest) {
140             try {
141                 //hmm how can an inbound  request be a fault? I doubt this will ever get called
142                 ProcessInboundRequestMessage(mc);
143             } catch (Exception ex) {
144                 log.log(Level.WARN, "fgsms Error processing inbound message", ex);
145             }
146         } else {
147             ProcessInboundResponseMessage(mc, true);
148         }
149     }
150 
151     /**
152      * Set the given option (name/value) in this handler's bag of options
153      */
154     public void setOption(String name, Object value) {
155         if (options == null) {
156             initHashtable();
157         }
158         options.put(name, value);
159     }
160 
161     /**
162      * Set a default value for the given option: if the option is not already
163      * set, then set it. if the option is already set, then do not set it.
164      * <p>
165      * If this is called multiple times, the first with a non-null value if
166      * 'value' will set the default, remaining calls will be ignored.
167      * <p>
168      * Returns true if value set (by this call), otherwise false;
169      */
170     public boolean setOptionDefault(String name, Object value) {
171         boolean val = (options == null || options.get(name) == null) && value != null;
172         if (val) {
173             setOption(name, value);
174         }
175         return val;
176     }
177 
178     /**
179      * Returns the option corresponding to the 'name' given
180      */
181     public Object getOption(String name) {
182         if (options == null) {
183             return (null);
184         }
185         return (options.get(name));
186     }
187 
188     /**
189      * Return the entire list of options
190      */
191     public Hashtable getOptions() {
192         return (options);
193     }
194 
195     public void setOptions(Hashtable opts) {
196         options = opts;
197     }
198 
199     /**
200      * Set the name (i.e. registry key) of this Handler
201      */
202     public void setName(String name) {
203         this.name = name;
204     }
205 
206     /**
207      * Return the name (i.e. registry key) for this Handler
208      */
209     public String getName() {
210         return name;
211     }
212 
213     public Element getDeploymentData(Document doc) {
214         log.log(Level.INFO, "Enter: BasicHandler::getDeploymentData");
215 
216         Element root = doc.createElementNS("", "handler");
217 
218         root.setAttribute("class", this.getClass().getName());
219         options = this.getOptions();
220         if (options != null) {
221             Enumeration e = options.keys();
222             while (e.hasMoreElements()) {
223                 String k = (String) e.nextElement();
224                 Object v = options.get(k);
225                 Element e1 = doc.createElementNS("", "option");
226                 e1.setAttribute("name", k);
227                 e1.setAttribute("value", v.toString());
228                 root.appendChild(e1);
229             }
230         }
231         log.log(Level.INFO, "Exit: BasicHandler::getDeploymentData");
232         return (root);
233     }
234 
235     public void generateWSDL(MessageContext msgContext) throws AxisFault {
236     }
237 
238     /**
239      * Return a list of QNames which this Handler understands. By returning a
240      * particular QName here, we are committing to fulfilling any contracts
241      * defined in the specification of the SOAP header with that QName.
242      */
243     public List getUnderstoodHeaders() {
244         return null;
245     }
246     //</editor-fold>
247 
248     /*
249      * Inbound client request to a service
250      */
251     private void ProcessInboundRequestMessage(org.apache.axis.MessageContext messageContext) throws SOAPException {
252 
253         long now = System.currentTimeMillis();
254         try {
255             IMessageProcessor mp = MessageProcessor.getSingletonObject();
256         } catch (Exception ex) {
257             log.log(Level.ERROR, "Unable to get a reference to the Message Processor singleton object", ex);
258         }
259         UUID id = UUID.randomUUID();
260         //log.log(Level.WARN, "fgsms Timer, inbound setup1 " + (System.currentTimeMillis() - start));
261         messageContext.setProperty(org.miloss.fgsms.common.Constants.key, id);
262         //log.log(Level.WARN, "fgsms Timer, inbound setup2 " + (System.currentTimeMillis() - start));
263         org.apache.axis.Message msg = messageContext.getCurrentMessage();
264         String transactionthreadid = "";
265 
266         String action = "";
267 
268         HashMap map = new HashMap();
269         try {
270             MimeHeaders me = messageContext.getMessage().getMimeHeaders();
271             Iterator it = me.getAllHeaders();
272             while (it.hasNext()) {
273                 MimeHeader h = (MimeHeader) it.next();
274                 if (h != null) {
275                     map.put(h.getName(), h.getValue());
276                     if (h.getName().equalsIgnoreCase("SOAPAction")) {
277                         action = h.getValue();
278                     }
279                 }
280             }
281 
282         } catch (Exception ex) {
283             log.log(Level.WARN, "unexpected error caught obtaining http headers from message context" + ex.getLocalizedMessage());
284         }
285 
286         if (Utility.stringIsNullOrEmpty(action)) {
287             action = messageContext.getOperation().getName();
288             if (!Utility.stringIsNullOrEmpty(action)) {
289                 action = action.replace("\"", "");
290                 action = action.replace("'", "");
291             }
292         }
293 
294         if (Utility.stringIsNullOrEmpty(action) && messageContext.useSOAPAction()) {
295             action = messageContext.getSOAPActionURI();
296             if (!Utility.stringIsNullOrEmpty(action)) {
297                 action = action.replace("\"", "");
298                 action = action.replace("'", "");
299             }
300         }
301 
302         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.DCSaction.toLowerCase().trim())) {
303             log.log(Level.DEBUG, "fgsms, skipping the request for DCS AddData to prevent recursive looping. This is normal and no action is required.");
304             return;     //prevent recursive loops
305         }
306 
307         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.DCSaction3.toLowerCase().trim())) {
308             log.log(Level.DEBUG, "fgsms, skipping the request for DCS AddData to prevent recursive looping. This is normal and no action is required.");
309             return;     //prevent recursive loops
310         }
311         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.DCSaction4.toLowerCase().trim())) {
312             log.log(Level.DEBUG, "fgsms, skipping the request for DCS AddData to prevent recursive looping. This is normal and no action is required.");
313             return;     //prevent recursive loops
314         }
315         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.PCSaction.toLowerCase().trim())) {
316             log.log(Level.DEBUG, "fgsms, skipping the request for PCS GetServicePolicy to prevent recursive looping. This is normal and no action is required.");
317             return;     //prevent recursive loops
318         }
319 
320         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.DCSaction2.toLowerCase().trim())) {
321             log.log(Level.DEBUG, "fgsms, skipping the request for DCS AddData to prevent recursive looping. This is normal and no action is required.");
322             return;     //prevent recursive loops
323         }
324         if (action.toLowerCase().trim().equals(org.miloss.fgsms.common.Constants.PCSaction2.toLowerCase().trim())) {
325             log.log(Level.DEBUG, "fgsms, skipping the request for PCS GetServicePolicy to prevent recursive looping. This is normal and no action is required.");
326             return;     //prevent recursive loops
327         }
328 
329         String requestURL = (String) messageContext.getProperty(org.apache.axis.MessageContext.TRANS_URL);
330         String messagexml = "";
331 
332         ByteArrayOutputStream b = new ByteArrayOutputStream();
333         try {
334             msg.writeTo(b);
335             messagexml = b.toString(org.miloss.fgsms.common.Constants.CHARSET);
336         } catch (IOException ex) {
337             log.log(Level.WARN, "fgsms, error obtaining request message.", ex);
338         } finally {
339             try {
340                 b.close();
341             } catch (Exception ex) {
342 
343             }
344         }
345 
346         if (Utility.stringIsNullOrEmpty(action) || action.equals("/DDS")) {
347             action = Utility.getActionNameFromXML(messagexml);
348             if (Utility.stringIsNullOrEmpty(action)) {
349                 action = org.miloss.fgsms.common.Constants.Undetermineable;
350             }
351             action = action.replace("\"", "");
352             action = action.replace("'", "");
353         }
354 
355         if (Utility.stringIsNullOrEmpty(action)) {
356             action = org.miloss.fgsms.common.Constants.Undetermineable;
357         }
358         action = action.replace("\"", "");
359         action = action.replace("'", "");
360 
361         log.log(Level.DEBUG, "fgsms Agent for Axis 1.x, inbound message for " + requestURL + " action " + action);
362 
363         String ip = "";
364         try {
365             ip = (String) messageContext.getProperty("remoteaddr");
366         } catch (Exception ex) {
367         }
368         String relatedTransaction = null;
369         HashMap headers = new HashMap();
370         MimeHeaders mimeHeaders = msg.getMimeHeaders();
371         if (mimeHeaders != null) {
372             Iterator it = mimeHeaders.getAllHeaders();
373             while (it.hasNext()) {
374                 MimeHeader header = (MimeHeader) it.next();
375                 if (header != null) {
376                     headers.put(header.getName(), header.getValue());
377                 }
378             }
379         }
380         if (headers.containsKey(org.miloss.fgsms.common.Constants.MessageId)) {
381             relatedTransaction = (String) headers.get(org.miloss.fgsms.common.Constants.MessageId);
382         }
383         if (headers.containsKey(org.miloss.fgsms.common.Constants.transactionthreadKey)) {
384             transactionthreadid = (String) headers.get(org.miloss.fgsms.common.Constants.transactionthreadKey);
385         }
386         if (Utility.stringIsNullOrEmpty(transactionthreadid)) {
387             transactionthreadid = UUID.randomUUID().toString();
388         }
389         try {
390             MessageProcessor.getSingletonObject().setTransactionThreadId(Thread.currentThread().getId(), transactionthreadid);
391         } catch (Exception ex) {
392         }
393 
394         String user = "";
395 
396         if (!Utility.stringIsNullOrEmpty((String) messageContext.getProperty(org.apache.axis.MessageContext.AUTHUSER))) {
397             user = (String) messageContext.getProperty(org.apache.axis.MessageContext.AUTHUSER);
398         }
399         messageContext.setProperty(org.miloss.fgsms.common.Constants.urlKEY, requestURL);
400 
401         //log.log(Level.WARN, "fgsms Timer, inbound setup10 " + (System.currentTimeMillis() - start));
402         messageContext.setProperty(org.miloss.fgsms.common.Constants.relatedtransactionKey, relatedTransaction);
403         MessageProcessor.getSingletonObject().processMessageInput(messagexml, messagexml.length(), requestURL, action, user, id.toString(), map, ip, this.getClass().getCanonicalName(), relatedTransaction, transactionthreadid);
404 
405     }
406 
407     /*
408      * Client Response from a service
409      */
410     private void ProcessInboundResponseMessage(MessageContext messageContext, boolean fault) {
411 
412         /*
413          * inbound response, aka this object is running on a client request
414          * after the response is returned.
415          */
416         UUID id = (UUID) messageContext.getProperty(org.miloss.fgsms.common.Constants.key);
417         String requrl = (String) messageContext.getProperty(org.miloss.fgsms.common.Constants.urlKEY);
418         if (id == null) {
419             log.log(Level.WARN, "fgsms InboundResponse message did not have context variable added. This is unexpected. This transaction will be ignored");
420             return;
421         }
422         if (Utility.stringIsNullOrEmpty(requrl)) {
423             log.log(Level.WARN, "fgsms InboundResponse message did not have the URL context variable added. This is unexpected. This transaction will be ignored");
424             MessageProcessor.getSingletonObject().removeFromQueue(id);
425             return;
426         }
427         org.apache.axis.Message msg = messageContext.getCurrentMessage();
428 
429         HashMap headers = new HashMap();
430 
431         try {
432             MimeHeaders mimeHeaders = msg.getMimeHeaders();
433             Iterator allHeaders = mimeHeaders.getAllHeaders();
434             while (allHeaders.hasNext()) {
435                 String key = (String) allHeaders.next();
436                 headers.put(key, mimeHeaders.getHeader(key));
437             }
438 
439         } catch (Exception ex) {
440             log.log(Level.ERROR, "Unexpected error caught when searching for fgsms soap header", ex);
441         }
442 
443         String messagexml = "not availabile.";
444 
445         ByteArrayOutputStream b = new ByteArrayOutputStream();
446 
447         try {
448             msg.writeTo(b);
449             messagexml = b.toString(org.miloss.fgsms.common.Constants.CHARSET);
450         } catch (Exception ex) {
451             log.log(Level.WARN, null, ex);
452         } finally {
453             try {
454                 b.close();
455             } catch (Exception ex) {
456             }
457         }
458 
459         log.log(Level.DEBUG, "fgsms Message intercepted, this is a response message to " + requrl + " transaction id:" + id.toString() + " Fault=" + fault);
460         if (fault) {
461             log.log(Level.WARN, "fgsms, this message to " + requrl + " transaction id:" + id.toString() + " has faulted.");
462         }
463 
464         MessageProcessor.getSingletonObject().processMessageOutput(id.toString(), messagexml, messagexml.length(), fault, System.currentTimeMillis(), headers);
465         //  log.log(Level.WARN, "fgsms Timer, outbound final" + (System.currentTimeMillis() - start));
466 
467     }
468 }