[ISSUE-67901957] add "entities/apiproducts" endpoint
diff --git a/accessEntity/accessEntity_suite_test.go b/accessEntity/accessEntity_suite_test.go
new file mode 100644
index 0000000..f8a1ed1
--- /dev/null
+++ b/accessEntity/accessEntity_suite_test.go
@@ -0,0 +1,49 @@
+// Copyright 2017 Google 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 accessEntity
+
+import (
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+
+	"github.com/apid/apid-core"
+	"github.com/apid/apid-core/factory"
+	"github.com/apid/apidVerifyApiKey/common"
+	"os"
+	"testing"
+)
+
+const testTempDirBase = "./tmp/"
+
+var (
+	testTempDir string
+)
+
+var _ = BeforeSuite(func() {
+	_ = os.MkdirAll(testTempDirBase, os.ModePerm)
+	s := factory.DefaultServicesFactory()
+	apid.Initialize(s)
+	SetApidServices(s, apid.Log())
+	common.SetApidServices(s, s.Log())
+})
+
+var _ = AfterSuite(func() {
+	apid.Events().Close()
+	os.RemoveAll(testTempDirBase)
+})
+
+func TestVerifyAPIKey(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "VerifyAPIKey Suite")
+}
diff --git a/accessEntity/api.go b/accessEntity/api.go
index 534e913..160b79e 100644
--- a/accessEntity/api.go
+++ b/accessEntity/api.go
@@ -1,4 +1,3 @@
-
 // Copyright 2017 Google Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,12 +15,268 @@
 package accessEntity
 
 import (
+	"encoding/json"
+	"fmt"
+	"github.com/apid/apidVerifyApiKey/common"
+	"net/http"
+	"strconv"
+	"strings"
 )
 
+const (
+	AccessEntityPath         = "/entities"
+	EndpointApp              = "/apps"
+	EndpointApiProduct       = "/apiproducts"
+	EndpointCompany          = "/companies"
+	EndpointCompanyDeveloper = "/companydevelopers"
+	EndpointDeveloper        = "/developers"
+	EndpointAppCredentials   = "/appcredentials"
+)
 
+const (
+	IdentifierAppId          = "appid"
+	IdentifierApiProductName = "apiproductname"
+	IdentifierAppName        = "appname"
+	IdentifierApiResource    = "apiresource"
+	IdentifierDeveloperId    = "developerid"
+	IdentifierDeveloperEmail = "developeremail"
+	IdentifierConsumerKey    = "consumerkey"
+	IdentifierCompanyName    = "companyname"
+)
+
+var (
+	Identifiers = map[string]bool{
+		"appid":          true,
+		"apiproductname": true,
+		"appname":        true,
+		"apiresource":    true,
+		"developerid":    true,
+		"companyname":    true,
+		"developeremail": true,
+		"consumerkey":    true,
+	}
+
+	ErrInvalidPar = &common.ErrorResponse{
+		ResponseCode:    strconv.Itoa(INVALID_PARAMETERS),
+		ResponseMessage: "invalid identifiers",
+		StatusCode:      http.StatusBadRequest,
+	}
+
+	IdentifierTree = map[string]map[string][]string{
+		EndpointApiProduct: {
+			IdentifierApiProductName: {},
+			IdentifierAppId:          {IdentifierApiResource},
+			IdentifierAppName:        {IdentifierApiResource, IdentifierDeveloperEmail, IdentifierDeveloperId, IdentifierCompanyName},
+			IdentifierConsumerKey:    {IdentifierApiResource},
+		},
+		EndpointApp: {
+			IdentifierAppId:       {},
+			IdentifierAppName:     {IdentifierDeveloperEmail, IdentifierDeveloperId, IdentifierCompanyName},
+			IdentifierConsumerKey: {},
+		},
+		EndpointCompany: {
+			IdentifierAppId:       {},
+			IdentifierCompanyName: {},
+			IdentifierConsumerKey: {},
+		},
+		EndpointCompanyDeveloper: {
+			IdentifierCompanyName: {},
+		},
+		EndpointAppCredentials: {
+			IdentifierConsumerKey: {},
+		},
+		EndpointDeveloper: {
+			IdentifierDeveloperEmail: {},
+			IdentifierAppId:          {},
+			IdentifierDeveloperId:    {},
+			IdentifierConsumerKey:    {},
+		},
+	}
+)
+
+const (
+	INVALID_PARAMETERS = iota
+	DB_ERROR
+	DATA_ERROR
+)
 
 type ApiManager struct {
-	DbMan             DbManagerInterface
-	apiInitialized    bool
+	DbMan            DbManagerInterface
+	AccessEntityPath string
+	apiInitialized   bool
 }
 
