blob: 1bde40b678a62f15b54312a18ad9c913aca0089e [file] [log] [blame]
// 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.dispatch;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ServerApiException;
public class ParamUnpackWorker implements DispatchWorker {
protected Logger logger = LogManager.getLogger(getClass());
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public void handle(final DispatchTask task) throws ServerApiException {
final Map<String, Object> lowercaseParams = new HashMap<String, Object>();
final Map<String, String> params = task.getParams();
for (final Map.Entry<String,String> entry : params.entrySet()) {
final String key = entry.getKey();
final int arrayStartIndex = key.indexOf('[');
final 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");
}
if (arrayStartIndex > 0) {
final int arrayEndIndex = key.indexOf(']');
final 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");
}
// Now that we have an array object, check for a field name in the case of a complex object
final 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);
}
// 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;
final String indexStr = key.substring(arrayStartIndex + 1, arrayEndIndex);
int index = 0;
boolean parsedIndex = false;
try {
if (indexStr != null) {
index = Integer.parseInt(indexStr);
parsedIndex = true;
}
} catch (final NumberFormatException nfe) {
logger.warn("Invalid parameter " + key + " received, unable to parse object array, returning an error.");
}
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");
}
final 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);
}
}
// we are ready to store the value for a particular field into the map for this object
mapValue.put(fieldName, entry.getValue());
lowercaseParams.put(paramName, mapArray);
} else {
lowercaseParams.put(key.toLowerCase(), entry.getValue());
}
}
// The chain continues processing the unpacked parameters
task.setParams(lowercaseParams);
}
}