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