com.magnet.mmx.server.plugin.mmxmgmt.servlet.integration.IntegrationChannelResource.java Source code

Java tutorial

Introduction

Here is the source code for com.magnet.mmx.server.plugin.mmxmgmt.servlet.integration.IntegrationChannelResource.java

Source

/*   Copyright (c) 2015 Magnet Systems, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.magnet.mmx.server.plugin.mmxmgmt.servlet.integration;

import com.google.common.base.Function;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.magnet.mmx.protocol.*;
import com.magnet.mmx.protocol.ChannelInfo;
import com.magnet.mmx.sasl.TokenInfo;
import com.magnet.mmx.server.api.v1.RestUtils;
import com.magnet.mmx.server.api.v1.protocol.*;
import com.magnet.mmx.server.api.v2.ChannelResource;
import com.magnet.mmx.server.common.data.AppEntity;
import com.magnet.mmx.server.plugin.mmxmgmt.MMXException;
import com.magnet.mmx.server.plugin.mmxmgmt.api.*;
import com.magnet.mmx.server.plugin.mmxmgmt.db.*;
import com.magnet.mmx.server.plugin.mmxmgmt.handler.MMXChannelManager;
import com.magnet.mmx.server.plugin.mmxmgmt.message.*;
import com.magnet.mmx.server.plugin.mmxmgmt.pubsub.PubSubPersistenceManagerExt;
import com.magnet.mmx.server.plugin.mmxmgmt.servlet.TopicPostResponse;
import com.magnet.mmx.server.plugin.mmxmgmt.topic.TopicPostMessageRequest;
import com.magnet.mmx.server.plugin.mmxmgmt.util.Helper;
import com.magnet.mmx.server.plugin.mmxmgmt.util.JIDUtil;
import com.magnet.mmx.server.plugin.mmxmgmt.util.MMXServerConstants;
import com.magnet.mmx.util.AppChannel;
import com.magnet.mmx.util.ChannelHelper;
import org.apache.commons.lang3.StringUtils;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.pubsub.*;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID;

import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 * Channel admin REST API using auth token.  Accessing this resource must be
 * restricted to MMS or admin user.
 */
