Package org.apache.cloudstack.discovery

Source Code of org.apache.cloudstack.discovery.ApiDiscoveryServiceImpl

// 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.cloudstack.discovery;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;

import org.apache.cloudstack.acl.APIChecker;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.command.user.discovery.ListApisCmd;
import org.apache.cloudstack.api.response.ApiDiscoveryResponse;
import org.apache.cloudstack.api.response.ApiParameterResponse;
import org.apache.cloudstack.api.response.ApiResponseResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.cloud.serializer.Param;
import com.cloud.user.User;
import com.cloud.utils.ReflectUtil;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.component.PluggableService;
import com.google.gson.annotations.SerializedName;

@Component
@Local(value = ApiDiscoveryService.class)
public class ApiDiscoveryServiceImpl extends ManagerBase implements ApiDiscoveryService {
    private static final Logger s_logger = Logger.getLogger(ApiDiscoveryServiceImpl.class);

    @Inject protected List<APIChecker> _apiAccessCheckers = null;
    @Inject protected List<PluggableService> _services = null;
    private static Map<String, ApiDiscoveryResponse> s_apiNameDiscoveryResponseMap = null;

    protected ApiDiscoveryServiceImpl() {
        super();
    }

    @Override
  public boolean configure(String name, Map<String, Object> params)
      throws ConfigurationException {
        if (s_apiNameDiscoveryResponseMap == null) {
            long startTime = System.nanoTime();
            s_apiNameDiscoveryResponseMap = new HashMap<String, ApiDiscoveryResponse>();
            Set<Class<?>> cmdClasses = new HashSet<Class<?>>();
            for(PluggableService service: _services) {
                s_logger.debug(String.format("getting api commands of service: %s", service.getClass().getName()));
                cmdClasses.addAll(service.getCommands());
            }
            cmdClasses.addAll(this.getCommands());
            cacheResponseMap(cmdClasses);
            long endTime = System.nanoTime();
            s_logger.info("Api Discovery Service: Annotation, docstrings, api relation graph processed in " + (endTime - startTime) / 1000000.0 + " ms");
        }
       
        return true;
    }

