com.att.nsa.cambria.service.impl.EventsServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.att.nsa.cambria.service.impl.EventsServiceImpl.java

Source

/*******************************************************************************
 * BSD License
 *  
 * Copyright (c) 2016, AT&T Intellectual Property.  All other rights reserved.
 *  
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *  
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
 *    and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 * 3. All advertising materials mentioning features or use of this software must display the
 *    following acknowledgement:  This product includes software developed by the AT&T.
 * 4. Neither the name of AT&T nor the names of its contributors may be used to endorse or
 *    promote products derived from this software without specific prior written permission.
 *  
 * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *******************************************************************************/
package com.att.nsa.cambria.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.MediaType;

import org.apache.http.HttpStatus;

import com.att.eelf.configuration.EELFLogger;
import com.att.eelf.configuration.EELFManager;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.att.ajsc.filemonitor.AJSCPropertiesMap;
import com.att.nsa.cambria.CambriaApiException;
import com.att.nsa.cambria.backends.Consumer;
import com.att.nsa.cambria.backends.ConsumerFactory;
import com.att.nsa.cambria.backends.ConsumerFactory.UnavailableException;
import com.att.nsa.cambria.backends.MetricsSet;
import com.att.nsa.cambria.backends.Publisher;
import com.att.nsa.cambria.backends.Publisher.message;
import com.att.nsa.cambria.beans.DMaaPCambriaLimiter;
import com.att.nsa.cambria.beans.DMaaPContext;
import com.att.nsa.cambria.beans.LogDetails;
import com.att.nsa.cambria.constants.CambriaConstants;
import com.att.nsa.cambria.exception.DMaaPAccessDeniedException;
import com.att.nsa.cambria.exception.DMaaPErrorMessages;
import com.att.nsa.cambria.exception.DMaaPResponseCode;
import com.att.nsa.cambria.exception.ErrorResponse;
import com.att.nsa.cambria.metabroker.Broker.TopicExistsException;
import com.att.nsa.cambria.metabroker.Topic;
import com.att.nsa.cambria.resources.CambriaEventSet;
import com.att.nsa.cambria.resources.CambriaOutboundEventStream;
import com.att.nsa.cambria.security.DMaaPAAFAuthenticator;
import com.att.nsa.cambria.security.DMaaPAAFAuthenticatorImpl;
import com.att.nsa.cambria.security.DMaaPAuthenticatorImpl;
import com.att.nsa.cambria.service.EventsService;
import com.att.nsa.cambria.utils.DMaaPResponseBuilder;
import com.att.nsa.cambria.utils.Utils;
import com.att.nsa.configs.ConfigDbException;
import com.att.nsa.drumlin.service.standards.MimeTypes;
import com.att.nsa.drumlin.till.nv.rrNvReadable.missingReqdSetting;
import com.att.nsa.security.NsaApiKey;
import com.att.nsa.security.ReadWriteSecuredResource.AccessDeniedException;
import com.att.nsa.util.rrConvertor;

import kafka.producer.KeyedMessage;

/**
 * This class provides the functinality to publish and subscribe message to
 * kafka
 * 
 * @author author
 *
 */
@Service
public class EventsServiceImpl implements EventsService {
    //private static final Logger LOG = Logger.getLogger(EventsServiceImpl.class);
    private static final EELFLogger LOG = EELFManager.getInstance().getLogger(EventsServiceImpl.class);

    private static final String BATCH_LENGTH = "event.batch.length";
    private static final String TRANSFER_ENCODING = "Transfer-Encoding";
    @Autowired
    private DMaaPErrorMessages errorMessages;

    //@Value("${metrics.send.cambria.topic}")
    //private String metricsTopic;

