| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 org.apache.ranger.service; |
| |
| import java.lang.reflect.ParameterizedType; |
| import java.lang.reflect.TypeVariable; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import javax.persistence.EntityManager; |
| import javax.persistence.Query; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.ranger.biz.RangerBizUtil; |
| import org.apache.ranger.common.ContextUtil; |
| import org.apache.ranger.common.DateUtil; |
| import org.apache.ranger.common.MessageEnums; |
| import org.apache.ranger.common.RESTErrorUtil; |
| import org.apache.ranger.common.RangerSearchUtil; |
| import org.apache.ranger.common.SearchField; |
| import org.apache.ranger.common.SortField; |
| import org.apache.ranger.common.StringUtil; |
| import org.apache.ranger.common.db.BaseDao; |
| import org.apache.ranger.common.view.VList; |
| import org.apache.ranger.db.RangerDaoManager; |
| import org.apache.ranger.entity.XXAccessTypeDef; |
| import org.apache.ranger.entity.XXDBBase; |
| import org.apache.ranger.entity.XXGroup; |
| import org.apache.ranger.entity.XXPolicyConditionDef; |
| import org.apache.ranger.entity.XXPortalUser; |
| import org.apache.ranger.entity.XXResourceDef; |
| import org.apache.ranger.plugin.model.RangerBaseModelObject; |
| import org.apache.ranger.plugin.store.PList; |
| import org.apache.ranger.plugin.util.SearchFilter; |
| import org.springframework.beans.factory.annotation.Autowired; |
| |
| public abstract class RangerBaseModelService<T extends XXDBBase, V extends RangerBaseModelObject> { |
| private static final Log LOG = LogFactory |
| .getLog(RangerBaseModelService.class); |
| |
| @Autowired |
| protected RangerDaoManager daoMgr; |
| |
| @Autowired |
| protected StringUtil stringUtil; |
| |
| @Autowired |
| protected RESTErrorUtil restErrorUtil; |
| |
| @Autowired |
| protected RangerSearchUtil searchUtil; |
| |
| @Autowired |
| RangerBizUtil bizUtil; |
| |
| public static final int OPERATION_CREATE_CONTEXT = 1; |
| public static final int OPERATION_UPDATE_CONTEXT = 2; |
| public static final int OPERATION_DELETE_CONTEXT = 3; |
| |
| protected Class<T> tEntityClass; |
| protected Class<V> tViewClass; |
| private Boolean populateExistingBaseFields; |
| protected String tClassName; |
| |
| public List<SortField> sortFields = new ArrayList<SortField>(); |
| public List<SearchField> searchFields = new ArrayList<SearchField>(); |
| protected final String countQueryStr; |
| protected String queryStr; |
| |
| BaseDao<T> entityDao; |
| |
| @SuppressWarnings("unchecked") |
| public RangerBaseModelService() { |
| Class klass = getClass(); |
| ParameterizedType genericSuperclass = (ParameterizedType) klass |
| .getGenericSuperclass(); |
| TypeVariable<Class<?>> var[] = klass.getTypeParameters(); |
| |
| if (genericSuperclass.getActualTypeArguments()[0] instanceof Class) { |
| tEntityClass = (Class<T>) genericSuperclass |
| .getActualTypeArguments()[0]; |
| tViewClass = (Class<V>) genericSuperclass.getActualTypeArguments()[1]; |
| } else if (var.length > 0) { |
| tEntityClass = (Class<T>) var[0].getBounds()[0]; |
| tViewClass = (Class<V>) var[1].getBounds()[0]; |
| } else { |
| LOG.fatal("Cannot find class for template", new Throwable()); |
| } |
| |
| if (tEntityClass != null) { |
| tClassName = tEntityClass.getName(); |
| } |
| |
| populateExistingBaseFields = false; |
| |
| countQueryStr = "SELECT COUNT(obj) FROM " + tClassName + " obj "; |
| queryStr = "SELECT obj FROM " + tClassName + " obj "; |
| } |
| |
| protected abstract T mapViewToEntityBean(V viewBean, T t, |
| int OPERATION_CONTEXT); |
| |
| protected abstract V mapEntityToViewBean(V viewBean, T t); |
| |
| protected T createEntityObject() { |
| try { |
| return tEntityClass.newInstance(); |
| } catch (Throwable e) { |
| LOG.error("Error instantiating entity class. tEntityClass=" |
| + tEntityClass.toString(), e); |
| } |
| return null; |
| } |
| |
| protected V createViewObject() { |
| try { |
| return tViewClass.newInstance(); |
| } catch (Throwable e) { |
| LOG.error("Error instantiating view class. tViewClass=" |
| + tViewClass.toString(), e); |
| } |
| return null; |
| } |
| |
| @SuppressWarnings("unchecked") |
| protected BaseDao<T> getDao() { |
| if (entityDao == null) { |
| entityDao = (BaseDao<T>) daoMgr.getDaoForClassName(tEntityClass |
| .getSimpleName()); |
| |
| } |
| return entityDao; |
| } |
| |
| protected V populateViewBean(T entityObj) { |
| V vObj = createViewObject(); |
| vObj.setId(entityObj.getId()); |
| vObj.setCreateTime(entityObj.getCreateTime()); |
| vObj.setUpdateTime(entityObj.getUpdateTime()); |
| vObj.setCreatedBy(getUserScreenName(entityObj.getAddedByUserId())); |
| vObj.setUpdatedBy(getUserScreenName(entityObj.getUpdatedByUserId())); |
| |
| return mapEntityToViewBean(vObj, entityObj); |
| } |
| |
| protected T populateEntityBeanForCreate(T entityObj, V vObj) { |
| if(!populateExistingBaseFields) { |
| entityObj.setCreateTime(DateUtil.getUTCDate()); |
| entityObj.setUpdateTime(entityObj.getCreateTime()); |
| entityObj.setAddedByUserId(ContextUtil.getCurrentUserId()); |
| entityObj.setUpdatedByUserId(entityObj.getAddedByUserId()); |
| } else if(populateExistingBaseFields) { |
| XXPortalUser createdByUser = daoMgr.getXXPortalUser().findByLoginId(vObj.getCreatedBy()); |
| XXPortalUser updByUser = daoMgr.getXXPortalUser().findByLoginId(vObj.getUpdatedBy()); |
| |
| entityObj.setId(vObj.getId()); |
| entityObj.setCreateTime(vObj.getCreateTime() != null ? vObj.getCreateTime() : DateUtil.getUTCDate()); |
| entityObj.setUpdateTime(vObj.getUpdateTime() != null ? vObj.getUpdateTime() : DateUtil.getUTCDate()); |
| entityObj.setAddedByUserId(createdByUser != null ? createdByUser.getId() : ContextUtil.getCurrentUserId()); |
| entityObj.setUpdatedByUserId(updByUser != null ? updByUser.getId() : ContextUtil.getCurrentUserId()); |
| } |
| |
| return mapViewToEntityBean(vObj, entityObj, OPERATION_CREATE_CONTEXT); |
| } |
| |
| protected T populateEntityBeanForUpdate(T entityObj, V vObj) { |
| if (entityObj == null) { |
| throw restErrorUtil.createRESTException( |
| "No Object found to update.", |
| MessageEnums.DATA_NOT_FOUND); |
| } |
| |
| T ret = mapViewToEntityBean(vObj, entityObj, OPERATION_UPDATE_CONTEXT); |
| |
| if (ret.getCreateTime() == null) { |
| ret.setCreateTime(DateUtil.getUTCDate()); |
| } |
| |
| if (ret.getAddedByUserId() == null) { |
| ret.setAddedByUserId(ContextUtil.getCurrentUserId()); |
| } |
| |
| if(!populateExistingBaseFields) { |
| ret.setUpdateTime(DateUtil.getUTCDate()); |
| ret.setUpdatedByUserId(ContextUtil.getCurrentUserId()); |
| } |
| |
| return ret; |
| } |
| |
| protected abstract void validateForCreate(V vObj); |
| |
| protected abstract void validateForUpdate(V vObj, T entityObj); |
| |
| public T preCreate(V vObj) { |
| validateForCreate(vObj); |
| |
| T entityObj = createEntityObject(); |
| |
| return populateEntityBeanForCreate(entityObj, vObj); |
| } |
| |
| public V postCreate(T xObj) { |
| return populateViewBean(xObj); |
| } |
| |
| public V create(V vObj) { |
| T resource = preCreate(vObj); |
| resource = getDao().create(resource); |
| vObj = postCreate(resource); |
| return vObj; |
| } |
| |
| public V read(Long id) { |
| T resource = getDao().getById(id); |
| if (resource == null) { |
| throw restErrorUtil.createRESTException(tViewClass.getName() |
| + " :Data Not Found for given Id", |
| MessageEnums.DATA_NOT_FOUND, id, null, |
| "readResource : No Object found with given id."); |
| } |
| return populateViewBean(resource); |
| } |
| |
| public V update(V viewBaseBean) { |
| T resource = preUpdate(viewBaseBean); |
| resource = getDao().update(resource); |
| V viewBean = postUpdate(resource); |
| return viewBean; |
| } |
| |
| public V postUpdate(T resource) { |
| return populateViewBean(resource); |
| } |
| |
| public T preUpdate(V viewBaseBean) { |
| T resource = getDao().getById(viewBaseBean.getId()); |
| if (resource == null) { |
| throw restErrorUtil.createRESTException(tEntityClass.getSimpleName() |
| + " not found", MessageEnums.DATA_NOT_FOUND, |
| viewBaseBean.getId(), null, "preUpdate: id not found."); |
| } |
| validateForUpdate(viewBaseBean, resource); |
| return populateEntityBeanForUpdate(resource, viewBaseBean); |
| } |
| |
| public boolean delete(V vObj) { |
| boolean result = false; |
| Long id = vObj.getId(); |
| T resource = preDelete(id); |
| if (resource == null) { |
| throw restErrorUtil.createRESTException( |
| tEntityClass.getSimpleName() + " not found", |
| MessageEnums.DATA_NOT_FOUND, id, null, |
| tEntityClass.getSimpleName() + ":" + id); |
| } |
| try { |
| result = getDao().remove(resource); |
| } catch (Exception e) { |
| LOG.error("Error deleting " + tEntityClass.getSimpleName() |
| + ". Id=" + id, e); |
| |
| throw restErrorUtil.createRESTException( |
| tEntityClass.getSimpleName() + " can't be deleted", |
| MessageEnums.OPER_NOT_ALLOWED_FOR_STATE, id, null, "" + id |
| + ", error=" + e.getMessage()); |
| } |
| return result; |
| } |
| |
| protected T preDelete(Long id) { |
| T resource = getDao().getById(id); |
| if (resource == null) { |
| // Return without error |
| LOG.info("Delete ignored for non-existent Object, id=" + id); |
| } |
| return resource; |
| } |
| |
| public Boolean getPopulateExistingBaseFields() { |
| return populateExistingBaseFields; |
| } |
| |
| public void setPopulateExistingBaseFields(Boolean populateExistingBaseFields) { |
| this.populateExistingBaseFields = populateExistingBaseFields; |
| } |
| |
| /* |
| * Search Operations |
| * |
| */ |
| |
| public List<T> searchResources(SearchFilter searchCriteria, |
| List<SearchField> searchFieldList, List<SortField> sortFieldList, |
| VList vList) { |
| |
| // Get total count of the rows which meet the search criteria |
| long count = -1; |
| if (searchCriteria.isGetCount()) { |
| count = getCountForSearchQuery(searchCriteria, searchFieldList); |
| if (count == 0) { |
| return Collections.emptyList(); |
| } |
| } |
| |
| String sortClause = searchUtil.constructSortClause(searchCriteria, sortFieldList); |
| |
| String q = queryStr; |
| Query query = createQuery(q, sortClause, searchCriteria, searchFieldList, false); |
| |
| List<T> resultList = getDao().executeQueryInSecurityContext(tEntityClass, query); |
| |
| if (vList != null) { |
| vList.setResultSize(resultList.size()); |
| vList.setPageSize(query.getMaxResults()); |
| vList.setSortBy(searchCriteria.getSortBy()); |
| vList.setSortType(searchCriteria.getSortType()); |
| vList.setStartIndex(query.getFirstResult()); |
| vList.setTotalCount(count); |
| } |
| return resultList; |
| } |
| |
| protected List<T> searchRangerObjects(SearchFilter searchCriteria, List<SearchField> searchFieldList, List<SortField> sortFieldList, PList<V> pList) { |
| |
| // Get total count of the rows which meet the search criteria |
| long count = -1; |
| if (searchCriteria.isGetCount()) { |
| count = getCountForSearchQuery(searchCriteria, searchFieldList); |
| if (count == 0) { |
| return Collections.emptyList(); |
| } |
| } |
| |
| String sortClause = searchUtil.constructSortClause(searchCriteria, sortFieldList); |
| |
| String q = queryStr; |
| Query query = createQuery(q, sortClause, searchCriteria, searchFieldList, false); |
| |
| List<T> resultList = getDao().executeQueryInSecurityContext(tEntityClass, query); |
| |
| if (pList != null) { |
| pList.setResultSize(resultList.size()); |
| pList.setPageSize(query.getMaxResults()); |
| pList.setSortBy(searchCriteria.getSortBy()); |
| pList.setSortType(searchCriteria.getSortType()); |
| pList.setStartIndex(query.getFirstResult()); |
| pList.setTotalCount(count); |
| } |
| return resultList; |
| } |
| |
| protected long getCountForSearchQuery(SearchFilter searchCriteria, List<SearchField> searchFieldList) { |
| |
| String q = countQueryStr; |
| Query query = createQuery(q, null, searchCriteria, searchFieldList, true); |
| Long count = getDao().executeCountQueryInSecurityContext(tEntityClass, query); |
| |
| if (count == null) { |
| return 0; |
| } |
| return count.longValue(); |
| } |
| |
| protected Query createQuery(String searchString, String sortString, SearchFilter searchCriteria, |
| List<SearchField> searchFieldList, boolean isCountQuery) { |
| |
| EntityManager em = getDao().getEntityManager(); |
| Query query = searchUtil.createSearchQuery(em, searchString, sortString, searchCriteria, |
| searchFieldList, getClassType(), false, isCountQuery); |
| return query; |
| } |
| |
| protected int getClassType() { |
| return bizUtil.getClassType(tEntityClass); |
| } |
| |
| |
| protected String getUserScreenName(Long userId) { |
| String ret = null; |
| |
| XXPortalUser xPortalUser = userId == null ? null : daoMgr.getXXPortalUser().getById(userId); |
| |
| if(xPortalUser != null) { |
| ret = xPortalUser.getPublicScreenName(); |
| |
| if (stringUtil.isEmpty(ret)) { |
| ret = xPortalUser.getFirstName(); |
| |
| if(stringUtil.isEmpty(ret)) { |
| ret = xPortalUser.getLoginId(); |
| } else { |
| if(!stringUtil.isEmpty(xPortalUser.getLastName())) { |
| ret += (" " + xPortalUser.getLastName()); |
| } |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| protected String getUserName(Long userId) { |
| String ret = null; |
| |
| XXPortalUser xPortalUser = userId == null ? null : daoMgr.getXXPortalUser().getById(userId); |
| |
| if(xPortalUser != null) { |
| ret = xPortalUser.getLoginId(); |
| } |
| |
| return ret; |
| } |
| |
| protected String getGroupName(Long groupId) { |
| String ret = null; |
| |
| XXGroup xGroup = groupId == null ? null : daoMgr.getXXGroup().getById(groupId); |
| |
| if(xGroup != null) { |
| ret = xGroup.getName(); |
| } |
| |
| return ret; |
| } |
| |
| protected String getAccessTypeName(Long accessTypeDefId) { |
| String ret = null; |
| |
| XXAccessTypeDef accessTypeDef = accessTypeDefId == null ? null : daoMgr.getXXAccessTypeDef().getById(accessTypeDefId); |
| |
| if(accessTypeDef != null) { |
| ret = accessTypeDef.getName(); |
| } |
| |
| return ret; |
| } |
| |
| protected String getConditionName(Long conditionDefId) { |
| String ret = null; |
| |
| XXPolicyConditionDef conditionDef = conditionDefId == null ? null : daoMgr.getXXPolicyConditionDef().getById(conditionDefId); |
| |
| if(conditionDef != null) { |
| ret = conditionDef.getName(); |
| } |
| |
| return ret; |
| } |
| |
| protected String getResourceName(Long resourceDefId) { |
| String ret = null; |
| |
| XXResourceDef resourceDef = resourceDefId == null ? null : daoMgr.getXXResourceDef().getById(resourceDefId); |
| |
| if(resourceDef != null) { |
| ret = resourceDef.getName(); |
| } |
| |
| return ret; |
| } |
| } |