/* * Copyright 2015 Stripes Framework. * * Licensed 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 net.sourceforge.stripes.controller.json; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import net.sourceforge.stripes.controller.ContentTypeRequestWrapper; import net.sourceforge.stripes.exception.StripesRuntimeException; import net.sourceforge.stripes.util.Log; /** * This class is responsible for extracting parameters from the body of requests * which are of a JSON content type. * * @author Rick Grashel */ public class JsonContentTypeRequestWrapper implements ContentTypeRequestWrapper { private static final Log log = Log.getInstance(JsonContentTypeRequestWrapper.class); private Map< String, Set<String>> parameters = new HashMap< String, Set<String>>(); public void build(HttpServletRequest request) throws IOException { log.debug("build() called."); ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readTree(request.getReader()); if (rootNode.isArray()) { throw new StripesRuntimeException("The JSON requests bodies must start with an object brace and not an array."); } processNode(rootNode, null); } /** * This method will take a JSON node and process its conversion into a * parameter name and values. * * @param node - The JSON node to process. * @param parent - The parent path of this JSON node */ private void processNode(JsonNode node, String parent) { log.debug("Processing node (", node.toString(), ")"); if (node.isArray()) { for (int i = 0; i < node.size(); ++i) { String currentPath = parent + "[" + i + "]"; JsonNode childNode = node.get(i); processNode(childNode, currentPath); } } else if (node.isObject()) { for (Iterator<String> i = node.fieldNames(); i.hasNext();) { String childFieldName = i.next(); JsonNode childNode = node.get(childFieldName); String currentPath = (parent != null ? parent + "." + childFieldName : childFieldName); processNode(childNode, currentPath); } } else { String name = parent; Set<String> parameterValues = parameters.get(name); if (parameterValues == null) { parameterValues = new HashSet<String>(); } parameterValues.add(node.asText()); log.debug("Adding parameter (name=", name, ",value=", node.asText(), ")"); parameters.put(name, parameterValues); } } /** * Returns the names of the parameters for this request. * * @return Names of the parameters for this request */ public Enumeration<String> getParameterNames() { log.debug("Returning parameter names to a caller."); return new Enumeration<String>() { Iterator<String> iterator = parameters.keySet().iterator(); public boolean hasMoreElements() { return iterator.hasNext(); } public String nextElement() { return iterator.next(); } }; } /** * Returns a string array of the values for the passed parameter name. * * @param name - Parameter name to return values for * @return Array of values for the passed parameter name */ public String[] getParameterValues(String name) { log.debug("Returning parameter value for name (", name, ") to a caller."); String[] returnValues = null; Set<String> values = parameters.get(name); if (values != null) { returnValues = values.toArray(new String[values.size()]); } log.debug("Returning parameter value (", returnValues, ") for name (", name, ") to a caller."); return returnValues; } }