    /**
     * @param ctx
     * @param topic
     * @param consumerGroup
     * @param clientId
     * @throws ConfigDbException,
     *             TopicExistsException, AccessDeniedException,
     *             UnavailableException, CambriaApiException, IOException
     * 
     * 
     */
    @Override
    public void getEvents(DMaaPContext ctx, String topic, String consumerGroup, String clientId)
            throws ConfigDbException, TopicExistsException, AccessDeniedException, UnavailableException,
            CambriaApiException, IOException, DMaaPAccessDeniedException {
        final long startTime = System.currentTimeMillis();
        final HttpServletRequest req = ctx.getRequest();

        boolean isAAFTopic = false;
        // was this host blacklisted?
        final String remoteAddr = Utils.getRemoteAddress(ctx);
        ;
        if (ctx.getConfigReader().getfIpBlackList().contains(remoteAddr)) {

            ErrorResponse errRes = new ErrorResponse(HttpStatus.SC_FORBIDDEN,
                    DMaaPResponseCode.ACCESS_NOT_PERMITTED.getResponseCode(),
                    "Source address [" + remoteAddr
                            + "] is blacklisted. Please contact the cluster management team.",
                    null, Utils.getFormattedDate(new Date()), topic, Utils.getUserApiKey(ctx.getRequest()),
                    ctx.getRequest().getRemoteHost(), null, null);
            LOG.info(errRes.toString());
            throw new CambriaApiException(errRes);
        }

        int limit = CambriaConstants.kNoLimit;
        if (req.getParameter("limit") != null) {
            limit = Integer.parseInt(req.getParameter("limit"));
        }

        int timeoutMs = CambriaConstants.kNoTimeout;
        String strtimeoutMS = AJSCPropertiesMap.getProperty(CambriaConstants.msgRtr_prop, "timeout");
        if (strtimeoutMS != null)
            timeoutMs = Integer.parseInt(strtimeoutMS);
        //int timeoutMs = ctx.getConfigReader().getSettings().getInt("timeout", CambriaConstants.kNoTimeout);
        if (req.getParameter("timeout") != null) {
            timeoutMs = Integer.parseInt(req.getParameter("timeout"));
        }

        // By default no filter is applied if filter is not passed as a
        // parameter in the request URI
        String topicFilter = CambriaConstants.kNoFilter;
        if (null != req.getParameter("filter")) {
            topicFilter = req.getParameter("filter");
        }
        // pretty to print the messaages in new line
        String prettyval = "0";
        String strPretty = AJSCPropertiesMap.getProperty(CambriaConstants.msgRtr_prop, "pretty");
        if (null != strPretty)
            prettyval = strPretty;

        String metaval = "0";
        String strmeta = AJSCPropertiesMap.getProperty(CambriaConstants.msgRtr_prop, "meta");
        if (null != strmeta)
            metaval = strmeta;

        final boolean pretty = rrConvertor.convertToBooleanBroad(prettyval);
        // withMeta to print offset along with message
        final boolean withMeta = rrConvertor.convertToBooleanBroad(metaval);

        /*final boolean pretty = rrConvertor
        .convertToBooleanBroad(ctx.getConfigReader().getSettings().getString("pretty", "0"));
        // withMeta to print offset along with message
        final boolean withMeta = rrConvertor
        .convertToBooleanBroad(ctx.getConfigReader().getSettings().getString("meta", "0"));
        */
        final LogWrap logger = new LogWrap(topic, consumerGroup, clientId);
        logger.info("fetch: timeout=" + timeoutMs + ", limit=" + limit + ", filter=" + topicFilter);

        // is this user allowed to read this topic?
        final NsaApiKey user = DMaaPAuthenticatorImpl.getAuthenticatedUser(ctx);
        final Topic metatopic = ctx.getConfigReader().getfMetaBroker().getTopic(topic);

        if (metatopic == null) {
            // no such topic.
            ErrorResponse errRes = new ErrorResponse(HttpStatus.SC_NOT_FOUND,
                    DMaaPResponseCode.RESOURCE_NOT_FOUND.getResponseCode(),
                    errorMessages.getTopicNotExist() + "-[" + topic + "]", null, Utils.getFormattedDate(new Date()),
                    topic, null, null, clientId, ctx.getRequest().getRemoteHost());
            LOG.info(errRes.toString());
            throw new CambriaApiException(errRes);
        }
        String metricTopicname = com.att.ajsc.filemonitor.AJSCPropertiesMap
                .getProperty(CambriaConstants.msgRtr_prop, "metrics.send.cambria.topic");
        if (null == metricTopicname)
            metricTopicname = "msgrtr.apinode.metrics.dmaap";

        if (null == ctx.getRequest().getHeader("Authorization") && !topic.equalsIgnoreCase(metricTopicname)) {
            if (null != metatopic.getOwner() && !("".equals(metatopic.getOwner()))) {
                // check permissions
                metatopic.checkUserRead(user);
            }
        }
        // if headers are not provided then user will be null
        if (user == null && null != ctx.getRequest().getHeader("Authorization")) {
            // the topic name will be sent by the client
            //         String permission = "com.att.dmaap.mr.topic"+"|"+topic+"|"+"sub";
            DMaaPAAFAuthenticator aaf = new DMaaPAAFAuthenticatorImpl();
            String permission = aaf.aafPermissionString(topic, "sub");
            if (!aaf.aafAuthentication(ctx.getRequest(), permission)) {
                ErrorResponse errRes = new ErrorResponse(HttpStatus.SC_UNAUTHORIZED,
                        DMaaPResponseCode.ACCESS_NOT_PERMITTED.getResponseCode(),
                        errorMessages.getNotPermitted1() + " read " + errorMessages.getNotPermitted2() + topic,
                        null, Utils.getFormattedDate(new Date()), topic, null, null, clientId,
                        ctx.getRequest().getRemoteHost());
                LOG.info(errRes.toString());
                throw new DMaaPAccessDeniedException(errRes);

            }
            isAAFTopic = true;
        }
        Consumer c = null;
        try {
            final MetricsSet metricsSet = ctx.getConfigReader().getfMetrics();

            final DMaaPCambriaLimiter rl = ctx.getConfigReader().getfRateLimiter();
            rl.onCall(topic, consumerGroup, clientId);

            c = ctx.getConfigReader().getfConsumerFactory().getConsumerFor(topic, consumerGroup, clientId,
                    timeoutMs);

            /*   final CambriaOutboundEventStream coes = new CambriaOutboundEventStream.Builder(c,
                     ctx.getConfigReader().getSettings()).timeout(timeoutMs).limit(limit).filter(topicFilter)
                 .pretty(pretty).withMeta(withMeta)
                 // .atOffset(topicOffset)
                 .build();*/
            final CambriaOutboundEventStream coes = new CambriaOutboundEventStream.Builder(c).timeout(timeoutMs)
                    .limit(limit).filter(topicFilter).pretty(pretty).withMeta(withMeta).build();
            coes.setDmaapContext(ctx);
            coes.setTopic(metatopic);
            if (isTransEnabled() || isAAFTopic) {
                coes.setTransEnabled(true);
            } else {
                coes.setTransEnabled(false);
            }
            coes.setTopicStyle(isAAFTopic);

            DMaaPResponseBuilder.setNoCacheHeadings(ctx);

            DMaaPResponseBuilder.respondOkWithStream(ctx, MediaType.APPLICATION_JSON, coes);

            // No IOException thrown during respondOkWithStream, so commit the
            // new offsets to all the brokers
            c.commitOffsets();
            final int sent = coes.getSentCount();

            metricsSet.consumeTick(sent);
            rl.onSend(topic, consumerGroup, clientId, sent);

            final long elapsedMs = System.currentTimeMillis() - startTime;
            logger.info("Sent " + sent + " msgs in " + elapsedMs + " ms; committed to offset " + c.getOffset());

        } catch (UnavailableException excp) {
            logger.warn(excp.getMessage(), excp);

            ErrorResponse errRes = new ErrorResponse(HttpStatus.SC_SERVICE_UNAVAILABLE,
                    DMaaPResponseCode.SERVER_UNAVAILABLE.getResponseCode(),
                    errorMessages.getServerUnav() + excp.getMessage(), null, Utils.getFormattedDate(new Date()),
                    topic, null, null, clientId, ctx.getRequest().getRemoteHost());
            LOG.info(errRes.toString());
            throw new CambriaApiException(errRes);

        } catch (CambriaApiException excp) {
            logger.warn(excp.getMessage(), excp);
            throw excp;
        } catch (Exception excp) {
            logger.warn("Couldn't respond to client, closing cambria consumer", excp);
            ctx.getConfigReader().getfConsumerFactory().destroyConsumer(topic, consumerGroup, clientId);

            ErrorResponse errRes = new ErrorResponse(HttpStatus.SC_SERVICE_UNAVAILABLE,
                    DMaaPResponseCode.SERVER_UNAVAILABLE.getResponseCode(),
                    "Couldn't respond to client, closing cambria consumer" + excp.getMessage(), null,
                    Utils.getFormattedDate(new Date()), topic, null, null, clientId,
                    ctx.getRequest().getRemoteHost());
            LOG.info(errRes.toString());
            throw new CambriaApiException(errRes);
        } finally {
            // If no cache, close the consumer now that we're done with it.
            boolean kSetting_EnableCache = ConsumerFactory.kDefault_IsCacheEnabled;
            String strkSetting_EnableCache = AJSCPropertiesMap.getProperty(CambriaConstants.msgRtr_prop,
                    ConsumerFactory.kSetting_EnableCache);
            if (null != strkSetting_EnableCache)
                kSetting_EnableCache = Boolean.parseBoolean(strkSetting_EnableCache);
            //if (!ctx.getConfigReader().getSettings().getBoolean(ConsumerFactory.kSetting_EnableCache,   ConsumerFactory.kDefault_IsCacheEnabled) && (c != null)) {
            if (!kSetting_EnableCache && (c != null)) {
                c.close();

            }
        }
    }

