001/* 002 * SonarQube 003 * Copyright (C) 2009-2016 SonarSource SA 004 * mailto:contact AT sonarsource DOT com 005 * 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public License 017 * along with this program; if not, write to the Free Software Foundation, 018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 */ 020package org.sonar.api.server.ws; 021 022import static com.google.common.base.Preconditions.checkArgument; 023 024import com.google.common.annotations.Beta; 025import com.google.common.base.Splitter; 026import com.google.common.collect.Lists; 027import java.io.InputStream; 028import java.util.ArrayList; 029import java.util.Date; 030import java.util.List; 031import javax.annotation.CheckForNull; 032import org.apache.commons.lang.StringUtils; 033import org.sonar.api.utils.DateUtils; 034import org.sonar.api.utils.SonarException; 035 036/** 037 * @since 4.2 038 */ 039public abstract class Request { 040 041 /** 042 * Returns the name of the HTTP method with which this request was made. Possible 043 * values are GET and POST. Others are not supported. 044 */ 045 public abstract String method(); 046 047 /** 048 * Returns the requested MIME type, or {@code "application/octet-stream"} if not specified. 049 */ 050 public abstract String getMediaType(); 051 052 /** 053 * Return true of the parameter is set. 054 */ 055 public abstract boolean hasParam(String key); 056 057 /** 058 * Returns a non-null value. To be used when parameter is required or has a default value. 059 * 060 * @throws java.lang.IllegalArgumentException is value is null or blank 061 */ 062 public String mandatoryParam(String key) { 063 String value = param(key); 064 if (value == null) { 065 throw new IllegalArgumentException(String.format("The '%s' parameter is missing", key)); 066 } 067 return value; 068 } 069 070 /** 071 * Returns a boolean value. To be used when parameter is required or has a default value. 072 * 073 * @throws java.lang.IllegalArgumentException is value is null or blank 074 */ 075 public boolean mandatoryParamAsBoolean(String key) { 076 String s = mandatoryParam(key); 077 return parseBoolean(key, s); 078 } 079 080 /** 081 * Returns an int value. To be used when parameter is required or has a default value. 082 * 083 * @throws java.lang.IllegalArgumentException is value is null or blank 084 */ 085 public int mandatoryParamAsInt(String key) { 086 String s = mandatoryParam(key); 087 return parseInt(key, s); 088 } 089 090 /** 091 * Returns a long value. To be used when parameter is required or has a default value. 092 * 093 * @throws java.lang.IllegalArgumentException is value is null or blank 094 */ 095 public long mandatoryParamAsLong(String key) { 096 String s = mandatoryParam(key); 097 return parseLong(key, s); 098 } 099 100 public <E extends Enum<E>> E mandatoryParamAsEnum(String key, Class<E> enumClass) { 101 return Enum.valueOf(enumClass, mandatoryParam(key)); 102 } 103 104 public List<String> mandatoryParamAsStrings(String key) { 105 List<String> values = paramAsStrings(key); 106 if (values == null) { 107 throw new IllegalArgumentException(String.format("The '%s' parameter is missing", key)); 108 } 109 return values; 110 } 111 112 @CheckForNull 113 public List<String> paramAsStrings(String key) { 114 String value = param(key); 115 if (value == null) { 116 return null; 117 } 118 return Lists.newArrayList(Splitter.on(',').omitEmptyStrings().trimResults().split(value)); 119 } 120 121 @CheckForNull 122 public abstract String param(String key); 123 124 @CheckForNull 125 public abstract InputStream paramAsInputStream(String key); 126 127 @CheckForNull 128 public abstract Part paramAsPart(String key); 129 130 public Part mandatoryParamAsPart(String key) { 131 Part part = paramAsPart(key); 132 checkArgument(part != null, "The '%s' parameter is missing", key); 133 return part; 134 } 135 136 /** 137 * @deprecated to be dropped in 4.4. Default values are declared in ws metadata 138 */ 139 @CheckForNull 140 @Deprecated 141 public String param(String key, @CheckForNull String defaultValue) { 142 return StringUtils.defaultString(param(key), defaultValue); 143 } 144 145 /** 146 * @deprecated to be dropped in 4.4. Default values must be declared in {@link org.sonar.api.server.ws.WebService} then 147 * this method can be replaced by {@link #mandatoryParamAsBoolean(String)}. 148 */ 149 @Deprecated 150 public boolean paramAsBoolean(String key, boolean defaultValue) { 151 String value = param(key); 152 return value == null ? defaultValue : parseBoolean(key, value); 153 } 154 155 /** 156 * @deprecated to be dropped in 4.4. Default values must be declared in {@link org.sonar.api.server.ws.WebService} then 157 * this method can be replaced by {@link #mandatoryParamAsInt(String)}. 158 */ 159 @Deprecated 160 public int paramAsInt(String key, int defaultValue) { 161 String s = param(key); 162 return s == null ? defaultValue : parseInt(key, s); 163 } 164 165 /** 166 * @deprecated to be dropped in 4.4. Default values must be declared in {@link org.sonar.api.server.ws.WebService} then 167 * this method can be replaced by {@link #mandatoryParamAsLong(String)}. 168 */ 169 @Deprecated 170 public long paramAsLong(String key, long defaultValue) { 171 String s = param(key); 172 return s == null ? defaultValue : parseLong(key, s); 173 } 174 175 @CheckForNull 176 public Boolean paramAsBoolean(String key) { 177 String value = param(key); 178 return value == null ? null : parseBoolean(key, value); 179 } 180 181 @CheckForNull 182 public Integer paramAsInt(String key) { 183 String s = param(key); 184 return s == null ? null : parseInt(key, s); 185 } 186 187 @CheckForNull 188 public Long paramAsLong(String key) { 189 String s = param(key); 190 return s == null ? null : parseLong(key, s); 191 } 192 193 @CheckForNull 194 public <E extends Enum<E>> E paramAsEnum(String key, Class<E> enumClass) { 195 String s = param(key); 196 return s == null ? null : Enum.valueOf(enumClass, s); 197 } 198 199 @CheckForNull 200 public <E extends Enum<E>> List<E> paramAsEnums(String key, Class<E> enumClass) { 201 String value = param(key); 202 if (value == null) { 203 return null; 204 } 205 Iterable<String> values = Splitter.on(',').omitEmptyStrings().trimResults().split(value); 206 List<E> result = new ArrayList<>(); 207 for (String s : values) { 208 result.add(Enum.valueOf(enumClass, s)); 209 } 210 211 return result; 212 } 213 214 @CheckForNull 215 public Date paramAsDateTime(String key) { 216 String s = param(key); 217 if (s != null) { 218 try { 219 return DateUtils.parseDateTime(s); 220 } catch (SonarException notDateTime) { 221 try { 222 return DateUtils.parseDate(s); 223 } catch (SonarException notDateEither) { 224 throw new IllegalArgumentException(String.format("'%s' cannot be parsed as either a date or date+time", s)); 225 } 226 } 227 } 228 return null; 229 } 230 231 @CheckForNull 232 public Date paramAsDate(String key) { 233 String s = param(key); 234 if (s == null) { 235 return null; 236 } 237 238 try { 239 return DateUtils.parseDate(s); 240 } catch (SonarException notDateException) { 241 throw new IllegalArgumentException(notDateException); 242 } 243 } 244 245 private static boolean parseBoolean(String key, String value) { 246 if ("true".equals(value) || "yes".equals(value)) { 247 return true; 248 } 249 if ("false".equals(value) || "no".equals(value)) { 250 return false; 251 } 252 throw new IllegalArgumentException(String.format("Property %s is not a boolean value: %s", key, value)); 253 } 254 255 private static int parseInt(String key, String value) { 256 try { 257 return Integer.parseInt(value); 258 } catch (NumberFormatException expection) { 259 throw new IllegalArgumentException(String.format("The '%s' parameter cannot be parsed as an integer value: %s", key, value)); 260 } 261 } 262 263 private static long parseLong(String key, String value) { 264 try { 265 return Long.parseLong(value); 266 } catch (NumberFormatException expection) { 267 throw new IllegalArgumentException(String.format("The '%s' parameter cannot be parsed as a long value: %s", key, value)); 268 } 269 } 270 271 /** 272 * Allows a web service to call another web service. 273 * @see LocalConnector 274 * @since 5.5 275 */ 276 @Beta 277 public abstract LocalConnector localConnector(); 278 279 /** 280 * Return path of the request 281 * @since 6.0 282 */ 283 public abstract String getPath(); 284 285 /** 286 * @since 6.0 287 */ 288 public interface Part { 289 InputStream getInputStream(); 290 291 String getFileName(); 292 } 293}