Search in sources :

Example 1 with NotifyContextRequestNGSIv2

use of com.telefonica.iot.cygnus.containers.NotifyContextRequestNGSIv2 in project fiware-cygnus by telefonicaid.

the class NGSIRestHandler method getEvents.

// configure
@Override
public List<Event> getEvents(javax.servlet.http.HttpServletRequest request) throws Exception {
    // Set some MDC logging fields to 'N/A' for this thread
    // Value for the component field is inherited from main thread (CygnusApplication.java)
    org.apache.log4j.MDC.put(CommonConstants.LOG4J_CORR, CommonConstants.NA);
    org.apache.log4j.MDC.put(CommonConstants.LOG4J_TRANS, CommonConstants.NA);
    org.apache.log4j.MDC.put(CommonConstants.LOG4J_SVC, CommonConstants.NA);
    org.apache.log4j.MDC.put(CommonConstants.LOG4J_SUBSVC, CommonConstants.NA);
    // Result
    ArrayList<Event> ngsiEvents = new ArrayList<>();
    // Update the counters
    numReceivedEvents++;
    // Check the headers looking for not supported content type and/or invalid FIWARE service and service path
    Enumeration headerNames = request.getHeaderNames();
    String corrId = null;
    String contentType = null;
    String service = defaultService;
    String servicePath = defaultServicePath;
    String ngsiVersion = null;
    while (headerNames.hasMoreElements()) {
        String headerName = ((String) headerNames.nextElement()).toLowerCase(Locale.ENGLISH);
        String headerValue = request.getHeader(headerName);
        LOGGER.debug("[NGSIRestHandler] Header " + headerName + " received with value " + headerValue);
        switch(headerName) {
            case CommonConstants.HEADER_CORRELATOR_ID:
                corrId = headerValue;
                break;
            case CommonConstants.HTTP_HEADER_CONTENT_TYPE:
                if (wrongContentType(headerValue)) {
                    LOGGER.warn("[NGSIRestHandler] Bad HTTP notification (" + headerValue + " content type not supported)");
                    throw new HTTPBadRequestException(headerValue + " content type not supported");
                } else {
                    contentType = headerValue;
                }
                break;
            case CommonConstants.HEADER_FIWARE_SERVICE:
                if (wrongServiceHeaderLength(headerValue)) {
                    LOGGER.warn("[NGSIRestHandler] Bad HTTP notification ('" + CommonConstants.HEADER_FIWARE_SERVICE + "' header length greater than " + NGSIConstants.SERVICE_HEADER_MAX_LEN + ")");
                    throw new HTTPBadRequestException("'" + CommonConstants.HEADER_FIWARE_SERVICE + "' header length greater than " + NGSIConstants.SERVICE_HEADER_MAX_LEN + ")");
                } else {
                    service = headerValue;
                }
                break;
            case CommonConstants.HEADER_FIWARE_SERVICE_PATH:
                String[] splitValues = headerValue.split(",");
                for (String splitValue : splitValues) {
                    if (wrongServicePathHeaderLength(splitValue)) {
                        LOGGER.warn("[NGSIRestHandler] Bad HTTP notification ('" + CommonConstants.HEADER_FIWARE_SERVICE_PATH + "' header value length greater than " + NGSIConstants.SERVICE_PATH_HEADER_MAX_LEN + ")");
                        throw new HTTPBadRequestException("'fiware-servicePath' header length greater than " + NGSIConstants.SERVICE_PATH_HEADER_MAX_LEN + ")");
                    } else if (wrongServicePathHeaderInitialCharacter(splitValue)) {
                        LOGGER.warn("[NGSIRestHandler] Bad HTTP notification ('" + CommonConstants.HEADER_FIWARE_SERVICE_PATH + "' header value must start with '/'");
                        throw new HTTPBadRequestException("'" + CommonConstants.HEADER_FIWARE_SERVICE_PATH + "' header value must start with '/'");
                    }
                // if else
                }
                // for
                servicePath = headerValue;
                break;
            case CommonConstants.HEADER_NGSI_VERSION:
                ngsiVersion = headerValue;
                break;
            default:
                LOGGER.debug("[NGSIRestHandler] Unnecessary header");
        }
    // switch
    }
    // while
    // Get a service and servicePath and store it in the log4j Mapped Diagnostic Context (MDC)
    MDC.put(CommonConstants.LOG4J_SVC, service == null ? defaultService : service);
    MDC.put(CommonConstants.LOG4J_SUBSVC, servicePath == null ? defaultServicePath : servicePath);
    // If the configuration is invalid, nothing has to be done but to return null
    if (invalidConfiguration) {
        serviceMetrics.add(service, servicePath, 1, request.getContentLength(), 0, 0, 0, 0, 0, 0, 0);
        LOGGER.debug("[NGSIRestHandler] Invalid configuration, thus returning an empty list of Flume events");
        return new ArrayList<>();
    }
    // if
    // Check the method
    String method = request.getMethod().toUpperCase(Locale.ENGLISH);
    if (!method.equals("POST")) {
        serviceMetrics.add(service, servicePath, 1, request.getContentLength(), 0, 1, 0, 0, 0, 0, 0);
        LOGGER.warn("[NGSIRestHandler] Bad HTTP notification (" + method + " method not supported)");
        // so we HTTPBadRequestException for 400 Bad Request instead
        throw new HTTPBadRequestException(method + " method not supported");
    }
    // if
    // Check the notificationTarget
    String target = request.getRequestURI();
    if (!target.equals(notificationTarget)) {
        serviceMetrics.add(service, servicePath, 1, request.getContentLength(), 0, 1, 0, 0, 0, 0, 0);
        LOGGER.warn("[NGSIRestHandler] Bad HTTP notification (" + target + " target not supported, " + notificationTarget + " expected.)");
        throw new HTTPBadRequestException(target + " target not supported, " + notificationTarget + " expected.");
    }
    // Check if received content type is null
    if (contentType == null) {
        serviceMetrics.add(service, servicePath, 1, request.getContentLength(), 0, 1, 0, 0, 0, 0, 0);
        LOGGER.warn("[NGSIRestHandler] Missing content type. Required 'application/json; charset=utf-8'");
        throw new HTTPBadRequestException("Missing content type. Required 'application/json; charset=utf-8'");
    }
    // if
    // Get an internal transaction ID.
    String transId = CommonUtils.generateUniqueId(null, null);
    // Get also a correlator ID if not sent in the notification. Id correlator ID is not notified
    // then correlator ID and transaction ID must have the same value.
    corrId = CommonUtils.generateUniqueId(corrId, transId);
    // Store both of them in the log4j Mapped Diagnostic Context (MDC), this way it will be accessible
    // by the whole source code.
    MDC.put(CommonConstants.LOG4J_CORR, corrId);
    MDC.put(CommonConstants.LOG4J_TRANS, transId);
    LOGGER.debug("[NGSIRestHandler] Starting internal transaction (" + transId + ")");
    // Get the data content
    String data = "";
    String line;
    try (BufferedReader reader = request.getReader()) {
        while ((line = reader.readLine()) != null) {
            data += line;
        }
    // while
    }
    if (data.length() == 0) {
        serviceMetrics.add(service, servicePath, 1, request.getContentLength(), 0, 1, 0, 0, 0, 0, 0);
        LOGGER.warn("[NGSIRestHandler] Bad HTTP notification (No content in the request)");
        throw new HTTPBadRequestException("No content in the request");
    }
    // if
    LOGGER.info("[NGSIRestHandler] Received data (" + data + ")");
    // Parse the original data into a NotifyContextRequest object
    NotifyContextRequest ncr = null;
    NotifyContextRequestNGSIv2 notifyContextRequestNGSIv2 = null;
    Gson gson = new Gson();
    try {
        if (ngsiVersion != null) {
            switch(ngsiVersion) {
                case "legacy":
                    ncr = gson.fromJson(data, NotifyContextRequest.class);
                    LOGGER.debug("[NGSIRestHandler] Parsed NotifyContextRequest on legacy NGSI: " + ncr.toString());
                    break;
                case "normalized":
                    gson = new GsonBuilder().registerTypeAdapter(NotifyContextRequestNGSIv2.class, new NotifyContextRequestNGSIv2Deserializer()).create();
                    notifyContextRequestNGSIv2 = gson.fromJson(data, NotifyContextRequestNGSIv2.class);
                    ncr = notifyContextRequestNGSIv2.toNotifyContextRequest();
                    LOGGER.debug("[NGSIRestHandler] Parsed NotifyContextRequest on normalized NGSIv2: " + ncr.toString());
                    break;
                default:
                    LOGGER.warn("Unknown value: " + ngsiVersion + " for NGSI format");
                    throw new HTTPBadRequestException(ngsiVersion + " format not supported");
            }
        } else {
            ncr = gson.fromJson(data, NotifyContextRequest.class);
            LOGGER.debug("[NGSIRestHandler] Parsed NotifyContextRequest on legacy NGSI: " + ncr.toString());
        }
    } catch (JsonSyntaxException e) {
        serviceMetrics.add(service, servicePath, 1, request.getContentLength(), 0, 1, 0, 0, 0, 0, 0);
        LOGGER.error("[NGSIRestHandler] Runtime error (" + e.getMessage() + ")");
        return null;
    }
    // try catch
    // Split the notified service path and check if it matches the number of notified context responses
    String[] servicePaths = servicePath.split(",");
    // when subservice is /
    if (ngsiVersion != null && ngsiVersion.equals("normalized")) {
        if (servicePaths.length < ncr.getContextResponses().size() && servicePaths.length == 1) /*&& servicePath.equals("/")*/
        {
            LOGGER.debug("[NGSIRestHandler] normalizing servicePath  " + servicePath);
            String[] newServicePaths = new String[ncr.getContextResponses().size()];
            for (int i = 0; i < ncr.getContextResponses().size(); i++) {
                newServicePaths[i] = servicePaths[0];
            }
            servicePaths = newServicePaths;
        }
    }
    if (servicePaths.length != ncr.getContextResponses().size()) {
        serviceMetrics.add(service, servicePath, 1, request.getContentLength(), 0, 1, 0, 0, 0, 0, 0);
        LOGGER.warn("[NGSIRestHandler] Bad HTTP notification ('" + CommonConstants.HEADER_FIWARE_SERVICE_PATH + "' header value: " + servicePath + " does not match the number of notified context responses: " + ncr.getContextResponses().size());
        throw new HTTPBadRequestException("'" + CommonConstants.HEADER_FIWARE_SERVICE_PATH + "' header value does not match the number of notified context responses");
    }
    // if
    // Iterate on the NotifyContextRequest object in order to create an event per ContextElement
    String ids = "";
    for (int i = 0; i < ncr.getContextResponses().size(); i++) {
        ContextElementResponse cer = ncr.getContextResponses().get(i);
        LOGGER.debug("[NGSIRestHandler] NGSI event created for ContextElementResponse: " + cer.toString());
        // Create the appropiate headers
        Map<String, String> headers = new HashMap<>();
        headers.put(CommonConstants.HEADER_FIWARE_SERVICE, service);
        LOGGER.debug("[NGSIRestHandler] Header added to NGSI event (" + CommonConstants.HEADER_FIWARE_SERVICE + ": " + service + ")");
        headers.put(CommonConstants.HEADER_FIWARE_SERVICE_PATH, servicePaths[i]);
        LOGGER.debug("[NGSIRestHandler] Header added to NGSI event (" + CommonConstants.HEADER_FIWARE_SERVICE_PATH + ": " + servicePaths[i] + ")");
        headers.put(CommonConstants.HEADER_CORRELATOR_ID, corrId);
        LOGGER.debug("[NGSIRestHandler] Header added to NGSI event (" + CommonConstants.HEADER_CORRELATOR_ID + ": " + corrId + ")");
        headers.put(NGSIConstants.FLUME_HEADER_TRANSACTION_ID, transId);
        LOGGER.debug("[NGSIRestHandler] Header added to NGSI event (" + NGSIConstants.FLUME_HEADER_TRANSACTION_ID + ": " + transId + ")");
        if (ngsiVersion != null) {
            headers.put(CommonConstants.HEADER_NGSI_VERSION, ngsiVersion);
            LOGGER.debug("[NGSIRestHandler] Header added to NGSI event (" + CommonConstants.HEADER_NGSI_VERSION + ": " + ngsiVersion + ")");
        }
        // Create the NGSI event and add it to the list
        NGSIEvent ngsiEvent = new NGSIEvent(// Headers
        headers, // Bytes version of the notified ContextElement
        (cer.getContextElement().toString() + CommonConstants.CONCATENATOR).getBytes(), // Object version of the notified ContextElement
        cer.getContextElement(), // NGSINameMappingsInterceptor (if configured). Currently, null
        null);
        ngsiEvents.add(ngsiEvent);
        if (ids.isEmpty()) {
            ids += ngsiEvent.hashCode();
        } else {
            ids += "," + ngsiEvent.hashCode();
        }
    // if else
    }
    // for
    // Return the NGSIEvent list
    serviceMetrics.add(service, servicePath, 1, request.getContentLength(), 0, 0, 0, 0, 0, 0, 0);
    LOGGER.debug("[NGSIRestHandler] NGSI events put in the channel, ids=" + ids);
    numProcessedEvents++;
    return ngsiEvents;
}
Also used : Enumeration(java.util.Enumeration) GsonBuilder(com.google.gson.GsonBuilder) HashMap(java.util.HashMap) NotifyContextRequestNGSIv2Deserializer(com.telefonica.iot.cygnus.utils.NotifyContextRequestNGSIv2Deserializer) ArrayList(java.util.ArrayList) HTTPBadRequestException(org.apache.flume.source.http.HTTPBadRequestException) Gson(com.google.gson.Gson) NGSIEvent(com.telefonica.iot.cygnus.interceptors.NGSIEvent) NotifyContextRequest(com.telefonica.iot.cygnus.containers.NotifyContextRequest) ContextElementResponse(com.telefonica.iot.cygnus.containers.NotifyContextRequest.ContextElementResponse) NotifyContextRequestNGSIv2(com.telefonica.iot.cygnus.containers.NotifyContextRequestNGSIv2) JsonSyntaxException(com.google.gson.JsonSyntaxException) BufferedReader(java.io.BufferedReader) NGSIEvent(com.telefonica.iot.cygnus.interceptors.NGSIEvent) Event(org.apache.flume.Event)

