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.services.status.impl;
21  
22  import java.sql.Connection;
23  import java.sql.PreparedStatement;
24  import java.sql.ResultSet;
25  import java.sql.SQLException;
26  import java.util.ArrayList;
27  import java.util.GregorianCalendar;
28  import java.util.List;
29  import java.util.UUID;
30  import javax.annotation.Resource;
31  import javax.jws.WebMethod;
32  import javax.jws.WebParam;
33  import javax.jws.WebResult;
34  import javax.jws.WebService;
35  import javax.jws.soap.SOAPBinding;
36  import javax.xml.datatype.DatatypeConfigurationException;
37  import javax.xml.datatype.DatatypeFactory;
38  import java.util.Calendar;
39  import javax.xml.ws.RequestWrapper;
40  import javax.xml.ws.ResponseWrapper;
41  import javax.xml.ws.WebServiceContext;
42  import org.miloss.fgsms.common.AuditLogger;
43  import org.miloss.fgsms.common.UserIdentityUtil;
44  import org.miloss.fgsms.common.Utility;
45  import org.miloss.fgsms.services.interfaces.common.GetOperatingStatusRequestMessage;
46  import org.miloss.fgsms.services.interfaces.common.GetOperatingStatusResponseMessage;
47  import org.miloss.fgsms.services.interfaces.common.GetOperatingStatusResponseMessage.VersionInfo;
48  import org.miloss.fgsms.services.interfaces.common.PolicyType;
49  import org.miloss.fgsms.services.interfaces.common.SecurityWrapper;
50  import org.miloss.fgsms.services.interfaces.faults.ServiceUnavailableFaultCodes;
51  import org.miloss.fgsms.services.interfaces.status.*;
52  import org.miloss.fgsms.sla.AuxHelper;
53  import org.miloss.fgsms.sla.SLACommon;
54  import org.apache.log4j.Level;
55  import org.miloss.fgsms.common.Logger;
56  ;
57  import org.miloss.fgsms.common.DBUtils;
58  import us.gov.ic.ism.v2.ClassificationType;
59  
60  /**
61   * fgsms's Status Service, gets/sets the status of any arbitrary service
62   *
63   * @author AO
64   * @since v3.0
65   */
66  //@javax.ejb.Stateless 
67  
68  
69  @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.WRAPPED, use = SOAPBinding.Use.LITERAL)
70  @WebService(name = "statusService", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status"
71  //    , wsdlLocation = "WEB-INF/wsdl/Statusv6.wsdl"
72  )
73  public class StatusServiceImpl implements org.miloss.fgsms.services.interfaces.status.StatusService, org.miloss.fgsms.services.interfaces.status.OpStatusService {
74  
75      private static final Logger log = Logger.getLogger("fgsms.StatusService");
76      private static DatatypeFactory df = null;
77      private static Calendar started = null;
78      @Resource
79      private WebServiceContext ctx;
80  
81      public StatusServiceImpl() throws DatatypeConfigurationException {
82          InitDF();
83      }
84  
85      private synchronized void InitDF() throws DatatypeConfigurationException {
86          if (df == null) {
87              df = DatatypeFactory.newInstance();
88          }
89          if (started == null) {
90              GregorianCalendar gcal = new GregorianCalendar();
91              gcal.setTimeInMillis(System.currentTimeMillis());
92              started = (gcal);
93          }
94      }
95  
96      /**
97       * constructor used for unit testing, do not remove
98       *
99       * @param w
100      */
101     protected StatusServiceImpl(WebServiceContext w) throws DatatypeConfigurationException {
102         InitDF();
103         ctx = w;
104     }
105 
106     /**
107      *
108      * @param req
109      * @return returns
110      * org.miloss.fgsms.services.interfaces.status.SetStatusResponseMsg
111      * @throws ServiceUnavailableException
112      * @throws AccessDeniedException
113      */
114     @WebMethod(operationName = "SetStatus", action = "urn:org:miloss:fgsms:services:interfaces:statusService/SetStatus")
115     @WebResult(name = "SetStatusResponseResult", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status")
116     @RequestWrapper(localName = "SetStatus", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.SetStatus")
117     @ResponseWrapper(localName = "SetStatusResponse", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.SetStatusResponse")
118     public SetStatusResponseMsg setStatus(
119             @WebParam(name = "req", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status") SetStatusRequestMsg req)
120             throws AccessDeniedException, ServiceUnavailableException {
121 
122         if (req == null) {
123             throw new IllegalArgumentException("request");
124         }
125         String currentUser = UserIdentityUtil.getFirstIdentityToString(ctx);
126         AuditLogger.logItem(this.getClass().getCanonicalName(), "setStatus", currentUser, "", (req.getClassification()), ctx.getMessageContext());
127         Utility.validateClassification(req.getClassification());
128 
129         if (req.getTimeStamp() == null || Utility.stringIsNullOrEmpty(req.getURI())) {
130             throw new IllegalArgumentException("request parameter uri or timestamp is null");
131         }
132         AuditLogger.logItem(this.getClass().getCanonicalName(), "setStatus", currentUser, req.getURI(), (req.getClassification()), ctx.getMessageContext());
133 
134         //authorize request
135         UserIdentityUtil.assertAgentRole(currentUser, "setStatus", req.getClassification(), ctx);
136 
137         PolicyType pt = PolicyType.STATUS;
138         if (req.getPolicyType() != null) {
139             pt = req.getPolicyType();
140         }
141 
142         //CheckPolicyAndCreate(currentUser, req.getURI());
143         return setStatusInternal(req.getURI(), pt, req.getDomainName(), req.getHostname(), req.getParentObject(), req.getTimeStamp(), req.getMessage(), req.isOperational());
144     }
145 
146     private SetStatusResponseMsg setStatusInternal(String uri, PolicyType pt, String domain, String hostname, String parentObject, Calendar timestamp, String message, boolean operational) {
147         Connection con = Utility.getConfigurationDBConnection();
148         Connection perf = Utility.getPerformanceDBConnection();
149         try {
150 
151             AuxHelper.CheckPolicyAndCreate(uri, con, pt, true, domain, hostname, parentObject);
152 
153             String oldstatusmsg = "";
154             boolean oldstatus = true;
155             boolean firstseenstatus = true;
156             PreparedStatement com = perf.prepareStatement("select * from availability where uri=? order by utcdatetime desc limit 1;");
157             com.setString(1, uri);
158             ResultSet availset = com.executeQuery();
159             if (availset.next()) {
160                 oldstatus = (availset.getBoolean("status"));
161                 oldstatusmsg = availset.getString("message");
162                 if (Utility.stringIsNullOrEmpty(oldstatusmsg)) {
163                     oldstatusmsg = "";
164                 }
165                 //    oldstatusat = availset.getLong("utcdatetime");
166 
167             }
168             availset.close();
169             com.close();
170             long usetime = System.currentTimeMillis();
171             if (timestamp != null) {
172                 try {
173                     usetime = timestamp.getTimeInMillis();
174                 } catch (Exception ex) {
175                 }
176             }
177             com = con.prepareStatement("select * from status  where uri=?;");
178             com.setString(1, uri);
179             availset = com.executeQuery();
180             if (availset.next()) {
181                 firstseenstatus = false;
182             }
183             availset.close();
184             com.close();
185 
186             if (firstseenstatus) {
187                 //insert in status
188                 PreparedStatement state = con.prepareStatement("INSERT INTO status(uri, utcdatetime, message, status, monitored) VALUES (?, ?, ?, ?, ?);");
189                 state.setString(1, uri);
190                 state.setLong(2, usetime);
191                 state.setString(3, message);
192                 state.setBoolean(4, operational);
193                 state.setBoolean(5, false);
194                 state.executeUpdate();
195                 state.close();
196                 //insert current into perf availity
197                 state = perf.prepareStatement("INSERT INTO availability(uri, utcdatetime, id, message, status)   VALUES (?, ?, ?, ?, ?);");
198                 state.setString(1, uri);
199                 state.setLong(2, usetime);
200                 state.setString(3, UUID.randomUUID().toString());
201                 state.setString(4, message);
202                 state.setBoolean(5, operational);
203                 state.executeUpdate();
204                 state.close();
205 
206             } else if (operational != oldstatus || (!operational && !oldstatusmsg.equalsIgnoreCase(message))) {
207                 //if (currenstatus != oldstatus || !oldstatusmsg.equalsIgnoreCase(s)) {
208                 //something happened, let's record it
209 
210                 //update current in config status table
211                 PreparedStatement state = con.prepareStatement("UPDATE status set utcdatetime=?, message=?, status=? where uri=?;");
212                 state.setLong(1, usetime);
213                 state.setString(2, message);
214                 state.setBoolean(3, operational);
215                 state.setString(4, uri);
216                 state.executeUpdate();
217                 state.close();
218 
219                 //insert current into perf availity
220                 state = perf.prepareStatement("INSERT INTO availability(uri, utcdatetime, id, message, status)   VALUES (?, ?, ?, ?, ?);");
221                 state.setString(1, uri);
222                 state.setLong(2, usetime);
223                 state.setString(3, UUID.randomUUID().toString());
224                 state.setString(4, message);
225                 state.setBoolean(5, operational);
226                 state.executeUpdate();
227                 state.close();
228                 if (oldstatus != operational) {
229                     log.log(Level.INFO, "Trigger status change SLAs");
230                     SLACommon.TriggerStatusChange(uri, oldstatus, oldstatusmsg, operational, message, true);
231                 }
232             } else {
233                 //no change in status, just update the now timestamp to keep the ui happy
234                 //update current in config status table
235                 PreparedStatement state = con.prepareStatement("UPDATE status   SET utcdatetime=?, message=? WHERE uri=?;");
236 
237                 state.setLong(1, usetime);
238                 state.setString(2, message);
239                 state.setString(3, uri);
240                 state.executeUpdate();
241                 state.close();
242             }
243 
244             con.close();
245 
246             perf.close();
247             SetStatusResponseMsg x = new SetStatusResponseMsg();
248 
249             x.setStatus(SetResponseStatus.SUCCESS);
250 
251             return x;
252         } catch (SQLException ex) {
253             try {
254                 perf.close();
255             } catch (Exception x) {
256             }
257             try {
258                 con.close();
259             } catch (Exception x) {
260             }
261 
262             log.log(Level.ERROR, "Error querying database for setStatus", ex);
263             SetStatusResponseMsg x = new SetStatusResponseMsg();
264             x.setStatus(SetResponseStatus.FAILURE);
265             return x;
266         } catch (Exception ex) {
267             try {
268                 perf.close();
269             } catch (Exception x) {
270             }
271             try {
272                 con.close();
273             } catch (Exception x) {
274             }
275 
276             log.log(Level.ERROR, "Unexpected rrror querying database for setStatus", ex);
277             SetStatusResponseMsg x = new SetStatusResponseMsg();
278             x.setStatus(SetResponseStatus.FAILURE);
279             return x;
280         }
281     }
282 
283     /**
284      *
285      * @param req
286      * @return returns
287      * org.miloss.fgsms.services.interfaces.status.GetStatusResponseMsg
288      * @throws ServiceUnavailableException
289      * @throws AccessDeniedException
290      */
291     @WebMethod(operationName = "GetStatus", action = "urn:org:miloss:fgsms:services:interfaces:statusService/GetStatus")
292     @WebResult(name = "GetStatusResponseResult", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status")
293     @RequestWrapper(localName = "GetStatus", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.GetStatus")
294     @ResponseWrapper(localName = "GetStatusResponse", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.GetStatusResponse")
295     public GetStatusResponseMsg getStatus(
296             @WebParam(name = "req", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status") GetStatusRequestMsg req)
297             throws AccessDeniedException, ServiceUnavailableException {
298         if (req == null) {
299             throw new IllegalArgumentException("null message body");
300         }
301 
302         Utility.validateClassification(req.getClassification());
303 
304         String currentUser = UserIdentityUtil.getFirstIdentityToString(ctx);
305         AuditLogger.logItem(this.getClass().getCanonicalName(), "getStatus", currentUser, "", (req.getClassification()), ctx.getMessageContext());
306 
307         UserIdentityUtil.assertReadAccess(req.getURI(), currentUser, "getStatus", req.getClassification(), ctx);
308         Connection con = Utility.getConfigurationDBConnection();
309         PreparedStatement com = null;
310         ResultSet rs = null;
311         try {
312             GetStatusResponseMsg ret = null;
313 
314             com = con.prepareStatement("select * from status where uri=? order by uri asc;");
315             com.setString(1, req.getURI());
316             rs = com.executeQuery();
317             int records = 0;
318             while (rs.next()) {
319                 GetStatusResponseMsg t = new GetStatusResponseMsg();
320                 t.setURI(rs.getString("uri"));
321                 t.setOperational(rs.getBoolean("status"));
322                 t.setMessage(rs.getString("message"));
323                 GregorianCalendar cal = new GregorianCalendar();
324                 cal.setTimeInMillis(rs.getLong("utcdatetime"));
325                 t.setTimeStamp((cal));
326                 t.setLastStatusChangeTimeStamp(GetLastChangeTimeStamp(req.getURI()));
327                 ret = t;
328                 records++;
329             }
330             if (records > 1) {
331                 log.log(Level.ERROR, "multiple records for uri " + req.getURI() + " detected. This is unexpected");
332                 throw new NullPointerException("Internal error, see server logs for reason.");
333             }
334             if (ret == null) {
335                 ret = new GetStatusResponseMsg();
336                 ret.setMessage("Status Unknown");
337                 ret.setOperational(false);
338             }
339             ret.setTimeStamp(Calendar.getInstance());
340             ret.setLastStatusChangeTimeStamp(GetLastChangeTimeStamp(req.getURI()));
341             ret.setClassification(getCurrentClassificationLevel());
342             return ret;
343         } catch (SQLException ex) {
344             log.log(Level.ERROR, "Error querying database", ex);
345             ServiceUnavailableException code = new ServiceUnavailableException("", null);
346             code.getFaultInfo().setCode(ServiceUnavailableFaultCodes.DATA_BASE_UNAVAILABLE);
347             throw code;
348         } catch (NullPointerException ex) {
349             log.log(Level.ERROR, "Error querying database for setStatus", ex);
350             ServiceUnavailableException f = new ServiceUnavailableException("", null);
351             f.getFaultInfo().setCode(ServiceUnavailableFaultCodes.UNEXPECTED_ERROR);
352             throw f;
353         } finally {
354             DBUtils.safeClose(rs);
355             DBUtils.safeClose(com);
356             DBUtils.safeClose(con);
357         }
358     }
359 
360     /**
361      *
362      * @param req
363      * @return returns
364      * java.util.List<org.miloss.fgsms.services.interfaces.status.GetStatusResponseMsg>
365      * @throws AccessDeniedException
366      * @throws ServiceUnavailableException
367      */
368     @WebMethod(operationName = "GetAllStatus", action = "urn:org:miloss:fgsms:services:interfaces:statusService/GetAllStatus")
369     @WebResult(name = "GetStatusResponseResult", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status")
370     @RequestWrapper(localName = "GetAllStatus", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.GetAllStatus")
371     @ResponseWrapper(localName = "GetAllStatusResponse", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.GetAllStatusResponse")
372     public List<GetStatusResponseMsg> getAllStatus(
373             @WebParam(name = "req", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status") GetStatusRequestMsg req)
374             throws AccessDeniedException, ServiceUnavailableException {
375         //authorize request?
376         Utility.validateClassification(req.getClassification());
377 
378         String currentUser = UserIdentityUtil.getFirstIdentityToString(ctx);
379         AuditLogger.logItem(this.getClass().getCanonicalName(), "getAllStatus", currentUser, "", (req.getClassification()), ctx.getMessageContext());
380         Connection con = Utility.getConfigurationDBConnection();
381          PreparedStatement com = null;
382          ResultSet rs=null;
383         try {
384             List<GetStatusResponseMsg> ret = new ArrayList<GetStatusResponseMsg>();
385             //DatatypeFactory fac = DatatypeFactory.newInstance();
386 
387            
388             if (UserIdentityUtil.hasGlobalAdministratorRole(currentUser, "getAllStatus", req.getClassification(), ctx)) {
389                 com = con.prepareStatement("select * from status;");
390             } else {
391                 com = con.prepareStatement("select ObjectURI as URI from UserPermissions, status "
392                         + "where status.uri=objecturi and username=? and (ReadObject=true or WriteObject=true or AdministerObject=true or AuditObject=true)  order by URI asc;");
393                 com.setString(1, currentUser);
394             }
395             SecurityWrapper currentlevel = getCurrentClassificationLevel();
396 
397             rs = com.executeQuery();
398             while (rs.next()) {
399                 GetStatusResponseMsg t = new GetStatusResponseMsg();
400                 t.setURI(rs.getString("uri"));
401                 t.setOperational(rs.getBoolean("status"));
402                 t.setMessage(rs.getString("message"));
403                 GregorianCalendar cal = new GregorianCalendar();
404                 cal.setTimeInMillis(rs.getLong("utcdatetime"));
405                 t.setTimeStamp((cal));
406                 t.setClassification(currentlevel);
407                 t.setLastStatusChangeTimeStamp(GetLastChangeTimeStamp(rs.getString("uri")));
408                 ret.add(t);
409             }
410             
411             return ret;
412         } catch (SQLException ex) {
413             log.log(Level.ERROR, "Error querying database", ex);
414         } catch (Exception ex) {
415             log.log(Level.ERROR, "Error querying database", ex);
416         } finally {
417             DBUtils.safeClose(rs);
418             DBUtils.safeClose(com);
419             DBUtils.safeClose(con);
420         }
421         ServiceUnavailableException code = new ServiceUnavailableException("", null);
422         code.getFaultInfo().setCode(ServiceUnavailableFaultCodes.DATA_BASE_UNAVAILABLE);
423         throw code;
424     }
425 
426     /**
427      *
428      * Removes an entry from the status listing, all associated history, SLAs,
429      * and alerting subscriptions requires global admin rights
430      *
431      * @param req
432      * @return returns
433      * org.miloss.fgsms.services.interfaces.status.RemoveStatusResponseMsg
434      * @throws ServiceUnavailableException
435      * @throws AccessDeniedException
436      */
437     @WebMethod(operationName = "RemoveStatus", action = "urn:org:miloss:fgsms:services:interfaces:statusService/RemoveStatus")
438     @WebResult(name = "response", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status")
439     @RequestWrapper(localName = "RemoveStatus", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.RemoveStatus")
440     @ResponseWrapper(localName = "RemoveStatusResponse", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.RemoveStatusResponse")
441     public RemoveStatusResponseMsg removeStatus(
442             @WebParam(name = "req", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status") RemoveStatusRequestMsg req)
443             throws AccessDeniedException, ServiceUnavailableException {
444         if (req == null) {
445             throw new IllegalArgumentException("empty message body");
446         }
447         Utility.validateClassification(req.getClassification());
448 
449         if (req.getURI().isEmpty()) {
450             throw new IllegalArgumentException("at least one url must be specified");
451         }
452 
453         String currentUser = UserIdentityUtil.getFirstIdentityToString(ctx);
454         AuditLogger.logItem(this.getClass().getCanonicalName(), "removeStatus", currentUser, Utility.listStringtoString(req.getURI()), req.getClassification(), ctx.getMessageContext());
455         UserIdentityUtil.assertGlobalAdministratorRole(currentUser, "removeStatus", req.getClassification(), ctx);
456         Connection con = Utility.getConfigurationDBConnection();
457         Connection perf = Utility.getPerformanceDBConnection();
458         PreparedStatement com = null;
459         try {
460 
461             for (int i = 0; i < req.getURI().size(); i++) {
462                 com = con.prepareStatement("delete from status where uri=?; delete from servicepolicies where uri=?; delete from userpermissions where ObjectURI=?;");
463                 com.setString(1, req.getURI().get(i));
464                 com.setString(2, req.getURI().get(i));
465                 com.setString(3, req.getURI().get(i));
466                 com.executeUpdate();
467                 com.close();
468 
469                 com = perf.prepareStatement("delete from availability where uri=?;");
470                 com.setString(1, req.getURI().get(i));
471                 com.executeUpdate();
472                 com.close();
473             }
474 
475             RemoveStatusResponseMsg ret = new RemoveStatusResponseMsg();
476             ret.setClassification(getCurrentClassificationLevel());
477 
478             return ret;
479         } catch (SQLException ex) {
480             log.log(Level.ERROR, "Error querying database", ex);
481             ServiceUnavailableException code = new ServiceUnavailableException("", null);
482             code.getFaultInfo().setCode(ServiceUnavailableFaultCodes.DATA_BASE_UNAVAILABLE);
483             throw code;
484         } catch (Exception ex) {
485             log.log(Level.ERROR, "Error querying database", ex);
486             ServiceUnavailableException f = new ServiceUnavailableException("", null);
487             f.getFaultInfo().setCode(ServiceUnavailableFaultCodes.UNEXPECTED_ERROR);
488             throw f;
489         } finally {
490             DBUtils.safeClose(con);
491             DBUtils.safeClose(perf);
492         }
493 
494     }
495 
496     private SecurityWrapper getCurrentClassificationLevel() throws ServiceUnavailableException {
497         Connection con = Utility.getConfigurationDBConnection();
498         PreparedStatement comm = null;
499         ResultSet results = null;
500         try {
501             SecurityWrapper ret = new SecurityWrapper();
502 
503             comm = con.prepareStatement("Select classification, caveat from GlobalPolicies;");
504             /////////////////////////////////////////////
505             //get the global policy for data retension
506             /////////////////////////////////////////////
507             results = comm.executeQuery();
508 
509             try {
510                 if (results.next()) {
511                     ret.setClassification(ClassificationType.fromValue(results.getString("classification")));
512                     ret.setCaveats(results.getString("caveat"));
513                     results.close();
514                     comm.close();
515                     con.close();
516                     return ret;
517                 }
518             } catch (Exception ex) {
519                 log.log(Level.ERROR, "error getting global policy", ex);
520             } finally {
521                 DBUtils.safeClose(results);
522                 DBUtils.safeClose(comm);
523             }
524 
525             try {
526                 comm = con.prepareStatement("INSERT INTO GlobalPolicies (PolicyRefreshRate, RecordedMessageCap, classification, caveat) " + " VALUES (?, ?, ?, ?);");
527                 comm.setLong(1, 3 * 60 * 100);
528                 comm.setLong(2, 1024000);
529                 comm.setString(3, "U");
530                 comm.setString(4, "FOUO");
531                 comm.execute();
532             } catch (Exception ex) {
533                 log.log(Level.ERROR, "error setting global policy", ex);
534             } finally {
535                 DBUtils.safeClose(comm);
536             }
537 
538             return ret;
539         } catch (Exception ex) {
540             log.log(Level.ERROR, "Error setting global policy (no records currently exist", ex);
541             ServiceUnavailableException f = new ServiceUnavailableException("", null);
542             f.getFaultInfo().setCode(ServiceUnavailableFaultCodes.DATA_BASE_UNAVAILABLE);
543             throw f;
544         } finally {
545             DBUtils.safeClose(con);
546         }
547     }
548 
549     /**
550      *
551      * @param req
552      * @return returns
553      * org.miloss.fgsms.services.interfaces.status.SetStatusResponseMsg
554      * @throws ServiceUnavailableException
555      * @throws AccessDeniedException
556      */
557     @WebMethod(operationName = "SetMoreStatus", action = "urn:org:miloss:fgsms:services:interfaces:statusService/SetMoreStatus")
558     @WebResult(name = "SetStatusMoreResponseResult", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status")
559     @RequestWrapper(localName = "SetMoreStatus", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.SetMoreStatus")
560     @ResponseWrapper(localName = "SetMoreStatusResponse", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.SetMoreStatusResponse")
561     public SetStatusResponseMsg setMoreStatus(
562             @WebParam(name = "req", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status") List<SetStatusRequestMsg> reqs)
563             throws AccessDeniedException, ServiceUnavailableException {
564         if (reqs == null) {
565             throw new IllegalArgumentException("empty message body");
566         }
567         String currentUser = UserIdentityUtil.getFirstIdentityToString(ctx);
568         if (reqs == null || reqs.isEmpty() || reqs.get(0) == null) {
569             throw new IllegalArgumentException("at least one item must be specified");
570         }
571         Utility.validateClassification(reqs.get(0).getClassification());
572 
573         UserIdentityUtil.assertAgentRole(currentUser, "setMoreStatus", reqs.get(0).getClassification(), ctx);
574         AuditLogger.logItem(this.getClass().getCanonicalName(), "setMoreStatus", currentUser, "", (reqs.get(0).getClassification()), ctx.getMessageContext());
575 
576         Connection con = Utility.getConfigurationDBConnection();
577         Connection perf = Utility.getPerformanceDBConnection();
578         for (int i = 0; i < reqs.size(); i++) {
579             SetStatusRequestMsg req = reqs.get(i);
580             if (req == null) {
581                 throw new IllegalArgumentException("request item " + i + " is null");
582             }
583             if (req.getTimeStamp() == null || Utility.stringIsNullOrEmpty(req.getURI())) {
584                 throw new IllegalArgumentException("request parameter uri or timestamp");
585             }
586             PolicyType pt = PolicyType.STATUS;
587             if (req.getPolicyType() != null) {
588                 pt = req.getPolicyType();
589             }
590 
591             AuxHelper.CheckPolicyAndCreate(req.getURI(), con, pt, true, req.getDomainName(), req.getHostname(), req.getParentObject());
592             //CheckPolicyAndCreate(currentUser, req.getURI());
593 
594             try {
595                 String oldstatusmsg = "";
596                 boolean oldstatus = true;
597                 boolean firstseenstatus = true;
598                 PreparedStatement com = perf.prepareStatement("select * from availability where uri=? order by utcdatetime desc limit 1;");
599                 com.setString(1, req.getURI());
600                 ResultSet availset = com.executeQuery();
601                 if (availset.next()) {
602                     oldstatus = (availset.getBoolean("status"));
603                     oldstatusmsg = availset.getString("message");
604                 }
605                 availset.close();
606                 com.close();
607                 long usetime = System.currentTimeMillis();
608                 if (req.getTimeStamp() != null) {
609                     try {
610                         usetime = req.getTimeStamp().getTimeInMillis();
611                     } catch (Exception ex) {
612                     }
613                 }
614                 com = con.prepareStatement("select * from status  where uri=?;");
615                 com.setString(1, req.getURI());
616                 availset = com.executeQuery();
617                 if (availset.next()) {
618                     firstseenstatus = false;
619                 }
620                 availset.close();
621                 com.close();
622                 if (firstseenstatus) {
623                     //insert in status
624                     PreparedStatement state = con.prepareStatement("INSERT INTO status(uri, utcdatetime, message, status, monitored) VALUES (?, ?, ?, ?, ?);");
625                     state.setString(1, req.getURI());
626                     state.setLong(2, usetime);
627                     state.setString(3, req.getMessage());
628                     state.setBoolean(4, req.isOperational());
629                     state.setBoolean(5, false);
630                     state.executeUpdate();
631                     state.close();
632                     //insert current into perf availity
633                     state = perf.prepareStatement("INSERT INTO availability(uri, utcdatetime, id, message, status)   VALUES (?, ?, ?, ?, ?);");
634                     state.setString(1, req.getURI());
635                     state.setLong(2, usetime);
636                     state.setString(3, UUID.randomUUID().toString());
637                     state.setString(4, req.getMessage());
638                     state.setBoolean(5, req.isOperational());
639                     state.executeUpdate();
640                     state.close();
641 
642                 } else if (req.isOperational() != oldstatus || (!req.isOperational() && !oldstatusmsg.equalsIgnoreCase(req.getMessage()))) {
643                     //update current in config status table
644                     PreparedStatement state = con.prepareStatement("UPDATE status set utcdatetime=?, message=?, status=? where uri=?;");
645                     state.setLong(1, usetime);
646                     state.setString(2, req.getMessage());
647                     state.setBoolean(3, req.isOperational());
648                     state.setString(4, req.getURI());
649                     state.executeUpdate();
650                     state.close();
651 
652                     //insert current into perf availity
653                     state = perf.prepareStatement("INSERT INTO availability(uri, utcdatetime, id, message, status)   VALUES (?, ?, ?, ?, ?);");
654                     state.setString(1, req.getURI());
655                     state.setLong(2, usetime);
656                     state.setString(3, UUID.randomUUID().toString());
657                     state.setString(4, req.getMessage());
658                     state.setBoolean(5, req.isOperational());
659                     state.executeUpdate();
660                     state.close();
661                     if (oldstatus != req.isOperational()) {
662                         log.log(Level.INFO, "Trigger status change SLAs");
663                         SLACommon.TriggerStatusChange(req.getURI(), oldstatus, oldstatusmsg, req.isOperational(), req.getMessage(), true);
664                     }
665                 } else {
666                     //no change in status, just update the now timestamp to keep the ui happy
667                     //update current in config status table
668                     PreparedStatement state = con.prepareStatement("UPDATE status   SET utcdatetime=?, message=? WHERE uri=?;");
669 
670                     state.setLong(1, usetime);
671                     state.setString(2, req.getMessage());
672                     state.setString(3, req.getURI());
673                     state.executeUpdate();
674                     state.close();
675                 }
676 
677             } catch (SQLException ex) {
678                 log.log(Level.ERROR, "Error querying database for setStatus", ex);
679                 SetStatusResponseMsg x = new SetStatusResponseMsg();
680                 x.setStatus(SetResponseStatus.FAILURE);
681                 try {
682                     con.close();
683                     perf.close();
684                 } catch (Exception e) {
685                 }
686                 return x;
687             }
688 
689         }
690         DBUtils.safeClose(con);
691         DBUtils.safeClose(perf);
692         SetStatusResponseMsg x = new SetStatusResponseMsg();
693         x.setStatus(SetResponseStatus.SUCCESS);
694         return x;
695     }
696 
697     /**
698      * returns the last time the status changes, if it has never been recorded,
699      * null is returned
700      *
701      * @param uri
702      * @return
703      */
704     private Calendar GetLastChangeTimeStamp(String uri) {
705         Connection con = Utility.getPerformanceDBConnection();
706         PreparedStatement com = null;
707         ResultSet rs = null;
708         try {
709             Calendar cal = null;
710 
711             com = con.prepareStatement("select * from availability where uri=? order by utcdatetime desc limit 1");
712             com.setString(1, uri);
713             //         Duration d=null;
714             rs = com.executeQuery();
715             if (rs.next()) {
716                 long changeat = rs.getLong("utcdatetime");
717                 //DatatypeFactory f = DatatypeFactory.newInstance();
718                 GregorianCalendar gcal = new GregorianCalendar();
719                 gcal.setTimeInMillis(changeat);
720                 cal = (gcal);
721             }
722 
723             if (cal == null) {
724                 cal = Calendar.getInstance();
725             }
726             return cal;
727         } catch (Exception ex) {
728             log.log(Level.ERROR, null, ex);
729         } finally {
730             DBUtils.safeClose(rs);
731             DBUtils.safeClose(com);
732             DBUtils.safeClose(con);
733         }
734         return null;
735     }
736 
737     /**
738      * Get the operating status of this service
739      *
740      * @param versionInfo
741      * @param dataSentSuccessfully
742      * @param status
743      * @param classification
744      * @param startedAt
745      * @param dataNotSentSuccessfully
746      */
747     /**
748      * Get the operating status of this service
749      *
750      * @param request
751      * @return returns
752      * org.miloss.fgsms.services.interfaces.common.GetOperatingStatusResponseMessage
753      */
754     @WebMethod(operationName = "GetOperatingStatus", action = "urn:org:miloss:fgsms:services:interfaces:opStatusService/GetOperatingStatus")
755     @WebResult(name = "response", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:common")
756     @RequestWrapper(localName = "GetOperatingStatus", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:common", className = "org.miloss.fgsms.services.interfaces.common.GetOperatingStatus")
757     @ResponseWrapper(localName = "GetOperatingStatusResponse", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:common", className = "org.miloss.fgsms.services.interfaces.common.GetOperatingStatusResponse")
758     public GetOperatingStatusResponseMessage getOperatingStatus(
759             @WebParam(name = "request", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:common") GetOperatingStatusRequestMessage request) {
760         if (request == null) {
761             throw new IllegalArgumentException("empty message body");
762         }
763         String currentUser = UserIdentityUtil.getFirstIdentityToString(ctx);
764 
765         Utility.validateClassification(request.getClassification());
766         AuditLogger.logItem(this.getClass().getCanonicalName(), "getOperatingStatus", currentUser, "", (request.getClassification()), ctx.getMessageContext());
767 
768         GetOperatingStatusResponseMessage res = new GetOperatingStatusResponseMessage();
769 
770         res.setClassification(request.getClassification());
771         res.setVersionInfo(new VersionInfo());
772         res.getVersionInfo().setVersionData(org.miloss.fgsms.common.Constants.Version);
773         res.getVersionInfo().setVersionSource(org.miloss.fgsms.common.Constants.class.getCanonicalName());
774         res.setStartedAt(started);
775         boolean ok = true;
776         Connection con = Utility.getConfigurationDBConnection();
777         Connection con2 = Utility.getPerformanceDBConnection();
778         PreparedStatement prepareStatement = null;
779         PreparedStatement prepareStatement2 = null;
780         try {
781             prepareStatement = con.prepareStatement("select 1=1;");
782             prepareStatement.execute();
783 
784             prepareStatement2 = con2.prepareStatement("select 1=1;");
785             prepareStatement2.execute();
786 
787             res.setStatusMessage("OK");
788         } catch (Exception ex) {
789             ok = false;
790             res.setStatusMessage("One or more of the database connections is available");
791         } finally {
792             DBUtils.safeClose(prepareStatement);
793             DBUtils.safeClose(prepareStatement2);
794             DBUtils.safeClose(con2);
795             DBUtils.safeClose(con);
796         }
797         res.setStatus(ok);
798         return res;
799     }
800 
801     /**
802      * Set the Extended Status on a single item. If a policy does not exist for
803      * this item, it will be automatically created
804      *
805      * @param req
806      * @return returns
807      * org.miloss.fgsms.services.interfaces.status.SetStatusResponseMsg
808      * @throws ServiceUnavailableException
809      * @throws AccessDeniedException
810      */
811     @WebMethod(operationName = "SetExtendedStatus", action = "urn:org:miloss:fgsms:services:interfaces:statusService/SetExtendedStatus")
812     @WebResult(name = "SetStatusResponseResult", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status")
813     @RequestWrapper(localName = "SetExtendedStatus", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.SetExtendedStatus")
814     @ResponseWrapper(localName = "SetStatusResponse", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status", className = "org.miloss.fgsms.services.interfaces.status.SetStatusResponse")
815     public SetStatusResponseMsg setExtendedStatus(
816             @WebParam(name = "req", targetNamespace = "urn:org:miloss:fgsms:services:interfaces:status") SetExtendedStatusRequestMsg req)
817             throws AccessDeniedException, ServiceUnavailableException {
818         //TODO write this
819         if (req == null) {
820             throw new IllegalArgumentException("request");
821         }
822         String currentUser = UserIdentityUtil.getFirstIdentityToString(ctx);
823         AuditLogger.logItem(this.getClass().getCanonicalName(), "setStatus", currentUser, "", (req.getClassification()), ctx.getMessageContext());
824         Utility.validateClassification(req.getClassification());
825 
826         if (req.getTimeStamp() == null || Utility.stringIsNullOrEmpty(req.getURI())) {
827             throw new IllegalArgumentException("request parameter uri or timestamp is null");
828         }
829         AuditLogger.logItem(this.getClass().getCanonicalName(), "setStatus", currentUser, req.getURI(), (req.getClassification()), ctx.getMessageContext());
830 
831         //authorize request
832         UserIdentityUtil.assertAgentRole(currentUser, "setStatus", req.getClassification(), ctx);
833 
834         PolicyType pt = PolicyType.STATUS;
835         if (req.getPolicyType() != null) {
836             pt = req.getPolicyType();
837         }
838         SetStatusResponseMsg setStatusInternal = this.setStatusInternal(req.getURI(), pt, req.getDomainName(), req.getHostname(), req.getParentObject(), req.getTimeStamp(), req.getMessage(), req.isOperational());
839         if (setStatusInternal.getStatus() == SetResponseStatus.SUCCESS) {
840             //save the extended status info
841             if (req.getData() != null) {
842                 Connection con = Utility.getPerformanceDBConnection();
843                 PreparedStatement cmd = null;
844                 try {
845                     for (int i = 0; i < req.getData().getItems().size(); i++) {
846                         if (!Utility.stringIsNullOrEmpty(req.getData().getItems().get(i).getName()) && !Utility.stringIsNullOrEmpty(req.getData().getItems().get(i).getValue())) {
847 
848                             try {
849                                 cmd = con.prepareStatement("INSERT INTO statusext(uri, utcdatetime, dataname, datavalue)    VALUES (?, ?, ?, ?);");
850                                 cmd.setString(1, req.getURI());
851                                 cmd.setLong(2, req.getTimeStamp().getTimeInMillis());
852                                 cmd.setString(3, req.getData().getItems().get(i).getName());
853                                 cmd.setString(4, req.getData().getItems().get(i).getValue());
854                             } catch (Exception ex) {
855                                 log.log(Level.ERROR, "unable to save extended status data", ex);
856                             } finally {
857                                 DBUtils.safeClose(cmd);
858                             }
859                         }
860                     }
861                 } catch (Exception ex) {
862                     log.log(Level.ERROR, "unable to save extended status data", ex);
863                 } finally {
864                     DBUtils.safeClose(cmd);
865                     DBUtils.safeClose(con);
866                 }
867 
868             }
869         }
870 
871         return setStatusInternal;
872 
873     }
874 }