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