001/*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube 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 * SonarQube 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 com.google.common.base.Splitter;
023import com.google.common.collect.Lists;
024import java.io.InputStream;
025import java.util.ArrayList;
026import java.util.Date;
027import java.util.List;
028import javax.annotation.CheckForNull;
029import org.apache.commons.lang.StringUtils;
030import org.sonar.api.utils.DateUtils;
031import org.sonar.api.utils.SonarException;
032
033/**
034 * @since 4.2
035 */
036public abstract class Request {
037
038  /**
039   * Returns the name of the HTTP method with which this request was made. Possible
040   * values are GET and POST. Others are not supported.
041   */
042  public abstract String method();
043
044  /**
045   * Returns the requested MIME type, or {@code "application/octet-stream"} if not specified.
046   */
047  public abstract String getMediaType();
048
049  /**
050   * Return true of the parameter is set.
051   */
052  public abstract boolean hasParam(String key);
053
054  /**
055   * Returns a non-null value. To be used when parameter is required or has a default value.
056   *
057   * @throws java.lang.IllegalArgumentException is value is null or blank
058   */
059  public String mandatoryParam(String key) {
060    String value = param(key);
061    if (value == null) {
062      throw new IllegalArgumentException(String.format("The '%s' parameter is missing", key));
063    }
064    return value;
065  }
066
067  /**
068   * Returns a boolean value. To be used when parameter is required or has a default value.
069   *
070   * @throws java.lang.IllegalArgumentException is value is null or blank
071   */
072  public boolean mandatoryParamAsBoolean(String key) {
073    String s = mandatoryParam(key);
074    return parseBoolean(key, s);
075  }
076
077  /**
078   * Returns an int value. To be used when parameter is required or has a default value.
079   *
080   * @throws java.lang.IllegalArgumentException is value is null or blank
081   */
082  public int mandatoryParamAsInt(String key) {
083    String s = mandatoryParam(key);
084    return Integer.parseInt(s);
085  }
086
087  /**
088   * Returns a long value. To be used when parameter is required or has a default value.
089   *
090   * @throws java.lang.IllegalArgumentException is value is null or blank
091   */
092  public long mandatoryParamAsLong(String key) {
093    String s = mandatoryParam(key);
094    return Long.parseLong(s);
095  }
096
097  public <E extends Enum<E>> E mandatoryParamAsEnum(String key, Class<E> enumClass) {
098    return Enum.valueOf(enumClass, mandatoryParam(key));
099  }
100
101  public List<String> mandatoryParamAsStrings(String key) {
102    List<String> values = paramAsStrings(key);
103    if (values == null) {
104      throw new IllegalArgumentException(String.format("The '%s' parameter is missing", key));
105    }
106    return values;
107  }
108
109  @CheckForNull
110  public List<String> paramAsStrings(String key) {
111    String value = param(key);
112    if (value == null) {
113      return null;
114    }
115    return Lists.newArrayList(Splitter.on(',').omitEmptyStrings().trimResults().split(value));
116  }
117
118  @CheckForNull
119  public abstract String param(String key);
120
121  @CheckForNull
122  public abstract InputStream paramAsInputStream(String key);
123
124  /**
125   * @deprecated to be dropped in 4.4. Default values are declared in ws metadata
126   */
127  @CheckForNull
128  @Deprecated
129  public String param(String key, @CheckForNull String defaultValue) {
130    return StringUtils.defaultString(param(key), defaultValue);
131  }
132
133  /**
134   * @deprecated to be dropped in 4.4. Default values must be declared in {@link org.sonar.api.server.ws.WebService} then
135   * this method can be replaced by {@link #mandatoryParamAsBoolean(String)}.
136   */
137  @Deprecated
138  public boolean paramAsBoolean(String key, boolean defaultValue) {
139    String value = param(key);
140    return value == null ? defaultValue : parseBoolean(key, value);
141  }
142
143  /**
144   * @deprecated to be dropped in 4.4. Default values must be declared in {@link org.sonar.api.server.ws.WebService} then
145   * this method can be replaced by {@link #mandatoryParamAsInt(String)}.
146   */
147  @Deprecated
148  public int paramAsInt(String key, int defaultValue) {
149    String s = param(key);
150    return s == null ? defaultValue : Integer.parseInt(s);
151  }
152
153  /**
154   * @deprecated to be dropped in 4.4. Default values must be declared in {@link org.sonar.api.server.ws.WebService} then
155   * this method can be replaced by {@link #mandatoryParamAsLong(String)}.
156   */
157  @Deprecated
158  public long paramAsLong(String key, long defaultValue) {
159    String s = param(key);
160    return s == null ? defaultValue : Long.parseLong(s);
161  }
162
163  @CheckForNull
164  public Boolean paramAsBoolean(String key) {
165    String value = param(key);
166    return value == null ? null : parseBoolean(key, value);
167  }
168
169  @CheckForNull
170  public Integer paramAsInt(String key) {
171    String s = param(key);
172    return s == null ? null : Integer.parseInt(s);
173  }
174
175  @CheckForNull
176  public Long paramAsLong(String key) {
177    String s = param(key);
178    return s == null ? null : Long.parseLong(s);
179  }
180
181  @CheckForNull
182  public <E extends Enum<E>> E paramAsEnum(String key, Class<E> enumClass) {
183    String s = param(key);
184    return s == null ? null : Enum.valueOf(enumClass, s);
185  }
186
187  @CheckForNull
188  public <E extends Enum<E>> List<E> paramAsEnums(String key, Class<E> enumClass) {
189    String value = param(key);
190    if (value == null) {
191      return null;
192    }
193    Iterable<String> values = Splitter.on(',').omitEmptyStrings().trimResults().split(value);
194    List<E> result = new ArrayList<>();
195    for (String s : values) {
196      result.add(Enum.valueOf(enumClass, s));
197    }
198    return result;
199  }
200
201  @CheckForNull
202  public Date paramAsDateTime(String key) {
203    String s = param(key);
204    if (s != null) {
205      try {
206        return DateUtils.parseDateTime(s);
207      } catch (SonarException notDateTime) {
208        try {
209          return DateUtils.parseDate(s);
210        } catch (SonarException notDateEither) {
211          throw new SonarException(String.format("'%s' cannot be parsed as either a date or date+time", s));
212        }
213      }
214    }
215    return null;
216  }
217
218  @CheckForNull
219  public Date paramAsDate(String key) {
220    String s = param(key);
221    if (s != null) {
222      return DateUtils.parseDate(s);
223    }
224    return null;
225  }
226
227  private static boolean parseBoolean(String key, String value) {
228    if ("true".equals(value) || "yes".equals(value)) {
229      return true;
230    }
231    if ("false".equals(value) || "no".equals(value)) {
232      return false;
233    }
234    throw new IllegalArgumentException(String.format("Property %s is not a boolean value: %s", key, value));
235  }
236}