    /**
     * @throws missingReqdSetting 
     * 
     */
    @Override
    public void pushEvents(DMaaPContext ctx, final String topic, InputStream msg, final String defaultPartition,
            final String requestTime) throws ConfigDbException, AccessDeniedException, TopicExistsException,
            CambriaApiException, IOException, missingReqdSetting, DMaaPAccessDeniedException {

        // is this user allowed to write to this topic?
        final NsaApiKey user = DMaaPAuthenticatorImpl.getAuthenticatedUser(ctx);
        final Topic metatopic = ctx.getConfigReader().getfMetaBroker().getTopic(topic);
        boolean isAAFTopic = false;

        // was this host blacklisted?
        final String remoteAddr = Utils.getRemoteAddress(ctx);

        if (ctx.getConfigReader().getfIpBlackList().contains(remoteAddr)) {

            ErrorResponse errRes = new ErrorResponse(HttpStatus.SC_FORBIDDEN,
                    DMaaPResponseCode.ACCESS_NOT_PERMITTED.getResponseCode(),
                    "Source address [" + remoteAddr
                            + "] is blacklisted. Please contact the cluster management team.",
                    null, Utils.getFormattedDate(new Date()), topic, Utils.getUserApiKey(ctx.getRequest()),
                    ctx.getRequest().getRemoteHost(), null, null);
            LOG.info(errRes.toString());
            throw new CambriaApiException(errRes);
        }

        String topicNameStd = null;

        //   topicNameStd= ctx.getConfigReader().getSettings().getString("enforced.topic.name.AAF");
        topicNameStd = com.att.ajsc.beans.PropertiesMapBean.getProperty(CambriaConstants.msgRtr_prop,
                "enforced.topic.name.AAF");
        String metricTopicname = com.att.ajsc.filemonitor.AJSCPropertiesMap
                .getProperty(CambriaConstants.msgRtr_prop, "metrics.send.cambria.topic");
        if (null == metricTopicname)
            metricTopicname = "msgrtr.apinode.metrics.dmaap";
        boolean topicNameEnforced = false;
        if (null != topicNameStd && topic.startsWith(topicNameStd)) {
            topicNameEnforced = true;
        }

        //Here check if the user has rights to publish on the topic
        //( This will be called when no auth is added or when UEB API Key Authentication is used)
        //checkUserWrite(user) method will throw an error when there is no Auth header added or when the
        //user has no publish rights

        if (null != metatopic && null != metatopic.getOwner() && !("".equals(metatopic.getOwner()))
                && null == ctx.getRequest().getHeader("Authorization")
                && !topic.equalsIgnoreCase(metricTopicname)) {
            metatopic.checkUserWrite(user);
        }

        // if headers are not provided then user will be null
        if (topicNameEnforced || (user == null && null != ctx.getRequest().getHeader("Authorization")
                && !topic.equalsIgnoreCase(metricTopicname))) {
            // the topic name will be sent by the client
            // String permission = "com.att.dmaap.mr.topic"+"|"+topic+"|"+"pub";
            DMaaPAAFAuthenticator aaf = new DMaaPAAFAuthenticatorImpl();
            String permission = aaf.aafPermissionString(topic, "pub");
            if (!aaf.aafAuthentication(ctx.getRequest(), permission)) {
                ErrorResponse errRes = new ErrorResponse(HttpStatus.SC_UNAUTHORIZED,
                        DMaaPResponseCode.ACCESS_NOT_PERMITTED.getResponseCode(),
                        errorMessages.getNotPermitted1() + " publish " + errorMessages.getNotPermitted2() + topic,
                        null, Utils.getFormattedDate(new Date()), topic, Utils.getUserApiKey(ctx.getRequest()),
                        ctx.getRequest().getRemoteHost(), null, null);
                LOG.info(errRes.toString());
                throw new DMaaPAccessDeniedException(errRes);
            }
            isAAFTopic = true;
        }

        final HttpServletRequest req = ctx.getRequest();

        // check for chunked input
        boolean chunked = false;
        if (null != req.getHeader(TRANSFER_ENCODING)) {
            chunked = req.getHeader(TRANSFER_ENCODING).contains("chunked");
        }
        // get the media type, or set it to a generic value if it wasn't
        // provided
        String mediaType = req.getContentType();
        if (mediaType == null || mediaType.length() == 0) {
            mediaType = MimeTypes.kAppGenericBinary;
        }

        if (mediaType.contains("charset=UTF-8")) {
            mediaType = mediaType.replace("; charset=UTF-8", "").trim();
        }

        String istransidUEBtopicreqd = AJSCPropertiesMap.getProperty(CambriaConstants.msgRtr_prop,
                "transidUEBtopicreqd");
        boolean istransidreqd = false;
        if (null != istransidUEBtopicreqd && istransidUEBtopicreqd.equalsIgnoreCase("true")) {
            istransidreqd = true;
        }

        if (isAAFTopic || istransidreqd) {
            pushEventsWithTransaction(ctx, msg, topic, defaultPartition, requestTime, chunked, mediaType);
        } else {
            pushEvents(ctx, topic, msg, defaultPartition, chunked, mediaType);
        }

    }

