You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2012/12/18 13:29:32 UTC

[4/5] git commit: api: Process UUID and Parameter annotations in ApiDispatcher

api: Process UUID and Parameter annotations in ApiDispatcher

- Use @Parameter's entityType and type annotation fields
- Use @Entity annotation in Reponse class to get table info for Dao
- Use findByXId to process all entities and translate UUID to ID
- Handle error in reflection method invoking

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/5fdce84e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/5fdce84e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/5fdce84e

Branch: refs/heads/api_refactoring
Commit: 5fdce84e81c10650d41de1837d7f4a1791fc4a6e
Parents: 837d21b
Author: Rohit Yadav <bh...@apache.org>
Authored: Tue Dec 18 04:16:33 2012 -0800
Committer: Rohit Yadav <bh...@apache.org>
Committed: Tue Dec 18 04:16:33 2012 -0800

----------------------------------------------------------------------
 server/src/com/cloud/api/ApiDispatcher.java |  142 ++++++++++++++--------
 1 files changed, 92 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5fdce84e/server/src/com/cloud/api/ApiDispatcher.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiDispatcher.java b/server/src/com/cloud/api/ApiDispatcher.java
index 646bab9..e75a15c 100755
--- a/server/src/com/cloud/api/ApiDispatcher.java
+++ b/server/src/com/cloud/api/ApiDispatcher.java
@@ -17,6 +17,8 @@
 package com.cloud.api;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.util.ArrayList;
@@ -28,6 +30,7 @@ import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.regex.Matcher;
 
+import com.cloud.dao.EntityManager;
 import org.apache.cloudstack.api.*;
 import org.apache.log4j.Logger;
 
@@ -62,17 +65,16 @@ import com.cloud.utils.exception.CSExceptionErrorCode;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.uuididentity.dao.IdentityDao;
 
