| // 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.log4j.Logger; |
| |
| import org.apache.cloudstack.api.ApiErrorCode; |
| import org.apache.cloudstack.api.ServerApiException; |
| |
| public class ParamUnpackWorker implements DispatchWorker { |
| |
| private static final Logger s_logger = Logger.getLogger(ParamUnpackWorker.class); |
| |
| @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) { |
| s_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); |
| } |
| |
| } |