    /**
     * 
     * @param ctx
     * @param topic
     * @param msg
     * @param defaultPartition
     * @param chunked
     * @param mediaType
     * @throws ConfigDbException
     * @throws AccessDeniedException
     * @throws TopicExistsException
     * @throws CambriaApiException
     * @throws IOException
     */
    private void pushEvents(DMaaPContext ctx, String topic, InputStream msg, String defaultPartition,
            boolean chunked, String mediaType) throws ConfigDbException, AccessDeniedException,
            TopicExistsException, CambriaApiException, IOException {
        final MetricsSet metricsSet = ctx.getConfigReader().getfMetrics();

        // setup the event set
        final CambriaEventSet events = new CambriaEventSet(mediaType, msg, chunked, defaultPartition);

        // start processing, building a batch to push to the backend
        final long startMs = System.currentTimeMillis();
        long count = 0;

        long maxEventBatch = 1024 * 16;
        String batchlen = AJSCPropertiesMap.getProperty(CambriaConstants.msgRtr_prop, BATCH_LENGTH);
        if (null != batchlen)
            maxEventBatch = Long.parseLong(batchlen);

        // long maxEventBatch = ctx.getConfigReader().getSettings().getLong(BATCH_LENGTH, 1024 * 16);
        final LinkedList<Publisher.message> batch = new LinkedList<Publisher.message>();
        final ArrayList<KeyedMessage<String, String>> kms = new ArrayList<KeyedMessage<String, String>>();

        try {
            // for each message...
            Publisher.message m = null;
            while ((m = events.next()) != null) {
                // add the message to the batch
                batch.add(m);
                final KeyedMessage<String, String> data = new KeyedMessage<String, String>(topic, m.getKey(),
                        m.getMessage());
                kms.add(data);
                // check if the batch is full
                final int sizeNow = batch.size();
                if (sizeNow > maxEventBatch) {
                    ctx.getConfigReader().getfPublisher().sendBatchMessage(topic, kms);
                    kms.clear();
                    batch.clear();
                    metricsSet.publishTick(sizeNow);
                    count += sizeNow;
                }
            }

            // send the pending batch
            final int sizeNow = batch.size();
            if (sizeNow > 0) {
                ctx.getConfigReader().getfPublisher().sendBatchMessage(topic, kms);
                kms.clear();
                batch.clear();
                metricsSet.publishTick(sizeNow);
                count += sizeNow;
            }

            final long endMs = System.currentTimeMillis();
            final long totalMs = endMs - startMs;

            LOG.info("Published " + count + " msgs in " + totalMs + "ms for topic " + topic);

            // build a responseP
            final JSONObject response = new JSONObject();
            response.put("count", count);
            response.put("serverTimeMs", totalMs);
            DMaaPResponseBuilder.respondOk(ctx, response);

        } catch (Exception excp) {
            int status = HttpStatus.SC_NOT_FOUND;
            String errorMsg = null;
            if (excp instanceof CambriaApiException) {
                status = ((CambriaApiException) excp).getStatus();
                JSONTokener jsonTokener = new JSONTokener(((CambriaApiException) excp).getBody());
                JSONObject errObject = new JSONObject(jsonTokener);
                errorMsg = (String) errObject.get("message");

            }
            ErrorResponse errRes = new ErrorResponse(status,
                    DMaaPResponseCode.PARTIAL_PUBLISH_MSGS.getResponseCode(),
                    errorMessages.getPublishMsgError() + ":" + topic + "." + errorMessages.getPublishMsgCount()
                            + count + "." + errorMsg,
                    null, Utils.getFormattedDate(new Date()), topic, null, ctx.getRequest().getRemoteHost(), null,
                    null);
            LOG.info(errRes.toString());
            throw new CambriaApiException(errRes);

        }
    }