-/**
- * A class that dispatches API commands to the appropriate manager for execution.
- */
+// ApiDispatcher: A class that dispatches API commands to the appropriate manager for execution.
 public class ApiDispatcher {
     private static final Logger s_logger = Logger.getLogger(ApiDispatcher.class.getName());
 
     ComponentLocator _locator;
     Long _createSnapshotQueueSizeLimit;
-    @Inject AsyncJobManager _asyncMgr = null;
+    @Inject private AsyncJobManager _asyncMgr = null;
+    @Inject private AccountManager _accountMgr = null;
+    @Inject EntityManager _entityMgr = null;
     @Inject IdentityDao _identityDao = null;
-    @Inject AccountManager _accountMgr = null;
 
     Map<String, Class<? extends GenericDao>> _daoNameMap = new HashMap<String, Class<? extends GenericDao>>();
     // singleton class
@@ -105,7 +107,6 @@ public class ApiDispatcher {
     }
 
     public void dispatchCreateCmd(BaseAsyncCreateCmd cmd, Map<String, String> params) {
-
     	List<ControlledEntity> entitiesToAccess = new ArrayList<ControlledEntity>();
     	setupParameters(cmd, params, entitiesToAccess);
 
@@ -150,15 +151,12 @@ public class ApiDispatcher {
         }
     }
 
-    private void doAccessChecks(BaseAsyncCreateCmd cmd,
-			List<ControlledEntity> entitiesToAccess) {
-
+    private void doAccessChecks(BaseAsyncCreateCmd cmd, List<ControlledEntity> entitiesToAccess) {
 		//owner
 		Account caller = UserContext.current().getCaller();
-		Account owner = s_instance._accountMgr.getActiveAccountById(cmd.getEntityOwnerId());
+		Account owner = _accountMgr.getActiveAccountById(cmd.getEntityOwnerId());
 
 		List<Role> callerRoles = determineRole(caller);
-		
 		List<Role> ownerRoles = determineRole(owner);
 		
 		//check permission to call this command for the caller
@@ -166,10 +164,9 @@ public class ApiDispatcher {
 		checkACLOnCommand(cmd);
 		
 		//check that caller can access the owner account.
-		s_instance._accountMgr.checkAccess(caller, null, true, owner);
+		_accountMgr.checkAccess(caller, null, true, owner);
 		
 		checkACLOnEntities(caller, entitiesToAccess);
-
 	}
     
     
@@ -190,15 +187,14 @@ public class ApiDispatcher {
 		//checkACLOnEntities
     	if(!entitiesToAccess.isEmpty()){
 			for(ControlledEntity entity : entitiesToAccess)
-			s_instance._accountMgr.checkAccess(caller, null, true, entity);
+			    _accountMgr.checkAccess(caller, null, true, entity);
        }
-
     }
 
 	public void dispatch(BaseCmd cmd, Map<String, String> params) {
     	List<ControlledEntity> entitiesToAccess = new ArrayList<ControlledEntity>();
     	setupParameters(cmd, params, entitiesToAccess);
-        
+
         if(!entitiesToAccess.isEmpty()){
 			 //owner
 			Account caller = UserContext.current().getCaller();
@@ -390,6 +386,7 @@ public class ApiDispatcher {
             }
         }
 
+        // Process all the fields of the cmd object using reflection to recursively process super class
         Field[] fields = cmd.getClass().getDeclaredFields();
         Class<?> superClass = cmd.getClass().getSuperclass();
         while (BaseCmd.class.isAssignableFrom(superClass)) {
@@ -404,20 +401,22 @@ public class ApiDispatcher {
         }
 
         for (Field field : fields) {
-        	
-        	//plug Services
-        	PlugService plugServiceAnnotation = field.getAnnotation(PlugService.class);
-        	if(plugServiceAnnotation != null){
-        		plugService(field, cmd);
-        	}
-        	
+            //plug Services
+            PlugService plugServiceAnnotation = field.getAnnotation(PlugService.class);
+            if(plugServiceAnnotation != null){
+                plugService(field, cmd);
+            }
+            //APITODO: change the checking here
             Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
             if ((parameterAnnotation == null) || !parameterAnnotation.expose()) {
                 continue;
             }
-
+            // APITODO Will remove this
             IdentityMapper identityMapper = field.getAnnotation(IdentityMapper.class);
 
+            //ACL checkAccess = field.getAnnotation(ACL.class);
+
+            Validator validators = field.getAnnotation(Validator.class);
             Object paramObj = unpackedParams.get(parameterAnnotation.name());
             if (paramObj == null) {
                 if (parameterAnnotation.required()) {
@@ -587,37 +586,80 @@ public class ApiDispatcher {
             case INTEGER:
                 field.set(cmdObj, Integer.valueOf(paramObj.toString()));
                 break;
-            case LIST:
-                List listParam = new ArrayList();
-                StringTokenizer st = new StringTokenizer(paramObj.toString(), ",");
-                while (st.hasMoreTokens()) {
-                    String token = st.nextToken();
-                    CommandType listType = annotation.collectionType();
-                    switch (listType) {
-                    case INTEGER:
-                        listParam.add(Integer.valueOf(token));
-                        break;
-                    case LONG: {
-                        Long val = null;
-                        if (identityMapper != null)
-                            val = s_instance._identityDao.getIdentityId(identityMapper, token);
-                        else
-                            val = Long.valueOf(token);
-
-                        listParam.add(val);
+                case LIST:
+                    List listParam = new ArrayList();
+                    StringTokenizer st = new StringTokenizer(paramObj.toString(), ",");
+                    while (st.hasMoreTokens()) {
+                        String token = st.nextToken();
+                        CommandType listType = annotation.collectionType();
+                        switch (listType) {
+                            case INTEGER:
+                                listParam.add(Integer.valueOf(token));
+                                break;
+                            case UUID:
+                                //APITODO: FIXME if there is any APICmd that has List<UUID>
+                                break;
+                            case LONG: {
+                                Long val = null;
+                                if (identityMapper != null)
+                                    val = s_instance._identityDao.getIdentityId(identityMapper, token);
+                                else
+                                    val = Long.valueOf(token);
+
+                                listParam.add(val);
+                            }
+                            break;
+                            case SHORT:
+                                listParam.add(Short.valueOf(token));
+                            case STRING:
+                                listParam.add(token);
+                                break;
+                        }
                     }
-                        break;
-                    case SHORT:
-                        listParam.add(Short.valueOf(token));
-                    case STRING:
-                        listParam.add(token);
-                        break;
+                    field.set(cmdObj, listParam);
+                    break;
+            case UUID:
+                // There may be multiple entities defined on the @Entity of a Response.class
+                // UUID CommandType would expect only one entityType, so use the first entityType
+                Class<?>[] entities = annotation.entityType()[0].getAnnotation(Entity.class).value();
+                Long id = null;
+                // Go through each entity which is an interface to a VO class and get a VO object
+                // Try to getId() for the object using reflection, break on first non-null value
+                for (Class<?> entity: entities) {
+                    // findByXId returns a VO object using uuid, use reflect to get the Id
+                    Object objVO = s_instance._entityMgr.findByXId(entity, paramObj.toString());
+                    if (objVO == null) {
+                        continue;
                     }
+                    Method method = null;
+                    try {
+                        method = objVO.getClass().getMethod("getId", null);
+                    } catch (NoSuchMethodException e) {
+                        continue;
+                    } catch (SecurityException e) {
+                        continue;
+                    }
+                    // Invoke the getId method, get the internal long ID
+                    // If that fails hide exceptions as the uuid may not exist
+                    try {
+                        id = (Long) method.invoke(objVO);
+                    } catch (InvocationTargetException e) {
+                    } catch (IllegalArgumentException e) {
+                    } catch (IllegalAccessException e) {
+                    }
+                    // Return on first non-null Id for the uuid entity
+                    if (id != null)
+                        break;
                 }
-                field.set(cmdObj, listParam);
+                // If id is null, entity with the uuid was not found, throw exception
+                if (id == null) {
+                    throw new InvalidParameterValueException("No entity with " + field.getName() + "(uuid)="
+                            + paramObj.toString() + " was found in the database.");
+                }
+                field.set(cmdObj, id);
                 break;
             case LONG:
-            case UUID:
+                // APITODO: Remove identityMapper, simply convert the over the wire param to Long
                 if (identityMapper != null)
                     field.set(cmdObj, s_instance._identityDao.getIdentityId(identityMapper, paramObj.toString()));
                 else