/*
* Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package org.entando.entando.aps.system.services.api;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.entando.entando.aps.system.services.api.model.ApiMethod;
import org.entando.entando.aps.system.services.api.model.ApiMethodRelatedWidget;
import org.entando.entando.aps.system.services.api.model.ApiResource;
import org.entando.entando.aps.system.services.api.model.ApiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.agiletec.aps.system.common.AbstractService;
import com.agiletec.aps.system.exception.ApsSystemException;
/**
* @author E.Santoboni
*/
public class ApiCatalogManager extends AbstractService implements IApiCatalogManager {
private static final Logger _logger = LoggerFactory.getLogger(ApiCatalogManager.class);
@Override
public void init() throws Exception {
_logger.debug("{} ready.", this.getClass().getName());
}
@Override
protected void release() {
super.release();
this.setMasterResources(null);
this.setMasterServices(null);
}
protected void loadResources() throws ApsSystemException {
try {
ApiResourceLoader loader = new ApiResourceLoader(this.getLocationPatterns());
Map<String, ApiResource> resources = loader.getResources();
this.setMasterResources(resources);
_logger.debug("{}: initialized Api Methods", this.getClass().getName());
this.getApiCatalogDAO().loadApiStatus(resources);
} catch (Throwable t) {
_logger.error("Error loading Api Resources definitions", t);
throw new ApsSystemException("Error loading Api Resources definitions", t);
}
}
protected void loadServices() throws ApsSystemException {
try {
if (null == this.getMasterResources()) {
this.loadResources();
}
List<ApiMethod> apiGETMethods = new ArrayList<ApiMethod>();
List<ApiResource> resourceList = new ArrayList<ApiResource>(this.getMasterResources().values());
for (int i = 0; i < resourceList.size(); i++) {
ApiResource apiResource = resourceList.get(i);
if (null != apiResource.getGetMethod()) {
apiGETMethods.add(apiResource.getGetMethod());
}
}
this.setMasterServices(this.getApiCatalogDAO().loadServices(apiGETMethods));
} catch (Throwable t) {
this.setMasterServices(new HashMap<String, ApiService>());
_logger.error("Error loading Services definitions", t);
throw new ApsSystemException("Error loading Services definitions", t);
}
}
@Override
public ApiMethod getRelatedMethod(String showletCode) throws ApsSystemException {
List<ApiMethod> masterMethods = this.getMasterMethods(ApiMethod.HttpMethod.GET);
for (int i = 0; i < masterMethods.size(); i++) {
ApiMethod apiMethod = masterMethods.get(i);
ApiMethodRelatedWidget relatedWidget = apiMethod.getRelatedWidget();
if (null != relatedWidget && relatedWidget.getWidgetCode().equals(showletCode)) {
return apiMethod.clone();
}
}
return null;
}
@Override
@Deprecated
public Map<String, ApiMethod> getRelatedShowletMethods() throws ApsSystemException {
return this.getRelatedWidgetMethods();
}
@Override
public Map<String, ApiMethod> getRelatedWidgetMethods() throws ApsSystemException {
Map<String, ApiMethod> mapping = new HashMap<String, ApiMethod>();
try {
List<ApiMethod> masterMethods = this.getMasterMethods(ApiMethod.HttpMethod.GET);
for (int i = 0; i < masterMethods.size(); i++) {
ApiMethod apiMethod = masterMethods.get(i);
ApiMethodRelatedWidget relatedWidget = apiMethod.getRelatedWidget();
if (null != relatedWidget) {
String widgetCode = relatedWidget.getWidgetCode();
if (mapping.containsKey(widgetCode)) {
ApiMethod alreadyMapped = mapping.get(widgetCode);
_logger.error("There is more than one method related whith widget '{}' - Actual mapped '{}'; other method '{}'", widgetCode, alreadyMapped.getResourceName(), apiMethod.getResourceName());
} else {
mapping.put(widgetCode, apiMethod.clone());
}
}
}
} catch (Throwable t) {
_logger.error("Error loading related widget methods", t);
throw new ApsSystemException("Error loading related widget methods", t);
}
return mapping;
}
@Override
public void updateMethodConfig(ApiMethod apiMethod) throws ApsSystemException {
try {
ApiMethod masterMethod = this.checkMethod(apiMethod);
this.getApiCatalogDAO().saveApiStatus(apiMethod);
masterMethod.setStatus(apiMethod.getStatus());
masterMethod.setHidden(apiMethod.getHidden());
masterMethod.setRequiredAuth(apiMethod.getRequiredAuth());
String requiredPermission = apiMethod.getRequiredPermission();
if (null != requiredPermission && requiredPermission.trim().length() > 0) {
masterMethod.setRequiredPermission(requiredPermission);
} else {
masterMethod.setRequiredPermission(null);
}
} catch (Throwable t) {
_logger.error("Error error updating api status : resource '{}' method '{}'", apiMethod.getResourceName(), apiMethod.getHttpMethod(), t);
throw new ApsSystemException("Error updating api status", t);
}
}
@Override
public void resetMethodConfig(ApiMethod apiMethod) throws ApsSystemException {
try {
ApiMethod masterMethod = this.checkMethod(apiMethod);
String resourceCode = ApiResource.getCode(masterMethod.getNamespace(), masterMethod.getResourceName());
this.getApiCatalogDAO().resetApiStatus(resourceCode, masterMethod.getHttpMethod());
masterMethod.resetConfiguration();
} catch (Throwable t) {
_logger.error("Error error resetting api status : resource '{}' method '{}'",apiMethod.getResourceName(), apiMethod.getHttpMethod(), t);
throw new ApsSystemException("Error resetting api status", t);
}
}
private ApiMethod checkMethod(ApiMethod apiMethod) throws ApsSystemException {
if (null == apiMethod) {
throw new ApsSystemException("Null api method");
}
ApiMethod masterMethod = this.getMasterMethod(apiMethod.getHttpMethod(), apiMethod.getNamespace(), apiMethod.getResourceName());
if (null == masterMethod) {
throw new ApsSystemException("Api namespace '" + apiMethod.getNamespace() + "' "
+ "resource '" + apiMethod.getResourceName() + "' "
+ "method '" + apiMethod.getHttpMethod() + "' does not exist");
}
return masterMethod;
}
@Deprecated
@Override
public ApiMethod getMethod(String resourceName) throws ApsSystemException {
return this.getMethod(ApiMethod.HttpMethod.GET, resourceName);
}
@Override
public ApiMethod getMethod(ApiMethod.HttpMethod httpMethod, String resourceName) throws ApsSystemException {
return this.getMethod(ApiMethod.HttpMethod.GET, null, resourceName);
}
@Override
public ApiMethod getMethod(ApiMethod.HttpMethod httpMethod, String namespace, String resourceName) throws ApsSystemException {
ApiMethod masterMethod = this.getMasterMethod(httpMethod, namespace, resourceName);
if (null != masterMethod) {
return masterMethod.clone();
}
return null;
}
protected ApiMethod getMasterMethod(ApiMethod.HttpMethod httpMethod, String namespace, String resourceName) throws ApsSystemException {
try {
if (null == this.getMasterResources()) {
this.loadResources();
}
String resourceCode = ApiResource.getCode(namespace, resourceName);
ApiResource resource = this.getMasterResources().get(resourceCode);
if (null != resource) {
return resource.getMethod(httpMethod);
}
} catch (Throwable t) {
_logger.error("Error extracting methods", t);
throw new ApsSystemException("Error extracting methods", t);
}
return null;
}
@Deprecated
@Override
public Map<String, ApiMethod> getMethods() throws ApsSystemException {
Map<String, ApiMethod> map = new HashMap<String, ApiMethod>();
List<ApiMethod> list = this.getMethods(ApiMethod.HttpMethod.GET);
for (int i = 0; i < list.size(); i++) {
ApiMethod apiMethod = list.get(i);
map.put(apiMethod.getResourceName(), apiMethod);
}
return map;
}
@Override
public List<ApiMethod> getMethods(ApiMethod.HttpMethod httpMethod) throws ApsSystemException {
List<ApiMethod> clonedMethods = new ArrayList<ApiMethod>();
try {
List<ApiMethod> masterMethods = this.getMasterMethods(httpMethod);
for (int i = 0; i < masterMethods.size(); i++) {
ApiMethod apiMethod = masterMethods.get(i);
clonedMethods.add(apiMethod.clone());
}
} catch (Throwable t) {
_logger.error("Error extracting methods", t);
throw new ApsSystemException("Error extracting methods", t);
}
return clonedMethods;
}
protected List<ApiMethod> getMasterMethods(ApiMethod.HttpMethod httpMethod) throws ApsSystemException {
List<ApiMethod> apiMethods = new ArrayList<ApiMethod>();
try {
if (null == this.getMasterResources()) {
this.loadResources();
}
List<ApiResource> resourceList = new ArrayList<ApiResource>(this.getMasterResources().values());
for (int i = 0; i < resourceList.size(); i++) {
ApiResource apiResource = resourceList.get(i);
if (null != apiResource.getMethod(httpMethod)) {
apiMethods.add(apiResource.getMethod(httpMethod));
}
}
} catch (Throwable t) {
_logger.error("Error loading Master Methods definitions", t);
throw new ApsSystemException("Error loading Master Methods definitions", t);
}
return apiMethods;
}
@Override
public Map<String, ApiResource> getResources() throws ApsSystemException {
Map<String, ApiResource> clonedApiResources = new HashMap<String, ApiResource>();
try {
if (null == this.getMasterResources()) {
this.loadResources();
}
Iterator<String> iterator = this.getMasterResources().keySet().iterator();
while (iterator.hasNext()) {
String resourceFullCode = iterator.next();
ApiResource resource = this.getMasterResources().get(resourceFullCode);
clonedApiResources.put(resourceFullCode, resource.clone());
}
} catch (Throwable t) {
_logger.error("Error extracting resources", t);
throw new ApsSystemException("Error extracting resources", t);
}
return clonedApiResources;
}
@Override
public ApiResource getResource(String namespace, String resourceName) throws ApsSystemException {
try {
if (null == this.getMasterResources()) {
this.loadResources();
}
String resourceCode = ApiResource.getCode(namespace, resourceName);
ApiResource apiResource = this.getMasterResources().get(resourceCode);
if (null != apiResource) {
return apiResource.clone();
}
} catch (Throwable t) {
_logger.error("Error extracting resource by name '{}'", resourceName, t);
throw new ApsSystemException("Error extracting resource", t);
}
return null;
}
@Override
public ApiService getApiService(String key) throws ApsSystemException {
try {
if (null == this.getMasterServices()) {
this.loadServices();
}
} catch (Throwable t) {
_logger.error("Error extracting services. key: {}", key, t);
throw new ApsSystemException("Error extracting services", t);
}
ApiService service = this.getMasterServices().get(key);
if (null == service) {
return null;
}
return service.clone();
}
@Override
public Map<String, ApiService> getServices() throws ApsSystemException {
Map<String, ApiService> clonedServices = new HashMap<String, ApiService>();
try {
if (null == this.getMasterResources()) {
this.loadResources();
}
if (null == this.getMasterServices()) {
this.loadServices();
}
if (null != this.getMasterServices()) {
Iterator<String> servicesIter = this.getMasterServices().keySet().iterator();
while (servicesIter.hasNext()) {
String serviceKey = servicesIter.next();
clonedServices.put(serviceKey, this.getMasterServices().get(serviceKey).clone());
}
}
} catch (Throwable t) {
_logger.error("Error extracting services", t);
throw new ApsSystemException("Error extracting services", t);
}
return clonedServices;
}
@Override
public Map<String, ApiService> getServices(String tag/*, Boolean myentando*/) throws ApsSystemException {
Map<String, ApiService> services = this.getServices();
if ((null == tag || tag.trim().length() == 0)/* && null == myentando*/) {
return services;
}
Map<String, ApiService> servicesToReturn = new HashMap<String, ApiService>();
try {
Iterator<ApiService> iter = services.values().iterator();
while (iter.hasNext()) {
ApiService apiService = iter.next();
String serviceTag = apiService.getTag();
boolean tagCheck = (null == tag || (null != serviceTag && serviceTag.toLowerCase().indexOf(tag.trim().toLowerCase()) > -1));
//boolean myentandoCheck = (null == myentando || (myentando.booleanValue() == apiService.isMyEntando()));
if (tagCheck /*&& myentandoCheck*/) {
servicesToReturn.put(apiService.getKey(), apiService);
}
}
} catch (Throwable t) {
_logger.error("Error extracting services", t);
throw new ApsSystemException("Error extracting services", t);
}
return servicesToReturn;
}
@Override
public void saveService(ApiService service) throws ApsSystemException {
try {
if (null == service) {
throw new ApsSystemException("Null api service to save");
}
ApiMethod master = service.getMaster();
if (null == master || null == this.getMethod(master.getHttpMethod(), master.getNamespace(), master.getResourceName())) {
throw new ApsSystemException("null or invalid master method of service to save");
}
if (null != this.getMasterServices().get(service.getKey())) {
this.getApiCatalogDAO().updateService(service);
} else {
this.getApiCatalogDAO().addService(service);
}
this.getMasterServices().put(service.getKey(), service);
} catch (Throwable t) {
_logger.error("Error saving service", t);
throw new ApsSystemException("Error saving service", t);
}
}
@Override
public void deleteService(String key) throws ApsSystemException {
try {
this.getApiCatalogDAO().deleteService(key);
this.getMasterServices().remove(key);
} catch (Throwable t) {
_logger.error("Error deleting api service by key '{}'", key, t);
throw new ApsSystemException("Error deleting service '" + key + "'", t);
}
}
@Override
public void updateService(ApiService service) throws ApsSystemException {
try {
if (null == service) {
throw new ApsSystemException("Null api service to update");
}
ApiService masterService = this.getMasterServices().get(service.getKey());
if (null == masterService) {
throw new ApsSystemException("Api service '" + service.getKey() + "' does not exist");
}
masterService.setActive(service.isActive());
masterService.setHidden(service.isHidden());
this.getApiCatalogDAO().updateService(masterService);
} catch (Throwable t) {
_logger.error("Error updating api service with key '{}'", service.getKey(), t);
throw new ApsSystemException("Error updating service '" + service.getKey() + "'", t);
}
}
public Map<String, ApiResource> getMasterResources() {
return _masterResources;
}
public void setMasterResources(Map<String, ApiResource> masterResources) {
this._masterResources = masterResources;
}
protected Map<String, ApiService> getMasterServices() {
return _masterServices;
}
protected void setMasterServices(Map<String, ApiService> masterServices) {
this._masterServices = masterServices;
}
protected String getLocationPatterns() {
if (null == this._locationPatterns) {
return DEFAULT_LOCATION_PATTERN;
}
return _locationPatterns;
}
public void setLocationPatterns(String locationPatterns) {
this._locationPatterns = locationPatterns;
}
protected IApiCatalogDAO getApiCatalogDAO() {
return _apiCatalogDAO;
}
public void setApiCatalogDAO(IApiCatalogDAO apiCatalogDAO) {
this._apiCatalogDAO = apiCatalogDAO;
}
private Map<String, ApiResource> _masterResources;
private Map<String, ApiService> _masterServices;
private String _locationPatterns;
private IApiCatalogDAO _apiCatalogDAO;
public static final String DEFAULT_LOCATION_PATTERN = "classpath*:/api/**/aps/apiMethods.xml";
}