+func (a *ApiManager) InitAPI() {
+	if a.apiInitialized {
+		return
+	}
+	services.API().HandleFunc(a.AccessEntityPath+EndpointApp, a.HandleApps).Methods("GET")
+	services.API().HandleFunc(a.AccessEntityPath+EndpointApiProduct, a.HandleApiProducts).Methods("GET")
+	services.API().HandleFunc(a.AccessEntityPath+EndpointCompany, a.HandleCompanies).Methods("GET")
+	services.API().HandleFunc(a.AccessEntityPath+EndpointCompanyDeveloper, a.HandleCompanyDevelopers).Methods("GET")
+	services.API().HandleFunc(a.AccessEntityPath+EndpointDeveloper, a.HandleDevelopers).Methods("GET")
+	services.API().HandleFunc(a.AccessEntityPath+EndpointAppCredentials, a.HandleConsumers).Methods("GET")
+	a.apiInitialized = true
+	log.Debug("API endpoints initialized")
+}
+
+func (a *ApiManager) HandleApps(w http.ResponseWriter, r *http.Request) {
+
+}
+
+func (a *ApiManager) HandleApiProducts(w http.ResponseWriter, r *http.Request) {
+	ids, err := extractIdentifiers(r.URL.Query())
+	if err != nil {
+		common.WriteError(w, err.Error(), INVALID_PARAMETERS, http.StatusBadRequest)
+	}
+	details, errRes := a.getApiProduct(ids)
+	if errRes != nil {
+		writeJson(errRes, w, r)
+		return
+	}
+	writeJson(details, w, r)
+}
+
+func (a *ApiManager) HandleCompanies(w http.ResponseWriter, r *http.Request) {
+
+}
+func (a *ApiManager) HandleCompanyDevelopers(w http.ResponseWriter, r *http.Request) {
+
+}
+func (a *ApiManager) HandleDevelopers(w http.ResponseWriter, r *http.Request) {
+
+}
+func (a *ApiManager) HandleConsumers(w http.ResponseWriter, r *http.Request) {
+
+}
+
+func extractIdentifiers(pars map[string][]string) (map[string]string, error) {
+	m := make(map[string]string)
+	for k, v := range pars {
+		k = strings.ToLower(k)
+		if Identifiers[k] {
+			if len(v) == 1 {
+				m[k] = v[0]
+			} else {
+				return nil, fmt.Errorf("each identifier must have only 1 value")
+			}
+		}
+	}
+	return m, nil
+}
+
+func (a *ApiManager) getApiProduct(ids map[string]string) (*ApiProductDetails, *common.ErrorResponse) {
+	valid, keyVals := parseIdentifiers(EndpointApiProduct, ids)
+	if !valid {
+		return nil, ErrInvalidPar
+	}
+	priKey, priVal, secKey, secVal := keyVals[0], keyVals[1], keyVals[2], keyVals[3]
+
+	prods, err := a.DbMan.GetApiProducts(priKey, priVal, secKey, secVal)
+	if err != nil {
+		log.Errorf("getApiProduct: %v", err)
+		return nil, newDbError(err)
+	}
+
+	var prod *common.ApiProduct
+	var attrs []common.Attribute
+	if len(prods) > 0 {
+		prod = &prods[0]
+		attrs = a.DbMan.GetKmsAttributes(prod.TenantId, prod.Id)[prod.Id]
+	}
+
+	return makeApiProductDetails(prod, attrs, priKey, priVal, secKey, secVal)
+}
+
+func makeApiProductDetails(prod *common.ApiProduct, attrs []common.Attribute, priKey, priVal, secKey, secVal string) (*ApiProductDetails, *common.ErrorResponse) {
+	var a *ApiProductDetails
+	if prod != nil {
+		quotaLimit, err := strconv.Atoi(prod.Quota)
+		if err != nil {
+			return nil, newDataError(err)
+		}
+		a = &ApiProductDetails{
+			APIProxies:     common.JsonToStringArray(prod.Proxies),
+			APIResources:   common.JsonToStringArray(prod.ApiResources),
+			ApprovalType:   prod.ApprovalType,
+			Attributes:     attrs,
+			CreatedAt:      prod.CreatedAt,
+			CreatedBy:      prod.CreatedBy,
+			Description:    prod.Description,
+			DisplayName:    prod.DisplayName,
+			Environments:   common.JsonToStringArray(prod.Environments),
+			ID:             prod.Id,
+			LastModifiedAt: prod.UpdatedAt,
+			LastModifiedBy: prod.UpdatedBy,
+			Name:           prod.Name,
+			QuotaInterval:  prod.QuotaInterval,
+			QuotaLimit:     int64(quotaLimit),
+			QuotaTimeUnit:  prod.QuotaTimeUnit,
+			Scopes:         common.JsonToStringArray(prod.Scopes),
+		}
+	} else {
+		a = new(ApiProductDetails)
+	}
+
+	setResIdentifiers(a, priKey, priVal, secKey, secVal)
+	return a, nil
+}
+
+func setResIdentifiers(a *ApiProductDetails, priKey, priVal, secKey, secVal string) {
+	a.PrimaryIdentifierType = priKey
+	a.PrimaryIdentifierValue = priVal
+	a.SecondaryIdentifierType = secKey
+	a.PrimaryIdentifierValue = secVal
+}
+
+func parseIdentifiers(endpoint string, ids map[string]string) (valid bool, keyVals []string) {
+	if len(ids) > 2 {
+		return false, nil
+	}
+	if m := IdentifierTree[endpoint]; m != nil {
+		for key, val := range ids {
+			if m[key] != nil {
+				keyVals = append(keyVals, key, val)
+				for _, id := range m[key] {
+					if ids[id] != "" {
+						keyVals = append(keyVals, id, ids[id])
+						return true, keyVals
+					}
+				}
+				if len(ids) == 2 {
+					return false, nil
+				}
+				keyVals = append(keyVals, "", "")
+				return true, keyVals
+			}
+		}
+	}
+	return false, nil
+}
+
+func newDbError(err error) *common.ErrorResponse {
+	return &common.ErrorResponse{
+		ResponseCode:    strconv.Itoa(DB_ERROR),
+		ResponseMessage: err.Error(),
+		StatusCode:      http.StatusInternalServerError,
+	}
+}
+
+func newDataError(err error) *common.ErrorResponse {
+	return &common.ErrorResponse{
+		ResponseCode:    strconv.Itoa(DATA_ERROR),
+		ResponseMessage: err.Error(),
+		StatusCode:      http.StatusInternalServerError,
+	}
+}
+
+func writeJson(obj interface{}, w http.ResponseWriter, r *http.Request) {
+	bytes, err := json.Marshal(obj)
+	if err != nil {
+		log.Error("unable to marshal errorResponse: " + err.Error())
+		w.Write([]byte("unable to marshal errorResponse: " + err.Error()))
+	} else {
+		w.Header().Set("Content-Type", "application/json")
+		w.Write(bytes)
+	}
+}
diff --git a/accessEntity/api_response.go b/accessEntity/api_response.go
index d61042c..07b3f49 100644
--- a/accessEntity/api_response.go
+++ b/accessEntity/api_response.go
@@ -1 +1,68 @@
 package accessEntity
