/** * */ package org.easysoa.registry.integration; import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import javax.ws.rs.core.Context; import org.easysoa.registry.rest.integration.EndpointStateService; import org.easysoa.registry.rest.integration.ServiceLevelHealth; import org.easysoa.registry.rest.integration.SlaOrOlaIndicator; import org.easysoa.registry.rest.integration.SlaOrOlaIndicators; import org.easysoa.registry.types.Endpoint; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.directory.DirectoryException; import org.nuxeo.ecm.directory.Session; import org.nuxeo.ecm.directory.api.DirectoryService; import org.nuxeo.ecm.directory.sql.filter.SQLBetweenFilter; import org.nuxeo.ecm.platform.query.nxql.NXQLQueryBuilder; import org.nuxeo.ecm.webengine.jaxrs.session.SessionFactory; import org.nuxeo.runtime.api.Framework; /** * Endpoint state service implementation * * @author jguillemotte * */ @Path("easysoa/endpointStateService") public class EndpointStateServiceImpl implements EndpointStateService { // Servlet context @Context HttpServletRequest request; /** * @see org.easysoa.registry.rest.integration.EndpointStateService#updateSlaOlaIndicators(SlaOrOlaIndicator[]) */ @Override public void createSlaOlaIndicators(SlaOrOlaIndicators slaOrOlaIndicators) throws Exception { DirectoryService directoryService = Framework.getService(DirectoryService.class); if(slaOrOlaIndicators != null){ // Open a session on slaOrOlaIndicator directory Session session = directoryService.open("slaOrOlaIndicator"); if(session == null){ throw new Exception("Unable to open a new session on directory 'slaOrOlaIndicator'"); } try{ // Update each indicator for(SlaOrOlaIndicator indicator : slaOrOlaIndicators.getSlaOrOlaIndicatorList()){ // Create new indicator createIndicator(session, indicator); } } catch(Exception ex){ // Return the exception and cancel the transaction throw new Exception("Failed to update SLA or OLA indicators ", ex); } finally { // NB. container manages transaction, so no need to commit or rollback // (see doc of deprecated session.commit()) session.close(); } } } private void createIndicator(Session session, SlaOrOlaIndicator indicator) throws DirectoryException, ClientException, Exception { checkNotNull(indicator.getEndpointId(), "SlaOrOlaIndicator.endpointId"); checkNotNull(indicator.getSlaOrOlaName(), "SlaOrOlaIndicator.slaOrOlaName"); // TODO LATER check that both exist Map<String, Object> properties = new HashMap<String, Object>(); properties.put("endpointId", indicator.getEndpointId()); properties.put("slaOrOlaName", indicator.getSlaOrOlaName()); properties.put("serviceLeveHealth", indicator.getServiceLevelHealth().toString()); properties.put("serviceLevelViolation", indicator.isServiceLevelViolation()); if(indicator.getTimestamp() != null){ GregorianCalendar calendar = new GregorianCalendar(); calendar.setTime(indicator.getTimestamp()); properties.put("timestamp", calendar); } session.createEntry(properties); } private void checkNotNull(String value, String displayName) throws Exception { if (value == null || value.trim().isEmpty()) { throw new Exception(displayName + " must not be empty !"); } } /** * @see org.easysoa.registry.rest.integration.EndpointStateService#updateSlaOlaIndicators(SlaOrOlaIndicator[]) */ @Override public void updateSlaOlaIndicators(SlaOrOlaIndicators slaOrOlaIndicators) throws Exception { DirectoryService directoryService = Framework.getService(DirectoryService.class); if(slaOrOlaIndicators != null){ // Open a session on slaOrOlaIndicator directory Session session = directoryService.open("slaOrOlaIndicator"); if (session == null){ throw new Exception("Unable to open a new session on directory 'slaOrOlaIndicator'"); } try { // Update each indicator for(SlaOrOlaIndicator indicator : slaOrOlaIndicators.getSlaOrOlaIndicatorList()){ // get the indicator if exists Map<String, Serializable> parameters = new HashMap<String, Serializable>(); parameters.put("slaOrOlaName", indicator.getSlaOrOlaName()); parameters.put("endpointId", indicator.getEndpointId()); GregorianCalendar calendar = new GregorianCalendar(); calendar.setTime(indicator.getTimestamp()); parameters.put("timestamp", calendar); DocumentModelList documentModelList = session.query(parameters); DocumentModel indicatorModel; if(documentModelList != null && documentModelList.size() > 0){ // Update existing indicator indicatorModel = documentModelList.get(0); indicatorModel.setPropertyValue("serviceLeveHealth", indicator.getServiceLevelHealth().toString()); indicatorModel.setPropertyValue("serviceLevelViolation", String.valueOf(indicator.isServiceLevelViolation())); session.updateEntry(indicatorModel); } else { // Create new indicator createIndicator(session, indicator); } } } catch (Exception ex) { // Return the exception and cancel the transaction throw new Exception("Failed to update SLA or OLA indicators ", ex); } finally { // NB. container manages transaction, so no need to commit or rollback // (see doc of deprecated session.commit()) session.close(); } } } /** * @see org.easysoa.registry.rest.integration.EndpointStateService#getSlaOrOlaIndicatorsByEnv(String, String, Date, * Date, int, int) */ @Override public SlaOrOlaIndicators getSlaOrOlaIndicatorsByEnv(String environment, String projectId, String periodStart, String periodEnd, int pageSize, int pageStart) throws Exception { // TODO NXQL query returning all endpoints where environment & projectId // TODO put them in call to getSlaOrOlaIndicators(String endpointIds...) and return it CoreSession documentManager = SessionFactory.getSession(request); if(environment != null && !"".equals(environment) && projectId != null && !"".equals(projectId)){ throw new IllegalArgumentException("Environment or projectid parameter must not be null or empty"); } // Fetch SoaNode list ArrayList<String> parameters = new ArrayList<String>(); StringBuilder query = new StringBuilder(); query.append("SELECT * FROM Endpoint WHERE "); // Search parameters if(environment != null && !"".equals(environment)){ query.append(Endpoint.XPATH_ENDP_ENVIRONMENT + " like '?' "); parameters.add(environment); } if(projectId != null && !"".equals(projectId)){ if(environment != null && !"".equals(environment)){ query.append(" AND "); } query.append("endp:projectid" + " like '?' "); parameters.add(projectId); } // Execute query String nxqlQuery = NXQLQueryBuilder.getQuery(query.toString(), parameters.toArray(), false, true); DocumentModelList soaNodeModelList = documentManager.query(nxqlQuery); // Get endpoints list List<String> endpointsList = new ArrayList<String>(); for(DocumentModel documentModel : soaNodeModelList){ endpointsList.add((String)documentModel.getPropertyValue(Endpoint.XPATH_UUID)); } // Get endpoints indicators return this.getSlaOrOlaIndicators(endpointsList, periodStart, periodEnd, pageSize, pageStart); } /** * * not REST, used by above * TODO LATER ask Nuxeo to support OR in SQL Directory queries * * @param endpointIds * @param periodStart * @param periodEnd * @param pageSize * @param pageStart * @return * @throws Exception */ protected SlaOrOlaIndicators getSlaOrOlaIndicators(List<String> endpointIds, String periodStart, String periodEnd, int pageSize, int pageStart) throws Exception { // For each endpoint, get the corresponding indicators and returns the indicator list SlaOrOlaIndicators slaOrOlaIndicators = new SlaOrOlaIndicators(); for(String endpointId : endpointIds){ slaOrOlaIndicators.getSlaOrOlaIndicatorList().addAll(getSlaOrOlaIndicators(endpointId, "", periodStart, periodEnd, pageSize, pageStart).getSlaOrOlaIndicatorList()); } return slaOrOlaIndicators; } public int getTotalNumberOfSlaOrOlaindicators(List<String> endpointIds, String periodStart, String periodEnd) throws Exception { DirectoryService directoryService = Framework.getService(DirectoryService.class); Session session = directoryService.open(org.easysoa.registry.types.SlaOrOlaIndicator.DOCTYPE); if (session == null){ throw new Exception("Unable to open a new session on directory 'slaOrOlaIndicator'"); } try { int totalIndicatorNumber = 0; for(String endpointId : endpointIds){ int indicatorNumber = getTotalNumberOfSlaOrOlaindicators(session, endpointId, "", periodStart, periodEnd); totalIndicatorNumber = totalIndicatorNumber + indicatorNumber; } return totalIndicatorNumber; } catch (Exception ex) { // Return the exception and cancel the transaction throw new Exception("Failed to getTotalNumberOfSlaOrOlaindicators ", ex); } finally { // NB. container manages transaction, so no need to commit or rollback // (see doc of deprecated session.commit()) session.close(); } } public int getTotalNumberOfSlaOrOlaindicators(Session session, String endpointId, String slaOrOlaName, String periodStart, String periodEnd) throws Exception { return session.query(buildParameters(endpointId, slaOrOlaName, periodStart, periodEnd), buildFullTextSearchParams()).size(); } /** * @see org.easysoa.registry.rest.integration.EndpointStateService#getSlaOrOlaIndicators(String, String, Date, * Date, int, int) */ @Override public SlaOrOlaIndicators getSlaOrOlaIndicators(String endpointId, String slaOrOlaName, String periodStart, String periodEnd, int pageSize, int pageStart) throws Exception { SlaOrOlaIndicators slaOrOlaIndicators = new SlaOrOlaIndicators(); DirectoryService directoryService = Framework.getService(DirectoryService.class); Session session = directoryService.open(org.easysoa.registry.types.SlaOrOlaIndicator.DOCTYPE); if (session == null) { throw new Exception("Unable to open a new session on directory '" + org.easysoa.registry.types.SlaOrOlaIndicator.DOCTYPE + "'"); } try { /* * Returns level indicators, in the given period (default : daily) * OPT paginated navigation * @param periodStart : if null day start, if both null returns all in the current day * @param periodEnd : if null now, if both null returns all in the current day * @param pageSize OPT pagination : number of indicators per page, if not specified, all results are returned * @param pageStart OPT pagination : index of the first indicator to return (starts with 0) * @return SlaOrOlaIndicators array of SlaOrOlaIndicator */ Map<String, Serializable> parameters = new HashMap<String, Serializable>(); if(endpointId != null && !"".equals(endpointId)){ parameters.put("endpointId", endpointId); } if(slaOrOlaName != null && !"".equals(slaOrOlaName)){ parameters.put("slaOrOlaName", slaOrOlaName); } // Execute query // Use this method to have request on date range and pagination Map<String, String> orderByParams = new HashMap<String, String>(); Set<String> fullTextSearchParams = new HashSet<String>(); SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); Calendar calendarFrom = new GregorianCalendar(); Calendar calendarTo = new GregorianCalendar(); Calendar currentDate = new GregorianCalendar(); // Add date Range param // If periodEnd is null and period start is null, set to current day end if(periodEnd == null && periodStart == null){ calendarTo.clear(); calendarTo.set(currentDate.get(Calendar.YEAR) , currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DAY_OF_MONTH), 23, 59, 59); } // If period End is null and periodStart not null, set to now else if(periodEnd == null && periodStart != null) { calendarTo.setTime(currentDate.getTime()); } // else set with the periodEnd param else { calendarTo.setTime(dateFormater.parse(periodEnd)); } // Set period start if(periodStart != null){ calendarFrom.setTime(dateFormater.parse(periodStart)); } // If periodStart is null, set to current day start else { calendarFrom.clear(); // NB. to ease testing, temporarily replace by : currentDate.get(Calendar.YEAR) - 1 calendarFrom.set(currentDate.get(Calendar.YEAR), currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DAY_OF_MONTH)); } SQLBetweenFilter dateRangeFilter = new SQLBetweenFilter(calendarFrom, calendarTo); parameters.put("timestamp", dateRangeFilter); // Execute the query DocumentModelList soaNodeModelList = session.query(parameters, fullTextSearchParams, orderByParams, false, pageSize, pageStart * pageSize); SlaOrOlaIndicator indicator; for(DocumentModel model : soaNodeModelList){ indicator = new SlaOrOlaIndicator(); indicator.setEndpointId((String)model.getPropertyValue(org.easysoa.registry.types.SlaOrOlaIndicator.XPATH_ENDPOINT_ID)); indicator.setType(model.getType()); indicator.setServiceLevelHealth(ServiceLevelHealth.valueOf((String)model.getPropertyValue(org.easysoa.registry.types.SlaOrOlaIndicator.XPATH_SERVICE_LEVEL_HEALTH))); indicator.setServiceLevelViolation((Boolean)model.getPropertyValue(org.easysoa.registry.types.SlaOrOlaIndicator.XPATH_SERVICE_LEVEL_VIOLATION)); indicator.setSlaOrOlaName((String)model.getPropertyValue(org.easysoa.registry.types.SlaOrOlaIndicator.XPATH_SLA_OR_OLA_NAME)); GregorianCalendar calendar = (GregorianCalendar)model.getPropertyValue(org.easysoa.registry.types.SlaOrOlaIndicator.XPATH_TIMESTAMP); indicator.setTimestamp(calendar.getTime()); slaOrOlaIndicators.getSlaOrOlaIndicatorList().add(indicator); } } catch (ClientException ex) { // Return the exception and cancel the transaction throw new Exception("Failed to getSlaOrOlaIndicators on paginated range ", ex); } finally { // NB. container manages transaction, so no need to commit or rollback // (see doc of deprecated session.commit()) session.close(); } return slaOrOlaIndicators; } private Map<String, Serializable> buildParameters(String endpointId, String slaOrOlaName, String periodStart, String periodEnd) throws Exception { Map<String, Serializable> parameters = new HashMap<String, Serializable>(); SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); Calendar calendarFrom = new GregorianCalendar(); Calendar calendarTo = new GregorianCalendar(); Calendar currentDate = new GregorianCalendar(); if(endpointId != null && !"".equals(endpointId)){ parameters.put("endpointId", endpointId); } if(slaOrOlaName != null && !"".equals(slaOrOlaName)){ parameters.put("slaOrOlaName", slaOrOlaName); } // Add date Range param // If periodEnd is null and period start is null, set to current day end if(periodEnd == null && periodStart == null){ calendarTo.clear(); calendarTo.set(currentDate.get(Calendar.YEAR) , currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DAY_OF_MONTH), 23, 59, 59); } // If period End is null and periodStart not null, set to now else if(periodEnd == null && periodStart != null) { calendarTo.setTime(currentDate.getTime()); } // else set with the periodEnd param else { calendarTo.setTime(dateFormater.parse(periodEnd)); } // Set period start if(periodStart != null){ calendarFrom.setTime(dateFormater.parse(periodStart)); } // If periodStart is null, set to current day start else { calendarFrom.clear(); // TODO : previous setting was to fix the from date to the current day // But cause some problems to test the UI when the model is not reloaded daily // Remove the "-1" when finished calendarFrom.set(currentDate.get(Calendar.YEAR) - 1, currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DAY_OF_MONTH)); } SQLBetweenFilter dateRangeFilter = new SQLBetweenFilter(calendarFrom, calendarTo); parameters.put("timestamp", dateRangeFilter); return parameters; } private Set<String> buildFullTextSearchParams() { Set<String> fullTextSearchParams = new HashSet<String>(); // TODO : complete this method return fullTextSearchParams; } }