You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ml...@apache.org on 2014/03/08 01:23:16 UTC
[43/50] [abbrv] git commit: updated refs/heads/resize-root to 0eb9967
Dispatcher corrections, refactoring and tests
Corrects problems from previous attempt. Fixes based on help comments from
the community and conflict resolution
Signed-off-by: Daan Hoogland <da...@onecht.net>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/c211f0bb
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/c211f0bb
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/c211f0bb
Branch: refs/heads/resize-root
Commit: c211f0bbbe940ed3b9a6e9ef4b5a29be16062e85
Parents: 4552ec6
Author: Antonio Fornie <af...@schubergphilis.com>
Authored: Fri Mar 7 09:57:31 2014 -0600
Committer: Daan Hoogland <da...@onecht.net>
Committed: Fri Mar 7 19:12:07 2014 +0100
----------------------------------------------------------------------
.../org/apache/cloudstack/api/ApiConstants.java | 15 +-
api/src/org/apache/cloudstack/api/BaseCmd.java | 185 ++++---
.../org/apache/cloudstack/api/BaseListCmd.java | 30 +-
.../org/apache/cloudstack/api/BaseCmdTest.java | 69 +++
.../core/spring-server-core-misc-context.xml | 12 +
server/src/com/cloud/api/ApiDispatcher.java | 490 +------------------
server/src/com/cloud/api/ApiServer.java | 374 +++++++-------
server/src/com/cloud/api/ApiServlet.java | 133 ++---
.../api/dispatch/CommandCreationWorker.java | 56 +++
.../com/cloud/api/dispatch/DispatchChain.java | 40 ++
.../api/dispatch/DispatchChainFactory.java | 72 +++
.../com/cloud/api/dispatch/DispatchTask.java | 41 ++
.../com/cloud/api/dispatch/DispatchWorker.java | 30 ++
.../dispatch/ParamGenericValidationWorker.java | 103 ++++
.../cloud/api/dispatch/ParamProcessWorker.java | 428 ++++++++++++++++
.../cloud/api/dispatch/ParamUnpackWorker.java | 114 +++++
.../dispatch/SpecificCmdValidationWorker.java | 34 ++
.../cloud/network/as/AutoScaleManagerImpl.java | 466 +++++++++---------
.../VirtualNetworkApplianceManagerImpl.java | 2 -
.../storage/snapshot/SnapshotSchedulerImpl.java | 105 ++--
.../test/com/cloud/api/ApiDispatcherTest.java | 106 ----
.../api/dispatch/CommandCreationWorkerTest.java | 48 ++
.../api/dispatch/DispatchChainFactoryTest.java | 55 +++
.../ParamGenericValidationWorkerTest.java | 173 +++++++
.../api/dispatch/ParamProcessWorkerTest.java | 107 ++++
.../SpecificCmdValidationWorkerTest.java | 48 ++
26 files changed, 2157 insertions(+), 1179 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c211f0bb/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 14df653..f0de48e 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -23,7 +23,8 @@ public class ApiConstants {
public static final String ACCOUNT_ID = "accountid";
public static final String ALGORITHM = "algorithm";
public static final String ALLOCATED_ONLY = "allocatedonly";
- public static final String API_KEY = "userapikey";
+ public static final String API_KEY = "apikey";
+ public static final String USER_API_KEY = "userapikey";
public static final String APPLIED = "applied";
public static final String AVAILABLE = "available";
public static final String BITS = "bits";
@@ -49,10 +50,16 @@ public class ApiConstants {
public static final String CLUSTER_ID = "clusterid";
public static final String CLUSTER_NAME = "clustername";
public static final String CLUSTER_TYPE = "clustertype";
+ public static final String COMMAND = "command";
+ public static final String CMD_EVENT_TYPE = "cmdeventtype";
public static final String COMPONENT = "component";
public static final String CPU_NUMBER = "cpunumber";
public static final String CPU_SPEED = "cpuspeed";
public static final String CREATED = "created";
+ public static final String CTX_ACCOUNT_ID = "ctxaccountid";
+ public static final String CTX_USER_ID = "ctxuserid";
+ public static final String CTXSTARTEVENTID = "ctxstarteventid";
+ public static final String CTX_START_EVENT_ID = "ctxStartEventId";
public static final String CUSTOMIZED = "customized";
public static final String CUSTOMIZED_IOPS = "customizediops";
public static final String CUSTOM_ID = "customid";
@@ -79,6 +86,7 @@ public class ApiConstants {
public static final String IP6_DNS2 = "ip6dns2";
public static final String DOMAIN = "domain";
public static final String DOMAIN_ID = "domainid";
+ public static final String DOMAIN__ID = "domainId";
public static final String DURATION = "duration";
public static final String EMAIL = "email";
public static final String END_DATE = "enddate";
@@ -86,6 +94,7 @@ public class ApiConstants {
public static final String END_IPV6 = "endipv6";
public static final String END_PORT = "endport";
public static final String ENTRY_TIME = "entrytime";
+ public static final String EXPIRES = "expires";
public static final String FETCH_LATEST = "fetchlatest";
public static final String FIRSTNAME = "firstname";
public static final String FORCED = "forced";
@@ -209,8 +218,11 @@ public class ApiConstants {
public static final String SENT = "sent";
public static final String SENT_BYTES = "sentbytes";
public static final String SERVICE_OFFERING_ID = "serviceofferingid";
+ public static final String SESSIONKEY = "sessionkey";
public static final String SHOW_CAPACITIES = "showcapacities";
public static final String SHOW_REMOVED = "showremoved";
+ public static final String SIGNATURE = "signature";
+ public static final String SIGNATURE_VERSION = "signatureversion";
public static final String SIZE = "size";
public static final String SNAPSHOT_ID = "snapshotid";
public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid";
@@ -277,6 +289,7 @@ public class ApiConstants {
public static final String NETWORKRATE = "networkrate";
public static final String HOST_TAGS = "hosttags";
public static final String SSH_KEYPAIR = "keypair";
+ public static final String HTTPMETHOD = "httpmethod";
public static final String HOST_CPU_CAPACITY = "hostcpucapacity";
public static final String HOST_CPU_NUM = "hostcpunum";
public static final String HOST_MEM_CAPACITY = "hostmemcapacity";
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c211f0bb/api/src/org/apache/cloudstack/api/BaseCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java
index e869ddf..02250d7 100644
--- a/api/src/org/apache/cloudstack/api/BaseCmd.java
+++ b/api/src/org/apache/cloudstack/api/BaseCmd.java
@@ -17,22 +17,28 @@
package org.apache.cloudstack.api;
+import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.inject.Inject;
+import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.affinity.AffinityGroupService;
import org.apache.cloudstack.alert.AlertService;
+import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
import org.apache.cloudstack.network.lb.ApplicationLoadBalancerService;
import org.apache.cloudstack.network.lb.InternalLoadBalancerVMService;
import org.apache.cloudstack.query.QueryService;
import org.apache.cloudstack.usage.UsageService;
+
import org.apache.log4j.Logger;
import com.cloud.configuration.ConfigurationService;
@@ -74,6 +80,7 @@ import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.DomainService;
import com.cloud.user.ResourceLimitService;
+import com.cloud.utils.ReflectUtil;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.UUIDManager;
import com.cloud.vm.UserVmService;
@@ -97,7 +104,9 @@ public abstract class BaseCmd {
public static Pattern newInputDateFormat = Pattern.compile("[\\d]+-[\\d]+-[\\d]+ [\\d]+:[\\d]+:[\\d]+");
private static final DateFormat s_outputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
- private Object _responseObject = null;
+ protected static final Map<Class<?>, List<Field>> fieldsForCmdClass = new HashMap<Class<?>, List<Field>>();
+
+ private Object _responseObject;
private Map<String, String> fullUrlParams;
public enum HTTPMethod {
@@ -205,7 +214,7 @@ public abstract class BaseCmd {
return httpMethod;
}
- public void setHttpMethod(String method) {
+ public void setHttpMethod(final String method) {
if (method != null) {
if (method.equalsIgnoreCase("GET"))
httpMethod = HTTPMethod.GET;
@@ -227,12 +236,36 @@ public abstract class BaseCmd {
return responseType;
}
- public void setResponseType(String responseType) {
+ public void setResponseType(final String responseType) {
this.responseType = responseType;
}
+ /**
+ * For some reason this method does not return the actual command name, but more a name that
+ * is used to create the response. So you can expect for a XCmd a value like xcmdresponse. Anyways
+ * this methods is used in too many places so for now instead of changing it we just create another
+ * method {@link BaseCmd#getActualCommandName()} that returns the value from {@link APICommand#name()}
+ *
+ * @return
+ */
public abstract String getCommandName();
+
+ /**
+ * Gets the CommandName based on the class annotations: the value from {@link APICommand#name()}
+ *
+ * @return the value from {@link APICommand#name()}
+ */
+ public String getActualCommandName() {
+ String cmdName = null;
+ if (this.getClass().getAnnotation(APICommand.class) != null) {
+ cmdName = this.getClass().getAnnotation(APICommand.class).name();
+ } else {
+ cmdName = this.getClass().getName();
+ }
+ return cmdName;
+ }
+
/**
* For commands the API framework needs to know the owner of the object being acted upon. This method is
* used to determine that information.
@@ -245,7 +278,7 @@ public abstract class BaseCmd {
return _responseObject;
}
- public void setResponseObject(Object responseObject) {
+ public void setResponseObject(final Object responseObject) {
_responseObject = responseObject;
}
@@ -253,7 +286,7 @@ public abstract class BaseCmd {
return _mgr;
}
- public static String getDateString(Date date) {
+ public static String getDateString(final Date date) {
if (date == null) {
return "";
}
@@ -264,101 +297,86 @@ public abstract class BaseCmd {
return formattedString;
}
- // FIXME: move this to a utils method so that maps can be unpacked and integer/long values can be appropriately cast
- @SuppressWarnings({"unchecked", "rawtypes"})
- public Map<String, Object> unpackParams(Map<String, String> params) {
- Map<String, Object> lowercaseParams = new HashMap<String, Object>();
- for (String key : params.keySet()) {
- int arrayStartIndex = key.indexOf('[');
- int arrayStartLastIndex = key.lastIndexOf('[');
- if (arrayStartIndex != arrayStartLastIndex) {
- throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
- "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
- }
+ protected List<Field> getAllFieldsForClass(final Class<?> clazz) {
+ List<Field> filteredFields = fieldsForCmdClass.get(clazz);
- if (arrayStartIndex > 0) {
- int arrayEndIndex = key.indexOf(']');
- int arrayEndLastIndex = key.lastIndexOf(']');
- if ((arrayEndIndex < arrayStartIndex) || (arrayEndIndex != arrayEndLastIndex)) {
- // malformed parameter
- throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
- "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
- }
+ // If list of fields was not cached yet
+ if (filteredFields == null) {
+ final List<Field> allFields = ReflectUtil.getAllFieldsForClass(this.getClass(), BaseCmd.class);
+ filteredFields = new ArrayList<Field>();
- // Now that we have an array object, check for a field name in the case of a complex object
- int fieldIndex = key.indexOf('.');
- String fieldName = null;
- if (fieldIndex < arrayEndIndex) {
- throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
- "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
- } else {
- fieldName = key.substring(fieldIndex + 1);
+ for (final Field field : allFields) {
+ final Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
+ if ((parameterAnnotation != null) && parameterAnnotation.expose()) {
+ filteredFields.add(field);
}
+ }
- // parse the parameter name as the text before the first '[' character
- String paramName = key.substring(0, arrayStartIndex);
- paramName = paramName.toLowerCase();
-
- Map<Integer, Map> mapArray = null;
- Map<String, Object> mapValue = null;
- String indexStr = key.substring(arrayStartIndex + 1, arrayEndIndex);
- int index = 0;
- boolean parsedIndex = false;
- try {
- if (indexStr != null) {
- index = Integer.parseInt(indexStr);
- parsedIndex = true;
- }
- } catch (NumberFormatException nfe) {
- s_logger.warn("Invalid parameter " + key + " received, unable to parse object array, returning an error.");
- }
+ // Cache the prepared list for future use
+ fieldsForCmdClass.put(clazz, filteredFields);
+ }
+ return filteredFields;
+ }
- if (!parsedIndex) {
- throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, "Unable to decode parameter " + key +
- "; if specifying an object array, please use parameter[index].field=XXX, e.g. userGroupList[0].group=httpGroup");
- }
+ protected Account getCurrentContextAccount() {
+ return CallContext.current().getCallingAccount();
+ }
- Object value = lowercaseParams.get(paramName);
- if (value == null) {
- // for now, assume object array with sub fields
- mapArray = new HashMap<Integer, Map>();
- mapValue = new HashMap<String, Object>();
- mapArray.put(Integer.valueOf(index), mapValue);
- } else if (value instanceof Map) {
- mapArray = (HashMap)value;
- mapValue = mapArray.get(Integer.valueOf(index));
- if (mapValue == null) {
- mapValue = new HashMap<String, Object>();
- mapArray.put(Integer.valueOf(index), mapValue);
+ /**
+ * This method doesn't return all the @{link Parameter}, but only the ones exposed
+ * and allowed for current @{link RoleType}. This method will get the fields for a given
+ * Cmd class only once and never again, so in case of a dynamic update the result would
+ * be obsolete (this might be a plugin update. It is agreed upon that we will not do
+ * upgrades dynamically but in case we come back on that decision we need to revisit this)
+ *
+ * @return
+ */
+ public List<Field> getParamFields() {
+ final List<Field> allFields = getAllFieldsForClass(this.getClass());
+ final List<Field> validFields = new ArrayList<Field>();
+ final Account caller = getCurrentContextAccount();
+
+ for (final Field field : allFields) {
+ final Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
+
+ //TODO: Annotate @Validate on API Cmd classes, FIXME how to process Validate
+ final RoleType[] allowedRoles = parameterAnnotation.authorized();
+ boolean roleIsAllowed = true;
+ if (allowedRoles.length > 0) {
+ roleIsAllowed = false;
+ for (final RoleType allowedRole : allowedRoles) {
+ if (allowedRole.getValue() == caller.getType()) {
+ roleIsAllowed = true;
+ break;
}
}
+ }
- // we are ready to store the value for a particular field into the map for this object
- mapValue.put(fieldName, params.get(key));
-
- lowercaseParams.put(paramName, mapArray);
+ if (roleIsAllowed) {
+ validFields.add(field);
} else {
- lowercaseParams.put(key.toLowerCase(), params.get(key));
+ s_logger.debug("Ignoring paremeter " + parameterAnnotation.name() + " as the caller is not authorized to pass it in");
}
}
- return lowercaseParams;
+
+ return validFields;
}
- protected long getInstanceIdFromJobSuccessResult(String result) {
+ protected long getInstanceIdFromJobSuccessResult(final String result) {
s_logger.debug("getInstanceIdFromJobSuccessResult not overridden in subclass " + this.getClass().getName());
return 0;
}
- public static boolean isAdmin(short accountType) {
+ public static boolean isAdmin(final short accountType) {
return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) ||
(accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
}
- public static boolean isRootAdmin(short accountType) {
+ public static boolean isRootAdmin(final short accountType) {
return ((accountType == Account.ACCOUNT_TYPE_ADMIN));
}
- public void setFullUrlParams(Map<String, String> map) {
+ public void setFullUrlParams(final Map<String, String> map) {
fullUrlParams = map;
}
@@ -366,18 +384,18 @@ public abstract class BaseCmd {
return fullUrlParams;
}
- public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) {
+ public Long finalyzeAccountId(final String accountName, final Long domainId, final Long projectId, final boolean enabledOnly) {
if (accountName != null) {
if (domainId == null) {
throw new InvalidParameterValueException("Account must be specified with domainId parameter");
}
- Domain domain = _domainService.getDomain(domainId);
+ final Domain domain = _domainService.getDomain(domainId);
if (domain == null) {
throw new InvalidParameterValueException("Unable to find domain by id");
}
- Account account = _accountService.getActiveAccountByName(accountName, domainId);
+ final Account account = _accountService.getActiveAccountByName(accountName, domainId);
if (account != null && account.getType() != Account.ACCOUNT_TYPE_PROJECT) {
if (!enabledOnly || account.getState() == Account.State.enabled) {
return account.getId();
@@ -394,12 +412,12 @@ public abstract class BaseCmd {
}
if (projectId != null) {
- Project project = _projectService.getProject(projectId);
+ final Project project = _projectService.getProject(projectId);
if (project != null) {
if (!enabledOnly || project.getState() == Project.State.Active) {
return project.getProjectAccountId();
} else {
- PermissionDeniedException ex =
+ final PermissionDeniedException ex =
new PermissionDeniedException("Can't add resources to the project with specified projectId in state=" + project.getState() +
" as it's no longer active");
ex.addProxyObject(project.getUuid(), "projectId");
@@ -413,6 +431,13 @@ public abstract class BaseCmd {
}
/**
+ * To be overwritten by any class who needs specific validation
+ */
+ public void validateSpecificParameters(final Map<String, String> params){
+ // To be overwritten by any class who needs specific validation
+ }
+
+ /**
* display flag is used to control the display of the resource only to the end user. It doesnt affect Root Admin.
* @return display flag
*/
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c211f0bb/api/src/org/apache/cloudstack/api/BaseListCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/BaseListCmd.java b/api/src/org/apache/cloudstack/api/BaseListCmd.java
index c1a4b4c..f280003 100644
--- a/api/src/org/apache/cloudstack/api/BaseListCmd.java
+++ b/api/src/org/apache/cloudstack/api/BaseListCmd.java
@@ -16,7 +16,10 @@
// under the License.
package org.apache.cloudstack.api;
+import java.util.Map;
+
import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.utils.exception.CSExceptionErrorCode;
public abstract class BaseListCmd extends BaseCmd {
@@ -83,7 +86,7 @@ public abstract class BaseListCmd extends BaseCmd {
public Long getPageSizeVal() {
Long defaultPageSize = s_maxPageSize;
- Integer pageSizeInt = getPageSize();
+ final Integer pageSizeInt = getPageSize();
if (pageSizeInt != null) {
defaultPageSize = pageSizeInt.longValue();
}
@@ -96,12 +99,12 @@ public abstract class BaseListCmd extends BaseCmd {
public Long getStartIndex() {
Long startIndex = Long.valueOf(0);
- Long pageSizeVal = getPageSizeVal();
+ final Long pageSizeVal = getPageSizeVal();
if (pageSizeVal == null) {
startIndex = null;
} else if (page != null) {
- int pageNum = page.intValue();
+ final int pageNum = page.intValue();
if (pageNum > 0) {
startIndex = Long.valueOf(pageSizeVal * (pageNum - 1));
}
@@ -112,4 +115,25 @@ public abstract class BaseListCmd extends BaseCmd {
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.None;
}
+
+ @Override
+ public void validateSpecificParameters(final Map<String, String> params){
+ super.validateSpecificParameters(params);
+
+ final Object pageSizeObj = params.get(ApiConstants.PAGE_SIZE);
+ Long pageSize = null;
+ if (pageSizeObj != null) {
+ pageSize = Long.valueOf((String)pageSizeObj);
+ }
+
+ if (params.get(ApiConstants.PAGE) == null &&
+ pageSize != null &&
+ !pageSize.equals(BaseListCmd.s_pageSizeUnlimited)) {
+ final ServerApiException ex = new ServerApiException(ApiErrorCode.PARAM_ERROR, "\"page\" parameter is required when \"pagesize\" is specified");
+ ex.setCSErrorCode(CSExceptionErrorCode.getCSErrCode(ex.getClass().getName()));
+ throw ex;
+ } else if (pageSize == null && (params.get(ApiConstants.PAGE) != null)) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "\"pagesize\" parameter is required when \"page\" is specified");
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c211f0bb/api/test/org/apache/cloudstack/api/BaseCmdTest.java
----------------------------------------------------------------------
diff --git a/api/test/org/apache/cloudstack/api/BaseCmdTest.java b/api/test/org/apache/cloudstack/api/BaseCmdTest.java
new file mode 100644
index 0000000..edf5776
--- /dev/null
+++ b/api/test/org/apache/cloudstack/api/BaseCmdTest.java
@@ -0,0 +1,69 @@
+// 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.api;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+
+public class BaseCmdTest {
+
+ private static final String NON_EXPECTED_COMMAND_NAME = "Non expected command name";
+ protected static final String CMD1_NAME = "Cmd1Name";
+ protected static final String CMD2_NAME = "Cmd2Name";
+ protected static final String CMD1_RESPONSE = "cmd1response";
+ protected static final String CMD2_RESPONSE = "cmd2response";
+
+ @Test
+ public void testGetActualCommandName(){
+ BaseCmd cmd1 = new Cmd1();
+ BaseCmd cmd2 = new Cmd2();
+
+ assertEquals(NON_EXPECTED_COMMAND_NAME, CMD1_NAME, cmd1.getActualCommandName());
+ assertEquals(NON_EXPECTED_COMMAND_NAME, CMD2_NAME, cmd2.getActualCommandName());
+ }
+}
+
+@APICommand(name=BaseCmdTest.CMD1_NAME, responseObject=BaseResponse.class)
+class Cmd1 extends BaseCmd {
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException,
+ NetworkRuleConflictException {
+ }
+ @Override
+ public String getCommandName() {
+ return BaseCmdTest.CMD1_RESPONSE;
+ }
+ @Override
+ public long getEntityOwnerId() {
+ return 0;
+ }
+}
+
+@APICommand(name=BaseCmdTest.CMD2_NAME, responseObject=BaseResponse.class)
+class Cmd2 extends Cmd1 {
+ @Override
+ public String getCommandName() {
+ return BaseCmdTest.CMD2_RESPONSE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c211f0bb/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml
----------------------------------------------------------------------
diff --git a/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml b/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml
index fd2f5fb..91401e3 100644
--- a/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml
+++ b/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml
@@ -50,6 +50,18 @@
<bean id="apiDispatcher" class="com.cloud.api.ApiDispatcher" />
+ <bean id="dispatchChainFactory" class="com.cloud.api.dispatch.DispatchChainFactory" />
+
+ <bean id="paramProcessWorker" class="com.cloud.api.dispatch.ParamProcessWorker" />
+
+ <bean id="paramUnpackWorker" class="com.cloud.api.dispatch.ParamUnpackWorker" />
+
+ <bean id="paramGenericValidationWorker" class="com.cloud.api.dispatch.ParamGenericValidationWorker" />
+
+ <bean id="specificCmdValidationWorker" class="com.cloud.api.dispatch.SpecificCmdValidationWorker" />
+
+ <bean id="commandCreationWorker" class="com.cloud.api.dispatch.CommandCreationWorker" />
+
<bean id="apiResponseHelper" class="com.cloud.api.ApiResponseHelper" />
<bean id="apiServer" class="com.cloud.api.ApiServer">
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c211f0bb/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 5bdefe7..5d4b4d3 100755
--- a/server/src/com/cloud/api/ApiDispatcher.java
+++ b/server/src/com/cloud/api/ApiDispatcher.java
@@ -16,127 +16,72 @@
// 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.HashMap;
-import java.util.List;
import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.regex.Matcher;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
-import org.apache.cloudstack.acl.ControlledEntity;
-import org.apache.cloudstack.acl.InfrastructureEntity;
-import org.apache.cloudstack.acl.RoleType;
-import org.apache.cloudstack.acl.SecurityChecker.AccessType;
-import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
import org.apache.cloudstack.api.BaseAsyncCustomIdCmd;
import org.apache.cloudstack.api.BaseCmd;
-import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.BaseCustomIdCmd;
-import org.apache.cloudstack.api.BaseListCmd;
-import org.apache.cloudstack.api.EntityReference;
-import org.apache.cloudstack.api.InternalIdentity;
-import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
-import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd;
-import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd;
-import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd;
-import org.apache.cloudstack.api.command.user.event.DeleteEventsCmd;
-import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.jobs.AsyncJob;
import org.apache.cloudstack.framework.jobs.AsyncJobManager;
import org.apache.log4j.Logger;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.user.Account;
-import com.cloud.user.AccountManager;
-import com.cloud.utils.DateUtil;
-import com.cloud.utils.ReflectUtil;
-import com.cloud.utils.db.EntityManager;
-import com.cloud.utils.exception.CSExceptionErrorCode;
-import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.api.dispatch.DispatchChain;
+import com.cloud.api.dispatch.DispatchChainFactory;
+import com.cloud.api.dispatch.DispatchTask;
public class ApiDispatcher {
private static final Logger s_logger = Logger.getLogger(ApiDispatcher.class.getName());
Long _createSnapshotQueueSizeLimit;
+
@Inject
- AsyncJobManager _asyncMgr = null;
- @Inject
- AccountManager _accountMgr = null;
- @Inject
- EntityManager _entityMgr = null;
+ AsyncJobManager _asyncMgr;
- private static ApiDispatcher s_instance;
+ @Inject()
+ protected DispatchChainFactory dispatchChainFactory;
- public static ApiDispatcher getInstance() {
- return s_instance;
- }
+ protected DispatchChain standardDispatchChain;
+
+ protected DispatchChain asyncCreationDispatchChain;
public ApiDispatcher() {
}
@PostConstruct
- void init() {
- s_instance = this;
+ public void setup() {
+ standardDispatchChain = dispatchChainFactory.getStandardDispatchChain();
+ asyncCreationDispatchChain = dispatchChainFactory.getAsyncCreationDispatchChain();
}
- public void setCreateSnapshotQueueSizeLimit(Long snapshotLimit) {
+ public void setCreateSnapshotQueueSizeLimit(final Long snapshotLimit) {
_createSnapshotQueueSizeLimit = snapshotLimit;
}
- public void dispatchCreateCmd(BaseAsyncCreateCmd cmd, Map<String, String> params) throws Exception {
- processParameters(cmd, params);
- CallContext.current().setEventDisplayEnabled(cmd.isDisplayResourceEnabled());
- cmd.create();
+ public void dispatchCreateCmd(final BaseAsyncCreateCmd cmd, final Map<String, String> params) throws Exception {
+ asyncCreationDispatchChain.dispatch(new DispatchTask(cmd, params));
+ CallContext.current().setEventDisplayEnabled(cmd.isDisplayResourceEnabled());
}
- private void doAccessChecks(BaseCmd cmd, Map<Object, AccessType> entitiesToAccess) {
- Account caller = CallContext.current().getCallingAccount();
- Account owner = _accountMgr.getActiveAccountById(cmd.getEntityOwnerId());
+ public void dispatch(final BaseCmd cmd, final Map<String, String> params, final boolean execute) throws Exception {
+ // Let the chain of responsibility dispatch gradually
+ standardDispatchChain.dispatch(new DispatchTask(cmd, params));
- if (cmd instanceof BaseAsyncCreateCmd) {
- //check that caller can access the owner account.
- _accountMgr.checkAccess(caller, null, true, owner);
- }
-
- if (!entitiesToAccess.isEmpty()) {
- //check that caller can access the owner account.
- _accountMgr.checkAccess(caller, null, true, owner);
- for (Object entity : entitiesToAccess.keySet()) {
- if (entity instanceof ControlledEntity) {
- _accountMgr.checkAccess(caller, entitiesToAccess.get(entity), true, (ControlledEntity)entity);
- } else if (entity instanceof InfrastructureEntity) {
- //FIXME: Move this code in adapter, remove code from Account manager
- }
- }
- }
- }
-
- public void dispatch(BaseCmd cmd, Map<String, String> params, boolean execute) throws Exception {
- processParameters(cmd, params);
- CallContext ctx = CallContext.current();
+ final CallContext ctx = CallContext.current();
ctx.setEventDisplayEnabled(cmd.isDisplayResourceEnabled());
+ // TODO This if shouldn't be here. Use polymorphism and move it to validateSpecificParameters
if (cmd instanceof BaseAsyncCmd) {
- BaseAsyncCmd asyncCmd = (BaseAsyncCmd)cmd;
- String startEventId = params.get("ctxStartEventId");
+ final BaseAsyncCmd asyncCmd = (BaseAsyncCmd)cmd;
+ final String startEventId = params.get(ApiConstants.CTX_START_EVENT_ID);
ctx.setStartEventId(Long.valueOf(startEventId));
// Synchronise job on the object if needed
@@ -160,6 +105,7 @@ public class ApiDispatcher {
}
}
+ // TODO This if shouldn't be here. Use polymorphism and move it to validateSpecificParameters
if (cmd instanceof BaseAsyncCustomIdCmd) {
((BaseAsyncCustomIdCmd)cmd).checkUuid();
} else if (cmd instanceof BaseCustomIdCmd) {
@@ -167,392 +113,6 @@ public class ApiDispatcher {
}
cmd.execute();
-
}
- @SuppressWarnings({"unchecked", "rawtypes"})
- public static void processParameters(BaseCmd cmd, Map<String, String> params) {
- Map<Object, AccessType> entitiesToAccess = new HashMap<Object, AccessType>();
- 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.equals(BaseListCmd.s_pageSizeUnlimited))) {
- ServerApiException ex = new ServerApiException(ApiErrorCode.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(ApiErrorCode.PARAM_ERROR, "\"pagesize\" parameter is required when \"page\" is specified");
- }
- }
-
- List<Field> fields = ReflectUtil.getAllFieldsForClass(cmd.getClass(), BaseCmd.class);
-
- for (Field field : fields) {
- Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
- if ((parameterAnnotation == null) || !parameterAnnotation.expose()) {
- continue;
- }
-
- //TODO: Annotate @Validate on API Cmd classes, FIXME how to process Validate
- RoleType[] allowedRoles = parameterAnnotation.authorized();
- if (allowedRoles.length > 0) {
- boolean permittedParameter = false;
- Account caller = CallContext.current().getCallingAccount();
- for (RoleType allowedRole : allowedRoles) {
- if (allowedRole.getValue() == caller.getType()) {
- permittedParameter = true;
- break;
- }
- }
- if (!permittedParameter) {
- s_logger.debug("Ignoring paremeter " + parameterAnnotation.name() + " as the caller is not authorized to pass it in");
- continue;
- }
- }
-
- Object paramObj = unpackedParams.get(parameterAnnotation.name());
- if (paramObj == null) {
- if (parameterAnnotation.required()) {
- throw new ServerApiException(ApiErrorCode.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);
- } 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(ApiErrorCode.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(ApiErrorCode.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(ApiErrorCode.PARAM_ERROR, "Unable to execute API command " +
- cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value. " + invEx.getMessage());
- } catch (CloudRuntimeException cloudEx) {
- s_logger.error("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(ApiErrorCode.INTERNAL_ERROR, "Internal error executing API command " +
- cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8));
- }
-
- //check access on the resource this field points to
- try {
- ACL checkAccess = field.getAnnotation(ACL.class);
- CommandType fieldType = parameterAnnotation.type();
-
- if (checkAccess != null) {
- // Verify that caller can perform actions in behalf of vm owner
- //acumulate all Controlled Entities together.
-
- //parse the array of resource types and in case of map check access on key or value or both as specified in @acl
- //implement external dao for classes that need findByName
- //for maps, specify access to be checkd on key or value.
-
- // find the controlled entity DBid by uuid
- if (parameterAnnotation.entityType() != null) {
- Class<?>[] entityList = parameterAnnotation.entityType()[0].getAnnotation(EntityReference.class).value();
-
- for (Class entity : entityList) {
- // Check if the parameter type is a single
- // Id or list of id's/name's
- switch (fieldType) {
- case LIST:
- CommandType listType = parameterAnnotation.collectionType();
- switch (listType) {
- case LONG:
- case UUID:
- List<Long> listParam = (List<Long>)field.get(cmd);
- for (Long entityId : listParam) {
- Object entityObj = s_instance._entityMgr.findById(entity, entityId);
- entitiesToAccess.put(entityObj, checkAccess.accessType());
- }
- break;
- /*
- * case STRING: List<String> listParam =
- * new ArrayList<String>(); listParam =
- * (List)field.get(cmd); for(String
- * entityName: listParam){
- * ControlledEntity entityObj =
- * (ControlledEntity
- * )daoClassInstance(entityId);
- * entitiesToAccess.add(entityObj); }
- * break;
- */
- default:
- break;
- }
- break;
- case LONG:
- case UUID:
- Object entityObj = s_instance._entityMgr.findById(entity, (Long)field.get(cmd));
- entitiesToAccess.put(entityObj, checkAccess.accessType());
- break;
- default:
- break;
- }
-
- if (ControlledEntity.class.isAssignableFrom(entity)) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("ControlledEntity name is:" + entity.getName());
- }
- }
-
- if (InfrastructureEntity.class.isAssignableFrom(entity)) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("InfrastructureEntity name is:" + entity.getName());
- }
- }
- }
-
- }
-
- }
-
- } catch (IllegalArgumentException e) {
- s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
- throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() +
- " is not accessible]");
- } catch (IllegalAccessException e) {
- s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
- throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() +
- " is not accessible]");
- }
-
- }
-
- //check access on the entities.
- getInstance().doAccessChecks(cmd, entitiesToAccess);
-
- }
-
- private static Long translateUuidToInternalId(String uuid, Parameter annotation) {
- if (uuid.equals("-1")) {
- // FIXME: This is to handle a lot of hardcoded special cases where -1 is sent
- // APITODO: Find and get rid of all hardcoded params in API Cmds and service layer
- return -1L;
- }
- Long internalId = null;
- // If annotation's empty, the cmd existed before 3.x try conversion to long
- boolean isPre3x = annotation.since().isEmpty();
- // Match against Java's UUID regex to check if input is uuid string
- boolean isUuid = uuid.matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
- // Enforce that it's uuid for newly added apis from version 3.x
- if (!isPre3x && !isUuid)
- return null;
- // Allow both uuid and internal id for pre3x apis
- if (isPre3x && !isUuid) {
- try {
- internalId = Long.parseLong(uuid);
- } catch (NumberFormatException e) {
- internalId = null;
- }
- if (internalId != null)
- return internalId;
- }
- // There may be multiple entities defined on the @EntityReference of a Response.class
- // UUID CommandType would expect only one entityType, so use the first entityType
- Class<?>[] entities = annotation.entityType()[0].getAnnotation(EntityReference.class).value();
- // 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) {
- // For backward compatibility, we search within removed entities and let service layer deal
- // with removed ones, return empty response or error
- Object objVO = s_instance._entityMgr.findByUuidIncludingRemoved(entity, uuid);
- if (objVO == null) {
- continue;
- }
- // Invoke the getId method, get the internal long ID
- // If that fails hide exceptions as the uuid may not exist
- try {
- internalId = ((InternalIdentity)objVO).getId();
- } catch (IllegalArgumentException e) {
- } catch (NullPointerException e) {
- }
- // Return on first non-null Id for the uuid entity
- if (internalId != null)
- break;
- }
- if (internalId == null) {
- if (s_logger.isDebugEnabled())
- s_logger.debug("Object entity uuid = " + uuid + " does not exist in the database.");
- throw new InvalidParameterValueException("Invalid parameter " + annotation.name() + " value=" + uuid +
- " due to incorrect long value format, or entity does not exist or due to incorrect parameter annotation for the field in api cmd class.");
- }
- return internalId;
- }
-
- @SuppressWarnings({"unchecked", "rawtypes"})
- private static void setFieldValue(Field field, BaseCmd cmdObj, Object paramObj, Parameter annotation) 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 messaging for ListEventsCmd only
- if (cmdObj instanceof ListEventsCmd || cmdObj instanceof DeleteEventsCmd || cmdObj instanceof ArchiveEventsCmd ||
- cmdObj instanceof ArchiveAlertsCmd || cmdObj instanceof DeleteAlertsCmd) {
- 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 = messageDate(date, 0, 0, 0);
- } else if (field.getName().equals("endDate")) {
- date = messageDate(date, 23, 59, 59);
- }
- field.set(cmdObj, date);
- }
- }
- } else {
- DateFormat format = BaseCmd.INPUT_FORMAT;
- synchronized (format) {
- format.setLenient(false);
- 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 UUID:
- if (token.isEmpty())
- break;
- Long internalId = translateUuidToInternalId(token, annotation);
- listParam.add(internalId);
- break;
- case LONG: {
- listParam.add(Long.valueOf(token));
- }
- break;
- case SHORT:
- listParam.add(Short.valueOf(token));
- case STRING:
- listParam.add(token);
- break;
- }
- }
- field.set(cmdObj, listParam);
- break;
- case UUID:
- if (paramObj.toString().isEmpty())
- break;
- Long internalId = translateUuidToInternalId(paramObj.toString(), annotation);
- field.set(cmdObj, internalId);
- break;
- case LONG:
- 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 messageDate(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(Field field, BaseCmd cmd) {
-
- Class<?> fc = field.getType();
- Object instance = null;
-
- if (instance == null) {
- throw new CloudRuntimeException("Unable to plug service " + fc.getSimpleName() + " in command " + cmd.getClass().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]");
- }
- }
}