    /**
     * 
     * @param ctx
     * @param inputStream
     * @param topic
     * @param partitionKey
     * @param requestTime
     * @param chunked
     * @param mediaType
     * @throws ConfigDbException
     * @throws AccessDeniedException
     * @throws TopicExistsException
     * @throws IOException
     * @throws CambriaApiException
     */
    private void pushEventsWithTransaction(DMaaPContext ctx, InputStream inputStream, final String topic,
            final String partitionKey, final String requestTime, final boolean chunked, final String mediaType)
            throws ConfigDbException, AccessDeniedException, TopicExistsException, IOException,
            CambriaApiException {

        final MetricsSet metricsSet = ctx.getConfigReader().getfMetrics();

        // setup the event set
        final CambriaEventSet events = new CambriaEventSet(mediaType, inputStream, chunked, partitionKey);

        // start processing, building a batch to push to the backend
        final long startMs = System.currentTimeMillis();
        long count = 0;
        long maxEventBatch = 1024 * 16;
        String evenlen = AJSCPropertiesMap.getProperty(CambriaConstants.msgRtr_prop, BATCH_LENGTH);
        if (null != evenlen)
            maxEventBatch = Long.parseLong(evenlen);
        //final long maxEventBatch = ctx.getConfigReader().getSettings().getLong(BATCH_LENGTH, 1024 * 16);
        final LinkedList<Publisher.message> batch = new LinkedList<Publisher.message>();
        final ArrayList<KeyedMessage<String, String>> kms = new ArrayList<KeyedMessage<String, String>>();

        Publisher.message m = null;
        int messageSequence = 1;
        Long batchId = 1L;
        final boolean transactionEnabled = true;
        int publishBatchCount = 0;
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss.SS");

        //LOG.warn("Batch Start Id: " + Utils.getFromattedBatchSequenceId(batchId));
        try {
            // for each message...
            batchId = DMaaPContext.getBatchID();

            String responseTransactionId = null;

            while ((m = events.next()) != null) {

                //LOG.warn("Batch Start Id: " + Utils.getFromattedBatchSequenceId(batchId));

                addTransactionDetailsToMessage(m, topic, ctx.getRequest(), requestTime, messageSequence, batchId,
                        transactionEnabled);
                messageSequence++;

                // add the message to the batch
                batch.add(m);

                responseTransactionId = m.getLogDetails().getTransactionId();

                JSONObject jsonObject = new JSONObject();
                jsonObject.put("message", m.getMessage());
                jsonObject.put("transactionId", responseTransactionId);
                final KeyedMessage<String, String> data = new KeyedMessage<String, String>(topic, m.getKey(),
                        jsonObject.toString());
                kms.add(data);

                // check if the batch is full
                final int sizeNow = batch.size();
                if (sizeNow >= maxEventBatch) {
                    String startTime = sdf.format(new Date());
                    LOG.info("Batch Start Details:[serverIp=" + ctx.getRequest().getLocalAddr() + ",Batch Start Id="
                            + batchId + "]");
                    try {
                        ctx.getConfigReader().getfPublisher().sendBatchMessage(topic, kms);
                        //transactionLogs(batch);
                        for (message msg : batch) {
                            LogDetails logDetails = msg.getLogDetails();
                            LOG.info("Publisher Log Details : " + logDetails.getPublisherLogDetails());
                        }
                    } catch (Exception excp) {

                        int status = HttpStatus.SC_NOT_FOUND;
                        String errorMsg = null;
                        if (excp instanceof CambriaApiException) {
                            status = ((CambriaApiException) excp).getStatus();
                            JSONTokener jsonTokener = new JSONTokener(((CambriaApiException) excp).getBody());
                            JSONObject errObject = new JSONObject(jsonTokener);
                            errorMsg = (String) errObject.get("message");
                        }
                        ErrorResponse errRes = new ErrorResponse(status,
                                DMaaPResponseCode.PARTIAL_PUBLISH_MSGS.getResponseCode(),
                                "Transaction-" + errorMessages.getPublishMsgError() + ":" + topic + "."
                                        + errorMessages.getPublishMsgCount() + count + "." + errorMsg,
                                null, Utils.getFormattedDate(new Date()), topic,
                                Utils.getUserApiKey(ctx.getRequest()), ctx.getRequest().getRemoteHost(), null,
                                null);
                        LOG.info(errRes.toString());
                        throw new CambriaApiException(errRes);
                    }
                    kms.clear();
                    batch.clear();
                    metricsSet.publishTick(sizeNow);
                    publishBatchCount = sizeNow;
                    count += sizeNow;
                    //batchId++;
                    String endTime = sdf.format(new Date());
                    LOG.info("Batch End Details:[serverIp=" + ctx.getRequest().getLocalAddr() + ",Batch End Id="
                            + batchId + ",Batch Total=" + publishBatchCount + ",Batch Start Time=" + startTime
                            + ",Batch End Time=" + endTime + "]");
                    batchId = DMaaPContext.getBatchID();
                }
            }

            // send the pending batch
            final int sizeNow = batch.size();
            if (sizeNow > 0) {
                String startTime = sdf.format(new Date());
                LOG.info("Batch Start Details:[serverIp=" + ctx.getRequest().getLocalAddr() + ",Batch Start Id="
                        + batchId + "]");
                try {
                    ctx.getConfigReader().getfPublisher().sendBatchMessage(topic, kms);
                    //transactionLogs(batch);
                    for (message msg : batch) {
                        LogDetails logDetails = msg.getLogDetails();
                        LOG.info("Publisher Log Details : " + logDetails.getPublisherLogDetails());
                    }
                } catch (Exception excp) {
                    int status = HttpStatus.SC_NOT_FOUND;
                    String errorMsg = null;
                    if (excp instanceof CambriaApiException) {
                        status = ((CambriaApiException) excp).getStatus();
                        JSONTokener jsonTokener = new JSONTokener(((CambriaApiException) excp).getBody());
                        JSONObject errObject = new JSONObject(jsonTokener);
                        errorMsg = (String) errObject.get("message");
                    }

                    ErrorResponse errRes = new ErrorResponse(status,
                            DMaaPResponseCode.PARTIAL_PUBLISH_MSGS.getResponseCode(),
                            "Transaction-" + errorMessages.getPublishMsgError() + ":" + topic + "."
                                    + errorMessages.getPublishMsgCount() + count + "." + errorMsg,
                            null, Utils.getFormattedDate(new Date()), topic, Utils.getUserApiKey(ctx.getRequest()),
                            ctx.getRequest().getRemoteHost(), null, null);
                    LOG.info(errRes.toString());
                    throw new CambriaApiException(errRes);
                }
                kms.clear();
                metricsSet.publishTick(sizeNow);
                count += sizeNow;
                //batchId++;
                String endTime = sdf.format(new Date());
                publishBatchCount = sizeNow;
                LOG.info("Batch End Details:[serverIp=" + ctx.getRequest().getLocalAddr() + ",Batch End Id="
                        + batchId + ",Batch Total=" + publishBatchCount + ",Batch Start Time=" + startTime
                        + ",Batch End Time=" + endTime + "]");
            }

            final long endMs = System.currentTimeMillis();
            final long totalMs = endMs - startMs;

            LOG.info("Published " + count + " msgs in " + totalMs + "ms for topic " + topic);

            if (null != responseTransactionId) {
                ctx.getResponse().setHeader("transactionId", Utils.getResponseTransactionId(responseTransactionId));
            }

            // build a response
            final JSONObject response = new JSONObject();
            response.put("count", count);
            response.put("serverTimeMs", totalMs);
            DMaaPResponseBuilder.respondOk(ctx, response);

        } catch (Exception excp) {
            int status = HttpStatus.SC_NOT_FOUND;
            String errorMsg = null;
            if (excp instanceof CambriaApiException) {
                status = ((CambriaApiException) excp).getStatus();
                JSONTokener jsonTokener = new JSONTokener(((CambriaApiException) excp).getBody());
                JSONObject errObject = new JSONObject(jsonTokener);
                errorMsg = (String) errObject.get("message");
            }

            ErrorResponse errRes = new ErrorResponse(status,
                    DMaaPResponseCode.PARTIAL_PUBLISH_MSGS.getResponseCode(),
                    "Transaction-" + errorMessages.getPublishMsgError() + ":" + topic + "."
                            + errorMessages.getPublishMsgCount() + count + "." + errorMsg,
                    null, Utils.getFormattedDate(new Date()), topic, Utils.getUserApiKey(ctx.getRequest()),
                    ctx.getRequest().getRemoteHost(), null, null);
            LOG.info(errRes.toString());
            throw new CambriaApiException(errRes);
        }
    }