    protected void cacheResponseMap(Set<Class<?>> cmdClasses) {
        Map<String, List<String>> responseApiNameListMap = new HashMap<String, List<String>>();

        for(Class<?> cmdClass: cmdClasses) {
            APICommand apiCmdAnnotation = cmdClass.getAnnotation(APICommand.class);
            if (apiCmdAnnotation == null)
                apiCmdAnnotation = cmdClass.getSuperclass().getAnnotation(APICommand.class);
            if (apiCmdAnnotation == null
                    || !apiCmdAnnotation.includeInApiDoc()
                    || apiCmdAnnotation.name().isEmpty())
                continue;

            String apiName = apiCmdAnnotation.name();
            String responseName = apiCmdAnnotation.responseObject().getName();
            if (!responseName.contains("SuccessResponse")) {
                if (!responseApiNameListMap.containsKey(responseName))
                    responseApiNameListMap.put(responseName, new ArrayList<String>());
                responseApiNameListMap.get(responseName).add(apiName);
            }
            ApiDiscoveryResponse response = new ApiDiscoveryResponse();
            response.setName(apiName);
            response.setDescription(apiCmdAnnotation.description());
            if (!apiCmdAnnotation.since().isEmpty())
                response.setSince(apiCmdAnnotation.since());
            response.setRelated(responseName);

            Field[] responseFields = apiCmdAnnotation.responseObject().getDeclaredFields();
            for(Field responseField: responseFields) {
                SerializedName serializedName = responseField.getAnnotation(SerializedName.class);
                if(serializedName != null) {
                    ApiResponseResponse responseResponse = new ApiResponseResponse();
                    responseResponse.setName(serializedName.value());
                    Param param = responseField.getAnnotation(Param.class);
                    if (param != null)
                        responseResponse.setDescription(param.description());
                    responseResponse.setType(responseField.getType().getSimpleName().toLowerCase());
                    response.addApiResponse(responseResponse);
                }
            }

            Set<Field> fields = ReflectUtil.getAllFieldsForClass(cmdClass,
                    new Class<?>[]{BaseCmd.class, BaseAsyncCmd.class, BaseAsyncCreateCmd.class});

            boolean isAsync = ReflectUtil.isCmdClassAsync(cmdClass,
                    new Class<?>[] {BaseAsyncCmd.class, BaseAsyncCreateCmd.class});

            response.setAsync(isAsync);

            for(Field field: fields) {
                Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
                if (parameterAnnotation != null
                        && parameterAnnotation.expose()
                        && parameterAnnotation.includeInApiDoc()) {

                    ApiParameterResponse paramResponse = new ApiParameterResponse();
                    paramResponse.setName(parameterAnnotation.name());
                    paramResponse.setDescription(parameterAnnotation.description());
                    paramResponse.setType(parameterAnnotation.type().toString().toLowerCase());
                    paramResponse.setLength(parameterAnnotation.length());
                    paramResponse.setRequired(parameterAnnotation.required());
                    if (!parameterAnnotation.since().isEmpty())
                        paramResponse.setSince(parameterAnnotation.since());
                    paramResponse.setRelated(parameterAnnotation.entityType()[0].getName());
                    response.addParam(paramResponse);
                }
            }
            response.setObjectName("api");
            s_apiNameDiscoveryResponseMap.put(apiName, response);
        }

        for (String apiName : s_apiNameDiscoveryResponseMap.keySet()) {
            ApiDiscoveryResponse response = s_apiNameDiscoveryResponseMap.get(apiName);
            Set<ApiParameterResponse> processedParams = new HashSet<ApiParameterResponse>();
            for (ApiParameterResponse param: response.getParams()) {
                if (responseApiNameListMap.containsKey(param.getRelated())) {
                    List<String> relatedApis = responseApiNameListMap.get(param.getRelated());
                    param.setRelated(StringUtils.join(relatedApis, ","));
                } else {
                    param.setRelated(null);
                }
                processedParams.add(param);
            }
            response.setParams(processedParams);

            if (responseApiNameListMap.containsKey(response.getRelated())) {
                List<String> relatedApis = responseApiNameListMap.get(response.getRelated());
                relatedApis.remove(apiName);
                response.setRelated(StringUtils.join(relatedApis, ","));
            } else {
                response.setRelated(null);
            }
            s_apiNameDiscoveryResponseMap.put(apiName, response);
        }
    }

    @Override
    public ListResponse<? extends BaseResponse> listApis(User user, String name) {
        ListResponse<ApiDiscoveryResponse> response = new ListResponse<ApiDiscoveryResponse>();
        List<ApiDiscoveryResponse> responseList = new ArrayList<ApiDiscoveryResponse>();

        if (user == null)
            return null;

        if (name != null) {
            if (!s_apiNameDiscoveryResponseMap.containsKey(name))
                return null;

            for (APIChecker apiChecker : _apiAccessCheckers) {
                try {
                    apiChecker.checkAccess(user, name);
                } catch (Exception ex) {
                    return null;
                }
            }
            responseList.add(s_apiNameDiscoveryResponseMap.get(name));

        } else {
            for (String apiName : s_apiNameDiscoveryResponseMap.keySet()) {
                boolean isAllowed = true;
                for (APIChecker apiChecker : _apiAccessCheckers) {
                    try {
                        apiChecker.checkAccess(user, apiName);
                    } catch (Exception ex) {
                        isAllowed = false;
                    }
                }
                if (isAllowed)
                    responseList.add(s_apiNameDiscoveryResponseMap.get(apiName));
            }
        }
        response.setResponses(responseList);
        return response;
    }

    @Override
    public List<Class<?>> getCommands() {
        List<Class<?>> cmdList = new ArrayList<Class<?>>();
        cmdList.add(ListApisCmd.class);
        return cmdList;
    }
}
TOP

Related Classes of org.apache.cloudstack.discovery.ApiDiscoveryServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.