+
+import "github.com/apid/apidVerifyApiKey/common"
+
+type ApiProductDetails struct {
+	// api proxies
+	APIProxies []string `json:"apiProxies,omitempty"`
+
+	// api resources
+	APIResources []string `json:"apiResources,omitempty"`
+
+	// approval type
+	ApprovalType string `json:"approvalType,omitempty"`
+
+	// Attributes associated with the apiproduct.
+	Attributes []common.Attribute `json:"attributes,omitempty"`
+
+	// ISO-8601
+	CreatedAt string `json:"createdAt,omitempty"`
+
+	// created by
+	CreatedBy string `json:"createdBy,omitempty"`
+
+	// description
+	Description string `json:"description,omitempty"`
+
+	// display name
+	DisplayName string `json:"displayName,omitempty"`
+
+	// environments
+	Environments []string `json:"environments,omitempty"`
+
+	// id
+	ID string `json:"id,omitempty"`
+
+	// ISO-8601
+	LastModifiedAt string `json:"lastModifiedAt,omitempty"`
+
+	// last modified by
+	LastModifiedBy string `json:"lastModifiedBy,omitempty"`
+
+	// name
+	Name string `json:"name,omitempty"`
+
+	// primary identifier type
+	PrimaryIdentifierType string `json:"primaryIdentifierType,omitempty"`
+
+	// primary identifier value
+	PrimaryIdentifierValue string `json:"primaryIdentifierValue,omitempty"`
+
+	// quota interval
+	QuotaInterval int64 `json:"quotaInterval,omitempty"`
+
+	// quota limit
+	QuotaLimit int64 `json:"quotaLimit,omitempty"`
+
+	// quota time unit
+	QuotaTimeUnit string `json:"quotaTimeUnit,omitempty"`
+
+	// scopes
+	Scopes []string `json:"scopes,omitempty"`
+
+	// secondary identifier type
+	SecondaryIdentifierType string `json:"secondaryIdentifierType,omitempty"`
+
+	// secondary identifier value
+	SecondaryIdentifierValue string `json:"secondaryIdentifierValue,omitempty"`
+}
diff --git a/accessEntity/data.go b/accessEntity/data.go
index d61042c..dabb2a3 100644
--- a/accessEntity/data.go
+++ b/accessEntity/data.go
@@ -1 +1,254 @@
+// Copyright 2017 Google 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 accessEntity
+
+import (
+	"github.com/apid/apidVerifyApiKey/common"
+	"strings"
+)
+
+const (
+	sql_select_api_product = `SELECT * FROM kms_api_product AS ap `
+	sql_select_api         = `
+	SELECT * FROM kms_api_product AS ap WHERE ap.id IN (
+		SELECT apiprdt_id FROM kms_app_credential_apiproduct_mapper AS acm WHERE acm.app_id IN (
+			SELECT a.id FROM kms_app AS a WHERE a.name IN ('apstest')
+		)
+	);
+
+	`
+)
+
+type DbManager struct {
+	common.DbManager
+}
+
+func (d *DbManager) GetApiProducts(priKey, priVal, secKey, secVal string) (apiProducts []common.ApiProduct, err error) {
+	if priKey == IdentifierAppId {
+		apiProducts, err = d.getApiProductsByAppId(priVal)
+		if err != nil {
+			return
+		}
+	} else if priKey == IdentifierApiProductName {
+		apiProducts, err = d.getApiProductsByName(priVal)
+		if err != nil {
+			return
+		}
+	} else if priKey == IdentifierAppName {
+		switch secKey {
+		case IdentifierDeveloperEmail:
+			apiProducts, err = d.getApiProductsByAppName(priVal, secVal, "", "")
+		case IdentifierDeveloperId:
+			apiProducts, err = d.getApiProductsByAppName(priVal, "", secVal, "")
+		case IdentifierCompanyName:
+			apiProducts, err = d.getApiProductsByAppName(priVal, "", "", secVal)
+		case IdentifierApiResource:
+			fallthrough
+		case "":
+			apiProducts, err = d.getApiProductsByAppName(priVal, "", "", "")
+		}
+		if err != nil {
+			return
+		}
+	} else if priKey == IdentifierConsumerKey {
+		apiProducts, err = d.getApiProductsByConsumerKey(priVal)
+		if err != nil {
+			return
+		}
+	}
+
+	if secKey == IdentifierApiResource {
+		apiProducts = filterApiProductsByResource(apiProducts, secVal)
+	}
+	return
+}
+
+func (d *DbManager) getApiProductsByName(apiProdName string) (apiProducts []common.ApiProduct, err error) {
+	err = d.GetDb().QueryStructs(&apiProducts,
+		sql_select_api_product+`WHERE ap.name = $1;`,
+		apiProdName,
+	)
+	return
+}
+
+func (d *DbManager) getApiProductsByAppId(appId string) (apiProducts []common.ApiProduct, err error) {
+	cols := []string{"*"}
+	query := selectApiProductsByIds(
+		selectAppCredentialMapperByAppIds(
+			"'"+appId+"'",
+			"apiprdt_id",
+		),
+		cols...,
+	)
+	log.Debugf("getApiProductsByAppId: %v", query)
+	err = d.GetDb().QueryStructs(&apiProducts, query)
+	return
+}
+
+func (d *DbManager) getApiProductsByConsumerKey(consumerKey string) (apiProducts []common.ApiProduct, err error) {
+	cols := []string{"*"}
+	query := selectApiProductsByIds(
+		selectAppCredentialMapperByAppIds(
+			selectAppCredentialByConsumerKey(
+				"'"+consumerKey+"'",
+				"app_id",
+			),
+			"apiprdt_id",
+		),
+		cols...,
+	)
+	log.Debugf("getApiProductsByConsumerKey: %v", query)
+	err = d.GetDb().QueryStructs(&apiProducts, query)
+	return
+}
+
+func (d *DbManager) getApiProductsByAppName(appName, devEmail, devId, comName string) (apiProducts []common.ApiProduct, err error) {
+	cols := []string{"*"}
+	var appQuery string
+	switch {
+	case devEmail != "":
+		appQuery = selectAppByNameAndDeveloperId(
+			"'"+appName+"'",
+			selectDeveloperByEmail(
+				"'"+devEmail+"'",
+				"id",
+			),
+			"id",
+		)
+	case devId != "":
+		appQuery = selectAppByNameAndDeveloperId(
+			"'"+appName+"'",
+			"'"+devId+"'",
+			"id",
+		)
+	case comName != "":
+		appQuery = selectAppByNameAndCompanyId(
+			"'"+appName+"'",
+			selectCompanyByName(
+				"'"+comName+"'",
+				"id",
+			),
+			"id",
+		)
+	default:
+		appQuery = selectAppByName(
+			"'"+appName+"'",
+			"id",
+		)
+	}
+
+	query := selectApiProductsByIds(
+		selectAppCredentialMapperByAppIds(
+			appQuery,
+			"apiprdt_id",
+		),
+		cols...,
+	)
+	log.Debugf("getApiProductsByAppName: %v", query)
+	err = d.GetDb().QueryStructs(&apiProducts, query)
+	return
+}
+
+func selectApiProductsByIds(idQuery string, colNames ...string) string {
+	query := "SELECT " +
+		strings.Join(colNames, ",") +
+		" FROM kms_api_product AS ap WHERE ap.id IN (" +
+		idQuery +
+		")"
+
+	return query
+}
+
+func selectAppCredentialMapperByAppIds(idQuery string, colNames ...string) string {
+	query := "SELECT " +
+		strings.Join(colNames, ",") +
+		" FROM kms_app_credential_apiproduct_mapper AS acm WHERE acm.app_id IN (" +
+		idQuery +
+		")"
+	return query
+}
+
+func selectAppByName(nameQuery string, colNames ...string) string {
+	query := "SELECT " +
+		strings.Join(colNames, ",") +
+		" FROM kms_app AS a WHERE a.name IN (" +
+		nameQuery +
+		")"
+	return query
+}
+
+func selectAppByNameAndDeveloperId(nameQuery string, developerIdQuery string, colNames ...string) string {
+	query := selectAppByName(nameQuery, colNames...) +
+		" AND developer_id IN (" +
+		developerIdQuery +
+		")"
+	return query
+}
+
+func selectAppByNameAndCompanyId(nameQuery string, companyIdQuery string, colNames ...string) string {
+	query := selectAppByName(nameQuery, colNames...) +
+		" AND company_id IN (" +
+		companyIdQuery +
+		")"
+	return query
+}
+
+func selectDeveloperByEmail(emailQuery string, colNames ...string) string {
+	query := "SELECT " +
+		strings.Join(colNames, ",") +
+		" FROM kms_developer AS dev WHERE dev.email IN (" +
+		emailQuery +
+		")"
+	return query
+}
+
+func selectCompanyByName(nameQuery string, colNames ...string) string {
+	query := "SELECT " +
+		strings.Join(colNames, ",") +
+		" FROM kms_company AS com WHERE com.name IN (" +
+		nameQuery +
+		")"
+	return query
+}
+
+func selectAppCredentialByConsumerKey(consumerQuery string, colNames ...string) string {
+	query := "SELECT " +
+		strings.Join(colNames, ",") +
+		" FROM kms_app_credential AS ac WHERE ac.consumer_secret IN (" +
+		consumerQuery +
+		")"
+	return query
+}
+
+func filterApiProductsByResource(apiProducts []common.ApiProduct, resource string) []common.ApiProduct {
+	log.Debugf("Before filter: %v", apiProducts)
+	var prods []common.ApiProduct
+	for _, prod := range apiProducts {
+		resources := common.JsonToStringArray(prod.ApiResources)
+		if InSlice(resources, resource) {
+			prods = append(prods, prod)
+		}
+	}
+	log.Debugf("After filter: %v", prods)
+	return prods
+}
+
+func InSlice(sl []string, str string) bool {
+	for _, s := range sl {
+		if s == str {
+			return true
+		}
+	}
+	return false
+}
diff --git a/accessEntity/data_test.go b/accessEntity/data_test.go
new file mode 100644
index 0000000..4cf7b78
--- /dev/null
+++ b/accessEntity/data_test.go
@@ -0,0 +1,141 @@
+// Copyright 2017 Google 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 accessEntity
+
+import (
+	"github.com/apid/apid-core"
+	"github.com/apid/apidVerifyApiKey/common"
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+	"io/ioutil"
+	"sync"
+)
+
+const (
+	fileDataTest = "data_test.sql"
+)
+
+var _ = Describe("DataTest", func() {
+
+	Context("query Db to get entities", func() {
+		var dataTestTempDir string
+		var dbMan *DbManager
+		BeforeEach(func() {
+			var err error
+			dataTestTempDir, err = ioutil.TempDir(testTempDirBase, "sqlite3")
+			Expect(err).NotTo(HaveOccurred())
+			services.Config().Set("local_storage_path", dataTestTempDir)
+
+			dbMan = &DbManager{
+				DbManager: common.DbManager{
+					Data:  services.Data(),
+					DbMux: sync.RWMutex{},
+				},
+			}
+			dbMan.SetDbVersion(dataTestTempDir)
+		})
+
+		It("should get apiProducts", func() {
+			setupTestDb(dbMan.GetDb())
+			testData := [][]string{
+				//positive tests
+				{IdentifierApiProductName, "apstest", "", ""},
+				{IdentifierAppId, "408ad853-3fa0-402f-90ee-103de98d71a5", "", ""},
+				{IdentifierAppId, "408ad853-3fa0-402f-90ee-103de98d71a5", IdentifierApiResource, "/**"},
+				{IdentifierAppName, "apstest", "", ""},
+				{IdentifierConsumerKey, "abcd", "", ""},
+				{IdentifierConsumerKey, "abcd", IdentifierApiResource, "/**"},
+				{IdentifierAppName, "apstest", IdentifierDeveloperId, "e41f04e8-9d3f-470a-8bfd-c7939945896c"},
+				{IdentifierAppName, "apstest", IdentifierDeveloperEmail, "bar@google.com"},
+				{IdentifierAppName, "apstest", IdentifierCompanyName, "DevCompany"},
+				{IdentifierAppName, "apstest", IdentifierApiResource, "/**"},
+				// negative tests
+				{IdentifierApiProductName, "non-existent", "", ""},
+				{IdentifierAppId, "non-existent", "", ""},
+				{IdentifierAppId, "non-existent", IdentifierApiResource, "non-existent"},
+				{IdentifierAppName, "non-existent", "", ""},
+				{IdentifierConsumerKey, "non-existent", "", ""},
+				{IdentifierConsumerKey, "non-existent", IdentifierApiResource, "non-existent"},
+				{IdentifierAppName, "non-existent", IdentifierDeveloperId, "non-existent"},
+				{IdentifierAppName, "non-existent", IdentifierDeveloperEmail, "non-existent"},
+				{IdentifierAppName, "non-existent", IdentifierCompanyName, "non-existent"},
+				{IdentifierAppName, "non-existent", IdentifierApiResource, "non-existent"},
+			}
+
+			var expectedApiProd = common.ApiProduct{
+				Id:            "b7e0970c-4677-4b05-8105-5ea59fdcf4e7",
+				Name:          "apstest",
+				DisplayName:   "apstest",
+				Description:   "",
+				ApiResources:  "{/**}",
+				ApprovalType:  "AUTO",
+				Scopes:        `{""}`,
+				Proxies:       `{aps,perfBenchmark}`,
+				Environments:  `{prod,test}`,
+				Quota:         "10000000",
+				QuotaTimeUnit: "MINUTE",
+				QuotaInterval: 1,
+				CreatedAt:     "2017-08-18 22:12:49.363+00:00",
+				CreatedBy:     "haoming@apid.git",
+				UpdatedAt:     "2017-08-18 22:26:50.153+00:00",
+				UpdatedBy:     "haoming@apid.git",
+				TenantId:      "515211e9",
+			}
+
+			results := [][]common.ApiProduct{
+				{expectedApiProd},
+				{expectedApiProd},
+				{expectedApiProd},
+				{expectedApiProd},
+				{expectedApiProd},
+				{expectedApiProd},
+				{expectedApiProd},
+				{expectedApiProd},
+				{expectedApiProd},
+				{expectedApiProd},
+				nil,
+				nil,
+				nil,
+				nil,
+				nil,
+				nil,
+				nil,
+				nil,
+				nil,
+				nil,
+			}
+
+			for i, data := range testData {
+				priKey, priVal, secKey, secVal := data[0], data[1], data[2], data[3]
+				prods, err := dbMan.GetApiProducts(priKey, priVal, secKey, secVal)
+				Expect(err).Should(Succeed())
+				if len(results[i]) > 0 {
+					Expect(prods).Should(Equal(results[i]))
+				} else {
+					Expect(prods).Should(BeZero())
+				}
+			}
+		})
+	})
+
+})
+
+func setupTestDb(db apid.DB) {
+	bytes, err := ioutil.ReadFile(fileDataTest)
+	Expect(err).Should(Succeed())
+	query := string(bytes)
+	log.Debug(query)
+	_, err = db.Exec(query)
+	Expect(err).Should(Succeed())
+}
diff --git a/accessEntity/data_test.sql b/accessEntity/data_test.sql
new file mode 100644
index 0000000..9a774df
--- /dev/null
+++ b/accessEntity/data_test.sql
@@ -0,0 +1,40 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE kms_app (id text,tenant_id text,name text,display_name text,access_type text,callback_url text,status text,app_family text,company_id text,developer_id text,parent_id text,type text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
+INSERT INTO "kms_app" VALUES('408ad853-3fa0-402f-90ee-103de98d71a5','515211e9','apstest','','','','APPROVED','default','8ba5b747-5104-4a40-89ca-a0a51798fe34','e41f04e8-9d3f-470a-8bfd-c7939945896c','e41f04e8-9d3f-470a-8bfd-c7939945896c','DEVELOPER','2017-08-18 22:13:18.325+00:00','haoming@apid.git','2017-08-18 22:13:18.325+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_app" VALUES('ae053aee-f12d-4591-84ef-2e6ae0d4205d','515211e9','apigee-remote-proxy','','','','APPROVED','default','','590f33bf-f05c-48c1-bb93-183759bd9ee1','590f33bf-f05c-48c1-bb93-183759bd9ee1','DEVELOPER','2017-09-20 23:05:59.125+00:00','haoming@apid.git','2017-09-20 23:05:59.125+00:00','haoming@apid.git','515211e9');
+CREATE TABLE kms_attributes (tenant_id text,entity_id text,cust_id text,org_id text,dev_id text,comp_id text,apiprdt_id text,app_id text,appcred_id text,name text,type text,value text,_change_selector text, primary key (tenant_id,entity_id,name,type));
+INSERT INTO "kms_attributes" VALUES('515211e9','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','','','','','features.isSmbOrganization','ORGANIZATION','false','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','','','','','features.mgmtGroup','ORGANIZATION','management-edgex','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','','','','','features.isEdgexEnabled','ORGANIZATION','true','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','','','','','features.isCpsEnabled','ORGANIZATION','true','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','b7e0970c-4677-4b05-8105-5ea59fdcf4e7','','','','','b7e0970c-4677-4b05-8105-5ea59fdcf4e7','','','access','APIPRODUCT','public','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','408ad853-3fa0-402f-90ee-103de98d71a5','','','','','','408ad853-3fa0-402f-90ee-103de98d71a5','','DisplayName','APP','apstest','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','408ad853-3fa0-402f-90ee-103de98d71a5','','','','','','408ad853-3fa0-402f-90ee-103de98d71a5','','Notes','APP','','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','db90a25a-15c8-42ad-96c1-63ed9682b5a9','','','','','db90a25a-15c8-42ad-96c1-63ed9682b5a9','','','access','APIPRODUCT','public','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','','','','','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','DisplayName','APP','apigee-remote-proxy','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','','','','','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','Notes','APP','','515211e9');
+CREATE TABLE kms_company (id text,tenant_id text,name text,display_name text,status text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
+INSERT INTO "kms_company" VALUES('8ba5b747-5104-4a40-89ca-a0a51798fe34','5aa3e93f','DevCompany','East India Company','ACTIVE','2017-08-15 03:29:02.449+00:00','haoming@apid.git','2017-08-15 03:29:02.449+00:00','haoming@apid.git','5aa3e93f');
+CREATE TABLE kms_company_developer (tenant_id text,company_id text,developer_id text,roles text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (tenant_id,company_id,developer_id));
+CREATE TABLE kms_developer (id text,tenant_id text,username text,first_name text,last_name text,password text,email text,status text,encrypted_password text,salt text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
+INSERT INTO "kms_developer" VALUES('e41f04e8-9d3f-470a-8bfd-c7939945896c','515211e9','haoming','haoming','zhang','','bar@google.com','ACTIVE','','','2017-08-16 22:39:46.669+00:00','foo@google.com','2017-08-16 22:39:46.669+00:00','foo@google.com','515211e9');
+INSERT INTO "kms_developer" VALUES('47d862db-884f-4b8e-9649-fe6d0be1a739','515211e9','qwe','qwe','qwe','','barfoo@google.com','ACTIVE','','','2017-10-12 19:12:48.306+00:00','haoming@apid.git','2017-10-12 19:12:48.306+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_developer" VALUES('590f33bf-f05c-48c1-bb93-183759bd9ee1','515211e9','remoteproxy','remote','proxy','','fooo@google.com','ACTIVE','','','2017-09-20 23:03:52.327+00:00','haoming@apid.git','2017-09-20 23:03:52.327+00:00','haoming@apid.git','515211e9');
+CREATE TABLE edgex_apid_cluster (id text,name text,description text,umbrella_org_app_name text,created blob,created_by text,updated blob,updated_by text,_change_selector text, last_sequence text DEFAULT '', primary key (id));
+INSERT INTO "edgex_apid_cluster" VALUES('950b30f1-8c41-4bf5-94a3-f10c104ff5d4','edgex01OrgCluster','','X-sZXhaOymL6VtWnNQqK7uPsFyPvZYq6FFnrc8','2017-08-23 23:31:49.134+00:00','temp@google.com','2017-08-23 23:31:49.134+00:00','temp@google.com','950b30f1-8c41-4bf5-94a3-f10c104ff5d4','');
+CREATE TABLE kms_api_product (id text,tenant_id text,name text,display_name text,description text,api_resources text,approval_type text,scopes text,proxies text,environments text,quota text,quota_time_unit text,quota_interval integer,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
+INSERT INTO "kms_api_product" VALUES('b7e0970c-4677-4b05-8105-5ea59fdcf4e7','515211e9','apstest','apstest','','{/**}','AUTO','{""}','{aps,perfBenchmark}','{prod,test}','10000000','MINUTE',1,'2017-08-18 22:12:49.363+00:00','haoming@apid.git','2017-08-18 22:26:50.153+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_api_product" VALUES('8501392f-c5f7-4d6a-8841-e038ad5913b4','515211e9','ApigeenTestApp','ApigeenTestApp','','{/}','AUTO','{scope1,scope2,scope3}','{}','{prod,test}','','',NULL,'2017-09-20 22:29:06.451+00:00','haoming@apid.git','2017-09-20 22:29:06.451+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_api_product" VALUES('e4ae89d0-ea47-4b23-b0dc-2723efb15c84','515211e9','ApigeenTestApp2','ApigeenTestApp2','','{/}','AUTO','{scope1,scope2,scope3}','{}','{prod,test}','','',NULL,'2017-09-20 22:29:08.988+00:00','haoming@apid.git','2017-09-20 22:29:08.988+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_api_product" VALUES('07419482-e5a1-4fd0-9d78-3560ba522b44','515211e9','ApigeenTestApp3','ApigeenTestApp3','','{/}','AUTO','{}','{}','{prod,test}','','',NULL,'2017-09-20 22:29:11.482+00:00','haoming@apid.git','2017-09-20 22:29:11.482+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_api_product" VALUES('db90a25a-15c8-42ad-96c1-63ed9682b5a9','515211e9','apigee-remote-proxy','apigee-remote-proxy','','{/**,/}','AUTO','{""}','{apigee-remote-proxy}','{prod,test}','','',NULL,'2017-09-20 23:05:09.234+00:00','haoming@apid.git','2017-09-20 23:05:09.234+00:00','haoming@apid.git','515211e9');
+CREATE TABLE kms_app_credential (id text,tenant_id text,consumer_secret text,app_id text,method_type text,status text,issued_at blob,expires_at blob,app_status text,scopes text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
+INSERT INTO "kms_app_credential" VALUES('qUQLHViLHm9a4L623DSnmZohz6m7C83C','515211e9','abcd','408ad853-3fa0-402f-90ee-103de98d71a5','','APPROVED','2017-08-18 22:13:18.35+00:00','','','{}','2017-08-18 22:13:18.35+00:00','-NA-','2017-08-18 22:13:18.352+00:00','-NA-','515211e9');
+INSERT INTO "kms_app_credential" VALUES('00A0RcOti8kEtstbt5knxbRXFpIUGOMP','515211e9','dcba','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','APPROVED','2017-09-20 23:05:59.148+00:00','','','{}','2017-09-20 23:05:59.148+00:00','-NA-','2017-09-20 23:05:59.151+00:00','-NA-','515211e9');
+CREATE TABLE kms_app_credential_apiproduct_mapper (tenant_id text,appcred_id text,app_id text,apiprdt_id text,status text,_change_selector text, primary key (tenant_id,appcred_id,app_id,apiprdt_id));
+INSERT INTO "kms_app_credential_apiproduct_mapper" VALUES('515211e9','qUQLHViLHm9a4L623DSnmZohz6m7C83C','408ad853-3fa0-402f-90ee-103de98d71a5','b7e0970c-4677-4b05-8105-5ea59fdcf4e7','APPROVED','515211e9');
+INSERT INTO "kms_app_credential_apiproduct_mapper" VALUES('515211e9','00A0RcOti8kEtstbt5knxbRXFpIUGOMP','ae053aee-f12d-4591-84ef-2e6ae0d4205d','db90a25a-15c8-42ad-96c1-63ed9682b5a9','APPROVED','515211e9');
+CREATE TABLE kms_organization (id text,name text,display_name text,type text,tenant_id text,customer_id text,description text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
+INSERT INTO "kms_organization" VALUES('e2cc4caf-40d6-4ecb-8149-ed32d04184b2','edgex01','edgex01','paid','515211e9','94cd5075-7f33-4afb-9545-a53a254277a1','','2017-08-16 22:16:06.544+00:00','foobar@google.com','2017-08-16 22:29:23.046+00:00','foobar@google.com','515211e9');
+COMMIT;
diff --git a/accessEntity/init.go b/accessEntity/init.go
index d61042c..ed5de94 100644
--- a/accessEntity/init.go
+++ b/accessEntity/init.go
@@ -1 +1,28 @@
+// Copyright 2017 Google 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 accessEntity
+
+import (
+	"github.com/apid/apid-core"
+)
+
+var (
+	services apid.Services
+	log      apid.LogService
+)
+
+func SetApidServices(s apid.Services, l apid.LogService) {
+	services = s
+	log = l
+}
diff --git a/accessEntity/interfaces.go b/accessEntity/interfaces.go
new file mode 100644
index 0000000..da5c25e
--- /dev/null
+++ b/accessEntity/interfaces.go
@@ -0,0 +1,16 @@
+package accessEntity
+
+import (
+	"github.com/apid/apidVerifyApiKey/common"
+	"net/http"
+)
+
+type ApiManagerInterface interface {
+	common.ApiManagerInterface
+	HandleRequest(w http.ResponseWriter, r *http.Request)
+}
+
+type DbManagerInterface interface {
+	common.DbManagerInterface
+	GetApiProducts(priKey, priVal, secKey, secVal string) (apiProducts []common.ApiProduct, err error)
+}
diff --git a/accessEntity/manager_interfaces.go b/accessEntity/manager_interfaces.go
deleted file mode 100644
index 07746ca..0000000
--- a/accessEntity/manager_interfaces.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package accessEntity
-
-import (
-	"net/http"
-	"github.com/apid/apid-core"
-)
-
-type ApiManagerInterface interface {
-	InitAPI()
-	HandleRequest(w http.ResponseWriter, r *http.Request)
-}
-
-type DbManagerInterface interface {
-	SetDbVersion(string)
-	GetDb() apid.DB
-	GetDbVersion() string
-}
\ No newline at end of file
diff --git a/common/data.go b/common/data.go
index b750195..9a824a8 100644
--- a/common/data.go
+++ b/common/data.go
@@ -2,9 +2,11 @@
 
 import (
 	"database/sql"
+	"encoding/json"
 	"github.com/apid/apid-core"
 	"strings"
 	"sync"
+	"unicode/utf8"
 )
 
 type DbManager struct {
@@ -82,3 +84,17 @@
 	log.Debug("attributes returned for query ", sql, " are ", mapOfAttributes)
 	return mapOfAttributes
 }
+
+func JsonToStringArray(fjson string) []string {
+	var array []string
+	if err := json.Unmarshal([]byte(fjson), &array); err == nil {
+		return array
+	}
+	s := strings.TrimPrefix(fjson, "{")
+	s = strings.TrimSuffix(s, "}")
+	if utf8.RuneCountInString(s) > 0 {
+		array = strings.Split(s, ",")
+	}
+	log.Debug("unmarshall error for string, performing custom unmarshal ", fjson, " and result is : ", array)
+	return array
+}
diff --git a/common/data_structs.go b/common/data_structs.go
index 2a319fd..13dc1e9 100644
--- a/common/data_structs.go
+++ b/common/data_structs.go
@@ -47,6 +47,7 @@
 	CreatedBy     string `db:"created_by"`
 	UpdatedAt     string `db:"updated_at"`
 	UpdatedBy     string `db:"updated_by"`
+	TenantId      string `db:"tenant_id"`
 }
 
 type App struct {
diff --git a/interfaces.go b/common/interfaces.go
similarity index 88%
rename from interfaces.go
rename to common/interfaces.go
index 0974bbd..dda46f3 100644
--- a/interfaces.go
+++ b/common/interfaces.go
@@ -11,20 +11,19 @@
 // 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 apidVerifyApiKey
+package common
 
 import (
 	"github.com/apid/apid-core"
-	"net/http"
 )
 
 type ApiManagerInterface interface {
 	InitAPI()
-	HandleRequest(w http.ResponseWriter, r *http.Request)
 }
 
 type DbManagerInterface interface {
 	SetDbVersion(string)
 	GetDb() apid.DB
 	GetDbVersion() string
+	GetKmsAttributes(tenantId string, entities ...string) map[string][]Attribute
 }
diff --git a/glide.yaml b/glide.yaml
index da46400..936dfe3 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -15,7 +15,7 @@
 package: github.com/apid/apidVerifyApiKey
 import:
 - package: github.com/apid/apid-core
-  version: master
+  version: ISSUE-68272561
 - package: github.com/apid/apidApigeeSync
   version: master
 testImport:
diff --git a/init.go b/init.go
index 5131f64..37fecd3 100644
--- a/init.go
+++ b/init.go
@@ -38,7 +38,13 @@
 	accessEntity.SetApidServices(services, log)
 	common.SetApidServices(services, log)
 	log.Debug("start init")
+	initManagers(services)
+	log.Debug("end init")
 
+	return pluginData, nil
+}
+
+func initManagers(services apid.Services) apigeeSyncHandler {
 	verifyDbMan := &verifyApiKey.DbManager{
 		DbManager: common.DbManager{
 			Data:  services.Data(),
@@ -50,14 +56,22 @@
 		VerifiersEndpoint: verifyApiKey.ApiPath,
 	}
 
-	syncHandler := apigeeSyncHandler{
-		dbMans:  []DbManagerInterface{verifyDbMan},
-		apiMans: []ApiManagerInterface{verifyApiMan},
+	entityDbMan := &accessEntity.DbManager{
+		DbManager: common.DbManager{
+			Data:  services.Data(),
+			DbMux: sync.RWMutex{},
+		},
 	}
 
+	entityApiMan := &accessEntity.ApiManager{
+		DbMan:            entityDbMan,
+		AccessEntityPath: accessEntity.AccessEntityPath,
+	}
+
+	syncHandler := apigeeSyncHandler{
+		dbMans:  []common.DbManagerInterface{verifyDbMan, entityDbMan},
+		apiMans: []common.ApiManagerInterface{verifyApiMan, entityApiMan},
+	}
 	syncHandler.initListener(services)
-
-	log.Debug("end init")
-
-	return pluginData, nil
+	return syncHandler
 }
diff --git a/listener.go b/listener.go
index 5174026..7f2ec69 100644
--- a/listener.go
+++ b/listener.go
@@ -16,7 +16,8 @@
 
 import (
 	"github.com/apid/apid-core"
-	"github.com/apigee-labs/transicator/common"
+	"github.com/apid/apidVerifyApiKey/common"
+	tran "github.com/apigee-labs/transicator/common"
 )
 
 const (
@@ -24,8 +25,8 @@
 )
 
 type apigeeSyncHandler struct {
-	dbMans  []DbManagerInterface
-	apiMans []ApiManagerInterface
+	dbMans  []common.DbManagerInterface
+	apiMans []common.ApiManagerInterface
 }
 
 func (h *apigeeSyncHandler) initListener(services apid.Services) {
@@ -36,7 +37,7 @@
 	return "verifyAPIKey"
 }
 
-func (h *apigeeSyncHandler) processSnapshot(snapshot *common.Snapshot) {
+func (h *apigeeSyncHandler) processSnapshot(snapshot *tran.Snapshot) {
 	log.Debugf("Snapshot received. Switching to DB version: %s", snapshot.SnapshotInfo)
 	// set db version for all packages
 	for _, dbMan := range h.dbMans {
@@ -51,7 +52,7 @@
 
 func (h *apigeeSyncHandler) Handle(e apid.Event) {
 
-	if snapData, ok := e.(*common.Snapshot); ok {
+	if snapData, ok := e.(*tran.Snapshot); ok {
 		h.processSnapshot(snapData)
 	} else {
 		log.Debugf("Received event. No action required for verifyApiKey plugin. Ignoring. %v", e)
diff --git a/listener_test.go b/listener_test.go
index a4689c4..c82b96a 100644
--- a/listener_test.go
+++ b/listener_test.go
@@ -17,13 +17,11 @@
 import (
 	"github.com/apid/apid-core"
 	"github.com/apid/apid-core/factory"
-	"github.com/apid/apidVerifyApiKey/verifyApiKey"
-	"github.com/apigee-labs/transicator/common"
+	tran "github.com/apigee-labs/transicator/common"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 	"io/ioutil"
 	"os"
-	"sync"
 )
 
 var _ = Describe("listener", func() {
@@ -40,22 +38,7 @@
 		Expect(err).NotTo(HaveOccurred())
 
 		apid.InitializePlugins("")
-
-		db, err := apid.Data().DB()
-		Expect(err).NotTo(HaveOccurred())
-
-		dbMan := &verifyApiKey.DbManager{
-			Data:  s.Data(),
-			DbMux: sync.RWMutex{},
-			Db:    db,
-		}
-
-		listnerTestSyncHandler = apigeeSyncHandler{
-			dbMans:  []DbManagerInterface{dbMan},
-			apiMans: []ApiManagerInterface{&verifyApiKey.ApiManager{}},
-		}
-
-		listnerTestSyncHandler.initListener(s)
+		listnerTestSyncHandler = initManagers(s)
 	})
 
 	var _ = AfterEach(func() {
@@ -65,9 +48,9 @@
 	Context("Apigee Sync Event Processing", func() {
 
 		It("should set DB to appropriate version", func() {
-			s := &common.Snapshot{
+			s := &tran.Snapshot{
 				SnapshotInfo: "test_snapshot",
-				Tables:       []common.Table{},
+				Tables:       []tran.Table{},
 			}
 			listnerTestSyncHandler.Handle(s)
 			for _, dbMan := range listnerTestSyncHandler.dbMans {
@@ -79,7 +62,7 @@
 		It("should not change version for chang event", func() {
 
 			version := listnerTestSyncHandler.dbMans[0].GetDbVersion()
-			s := &common.Change{
+			s := &tran.Change{
 				ChangeSequence: 12321,
 				Table:          "",
 			}
diff --git a/verifyApiKey/data.go b/verifyApiKey/data.go
index 56ae2d2..769a92d 100644
--- a/verifyApiKey/data.go
+++ b/verifyApiKey/data.go
@@ -15,15 +15,11 @@
 
 import (
 	"errors"
-	"github.com/apid/apid-core"
 	"github.com/apid/apidVerifyApiKey/common"
 )
 
 type DbManagerInterface interface {
-	SetDbVersion(string)
-	GetDb() apid.DB
-	GetDbVersion() string
-	GetKmsAttributes(tenantId string, entities ...string) map[string][]common.Attribute
+	common.DbManagerInterface
 	getApiKeyDetails(dataWrapper *VerifyApiKeyRequestResponseDataWrapper) error
 }
 
@@ -113,9 +109,9 @@
 			&environments,
 			&resources,
 		)
-		apiProductDetais.Apiproxies = jsonToStringArray(proxies)
-		apiProductDetais.Environments = jsonToStringArray(environments)
-		apiProductDetais.Resources = jsonToStringArray(resources)
+		apiProductDetais.Apiproxies = common.JsonToStringArray(proxies)
+		apiProductDetais.Environments = common.JsonToStringArray(environments)
+		apiProductDetais.Resources = common.JsonToStringArray(resources)
 
 		allProducts = append(allProducts, apiProductDetais)
 	}
diff --git a/verifyApiKey/verifyApiKeyUtil.go b/verifyApiKey/verifyApiKeyUtil.go
index ee571b5..85aa8c5 100644
--- a/verifyApiKey/verifyApiKeyUtil.go
+++ b/verifyApiKey/verifyApiKeyUtil.go
@@ -15,10 +15,8 @@
 package verifyApiKey
 
 import (
-	"encoding/json"
 	"regexp"
 	"strings"
-	"unicode/utf8"
 )
 
 /*
@@ -56,20 +54,6 @@
 	return len(fs) == 0
 }
 
-func jsonToStringArray(fjson string) []string {
-	var array []string
-	if err := json.Unmarshal([]byte(fjson), &array); err == nil {
-		return array
-	}
-	s := strings.TrimPrefix(fjson, "{")
-	s = strings.TrimSuffix(s, "}")
-	if utf8.RuneCountInString(s) > 0 {
-		array = strings.Split(s, ",")
-	}
-	log.Debug("unmarshall error for string, performing custom unmarshal ", fjson, " and result is : ", array)
-	return array
-}
-
 func contains(givenArray []string, searchString string) bool {
 	for _, element := range givenArray {
 		if element == searchString {
diff --git a/verifyApiKey/verifyApiKeyUtil_test.go b/verifyApiKey/verifyApiKeyUtil_test.go
index 95aef55..0ff7f22 100644
--- a/verifyApiKey/verifyApiKeyUtil_test.go
+++ b/verifyApiKey/verifyApiKeyUtil_test.go
@@ -15,6 +15,7 @@
 package verifyApiKey
 
 import (
+	"github.com/apid/apidVerifyApiKey/common"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 	"reflect"
@@ -40,30 +41,30 @@
 	})
 })
 
-var _ = Describe("Validate jsonToStringArray", func() {
+var _ = Describe("Validate common.JsonToStringArray", func() {
 
 	It("should tranform simple valid json", func() {
-		array := jsonToStringArray("[\"test-1\", \"test-2\"]")
+		array := common.JsonToStringArray("[\"test-1\", \"test-2\"]")
 		Expect(reflect.DeepEqual(array, []string{"test-1", "test-2"})).Should(BeTrue())
 	})
 	It("should tranform simple single valid json", func() {
-		array := jsonToStringArray("[\"test-1\"]")
+		array := common.JsonToStringArray("[\"test-1\"]")
 		Expect(reflect.DeepEqual(array, []string{"test-1"})).Should(BeTrue())
 	})
 	It("should tranform simple fake json", func() {
-		s := jsonToStringArray("{test-1,test-2}")
+		s := common.JsonToStringArray("{test-1,test-2}")
 		Expect(reflect.DeepEqual(s, []string{"test-1", "test-2"})).Should(BeTrue())
 	})
 	It("should tranform simple single valued fake json", func() {
-		s := jsonToStringArray("{test-1}")
+		s := common.JsonToStringArray("{test-1}")
 		Expect(reflect.DeepEqual(s, []string{"test-1"})).Should(BeTrue())
 	})
 	It("space between fields considered as valid char", func() {
-		s := jsonToStringArray("{test-1, test-2}")
+		s := common.JsonToStringArray("{test-1, test-2}")
 		Expect(reflect.DeepEqual(s, []string{"test-1", " test-2"})).Should(BeTrue())
 	})
 	It("remove only last braces", func() {
-		s := jsonToStringArray("{test-1,test-2}}")
+		s := common.JsonToStringArray("{test-1,test-2}}")
 		Expect(reflect.DeepEqual(s, []string{"test-1", "test-2}"})).Should(BeTrue())
 	})