    /**
     * 
     * @param msg
     * @param topic
     * @param request
     * @param messageCreationTime
     * @param messageSequence
     * @param batchId
     * @param transactionEnabled
     */
    private static void addTransactionDetailsToMessage(message msg, final String topic, HttpServletRequest request,
            final String messageCreationTime, final int messageSequence, final Long batchId,
            final boolean transactionEnabled) {
        LogDetails logDetails = generateLogDetails(topic, request, messageCreationTime, messageSequence, batchId,
                transactionEnabled);
        logDetails.setMessageLengthInBytes(Utils.messageLengthInBytes(msg.getMessage()));
        msg.setTransactionEnabled(transactionEnabled);
        msg.setLogDetails(logDetails);
    }

    /**
     * 
     * @author author
     *
     */
    private static class LogWrap {
        private final String fId;

        /**
         * constructor initialization
         * 
         * @param topic
         * @param cgroup
         * @param cid
         */
        public LogWrap(String topic, String cgroup, String cid) {
            fId = "[" + topic + "/" + cgroup + "/" + cid + "] ";
        }

        /**
         * 
         * @param msg
         */
        public void info(String msg) {
            LOG.info(fId + msg);
        }

        /**
         * 
         * @param msg
         * @param t
         */
        public void warn(String msg, Exception t) {
            LOG.warn(fId + msg, t);
        }

    }

