001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.bind; 018 019import java.util.Arrays; 020import java.util.Iterator; 021import java.util.List; 022import java.util.Map; 023 024import org.springframework.util.Assert; 025import org.springframework.util.CollectionUtils; 026import org.springframework.util.ObjectUtils; 027import org.springframework.util.StringUtils; 028 029/** 030 * {@link ServletRequestBindingException} subclass that indicates an unsatisfied 031 * parameter condition, as typically expressed using an {@code @RequestMapping} 032 * annotation at the {@code @Controller} type level. 033 * 034 * @author Juergen Hoeller 035 * @since 3.0 036 * @see org.springframework.web.bind.annotation.RequestMapping#params() 037 */ 038@SuppressWarnings("serial") 039public class UnsatisfiedServletRequestParameterException extends ServletRequestBindingException { 040 041 private final List<String[]> paramConditions; 042 043 private final Map<String, String[]> actualParams; 044 045 046 /** 047 * Create a new UnsatisfiedServletRequestParameterException. 048 * @param paramConditions the parameter conditions that have been violated 049 * @param actualParams the actual parameter Map associated with the ServletRequest 050 */ 051 public UnsatisfiedServletRequestParameterException(String[] paramConditions, Map<String, String[]> actualParams) { 052 super(""); 053 this.paramConditions = Arrays.<String[]>asList(paramConditions); 054 this.actualParams = actualParams; 055 } 056 057 /** 058 * Create a new UnsatisfiedServletRequestParameterException. 059 * @param paramConditions all sets of parameter conditions that have been violated 060 * @param actualParams the actual parameter Map associated with the ServletRequest 061 * @since 4.2 062 */ 063 public UnsatisfiedServletRequestParameterException(List<String[]> paramConditions, 064 Map<String, String[]> actualParams) { 065 066 super(""); 067 Assert.notEmpty(paramConditions, "Parameter conditions must not be empty"); 068 this.paramConditions = paramConditions; 069 this.actualParams = actualParams; 070 } 071 072 073 @Override 074 public String getMessage() { 075 StringBuilder sb = new StringBuilder("Parameter conditions "); 076 int i = 0; 077 for (String[] conditions : this.paramConditions) { 078 if (i > 0) { 079 sb.append(" OR "); 080 } 081 sb.append("\""); 082 sb.append(StringUtils.arrayToDelimitedString(conditions, ", ")); 083 sb.append("\""); 084 i++; 085 } 086 sb.append(" not met for actual request parameters: "); 087 sb.append(requestParameterMapToString(this.actualParams)); 088 return sb.toString(); 089 } 090 091 /** 092 * Return the parameter conditions that have been violated or the first group 093 * in case of multiple groups. 094 * @see org.springframework.web.bind.annotation.RequestMapping#params() 095 */ 096 public final String[] getParamConditions() { 097 return this.paramConditions.get(0); 098 } 099 100 /** 101 * Return all parameter condition groups that have been violated. 102 * @see org.springframework.web.bind.annotation.RequestMapping#params() 103 * @since 4.2 104 */ 105 public final List<String[]> getParamConditionGroups() { 106 return this.paramConditions; 107 } 108 109 /** 110 * Return the actual parameter Map associated with the ServletRequest. 111 * @see javax.servlet.ServletRequest#getParameterMap() 112 */ 113 public final Map<String, String[]> getActualParams() { 114 return this.actualParams; 115 } 116 117 118 private static String requestParameterMapToString(Map<String, String[]> actualParams) { 119 StringBuilder result = new StringBuilder(); 120 for (Iterator<Map.Entry<String, String[]>> it = actualParams.entrySet().iterator(); it.hasNext();) { 121 Map.Entry<String, String[]> entry = it.next(); 122 result.append(entry.getKey()).append('=').append(ObjectUtils.nullSafeToString(entry.getValue())); 123 if (it.hasNext()) { 124 result.append(", "); 125 } 126 } 127 return result.toString(); 128 } 129 130}