Coverage Report - org.apache.shindig.social.opensocial.service.RestfulRequestItem
 
Classes in this File Line Coverage Branch Coverage Complexity
RestfulRequestItem
95%
86/91
86%
38/44
0
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements. See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership. The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License. You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied. See the License for the
 16  
  * specific language governing permissions and limitations under the License.
 17  
  */
 18  
 package org.apache.shindig.social.opensocial.service;
 19  
 
 20  
 import org.apache.shindig.auth.SecurityToken;
 21  
 
 22  
 import com.google.common.collect.Lists;
 23  
 import com.google.common.collect.Maps;
 24  
 
 25  
 import org.apache.commons.io.IOUtils;
 26  
 import org.apache.commons.lang.StringUtils;
 27  
 
 28  
 import java.io.IOException;
 29  
 import java.util.Arrays;
 30  
 import java.util.Collections;
 31  
 import java.util.Enumeration;
 32  
 import java.util.List;
 33  
 import java.util.Map;
 34  
 
 35  
 import javax.servlet.ServletInputStream;
 36  
 import javax.servlet.http.HttpServletRequest;
 37  
 
 38  
 /**
 39  
  * Represents the request items that come from the restful request.
 40  
  */
 41  
 public class RestfulRequestItem extends RequestItem {
 42  
 
 43  
   protected static final String X_HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override";
 44  
 
 45  
   private String url;
 46  
 
 47  
   private Map<String, List<String>> params;
 48  
 
 49  
   private String postData;
 50  
 
 51  
   public RestfulRequestItem(String service, String method,
 52  
       SecurityToken token, BeanConverter converter) {
 53  7
     super(service, method, token, converter);
 54  7
   }
 55  
 
 56  
   public RestfulRequestItem(String path, String method, String postData, SecurityToken token,
 57  
       BeanConverter converter) {
 58  38
     super(getServiceFromPath(path), method, token, converter);
 59  38
     this.postData = postData;
 60  38
     this.url = path;
 61  38
     putUrlParamsIntoParameters();
 62  38
   }
 63  
 
 64  
   public RestfulRequestItem(HttpServletRequest servletRequest, SecurityToken token,
 65  
       BeanConverter converter) {
 66  53
     super(getServiceFromPath(servletRequest.getPathInfo()),
 67  
         getMethod(servletRequest),
 68  
         token, converter);
 69  53
     this.url = servletRequest.getPathInfo();
 70  53
     this.params = createParameterMap(servletRequest);
 71  
 
 72  53
     String method = getMethod(servletRequest);
 73  53
     if (method != null && !("GET").equals(method) && !("HEAD").equals(method)) {
 74  
       try {
 75  16
         ServletInputStream is = servletRequest.getInputStream();
 76  16
         postData = IOUtils.toString(is, servletRequest.getCharacterEncoding());
 77  0
       } catch (IOException e) {
 78  0
         throw new RuntimeException("Could not get the post data from the request", e);
 79  16
       }
 80  
     }
 81  53
   }
 82  
 
 83  
   static String getServiceFromPath(String pathInfo) {
 84  94
     pathInfo = pathInfo.substring(1);
 85  94
     int indexOfNextPathSeparator = pathInfo.indexOf('/');
 86  94
     if (indexOfNextPathSeparator != -1) {
 87  84
       return pathInfo.substring(0, indexOfNextPathSeparator);
 88  
     }
 89  10
     return pathInfo;
 90  
   }
 91  
 
 92  
   static String getMethod(HttpServletRequest request) {
 93  107
     String override = request.getParameter(X_HTTP_METHOD_OVERRIDE);
 94  107
     if (!StringUtils.isBlank(override)) {
 95  95
       return override;
 96  
     } else {
 97  12
       return request.getMethod();
 98  
     }
 99  
   }
 100  
 
 101  
   private static Map<String, List<String>> createParameterMap(HttpServletRequest servletRequest) {
 102  53
     Map<String, List<String>> parameters = Maps.newHashMap();
 103  
 
 104  53
     Enumeration<?> names = servletRequest.getParameterNames();
 105  105
     while (names.hasMoreElements()) {
 106  52
       String name = (String) names.nextElement();
 107  52
       String[] paramValues = servletRequest.getParameterValues(name);
 108  52
       parameters.put(name, Lists.newArrayList(paramValues));
 109  52
     }
 110  53
     return parameters;
 111  
   }
 112  
 
 113  
   /*
 114  
    * Takes any url params out of the url and puts them into the param map.
 115  
    * Usually the servlet request code does this for us but the batch request calls have to do it
 116  
    * by hand.
 117  
    */
 118  
   void putUrlParamsIntoParameters() {
 119  104
     if (this.params == null) {
 120  38
       this.params = Maps.newHashMap();
 121  
     }
 122  
 
 123  104
     String fullUrl = this.url;
 124  104
     int queryParamIndex = fullUrl.indexOf('?');
 125  
 
 126  104
     if (queryParamIndex != -1) {
 127  12
       this.url = fullUrl.substring(0, queryParamIndex);
 128  
 
 129  12
       String queryParams = fullUrl.substring(queryParamIndex + 1);
 130  24
       for (String param : queryParams.split("&")) {
 131  12
         String[] paramPieces = param.split("=", 2);
 132  12
         List<String> paramList = this.params.get(paramPieces[0]);
 133  12
         if (paramList == null) {
 134  12
           paramList = Lists.newArrayListWithCapacity(1);
 135  12
           this.params.put(paramPieces[0], paramList);
 136  
         }
 137  12
         if (paramPieces.length == 2) {
 138  12
           paramList.add(paramPieces[1]);
 139  12
         } else {
 140  0
           paramList.add("");
 141  
         }
 142  
       }
 143  
     }
 144  104
   }
 145  
 
 146  
   /**
 147  
    * This could definitely be cleaner.. TODO: Come up with a cleaner way to handle all of this
 148  
    * code.
 149  
    *
 150  
    * @param urlTemplate The template the url follows
 151  
    */
 152  
   @Override
 153  
   public void applyUrlTemplate(String urlTemplate) {
 154  66
     this.putUrlParamsIntoParameters();
 155  
 
 156  66
     String[] actualUrl = this.url.split("/");
 157  66
     String[] expectedUrl = urlTemplate.split("/");
 158  
 
 159  376
     for (int i = 0; i < actualUrl.length; i++) {
 160  310
       String actualPart = actualUrl[i];
 161  310
       String expectedPart = expectedUrl[i];
 162  
 
 163  310
       if (expectedPart.startsWith("{")) {
 164  178
         if (expectedPart.endsWith("}+")) {
 165  
           // The param can be a repeated field. Use ',' as default separator
 166  71
           this.params
 167  
               .put(expectedPart.substring(1, expectedPart.length() - 2),
 168  
                   Lists.newArrayList(actualPart.split(",")));
 169  71
         } else {
 170  107
           if (actualPart.indexOf(',') != -1) {
 171  0
             throw new IllegalArgumentException("Cannot expect plural value " + actualPart
 172  
                 + " for singular field " + expectedPart + " in " + this.url);
 173  
           }
 174  107
           this.params.put(expectedPart.substring(1, expectedPart.length() - 1),
 175  
               Lists.newArrayList(actualPart));
 176  
         }
 177  
       }
 178  
     }
 179  66
   }
 180  
 
 181  
 
 182  
   @Override
 183  
   public <T> T getTypedParameter(String parameterName, Class<T> dataTypeClass) {
 184  
     // We assume the the only typed parameter in a restful request is the post-content
 185  
     // and so we simply ignore the parameter name
 186  11
     return getTypedParameters(dataTypeClass);
 187  
   }
 188  
   
 189  
   @Override
 190  
   public <T> T getTypedParameters(Class<T> dataTypeClass) {
 191  12
     return converter.convertToObject(postData, dataTypeClass);
 192  
   }
 193  
 
 194  
 
 195  
   Map<String, List<String>> getParameters() {
 196  1
     return params;
 197  
   }
 198  
 
 199  
   void setParameter(String paramName, String paramValue) {
 200  
     // Ignore nulls
 201  59
     if (paramValue == null) {
 202  37
       return;
 203  
     }
 204  22
     this.params.put(paramName, Lists.newArrayList(paramValue));
 205  22
   }
 206  
 
 207  
   void setListParameter(String paramName, List<String> paramValue) {
 208  1
     this.params.put(paramName, paramValue);
 209  1
   }
 210  
 
 211  
   /**
 212  
    * Return a single param value
 213  
    */
 214  
   @Override
 215  
   public String getParameter(String paramName) {
 216  235
     List<String> paramValue = this.params.get(paramName);
 217  235
     if (paramValue != null && !paramValue.isEmpty()) {
 218  132
       return paramValue.get(0);
 219  
     }
 220  103
     return null;
 221  
   }
 222  
 
 223  
   @Override
 224  
   public String getParameter(String paramName, String defaultValue) {
 225  65
     String result = getParameter(paramName);
 226  65
     if (result == null) {
 227  0
       return defaultValue;
 228  
     }
 229  65
     return result;
 230  
   }
 231  
 
 232  
   /**
 233  
    * Return a list param value
 234  
    */
 235  
   @Override
 236  
   public List<String> getListParameter(String paramName) {
 237  165
     List<String> stringList = this.params.get(paramName);
 238  165
     if (stringList == null) {
 239  63
       return Collections.emptyList();
 240  
     }
 241  102
     if (stringList.size() == 1 && stringList.get(0).indexOf(',') != -1) {
 242  5
       stringList = Arrays.asList(stringList.get(0).split(","));
 243  5
       this.params.put(paramName, stringList);
 244  
     }
 245  102
     return stringList;
 246  
   }
 247  
 }