    private boolean isTransEnabled() {
        String istransidUEBtopicreqd = AJSCPropertiesMap.getProperty(CambriaConstants.msgRtr_prop,
                "transidUEBtopicreqd");
        boolean istransidreqd = false;
        if ((null != istransidUEBtopicreqd && istransidUEBtopicreqd.equalsIgnoreCase("true"))) {
            istransidreqd = true;
        }

        return istransidreqd;

    }

    private static LogDetails generateLogDetails(final String topicName, HttpServletRequest request,
            final String messageTimestamp, int messageSequence, Long batchId, final boolean transactionEnabled) {
        LogDetails logDetails = new LogDetails();
        logDetails.setTopicId(topicName);
        logDetails.setMessageTimestamp(messageTimestamp);
        logDetails.setPublisherId(Utils.getUserApiKey(request));
        logDetails.setPublisherIp(request.getRemoteHost());
        logDetails.setMessageBatchId(batchId);
        logDetails.setMessageSequence(String.valueOf(messageSequence));
        logDetails.setTransactionEnabled(transactionEnabled);
        logDetails.setTransactionIdTs(Utils.getFormattedDate(new Date()));
        logDetails.setServerIp(request.getLocalAddr());
        return logDetails;
    }

    /*public String getMetricsTopic() {
       return metricsTopic;
    }
        
    public void setMetricsTopic(String metricsTopic) {
       this.metricsTopic = metricsTopic;
    }*/

}