Example 2 with NotifyContextRequestNGSIv2

use of com.telefonica.iot.cygnus.containers.NotifyContextRequestNGSIv2 in project fiware-cygnus by telefonicaid.

the class NotifyContextRequestNGSIv2Deserializer method deserialize.

@Override
public NotifyContextRequestNGSIv2 deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    JsonObject jsonObject = json.getAsJsonObject();
    String subscriptionId = jsonObject.get("subscriptionId").getAsString();
    ArrayList<Data> data = deserializeAllData(jsonObject.getAsJsonArray("data"));
    NotifyContextRequestNGSIv2 ncr = new NotifyContextRequestNGSIv2();
    ncr.setSubscriptionId(subscriptionId);
    ncr.setData(data);
    return ncr;
}
Also used : NotifyContextRequestNGSIv2(com.telefonica.iot.cygnus.containers.NotifyContextRequestNGSIv2) JsonObject(com.google.gson.JsonObject) Data(com.telefonica.iot.cygnus.containers.NotifyContextRequestNGSIv2.Data)

Aggregations

NotifyContextRequestNGSIv2 (com.telefonica.iot.cygnus.containers.NotifyContextRequestNGSIv2)2 Gson (com.google.gson.Gson)1 GsonBuilder (com.google.gson.GsonBuilder)1 JsonObject (com.google.gson.JsonObject)1 JsonSyntaxException (com.google.gson.JsonSyntaxException)1 NotifyContextRequest (com.telefonica.iot.cygnus.containers.NotifyContextRequest)1 ContextElementResponse (com.telefonica.iot.cygnus.containers.NotifyContextRequest.ContextElementResponse)1 Data (com.telefonica.iot.cygnus.containers.NotifyContextRequestNGSIv2.Data)1 NGSIEvent (com.telefonica.iot.cygnus.interceptors.NGSIEvent)1 NotifyContextRequestNGSIv2Deserializer (com.telefonica.iot.cygnus.utils.NotifyContextRequestNGSIv2Deserializer)1 BufferedReader (java.io.BufferedReader)1 ArrayList (java.util.ArrayList)1 Enumeration (java.util.Enumeration)1 HashMap (java.util.HashMap)1 Event (org.apache.flume.Event)1 HTTPBadRequestException (org.apache.flume.source.http.HTTPBadRequestException)1