src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/http/HttpUtil.java
branchjmx-rest-api
changeset 56026 bd531f08d7c7
parent 56007 d6cbabcaf518
child 56027 81372436b79e
equal deleted inserted replaced
56007:d6cbabcaf518 56026:bd531f08d7c7
     1 /*
       
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.oracle.jmx.remote.rest.http;
       
    27 
       
    28 import com.oracle.jmx.remote.rest.json.JSONObject;
       
    29 import com.sun.net.httpserver.Headers;
       
    30 import com.sun.net.httpserver.HttpExchange;
       
    31 
       
    32 import javax.management.remote.rest.PlatformRestAdapter;
       
    33 import java.io.*;
       
    34 import java.net.URI;
       
    35 import java.net.URL;
       
    36 import java.net.URLDecoder;
       
    37 import java.net.URLEncoder;
       
    38 import java.nio.charset.StandardCharsets;
       
    39 import java.util.Base64;
       
    40 import java.util.LinkedHashMap;
       
    41 import java.util.List;
       
    42 import java.util.Map;
       
    43 import java.util.stream.Collectors;
       
    44 
       
    45 public class HttpUtil {
       
    46 
       
    47     public static String getRequestCharset(HttpExchange ex) {
       
    48         String charset = null;
       
    49         List<String> contentType = ex.getRequestHeaders().get("Content-type");
       
    50         if (contentType != null) {
       
    51             for (String kv : contentType) {
       
    52                 for (String value : kv.split(";")) {
       
    53                     value = value.trim();
       
    54                     if (value.toLowerCase().startsWith("charset=")) {
       
    55                         charset = value.substring("charset=".length());
       
    56                     }
       
    57                 }
       
    58             }
       
    59         }
       
    60         return charset;
       
    61     }
       
    62 
       
    63     public static String getAcceptCharset(HttpExchange ex) {
       
    64         List<String> acceptCharset = ex.getRequestHeaders().get("Accept-Charset");
       
    65         if (acceptCharset != null && acceptCharset.size() > 0) {
       
    66             return acceptCharset.get(0);
       
    67         }
       
    68         return null;
       
    69     }
       
    70 
       
    71     public static String getGetRequestResource(HttpExchange ex) throws UnsupportedEncodingException {
       
    72         String charset = getRequestCharset(ex);
       
    73         String httpHandlerPath = ex.getHttpContext().getPath();
       
    74         String requestURIpath = ex.getRequestURI().getPath();
       
    75         String getRequestPath = requestURIpath.substring(httpHandlerPath.length());
       
    76         if (charset != null) {
       
    77             return URLDecoder.decode(getRequestPath, charset);
       
    78         } else {
       
    79             return getRequestPath;
       
    80         }
       
    81     }
       
    82 
       
    83     public static String getGetRequestQuery(HttpExchange ex) throws UnsupportedEncodingException {
       
    84         String charset = getRequestCharset(ex);
       
    85         String query = ex.getRequestURI().getQuery();
       
    86         if (charset != null && query != null) {
       
    87             return URLDecoder.decode(query, charset);
       
    88         } else {
       
    89             return query;
       
    90         }
       
    91     }
       
    92 
       
    93     public static Map<String, String> getGetRequestQueryMap(HttpExchange ex)
       
    94             throws UnsupportedEncodingException {
       
    95         String query = ex.getRequestURI().getQuery();
       
    96         Map<String, String> queryParams = new LinkedHashMap<>();
       
    97 
       
    98         if (query == null || query.isEmpty()) {
       
    99             return queryParams;
       
   100         }
       
   101         query = URLDecoder.decode(query, StandardCharsets.UTF_8.displayName());
       
   102         String[] params = query.trim().split("&");
       
   103         for (String param : params) {
       
   104             int idx = param.indexOf('=');
       
   105             if (idx != -1) {
       
   106                 queryParams.put(param.substring(0, idx), param.substring(idx + 1));
       
   107             }
       
   108         }
       
   109         return queryParams;
       
   110     }
       
   111 
       
   112     public static String getCredentials(HttpExchange exchange) {
       
   113         Headers rmap = exchange.getRequestHeaders();
       
   114         String auth = rmap.getFirst("Authorization");
       
   115         if (auth != null && !auth.isEmpty()) {
       
   116             int sp = auth.indexOf(' ');
       
   117             byte[] b = Base64.getDecoder().decode(auth.substring(sp + 1));
       
   118             String authCredentials = new String(b);
       
   119             int colon = authCredentials.indexOf(':');
       
   120             return authCredentials.substring(0, colon);
       
   121         }
       
   122         return "";
       
   123     }
       
   124 
       
   125     public static String readRequestBody(HttpExchange he) throws IOException {
       
   126         String charset = getRequestCharset(he);
       
   127         StringBuilder stringBuilder = new StringBuilder();
       
   128         InputStreamReader in = charset != null ? new InputStreamReader(he.getRequestBody(), charset) : new InputStreamReader(he.getRequestBody());
       
   129         BufferedReader br = new BufferedReader(in);
       
   130         String line;
       
   131         while ((line = br.readLine()) != null) {
       
   132             String decode = charset != null ? URLDecoder.decode(line, charset) : line;
       
   133             stringBuilder.append(decode);
       
   134         }
       
   135         return stringBuilder.toString();
       
   136     }
       
   137 
       
   138     public static void sendResponse(HttpExchange exchange, HttpResponse response) throws IOException {
       
   139         String charset = getRequestCharset(exchange);
       
   140         String acceptCharset = HttpUtil.getAcceptCharset(exchange);
       
   141         if (acceptCharset != null) {
       
   142             charset = acceptCharset;
       
   143         }
       
   144 
       
   145         // Set response headers explicitly
       
   146         String msg = charset == null ? response.getBody() : URLEncoder.encode(response.getBody(), charset);
       
   147         byte[] bytes = msg.getBytes();
       
   148         Headers resHeaders = exchange.getResponseHeaders();
       
   149         if (charset != null && !charset.isEmpty()) {
       
   150             resHeaders.add("Content-Type", "application/json; charset=" + charset);
       
   151         } else {
       
   152             resHeaders.add("Content-Type", "application/json;");
       
   153         }
       
   154 
       
   155         exchange.sendResponseHeaders(response.getCode(), bytes.length);
       
   156         try (OutputStream os = exchange.getResponseBody()) {
       
   157             os.write(bytes);
       
   158         }
       
   159     }
       
   160 
       
   161     public static <T> List<T> filterByPage(HttpExchange exchange, List<T> input, int pageSize) throws UnsupportedEncodingException {
       
   162 
       
   163         Map<String, String> queryParams = HttpUtil.getGetRequestQueryMap(exchange);
       
   164         int currPage = 1;
       
   165         if (queryParams != null && !queryParams.isEmpty()) {
       
   166             String pageStr = queryParams.get("page");
       
   167             if (pageStr != null && !pageStr.isEmpty()) {
       
   168                 currPage = Integer.parseInt(pageStr);
       
   169                 currPage = currPage > 1 ? currPage : 1;
       
   170             }
       
   171         }
       
   172 
       
   173         if (input.size() <= pageSize) {
       
   174             return input;
       
   175         }
       
   176 
       
   177         int start = (currPage - 1) * pageSize;
       
   178         int end = Math.min(input.size(), start + pageSize);
       
   179         if (start < end) {
       
   180             return input.subList(start, end);
       
   181         } else {
       
   182             return null;
       
   183         }
       
   184     }
       
   185 
       
   186     public static <T> JSONObject getPaginationLinks(HttpExchange exchange, List<T> input, int pageSize) throws UnsupportedEncodingException {
       
   187 
       
   188         if (pageSize >= input.size()) {
       
   189             return null;
       
   190         }
       
   191 
       
   192         Map<String, String> queryParams = HttpUtil.getGetRequestQueryMap(exchange);
       
   193         int currPage = 1;
       
   194         if (queryParams != null && !queryParams.isEmpty()) {
       
   195             String pageStr = queryParams.get("page");
       
   196             if (pageStr != null && !pageStr.isEmpty()) {
       
   197                 currPage = Integer.parseInt(pageStr);
       
   198             }
       
   199         }
       
   200         String path = PlatformRestAdapter.getDomain() + exchange.getRequestURI().getPath() + "?";
       
   201         Map<String, String> queryMap = getGetRequestQueryMap(exchange);
       
   202         if (queryMap != null) {
       
   203             queryMap.remove("page");
       
   204             if (!queryMap.isEmpty()) {
       
   205                 String query = queryMap.keySet().stream()
       
   206                         .map(k -> k + "=" + queryMap.get(k))
       
   207                         .collect(Collectors.joining("&"));
       
   208                 path = path + query + "&";
       
   209             }
       
   210         }
       
   211         int totalPages = (input.size() % pageSize == 0) ? input.size() / pageSize : input.size() / pageSize + 1;
       
   212 
       
   213         JSONObject jobj = new JSONObject();
       
   214         jobj.put("first", path.replaceAll(".$", ""));
       
   215         if (currPage == 2) {
       
   216             jobj.put("prev", path.replaceAll(".$", ""));
       
   217         } else if (currPage > 2) {
       
   218             jobj.put("prev", path + "page=" + (currPage - 1));
       
   219         }
       
   220         if (currPage < totalPages) {
       
   221             jobj.put("next", path + "page=" + (currPage + 1));
       
   222         }
       
   223         jobj.put("last", path + "page=" + totalPages);
       
   224 
       
   225         return jobj;
       
   226     }
       
   227 
       
   228     public static String escapeUrl(String input) {
       
   229         try {
       
   230             URL url = new URL(input);
       
   231             URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
       
   232             return uri.toURL().toString();
       
   233         } catch (Exception ex) {
       
   234             return null;
       
   235         }
       
   236     }
       
   237 
       
   238 }