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