You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2013/01/12 00:51:02 UTC

[19/32] git commit: ApiDiscovery: Fix listApis to return api response, related apis etc.

ApiDiscovery: Fix listApis to return api response, related apis etc.

- Fix method to return listApis per api name basis
- Return api response, api related cmd etc. as part of response
- Caching and processing all cmd, response classes when plugin starts, made class
  list, maps static so they are shared by multiple instances in case, takes about
  1306ms to do the processsing but only on load time
- Cache for first listApi() and return precached data thereon, takes 2.2ms
  for first call, during runtime and 0ms thereon

Signed-off-by: Rohit Yadav <bh...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/86a77e29
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/86a77e29
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/86a77e29

Branch: refs/heads/api_limit
Commit: 86a77e29dc26fee1bb2169a9a1424bdd4e52f65e
Parents: f170075
Author: Rohit Yadav <bh...@apache.org>
Authored: Thu Jan 10 22:52:10 2013 -0800
Committer: Rohit Yadav <bh...@apache.org>
Committed: Thu Jan 10 22:52:10 2013 -0800

----------------------------------------------------------------------
 .../org/apache/cloudstack/api/ApiConstants.java    |    1 +
 .../api/command/user/discovery/ListApisCmd.java    |   22 ++-
 .../cloudstack/discovery/ApiDiscoveryService.java  |    2 +-
 .../discovery/ApiDiscoveryServiceImpl.java         |  102 ++++++++++++---
 4 files changed, 103 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/86a77e29/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index b4ce24c..d3bfcd6 100644
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -158,6 +158,7 @@ public class ApiConstants {
     public static final String RECEIVED_BYTES = "receivedbytes";
     public static final String REQUIRES_HVM = "requireshvm";
     public static final String RESOURCE_TYPE = "resourcetype";
+    public static final String RESPONSE = "response";
     public static final String QUERY_FILTER = "queryfilter";
     public static final String SCHEDULE = "schedule";
     public static final String SCOPE = "scope";

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/86a77e29/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java
----------------------------------------------------------------------
diff --git a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java
index feab20a..ed3e175 100644
--- a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java
+++ b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java
@@ -16,12 +16,12 @@
 // under the License.
 package org.apache.cloudstack.api.command.user.discovery;
 
-import com.cloud.user.Account;
 import com.cloud.user.UserContext;
 import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.BaseCmd;
-import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.PlugService;
 import org.apache.cloudstack.api.ServerApiException;
 import org.apache.cloudstack.api.response.ListResponse;
@@ -30,8 +30,8 @@ import org.apache.cloudstack.api.response.ApiDiscoveryResponse;
 
 import org.apache.log4j.Logger;
 
-@APICommand(name = "listApis", responseObject = ApiDiscoveryResponse.class, description = "lists all available apis on the server, provided by Api Discovery plugin", since = "4.1.0")
-public class ListApisCmd extends BaseListCmd {
+@APICommand(name = "listApis", responseObject = ApiDiscoveryResponse.class, description = "lists all available apis on the server, provided by the Api Discovery plugin", since = "4.1.0")
+public class ListApisCmd extends BaseCmd {
 
     public static final Logger s_logger = Logger.getLogger(ListApisCmd.class.getName());
     private static final String s_name = "listapisresponse";
@@ -39,14 +39,16 @@ public class ListApisCmd extends BaseListCmd {
     @PlugService
     ApiDiscoveryService _apiDiscoveryService;
 
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="API name")
+    private String name;
+
     @Override
     public void execute() throws ServerApiException {
         if (_apiDiscoveryService != null) {
-            Account caller = UserContext.current().getCaller();
             RoleType roleType = _accountService.getRoleType(UserContext.current().getCaller());
-            ListResponse<ApiDiscoveryResponse> response = (ListResponse<ApiDiscoveryResponse>) _apiDiscoveryService.listApis(roleType);
+            ListResponse<ApiDiscoveryResponse> response = (ListResponse<ApiDiscoveryResponse>) _apiDiscoveryService.listApis(roleType, name);
             if (response == null) {
-                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Api Discovery plugin was unable to find and process any apis");
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Api Discovery plugin was unable to find an api by that name or process any apis");
             }
             response.setResponseName(getCommandName());
             this.setResponseObject(response);
@@ -57,4 +59,10 @@ public class ListApisCmd extends BaseListCmd {
     public String getCommandName() {
         return s_name;
     }
+
+    @Override
+    public long getEntityOwnerId() {
+        // no owner is needed for list command
+        return 0;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/86a77e29/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java
----------------------------------------------------------------------
diff --git a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java
index a1d440e..611493b 100644
--- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java
+++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java
@@ -22,5 +22,5 @@ import org.apache.cloudstack.api.BaseResponse;
 import org.apache.cloudstack.api.response.ListResponse;
 
 public interface ApiDiscoveryService extends PluggableService {
-    ListResponse<? extends BaseResponse> listApis(RoleType roleType);
+    ListResponse<? extends BaseResponse> listApis(RoleType roleType, String apiName);
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/86a77e29/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java
----------------------------------------------------------------------
diff --git a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java
index 9f4031c..5f84486 100644
--- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java
+++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java
@@ -16,13 +16,13 @@
 // under the License.
 package org.apache.cloudstack.discovery;
 
+import com.cloud.serializer.Param;
 import com.cloud.server.ManagementServer;
 import com.cloud.utils.ReflectUtil;
-import com.cloud.utils.component.Adapters;
+import com.cloud.utils.StringUtils;
 import com.cloud.utils.component.ComponentLocator;
-import com.cloud.utils.component.Inject;
 import com.cloud.utils.component.PluggableService;
-import org.apache.cloudstack.acl.APIChecker;
+import com.google.gson.annotations.SerializedName;
 import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.BaseCmd;
@@ -32,6 +32,7 @@ import org.apache.cloudstack.api.BaseResponse;
 import org.apache.cloudstack.api.Parameter;
 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;
 
@@ -39,6 +40,7 @@ import javax.ejb.Local;
 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;
@@ -47,19 +49,24 @@ import java.util.Set;
 public class ApiDiscoveryServiceImpl implements ApiDiscoveryService {
     private static final Logger s_logger = Logger.getLogger(ApiDiscoveryServiceImpl.class);
 
+    private static Map<RoleType, List<ApiDiscoveryResponse>> _roleTypeDiscoveryResponseListMap;
+
     private static Map<String, ApiDiscoveryResponse> _apiNameDiscoveryResponseMap =
             new HashMap<String, ApiDiscoveryResponse>();
 
-    private static Map<RoleType, List<ApiDiscoveryResponse>> _roleTypeDiscoveryResponseListMap =
-            new HashMap<RoleType, List<ApiDiscoveryResponse>>();
-
     private static Map<String, List<RoleType>> _apiNameRoleTypeListMap = null;
 
     protected ApiDiscoveryServiceImpl() {
         super();
-        for (RoleType roleType: RoleType.values())
-            _roleTypeDiscoveryResponseListMap.put(roleType, new ArrayList<ApiDiscoveryResponse>());
-        cacheListApiResponse();
+        if (_roleTypeDiscoveryResponseListMap == null) {
+            long startTime = System.nanoTime();
+            _roleTypeDiscoveryResponseListMap = new HashMap<RoleType, List<ApiDiscoveryResponse>>();
+            for (RoleType roleType: RoleType.values())
+                _roleTypeDiscoveryResponseListMap.put(roleType, new ArrayList<ApiDiscoveryResponse>());
+            cacheResponseMap();
+            long endTime = System.nanoTime();
+            s_logger.info("Api Discovery Service: Annotation, docstrings, api relation graph processed in " + (endTime - startTime) / 1000000.0 + " ms");
+        }
     }
 
     private Map<String, List<RoleType>> getApiNameRoleTypeListMap() {
@@ -86,10 +93,12 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService {
         return apiNameRoleTypeMap;
     }
 
-    private void cacheListApiResponse() {
+    private void cacheResponseMap() {
         Set<Class<?>> cmdClasses = ReflectUtil.getClassesWithAnnotation(APICommand.class,
                 new String[]{"org.apache.cloudstack.api", "com.cloud.api"});
 
+        Map<String, List<String>> responseApiNameListMap = new HashMap<String, List<String>>();
+
         for(Class<?> cmdClass: cmdClasses) {
             APICommand apiCmdAnnotation = cmdClass.getAnnotation(APICommand.class);
             if (apiCmdAnnotation == null)
@@ -100,10 +109,32 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService {
                 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());
-            response.setSince(apiCmdAnnotation.since());
+            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);
+                }
+            }
 
             Field[] fields = ReflectUtil.getAllFieldsForClass(cmdClass,
                     new Class<?>[] {BaseCmd.class, BaseAsyncCmd.class, BaseAsyncCreateCmd.class});
@@ -122,23 +153,50 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService {
                     ApiParameterResponse paramResponse = new ApiParameterResponse();
                     paramResponse.setName(parameterAnnotation.name());
                     paramResponse.setDescription(parameterAnnotation.description());
-                    paramResponse.setType(parameterAnnotation.type().toString());
+                    paramResponse.setType(parameterAnnotation.type().toString().toLowerCase());
                     paramResponse.setLength(parameterAnnotation.length());
                     paramResponse.setRequired(parameterAnnotation.required());
-                    paramResponse.setSince(parameterAnnotation.since());
+                    if (!parameterAnnotation.since().isEmpty())
+                        paramResponse.setSince(parameterAnnotation.since());
+                    paramResponse.setRelated(parameterAnnotation.entityType()[0].getName());
                     response.addParam(paramResponse);
                 }
             }
-            response.setObjectName("apis");
+            response.setObjectName("api");
+            _apiNameDiscoveryResponseMap.put(apiName, response);
+        }
+
+        for (String apiName: _apiNameDiscoveryResponseMap.keySet()) {
+            ApiDiscoveryResponse response = _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);
+            }
             _apiNameDiscoveryResponseMap.put(apiName, response);
         }
     }
 
     @Override
-    public ListResponse<? extends BaseResponse> listApis(RoleType roleType) {
+    public ListResponse<? extends BaseResponse> listApis(RoleType roleType, String name) {
         // Creates roles based response list cache the first time listApis is called
         // Due to how adapters work, this cannot be done when mgmt loads
         if (_apiNameRoleTypeListMap == null) {
+            long startTime = System.nanoTime();
             _apiNameRoleTypeListMap = getApiNameRoleTypeListMap();
             for (Map.Entry<String, List<RoleType>> entry: _apiNameRoleTypeListMap.entrySet()) {
                 String apiName = entry.getKey();
@@ -147,9 +205,21 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService {
                             _apiNameDiscoveryResponseMap.get(apiName));
                 }
             }
+            long endTime = System.nanoTime();
+            s_logger.info("Api Discovery Service: List apis cached in " + (endTime - startTime) / 1000000.0 + " ms");
         }
         ListResponse<ApiDiscoveryResponse> response = new ListResponse<ApiDiscoveryResponse>();
-        response.setResponses(_roleTypeDiscoveryResponseListMap.get(roleType));
+        if (name != null) {
+            if (!_apiNameDiscoveryResponseMap.containsKey(name))
+                return null;
+
+             List<ApiDiscoveryResponse> singleResponse = new ArrayList<ApiDiscoveryResponse>();
+            singleResponse.add(_apiNameDiscoveryResponseMap.get(name));
+            response.setResponses(singleResponse);
+
+        } else {
+            response.setResponses(_roleTypeDiscoveryResponseListMap.get(roleType));
+        }
         return response;
     }