| // 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 com.cloud.api; |
| |
| import static org.apache.commons.lang.StringUtils.isNotBlank; |
| |
| import java.lang.reflect.Field; |
| import java.text.DateFormat; |
| import java.text.ParseException; |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.StringTokenizer; |
| import java.util.regex.Matcher; |
| |
| import org.apache.log4j.Logger; |
| |
| import com.cloud.api.BaseCmd.CommandType; |
| import com.cloud.api.commands.ListEventsCmd; |
| import com.cloud.async.AsyncCommandQueued; |
| import com.cloud.async.AsyncJobManager; |
| import com.cloud.configuration.Config; |
| import com.cloud.configuration.dao.ConfigurationDao; |
| import com.cloud.exception.AccountLimitException; |
| import com.cloud.exception.InsufficientCapacityException; |
| import com.cloud.exception.InvalidParameterValueException; |
| import com.cloud.exception.PermissionDeniedException; |
| import com.cloud.exception.ResourceAllocationException; |
| import com.cloud.exception.ResourceUnavailableException; |
| import com.cloud.server.ManagementServer; |
| import com.cloud.user.Account; |
| import com.cloud.user.UserContext; |
| import com.cloud.utils.DateUtil; |
| import com.cloud.utils.IdentityProxy; |
| import com.cloud.utils.NumbersUtil; |
| import com.cloud.utils.component.ComponentLocator; |
| import com.cloud.utils.component.PluggableService; |
| 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. |
| */ |
| public class ApiDispatcher { |
| private static final Logger s_logger = Logger.getLogger(ApiDispatcher.class.getName()); |
| |
| ComponentLocator _locator; |
| AsyncJobManager _asyncMgr; |
| IdentityDao _identityDao; |
| Long _createSnapshotQueueSizeLimit; |
| |
| // singleton class |
| private static ApiDispatcher s_instance = new ApiDispatcher(); |
| |
| public static ApiDispatcher getInstance() { |
| return s_instance; |
| } |
| |
| private ApiDispatcher() { |
| _locator = ComponentLocator.getLocator(ManagementServer.Name); |
| _asyncMgr = _locator.getManager(AsyncJobManager.class); |
| _identityDao = _locator.getDao(IdentityDao.class); |
| ConfigurationDao configDao = _locator.getDao(ConfigurationDao.class); |
| Map<String, String> configs = configDao.getConfiguration(); |
| String strSnapshotLimit = configs.get(Config.ConcurrentSnapshotsThresholdPerHost.key()); |
| if (strSnapshotLimit != null) { |
| Long snapshotLimit = NumbersUtil.parseLong(strSnapshotLimit, 1L); |
| if (snapshotLimit <= 0) { |
| s_logger.debug("Global config parameter " + Config.ConcurrentSnapshotsThresholdPerHost.toString() |
| + " is less or equal 0; defaulting to unlimited"); |
| } else { |
| _createSnapshotQueueSizeLimit = snapshotLimit; |
| } |
| } |
| } |
| |
| public void dispatchCreateCmd(BaseAsyncCreateCmd cmd, Map<String, String> params) { |
| |
| setupParameters(cmd, params); |
| plugService(cmd); |
| |
| try { |
| UserContext ctx = UserContext.current(); |
| ctx.setAccountId(cmd.getEntityOwnerId()); |
| cmd.create(); |
| } catch (Throwable t) { |
| if (t instanceof InvalidParameterValueException || t instanceof IllegalArgumentException) { |
| s_logger.info(t.getMessage()); |
| throw new ServerApiException(BaseCmd.PARAM_ERROR, t.getMessage()); |
| } else if (t instanceof PermissionDeniedException) { |
| s_logger.info("PermissionDenied: " + t.getMessage()); |
| throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, t.getMessage()); |
| } else if (t instanceof AccountLimitException) { |
| s_logger.info(t.getMessage()); |
| throw new ServerApiException(BaseCmd.ACCOUNT_RESOURCE_LIMIT_ERROR, t.getMessage()); |
| } else if (t instanceof InsufficientCapacityException) { |
| s_logger.info(t.getMessage()); |
| throw new ServerApiException(BaseCmd.INSUFFICIENT_CAPACITY_ERROR, t.getMessage()); |
| } else if (t instanceof ResourceAllocationException) { |
| s_logger.info(t.getMessage()); |
| throw new ServerApiException(BaseCmd.RESOURCE_ALLOCATION_ERROR, t.getMessage()); |
| } else if (t instanceof ResourceUnavailableException) { |
| s_logger.warn("Exception: ", t); |
| throw new ServerApiException(BaseCmd.RESOURCE_UNAVAILABLE_ERROR, t.getMessage()); |
| } else if (t instanceof AsyncCommandQueued) { |
| throw (AsyncCommandQueued) t; |
| } else if (t instanceof ServerApiException) { |
| s_logger.warn(t.getClass() + " : " + ((ServerApiException) t).getDescription()); |
| throw (ServerApiException) t; |
| } else { |
| s_logger.error("Exception while executing " + cmd.getClass().getSimpleName() + ":", t); |
| if (UserContext.current().getCaller().getType() == Account.ACCOUNT_TYPE_ADMIN) { |
| throw new ServerApiException(BaseCmd.INTERNAL_ERROR, t.getMessage()); |
| } else { |
| throw new ServerApiException(BaseCmd.INTERNAL_ERROR, BaseCmd.USER_ERROR_MESSAGE); |
| } |
| } |
| } |
| } |
| |
| public void dispatch(BaseCmd cmd, Map<String, String> params) { |
| setupParameters(cmd, params); |
| ApiDispatcher.plugService(cmd); |
| try { |
| UserContext ctx = UserContext.current(); |
| ctx.setAccountId(cmd.getEntityOwnerId()); |
| if (cmd instanceof BaseAsyncCmd) { |
| |
| BaseAsyncCmd asyncCmd = (BaseAsyncCmd) cmd; |
| String startEventId = params.get("ctxStartEventId"); |
| ctx.setStartEventId(Long.valueOf(startEventId)); |
| |
| // Synchronise job on the object if needed |
| if (asyncCmd.getJob() != null && asyncCmd.getSyncObjId() != null && asyncCmd.getSyncObjType() != null) { |
| Long queueSizeLimit = null; |
| if (asyncCmd.getSyncObjType() != null && asyncCmd.getSyncObjType().equalsIgnoreCase(BaseAsyncCmd.snapshotHostSyncObject)) { |
| queueSizeLimit = _createSnapshotQueueSizeLimit; |
| } else { |
| queueSizeLimit = 1L; |
| } |
| |
| if (queueSizeLimit != null) { |
| _asyncMgr.syncAsyncJobExecution(asyncCmd.getJob(), asyncCmd.getSyncObjType(), |
| asyncCmd.getSyncObjId().longValue(), queueSizeLimit); |
| } else { |
| s_logger.trace("The queue size is unlimited, skipping the synchronizing"); |
| } |
| } |
| } |
| |
| cmd.execute(); |
| |
| } catch (Throwable t) { |
| if (t instanceof InvalidParameterValueException) { |
| // earlier, we'd log the db id as part of the log message, but now since we've pushed |
| // the id into a IdentityProxy object, we would need to dump that object alongwith the |
| // message. |
| InvalidParameterValueException ref = (InvalidParameterValueException) t; |
| ServerApiException ex = new ServerApiException(BaseCmd.PARAM_ERROR, t.getMessage()); |
| // copy over the IdentityProxy information as well and throw the serverapiexception. |
| ArrayList<IdentityProxy> idList = ref.getIdProxyList(); |
| if (idList != null) { |
| // Iterate through entire arraylist and copy over each proxy id. |
| for (int i = 0 ; i < idList.size(); i++) { |
| IdentityProxy id = idList.get(i); |
| ex.addProxyObject(id.getTableName(), id.getValue(), id.getidFieldName()); |
| s_logger.info(t.getMessage() + " db_id: " + id.getValue()); |
| } |
| } else { |
| s_logger.info(t.getMessage()); |
| } |
| // Also copy over the cserror code. |
| ex.setCSErrorCode(ref.getCSErrorCode()); |
| throw ex; |
| } else if(t instanceof IllegalArgumentException) { |
| throw new ServerApiException(BaseCmd.PARAM_ERROR, t.getMessage()); |
| } else if (t instanceof PermissionDeniedException) { |
| PermissionDeniedException ref = (PermissionDeniedException)t; |
| ServerApiException ex = new ServerApiException(BaseCmd.ACCOUNT_ERROR, t.getMessage()); |
| // copy over the IdentityProxy information as well and throw the serverapiexception. |
| ArrayList<IdentityProxy> idList = ref.getIdProxyList(); |
| if (idList != null) { |
| // Iterate through entire arraylist and copy over each proxy id. |
| for (int i = 0 ; i < idList.size(); i++) { |
| IdentityProxy id = idList.get(i); |
| ex.addProxyObject(id.getTableName(), id.getValue(), id.getidFieldName()); |
| s_logger.info("PermissionDenied: " + t.getMessage() + "db_id: " + id.getValue()); |
| } |
| } else { |
| s_logger.info("PermissionDenied: " + t.getMessage()); |
| } |
| // Also copy over the cserror code. |
| ex.setCSErrorCode(ref.getCSErrorCode()); |
| throw ex; |
| } else if (t instanceof AccountLimitException) { |
| AccountLimitException ref = (AccountLimitException)t; |
| ServerApiException ex = new ServerApiException(BaseCmd.ACCOUNT_RESOURCE_LIMIT_ERROR, t.getMessage()); |
| // copy over the IdentityProxy information as well and throw the serverapiexception. |
| ArrayList<IdentityProxy> idList = ref.getIdProxyList(); |
| if (idList != null) { |
| // Iterate through entire arraylist and copy over each proxy id. |
| for (int i = 0 ; i < idList.size(); i++) { |
| IdentityProxy id = idList.get(i); |
| ex.addProxyObject(id.getTableName(), id.getValue(), id.getidFieldName()); |
| s_logger.info(t.getMessage() + "db_id: " + id.getValue()); |
| } |
| } else { |
| s_logger.info(t.getMessage()); |
| } |
| // Also copy over the cserror code. |
| ex.setCSErrorCode(ref.getCSErrorCode()); |
| throw ex; |
| } else if (t instanceof InsufficientCapacityException) { |
| InsufficientCapacityException ref = (InsufficientCapacityException)t; |
| ServerApiException ex = new ServerApiException(BaseCmd.INSUFFICIENT_CAPACITY_ERROR, t.getMessage()); |
| // copy over the IdentityProxy information as well and throw the serverapiexception. |
| ArrayList<IdentityProxy> idList = ref.getIdProxyList(); |
| if (idList != null) { |
| // Iterate through entire arraylist and copy over each proxy id. |
| for (int i = 0 ; i < idList.size(); i++) { |
| IdentityProxy id = idList.get(i); |
| ex.addProxyObject(id.getTableName(), id.getValue(), id.getidFieldName()); |
| s_logger.info(t.getMessage() + "db_id: " + id.getValue()); |
| } |
| } else { |
| s_logger.info(t.getMessage()); |
| } |
| // Also copy over the cserror code |
| ex.setCSErrorCode(ref.getCSErrorCode()); |
| throw ex; |
| } else if (t instanceof ResourceAllocationException) { |
| ResourceAllocationException ref = (ResourceAllocationException)t; |
| ServerApiException ex = new ServerApiException(BaseCmd.RESOURCE_ALLOCATION_ERROR, t.getMessage()); |
| // copy over the IdentityProxy information as well and throw the serverapiexception. |
| ArrayList<IdentityProxy> idList = ref.getIdProxyList(); |
| if (idList != null) { |
| // Iterate through entire arraylist and copy over each proxy id. |
| for (int i = 0 ; i < idList.size(); i++) { |
| IdentityProxy id = idList.get(i); |
| ex.addProxyObject(id.getTableName(), id.getValue(), id.getidFieldName()); |
| s_logger.warn("Exception: " + t.getMessage() + "db_id: " + id.getValue()); |
| } |
| } else { |
| s_logger.warn("Exception: ", t); |
| } |
| // Also copy over the cserror code. |
| ex.setCSErrorCode(ref.getCSErrorCode()); |
| throw ex; |
| } else if (t instanceof ResourceUnavailableException) { |
| ResourceUnavailableException ref = (ResourceUnavailableException)t; |
| ServerApiException ex = new ServerApiException(BaseCmd.RESOURCE_UNAVAILABLE_ERROR, t.getMessage()); |
| // copy over the IdentityProxy information as well and throw the serverapiexception. |
| ArrayList<IdentityProxy> idList = ref.getIdProxyList(); |
| if (idList != null) { |
| // Iterate through entire arraylist and copy over each proxy id. |
| for (int i = 0 ; i < idList.size(); i++) { |
| IdentityProxy id = idList.get(i); |
| ex.addProxyObject(id.getTableName(), id.getValue(), id.getidFieldName()); |
| s_logger.warn("Exception: " + t.getMessage() + "db_id: " + id.getValue()); |
| } |
| } else { |
| s_logger.warn("Exception: ", t); |
| } |
| // Also copy over the cserror code. |
| ex.setCSErrorCode(ref.getCSErrorCode()); |
| throw ex; |
| } else if (t instanceof AsyncCommandQueued) { |
| throw (AsyncCommandQueued) t; |
| } else if (t instanceof ServerApiException) { |
| s_logger.warn(t.getClass() + " : " + ((ServerApiException) t).getDescription()); |
| throw (ServerApiException) t; |
| } else { |
| s_logger.error("Exception while executing " + cmd.getClass().getSimpleName() + ":", t); |
| ServerApiException ex; |
| if (UserContext.current().getCaller().getType() == Account.ACCOUNT_TYPE_ADMIN) { |
| ex = new ServerApiException(BaseCmd.INTERNAL_ERROR, t.getMessage()); |
| } else { |
| ex = new ServerApiException(BaseCmd.INTERNAL_ERROR, BaseCmd.USER_ERROR_MESSAGE); |
| } |
| ex.setCSErrorCode(CSExceptionErrorCode.getCSErrCode(ex.getClass().getName())); |
| throw ex; |
| } |
| } |
| } |
| |
| public static void setupParameters(BaseCmd cmd, Map<String, String> params) { |
| Map<String, Object> unpackedParams = cmd.unpackParams(params); |
| |
| if (cmd instanceof BaseListCmd) { |
| Object pageSizeObj = unpackedParams.get(ApiConstants.PAGE_SIZE); |
| Long pageSize = null; |
| if (pageSizeObj != null) { |
| pageSize = Long.valueOf((String) pageSizeObj); |
| } |
| |
| if ((unpackedParams.get(ApiConstants.PAGE) == null) && (pageSize != null && pageSize != BaseListCmd.PAGESIZE_UNLIMITED)) { |
| ServerApiException ex = new ServerApiException(BaseCmd.PARAM_ERROR, "\"page\" parameter is required when \"pagesize\" is specified"); |
| ex.setCSErrorCode(CSExceptionErrorCode.getCSErrCode(ex.getClass().getName())); |
| throw ex; |
| } else if (pageSize == null && (unpackedParams.get(ApiConstants.PAGE) != null)) { |
| throw new ServerApiException(BaseCmd.PARAM_ERROR, "\"pagesize\" parameter is required when \"page\" is specified"); |
| } |
| } |
| |
| Field[] fields = cmd.getClass().getDeclaredFields(); |
| Class<?> superClass = cmd.getClass().getSuperclass(); |
| while (BaseCmd.class.isAssignableFrom(superClass)) { |
| Field[] superClassFields = superClass.getDeclaredFields(); |
| if (superClassFields != null) { |
| Field[] tmpFields = new Field[fields.length + superClassFields.length]; |
| System.arraycopy(fields, 0, tmpFields, 0, fields.length); |
| System.arraycopy(superClassFields, 0, tmpFields, fields.length, superClassFields.length); |
| fields = tmpFields; |
| } |
| superClass = superClass.getSuperclass(); |
| } |
| |
| for (Field field : fields) { |
| Parameter parameterAnnotation = field.getAnnotation(Parameter.class); |
| if ((parameterAnnotation == null) || !parameterAnnotation.expose()) { |
| continue; |
| } |
| |
| IdentityMapper identityMapper = field.getAnnotation(IdentityMapper.class); |
| |
| Object paramObj = unpackedParams.get(parameterAnnotation.name()); |
| if (paramObj == null) { |
| if (parameterAnnotation.required()) { |
| throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to execute API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to missing parameter " |
| + parameterAnnotation.name()); |
| } |
| continue; |
| } |
| |
| // marshall the parameter into the correct type and set the field value |
| try { |
| setFieldValue(field, cmd, paramObj, parameterAnnotation, identityMapper); |
| } catch (IllegalArgumentException argEx) { |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Unable to execute API command " + cmd.getCommandName() + " due to invalid value " + paramObj + " for parameter " + parameterAnnotation.name()); |
| } |
| throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to execute API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value " + paramObj |
| + " for parameter " |
| + parameterAnnotation.name()); |
| } catch (ParseException parseEx) { |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Invalid date parameter " + paramObj + " passed to command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8)); |
| } |
| throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to parse date " + paramObj + " for command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) |
| + ", please pass dates in the format mentioned in the api documentation"); |
| } catch (InvalidParameterValueException invEx) { |
| throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to execute API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value. " + invEx.getMessage()); |
| } catch (CloudRuntimeException cloudEx) { |
| // FIXME: Better error message? This only happens if the API command is not executable, which typically |
| // means |
| // there was |
| // and IllegalAccessException setting one of the parameters. |
| throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error executing API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8)); |
| } |
| } |
| } |
| |
| @SuppressWarnings({ "unchecked", "rawtypes" }) |
| private static void setFieldValue(Field field, BaseCmd cmdObj, Object paramObj, Parameter annotation, IdentityMapper identityMapper) throws IllegalArgumentException, ParseException { |
| try { |
| field.setAccessible(true); |
| CommandType fieldType = annotation.type(); |
| switch (fieldType) { |
| case BOOLEAN: |
| field.set(cmdObj, Boolean.valueOf(paramObj.toString())); |
| break; |
| case DATE: |
| // This piece of code is for maintaining backward compatibility and support both the date formats(Bug |
| // 9724) |
| // Do the date massaging for ListEventsCmd only |
| if (cmdObj instanceof ListEventsCmd) { |
| boolean isObjInNewDateFormat = isObjInNewDateFormat(paramObj.toString()); |
| if (isObjInNewDateFormat) { |
| DateFormat newFormat = BaseCmd.NEW_INPUT_FORMAT; |
| synchronized (newFormat) { |
| field.set(cmdObj, newFormat.parse(paramObj.toString())); |
| } |
| } else { |
| DateFormat format = BaseCmd.INPUT_FORMAT; |
| synchronized (format) { |
| Date date = format.parse(paramObj.toString()); |
| if (field.getName().equals("startDate")) { |
| date = massageDate(date, 0, 0, 0); |
| } else if (field.getName().equals("endDate")) { |
| date = massageDate(date, 23, 59, 59); |
| } |
| field.set(cmdObj, date); |
| } |
| } |
| } else { |
| DateFormat format = BaseCmd.INPUT_FORMAT; |
| format.setLenient(false); |
| synchronized (format) { |
| field.set(cmdObj, format.parse(paramObj.toString())); |
| } |
| } |
| break; |
| case FLOAT: |
| // Assuming that the parameters have been checked for required before now, |
| // we ignore blank or null values and defer to the command to set a default |
| // value for optional parameters ... |
| if (paramObj != null && isNotBlank(paramObj.toString())) { |
| field.set(cmdObj, Float.valueOf(paramObj.toString())); |
| } |
| break; |
| case INTEGER: |
| // Assuming that the parameters have been checked for required before now, |
| // we ignore blank or null values and defer to the command to set a default |
| // value for optional parameters ... |
| if (paramObj != null && isNotBlank(paramObj.toString())) { |
| 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); |
| } |
| break; |
| case SHORT: |
| listParam.add(Short.valueOf(token)); |
| case STRING: |
| listParam.add(token); |
| break; |
| } |
| } |
| field.set(cmdObj, listParam); |
| break; |
| case LONG: |
| if (identityMapper != null) |
| field.set(cmdObj, s_instance._identityDao.getIdentityId(identityMapper, paramObj.toString())); |
| else |
| field.set(cmdObj, Long.valueOf(paramObj.toString())); |
| break; |
| case SHORT: |
| field.set(cmdObj, Short.valueOf(paramObj.toString())); |
| break; |
| case STRING: |
| if ((paramObj != null) && paramObj.toString().length() > annotation.length()) { |
| s_logger.error("Value greater than max allowed length " + annotation.length() + " for param: " + field.getName()); |
| throw new InvalidParameterValueException("Value greater than max allowed length " + annotation.length() + " for param: " + field.getName()); |
| } |
| field.set(cmdObj, paramObj.toString()); |
| break; |
| case TZDATE: |
| field.set(cmdObj, DateUtil.parseTZDateString(paramObj.toString())); |
| break; |
| case MAP: |
| default: |
| field.set(cmdObj, paramObj); |
| break; |
| } |
| } catch (IllegalAccessException ex) { |
| s_logger.error("Error initializing command " + cmdObj.getCommandName() + ", field " + field.getName() + " is not accessible."); |
| throw new CloudRuntimeException("Internal error initializing parameters for command " + cmdObj.getCommandName() + " [field " + field.getName() + " is not accessible]"); |
| } |
| } |
| |
| private static boolean isObjInNewDateFormat(String string) { |
| Matcher matcher = BaseCmd.newInputDateFormat.matcher(string); |
| return matcher.matches(); |
| } |
| |
| private static Date massageDate(Date date, int hourOfDay, int minute, int second) { |
| Calendar cal = Calendar.getInstance(); |
| cal.setTime(date); |
| cal.set(Calendar.HOUR_OF_DAY, hourOfDay); |
| cal.set(Calendar.MINUTE, minute); |
| cal.set(Calendar.SECOND, second); |
| return cal.getTime(); |
| } |
| |
| public static void plugService(BaseCmd cmd) { |
| |
| if (!ApiServer.isPluggableServiceCommand(cmd.getClass().getName())) { |
| return; |
| } |
| Class<?> clazz = cmd.getClass(); |
| ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name); |
| do { |
| Field[] fields = clazz.getDeclaredFields(); |
| for (Field field : fields) { |
| PlugService plugService = field.getAnnotation(PlugService.class); |
| if (plugService == null) { |
| continue; |
| } |
| Class<?> fc = field.getType(); |
| Object instance = null; |
| if (PluggableService.class.isAssignableFrom(fc)) { |
| instance = locator.getPluggableService(fc); |
| } |
| |
| if (instance == null) { |
| throw new CloudRuntimeException("Unable to plug service " + fc.getSimpleName() + " in command " + clazz.getSimpleName()); |
| } |
| |
| try { |
| field.setAccessible(true); |
| field.set(cmd, instance); |
| } catch (IllegalArgumentException e) { |
| s_logger.error("IllegalArgumentException at plugService for command " + cmd.getCommandName() + ", field " + field.getName()); |
| throw new CloudRuntimeException("Internal error at plugService for command " + cmd.getCommandName() + " [Illegal argumet at field " + field.getName() + "]"); |
| } catch (IllegalAccessException e) { |
| s_logger.error("Error at plugService for command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible."); |
| throw new CloudRuntimeException("Internal error at plugService for command " + cmd.getCommandName() + " [field " + field.getName() + " is not accessible]"); |
| } |
| } |
| clazz = clazz.getSuperclass(); |
| } while (clazz != Object.class && clazz != null); |
| } |
| |
| |
| public static Long getIdentiyId(String tableName, String token) { |
| return s_instance._identityDao.getIdentityId(tableName, token); |
| } |
| } |