@Path("/integration/channels")
public class IntegrationChannelResource {
    private static final Logger LOGGER = LoggerFactory.getLogger(IntegrationChannelResource.class);
    static final String DESCRIPTION_KEY = "description";
    static final String TAGS_KEY = "tag";
    static final String ID_KEY = "id";
    static final String CHANNEL_NAME = "channelName";
    static final String MMX_INTERNAL_SALT = "Z00N13!!";
    private static char[] hexArray = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
            'F' };
    private static int HASH_MIN_KEY_SIZE = 8;
    UserDAO userDAO = new UserDAOImpl(new OpenFireDBConnectionProvider());
    AppDAO appDAO = new AppDAOImpl(new OpenFireDBConnectionProvider());

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/create")
    public Response createChannel(@Context HttpHeaders headers, CreateChannelRequest channelInfo) {

        ErrorResponse errorResponse = null;
        CreateChannelResponse chatChannelResponse = null;

        if (channelInfo == null) {
            chatChannelResponse = new CreateChannelResponse(ErrorCode.ILLEGAL_ARGUMENT.getCode(),
                    "Channel information not set");
            return RestUtils.getOKJAXRSResp(chatChannelResponse);
        }

        if (!ChannelHelper.validateApplicationChannelName(channelInfo.getChannelName())) {
            chatChannelResponse = new CreateChannelResponse(ErrorCode.ILLEGAL_ARGUMENT.getCode(),
                    MMXChannelManager.StatusCode.INVALID_CHANNEL_NAME.getMessage());
            return RestUtils.getOKJAXRSResp(chatChannelResponse);
        }

        if (!Strings.isNullOrEmpty(channelInfo.getDescription())
                && channelInfo.getDescription().length() > MMXServerConstants.MAX_TOPIC_DESCRIPTION_LEN) {

            chatChannelResponse = new CreateChannelResponse(ErrorCode.ILLEGAL_ARGUMENT.getCode(),
                    "channel description too long, max length = " + MMXServerConstants.MAX_TOPIC_DESCRIPTION_LEN);

            return RestUtils.getOKJAXRSResp(chatChannelResponse);
        }

        // Attempt to create or Fetch Channel
        String channelName = channelInfo.getChannelName();

        MMXChannelManager channelManager = MMXChannelManager.getInstance();
        channelInfo.setChannelName(channelName);
        channelInfo.setPrivateChannel(channelInfo.isPrivateChannel());
        JID from = RestUtils.createJID(channelInfo.getUserId(), channelInfo.getMmxAppId(),
                channelInfo.getDeviceId());
        try {
            ChannelAction.CreateRequest rqt = toCreateRequest(channelInfo);
            channelManager.createChannel(from, channelInfo.getMmxAppId(), rqt);

        } catch (MMXException e) {
            if (e.getCode() == StatusCode.CONFLICT) {
                errorResponse = new ErrorResponse(ErrorCode.TOPIC_EXISTS, "Channel already exists");
            } else if (e.getCode() == StatusCode.FORBIDDEN) {
                errorResponse = new ErrorResponse(ErrorCode.ILLEGAL_ARGUMENT, e.getMessage());
            } else if (e.getCode() == StatusCode.BAD_REQUEST) {
                errorResponse = new ErrorResponse(ErrorCode.ILLEGAL_ARGUMENT, e.getMessage());
            } else {
                errorResponse = new ErrorResponse(ErrorCode.UNKNOWN_ERROR, e.getMessage());
            }

            chatChannelResponse = new CreateChannelResponse(errorResponse.getCode(), errorResponse.getMessage());
            return RestUtils.getOKJAXRSResp(chatChannelResponse);

        } catch (Throwable e) {

            chatChannelResponse = new CreateChannelResponse(ErrorCode.UNKNOWN_ERROR.getCode(), e.getMessage());
            return RestUtils.getOKJAXRSResp(chatChannelResponse);

        }

        // auto subscribe recipients to this channel
        Map<String, ChannelAction.SubscribeResponse> subResponseMap = new HashMap<String, ChannelAction.SubscribeResponse>();

        try {
            //MMXChannelId channelId = nameToId(channelName);
            MMXChannelId channelId;
            if (channelInfo.isPrivateChannel()) {
                channelId = new MMXChannelId(channelInfo.getUserId(), channelInfo.getChannelName());
            } else {
                channelId = new MMXChannelId(channelInfo.getChannelName());
            }
            //ChannelInfo foundChannel =  channelManager.getChannel(channelInfo.getMmxAppId(),channelId );
            //errorResponse = new ErrorResponse(ErrorCode.NO_ERROR, "Send Message to Chat Success");

            ChannelAction.SubscribeRequest rqt = new ChannelAction.SubscribeRequest(channelId.getEscUserId(),
                    channelId.getName(), null);
            ChannelAction.SubscribeResponse resp = null;
            if (channelInfo.getSubscribers() != null) {
                for (String subscriber : channelInfo.getSubscribers()) {
                    JID sub = new JID(JIDUtil.makeNode(subscriber, channelInfo.getMmxAppId()), from.getDomain(),
                            null);
                    resp = channelManager.subscribeChannel(sub, channelInfo.getMmxAppId(), rqt,
                            Arrays.asList(MMXServerConstants.TOPIC_ROLE_PUBLIC));
                    if (resp.getCode() == 200) {
                        subResponseMap.put(subscriber,
                                new ChannelAction.SubscribeResponse(resp.getSubId(), 0, resp.getSubId()));
                    } else {
                        subResponseMap.put(subscriber, resp);
                    }

                }
            }

        } catch (MMXException e) {
            LOGGER.error("Exception during createChannel request", e);
            chatChannelResponse = new CreateChannelResponse(ErrorCode.UNKNOWN_ERROR.getCode(), e.getMessage());
            chatChannelResponse.setSubscribeResponse(subResponseMap);

            return RestUtils.getCreatedJAXRSResp(chatChannelResponse);

        }

        chatChannelResponse = new CreateChannelResponse(ErrorCode.NO_ERROR.getCode(), "Channel created");
        chatChannelResponse.setSubscribeResponse(subResponseMap);

        return RestUtils.getCreatedJAXRSResp(chatChannelResponse);

    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/subscribers/add")
    public Response addSubscribersToChannel(@Context HttpHeaders headers, CreateChannelRequest channelInfo) {

        ErrorResponse errorResponse = null;
        CreateChannelResponse chatChannelResponse = null;

        MMXChannelManager channelManager = MMXChannelManager.getInstance();
        JID from = RestUtils.createJID(channelInfo.getUserId(), channelInfo.getMmxAppId(),
                channelInfo.getDeviceId());

        MMXChannelId tid = null;
        if (channelInfo.isPrivateChannel()) {
            tid = new MMXChannelId(channelInfo.getUserId(), channelInfo.getChannelName());
        } else {
            tid = new MMXChannelId(channelInfo.getChannelName());
        }

        try {
            com.magnet.mmx.protocol.ChannelInfo info = channelManager.getChannel(from, channelInfo.getMmxAppId(),
                    tid);

            if (info.isUserChannel()) {
                if (!JIDUtil.getReadableUserId(info.getCreator()).equals(channelInfo.getUserId())) {
                    errorResponse = new ErrorResponse(ErrorCode.TOPIC_NOT_OWNER,
                            "Channel doesn't belong to this user: " + channelInfo.getChannelName());
                    return RestUtils.getJAXRSResp(Response.Status.OK, errorResponse);
                }
            } else {
                //Validate the subscriber
                String channelId = ChannelHelper.makeChannel(channelInfo.getMmxAppId(), info.getEscUserId(),
                        info.getName());
                List<NodeSubscription> subscriptions = channelManager.listSubscriptionsForChannel(channelId);

                boolean isSubscribedUser = false;
                for (NodeSubscription subscription : subscriptions) {
                    if (subscription.getJID().equals(from)) {
                        isSubscribedUser = true;
                    }
                }
                if (!isSubscribedUser) {
                    errorResponse = new ErrorResponse(ErrorCode.TOPIC_NOT_SUBSCRIBED,
                            "User doesn't subscribed to this channel: " + channelInfo.getChannelName());
                    return RestUtils.getJAXRSResp(Response.Status.OK, errorResponse);
                }

            }

        } catch (MMXException e) {
            ErrorResponse response;
            if (e.getCode() == StatusCode.NOT_FOUND) {
                response = new ErrorResponse(ErrorCode.TOPIC_NOT_EXIST.getCode(),
                        "Channel not found: " + channelInfo.getChannelName());
                return RestUtils.getJAXRSResp(Response.Status.OK, response);
            } else {
                response = new ErrorResponse(ErrorCode.UNKNOWN_ERROR.getCode(), e.getMessage());
                return RestUtils.getInternalErrorJAXRSResp(response);
            }
        }

        // auto subscribe recipients to this channel
        Map<String, ChannelAction.SubscribeResponse> subResponseMap = new HashMap<String, ChannelAction.SubscribeResponse>();

        try {
            //MMXChannelId channelId = nameToId(channelName);
            MMXChannelId channelId;
            if (channelInfo.isPrivateChannel()) {
                channelId = new MMXChannelId(channelInfo.getUserId(), channelInfo.getChannelName());
            } else {
                channelId = new MMXChannelId(channelInfo.getChannelName());
            }

            ChannelAction.SubscribeRequest rqt = new ChannelAction.SubscribeRequest(channelId.getEscUserId(),
                    channelId.getName(), null);
            ChannelAction.SubscribeResponse resp = null;
            if (channelInfo.getSubscribers() != null) {
                for (String subscriber : channelInfo.getSubscribers()) {

                    //Validate the user
                    if (!isValidUser(channelInfo.getMmxAppId(), subscriber)) {
                        subResponseMap.put(subscriber, new ChannelAction.SubscribeResponse(null,
                                ErrorCode.INVALID_USER_NAME.getCode(), "Invalid User"));
                        continue;
                    }
                    JID sub = new JID(JIDUtil.makeNode(subscriber, channelInfo.getMmxAppId()), from.getDomain(),
                            null);
                    resp = channelManager.subscribeChannel(sub, channelInfo.getMmxAppId(), rqt,
                            Arrays.asList(MMXServerConstants.TOPIC_ROLE_PUBLIC));

                    if (resp.getCode() == 200) {
                        subResponseMap.put(subscriber,
                                new ChannelAction.SubscribeResponse(resp.getSubId(), 0, resp.getSubId()));
                    } else {
                        subResponseMap.put(subscriber, resp);
                    }
                }
            }

        } catch (MMXException e) {
            LOGGER.error("Exception during addSubscribersToChannel request", e);
            chatChannelResponse = new CreateChannelResponse(ErrorCode.UNKNOWN_ERROR.getCode(), e.getMessage());
            chatChannelResponse.setSubscribeResponse(subResponseMap);

            return RestUtils.getCreatedJAXRSResp(chatChannelResponse);

        }

        chatChannelResponse = new CreateChannelResponse(ErrorCode.NO_ERROR.getCode(), "Subscribers added");
        chatChannelResponse.setSubscribeResponse(subResponseMap);

        return RestUtils.getCreatedJAXRSResp(chatChannelResponse);

    }

    private boolean isValidUser(String appId, String subscriber) {
        String mmxUsername = Helper.getMMXUsername(subscriber, appId);
        UserEntity userEntity = userDAO.getUser(mmxUsername);
        return (userEntity != null);
    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/subscribers/remove")
    public Response removeSubscribersToChannel(@Context HttpHeaders headers, CreateChannelRequest channelInfo) {

        ErrorResponse errorResponse = null;
        CreateChannelResponse chatChannelResponse = null;

        JID from = RestUtils.createJID(channelInfo.getUserId(), channelInfo.getMmxAppId(),
                channelInfo.getDeviceId());

        MMXChannelId tid = null;
        if (channelInfo.isPrivateChannel()) {
            tid = new MMXChannelId(channelInfo.getUserId(), channelInfo.getChannelName());
        } else {
            tid = new MMXChannelId(channelInfo.getChannelName());
        }

        MMXChannelManager channelManager = MMXChannelManager.getInstance();
        try {
            com.magnet.mmx.protocol.ChannelInfo info = channelManager.getChannel(from, channelInfo.getMmxAppId(),
                    tid);

            if (!JIDUtil.getReadableUserId(info.getCreator()).equals(channelInfo.getUserId())) {
                errorResponse = new ErrorResponse(ErrorCode.TOPIC_NOT_OWNER,
                        "Channel doesn't belong to this user: " + channelInfo.getChannelName());
                return RestUtils.getJAXRSResp(Response.Status.OK, errorResponse);
            }

        } catch (MMXException e) {
            ErrorResponse response;
            if (e.getCode() == StatusCode.NOT_FOUND) {
                response = new ErrorResponse(ErrorCode.TOPIC_NOT_EXIST.getCode(),
                        "Channel not found: " + channelInfo.getChannelName());
                return RestUtils.getJAXRSResp(Response.Status.OK, response);
            } else {
                response = new ErrorResponse(ErrorCode.UNKNOWN_ERROR.getCode(), e.getMessage());
                return RestUtils.getInternalErrorJAXRSResp(response);
            }
        }

        // auto subscribe recipients to this channel
        Map<String, ChannelAction.SubscribeResponse> subResponseMap = new HashMap<String, ChannelAction.SubscribeResponse>();

        try {
            //MMXChannelId channelId = nameToId(channelName);
            MMXChannelId channelId;
            if (channelInfo.isPrivateChannel()) {
                channelId = new MMXChannelId(channelInfo.getUserId(), channelInfo.getChannelName());
            } else {
                channelId = new MMXChannelId(channelInfo.getChannelName());
            }
            //ChannelInfo foundChannel =  channelManager.getChannel(channelInfo.getMmxAppId(),channelId );
            //errorResponse = new ErrorResponse(ErrorCode.NO_ERROR, "Send Message to Chat Success");

            ChannelAction.UnsubscribeRequest rqt = new ChannelAction.UnsubscribeRequest(channelId.getEscUserId(),
                    channelId.getName(), null);
            MMXStatus resp = null;
            if (channelInfo.getSubscribers() != null) {
                for (String subscriber : channelInfo.getSubscribers()) {
                    try {

                        //Validate the user
                        if (!isValidUser(channelInfo.getMmxAppId(), subscriber)) {
                            subResponseMap.put(subscriber, new ChannelAction.SubscribeResponse(null,
                                    ErrorCode.INVALID_USER_NAME.getCode(), "Invalid User"));
                            continue;
                        }

                        JID sub = new JID(JIDUtil.makeNode(subscriber, channelInfo.getMmxAppId()), from.getDomain(),
                                null);
                        resp = channelManager.unsubscribeChannel(sub, channelInfo.getMmxAppId(), rqt);

                        if (resp.getCode() == 200) {
                            subResponseMap.put(subscriber,
                                    new ChannelAction.SubscribeResponse(null, 0, resp.getMessage()));
                        } else {
                            subResponseMap.put(subscriber,
                                    new ChannelAction.SubscribeResponse(null, resp.getCode(), resp.getMessage()));

                        }
                    } catch (Exception ex) {
                        subResponseMap.put(subscriber, new ChannelAction.SubscribeResponse(null,
                                ErrorCode.UNKNOWN_ERROR.getCode(), ex.getMessage()));
                    }

                }
            }

        } catch (Exception e) {
            LOGGER.error("Exception during addSubscribersToChannel request", e);
            chatChannelResponse = new CreateChannelResponse(ErrorCode.UNKNOWN_ERROR.getCode(), e.getMessage());
            chatChannelResponse.setSubscribeResponse(subResponseMap);

            return RestUtils.getCreatedJAXRSResp(chatChannelResponse);

        }

        chatChannelResponse = new CreateChannelResponse(ErrorCode.NO_ERROR.getCode(), "Subscribers removed");
        chatChannelResponse.setSubscribeResponse(subResponseMap);

        return RestUtils.getCreatedJAXRSResp(chatChannelResponse);

    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/query/sql")
    public Response findChannelsUsingSQL(@Context HttpHeaders headers, QueryChannelRequest queryChannelRequest) {

        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        Map<String, Integer> channelCountMap = new HashMap<String, Integer>(3);
        Map<String, Integer> channelSubscriptionMap = new HashMap<String, Integer>(3);
        List<ChannelInfo> channels = new ArrayList<ChannelInfo>(3);
        try {
            con = DbConnectionManager.getConnection();

            StringBuffer userInClause = new StringBuffer();
            for (String user : queryChannelRequest.getSubscribers()) {

                JID from = RestUtils.createJID(user, queryChannelRequest.getMmxAppId(),
                        queryChannelRequest.getDeviceId());
                if (userInClause.length() == 0) {
                    userInClause.append("'").append(from).append("'");
                } else {
                    userInClause.append(",'").append(from).append("'");
                }
            }

            String sql = "SELECT nodeID,count(*) FROM ofPubsubSubscription where state = 'subscribed' AND nodeID "
                    + "like '" + "/" + queryChannelRequest.getMmxAppId() + "%' AND " + "jid in ("
                    + userInClause.toString() + ") group by nodeID";
            pstmt = con.prepareStatement(sql);
            rs = pstmt.executeQuery();

            while (rs.next()) {
                channelCountMap.put(rs.getString(1), rs.getInt(2));
            }

            StringBuffer channelInClause = new StringBuffer();
            for (String node : channelCountMap.keySet()) {
                if (channelInClause.length() == 0) {
                    channelInClause.append("'").append(node).append("'");
                } else {
                    channelInClause.append(",'").append(node).append("'");
                }
            }

            if (channelInClause.length() == 0) {
                QueryChannelResponse response = new QueryChannelResponse(ErrorCode.NO_ERROR.getCode(), "Success");
                response.setChannels(channels);
                return RestUtils.getCreatedJAXRSResp(response);

            }

            String countSql = "SELECT nodeID, count(*) FROM ofPubsubSubscription where state = 'subscribed' AND "
                    + "nodeID in (" + channelInClause + ") group by nodeID";

            pstmt = con.prepareStatement(countSql);
            rs = pstmt.executeQuery();

            while (rs.next()) {
                channelSubscriptionMap.put(rs.getString(1), rs.getInt(2));
            }

            List<String> filteredChannels = new ArrayList<String>(3);

            if (!queryChannelRequest.getMatchFilter().equals(QueryChannelRequest.MatchType.ANY_MATCH)) {
                //Populate the subscription count
                for (String channelName : channelCountMap.keySet()) {

                    int totalSubscriptionCount = channelSubscriptionMap.get(channelName);
                    int matchingSubscriptionCount = channelCountMap.get(channelName);
                    if (queryChannelRequest.getMatchFilter().equals(QueryChannelRequest.MatchType.EXACT_MATCH)) {

                        if (matchingSubscriptionCount == totalSubscriptionCount
                                && matchingSubscriptionCount == queryChannelRequest.getSubscribers().size()) {
                            filteredChannels.add(channelName);
                        }

                    } else if (queryChannelRequest.getMatchFilter()
                            .equals(QueryChannelRequest.MatchType.SUBSET_MATCH)) {
                        if (totalSubscriptionCount >= matchingSubscriptionCount
                                && matchingSubscriptionCount >= queryChannelRequest.getSubscribers().size()) {
                            filteredChannels.add(channelName);
                        }
                    } else {
                        filteredChannels.add(channelName);
                    }

                }
            } else {

                for (String channelName : channelCountMap.keySet()) {
                    filteredChannels.add(channelName);
                }

            }

            if (filteredChannels.size() > 0) {
                //convert from nodeId to name
                StringBuffer nodeIds = new StringBuffer();
                for (String nodeId : filteredChannels) {
                    AppChannel appChannel = ChannelHelper.parseChannel(nodeId);
                    MMXChannelId channelId = getChannelName(appChannel);
                    Node node = MMXChannelManager.getInstance().getChannelNode(queryChannelRequest.getMmxAppId(),
                            channelId);
                    ChannelInfo channelInfo = null;
                    //MMXChannelId tid = ChannelHelper.parseNode(node.getNodeID());
                    if (appChannel.isUserChannel()) {
                        channelInfo = MMXChannelManager.getInstance().nodeToChannelInfo(appChannel.getUserId(),
                                node);
                    } else {
                        channelInfo = MMXChannelManager.getInstance().nodeToChannelInfo(null, node);
                    }
                    channels.add(channelInfo);
                }
            }
            QueryChannelResponse response = new QueryChannelResponse(ErrorCode.NO_ERROR.getCode(), "Success");
            response.setChannels(channels);
            return RestUtils.getCreatedJAXRSResp(response);

        } catch (Exception sqlex) {
            LOGGER.error(sqlex.getMessage(), sqlex);
            ErrorResponse errorResponse = new ErrorResponse(ErrorCode.UNKNOWN_ERROR, "");
            return RestUtils.getBadReqJAXRSResp(errorResponse);
        } finally {
            DbConnectionManager.closeConnection(rs, pstmt, con);
        }
    }

    private MMXChannelId getChannelName(AppChannel appChannel) {
        MMXChannelId channelId;
        if (appChannel.isUserChannel()) {
            channelId = new MMXChannelId(appChannel.getUserId(), appChannel.getName());
        } else {
            channelId = new MMXChannelId(appChannel.getName());
        }
        return channelId;
    }
    //    @POST
    //    @Produces(MediaType.APPLICATION_JSON)
    //    @Consumes(MediaType.APPLICATION_JSON)
    //    @Path("/query")
    //    public Response findChannels(@Context HttpHeaders headers,QueryChannelRequest queryChannelRequest) {
    //
    //        Map<String,Integer> channelCountMap = new HashMap<String, Integer>(3);
    //
    //        MMXChannelManager channelManager = MMXChannelManager.getInstance();
    //
    //        try {
    //            ChannelAction.ListRequest request = new ChannelAction.ListRequest();
    //            request.setLimit(1000);
    //            request.setType(queryChannelRequest.getChannelType());
    //
    //            for(String userId:queryChannelRequest.getSubscribers()) {
    //                JID from = RestUtils.createJID(userId, queryChannelRequest.getMmxAppId(), null);
    //                ChannelAction.ListResponse response = channelManager.listChannels(from, queryChannelRequest.getMmxAppId(), request, null);
    //                for (ChannelInfo info : response) {
    //                    Integer integer = channelCountMap.get(info.getName());
    //                    if (integer != null) {
    //                        channelCountMap.put(info.getName(), new Integer(integer.intValue() + 1));
    //                    } else {
    //                        channelCountMap.put(info.getName(), new Integer(1));
    //                    }
    //                }
    //            }
    //            List<String> filteredChannels = new ArrayList<String>(3);
    //            for(String channelName:channelCountMap.keySet()) {
    //
    //                if(queryChannelRequest.getMatchFilter().equals(QueryChannelRequest.MatchType.EXACT_MATCH)) {
    //                    if (channelCountMap.get(channelName).intValue() == queryChannelRequest.getSubscribers().size()) {
    //                        //Get the subscriber count
    //                        List<NodeSubscription> subs = channelManager.listSubscriptionsForChannel(channelName);
    //
    //                        //Ignore if the user is not subscribed to this channel
    //
    //
    //                        if (queryChannelRequest.getSubscribers().size() == subs.size()) {
    //                            filteredChannels.add(channelName);
    //                        }
    //                    }
    //                }else if(queryChannelRequest.getMatchFilter().equals(QueryChannelRequest.MatchType.SUBSET_MATCH)) {
    //                    if (channelCountMap.get(channelName).intValue() == queryChannelRequest.getSubscribers().size()) {
    //                        filteredChannels.add(channelName);
    //                    }
    //
    //                }
    //            }
    //            QueryChannelResponse response = new QueryChannelResponse(ErrorCode.NO_ERROR.getCode(),
    //                    "Success");
    //            response.setChannels(filteredChannels);
    //            return RestUtils.getCreatedJAXRSResp(response);
    //
    //        } catch (MMXException e) {
    //            LOGGER.error("Exception during queryChannel request", e);
    //            return RestUtils.getCreatedJAXRSResp(e.toString());
    //
    //        }
    //
    //    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/chat/publish/")
    public Response publishToChannel(@Context HttpHeaders headers, PublishMessageToChatRequest channelInfo) {

        ErrorResponse errorResponse = null;

        if (channelInfo == null) {
            errorResponse = new ErrorResponse(ErrorCode.ILLEGAL_ARGUMENT, "Channel information not set");
            return RestUtils.getBadReqJAXRSResp(errorResponse);
        }

        //        if (!ChannelHelper.validateApplicationChannelName(channelInfo.getChannelName())) {
        //            errorResponse = new ErrorResponse(ErrorCode.ILLEGAL_ARGUMENT,
        //                    MMXChannelManager.StatusCode.INVALID_CHANNEL_NAME.getMessage());
        //            return RestUtils.getBadReqJAXRSResp(errorResponse);
        //        }

        if (!Strings.isNullOrEmpty(channelInfo.getDescription())
                && channelInfo.getDescription().length() > MMXServerConstants.MAX_TOPIC_DESCRIPTION_LEN) {
            errorResponse = new ErrorResponse(ErrorCode.ILLEGAL_ARGUMENT,
                    "channel description too long, max length = " + MMXServerConstants.MAX_TOPIC_DESCRIPTION_LEN);
            return RestUtils.getBadReqJAXRSResp(errorResponse);
        }

        // Attempt to create or Fetch Channel
        String channelHash = generateHash(channelInfo);
        String channelName = constructChannelName(channelInfo.getChannelName(), channelHash);
        MMXChannelManager channelManager = MMXChannelManager.getInstance();
        channelInfo.setChannelName(channelName);
        channelInfo.setPrivateChannel(true);
        JID from = RestUtils.createJID(channelInfo.getUserId(), channelInfo.getMmxAppId(),
                channelInfo.getDeviceId());
        try {
            ChannelAction.CreateRequest rqt = toCreateRequest(channelInfo);
            channelManager.createChannel(from, channelInfo.getMmxAppId(), rqt);

        } catch (MMXException e) {
            if (e.getCode() != StatusCode.CONFLICT) {
                if (e.getCode() == StatusCode.FORBIDDEN) {
                    errorResponse = new ErrorResponse(ErrorCode.ILLEGAL_ARGUMENT, e.getMessage());
                } else if (e.getCode() == StatusCode.BAD_REQUEST) {
                    errorResponse = new ErrorResponse(ErrorCode.ILLEGAL_ARGUMENT, e.getMessage());
                } else {
                    errorResponse = new ErrorResponse(ErrorCode.UNKNOWN_ERROR, e.getMessage());
                    return RestUtils.getInternalErrorJAXRSResp(errorResponse);
                }
            }

        } catch (Throwable e) {
            LOGGER.error("Throwable during publishToChatChannel request", e);
            errorResponse = new ErrorResponse(ErrorCode.UNKNOWN_ERROR, e.getMessage());
            return RestUtils.getInternalErrorJAXRSResp(errorResponse);
        }

        List<SentMessageId> sentList = new ArrayList<SentMessageId>();
        // auto subscribe recipients to this channel
        try {
            MMXChannelId channelId = nameToId(channelName);
            ChannelInfo foundChannel = channelManager.getChannel(channelInfo.getMmxAppId(), channelId);
            errorResponse = new ErrorResponse(ErrorCode.NO_ERROR, "Send Message to Chat Success");

            ChannelAction.SubscribeRequest rqt = new ChannelAction.SubscribeRequest(channelId.getEscUserId(),
                    channelId.getName(), null);
            ChannelAction.SubscribeResponse resp = null;

            for (String subscriber : channelInfo.getRecipients()) {
                JID sub = new JID(JIDUtil.makeNode(subscriber, channelInfo.getMmxAppId()), from.getDomain(), null);
                resp = channelManager.subscribeChannel(sub, channelInfo.getMmxAppId(), rqt,
                        Arrays.asList(MMXServerConstants.TOPIC_ROLE_PUBLIC));
                sentList.add(new SentMessageId(subscriber, "", null));

            }

        } catch (MMXException e) {
            // e.printStackTrace();
            //ignore this exception?
        }

        // send Message
        try {
            MessageSender sender = new MessageSenderImpl();

            TopicPostMessageRequest tpm = new TopicPostMessageRequest();
            tpm.setContent(channelInfo.getContent());
            tpm.setContentType(channelInfo.getContentType());
            tpm.setMessageType(channelInfo.getMessageType());

            TopicPostResult result = sender.postMessage(channelInfo.getUserId(),
                    channelInfo.getUserId() + "#" + channelName, channelInfo.getMmxAppId(), tpm);

            TopicPostResponse sendResponse = new TopicPostResponse();
            if (result.isError()) {
                LOGGER.info("Problem posting message:" + result.getErrorMessage());
                sendResponse.setMessage(result.getErrorMessage());
                sendResponse.setStatus(result.getStatus());
                throw new WebApplicationException(
                        Response.status(result.getErrorCode() == ErrorCode.TOPIC_PUBLISH_FORBIDDEN.getCode()
                                ? Response.Status.FORBIDDEN
                                : Response.Status.BAD_REQUEST).entity(sendResponse).build());
            } else {
                sendResponse.setMessageId(result.getMessageId());
                sendResponse.setMessage("Successfully published message");
                sendResponse.setStatus(result.getStatus());
                for (SentMessageId messageId : sentList) {
                    messageId.setMessageId(result.getMessageId());
                }
            }

            SendMessageResponse messageResponse = new SendMessageResponse();
            messageResponse.setCount(new Count(channelInfo.getRecipients().length, sentList.size(), 0));
            messageResponse.setSentList(sentList);
            return RestUtils.getOKJAXRSResp(messageResponse);
        } catch (WebApplicationException e) {
            throw e;
        } catch (Throwable t) {
            LOGGER.warn("Throwable during processing request", t);
            ErrorResponse error = new ErrorResponse(ErrorCode.UNKNOWN_ERROR, "Error processing request");
            return RestUtils.getInternalErrorJAXRSResp(error);
        }

    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/summary")
    public Response getChannelSummary(@Context HttpHeaders headers, ChannelSummaryRequest request) {

        List<ChannelSummaryResponse> summaryResponses = new ArrayList<ChannelSummaryResponse>();

        JID userRequestingSummary = RestUtils.createJID(request.getRequestingUserId(), request.getAppId(),
                request.getDeviceId());

        List<ChannelSummaryResponse> channelSummaries = getChannelsSummary(userRequestingSummary, request);

        //        //for each Channel
        //        for(String channelId:request.getChannelIds()) {
        //
        //            //ChannelInfo channelInfo = MMXChannelManager.getInstance().getChannel(null,request.getAppId(),)
        //            Node topicNode = MMXChannelManager.getInstance().getTopicNode(channelId);
        //            ChannelInfo channelInfo = MMXChannelManager.getInstance().nodeToChannelInfo(request.getAppId(), topicNode);
        //            MMXChannelManager.getInstance().getSummary(from,)
        //            List<NodeSubscription> subscriptions = MMXChannelManager.getInstance().listSubscriptionsForChannel(channelId);
        //            Date fromDate = topicNode.getCreationDate();
        //            Date toDate = new Date(System.currentTimeMillis());
        //            List<PublishedItem> messages = new ArrayList<PublishedItem>();
        //
        //            if(!topicNode.isCollectionNode())
        //                messages = PubSubPersistenceManagerExt.getPublishedItems((LeafNode)topicNode,0,request.getNumOfMessages(),fromDate,toDate,true);
        //
        //            summaryResponses.add(new ChannelSummaryResponse(channelInfo,))
        //            //MMXTopicManager.listSubscriptionsForTopic
        //        }

        return RestUtils.getCreatedJAXRSResp(channelSummaries);
    }

    protected List<ChannelSummaryResponse> getChannelsSummary(JID userRequestingSummary,
            ChannelSummaryRequest channelSummaryRequest) {

        List<ChannelSummaryResponse> summaryList = new ArrayList<ChannelSummaryResponse>();
        try {
            MMXChannelManager channelManager = MMXChannelManager.getInstance();
            List<MMXChannelId> channelIds = new ArrayList<MMXChannelId>();
            for (ChannelLookupKey channelLookupKey : channelSummaryRequest.getChannelIds()) {

                if (channelLookupKey.isPrivateChannel()) {
                    channelIds
                            .add(new MMXChannelId(channelLookupKey.getUserId(), channelLookupKey.getChannelName()));
                } else {
                    channelIds.add(new MMXChannelId(channelLookupKey.getChannelName()));
                }
                //channelIds.add(nameToId(channelLookupKey.getChannelName()));
            }

            ChannelAction.SummaryRequest rqt = new ChannelAction.SummaryRequest(channelIds);
            ChannelAction.SummaryResponse resp = channelManager.getSummary(userRequestingSummary,
                    channelSummaryRequest.getAppId(), rqt);

            for (ChannelSummary s : resp) {
                int count = s.getCount();
                Date lastPublishedDate = s.getLastPubTime();
                String userId = s.getChannelNode().getUserId();
                String name = s.getChannelNode().getName();

                // get Summary
                //                MMXChannelSummary mts = new MMXChannelSummary(userId, name, count,
                //                        lastPublishedDate);
                // get ChannelInfo
                MMXChannelId channelId;
                if (s.getChannelNode().isUserChannel()) {
                    channelId = new MMXChannelId(userId, name);
                } else {
                    channelId = new MMXChannelId(name);
                }

                String realChannel = ChannelHelper.makeChannel(channelSummaryRequest.getAppId(),
                        channelId.getEscUserId(), ChannelHelper.normalizePath(channelId.getName()));
                LOGGER.info("realChannel " + realChannel);
                PubSubPersistenceManager.loadNode(XMPPServer.getInstance().getPubSubModule(), realChannel);

                Node node = MMXChannelManager.getInstance().getChannelNode(channelSummaryRequest.getAppId(),
                        channelId);

                ChannelInfo channelInfo = MMXChannelManager.getInstance().nodeToChannelInfo(userId, node);
                // get Subscribers
                //ChannelAction.SubscribersRequest subscribersRequest = new ChannelAction.SubscribersRequest(JIDUtil.getUserId(userRequestingSummary),node.getNodeID(), 0, channelSummaryRequest.getNumOfSubcribers());
                ChannelAction.SubscribersResponse subscribersResponse = MMXChannelManager.getInstance()
                        .getSubscribersFromNode(null, channelSummaryRequest.getAppId(), 0,
                                channelSummaryRequest.getNumOfSubcribers(), node);

                Date sinceDate = null;
                if (channelSummaryRequest.getMessagesSince() == 0) {
                    Calendar oneyearDeafult = Calendar.getInstance();
                    oneyearDeafult.add(Calendar.YEAR, -1);
                    sinceDate = oneyearDeafult.getTime();
                } else {
                    sinceDate = new Date(channelSummaryRequest.getMessagesSince());
                }

                JID channelOwner = node.getOwners() == null ? null : node.getOwners().iterator().next();
                int messageOffset = 0;
                List<ChannelResource.MMXPubSubItemChannel2> messages = this.fetchItemsForChannel(channelOwner,
                        channelSummaryRequest.getAppId(), channelId, sinceDate, new Date(),
                        channelSummaryRequest.getNumOfMessages(), messageOffset, MMXServerConstants.SORT_ORDER_ASC);

                UserEntity ownerInfo = userDAO.getUser(channelOwner.getNode());
                //if (ownerInfo != null) {
                ChannelSummaryResponse channelSummaryResponse = new ChannelSummaryResponse(userId, name, ownerInfo,
                        count, lastPublishedDate, subscribersResponse.getTotal(),
                        subscribersResponse.getSubscribers(), messages);
                summaryList.add(channelSummaryResponse);
                //}
            }

        } catch (Exception exc) {
            exc.printStackTrace();

        }

        return summaryList;

    }

    private List<ChannelResource.MMXPubSubItemChannel2> fetchItemsForChannel(JID channelOwner, String appId,
            MMXChannelId channelId, Date since, Date until, int size, int offset, String sortOrder)
            throws MMXException {
        MMXChannelManager channelManager = MMXChannelManager.getInstance();

        ChannelAction.FetchOptions opt = new ChannelAction.FetchOptions().setMaxItems(size).setOffset(offset)
                .setAscending(sortOrder.equalsIgnoreCase(MMXServerConstants.SORT_ORDER_ASC))
                .setSince(since == null ? null : new DateTime(since).toDate())
                .setUntil(until == null ? null : new DateTime(until).toDate());
        ChannelAction.FetchRequest rqt = new ChannelAction.FetchRequest(channelId.getEscUserId(),
                channelId.getName(), opt);
        ChannelAction.FetchResponse resp = channelManager.fetchItems(channelOwner, appId, rqt);

        String nodeId = ChannelHelper.makeChannel(appId, channelId.getEscUserId(), channelId.getName());
        List<TopicItemEntity> channelItemEntities = toTopicItemEntity(nodeId, resp.getItems());
        List<ChannelResource.MMXPubSubItemChannel2> items = toPubSubItems(channelId, channelItemEntities, appId);

        return items;

    }

    //    /**
    //     * Add subscribers to a public or private channel by the admin.  The
    //     * <code>channelName</code> must be in the form of "user-id#channel-name"
    //     * (e.g. "38473af95e116c0#myblogs") for private channel, or without a hash
    //     * sign as "channel-name" (e.g. "company-announcement") for public channel.
    //     * @param headers
    //     * @param channelName Private or public channel name.
    //     * @param subscribers A list of subscribers.
    //     * @return
    //     */
    //    @PUT
    //    @Path("{" + CHANNEL_NAME + "}/subscribers")
    //    @Produces(MediaType.APPLICATION_JSON)
    //    @Consumes(MediaType.APPLICATION_JSON)
    //    public Response addSubscribers(@Context HttpHeaders headers,
    //                                    @PathParam(CHANNEL_NAME) String channelName,
    //                                    List<MMXid> subscribers) {
    //        TokenInfo tokenInfo = RestUtils.getAuthTokenInfo(headers);
    //        if (tokenInfo == null) {
    //            return RestUtils.getUnauthJAXRSResp();
    //        }
    //
    //      JID admin = RestUtils.createJID(tokenInfo);
    //        String domain = admin.getDomain();
    //        String appId = tokenInfo.getMmxAppId();
    //        MMXChannelId channelId = nameToId(channelName);
    //
    //        MMXChannelManager channelManager = MMXChannelManager.getInstance();
    //        try {
    //            ChannelAction.SubscribeRequest rqt = new ChannelAction.SubscribeRequest(
    //                    channelId.getEscUserId(), channelId.getName(), null);
    //            ChannelAction.SubscribeResponse resp = null;
    //            for (MMXid subscriber : subscribers) {
    //              JID sub = new JID(JIDUtil.makeNode(subscriber.getUserId(), appId),
    //                    domain, subscriber.getDeviceId());
    //              resp = channelManager.subscribeChannel(sub, appId, rqt,
    //                  Arrays.asList(MMXServerConstants.TOPIC_ROLE_PUBLIC));
    //            }
    //            return RestUtils.getOKJAXRSResp(resp);
    //        } catch (MMXException e) {
    //            Response.Status status;
    //            ErrorResponse response;
    //            if (e.getCode() == StatusCode.NOT_FOUND) {
    //                status = Response.Status.NOT_FOUND;
    //                response = new ErrorResponse(ErrorCode.TOPIC_NOT_EXIST,
    //                        "Channel does not exist: " + channelName);
    //            } else if (e.getCode() == StatusCode.FORBIDDEN) {
    //                status = Response.Status.FORBIDDEN;
    //                response = new ErrorResponse(ErrorCode.TOPIC_SUBSCRIBE_FORBIDDEN,
    //                        "Channel cannot be subscribed: " + channelName);
    //            } else if (e.getCode() == StatusCode.CONFLICT) {
    //                status = Response.Status.CONFLICT;
    //                response = new ErrorResponse(ErrorCode.TOPIC_ALREADY_SUBSCRIBED,
    //                        "Channel is already subscribed: " + channelName);
    //            } else {
    //                status = Response.Status.INTERNAL_SERVER_ERROR;
    //                response = new ErrorResponse(ErrorCode.UNKNOWN_ERROR, e.getMessage());
    //            }
    //            return RestUtils.getJAXRSResp(status, response);
    //        }
    //    }
    //
    //    /**
    //     * Delete subscribers from a public or private channel by the admin.  The
    //     * <code>channelName</code> must be in the form of "user-id#channel-name"
    //     * (e.g. "38473af95e116c0#myblogs") for private channel, or without a hash
    //     * sign as "channel-name" (e.g. "company-announcement") for public channel.
    //     * @param headers
    //     * @param channelName Private or public channel name.
    //     * @param subscribers A list of subscribers.
    //     * @return
    //     */
    //    @DELETE
    //    @Path("{" + CHANNEL_NAME + "}/subscribers")
    //    @Consumes(MediaType.APPLICATION_JSON)
    //    @Produces(MediaType.APPLICATION_JSON)
    //    public Response deleteSubscribers(@Context HttpHeaders headers,
    //                                       @PathParam(CHANNEL_NAME) String channelName,
    //                                       List<MMXid> subscribers) {
    //        TokenInfo tokenInfo = RestUtils.getAuthTokenInfo(headers);
    //        if (tokenInfo == null) {
    //            return RestUtils.getUnauthJAXRSResp();
    //        }
    //
    //        JID admin = RestUtils.createJID(tokenInfo);
    //        String domain = admin.getDomain();
    //        String appId = tokenInfo.getMmxAppId();
    //        MMXChannelId channelId = nameToId(channelName);
    //
    //        MMXChannelManager channelManager = MMXChannelManager.getInstance();
    //        try {
    //            ChannelAction.UnsubscribeRequest rqt = new ChannelAction.UnsubscribeRequest(
    //                    channelId.getEscUserId(), channelId.getName(), null);
    //            MMXStatus resp = null;
    //            for (MMXid subscriber : subscribers) {
    //              JID sub = new JID(JIDUtil.makeNode(subscriber.getUserId(), appId),
    //                    domain, subscriber.getDeviceId());
    //              resp = channelManager.unsubscribeChannel(sub, appId, rqt);
    //            }
    //            return RestUtils.getOKJAXRSResp(resp);
    //        } catch (MMXException e) {
    //            Response.Status status;
    //            ErrorResponse response;
    //            if (e.getCode() == StatusCode.NOT_FOUND) {
    //                status = Response.Status.NOT_FOUND;
    //                response = new ErrorResponse(ErrorCode.TOPIC_NOT_EXIST,
    //                        "Channel does not exist: " + channelName);
    //            } else if (e.getCode() == StatusCode.GONE) {
    //                status = Response.Status.GONE;
    //                response = new ErrorResponse(ErrorCode.TOPIC_NOT_SUBSCRIBED,
    //                        "Channel is not subscribed: " + channelName);
    //            } else {
    //                status = Response.Status.INTERNAL_SERVER_ERROR;
    //                response = new ErrorResponse(ErrorCode.UNKNOWN_ERROR, e.getMessage());
    //            }
    //            return RestUtils.getJAXRSResp(status, response);
    //        }
    //    }

    // The hack to fix MOB-2516 that allows the console to display user channels as
    // userID#channelName. This method parses the global channel or user channel
    // properly.
    public static MMXChannelId nameToId(String channelName) {
        int index = channelName.indexOf(ChannelHelper.CHANNEL_SEPARATOR);
        if (index < 0) {
            return new MMXChannelId(channelName);
        } else {
            return new MMXChannelId(channelName.substring(0, index), channelName.substring(index + 1));
        }
    }

    // The hack to fix MOB-2516 to convert a user channel to userID#channelName
    public static String idToName(String userId, String channelName) {

        if (userId == null) {
            return channelName;
        } else {
            return userId + ChannelHelper.CHANNEL_SEPARATOR + channelName;
        }
    }

    private ChannelAction.CreateRequest toCreateRequest(ChannelCreateInfo createInfo) {
        MMXTopicOptions options = new MMXTopicOptions().setDescription(createInfo.getDescription())
                .setMaxItems(createInfo.getMaxItems()).setSubscribeOnCreate(createInfo.isSubscribeOnCreate())
                .setSubscriptionEnabled(createInfo.isSubscriptionEnabled())
                .setPublisherType(createInfo.getPublishPermission());
        ChannelAction.CreateRequest rqt = new ChannelAction.CreateRequest(createInfo.getChannelName(),
                createInfo.isPrivateChannel(), options);
        return rqt;
    }

    private static String generateHash(PublishMessageToChatRequest request) {
        List<String> recipients = new ArrayList<String>();
        recipients.addAll(Arrays.asList(request.getRecipients()));
        recipients.add(request.getUserId());

        if (recipients != null && recipients.size() > 0) {
            //order recipients
            Collections.sort(recipients);
            String signature = StringUtils.join(recipients, ",");
            MessageDigest md5 = null;
            try {
                md5 = MessageDigest.getInstance("MD5");
                md5.update((MMX_INTERNAL_SALT + signature).getBytes());
                byte byteData[] = md5.digest();

                String channelHash = encode2Hex(byteData);
                return channelHash;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
        return null;

    }

    private static String constructChannelName(String channelName, String hash) {
        //return "chat/"+ hash;
        return hash;
    }

    public static String encode2Hex(byte[] bytes) {

        //shouldnt be using this to hexify a huge binary array
        if (bytes == null || bytes.length < 1 || bytes.length > (Integer.MAX_VALUE / 2)) {
            return null;
        }

        char[] hex = new char[bytes.length * 2];
        for (int indx = 0; indx < bytes.length; indx++) {
            byte lsb = (byte) (bytes[indx] & 0x0f);
            byte msb = (byte) ((bytes[indx] & 0xf0) >> 4);
            hex[indx * 2] = hexArray[msb];
            hex[indx * 2 + 1] = hexArray[lsb];
        }
        return new String(hex);
    }

    private List<TopicItemEntity> toTopicItemEntity(String nodeId, List<ChannelAction.MMXPublishedItem> items) {
        List<TopicItemEntity> list = new ArrayList<TopicItemEntity>(items.size());
        for (ChannelAction.MMXPublishedItem item : items) {
            TopicItemEntity itemEntity = new TopicItemEntity();
            itemEntity.setNodeId(nodeId);
            itemEntity.setJid(item.getPublisher());
            itemEntity.setId(item.getItemId());
            itemEntity.setPayload(item.getPayloadXml());
            itemEntity.setCreationDate(org.jivesoftware.util.StringUtils.dateToMillis(item.getCreationDate()));
            itemEntity.setServiceId("pubsub");
            list.add(itemEntity);
        }
        return list;
    }

    private List<ChannelResource.MMXPubSubItemChannel2> toPubSubItems(final MMXChannelId channelId,
            List<TopicItemEntity> entityList, String appId) {
        Function<TopicItemEntity, MMXPubSubItemChannel> entityToItem = new Function<TopicItemEntity, MMXPubSubItemChannel>() {
            @Override
            public MMXPubSubItemChannel apply(TopicItemEntity i) {
                return new MMXPubSubItemChannel(idToName(channelId.getEscUserId(), channelId.getName()), i.getId(),
                        new JID(i.getJid()), i.getPayload());
            }

            ;
        };

        List<MMXPubSubItemChannel> items = Lists.transform(entityList, entityToItem);
        List<ChannelResource.MMXPubSubItemChannel2> items2 = new ArrayList<ChannelResource.MMXPubSubItemChannel2>(
                items.size());
        for (MMXPubSubItemChannel item : items) {
            items2.add(new ChannelResource.MMXPubSubItemChannel2Ext(item, appId));
        }
        return items2;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/reports")
    public Response getnerateReport(@Context HttpHeaders headers) {

        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        Map<String, Integer> channelCountMap = new HashMap<String, Integer>(3);
        Map<String, Integer> channelSubscriptionMap = new HashMap<String, Integer>(3);
        try {

            List<AppEntity> apps = appDAO.getAllApps();

            for (AppEntity app : apps) {

                int messageCount;

                con = DbConnectionManager.getConnection();

                String sql = "SELECT ,count(*) FROM ofPubsubItem where nodeID " + "like '" + "/" + app.getAppId()
                        + "%'";

                pstmt = con.prepareStatement(sql);
                rs = pstmt.executeQuery();

                while (rs.next()) {
                    System.out.println("appId = " + app.getName() + " count = " + rs.getInt(1));
                }

            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return Response.ok().build();

    }

}